diff --git a/.editorconfig b/.editorconfig index 8565b274..7692ac78 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,24 +6,5 @@ root = true [*] charset = utf-8 end_of_line = lf +trim_trailing_whitespaces = true indent_style = tab -trim_trailing_whitespace = true -insert_final_newline = true -quote_type = single -max_line_length = off - -[*.js] -quote_type = double -ij_javascript_use_double_quotes = true - -[*.yml] -indent_style = space -indent_size = 2 - -[*.xml] -indent_style = space -indent_size = 2 - -[*.json] -indent_style = space -indent_size = 2 diff --git a/.tx/config b/.tx/config index 8542c680..710a560e 100644 --- a/.tx/config +++ b/.tx/config @@ -1,399 +1,399 @@ [main] -host = https://api.transifex.com +host = https://www.transifex.com -[o:Friendica:p:friendica:r:addon_advancedcontentfilter_messagespo] +[friendica.addon_advancedcontentfilter_messagespo] file_filter = advancedcontentfilter/lang//messages.po source_file = advancedcontentfilter/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_blackout_messagespo] +[friendica.addon_blackout_messagespo] file_filter = blackout/lang//messages.po source_file = blackout/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_blockem_messagespo] +[friendica.addon_blockem_messagespo] file_filter = blockem/lang//messages.po source_file = blockem/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_blogger_messagespo] +[friendica.addon_blogger_messagespo] file_filter = blogger/lang//messages.po source_file = blogger/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_buffer_messagespo] +[friendica.addon_buffer_messagespo] file_filter = buffer/lang//messages.po source_file = buffer/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_buglink_messagespo] +[friendica.addon_buglink_messagespo] file_filter = buglink/lang//messages.po source_file = buglink/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_catavatar_messagespo] +[friendica.addon_catavatar_messagespo] file_filter = catavatar/lang//messages.po source_file = catavatar/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_cookienotice_messagespo] +[friendica.addon_cookienotice_messagespo] file_filter = cookienotice/lang//messages.po source_file = cookienotice/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_curweather_messagespo] +[friendica.addon_curweather_messagespo] file_filter = curweather/lang//messages.po source_file = curweather/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_diaspora_messagespo] +[friendica.addon_diaspora_messagespo] file_filter = diaspora/lang//messages.po source_file = diaspora/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_dwpost_messagespo] +[friendica.addon_dwpost_messagespo] file_filter = dwpost/lang//messages.po source_file = dwpost/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_forumdirectory_messagespo] +[friendica.addon_forumdirectory_messagespo] file_filter = forumdirectory/lang//messages.po source_file = forumdirectory/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_fromapp_messagespo] +[friendica.addon_fromapp_messagespo] file_filter = fromapp/lang//messages.po source_file = fromapp/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_fromgplus_messagespo] +[friendica.addon_fromgplus_messagespo] file_filter = fromgplus/lang//messages.po source_file = fromgplus/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_geonames_messagespo] +[friendica.addon_geonames_messagespo] file_filter = geonames/lang//messages.po source_file = geonames/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_gnot_messagespo] +[friendica.addon_gnot_messagespo] file_filter = gnot/lang//messages.po source_file = gnot/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_gravatar_messagespo] +[friendica.addon_gravatar_messagespo] file_filter = gravatar/lang//messages.po source_file = gravatar/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_group_text_messagespo] +[friendica.addon_group_text_messagespo] file_filter = group_text/lang//messages.po source_file = group_text/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_ifttt_messagespo] +[friendica.addon_ifttt_messagespo] file_filter = ifttt/lang//messages.po source_file = ifttt/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_ijpost_messagespo] +[friendica.addon_ijpost_messagespo] file_filter = ijpost/lang//messages.po source_file = ijpost/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_impressum_messagespo] +[friendica.addon_impressum_messagespo] file_filter = impressum/lang//messages.po source_file = impressum/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_infiniteimprobabilitydrive_messagespo] +[friendica.addon_infiniteimprobabilitydrive_messagespo] file_filter = infiniteimprobabilitydrive/lang//messages.po source_file = infiniteimprobabilitydrive/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_irc_messagespo] +[friendica.addon_irc_messagespo] file_filter = irc/lang//messages.po source_file = irc/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_jappixmini_messagespo] +[friendica.addon_jappixmini_messagespo] file_filter = jappixmini/lang//messages.po source_file = jappixmini/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_js_upload_messagespo] +[friendica.addon_js_upload_messagespo] file_filter = js_upload/lang//messages.po source_file = js_upload/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_krynn_messagespo] +[friendica.addon_krynn_messagespo] file_filter = krynn/lang//messages.po source_file = krynn/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_langfilter_messagespo] +[friendica.addon_langfilter_messagespo] file_filter = langfilter/lang//messages.po source_file = langfilter/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_libertree_messagespo] +[friendica.addon_libertree_messagespo] file_filter = libertree/lang//messages.po source_file = libertree/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_libravatar_messagespo] +[friendica.addon_libravatar_messagespo] file_filter = libravatar/lang//messages.po source_file = libravatar/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_ljpost_messagespo] +[friendica.addon_ljpost_messagespo] file_filter = ljpost/lang//messages.po source_file = ljpost/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_mailstream_messagespo] +[friendica.addon_mailstream_messagespo] file_filter = mailstream/lang//messages.po source_file = mailstream/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_mathjax_messagespo] +[friendica.addon_mathjax_messagespo] file_filter = mathjax/lang//messages.po source_file = mathjax/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_membersince_messagespo] +[friendica.addon_membersince_messagespo] file_filter = membersince/lang//messages.po source_file = membersince/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_morechoice_messagespo] +[friendica.addon_morechoice_messagespo] file_filter = morechoice/lang//messages.po source_file = morechoice/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_morepokes_messagespo] +[friendica.addon_morepokes_messagespo] file_filter = morepokes/lang//messages.po source_file = morepokes/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_newmemberwidget_messagespo] +[friendica.addon_newmemberwidget_messagespo] file_filter = newmemberwidget/lang//messages.po source_file = newmemberwidget/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_notifyall_messagespo] +[friendica.addon_notifyall_messagespo] file_filter = notifyall/lang//messages.po source_file = notifyall/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_notimeline_messagespo] +[friendica.addon_notimeline_messagespo] file_filter = notimeline/lang//messages.po source_file = notimeline/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_nsfw_messagespo] +[friendica.addon_nsfw_messagespo] file_filter = nsfw/lang//messages.po source_file = nsfw/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_numfriends_messagespo] +[friendica.addon_numfriends_messagespo] file_filter = numfriends/lang//messages.po source_file = numfriends/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_openstreetmap_messagespo] +[friendica.addon_openstreetmap_messagespo] file_filter = openstreetmap/lang//messages.po source_file = openstreetmap/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_pageheader_messagespo] +[friendica.addon_pageheader_messagespo] file_filter = pageheader/lang//messages.po source_file = pageheader/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_piwik_messagespo] +[friendica.addon_piwik_messagespo] file_filter = piwik/lang//messages.po source_file = piwik/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_planets_messagespo] +[friendica.addon_planets_messagespo] file_filter = planets/lang//messages.po source_file = planets/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_public_server_messagespo] +[friendica.addon_public_server_messagespo] file_filter = public_server/lang//messages.po source_file = public_server/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_pumpio_messagespo] +[friendica.addon_pumpio_messagespo] file_filter = pumpio/lang//messages.po source_file = pumpio/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_qcomment_messagespo] +[friendica.addon_qcomment_messagespo] file_filter = qcomment/lang//messages.po source_file = qcomment/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_randplace_messagespo] +[friendica.addon_randplace_messagespo] file_filter = randplace/lang//messages.po source_file = randplace/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_remote_permissions_messagespo] +[friendica.addon_remote_permissions_messagespo] file_filter = remote_permissions/lang//messages.po source_file = remote_permissions/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_rendertime_messagespo] +[friendica.addon_rendertime_messagespo] file_filter = rendertime/lang//messages.po source_file = rendertime/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_securemail_messagespo] +[friendica.addon_securemail_messagespo] file_filter = securemail/lang//messages.po source_file = securemail/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_showmore_messagespo] +[friendica.addon_showmore_messagespo] file_filter = showmore/lang//messages.po source_file = showmore/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_smileybutton_messagespo] +[friendica.addon_smileybutton_messagespo] file_filter = smileybutton/lang//messages.po source_file = smileybutton/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_startpage_messagespo] +[friendica.addon_startpage_messagespo] file_filter = startpage/lang//messages.po source_file = startpage/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_statusnet_messagespo] +[friendica.addon_statusnet_messagespo] file_filter = statusnet/lang//messages.po source_file = statusnet/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_superblock_messagespo] +[friendica.addon_superblock_messagespo] file_filter = superblock/lang//messages.po source_file = superblock/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_testdrive_messagespo] +[friendica.addon_testdrive_messagespo] file_filter = testdrive/lang//messages.po source_file = testdrive/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_tictac_messagespo] +[friendica.addon_tictac_messagespo] file_filter = tictac/lang//messages.po source_file = tictac/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_tumblr_messagespo] +[friendica.addon_tumblr_messagespo] file_filter = tumblr/lang//messages.po source_file = tumblr/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_twitter_messagespo] +[friendica.addon_twitter_messagespo] file_filter = twitter/lang//messages.po source_file = twitter/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_viewsrc_messagespo] +[friendica.addon_viewsrc_messagespo] file_filter = viewsrc/lang//messages.po source_file = viewsrc/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_webrtc_messagespo] +[friendica.addon_webrtc_messagespo] file_filter = webrtc/lang//messages.po source_file = webrtc/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_widgets_messagespo] +[friendica.addon_widgets_messagespo] file_filter = widgets/lang//messages.po source_file = widgets/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_windowsphonepush_messagespo] +[friendica.addon_windowsphonepush_messagespo] file_filter = windowsphonepush/lang//messages.po source_file = windowsphonepush/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_wppost_messagespo] +[friendica.addon_wppost_messagespo] file_filter = wppost/lang//messages.po source_file = wppost/lang/C/messages.po source_lang = en -type = PO +type = PO -[o:Friendica:p:friendica:r:addon_xmpp_messagespo] +[friendica.addon_xmpp_messagespo] file_filter = xmpp/lang//messages.po source_file = xmpp/lang/C/messages.po source_lang = en -type = PO +type = PO diff --git a/.woodpecker/.phpunit.yml b/.woodpecker/.phpunit.yml deleted file mode 100644 index a6c5db09..00000000 --- a/.woodpecker/.phpunit.yml +++ /dev/null @@ -1,113 +0,0 @@ -matrix: - include: - - PHP_MAJOR_VERSION: 7.4 - PHP_VERSION: 7.4.33 - - PHP_MAJOR_VERSION: 8.0 - PHP_VERSION: 8.0.30 - - PHP_MAJOR_VERSION: 8.1 - PHP_VERSION: 8.1.23 - - PHP_MAJOR_VERSION: 8.2 - PHP_VERSION: 8.2.11 - -# 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 diff --git a/advancedcontentfilter/advancedcontentfilter.php b/advancedcontentfilter/advancedcontentfilter.php index f2927f57..2254e587 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'] = DI::postMediaRepository()->splitAttachments($item_row['uri-id']); + $item_row['attachments'] = Post\Media::splitAttachments($item_row['uri-id']); return $item_row; } diff --git a/advancedcontentfilter/lang/de/messages.po b/advancedcontentfilter/lang/de/messages.po index e338fb61..cbd8b37a 100644 --- a/advancedcontentfilter/lang/de/messages.po +++ b/advancedcontentfilter/lang/de/messages.po @@ -15,7 +15,7 @@ msgstr "" "POT-Creation-Date: 2022-05-11 08:54-0400\n" "PO-Revision-Date: 2018-05-24 06:41+0000\n" "Last-Translator: Tobias Diekershoff , 2022\n" -"Language-Team: German (https://app.transifex.com/Friendica/teams/12172/de/)\n" +"Language-Team: German (https://www.transifex.com/Friendica/teams/12172/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/advancedcontentfilter/lang/it/messages.po b/advancedcontentfilter/lang/it/messages.po index f32c5b94..95f14912 100644 --- a/advancedcontentfilter/lang/it/messages.po +++ b/advancedcontentfilter/lang/it/messages.po @@ -3,63 +3,60 @@ # This file is distributed under the same license as the Friendica advancedcontentfilter addon package. # # -# Translators: -# fabrixxm , 2018 -# Sylke Vicious , 2021 -# #, fuzzy msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-05-11 08:54-0400\n" -"PO-Revision-Date: 2018-05-24 06:41+0000\n" -"Last-Translator: Sylke Vicious , 2021\n" -"Language-Team: Italian (https://app.transifex.com/Friendica/teams/12172/it/)\n" +"POT-Creation-Date: 2018-04-17 04:04+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: fabrixxm , 2018\n" +"Language-Team: Italian (https://www.transifex.com/Friendica/teams/12172/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: advancedcontentfilter.php:154 +#: advancedcontentfilter.php:134 #, php-format msgid "Filtered by rule: %s" msgstr "Filtrato dalla regola: %s" -#: advancedcontentfilter.php:170 advancedcontentfilter.php:225 +#: advancedcontentfilter.php:147 advancedcontentfilter.php:204 msgid "Advanced Content Filter" msgstr "Filtro Avanzato Contenuti" -#: advancedcontentfilter.php:224 +#: advancedcontentfilter.php:203 msgid "Back to Addon Settings" msgstr "Torna alle impostazioni del componente aggiuntivo" -#: advancedcontentfilter.php:226 +#: advancedcontentfilter.php:205 msgid "Add a Rule" msgstr "Aggiungi una regola" -#: advancedcontentfilter.php:227 +#: advancedcontentfilter.php:206 msgid "Help" msgstr "Aiuto" -#: advancedcontentfilter.php:228 +#: advancedcontentfilter.php:207 msgid "" "Add and manage your personal content filter rules in this screen. Rules have" " a name and an arbitrary expression that will be matched against post data. " "For a complete reference of the available operations and variables, check " -"the help page." +"the help page." msgstr "" "Aggiungi e gestisci le tue regole personali di filtro contenuti in questa " "schermata. Le regole hanno un nome e un'espressione arbitraria che sarà " "confrontata con i dati del messaggio. Per un elenco completo delle " -"operazioni e variabili disponibili, controlla la pagina di aiuto." +"operazioni disponibili, controlla la pagina di aiuto." -#: advancedcontentfilter.php:229 +#: advancedcontentfilter.php:208 msgid "Your rules" msgstr "Le tue regole" -#: advancedcontentfilter.php:230 +#: advancedcontentfilter.php:209 msgid "" "You have no rules yet! Start adding one by clicking on the button above next" " to the title." @@ -67,106 +64,110 @@ msgstr "" "Non hai ancora nessuna regola! Aggiungine una cliccando sul bottone qui " "sopra a fianco al titolo." -#: advancedcontentfilter.php:231 +#: advancedcontentfilter.php:210 msgid "Disabled" msgstr "Disabilitato" -#: advancedcontentfilter.php:232 +#: advancedcontentfilter.php:211 msgid "Enabled" msgstr "Abilitato" -#: advancedcontentfilter.php:233 +#: advancedcontentfilter.php:212 msgid "Disable this rule" msgstr "Diabilita questa regola" -#: advancedcontentfilter.php:234 +#: advancedcontentfilter.php:213 msgid "Enable this rule" msgstr "Abilita questa regola" -#: advancedcontentfilter.php:235 +#: advancedcontentfilter.php:214 msgid "Edit this rule" msgstr "Modifica questa regola" -#: advancedcontentfilter.php:236 +#: advancedcontentfilter.php:215 msgid "Edit the rule" msgstr "Modifica la regola" -#: advancedcontentfilter.php:237 +#: advancedcontentfilter.php:216 msgid "Save this rule" msgstr "Salva questa regola" -#: advancedcontentfilter.php:238 +#: advancedcontentfilter.php:217 msgid "Delete this rule" msgstr "Elimina questa regola" -#: advancedcontentfilter.php:239 +#: advancedcontentfilter.php:218 msgid "Rule" msgstr "Regola" -#: advancedcontentfilter.php:240 +#: advancedcontentfilter.php:219 msgid "Close" msgstr "Chiudi" -#: advancedcontentfilter.php:241 +#: advancedcontentfilter.php:220 msgid "Add new rule" msgstr "Aggiungi nuova regola" -#: advancedcontentfilter.php:242 +#: advancedcontentfilter.php:221 msgid "Rule Name" msgstr "Nome Regola" -#: advancedcontentfilter.php:243 +#: advancedcontentfilter.php:222 msgid "Rule Expression" msgstr "Espressione Regola" -#: advancedcontentfilter.php:244 +#: advancedcontentfilter.php:223 +msgid "" +"

Examples:

  • author_link == "
    +"'https://friendica.mrpetovan.com/profile/hypolite'
  • tags
" +msgstr "" +"

Esempi:

  • author_link == "
    +"'https://friendica.mrpetovan.com/profile/hypolite'
  • tags
" + +#: advancedcontentfilter.php:224 msgid "Cancel" msgstr "Annulla" -#: advancedcontentfilter.php:295 -msgid "This addon requires this node having at least one post" -msgstr "" - -#: advancedcontentfilter.php:325 advancedcontentfilter.php:336 -#: advancedcontentfilter.php:347 advancedcontentfilter.php:383 -#: advancedcontentfilter.php:414 advancedcontentfilter.php:437 +#: advancedcontentfilter.php:290 advancedcontentfilter.php:301 +#: advancedcontentfilter.php:312 advancedcontentfilter.php:346 +#: advancedcontentfilter.php:375 advancedcontentfilter.php:396 msgid "You must be logged in to use this method" msgstr "Devi essere autenticato per usare questo metodo" -#: advancedcontentfilter.php:351 advancedcontentfilter.php:387 -#: advancedcontentfilter.php:418 +#: advancedcontentfilter.php:316 advancedcontentfilter.php:350 +#: advancedcontentfilter.php:379 msgid "Invalid form security token, please refresh the page." msgstr "Token di sicurezza invalido, aggiorna la pagina." -#: advancedcontentfilter.php:363 +#: advancedcontentfilter.php:328 msgid "The rule name and expression are required." msgstr "Il nome e l'espressione della regola sono richiesti." -#: advancedcontentfilter.php:377 +#: advancedcontentfilter.php:340 msgid "Rule successfully added" msgstr "Regola aggiunta con successo" -#: advancedcontentfilter.php:391 advancedcontentfilter.php:422 +#: advancedcontentfilter.php:354 advancedcontentfilter.php:383 msgid "Rule doesn't exist or doesn't belong to you." msgstr "La regola non esiste o non ti appartiene." -#: advancedcontentfilter.php:408 +#: advancedcontentfilter.php:369 msgid "Rule successfully updated" msgstr "Regola aggiornata con successo" -#: advancedcontentfilter.php:431 +#: advancedcontentfilter.php:390 msgid "Rule successfully deleted" msgstr "Regola eliminata con successo" -#: advancedcontentfilter.php:441 +#: advancedcontentfilter.php:400 msgid "Missing argument: guid." msgstr "Argomento mancante: guid." -#: advancedcontentfilter.php:449 +#: advancedcontentfilter.php:406 #, php-format msgid "Unknown post with guid: %s" msgstr "Messaggio con guid %s sconosciuto" -#: src/middlewares.php:49 +#: src/middlewares.php:28 msgid "Method not found" msgstr "Metodo non trovato" diff --git a/advancedcontentfilter/lang/it/strings.php b/advancedcontentfilter/lang/it/strings.php index 5cc01739..50cde891 100644 --- a/advancedcontentfilter/lang/it/strings.php +++ b/advancedcontentfilter/lang/it/strings.php @@ -3,14 +3,14 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $a->strings['Filtered by rule: %s'] = 'Filtrato dalla regola: %s'; $a->strings['Advanced Content Filter'] = 'Filtro Avanzato Contenuti'; $a->strings['Back to Addon Settings'] = 'Torna alle impostazioni del componente aggiuntivo'; $a->strings['Add a Rule'] = 'Aggiungi una regola'; $a->strings['Help'] = 'Aiuto'; -$a->strings['Add and manage your personal content filter rules in this screen. Rules have a name and an arbitrary expression that will be matched against post data. For a complete reference of the available operations and variables, check the help page.'] = 'Aggiungi e gestisci le tue regole personali di filtro contenuti in questa schermata. Le regole hanno un nome e un\'espressione arbitraria che sarà confrontata con i dati del messaggio. Per un elenco completo delle operazioni e variabili disponibili, controlla la pagina di aiuto.'; +$a->strings['Add and manage your personal content filter rules in this screen. Rules have a name and an arbitrary expression that will be matched against post data. For a complete reference of the available operations and variables, check the help page.'] = 'Aggiungi e gestisci le tue regole personali di filtro contenuti in questa schermata. Le regole hanno un nome e un\'espressione arbitraria che sarà confrontata con i dati del messaggio. Per un elenco completo delle operazioni disponibili, controlla la pagina di aiuto.'; $a->strings['Your rules'] = 'Le tue regole'; $a->strings['You have no rules yet! Start adding one by clicking on the button above next to the title.'] = 'Non hai ancora nessuna regola! Aggiungine una cliccando sul bottone qui sopra a fianco al titolo.'; $a->strings['Disabled'] = 'Disabilitato'; @@ -26,6 +26,7 @@ $a->strings['Close'] = 'Chiudi'; $a->strings['Add new rule'] = 'Aggiungi nuova regola'; $a->strings['Rule Name'] = 'Nome Regola'; $a->strings['Rule Expression'] = 'Espressione Regola'; +$a->strings['

Examples:

  • author_link == \'https://friendica.mrpetovan.com/profile/hypolite\'
  • tags
'] = '

Esempi:

  • author_link == \'https://friendica.mrpetovan.com/profile/hypolite\'
  • tags
'; $a->strings['Cancel'] = 'Annulla'; $a->strings['You must be logged in to use this method'] = 'Devi essere autenticato per usare questo metodo'; $a->strings['Invalid form security token, please refresh the page.'] = 'Token di sicurezza invalido, aggiorna la pagina.'; diff --git a/audon/README.md b/audon/README.md deleted file mode 100644 index beb89a1e..00000000 --- a/audon/README.md +++ /dev/null @@ -1,6 +0,0 @@ -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/audon.php b/audon/audon.php deleted file mode 100644 index 553e7f5c..00000000 --- a/audon/audon.php +++ /dev/null @@ -1,69 +0,0 @@ - - * 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 an 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/lang/C/messages.po b/audon/lang/C/messages.po deleted file mode 100644 index c8fd38af..00000000 --- a/audon/lang/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 "" diff --git a/audon/templates/admin.tpl b/audon/templates/admin.tpl deleted file mode 100644 index e2758583..00000000 --- a/audon/templates/admin.tpl +++ /dev/null @@ -1,2 +0,0 @@ -{{include file="field_input.tpl" field=$audonurl}} - diff --git a/birdavatar/birdavatar.php b/birdavatar/birdavatar.php index 4841ba52..e389d561 100644 --- a/birdavatar/birdavatar.php +++ b/birdavatar/birdavatar.php @@ -69,7 +69,7 @@ function birdavatar_addon_settings_post(&$s) } if (!empty($_POST['birdavatar-usebird'])) { - $url = DI::baseUrl() . '/birdavatar/' . DI::userSession()->getLocalUserId() . '?ts=' . time(); + $url = DI::baseUrl()->get() . '/birdavatar/' . DI::userSession()->getLocalUserId() . '?ts=' . time(); $self = DBA::selectFirst('contact', ['id'], ['uid' => DI::userSession()->getLocalUserId(), 'self' => true]); if (!DBA::isResult($self)) { @@ -120,9 +120,9 @@ function birdavatar_lookup(array &$b) { $user = DBA::selectFirst('user', ['uid'], ['email' => $b['email']]); if (DBA::isResult($user)) { - $url = DI::baseUrl() . '/birdavatar/' . $user['uid']; + $url = DI::baseUrl()->get() . '/birdavatar/' . $user['uid']; } else { - $url = DI::baseUrl() . '/birdavatar/' . md5(trim(strtolower($b['email']))); + $url = DI::baseUrl()->get() . '/birdavatar/' . md5(trim(strtolower($b['email']))); } switch ($b['size']) { diff --git a/blackout/lang/de/messages.po b/blackout/lang/de/messages.po index 3549512f..6757d2ad 100644 --- a/blackout/lang/de/messages.po +++ b/blackout/lang/de/messages.po @@ -12,9 +12,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-02-01 18:15+0100\n" -"PO-Revision-Date: 2014-06-22 11:19+0000\n" -"Last-Translator: Till Mohr , 2021\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2021-05-23 19:26+0000\n" +"Last-Translator: Till Mohr \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/blockbot/blockbot.php b/blockbot/blockbot.php index 10327edf..93da4e53 100644 --- a/blockbot/blockbot.php +++ b/blockbot/blockbot.php @@ -8,7 +8,9 @@ * */ +use Friendica\App; use Friendica\Core\Hook; +use Friendica\Core\System; use Friendica\DI; use Jaybizzle\CrawlerDetect\CrawlerDetect; use Friendica\Core\Logger; @@ -50,15 +52,12 @@ function blockbot_init_1() $logdata = ['agent' => $_SERVER['HTTP_USER_AGENT'], 'uri' => $_SERVER['REQUEST_URI']]; // List of "good" crawlers - $good_agents = [ - 'fediverse.space crawler', 'fediverse.network crawler', 'Active_Pods_CheckBot_3.0', + $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/']; // List of known crawlers. - $agents = [ - 'SemrushBot', 's~feedly-nikon3', 'Qwantify/Bleriot/', 'ltx71', 'Sogou web spider/', + $agents = ['SemrushBot', 's~feedly-nikon3', 'Qwantify/Bleriot/', 'ltx71', 'Sogou web spider/', 'Diffbot/', 'Twitterbot/', 'YisouSpider', 'evc-batch/', 'LivelapBot/', 'TrendsmapResolver/', 'PaperLiBot/', 'Nuzzel', 'um-LN/', 'Google Favicon', 'Datanyze', 'BLEXBot/', '360Spider', 'adscanner/', 'HeadlessChrome', 'wpif', 'startmebot/', 'Googlebot/', 'Applebot/', @@ -80,8 +79,7 @@ function blockbot_init_1() 'Google-Apps-Script; beanserver;', 'woorankreview/', 'Seekport Crawler;', 'AHC/', 'SkypeUriPreview Preview/', 'Semanticbot/', 'Embed PHP library', 'XoviOnpageCrawler;', 'GetHPinfo.com-Bot/', 'BoardReader Favicon Fetcher', 'Google-Adwords-Instant', 'newspaper/', - 'YurichevBot/', 'Crawling at Home Project', 'InfoTigerBot/' - ]; + 'YurichevBot/', 'Crawling at Home Project', 'InfoTigerBot/']; if (!DI::config()->get('blockbot', 'good_crawlers')) { $agents = array_merge($agents, $good_agents); @@ -116,8 +114,7 @@ function blockbot_init_1() } // List of false positives' strings of known "good" agents. - $agents = [ - 'curl', 'zgrab', 'Go-http-client', 'curb', 'github.com', 'reqwest', 'Feedly/', + $agents = ['curl', 'zgrab', 'Go-http-client', 'curb', 'github.com', 'reqwest', 'Feedly/', 'Python-urllib/', 'Liferea/', 'aiohttp/', 'WordPress.com Reader', 'hackney/', 'Faraday v', 'okhttp', 'UniversalFeedParser', 'PixelFedBot', 'python-requests', 'WordPress/', 'http.rb/', 'Apache-HttpClient/', 'WordPress.com;', 'Pleroma', @@ -125,8 +122,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']; if (DI::config()->get('blockbot', 'good_crawlers')) { $agents = array_merge($agents, $good_agents); @@ -134,11 +130,11 @@ function blockbot_init_1() foreach ($agents as $agent) { if (stristr($_SERVER['HTTP_USER_AGENT'], $agent)) { - logger::info('False positive', $logdata); + logger::notice('False positive', $logdata); return; } } - logger::notice('Blocked bot', $logdata); + logger::info('Blocked bot', $logdata); throw new ForbiddenException('Bots are not allowed'); } diff --git a/blockem/blockem.php b/blockem/blockem.php new file mode 100644 index 00000000..77c8215d --- /dev/null +++ b/blockem/blockem.php @@ -0,0 +1,230 @@ + + * Author: Roland Haeder + * Status: unsupported + */ + +use Friendica\App; +use Friendica\Core\Hook; +use Friendica\Core\Renderer; +use Friendica\DI; +use Friendica\Util\Strings; + +global $blockem_words; + +function blockem_install() +{ + Hook::register('prepare_body_content_filter', 'addon/blockem/blockem.php', 'blockem_prepare_body_content_filter'); + Hook::register('display_item' , 'addon/blockem/blockem.php', 'blockem_display_item'); + Hook::register('addon_settings' , 'addon/blockem/blockem.php', 'blockem_addon_settings'); + Hook::register('addon_settings_post' , 'addon/blockem/blockem.php', 'blockem_addon_settings_post'); + Hook::register('conversation_start' , 'addon/blockem/blockem.php', 'blockem_conversation_start'); + Hook::register('item_photo_menu' , 'addon/blockem/blockem.php', 'blockem_item_photo_menu'); + Hook::register('enotify_store' , 'addon/blockem/blockem.php', 'blockem_enotify_store'); +} + +function blockem_addon_settings(array &$data) +{ + if (!DI::userSession()->getLocalUserId()) { + return; + } + + $words = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'blockem', 'words', ''); + + $t = Renderer::getMarkupTemplate('settings.tpl', 'addon/blockem/'); + $html = Renderer::replaceMacros($t, [ + '$info' => DI::l10n()->t("Hides user's content by collapsing posts. Also replaces their avatar with generic image."), + '$words' => ['blockem-words', DI::l10n()->t('Comma separated profile URLS:'), $words], + ]); + + $data = [ + 'addon' => 'blockem', + 'title' => DI::l10n()->t('Blockem'), + 'html' => $html, + ]; +} + +function blockem_addon_settings_post(array &$b) +{ + if (!DI::userSession()->getLocalUserId()) { + return; + } + + if (!empty($_POST['blockem-submit'])) { + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'blockem', 'words', trim($_POST['blockem-words'])); + } +} + +function blockem_enotify_store(array &$b) +{ + $words = DI::pConfig()->get($b['uid'], 'blockem', 'words'); + + if ($words) { + $arr = explode(',', $words); + } else { + return; + } + + $found = false; + + if (count($arr)) { + foreach ($arr as $word) { + if (!strlen(trim($word))) { + continue; + } + + if (Strings::compareLink($b['url'], $word)) { + $found = true; + break; + } + } + } + + if ($found) { + // empty out the fields + $b = []; + } +} + +function blockem_prepare_body_content_filter(array &$hook_data) +{ + if (!DI::userSession()->getLocalUserId()) { + return; + } + + $profiles_string = null; + + if (DI::userSession()->getLocalUserId()) { + $profiles_string = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'blockem', 'words'); + } + + if ($profiles_string) { + $profiles_array = explode(',', $profiles_string); + } else { + return; + } + + $found = false; + + foreach ($profiles_array as $word) { + if (Strings::compareLink($hook_data['item']['author-link'], trim($word))) { + $found = true; + break; + } + } + + if ($found) { + $hook_data['filter_reasons'][] = DI::l10n()->t('Filtered user: %s', $hook_data['item']['author-name']); + } +} + +function blockem_display_item(array &$b = null) +{ + if (!empty($b['output']['body']) && strstr($b['output']['body'], 'id="blockem-wrap-')) { + $b['output']['thumb'] = DI::baseUrl()->get() . "/images/person-80.jpg"; + } +} + +function blockem_conversation_start(array &$b) +{ + global $blockem_words; + + if (!DI::userSession()->getLocalUserId()) { + return; + } + + $words = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'blockem', 'words'); + + if ($words) { + $blockem_words = explode(',', $words); + } + + DI::page()['htmlhead'] .= <<< EOT + + + +EOT; +} + +function blockem_item_photo_menu(array &$b) +{ + global $blockem_words; + + if (!DI::userSession()->getLocalUserId() || $b['item']['self']) { + return; + } + + $blocked = false; + $author = $b['item']['author-link']; + + if (!empty($blockem_words)) { + foreach($blockem_words as $bloke) { + if (Strings::compareLink($bloke,$author)) { + $blocked = true; + break; + } + } + } + if ($blocked) { + $b['menu'][DI::l10n()->t('Unblock Author')] = 'javascript:blockemUnblock(\'' . $author . '\');'; + } else { + $b['menu'][DI::l10n()->t('Block Author')] = 'javascript:blockemBlock(\'' . $author . '\');'; + } +} + +/** + * 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 blockem_module() {} + +function blockem_init() +{ + if (!DI::userSession()->getLocalUserId()) { + return; + } + + $words = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'blockem', 'words'); + + if (array_key_exists('block', $_GET) && $_GET['block']) { + if (strlen($words)) { + $words .= ','; + } + + $words .= trim($_GET['block']); + } + + if (array_key_exists('unblock', $_GET) && $_GET['unblock']) { + $arr = explode(',',$words); + $newarr = []; + + if (count($arr)) { + foreach ($arr as $x) { + if (!Strings::compareLink(trim($x), trim($_GET['unblock']))) { + $newarr[] = $x; + } + } + } + + $words = implode(',', $newarr); + } + + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'blockem', 'words', $words); + exit(); +} diff --git a/blockem/lang/C/messages.po b/blockem/lang/C/messages.po new file mode 100644 index 00000000..64bb3fc4 --- /dev/null +++ b/blockem/lang/C/messages.po @@ -0,0 +1,45 @@ +# ADDON blockem +# Copyright (C) +# This file is distributed under the same license as the Friendica blockem addon package. +# +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-11-21 19:13-0500\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" + +#: blockem.php:39 +msgid "" +"Hides user's content by collapsing posts. Also replaces their avatar with " +"generic image." +msgstr "" + +#: blockem.php:40 +msgid "Comma separated profile URLS:" +msgstr "" + +#: blockem.php:45 +msgid "Blockem" +msgstr "" + +#: blockem.php:120 +#, php-format +msgid "Filtered user: %s" +msgstr "" + +#: blockem.php:183 +msgid "Unblock Author" +msgstr "" + +#: blockem.php:185 +msgid "Block Author" +msgstr "" diff --git a/blockem/lang/ar/messages.po b/blockem/lang/ar/messages.po new file mode 100644 index 00000000..c9d6d5f9 --- /dev/null +++ b/blockem/lang/ar/messages.po @@ -0,0 +1,52 @@ +# ADDON blockem +# Copyright (C) +# This file is distributed under the same license as the Friendica blockem addon package. +# +# +# Translators: +# abidin toumi , 2021 +# Farida Khalaf , 2021 +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-10-29 08:15+0000\n" +"Last-Translator: abidin toumi \n" +"Language-Team: Arabic (http://www.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" + +#: blockem.php:42 blockem.php:46 +msgid "Blockem" +msgstr "احجبه
" + +#: blockem.php:50 +msgid "" +"Hides user's content by collapsing posts. Also replaces their avatar with " +"generic image." +msgstr "إخفاء محتوى المستخدم عن طريق تصغير المشاركات. و استبدال الصورة الرمزية الخاصة بهم بصورة عامة." + +#: blockem.php:51 +msgid "Comma separated profile URLS:" +msgstr "عناوين الملفات الشخصية مفصولة بفواصل:" + +#: blockem.php:55 +msgid "Save Settings" +msgstr "احفظ الإعدادات" + +#: blockem.php:131 +#, php-format +msgid "Filtered user: %s" +msgstr "ترشيح المستخدم :1%s" + +#: blockem.php:190 +msgid "Unblock Author" +msgstr "ألغ الحجب عن المدون" + +#: blockem.php:192 +msgid "Block Author" +msgstr "احجب المدون" diff --git a/blockem/lang/ar/strings.php b/blockem/lang/ar/strings.php new file mode 100644 index 00000000..0f58fa22 --- /dev/null +++ b/blockem/lang/ar/strings.php @@ -0,0 +1,14 @@ +=3 && $n%100<=10) { return 3; } else if ($n%100>=11 && $n%100<=99) { return 4; } else { return 5; } +}} +$a->strings['Blockem'] = 'احجبه
'; +$a->strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'إخفاء محتوى المستخدم عن طريق تصغير المشاركات. و استبدال الصورة الرمزية الخاصة بهم بصورة عامة.'; +$a->strings['Comma separated profile URLS:'] = 'عناوين الملفات الشخصية مفصولة بفواصل:'; +$a->strings['Save Settings'] = 'احفظ الإعدادات'; +$a->strings['Filtered user: %s'] = 'ترشيح المستخدم :1%s'; +$a->strings['Unblock Author'] = 'ألغ الحجب عن المدون'; +$a->strings['Block Author'] = 'احجب المدون'; diff --git a/blockem/lang/ca/messages.po b/blockem/lang/ca/messages.po new file mode 100644 index 00000000..6d4c3468 --- /dev/null +++ b/blockem/lang/ca/messages.po @@ -0,0 +1,59 @@ +# ADDON blockem +# Copyright (C) +# This file is distributed under the same license as the Friendica blockem addon package. +# +# +# Translators: +# Joan Bar , 2019 +msgid "" +msgstr "" +"Project-Id-Version: friendica\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-08-17 10:23+0200\n" +"PO-Revision-Date: 2019-10-14 11:50+0000\n" +"Last-Translator: Joan Bar \n" +"Language-Team: Catalan (http://www.transifex.com/Friendica/friendica/language/ca/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ca\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: blockem.php:54 blockem.php:58 +msgid "Blockem" +msgstr "Blockem" + +#: blockem.php:62 +msgid "" +"Hides user's content by collapsing posts. Also replaces their avatar with " +"generic image." +msgstr "Amaga el contingut de l'usuari mitjançant la publicació col·lapsada. També substitueix el seu avatar per una imatge genèrica" + +#: blockem.php:63 +msgid "Comma separated profile URLS:" +msgstr "URL de perfil separats per comes:" + +#: blockem.php:67 +msgid "Save Settings" +msgstr "Desa la configuració" + +#: blockem.php:81 +msgid "BLOCKEM Settings saved." +msgstr "S'ha desat la configuració de BLOCKEM." + +#: blockem.php:143 +#, php-format +msgid "Filtered user: %s" +msgstr "Usuari filtrat:%s" + +#: blockem.php:202 +msgid "Unblock Author" +msgstr "Desbloca l'autor" + +#: blockem.php:204 +msgid "Block Author" +msgstr "Autor de bloc" + +#: blockem.php:244 +msgid "blockem settings updated" +msgstr "S'ha actualitzat la configuració de blockem" diff --git a/blockem/lang/ca/strings.php b/blockem/lang/ca/strings.php new file mode 100644 index 00000000..be4deede --- /dev/null +++ b/blockem/lang/ca/strings.php @@ -0,0 +1,16 @@ +strings['Blockem'] = 'Blockem'; +$a->strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Amaga el contingut de l\'usuari mitjançant la publicació col·lapsada. També substitueix el seu avatar per una imatge genèrica'; +$a->strings['Comma separated profile URLS:'] = 'URL de perfil separats per comes:'; +$a->strings['Save Settings'] = 'Desa la configuració'; +$a->strings['BLOCKEM Settings saved.'] = 'S\'ha desat la configuració de BLOCKEM.'; +$a->strings['Filtered user: %s'] = 'Usuari filtrat:%s'; +$a->strings['Unblock Author'] = 'Desbloca l\'autor'; +$a->strings['Block Author'] = 'Autor de bloc'; +$a->strings['blockem settings updated'] = 'S\'ha actualitzat la configuració de blockem'; diff --git a/blockem/lang/cs/messages.po b/blockem/lang/cs/messages.po new file mode 100644 index 00000000..fb90a2ca --- /dev/null +++ b/blockem/lang/cs/messages.po @@ -0,0 +1,60 @@ +# ADDON blockem +# Copyright (C) +# This file is distributed under the same license as the Friendica blockem addon package. +# +# +# Translators: +# Aditoo, 2018 +# michal_s , 2014 +msgid "" +msgstr "" +"Project-Id-Version: friendica\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-08-17 10:23+0200\n" +"PO-Revision-Date: 2018-08-18 12:25+0000\n" +"Last-Translator: Aditoo\n" +"Language-Team: Czech (http://www.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" + +#: blockem.php:54 blockem.php:58 +msgid "Blockem" +msgstr "Blockem" + +#: blockem.php:62 +msgid "" +"Hides user's content by collapsing posts. Also replaces their avatar with " +"generic image." +msgstr "Skrývá uživatelský obsah zabalením příspěvků. Navíc nahrazuje avatar generickým obrázkem." + +#: blockem.php:63 +msgid "Comma separated profile URLS:" +msgstr "URL adresy profilů, oddělené čárkami:" + +#: blockem.php:67 +msgid "Save Settings" +msgstr "Uložit nastavení" + +#: blockem.php:81 +msgid "BLOCKEM Settings saved." +msgstr "Nastavení BLOCKEM uložena." + +#: blockem.php:143 +#, php-format +msgid "Filtered user: %s" +msgstr "Filtrovaný uživatel: %s" + +#: blockem.php:202 +msgid "Unblock Author" +msgstr "Odblokovat autora" + +#: blockem.php:204 +msgid "Block Author" +msgstr "Zablokovat autora" + +#: blockem.php:244 +msgid "blockem settings updated" +msgstr "nastavení blockem aktualizována" diff --git a/blockem/lang/cs/strings.php b/blockem/lang/cs/strings.php new file mode 100644 index 00000000..ac32d78f --- /dev/null +++ b/blockem/lang/cs/strings.php @@ -0,0 +1,16 @@ += 2 && $n <= 4 && $n % 1 == 0)) { return 1; } else if (($n % 1 != 0 )) { return 2; } else { return 3; } +}} +$a->strings['Blockem'] = 'Blockem'; +$a->strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Skrývá uživatelský obsah zabalením příspěvků. Navíc nahrazuje avatar generickým obrázkem.'; +$a->strings['Comma separated profile URLS:'] = 'URL adresy profilů, oddělené čárkami:'; +$a->strings['Save Settings'] = 'Uložit nastavení'; +$a->strings['BLOCKEM Settings saved.'] = 'Nastavení BLOCKEM uložena.'; +$a->strings['Filtered user: %s'] = 'Filtrovaný uživatel: %s'; +$a->strings['Unblock Author'] = 'Odblokovat autora'; +$a->strings['Block Author'] = 'Zablokovat autora'; +$a->strings['blockem settings updated'] = 'nastavení blockem aktualizována'; diff --git a/blockem/lang/da-dk/messages.po b/blockem/lang/da-dk/messages.po new file mode 100644 index 00000000..e4a80bff --- /dev/null +++ b/blockem/lang/da-dk/messages.po @@ -0,0 +1,47 @@ +# ADDON blockem +# Copyright (C) +# This file is distributed under the same license as the Friendica blockem addon package. +# +# +# Translators: +# Anton , 2022 +msgid "" +msgstr "" +"Project-Id-Version: friendica\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-11-21 19:13-0500\n" +"PO-Revision-Date: 2014-06-22 11:20+0000\n" +"Last-Translator: Anton , 2022\n" +"Language-Team: Danish (Denmark) (http://www.transifex.com/Friendica/friendica/language/da_DK/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: da_DK\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: blockem.php:39 +msgid "" +"Hides user's content by collapsing posts. Also replaces their avatar with " +"generic image." +msgstr "Skjul brugers indhold ved at kollapse deres opslag. Erstatter også deres avatar med et generisk billede." + +#: blockem.php:40 +msgid "Comma separated profile URLS:" +msgstr "Kommasepareret liste over profil-URL's:" + +#: blockem.php:45 +msgid "Blockem" +msgstr "Blokdem" + +#: blockem.php:120 +#, php-format +msgid "Filtered user: %s" +msgstr "Filtreret bruger: %s" + +#: blockem.php:183 +msgid "Unblock Author" +msgstr "Fjern blokering af forfatter" + +#: blockem.php:185 +msgid "Block Author" +msgstr "Blokér forfatter" diff --git a/blockem/lang/da-dk/strings.php b/blockem/lang/da-dk/strings.php new file mode 100644 index 00000000..e99144ec --- /dev/null +++ b/blockem/lang/da-dk/strings.php @@ -0,0 +1,13 @@ +strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Skjul brugers indhold ved at kollapse deres opslag. Erstatter også deres avatar med et generisk billede.'; +$a->strings['Comma separated profile URLS:'] = 'Kommasepareret liste over profil-URL\'s:'; +$a->strings['Blockem'] = 'Blokdem'; +$a->strings['Filtered user: %s'] = 'Filtreret bruger: %s'; +$a->strings['Unblock Author'] = 'Fjern blokering af forfatter'; +$a->strings['Block Author'] = 'Blokér forfatter'; diff --git a/blockem/lang/de/messages.po b/blockem/lang/de/messages.po new file mode 100644 index 00000000..d1e2f704 --- /dev/null +++ b/blockem/lang/de/messages.po @@ -0,0 +1,50 @@ +# ADDON blockem +# Copyright (C) +# This file is distributed under the same license as the Friendica blockem addon package. +# +# +# Translators: +# Andreas H., 2018 +# Tobias Diekershoff , 2014 +# Tobias Diekershoff , 2018 +# Ulf Rompe , 2019 +msgid "" +msgstr "" +"Project-Id-Version: friendica\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-11-21 19:13-0500\n" +"PO-Revision-Date: 2021-12-22 15:27+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: blockem.php:39 +msgid "" +"Hides user's content by collapsing posts. Also replaces their avatar with " +"generic image." +msgstr "Verbirgt Inhalte von Benutzern durch Zusammenklappen der Beiträge. Des Weiteren wird das Profilbild durch einen generischen Avatar ersetzt." + +#: blockem.php:40 +msgid "Comma separated profile URLS:" +msgstr "Komma-separierte Liste von Profil-URLs" + +#: blockem.php:45 +msgid "Blockem" +msgstr "Blockem" + +#: blockem.php:120 +#, php-format +msgid "Filtered user: %s" +msgstr "Gefilterte Person: %s" + +#: blockem.php:183 +msgid "Unblock Author" +msgstr "Autor freischalten" + +#: blockem.php:185 +msgid "Block Author" +msgstr "Autor blockieren" diff --git a/blockem/lang/de/strings.php b/blockem/lang/de/strings.php new file mode 100644 index 00000000..109af368 --- /dev/null +++ b/blockem/lang/de/strings.php @@ -0,0 +1,13 @@ +strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Verbirgt Inhalte von Benutzern durch Zusammenklappen der Beiträge. Des Weiteren wird das Profilbild durch einen generischen Avatar ersetzt.'; +$a->strings['Comma separated profile URLS:'] = 'Komma-separierte Liste von Profil-URLs'; +$a->strings['Blockem'] = 'Blockem'; +$a->strings['Filtered user: %s'] = 'Gefilterte Person: %s'; +$a->strings['Unblock Author'] = 'Autor freischalten'; +$a->strings['Block Author'] = 'Autor blockieren'; diff --git a/blockem/lang/en-gb/messages.po b/blockem/lang/en-gb/messages.po new file mode 100644 index 00000000..6bcc7b9b --- /dev/null +++ b/blockem/lang/en-gb/messages.po @@ -0,0 +1,59 @@ +# ADDON blockem +# Copyright (C) +# This file is distributed under the same license as the Friendica blockem addon package. +# +# +# Translators: +# Andy H3 , 2018 +msgid "" +msgstr "" +"Project-Id-Version: friendica\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-02-09 13:00+0100\n" +"PO-Revision-Date: 2018-03-15 14:10+0000\n" +"Last-Translator: Andy H3 \n" +"Language-Team: English (United Kingdom) (http://www.transifex.com/Friendica/friendica/language/en_GB/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_GB\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: blockem.php:51 blockem.php:55 +msgid "\"Blockem\"" +msgstr "\"Blockem\"" + +#: blockem.php:59 +msgid "" +"Hides user's content by collapsing posts. Also replaces their avatar with " +"generic image." +msgstr "Hides user's content by collapsing posts. Also replaces their avatar with generic image." + +#: blockem.php:60 +msgid "Comma separated profile URLS:" +msgstr "Comma separated profile URLs:" + +#: blockem.php:64 +msgid "Save Settings" +msgstr "Save settings" + +#: blockem.php:77 +msgid "BLOCKEM Settings saved." +msgstr "Blockem settings saved." + +#: blockem.php:140 +#, php-format +msgid "Hidden content by %s - Click to open/close" +msgstr "Hidden content by %s - Reveal/hide" + +#: blockem.php:193 +msgid "Unblock Author" +msgstr "Unblock author" + +#: blockem.php:195 +msgid "Block Author" +msgstr "Block author" + +#: blockem.php:227 +msgid "blockem settings updated" +msgstr "Blockem settings updated" diff --git a/blockem/lang/en-gb/strings.php b/blockem/lang/en-gb/strings.php new file mode 100644 index 00000000..0b9d9e4b --- /dev/null +++ b/blockem/lang/en-gb/strings.php @@ -0,0 +1,16 @@ +strings['"Blockem"'] = '"Blockem"'; +$a->strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'; +$a->strings['Comma separated profile URLS:'] = 'Comma separated profile URLs:'; +$a->strings['Save Settings'] = 'Save settings'; +$a->strings['BLOCKEM Settings saved.'] = 'Blockem settings saved.'; +$a->strings['Hidden content by %s - Click to open/close'] = 'Hidden content by %s - Reveal/hide'; +$a->strings['Unblock Author'] = 'Unblock author'; +$a->strings['Block Author'] = 'Block author'; +$a->strings['blockem settings updated'] = 'Blockem settings updated'; diff --git a/blockem/lang/en-us/messages.po b/blockem/lang/en-us/messages.po new file mode 100644 index 00000000..1d64620b --- /dev/null +++ b/blockem/lang/en-us/messages.po @@ -0,0 +1,61 @@ +# ADDON blockem +# Copyright (C) +# This file is distributed under the same license as the Friendica blockem addon package. +# +# +# Translators: +# Adam Clark , 2018 +# Andy H3 , 2018 +# R C , 2018 +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: 2018-06-13 02:40+0000\n" +"Last-Translator: R C \n" +"Language-Team: English (United States) (http://www.transifex.com/Friendica/friendica/language/en_US/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_US\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: blockem.php:52 blockem.php:56 +msgid "\"Blockem\"" +msgstr "Blockem" + +#: blockem.php:60 +msgid "" +"Hides user's content by collapsing posts. Also replaces their avatar with " +"generic image." +msgstr "Hides user's content by collapsing posts. Also replaces their avatar with generic image." + +#: blockem.php:61 +msgid "Comma separated profile URLS:" +msgstr "Comma-separated profile URLs:" + +#: blockem.php:65 +msgid "Save Settings" +msgstr "Save settings" + +#: blockem.php:78 +msgid "BLOCKEM Settings saved." +msgstr "Blockem settings saved." + +#: blockem.php:136 +#, php-format +msgid "Filtered user: %s" +msgstr "Filtered user: %s" + +#: blockem.php:189 +msgid "Unblock Author" +msgstr "Unblock author" + +#: blockem.php:191 +msgid "Block Author" +msgstr "Block author" + +#: blockem.php:223 +msgid "blockem settings updated" +msgstr "Blockem settings updated" diff --git a/blockem/lang/en-us/strings.php b/blockem/lang/en-us/strings.php new file mode 100644 index 00000000..fd76a1bc --- /dev/null +++ b/blockem/lang/en-us/strings.php @@ -0,0 +1,16 @@ +strings['"Blockem"'] = 'Blockem'; +$a->strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'; +$a->strings['Comma separated profile URLS:'] = 'Comma-separated profile URLs:'; +$a->strings['Save Settings'] = 'Save settings'; +$a->strings['BLOCKEM Settings saved.'] = 'Blockem settings saved.'; +$a->strings['Filtered user: %s'] = 'Filtered user: %s'; +$a->strings['Unblock Author'] = 'Unblock author'; +$a->strings['Block Author'] = 'Block author'; +$a->strings['blockem settings updated'] = 'Blockem settings updated'; diff --git a/blockem/lang/eo/strings.php b/blockem/lang/eo/strings.php new file mode 100644 index 00000000..b6116507 --- /dev/null +++ b/blockem/lang/eo/strings.php @@ -0,0 +1,10 @@ +strings["\"Blockem\" Settings"] = "\"Blockem\" Agordoj"; +$a->strings["Comma separated profile URLS to block"] = "Blokotaj URL adresoj, disigita per komo"; +$a->strings["Submit"] = "Sendi"; +$a->strings["BLOCKEM Settings saved."] = "Konservis Agordojn de BLOCKEM."; +$a->strings["Blocked %s - Click to open/close"] = "%s blokita - Klaku por malfermi/fermi"; +$a->strings["Unblock Author"] = "Malbloki Aŭtoron"; +$a->strings["Block Author"] = "Bloki Aŭtoron"; +$a->strings["blockem settings updated"] = "Ĝisdatigis la blockem agordojn"; diff --git a/blockem/lang/es/messages.po b/blockem/lang/es/messages.po new file mode 100644 index 00000000..0b59921e --- /dev/null +++ b/blockem/lang/es/messages.po @@ -0,0 +1,53 @@ +# ADDON blockem +# Copyright (C) +# This file is distributed under the same license as the Friendica blockem addon package. +# +# +# Translators: +# Albert, 2018 +# Senex Petrovic , 2021 +# Tupambae.org, 2016 +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-01 09:45+0000\n" +"Last-Translator: Senex Petrovic \n" +"Language-Team: Spanish (http://www.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" + +#: blockem.php:42 blockem.php:46 +msgid "Blockem" +msgstr "Blockem (Bloquealos)" + +#: blockem.php:50 +msgid "" +"Hides user's content by collapsing posts. Also replaces their avatar with " +"generic image." +msgstr "Oculta el contenido del usuario al colapsar las publicaciones. También reemplaza su avatar con una imagen genérica." + +#: blockem.php:51 +msgid "Comma separated profile URLS:" +msgstr "URLs de perfil separadas por comas:" + +#: blockem.php:55 +msgid "Save Settings" +msgstr "Guardar configuración" + +#: blockem.php:131 +#, php-format +msgid "Filtered user: %s" +msgstr "Usuario filtrado: %s" + +#: blockem.php:190 +msgid "Unblock Author" +msgstr "Desbloquear autor" + +#: blockem.php:192 +msgid "Block Author" +msgstr "Bloquear autor" diff --git a/blockem/lang/es/strings.php b/blockem/lang/es/strings.php new file mode 100644 index 00000000..7d1de601 --- /dev/null +++ b/blockem/lang/es/strings.php @@ -0,0 +1,14 @@ +strings['Blockem'] = 'Blockem (Bloquealos)'; +$a->strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Oculta el contenido del usuario al colapsar las publicaciones. También reemplaza su avatar con una imagen genérica.'; +$a->strings['Comma separated profile URLS:'] = 'URLs de perfil separadas por comas:'; +$a->strings['Save Settings'] = 'Guardar configuración'; +$a->strings['Filtered user: %s'] = 'Usuario filtrado: %s'; +$a->strings['Unblock Author'] = 'Desbloquear autor'; +$a->strings['Block Author'] = 'Bloquear autor'; diff --git a/blockem/lang/fi-fi/messages.po b/blockem/lang/fi-fi/messages.po new file mode 100644 index 00000000..4fac9aa7 --- /dev/null +++ b/blockem/lang/fi-fi/messages.po @@ -0,0 +1,60 @@ +# ADDON blockem +# Copyright (C) +# This file is distributed under the same license as the Friendica blockem addon package. +# +# +# Translators: +# Kris, 2018 +# Kris, 2018 +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: 2018-04-18 14:44+0000\n" +"Last-Translator: Kris\n" +"Language-Team: Finnish (Finland) (http://www.transifex.com/Friendica/friendica/language/fi_FI/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fi_FI\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: blockem.php:52 blockem.php:56 +msgid "\"Blockem\"" +msgstr "\"Blockem\"" + +#: blockem.php:60 +msgid "" +"Hides user's content by collapsing posts. Also replaces their avatar with " +"generic image." +msgstr "" + +#: blockem.php:61 +msgid "Comma separated profile URLS:" +msgstr "Profiilien URL-osoitteet pilkulla erotettuina:" + +#: blockem.php:65 +msgid "Save Settings" +msgstr "Tallenna asetukset" + +#: blockem.php:78 +msgid "BLOCKEM Settings saved." +msgstr "Blockem -asetukset tallennettu" + +#: blockem.php:136 +#, php-format +msgid "Filtered user: %s" +msgstr "Suodatettu käyttäjä: %s" + +#: blockem.php:189 +msgid "Unblock Author" +msgstr "Poista kirjoittaja estolistalta" + +#: blockem.php:191 +msgid "Block Author" +msgstr "Lisää kirjoittaja estolistalle" + +#: blockem.php:223 +msgid "blockem settings updated" +msgstr "blockem -asetukset päivitetty" diff --git a/blockem/lang/fi-fi/strings.php b/blockem/lang/fi-fi/strings.php new file mode 100644 index 00000000..d15b4a56 --- /dev/null +++ b/blockem/lang/fi-fi/strings.php @@ -0,0 +1,15 @@ +strings['"Blockem"'] = '"Blockem"'; +$a->strings['Comma separated profile URLS:'] = 'Profiilien URL-osoitteet pilkulla erotettuina:'; +$a->strings['Save Settings'] = 'Tallenna asetukset'; +$a->strings['BLOCKEM Settings saved.'] = 'Blockem -asetukset tallennettu'; +$a->strings['Filtered user: %s'] = 'Suodatettu käyttäjä: %s'; +$a->strings['Unblock Author'] = 'Poista kirjoittaja estolistalta'; +$a->strings['Block Author'] = 'Lisää kirjoittaja estolistalle'; +$a->strings['blockem settings updated'] = 'blockem -asetukset päivitetty'; diff --git a/blockem/lang/fr/messages.po b/blockem/lang/fr/messages.po new file mode 100644 index 00000000..d3617290 --- /dev/null +++ b/blockem/lang/fr/messages.po @@ -0,0 +1,50 @@ +# ADDON blockem +# Copyright (C) +# This file is distributed under the same license as the Friendica blockem addon package. +# +# +# Translators: +# Hypolite Petovan , 2016 +# Marie Olive , 2018 +# StefOfficiel , 2015 +# Vladimir Núñez , 2018 +msgid "" +msgstr "" +"Project-Id-Version: friendica\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-11-21 19:13-0500\n" +"PO-Revision-Date: 2014-06-22 11:20+0000\n" +"Last-Translator: Vladimir Núñez , 2018\n" +"Language-Team: French (http://www.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" + +#: blockem.php:39 +msgid "" +"Hides user's content by collapsing posts. Also replaces their avatar with " +"generic image." +msgstr "Cache le contenu de l'utilisateur en contractant les publications. Remplace aussi leur avatar par une image générique." + +#: blockem.php:40 +msgid "Comma separated profile URLS:" +msgstr "URLs de profil séparées par des virgules:" + +#: blockem.php:45 +msgid "Blockem" +msgstr "Bloquez-les" + +#: blockem.php:120 +#, php-format +msgid "Filtered user: %s" +msgstr "Utilisateur filtré:%s" + +#: blockem.php:183 +msgid "Unblock Author" +msgstr "Débloquer l'Auteur" + +#: blockem.php:185 +msgid "Block Author" +msgstr "Bloquer l'Auteur" diff --git a/blockem/lang/fr/strings.php b/blockem/lang/fr/strings.php new file mode 100644 index 00000000..26b86f24 --- /dev/null +++ b/blockem/lang/fr/strings.php @@ -0,0 +1,13 @@ +strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Cache le contenu de l\'utilisateur en contractant les publications. Remplace aussi leur avatar par une image générique.'; +$a->strings['Comma separated profile URLS:'] = 'URLs de profil séparées par des virgules:'; +$a->strings['Blockem'] = 'Bloquez-les'; +$a->strings['Filtered user: %s'] = 'Utilisateur filtré:%s'; +$a->strings['Unblock Author'] = 'Débloquer l\'Auteur'; +$a->strings['Block Author'] = 'Bloquer l\'Auteur'; diff --git a/blockem/lang/hu/messages.po b/blockem/lang/hu/messages.po new file mode 100644 index 00000000..3a29b820 --- /dev/null +++ b/blockem/lang/hu/messages.po @@ -0,0 +1,47 @@ +# ADDON blockem +# Copyright (C) +# This file is distributed under the same license as the Friendica blockem addon package. +# +# +# Translators: +# Balázs Úr, 2020 +msgid "" +msgstr "" +"Project-Id-Version: friendica\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-11-21 19:13-0500\n" +"PO-Revision-Date: 2014-06-22 11:20+0000\n" +"Last-Translator: Balázs Úr, 2020\n" +"Language-Team: Hungarian (http://www.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" + +#: blockem.php:39 +msgid "" +"Hides user's content by collapsing posts. Also replaces their avatar with " +"generic image." +msgstr "Elrejti a felhasználók tartalmát a bejegyzések összecsukásával. Ezenkívül lecseréli a profilképeiket egy általános képre." + +#: blockem.php:40 +msgid "Comma separated profile URLS:" +msgstr "Profil URL-ek vesszővel elválasztva:" + +#: blockem.php:45 +msgid "Blockem" +msgstr "Blockem" + +#: blockem.php:120 +#, php-format +msgid "Filtered user: %s" +msgstr "Kiszűrt felhasználó: %s" + +#: blockem.php:183 +msgid "Unblock Author" +msgstr "Szerző tiltásának feloldása" + +#: blockem.php:185 +msgid "Block Author" +msgstr "Szerző tiltása" diff --git a/blockem/lang/hu/strings.php b/blockem/lang/hu/strings.php new file mode 100644 index 00000000..5a3abfec --- /dev/null +++ b/blockem/lang/hu/strings.php @@ -0,0 +1,13 @@ +strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Elrejti a felhasználók tartalmát a bejegyzések összecsukásával. Ezenkívül lecseréli a profilképeiket egy általános képre.'; +$a->strings['Comma separated profile URLS:'] = 'Profil URL-ek vesszővel elválasztva:'; +$a->strings['Blockem'] = 'Blockem'; +$a->strings['Filtered user: %s'] = 'Kiszűrt felhasználó: %s'; +$a->strings['Unblock Author'] = 'Szerző tiltásának feloldása'; +$a->strings['Block Author'] = 'Szerző tiltása'; diff --git a/blockem/lang/is/strings.php b/blockem/lang/is/strings.php new file mode 100644 index 00000000..3075c457 --- /dev/null +++ b/blockem/lang/is/strings.php @@ -0,0 +1,10 @@ +strings["\"Blockem\" Settings"] = "\"Blockem\" stillingar"; +$a->strings["Comma separated profile URLS to block"] = "Banna lista af forsíðum (komma á milli)"; +$a->strings["Submit"] = "Senda inn"; +$a->strings["BLOCKEM Settings saved."] = "BLOCKEM stillingar vistaðar."; +$a->strings["Blocked %s - Click to open/close"] = "%s sett í straff - Smella til að taka úr/setja á"; +$a->strings["Unblock Author"] = "Leyfa notanda"; +$a->strings["Block Author"] = "Banna notanda"; +$a->strings["blockem settings updated"] = ""; diff --git a/blockem/lang/it/messages.po b/blockem/lang/it/messages.po new file mode 100644 index 00000000..cdf74f99 --- /dev/null +++ b/blockem/lang/it/messages.po @@ -0,0 +1,59 @@ +# ADDON blockem +# Copyright (C) +# This file is distributed under the same license as the Friendica blockem addon package. +# +# +# Translators: +# fabrixxm , 2014,2018-2019 +msgid "" +msgstr "" +"Project-Id-Version: friendica\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-08-17 10:23+0200\n" +"PO-Revision-Date: 2019-03-11 14:21+0000\n" +"Last-Translator: fabrixxm \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: it\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: blockem.php:54 blockem.php:58 +msgid "Blockem" +msgstr "Blockem" + +#: blockem.php:62 +msgid "" +"Hides user's content by collapsing posts. Also replaces their avatar with " +"generic image." +msgstr "Nascondi il contenuto degli utenti collassando i messaggi. Sostituisce anche gli avatar con un'immagine generica." + +#: blockem.php:63 +msgid "Comma separated profile URLS:" +msgstr "URL profili separati da virgola:" + +#: blockem.php:67 +msgid "Save Settings" +msgstr "Salva Impostazioni" + +#: blockem.php:81 +msgid "BLOCKEM Settings saved." +msgstr "Impostazioni BLOCKEM salvate." + +#: blockem.php:143 +#, php-format +msgid "Filtered user: %s" +msgstr "Utente filtrato: %s" + +#: blockem.php:202 +msgid "Unblock Author" +msgstr "Sblocca autore" + +#: blockem.php:204 +msgid "Block Author" +msgstr "Blocca autore" + +#: blockem.php:244 +msgid "blockem settings updated" +msgstr "Impostazioni 'blockem' aggiornate." diff --git a/blockem/lang/it/strings.php b/blockem/lang/it/strings.php new file mode 100644 index 00000000..aa73286a --- /dev/null +++ b/blockem/lang/it/strings.php @@ -0,0 +1,16 @@ +strings['Blockem'] = 'Blockem'; +$a->strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Nascondi il contenuto degli utenti collassando i messaggi. Sostituisce anche gli avatar con un\'immagine generica.'; +$a->strings['Comma separated profile URLS:'] = 'URL profili separati da virgola:'; +$a->strings['Save Settings'] = 'Salva Impostazioni'; +$a->strings['BLOCKEM Settings saved.'] = 'Impostazioni BLOCKEM salvate.'; +$a->strings['Filtered user: %s'] = 'Utente filtrato: %s'; +$a->strings['Unblock Author'] = 'Sblocca autore'; +$a->strings['Block Author'] = 'Blocca autore'; +$a->strings['blockem settings updated'] = 'Impostazioni \'blockem\' aggiornate.'; diff --git a/blockem/lang/nb-no/strings.php b/blockem/lang/nb-no/strings.php new file mode 100644 index 00000000..0dd6660d --- /dev/null +++ b/blockem/lang/nb-no/strings.php @@ -0,0 +1,10 @@ +strings["\"Blockem\" Settings"] = ""; +$a->strings["Comma separated profile URLS to block"] = ""; +$a->strings["Submit"] = "Lagre"; +$a->strings["BLOCKEM Settings saved."] = ""; +$a->strings["Blocked %s - Click to open/close"] = ""; +$a->strings["Unblock Author"] = ""; +$a->strings["Block Author"] = ""; +$a->strings["blockem settings updated"] = ""; diff --git a/blockem/lang/nl/messages.po b/blockem/lang/nl/messages.po new file mode 100644 index 00000000..f8bde25c --- /dev/null +++ b/blockem/lang/nl/messages.po @@ -0,0 +1,60 @@ +# ADDON blockem +# Copyright (C) +# This file is distributed under the same license as the Friendica blockem addon package. +# +# +# Translators: +# AgnesElisa , 2018 +# Jeroen De Meerleer , 2018 +msgid "" +msgstr "" +"Project-Id-Version: friendica\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-08-17 10:23+0200\n" +"PO-Revision-Date: 2018-08-24 13:49+0000\n" +"Last-Translator: Jeroen De Meerleer \n" +"Language-Team: Dutch (http://www.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" + +#: blockem.php:54 blockem.php:58 +msgid "Blockem" +msgstr "Blockem" + +#: blockem.php:62 +msgid "" +"Hides user's content by collapsing posts. Also replaces their avatar with " +"generic image." +msgstr "Verbergt de inhoud van het bericht van de gebruiker. Daarnaast vervangt het de avatar door een standaardafbeelding." + +#: blockem.php:63 +msgid "Comma separated profile URLS:" +msgstr "Profiel URLs (kommagescheiden):" + +#: blockem.php:67 +msgid "Save Settings" +msgstr "Instellingen opslaan" + +#: blockem.php:81 +msgid "BLOCKEM Settings saved." +msgstr "BLOCKEM instellingen opgeslagen." + +#: blockem.php:143 +#, php-format +msgid "Filtered user: %s" +msgstr "Gefilterde gebruiker: %s" + +#: blockem.php:202 +msgid "Unblock Author" +msgstr "Deblokkeer Auteur" + +#: blockem.php:204 +msgid "Block Author" +msgstr "Auteur blokkeren" + +#: blockem.php:244 +msgid "blockem settings updated" +msgstr "blockem instellingen opgeslagen" diff --git a/blockem/lang/nl/strings.php b/blockem/lang/nl/strings.php new file mode 100644 index 00000000..b523cdc4 --- /dev/null +++ b/blockem/lang/nl/strings.php @@ -0,0 +1,16 @@ +strings['Blockem'] = 'Blockem'; +$a->strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Verbergt de inhoud van het bericht van de gebruiker. Daarnaast vervangt het de avatar door een standaardafbeelding.'; +$a->strings['Comma separated profile URLS:'] = 'Profiel URLs (kommagescheiden):'; +$a->strings['Save Settings'] = 'Instellingen opslaan'; +$a->strings['BLOCKEM Settings saved.'] = 'BLOCKEM instellingen opgeslagen.'; +$a->strings['Filtered user: %s'] = 'Gefilterde gebruiker: %s'; +$a->strings['Unblock Author'] = 'Deblokkeer Auteur'; +$a->strings['Block Author'] = 'Auteur blokkeren'; +$a->strings['blockem settings updated'] = 'blockem instellingen opgeslagen'; diff --git a/blockem/lang/pl/messages.po b/blockem/lang/pl/messages.po new file mode 100644 index 00000000..8e70e0b5 --- /dev/null +++ b/blockem/lang/pl/messages.po @@ -0,0 +1,47 @@ +# ADDON blockem +# Copyright (C) +# This file is distributed under the same license as the Friendica blockem addon package. +# +# +# Translators: +# Waldemar Stoczkowski, 2018 +msgid "" +msgstr "" +"Project-Id-Version: friendica\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-11-21 19:13-0500\n" +"PO-Revision-Date: 2014-06-22 11:20+0000\n" +"Last-Translator: Waldemar Stoczkowski, 2018\n" +"Language-Team: Polish (http://www.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" + +#: blockem.php:39 +msgid "" +"Hides user's content by collapsing posts. Also replaces their avatar with " +"generic image." +msgstr "Ukrywa zawartość użytkownika, zwijając posty. Zastępuje również awatar wygenerowanym obrazem." + +#: blockem.php:40 +msgid "Comma separated profile URLS:" +msgstr "Rozdzielone przecinkami adresy URL profilu:" + +#: blockem.php:45 +msgid "Blockem" +msgstr "Zablokowanie" + +#: blockem.php:120 +#, php-format +msgid "Filtered user: %s" +msgstr "Użytkownik filtrowany: %s" + +#: blockem.php:183 +msgid "Unblock Author" +msgstr "Odblokuj autora" + +#: blockem.php:185 +msgid "Block Author" +msgstr "Zablokuj autora" diff --git a/blockem/lang/pl/strings.php b/blockem/lang/pl/strings.php new file mode 100644 index 00000000..49951a68 --- /dev/null +++ b/blockem/lang/pl/strings.php @@ -0,0 +1,13 @@ +=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['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Ukrywa zawartość użytkownika, zwijając posty. Zastępuje również awatar wygenerowanym obrazem.'; +$a->strings['Comma separated profile URLS:'] = 'Rozdzielone przecinkami adresy URL profilu:'; +$a->strings['Blockem'] = 'Zablokowanie'; +$a->strings['Filtered user: %s'] = 'Użytkownik filtrowany: %s'; +$a->strings['Unblock Author'] = 'Odblokuj autora'; +$a->strings['Block Author'] = 'Zablokuj autora'; diff --git a/blockem/lang/pt-br/strings.php b/blockem/lang/pt-br/strings.php new file mode 100644 index 00000000..49f69cc3 --- /dev/null +++ b/blockem/lang/pt-br/strings.php @@ -0,0 +1,10 @@ +strings["\"Blockem\" Settings"] = "Configurações \"Blockem\""; +$a->strings["Comma separated profile URLS to block"] = "URLS de perfis separados por vírgulas a serem bloqueados"; +$a->strings["Submit"] = "Enviar"; +$a->strings["BLOCKEM Settings saved."] = "Configurações BLOCKEM armazenadas."; +$a->strings["Blocked %s - Click to open/close"] = "Bloqueado %s - Clique para abrir/fechar"; +$a->strings["Unblock Author"] = "Desbloqueie Autor"; +$a->strings["Block Author"] = "Bloqueie Autor"; +$a->strings["blockem settings updated"] = "configurações blockem atualizadas"; diff --git a/blockem/lang/ro/messages.po b/blockem/lang/ro/messages.po new file mode 100644 index 00000000..a74e5757 --- /dev/null +++ b/blockem/lang/ro/messages.po @@ -0,0 +1,52 @@ +# ADDON blockem +# Copyright (C) +# This file is distributed under the same license as the Friendica blockem addon package. +# +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: friendica\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-06-22 13:18+0200\n" +"PO-Revision-Date: 2014-07-08 11:43+0000\n" +"Last-Translator: Arian - Cazare Muncitori \n" +"Language-Team: Romanian (Romania) (http://www.transifex.com/projects/p/friendica/language/ro_RO/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ro_RO\n" +"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n" + +#: blockem.php:53 blockem.php:57 +msgid "\"Blockem\"" +msgstr "\"Blockem\"" + +#: blockem.php:61 +msgid "Comma separated profile URLS to block" +msgstr "Adresele URL de profil, de blocat, separate prin virgulă" + +#: blockem.php:65 +msgid "Save Settings" +msgstr "Salvare Configurări" + +#: blockem.php:78 +msgid "BLOCKEM Settings saved." +msgstr "Configurările BLOCKEM au fost salvate." + +#: blockem.php:142 +#, php-format +msgid "Blocked %s - Click to open/close" +msgstr "%s Blocate - Apăsați pentru a deschide/închide" + +#: blockem.php:197 +msgid "Unblock Author" +msgstr "Deblocare Autor" + +#: blockem.php:199 +msgid "Block Author" +msgstr "Blocare Autor" + +#: blockem.php:231 +msgid "blockem settings updated" +msgstr "Configurările blockem au fost actualizate" diff --git a/blockem/lang/ro/strings.php b/blockem/lang/ro/strings.php new file mode 100644 index 00000000..6fc8a094 --- /dev/null +++ b/blockem/lang/ro/strings.php @@ -0,0 +1,15 @@ +19)||(($n%100==0)&&($n!=0)))) { return 2; } else { return 1; } +}} +$a->strings['"Blockem"'] = '"Blockem"'; +$a->strings['Comma separated profile URLS to block'] = 'Adresele URL de profil, de blocat, separate prin virgulă'; +$a->strings['Save Settings'] = 'Salvare Configurări'; +$a->strings['BLOCKEM Settings saved.'] = 'Configurările BLOCKEM au fost salvate.'; +$a->strings['Blocked %s - Click to open/close'] = '%s Blocate - Apăsați pentru a deschide/închide'; +$a->strings['Unblock Author'] = 'Deblocare Autor'; +$a->strings['Block Author'] = 'Blocare Autor'; +$a->strings['blockem settings updated'] = 'Configurările blockem au fost actualizate'; diff --git a/blockem/lang/ru/messages.po b/blockem/lang/ru/messages.po new file mode 100644 index 00000000..22427327 --- /dev/null +++ b/blockem/lang/ru/messages.po @@ -0,0 +1,60 @@ +# ADDON blockem +# Copyright (C) +# This file is distributed under the same license as the Friendica blockem addon package. +# +# +# Translators: +# Alexander An , 2020 +# Stanislav N. , 2017-2018 +msgid "" +msgstr "" +"Project-Id-Version: friendica\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-08-17 10:23+0200\n" +"PO-Revision-Date: 2020-04-23 14:13+0000\n" +"Last-Translator: Alexander An \n" +"Language-Team: Russian (http://www.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" + +#: blockem.php:54 blockem.php:58 +msgid "Blockem" +msgstr "Blockem" + +#: blockem.php:62 +msgid "" +"Hides user's content by collapsing posts. Also replaces their avatar with " +"generic image." +msgstr "Скрыть контент пользователя. Также заменяет его аватар изображением по-умолчанию." + +#: blockem.php:63 +msgid "Comma separated profile URLS:" +msgstr "URL профилей, разделенные запятыми:" + +#: blockem.php:67 +msgid "Save Settings" +msgstr "Сохранить настройки" + +#: blockem.php:81 +msgid "BLOCKEM Settings saved." +msgstr "BLOCKEM Настройки сохранены." + +#: blockem.php:143 +#, php-format +msgid "Filtered user: %s" +msgstr "Отфильтрованный пользователь: %s" + +#: blockem.php:202 +msgid "Unblock Author" +msgstr "Разблокировать автора" + +#: blockem.php:204 +msgid "Block Author" +msgstr "Блокировать автора" + +#: blockem.php:244 +msgid "blockem settings updated" +msgstr "Настройки Blockem обновлены" diff --git a/blockem/lang/ru/strings.php b/blockem/lang/ru/strings.php new file mode 100644 index 00000000..ef586740 --- /dev/null +++ b/blockem/lang/ru/strings.php @@ -0,0 +1,16 @@ +=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['Blockem'] = 'Blockem'; +$a->strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Скрыть контент пользователя. Также заменяет его аватар изображением по-умолчанию.'; +$a->strings['Comma separated profile URLS:'] = 'URL профилей, разделенные запятыми:'; +$a->strings['Save Settings'] = 'Сохранить настройки'; +$a->strings['BLOCKEM Settings saved.'] = 'BLOCKEM Настройки сохранены.'; +$a->strings['Filtered user: %s'] = 'Отфильтрованный пользователь: %s'; +$a->strings['Unblock Author'] = 'Разблокировать автора'; +$a->strings['Block Author'] = 'Блокировать автора'; +$a->strings['blockem settings updated'] = 'Настройки Blockem обновлены'; diff --git a/blockem/lang/sv/messages.po b/blockem/lang/sv/messages.po new file mode 100644 index 00000000..ede8ee94 --- /dev/null +++ b/blockem/lang/sv/messages.po @@ -0,0 +1,47 @@ +# ADDON blockem +# Copyright (C) +# This file is distributed under the same license as the Friendica blockem addon package. +# +# +# Translators: +# Bjoessi , 2019 +msgid "" +msgstr "" +"Project-Id-Version: friendica\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-11-21 19:13-0500\n" +"PO-Revision-Date: 2021-12-22 15:27+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Swedish (http://www.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" + +#: blockem.php:39 +msgid "" +"Hides user's content by collapsing posts. Also replaces their avatar with " +"generic image." +msgstr "Döljer användares inlägg genom sammanslagning nedåt. Användarens profilbild ersätts med en standardbild." + +#: blockem.php:40 +msgid "Comma separated profile URLS:" +msgstr "Kommaseparerade profiladresser:" + +#: blockem.php:45 +msgid "Blockem" +msgstr "BLOCKEM" + +#: blockem.php:120 +#, php-format +msgid "Filtered user: %s" +msgstr "Filtrerat på användare:%s" + +#: blockem.php:183 +msgid "Unblock Author" +msgstr "Avblockera författare" + +#: blockem.php:185 +msgid "Block Author" +msgstr "Blockera författare" diff --git a/blockem/lang/sv/strings.php b/blockem/lang/sv/strings.php new file mode 100644 index 00000000..724e2d23 --- /dev/null +++ b/blockem/lang/sv/strings.php @@ -0,0 +1,13 @@ +strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Döljer användares inlägg genom sammanslagning nedåt. Användarens profilbild ersätts med en standardbild.'; +$a->strings['Comma separated profile URLS:'] = 'Kommaseparerade profiladresser:'; +$a->strings['Blockem'] = 'BLOCKEM'; +$a->strings['Filtered user: %s'] = 'Filtrerat på användare:%s'; +$a->strings['Unblock Author'] = 'Avblockera författare'; +$a->strings['Block Author'] = 'Blockera författare'; diff --git a/blockem/lang/zh-cn/strings.php b/blockem/lang/zh-cn/strings.php new file mode 100644 index 00000000..3a3dfaeb --- /dev/null +++ b/blockem/lang/zh-cn/strings.php @@ -0,0 +1,10 @@ +strings["\"Blockem\" Settings"] = "「Blockem」配置"; +$a->strings["Comma separated profile URLS to block"] = "逗号分简介URL为栏"; +$a->strings["Submit"] = "提交"; +$a->strings["BLOCKEM Settings saved."] = "「Blockem」配置保存了。"; +$a->strings["Blocked %s - Click to open/close"] = "%s拦了-点击为开关"; +$a->strings["Unblock Author"] = "不拦作家"; +$a->strings["Block Author"] = "拦作家"; +$a->strings["blockem settings updated"] = "blockem设置更新了"; diff --git a/blockem/templates/settings.tpl b/blockem/templates/settings.tpl new file mode 100644 index 00000000..67398400 --- /dev/null +++ b/blockem/templates/settings.tpl @@ -0,0 +1 @@ +{{include file="field_textarea.tpl" field=$words}} diff --git a/bluesky/README.md b/bluesky/README.md deleted file mode 100644 index bf900fcd..00000000 --- a/bluesky/README.md +++ /dev/null @@ -1,9 +0,0 @@ -Bluesky Addon -============== - -This addon supports posting to and receiving posts from Bluesky. - -No setup is needed for the admins to make it work for their users. - -Bluesky itself is under development as well. It is planned to make it decentral. -The addon is prepared to support different servers. But it isn't enabled yet. \ No newline at end of file diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php deleted file mode 100644 index dac95437..00000000 --- a/bluesky/bluesky.php +++ /dev/null @@ -1,1775 +0,0 @@ - - * - * @todo - * Currently technical issues in the core: - * - Outgoing mentions - * - * At some point in time: - * - Sending Quote shares https://atproto.com/lexicons/app-bsky-embed#appbskyembedrecord and https://atproto.com/lexicons/app-bsky-embed#appbskyembedrecordwithmedia - * - * Possibly not possible: - * - only fetch new posts - * - * Currently not possible, due to limitations in Friendica - * - mute contacts https://atproto.com/lexicons/app-bsky-graph#appbskygraphmuteactor - * - unmute contacts https://atproto.com/lexicons/app-bsky-graph#appbskygraphunmuteactor - * - * Possibly interesting: - * - https://atproto.com/lexicons/com-atproto-label#comatprotolabelsubscribelabels - */ - -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; -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\GServer; -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; -use Friendica\Protocol\Activity; -use Friendica\Protocol\Relay; -use Friendica\Util\DateTimeFormat; -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_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'); - Hook::register('hook_fork', __FILE__, 'bluesky_hook_fork'); - Hook::register('post_local', __FILE__, 'bluesky_post_local'); - Hook::register('notifier_normal', __FILE__, 'bluesky_send'); - Hook::register('jot_networks', __FILE__, 'bluesky_jot_nets'); - Hook::register('connector_settings', __FILE__, 'bluesky_settings'); - 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'); -} - -function bluesky_load_config(ConfigFileManager $loader) -{ - DI::app()->getConfigCache()->load($loader->loadAddonConfig('bluesky'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); -} - -function bluesky_check_item_notification(array &$notification_data) -{ - $did = DI::pConfig()->get($notification_data['uid'], 'bluesky', 'did'); - - if (!empty($did)) { - $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 (preg_match('#^' . BLUESKY_WEB . '/profile/(.+)#', $hookData['uri'], $matches)) { - $did = bluesky_get_did($matches[1]); - 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)) { - return; - } - - $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 ?? ''; - $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'] = ''; -} - -function bluesky_item_by_link(array &$hookData) -{ - // Don't overwrite an existing result - if (isset($hookData['item_id'])) { - return; - } - - $token = bluesky_get_token($hookData['uid']); - if (empty($token)) { - return; - } - - if (!preg_match('#^' . BLUESKY_WEB . '/profile/(.+)/post/(.+)#', $hookData['uri'], $matches)) { - return; - } - - $did = bluesky_get_did($matches[1]); - if (empty($did)) { - return; - } - - Logger::debug('Found bluesky post', ['url' => $hookData['uri'], 'handle' => $matches[1], 'did' => $did, 'cid' => $matches[2]]); - - $uri = 'at://' . $did . '/app.bsky.feed.post/' . $matches[2]; - - $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']]); - if (!empty($item['id'])) { - $hookData['item_id'] = $item['id']; - } - } -} - -function bluesky_support_follow(array &$data) -{ - if ($data['protocol'] == Protocol::BLUESKY) { - $data['result'] = true; - } -} - -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']); - if (empty($token)) { - 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)) { - return; - } - - $record = [ - 'subject' => $contact['url'], - 'createdAt' => DateTimeFormat::utcNow(DateTimeFormat::ATOM), - '$type' => 'app.bsky.graph.follow' - ]; - - $post = [ - 'collection' => 'app.bsky.graph.follow', - 'repo' => DI::pConfig()->get($hook_data['uid'], 'bluesky', 'did'), - 'record' => $record - ]; - - $activity = bluesky_xrpc_post($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]); - } -} - -function bluesky_unfollow(array &$hook_data) -{ - $token = bluesky_get_token($hook_data['uid']); - if (empty($token)) { - return; - } - - if ($hook_data['contact']['network'] != Protocol::BLUESKY) { - return; - } - - $data = bluesky_xrpc_get($hook_data['uid'], 'app.bsky.actor.getProfile', ['actor' => $hook_data['contact']['url']]); - if (empty($data->viewer) || empty($data->viewer->following)) { - return; - } - - bluesky_delete_post($data->viewer->following, $hook_data['uid']); - - $hook_data['result'] = true; -} - -function bluesky_block(array &$hook_data) -{ - $token = bluesky_get_token($hook_data['uid']); - if (empty($token)) { - 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)) { - return; - } - - $record = [ - 'subject' => $contact['url'], - 'createdAt' => DateTimeFormat::utcNow(DateTimeFormat::ATOM), - '$type' => 'app.bsky.graph.block' - ]; - - $post = [ - 'collection' => 'app.bsky.graph.block', - 'repo' => DI::pConfig()->get($hook_data['uid'], 'bluesky', 'did'), - 'record' => $record - ]; - - $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']); - } - Logger::debug('Successfully blocked contact', ['url' => $hook_data['contact']['url'], 'uri' => $activity->uri]); - } -} - -function bluesky_unblock(array &$hook_data) -{ - $token = bluesky_get_token($hook_data['uid']); - if (empty($token)) { - return; - } - - if ($hook_data['contact']['network'] != Protocol::BLUESKY) { - return; - } - - $data = bluesky_xrpc_get($hook_data['uid'], 'app.bsky.actor.getProfile', ['actor' => $hook_data['contact']['url']]); - if (empty($data->viewer) || empty($data->viewer->blocking)) { - return; - } - - bluesky_delete_post($data->viewer->blocking, $hook_data['uid']); - - $hook_data['result'] = true; -} - -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; - - $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.')], - '$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.")], - '$status' => bluesky_get_status($handle, $did, $pds, $token), - ]); - - $data = [ - 'connector' => 'bluesky', - 'title' => DI::l10n()->t('Bluesky Import/Export'), - 'image' => 'images/bluesky.jpg', - 'enabled' => $enabled, - 'html' => $html, - ]; -} - -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'])) { - 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'); - - $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'])); - - if (!empty($handle)) { - if (empty($old_did) || $old_handle != $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($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($did) && !empty($pds) && !empty($_POST['bluesky_password'])) { - bluesky_create_token(DI::userSession()->getLocalUserId(), $_POST['bluesky_password']); - } -} - -function bluesky_jot_nets(array &$jotnets_fields) -{ - if (!DI::userSession()->getLocalUserId()) { - return; - } - - if (DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post')) { - $jotnets_fields[] = [ - 'type' => 'checkbox', - 'field' => [ - 'bluesky_enable', - DI::l10n()->t('Post to Bluesky'), - DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default') - ] - ]; - } -} - -function bluesky_cron() -{ - $last = (int)DI::keyValue()->get('bluesky_last_poll'); - - $poll_interval = intval(DI::config()->get('bluesky', 'poll_interval')); - if (!$poll_interval) { - $poll_interval = BLUESKY_DEFAULT_POLL_INTERVAL; - } - - if ($last) { - $next = $last + ($poll_interval * 60); - if ($next > time()) { - Logger::notice('poll interval not reached'); - return; - } - } - Logger::notice('cron_start'); - - $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' => 'bluesky', 'k' => 'import', 'v' => true]); - 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']]); - continue; - } - } - - // 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'], $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, $last); - } - } - } - - $last_clean = DI::keyValue()->get('bluesky_last_clean'); - if (empty($last_clean) || ($last_clean + 86400 < time())) { - 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'); - } - - Logger::notice('cron_end'); - - DI::keyValue()->set('bluesky_last_poll', time()); -} - -function bluesky_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 (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])) { - 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']]); - $b['execute'] = false; - return; - } -} - -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']) { - return; - } - - $bluesky_post = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post')); - $bluesky_enable = (($bluesky_post && !empty($_REQUEST['bluesky_enable'])) ? intval($_REQUEST['bluesky_enable']) : 0); - - // if API is used, default to the chosen settings - if ($b['api_source'] && intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default'))) { - $bluesky_enable = 1; - } - - if (!$bluesky_enable) { - return; - } - - if (strlen($b['postopts'])) { - $b['postopts'] .= ','; - } - - $b['postopts'] .= 'bluesky'; -} - -function bluesky_send(array &$b) -{ - if (($b['created'] !== $b['edited']) && !$b['deleted']) { - return; - } - - if ($b['gravity'] != Item::GRAVITY_PARENT) { - Logger::debug('Got comment', ['item' => $b]); - - if ($b['deleted']) { - $uri = bluesky_get_uri_class($b['uri']); - if (empty($uri)) { - Logger::debug('Not a bluesky post', ['uri' => $b['uri']]); - return; - } - bluesky_delete_post($b['uri'], $b['uid']); - return; - } - - $root = bluesky_get_uri_class($b['parent-uri']); - $parent = bluesky_get_uri_class($b['thr-parent']); - - if (empty($root) || empty($parent)) { - 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]); - bluesky_create_post($b, $root, $parent); - return; - } elseif (in_array($b['verb'], [Activity::LIKE, Activity::ANNOUNCE])) { - bluesky_create_activity($b, $parent); - } - return; - } elseif ($b['private'] || !strstr($b['postopts'], 'bluesky')) { - return; - } - - bluesky_create_post($b); -} - -function bluesky_create_activity(array $item, stdClass $parent = null) -{ - $uid = $item['uid']; - $token = bluesky_get_token($uid); - if (empty($token)) { - return; - } - - $did = DI::pConfig()->get($uid, 'bluesky', 'did'); - - if ($item['verb'] == Activity::LIKE) { - $record = [ - 'subject' => $parent, - 'createdAt' => DateTimeFormat::utcNow(DateTimeFormat::ATOM), - '$type' => 'app.bsky.feed.like' - ]; - - $post = [ - 'collection' => 'app.bsky.feed.like', - 'repo' => $did, - 'record' => $record - ]; - } elseif ($item['verb'] == Activity::ANNOUNCE) { - $record = [ - 'subject' => $parent, - 'createdAt' => DateTimeFormat::utcNow(DateTimeFormat::ATOM), - '$type' => 'app.bsky.feed.repost' - ]; - - $post = [ - 'collection' => 'app.bsky.feed.repost', - 'repo' => $did, - 'record' => $record - ]; - } - - $activity = bluesky_xrpc_post($uid, 'com.atproto.repo.createRecord', $post); - if (empty($activity)) { - return; - } - Logger::debug('Activity done', ['return' => $activity]); - $uri = bluesky_get_uri($activity); - Item::update(['extid' => $uri], ['id' => $item['id']]); - Logger::debug('Set extid', ['id' => $item['id'], 'extid' => $activity]); -} - -function bluesky_create_post(array $item, stdClass $root = null, stdClass $parent = null) -{ - $uid = $item['uid']; - $token = bluesky_get_token($uid); - if (empty($token)) { - 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']; - - $msg = Plaintext::getPost($item, 300, false, BBCode::BLUESKY); - foreach ($msg['parts'] as $key => $part) { - - $facets = bluesky_get_facets($part, $urls['urls']); - - $record = [ - 'text' => $facets['body'], - '$type' => 'app.bsky.feed.post', - 'createdAt' => DateTimeFormat::utcNow(DateTimeFormat::ATOM), - ]; - - if (!empty($language)) { - $record['langs'] = [$language]; - } - - if (!empty($facets['facets'])) { - $record['facets'] = $facets['facets']; - } - - if (!empty($root)) { - $record['reply'] = ['root' => $root, 'parent' => $parent]; - } - - if ($key == count($msg['parts']) - 1) { - $record = bluesky_add_embed($uid, $msg, $record); - if (empty($record)) { - if (Worker::getRetrial() < 3) { - Worker::defer(); - } - return; - } - } - - $post = [ - 'collection' => 'app.bsky.feed.post', - 'repo' => $did, - 'record' => $record - ]; - - $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]); - if (empty($root)) { - $root = $parent; - } - if (($key == 0) && ($item['gravity'] != Item::GRAVITY_PARENT)) { - $uri = bluesky_get_uri($parent); - Item::update(['extid' => $uri], ['id' => $item['id']]); - Logger::debug('Set extid', ['id' => $item['id'], 'extid' => $uri]); - } - } -} - -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 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) { - $text = Strings::getStyledURL($match[1]); - $hash = bluesky_get_hash_for_url($match[0], mb_strlen($text)); - $urls[] = ['url' => $match[1], 'text' => $text, 'hash' => $hash]; - $body = str_replace($match[0], $hash, $body); - } - } - - // Search for links with descriptions - if (preg_match_all("/\[url\=(https?:.*?)\](.*?)\[\/url\]/ism", $body, $matches, PREG_SET_ORDER)) { - foreach ($matches as $match) { - if ($match[1] == $match[2]) { - $text = Strings::getStyledURL($match[1]); - } else { - $text = $match[2]; - } - if (mb_strlen($text) < 100) { - $hash = bluesky_get_hash_for_url($match[0], mb_strlen($text)); - $urls[] = ['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]; - $body = str_replace($match[0], $text . ' ' . $hash, $body); - } - } - } - - return ['body' => $body, 'urls' => $urls]; -} - -function bluesky_get_hash_for_url(string $text, int $linklength): string -{ - if ($linklength <= 10) { - return '|' . hash('crc32', $text) . '|'; - } - return substr('|' . hash('crc32', $text) . base64_encode($text), 0, $linklength - 2) . '|'; -} - -function bluesky_get_facets(string $body, array $urls): array -{ - $facets = []; - - foreach ($urls as $url) { - $pos = strpos($body, $url['hash']); - if ($pos === false) { - continue; - } - if ($pos > 0) { - $prefix = substr($body, 0, $pos); - } else { - $prefix = ''; - } - - $body = $prefix . $url['text'] . substr($body, $pos + strlen($url['hash'])); - - $facet = new stdClass; - $facet->index = new stdClass; - $facet->index->byteEnd = $pos + strlen($url['text']); - $facet->index->byteStart = $pos; - - $feature = new stdClass; - - $type = '$type'; - 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; - } - - return ['facets' => $facets, 'body' => $body]; -} - -function bluesky_add_embed(int $uid, array $msg, array $record): array -{ - if (($msg['type'] != 'link') && !empty($msg['images'])) { - $images = []; - foreach ($msg['images'] as $image) { - 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]; - } - } elseif ($msg['type'] == 'link') { - $record['embed'] = [ - '$type' => 'app.bsky.embed.external', - 'external' => [ - 'uri' => $msg['url'], - 'title' => $msg['title'] ?? '', - 'description' => $msg['description'] ?? '', - ] - ]; - if (!empty($msg['image'])) { - $photo = Photo::createPhotoForExternalResource($msg['image']); - $blob = bluesky_upload_blob($uid, $photo); - if (!empty($blob)) { - $record['embed']['external']['thumb'] = $blob; - } - } - } - return $record; -} - -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, '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; -} - -function bluesky_delete_post(string $uri, int $uid) -{ - $parts = bluesky_get_uri_parts($uri); - if (empty($parts)) { - Logger::debug('No uri delected', ['uri' => $uri]); - return; - } - bluesky_xrpc_post($uid, 'com.atproto.repo.deleteRecord', $parts); - Logger::debug('Deleted', ['parts' => $parts]); -} - -function bluesky_fetch_timeline(int $uid, int $last_poll) -{ - $data = bluesky_xrpc_get($uid, 'app.bsky.feed.getTimeline'); - if (empty($data)) { - return; - } - - if (empty($data->feed)) { - return; - } - - foreach (array_reverse($data->feed) as $entry) { - 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); - } - } - - // @todo Support paging - // [cursor] => 1684670516000::bafyreidq3ilwslmlx72jf5vrk367xcc63s6lrhzlyup2bi3zwcvso6w2vi -} - -function bluesky_process_reason(stdClass $reason, string $uri, int $uid) -{ - $type = '$type'; - if ($reason->$type != 'app.bsky.feed.defs#reasonRepost') { - return; - } - - $contact = bluesky_get_contact($reason->by, $uid, $uid); - - $item = [ - 'network' => Protocol::BLUESKY, - 'uid' => $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'], - 'author-avatar' => $contact['avatar'], - 'verb' => Activity::ANNOUNCE, - 'body' => Activity::ANNOUNCE, - 'gravity' => Item::GRAVITY_ACTIVITY, - 'object-type' => Activity\ObjectType::NOTE, - 'thr-parent' => $uri, - ]; - - if (Post::exists(['uri' => $item['uri'], 'uid' => $uid])) { - return; - } - - $item['guid'] = Item::guidFromUri($item['uri'], $contact['alias']); - $item['owner-name'] = $item['author-name']; - $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]); - } -} - -function bluesky_fetch_notifications(int $uid, int $last_poll) -{ - $data = bluesky_xrpc_get($uid, 'app.bsky.notification.listNotifications'); - if (empty($data->notifications)) { - return; - } - foreach ($data->notifications as $notification) { - $uri = bluesky_get_uri($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; - } - 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['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); - if (!empty($item['thr-parent'])) { - $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]); - } - break; - - case 'repost': - $item = bluesky_get_header($notification, $uri, $uid, $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, $last_poll); - if (!empty($item['thr-parent'])) { - $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]); - } - break; - - case 'follow': - $contact = bluesky_get_contact($notification->author, $uid, $uid); - Logger::debug('New follower', ['uid' => $uid, 'nick' => $contact['nick'], 'uri' => $uri]); - 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]); - 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]); - 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]); - break; - - default: - Logger::notice('Unhandled reason', ['reason' => $notification->reason, 'uri' => $uri]); - break; - } - } -} - -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)) { - return; - } - - if (empty($data->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) { - $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; - } - $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]); - } - } - if (!empty($entry->reason)) { - bluesky_process_reason($entry->reason, bluesky_get_uri($entry->post), $uid); - } - } -} - -function bluesky_process_post(stdClass $post, int $uid, int $post_reason, int $level, int $last_poll): int -{ - $uri = bluesky_get_uri($post); - - 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 ?? '']); - - $item = bluesky_get_header($post, $uri, $uid, $uid); - $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, $last_poll); - } - - if (empty($item['post-reason'])) { - $item['post-reason'] = $post_reason; - } - - return Item::insert($item); -} - -function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_uid): array -{ - $parts = bluesky_get_uri_parts($uri); - if (empty($post->author)) { - return []; - } - $contact = bluesky_get_contact($post->author, $uid, $fetch_uid); - $item = [ - 'network' => Protocol::BLUESKY, - 'uid' => $uid, - 'wall' => false, - 'uri' => $uri, - 'guid' => $post->cid, - '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), - ]; - - $item['uri-id'] = ItemURI::getIdByURI($uri); - $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; - } - - return $item; -} - -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['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['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 ?? []; - - if (($last_poll != 0) && strtotime($item['created']) > $last_poll) { - $item['received'] = $item['created']; - } - - 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.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': - $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); - } - } - if (!empty($shared['uri-id'])) { - $item['quote-uri-id'] = $shared['uri-id']; - } - 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); - } - } - 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); - } - break; - - default: - Logger::notice('Unhandled embed type', ['type' => $embed->$type, 'embed' => $embed]); - break; - } - return $item; -} - -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 $causer, int $level, int $last_poll = 0, string $fallback = ''): string -{ - $fetched_uri = bluesky_fetch_post($uri, $uid); - if (!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); - $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)) { - 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) { - $cdata = Contact::getPublicAndUserContactID($causer, $uid); - } else { - $cdata = []; - } - - return bluesky_process_thread($data->thread, $uid, $fetch_uid, $cdata, $level, $last_poll); -} - -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_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]); - 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]); - $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]); - } else { - Logger::info('Post has not not been fetched', ['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, $cdata, $level, $last_poll); - 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, 'url' => $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, $fetch_uid, $update); - - $public_fields['uid'] = 0; - $public_fields['rel'] = Contact::NOTHING; - - if (empty($contact)) { - $cid = Contact::insert($public_fields); - } else { - $cid = $contact['id']; - Contact::update($public_fields, ['id' => $cid], true); - } - - if ($uid != 0) { - $condition = ['network' => Protocol::BLUESKY, 'uid' => $uid, 'url' => $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']; - 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, bool $update): array -{ - $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/' . $author->handle, - 'name' => $author->displayName ?? $author->handle, - 'nick' => $author->handle, - 'addr' => $author->handle, - ]; - - if (!$update) { - Logger::debug('Got contact fields', ['uid' => $uid, 'url' => $fields['url']]); - 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']]); - 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'; - $preferences = bluesky_get_preferences($uid); - foreach ($preferences->preferences as $preference) { - if ($preference->$type == 'app.bsky.actor.defs#savedFeedsPref') { - return $preference->pinned ?? []; - } - } - return []; -} - -function bluesky_get_preferences(int $uid): stdClass -{ - $cachekey = 'bluesky:preferences:' . $uid; - $data = DI::cache()->get($cachekey); - if (!is_null($data)) { - return $data; - } - - $data = bluesky_xrpc_get($uid, 'app.bsky.actor.getPreferences'); - - DI::cache()->set($cachekey, $data, Duration::HOUR); - return $data; -} - -function bluesky_get_did(string $handle): string -{ - $data = bluesky_get(BLUESKY_PDS . '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle)); - if (empty($data)) { - return ''; - } - Logger::debug('Got DID', ['return' => $data]); - return $data->did; -} - -function bluesky_get_user_pds(int $uid): string -{ - $pds = DI::pConfig()->get($uid, 'bluesky', 'pds'); - if (!empty($pds)) { - return $pds; - } - $did = DI::pConfig()->get($uid, 'bluesky', 'did'); - if (empty($did)) { - Logger::notice('Empty did for user', ['uid' => $uid]); - return ''; - } - $pds = bluesky_get_pds($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'); - $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)) { - 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 = DI::pConfig()->get($uid, 'bluesky', 'did'); - - $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 ''; - } - - 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 -{ - return bluesky_post($uid, '/xrpc/' . $url, json_encode($parameters), ['Content-type' => 'application/json', 'Authorization' => ['Bearer ' . bluesky_get_token($uid)]]); -} - -function bluesky_post(int $uid, string $url, string $params, array $headers): ?stdClass -{ - try { - $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()); -} - -function bluesky_xrpc_get(int $uid, string $url, array $parameters = []): ?stdClass -{ - if (!empty($parameters)) { - $url .= '?' . http_build_query($parameters); - } - - $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 -{ - try { - $curlResult = DI::httpClient()->get($url, $accept_content, $opts); - } catch (\Exception $e) { - Logger::notice('Exception on get', ['exception' => $e]); - return null; - } - - if (!$curlResult->isSuccess()) { - Logger::notice('API Error', ['error' => json_decode($curlResult->getBody()) ?: $curlResult->getBody()]); - return null; - } - - return json_decode($curlResult->getBody()); -} diff --git a/bluesky/bluesky_feed.php b/bluesky/bluesky_feed.php deleted file mode 100644 index c9a54223..00000000 --- a/bluesky/bluesky_feed.php +++ /dev/null @@ -1,16 +0,0 @@ - $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 deleted file mode 100644 index ad35dfe0..00000000 --- a/bluesky/bluesky_notifications.php +++ /dev/null @@ -1,16 +0,0 @@ - $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 deleted file mode 100644 index 22ef2224..00000000 --- a/bluesky/bluesky_timeline.php +++ /dev/null @@ -1,16 +0,0 @@ - $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/bluesky/lang/C/messages.po b/bluesky/lang/C/messages.po deleted file mode 100644 index 132e608a..00000000 --- a/bluesky/lang/C/messages.po +++ /dev/null @@ -1,116 +0,0 @@ -# ADDON bluesky -# Copyright (C) -# This file is distributed under the same license as the Friendica bluesky addon package. -# -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: \n" -"Report-Msgid-Bugs-To: \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" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: bluesky.php:336 -msgid "Enable Bluesky Post Addon" -msgstr "" - -#: bluesky.php:337 -msgid "Post to Bluesky by default" -msgstr "" - -#: bluesky.php:338 -msgid "Import the remote timeline" -msgstr "" - -#: bluesky.php:339 -msgid "Import the pinned feeds" -msgstr "" - -#: bluesky.php:339 -msgid "" -"When activated, Posts will be imported from all the feeds that you pinned in " -"Bluesky." -msgstr "" - -#: bluesky.php:340 -msgid "Personal Data Server" -msgstr "" - -#: bluesky.php:340 -msgid "The personal data server (PDS) is the system that hosts your profile." -msgstr "" - -#: bluesky.php:341 -msgid "Bluesky handle" -msgstr "" - -#: bluesky.php:342 -msgid "Bluesky DID" -msgstr "" - -#: bluesky.php:342 -msgid "" -"This is the unique identifier. It will be fetched automatically, when the " -"handle is entered." -msgstr "" - -#: bluesky.php:343 -msgid "Bluesky app password" -msgstr "" - -#: 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:349 -msgid "Bluesky Import/Export" -msgstr "" - -#: 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 "" diff --git a/bluesky/lang/de/messages.po b/bluesky/lang/de/messages.po deleted file mode 100644 index 13ea8e96..00000000 --- a/bluesky/lang/de/messages.po +++ /dev/null @@ -1,89 +0,0 @@ -# ADDON bluesky -# Copyright (C) -# This file is distributed under the same license as the Friendica bluesky addon package. -# -# -# Translators: -# Tobias Diekershoff , 2023 -# haheute , 2023 -# Raroun, 2023 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: \n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-05-24 05:52+0000\n" -"PO-Revision-Date: 2023-05-24 06:02+0000\n" -"Last-Translator: Raroun, 2023\n" -"Language-Team: German (https://app.transifex.com/Friendica/teams/12172/de/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: de\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: bluesky.php:100 -msgid "" -"You are authenticated to Bluesky. For security reasons the password isn't " -"stored." -msgstr "" -"Du bist auf Bluesky authentifiziert. Aus Sicherheitsgründen wird das " -"Passwort nicht gespeichert." - -#: bluesky.php:100 -msgid "You are not authenticated. Please enter the app password." -msgstr "" -"Du bist derzeit nicht authentifiziert. Bitte gib dein App Passwort ein." - -#: bluesky.php:104 -msgid "Enable Bluesky Post Addon" -msgstr "Bluesky Post Addon aktivieren" - -#: bluesky.php:105 -msgid "Post to Bluesky by default" -msgstr "Standardmäßig auf Bluesky veröffentlichen" - -#: bluesky.php:106 -msgid "Import the remote timeline" -msgstr "Importiere die entfernte Timeline" - -#: bluesky.php:107 -msgid "Bluesky host" -msgstr "Bluesky Host" - -#: bluesky.php:108 -msgid "Bluesky handle" -msgstr "Bluesky Handle" - -#: bluesky.php:109 -msgid "Bluesky DID" -msgstr "Bluesky DID" - -#: bluesky.php:109 -msgid "" -"This is the unique identifier. It will be fetched automatically, when the " -"handle is entered." -msgstr "" -"Sobald das Handle eingegeben ist, wird diese einzigartige Kennung " -"automatisch abgerufen." - -#: bluesky.php:110 -msgid "Bluesky app password" -msgstr "Bluesky App Passwort" - -#: bluesky.php:110 -msgid "" -"Please don't add your real password here, but instead create a specific app " -"password in the Bluesky settings." -msgstr "" -"Bitte verwende hier nicht dein echtes Passwort, sondern stattdessen ein " -"speziell für diese App in den Bluesky Einstellungen festgelegtes Passwort." - -#: bluesky.php:116 -msgid "Bluesky Import/Export" -msgstr "Bluesky Import/Export" - -#: bluesky.php:167 -msgid "Post to Bluesky" -msgstr "Auf Bluesky veröffentlichen" diff --git a/bluesky/lang/de/strings.php b/bluesky/lang/de/strings.php deleted file mode 100644 index 8e3c9421..00000000 --- a/bluesky/lang/de/strings.php +++ /dev/null @@ -1,20 +0,0 @@ -strings['You are authenticated to Bluesky. For security reasons the password isn\'t stored.'] = 'Du bist auf Bluesky authentifiziert. Aus Sicherheitsgründen wird das Passwort nicht gespeichert.'; -$a->strings['You are not authenticated. Please enter the app password.'] = 'Du bist derzeit nicht authentifiziert. Bitte gib dein App Passwort ein.'; -$a->strings['Enable Bluesky Post Addon'] = 'Bluesky Post Addon aktivieren'; -$a->strings['Post to Bluesky by default'] = 'Standardmäßig auf Bluesky veröffentlichen'; -$a->strings['Import the remote timeline'] = 'Importiere die entfernte Timeline'; -$a->strings['Bluesky host'] = 'Bluesky Host'; -$a->strings['Bluesky handle'] = 'Bluesky Handle'; -$a->strings['Bluesky DID'] = 'Bluesky DID'; -$a->strings['This is the unique identifier. It will be fetched automatically, when the handle is entered.'] = 'Sobald das Handle eingegeben ist, wird diese einzigartige Kennung automatisch abgerufen.'; -$a->strings['Bluesky app password'] = 'Bluesky App Passwort'; -$a->strings['Please don\'t add your real password here, but instead create a specific app password in the Bluesky settings.'] = 'Bitte verwende hier nicht dein echtes Passwort, sondern stattdessen ein speziell für diese App in den Bluesky Einstellungen festgelegtes Passwort.'; -$a->strings['Bluesky Import/Export'] = 'Bluesky Import/Export'; -$a->strings['Post to Bluesky'] = 'Auf Bluesky veröffentlichen'; diff --git a/bluesky/lang/zh-cn/messages.po b/bluesky/lang/zh-cn/messages.po deleted file mode 100644 index 9074ce34..00000000 --- a/bluesky/lang/zh-cn/messages.po +++ /dev/null @@ -1,80 +0,0 @@ -# ADDON bluesky -# Copyright (C) -# This file is distributed under the same license as the Friendica bluesky addon package. -# -# -# Translators: -# tslmuun, 2023 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: \n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-05-24 05:52+0000\n" -"PO-Revision-Date: 2023-05-24 06:02+0000\n" -"Last-Translator: tslmuun, 2023\n" -"Language-Team: Chinese (China) (https://app.transifex.com/Friendica/teams/12172/zh_CN/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: zh_CN\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: bluesky.php:100 -msgid "" -"You are authenticated to Bluesky. For security reasons the password isn't " -"stored." -msgstr "您已通过 Bluesky 的身份验证。 出于安全原因,不存储密码。" - -#: bluesky.php:100 -msgid "You are not authenticated. Please enter the app password." -msgstr "您未通过身份验证。 请输入应用密码。" - -#: bluesky.php:104 -msgid "Enable Bluesky Post Addon" -msgstr "启用Bluesky插件" - -#: bluesky.php:105 -msgid "Post to Bluesky by default" -msgstr "默认发布到Bluesky" - -#: bluesky.php:106 -msgid "Import the remote timeline" -msgstr "导入远程时间线" - -#: bluesky.php:107 -msgid "Bluesky host" -msgstr "Bluesky地址" - -#: bluesky.php:108 -msgid "Bluesky handle" -msgstr "Bluesky handle" - -#: bluesky.php:109 -msgid "Bluesky DID" -msgstr "Bluesky DID" - -#: bluesky.php:109 -msgid "" -"This is the unique identifier. It will be fetched automatically, when the " -"handle is entered." -msgstr "这是唯一标识符。 输入句柄时,它将自动获取。" - -#: bluesky.php:110 -msgid "Bluesky app password" -msgstr "Bluesky 应用密码" - -#: bluesky.php:110 -msgid "" -"Please don't add your real password here, but instead create a specific app " -"password in the Bluesky settings." -msgstr "请不要在此处填写您的真实密码,而是在 Bluesky 设置中创建一个特定的应用程序密码。" - -#: bluesky.php:116 -msgid "Bluesky Import/Export" -msgstr "Bluesky 导入/导出" - -#: bluesky.php:167 -msgid "Post to Bluesky" -msgstr "发布到Bluesky" diff --git a/bluesky/lang/zh-cn/strings.php b/bluesky/lang/zh-cn/strings.php deleted file mode 100644 index 9c71d974..00000000 --- a/bluesky/lang/zh-cn/strings.php +++ /dev/null @@ -1,20 +0,0 @@ -strings['You are authenticated to Bluesky. For security reasons the password isn\'t stored.'] = '您已通过 Bluesky 的身份验证。 出于安全原因,不存储密码。'; -$a->strings['You are not authenticated. Please enter the app password.'] = '您未通过身份验证。 请输入应用密码。'; -$a->strings['Enable Bluesky Post Addon'] = '启用Bluesky插件'; -$a->strings['Post to Bluesky by default'] = '默认发布到Bluesky'; -$a->strings['Import the remote timeline'] = '导入远程时间线'; -$a->strings['Bluesky host'] = 'Bluesky地址'; -$a->strings['Bluesky handle'] = 'Bluesky handle'; -$a->strings['Bluesky DID'] = 'Bluesky DID'; -$a->strings['This is the unique identifier. It will be fetched automatically, when the handle is entered.'] = '这是唯一标识符。 输入句柄时,它将自动获取。'; -$a->strings['Bluesky app password'] = 'Bluesky 应用密码'; -$a->strings['Please don\'t add your real password here, but instead create a specific app password in the Bluesky settings.'] = '请不要在此处填写您的真实密码,而是在 Bluesky 设置中创建一个特定的应用程序密码。'; -$a->strings['Bluesky Import/Export'] = 'Bluesky 导入/导出'; -$a->strings['Post to Bluesky'] = '发布到Bluesky'; diff --git a/bluesky/templates/connector_settings.tpl b/bluesky/templates/connector_settings.tpl deleted file mode 100644 index db5ac5d5..00000000 --- a/bluesky/templates/connector_settings.tpl +++ /dev/null @@ -1,9 +0,0 @@ -

{{$status}}

-{{include file="field_checkbox.tpl" field=$enable}} -{{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=$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 diff --git a/buglink/lang/cs/messages.po b/buglink/lang/cs/messages.po index 0e200c14..61dc88cf 100644 --- a/buglink/lang/cs/messages.po +++ b/buglink/lang/cs/messages.po @@ -4,21 +4,21 @@ # # # Translators: -# michal_s , 2014 +# Michal Šupler , 2014 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: 2014-06-22 11:27+0000\n" -"Last-Translator: michal_s , 2014\n" -"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" +"POT-Creation-Date: 2014-06-22 13:18+0200\n" +"PO-Revision-Date: 2014-07-07 18:27+0000\n" +"Last-Translator: Michal Šupler \n" +"Language-Team: Czech (http://www.transifex.com/projects/p/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" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -#: buglink.php:20 +#: buglink.php:15 msgid "Report Bug" msgstr "Nahlásit chybu" diff --git a/buglink/lang/cs/strings.php b/buglink/lang/cs/strings.php index ae45ea37..048b8334 100644 --- a/buglink/lang/cs/strings.php +++ b/buglink/lang/cs/strings.php @@ -3,6 +3,6 @@ if(! function_exists("string_plural_select_cs")) { function string_plural_select_cs($n){ $n = intval($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; } + if (($n==1)) { return 0; } else if (($n>=2 && $n<=4)) { return 1; } else { return 2; } }} $a->strings['Report Bug'] = 'Nahlásit chybu'; diff --git a/buglink/lang/de/messages.po b/buglink/lang/de/messages.po index 4858bc77..0e8d02d5 100644 --- a/buglink/lang/de/messages.po +++ b/buglink/lang/de/messages.po @@ -10,16 +10,16 @@ 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: 2014-06-22 11:27+0000\n" -"Last-Translator: René Wagner , 2019\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"POT-Creation-Date: 2014-06-22 13:18+0200\n" +"PO-Revision-Date: 2019-11-10 20:12+0000\n" +"Last-Translator: René Wagner \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: buglink.php:20 +#: buglink.php:15 msgid "Report Bug" msgstr "Fehler melden" diff --git a/catavatar/catavatar.php b/catavatar/catavatar.php index 2116ac44..69f71ef6 100644 --- a/catavatar/catavatar.php +++ b/catavatar/catavatar.php @@ -70,7 +70,7 @@ function catavatar_addon_settings_post(&$s) } if (!empty($_POST['catavatar-usecat'])) { - $url = DI::baseUrl() . '/catavatar/' . DI::userSession()->getLocalUserId() . '?ts=' . time(); + $url = DI::baseUrl()->get() . '/catavatar/' . DI::userSession()->getLocalUserId() . '?ts=' . time(); $self = DBA::selectFirst('contact', ['id'], ['uid' => DI::userSession()->getLocalUserId(), 'self' => true]); if (!DBA::isResult($self)) { @@ -121,9 +121,9 @@ function catavatar_lookup(array &$b) { $user = DBA::selectFirst('user', ['uid'], ['email' => $b['email']]); if (DBA::isResult($user)) { - $url = DI::baseUrl() . '/catavatar/' . $user['uid']; + $url = DI::baseUrl()->get() . '/catavatar/' . $user['uid']; } else { - $url = DI::baseUrl() . '/catavatar/' . md5(trim(strtolower($b['email']))); + $url = DI::baseUrl()->get() . '/catavatar/' . md5(trim(strtolower($b['email']))); } switch($b['size']) { diff --git a/catavatar/lang/de/messages.po b/catavatar/lang/de/messages.po index f99acaba..d78030ab 100644 --- a/catavatar/lang/de/messages.po +++ b/catavatar/lang/de/messages.po @@ -15,7 +15,7 @@ msgstr "" "POT-Creation-Date: 2021-11-21 19:14-0500\n" "PO-Revision-Date: 2018-04-07 05:23+0000\n" "Last-Translator: Tobias Diekershoff , 2022\n" -"Language-Team: German (https://app.transifex.com/Friendica/teams/12172/de/)\n" +"Language-Team: German (https://www.transifex.com/Friendica/teams/12172/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/catavatar/lang/fr/messages.po b/catavatar/lang/fr/messages.po index 64e98568..f4c4dd0d 100644 --- a/catavatar/lang/fr/messages.po +++ b/catavatar/lang/fr/messages.po @@ -5,7 +5,8 @@ # # Translators: # Vladimir Núñez , 2019 -# Florent C., 2023 +# Walter Bulbazor, 2021 +# Hypolite Petovan , 2022 # #, fuzzy msgid "" @@ -14,8 +15,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: Florent C., 2023\n" -"Language-Team: French (https://app.transifex.com/Friendica/teams/12172/fr/)\n" +"Last-Translator: Hypolite Petovan , 2022\n" +"Language-Team: French (https://www.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" @@ -24,7 +25,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" @@ -32,15 +33,15 @@ msgstr "Paramètres de Chat avatar" #: catavatar.php:56 msgid "Use Cat as Avatar" -msgstr "Utiliser ce Chat" +msgstr "Utiliser Chat comme avatar" #: 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 "Revenir au Chat par défaut" +msgstr "Réinitialiser à Chat courriel" #: 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 b68b9d45..5d8a10a3 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 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['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['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/circle_text/group_text.php b/circle_text/group_text.php deleted file mode 100644 index b52cbc19..00000000 --- a/circle_text/group_text.php +++ /dev/null @@ -1,64 +0,0 @@ - - */ - -use Friendica\Core\Hook; -use Friendica\Core\Renderer; -use Friendica\DI; - -function circle_text_install() -{ - Hook::register('addon_settings', __FILE__, 'circle_text_settings'); - Hook::register('addon_settings_post', __FILE__, 'circle_text_settings_post'); -} - -/** - * - * Callback from the settings post function. - * $post contains the $_POST array. - * We will make sure we've got a valid user account - * and if so set our configuration setting for this person. - * - */ - -function circle_text_settings_post(array $post) -{ - if (!DI::userSession()->getLocalUserId() || empty($post['circle_text-submit'])) { - return; - } - - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'system', 'circle_edit_image_limit', intval($post['circle_text'])); -} - - -/** - * - * Called from the Addon Setting form. - * Add our own settings info to the page. - * - */ - -function circle_text_settings(array &$data) -{ - if (!DI::userSession()->getLocalUserId()) { - return; - } - - $enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'circle_edit_image_limit') ?? - DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'groupedit_image_limit'); - - $t = Renderer::getMarkupTemplate('settings.tpl', 'addon/circle_text/'); - $html = Renderer::replaceMacros($t, [ - '$enabled' => ['circle_text', DI::l10n()->t('Use a text only (non-image) circle selector in the "circle edit" menu'), $enabled], - ]); - - $data = [ - 'addon' => 'circle_text', - 'title' => DI::l10n()->t('Circle Text'), - 'html' => $html, - ]; -} diff --git a/circle_text/lang/C/messages.po b/circle_text/lang/C/messages.po deleted file mode 100644 index 27c0e60e..00000000 --- a/circle_text/lang/C/messages.po +++ /dev/null @@ -1,26 +0,0 @@ -# ADDON circle_text -# Copyright (C) -# This file is distributed under the same license as the Friendica circle_text addon package. -# -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: \n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-06-03 15:48-0400\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" - -#: group_text.php:56 -msgid "Use a text only (non-image) circle selector in the \"circle edit\" menu" -msgstr "" - -#: group_text.php:61 -msgid "Circle Text" -msgstr "" diff --git a/circle_text/lang/ar/messages.po b/circle_text/lang/ar/messages.po deleted file mode 100644 index cfe9bb63..00000000 --- a/circle_text/lang/ar/messages.po +++ /dev/null @@ -1,32 +0,0 @@ -# ADDON group_text -# Copyright (C) -# This file is distributed under the same license as the Friendica group_text addon package. -# -# -# Translators: -# Farida Khalaf , 2021 -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-02-21 02:59+0000\n" -"Last-Translator: Farida Khalaf \n" -"Language-Team: Arabic (http://www.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" - -#: group_text.php:62 -msgid "Group Text" -msgstr "نص المجموعة:" - -#: group_text.php:64 -msgid "Use a text only (non-image) group selector in the \"group edit\" menu" -msgstr "استخدم محدد نصي للمجموعة فقط (غير مصور) في قائمة \"تعديل المجموعة\"" - -#: group_text.php:70 -msgid "Save Settings" -msgstr "حفظ الإعدادات" diff --git a/circle_text/lang/ar/strings.php b/circle_text/lang/ar/strings.php deleted file mode 100644 index 20e8496a..00000000 --- a/circle_text/lang/ar/strings.php +++ /dev/null @@ -1,10 +0,0 @@ -=3 && $n%100<=10) { return 3; } else if ($n%100>=11 && $n%100<=99) { return 4; } else { return 5; } -}} -$a->strings['Group Text'] = 'نص المجموعة:'; -$a->strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'استخدم محدد نصي للمجموعة فقط (غير مصور) في قائمة "تعديل المجموعة"'; -$a->strings['Save Settings'] = 'حفظ الإعدادات'; diff --git a/circle_text/lang/ca/messages.po b/circle_text/lang/ca/messages.po deleted file mode 100644 index 7081c0d7..00000000 --- a/circle_text/lang/ca/messages.po +++ /dev/null @@ -1,36 +0,0 @@ -# ADDON group_text -# Copyright (C) -# This file is distributed under the same license as the Friendica group_text addon package. -# -# -# Translators: -# Joan Bar , 2019 -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: 2019-10-14 00:45+0000\n" -"Last-Translator: Joan Bar \n" -"Language-Team: Catalan (http://www.transifex.com/Friendica/friendica/language/ca/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ca\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: group_text.php:46 -msgid "Group Text settings updated." -msgstr "La configuració del text del grup s'ha actualitzat." - -#: group_text.php:76 -msgid "Group Text" -msgstr "Missatge del grup" - -#: group_text.php:78 -msgid "Use a text only (non-image) group selector in the \"group edit\" menu" -msgstr "Utilitzeu un selector de grup de només text (que no sigui una imatge) al menú 'Edita grup'" - -#: group_text.php:84 -msgid "Submit" -msgstr "sotmetre's" diff --git a/circle_text/lang/ca/strings.php b/circle_text/lang/ca/strings.php deleted file mode 100644 index b28db322..00000000 --- a/circle_text/lang/ca/strings.php +++ /dev/null @@ -1,11 +0,0 @@ -strings['Group Text settings updated.'] = 'La configuració del text del grup s\'ha actualitzat.'; -$a->strings['Group Text'] = 'Missatge del grup'; -$a->strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'Utilitzeu un selector de grup de només text (que no sigui una imatge) al menú \'Edita grup\''; -$a->strings['Submit'] = 'sotmetre\'s'; diff --git a/circle_text/lang/cs/messages.po b/circle_text/lang/cs/messages.po deleted file mode 100644 index 8b56b630..00000000 --- a/circle_text/lang/cs/messages.po +++ /dev/null @@ -1,37 +0,0 @@ -# ADDON group_text -# Copyright (C) -# This file is distributed under the same license as the Friendica group_text addon package. -# -# -# Translators: -# Aditoo, 2018 -# michal_s , 2014-2015 -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-09-12 09:47+0000\n" -"Last-Translator: Aditoo\n" -"Language-Team: Czech (http://www.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" - -#: group_text.php:46 -msgid "Group Text settings updated." -msgstr "Nastavení Group Text aktualizována." - -#: group_text.php:76 -msgid "Group Text" -msgstr "Skupinový text" - -#: group_text.php:78 -msgid "Use a text only (non-image) group selector in the \"group edit\" menu" -msgstr "Použijte pouze textový (bezobrázkový) výběr skupiny v menu úpravy skupin." - -#: group_text.php:84 -msgid "Submit" -msgstr "Odeslat" diff --git a/circle_text/lang/cs/strings.php b/circle_text/lang/cs/strings.php deleted file mode 100644 index 510453af..00000000 --- a/circle_text/lang/cs/strings.php +++ /dev/null @@ -1,11 +0,0 @@ -= 2 && $n <= 4 && $n % 1 == 0)) { return 1; } else if (($n % 1 != 0 )) { return 2; } else { return 3; } -}} -$a->strings['Group Text settings updated.'] = 'Nastavení Group Text aktualizována.'; -$a->strings['Group Text'] = 'Skupinový text'; -$a->strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'Použijte pouze textový (bezobrázkový) výběr skupiny v menu úpravy skupin.'; -$a->strings['Submit'] = 'Odeslat'; diff --git a/circle_text/lang/da-dk/messages.po b/circle_text/lang/da-dk/messages.po deleted file mode 100644 index 9f1fbefa..00000000 --- a/circle_text/lang/da-dk/messages.po +++ /dev/null @@ -1,28 +0,0 @@ -# ADDON group_text -# Copyright (C) -# This file is distributed under the same license as the Friendica group_text addon package. -# -# -# Translators: -# Anton , 2022 -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: 2014-06-23 08:35+0000\n" -"Last-Translator: Anton , 2022\n" -"Language-Team: Danish (Denmark) (http://www.transifex.com/Friendica/friendica/language/da_DK/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: da_DK\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: group_text.php:58 -msgid "Use a text only (non-image) group selector in the \"group edit\" menu" -msgstr "Brug en kun-tekst (intet billede) gruppevælger i grupperedigeringsmenuen" - -#: group_text.php:63 -msgid "Group Text" -msgstr "Gruppebesked" diff --git a/circle_text/lang/da-dk/strings.php b/circle_text/lang/da-dk/strings.php deleted file mode 100644 index 4306b769..00000000 --- a/circle_text/lang/da-dk/strings.php +++ /dev/null @@ -1,9 +0,0 @@ -strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'Brug en kun-tekst (intet billede) gruppevælger i grupperedigeringsmenuen'; -$a->strings['Group Text'] = 'Gruppebesked'; diff --git a/circle_text/lang/de/messages.po b/circle_text/lang/de/messages.po deleted file mode 100644 index e4e5d782..00000000 --- a/circle_text/lang/de/messages.po +++ /dev/null @@ -1,31 +0,0 @@ -# ADDON group_text -# Copyright (C) -# This file is distributed under the same license as the Friendica group_text addon package. -# -# -# Translators: -# Andreas H., 2014 -# Tobias Diekershoff , 2014 -# Tobias Diekershoff , 2021 -# Ulf Rompe , 2019 -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: 2014-06-23 08:35+0000\n" -"Last-Translator: Tobias Diekershoff , 2021\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" -"Content-Transfer-Encoding: 8bit\n" -"Language: de\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: group_text.php:58 -msgid "Use a text only (non-image) group selector in the \"group edit\" menu" -msgstr "Beim Bearbeiten von Gruppen Text statt Bilder anzeigen" - -#: group_text.php:63 -msgid "Group Text" -msgstr "Gruppen als Text" diff --git a/circle_text/lang/de/strings.php b/circle_text/lang/de/strings.php deleted file mode 100644 index 7a75b54d..00000000 --- a/circle_text/lang/de/strings.php +++ /dev/null @@ -1,9 +0,0 @@ -strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'Beim Bearbeiten von Gruppen Text statt Bilder anzeigen'; -$a->strings['Group Text'] = 'Gruppen als Text'; diff --git a/circle_text/lang/eo/strings.php b/circle_text/lang/eo/strings.php deleted file mode 100644 index 4e220fb0..00000000 --- a/circle_text/lang/eo/strings.php +++ /dev/null @@ -1,5 +0,0 @@ -strings["Group Text"] = ""; -$a->strings["Use a text only (non-image) group selector in the \"group edit\" menu"] = ""; -$a->strings["Submit"] = "Sendi"; diff --git a/circle_text/lang/es/messages.po b/circle_text/lang/es/messages.po deleted file mode 100644 index 5d6d4107..00000000 --- a/circle_text/lang/es/messages.po +++ /dev/null @@ -1,33 +0,0 @@ -# ADDON group_text -# Copyright (C) -# This file is distributed under the same license as the Friendica group_text addon package. -# -# -# Translators: -# Albert, 2016 -# Senex Petrovic , 2021 -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-01 09:56+0000\n" -"Last-Translator: Senex Petrovic \n" -"Language-Team: Spanish (http://www.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" - -#: group_text.php:62 -msgid "Group Text" -msgstr "Grupo de Texto" - -#: group_text.php:64 -msgid "Use a text only (non-image) group selector in the \"group edit\" menu" -msgstr "Utilice sólo el selector de grupo de texto (no imagen) en el menú \"edición de grupo\"" - -#: group_text.php:70 -msgid "Save Settings" -msgstr "Guardar Ajustes" diff --git a/circle_text/lang/es/strings.php b/circle_text/lang/es/strings.php deleted file mode 100644 index 632130fd..00000000 --- a/circle_text/lang/es/strings.php +++ /dev/null @@ -1,10 +0,0 @@ -strings['Group Text'] = 'Grupo de Texto'; -$a->strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'Utilice sólo el selector de grupo de texto (no imagen) en el menú "edición de grupo"'; -$a->strings['Save Settings'] = 'Guardar Ajustes'; diff --git a/circle_text/lang/fi-fi/messages.po b/circle_text/lang/fi-fi/messages.po deleted file mode 100644 index 2e3782fd..00000000 --- a/circle_text/lang/fi-fi/messages.po +++ /dev/null @@ -1,37 +0,0 @@ -# ADDON group_text -# Copyright (C) -# This file is distributed under the same license as the Friendica group_text addon package. -# -# -# Translators: -# Kris, 2018 -# Kris, 2018 -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-04-08 15:51+0000\n" -"Last-Translator: Kris\n" -"Language-Team: Finnish (Finland) (http://www.transifex.com/Friendica/friendica/language/fi_FI/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: fi_FI\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: group_text.php:46 -msgid "Group Text settings updated." -msgstr "Group Text -asetukset päivitetty." - -#: group_text.php:76 -msgid "Group Text" -msgstr "Group Text" - -#: group_text.php:78 -msgid "Use a text only (non-image) group selector in the \"group edit\" menu" -msgstr "" - -#: group_text.php:84 -msgid "Submit" -msgstr "Lähetä" diff --git a/circle_text/lang/fi-fi/strings.php b/circle_text/lang/fi-fi/strings.php deleted file mode 100644 index 5bcd0ddc..00000000 --- a/circle_text/lang/fi-fi/strings.php +++ /dev/null @@ -1,10 +0,0 @@ -strings['Group Text settings updated.'] = 'Group Text -asetukset päivitetty.'; -$a->strings['Group Text'] = 'Group Text'; -$a->strings['Submit'] = 'Lähetä'; diff --git a/circle_text/lang/fr/messages.po b/circle_text/lang/fr/messages.po deleted file mode 100644 index c076d697..00000000 --- a/circle_text/lang/fr/messages.po +++ /dev/null @@ -1,29 +0,0 @@ -# ADDON group_text -# Copyright (C) -# This file is distributed under the same license as the Friendica group_text addon package. -# -# -# Translators: -# bob lebonche , 2021 -# Hypolite Petovan , 2016 -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: 2014-06-23 08:35+0000\n" -"Last-Translator: bob lebonche , 2021\n" -"Language-Team: French (http://www.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" - -#: group_text.php:58 -msgid "Use a text only (non-image) group selector in the \"group edit\" menu" -msgstr "Utiliser uniquement un groupe de texte (pas d'image) dans le menu \"groupedit\"" - -#: group_text.php:63 -msgid "Group Text" -msgstr "Groupe de texte" diff --git a/circle_text/lang/fr/strings.php b/circle_text/lang/fr/strings.php deleted file mode 100644 index 657d7657..00000000 --- a/circle_text/lang/fr/strings.php +++ /dev/null @@ -1,9 +0,0 @@ -strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'Utiliser uniquement un groupe de texte (pas d\'image) dans le menu "groupedit"'; -$a->strings['Group Text'] = 'Groupe de texte'; diff --git a/circle_text/lang/hu/messages.po b/circle_text/lang/hu/messages.po deleted file mode 100644 index 2c4f19c9..00000000 --- a/circle_text/lang/hu/messages.po +++ /dev/null @@ -1,28 +0,0 @@ -# ADDON group_text -# Copyright (C) -# This file is distributed under the same license as the Friendica group_text addon package. -# -# -# Translators: -# Balázs Úr, 2020-2021 -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: 2014-06-23 08:35+0000\n" -"Last-Translator: Balázs Úr, 2020-2021\n" -"Language-Team: Hungarian (http://www.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" - -#: group_text.php:58 -msgid "Use a text only (non-image) group selector in the \"group edit\" menu" -msgstr "Csak szöveges (kép nélküli) csoportválasztó használata a „csoportszerkesztés” menüben" - -#: group_text.php:63 -msgid "Group Text" -msgstr "Csoportszöveg" diff --git a/circle_text/lang/hu/strings.php b/circle_text/lang/hu/strings.php deleted file mode 100644 index ac72f9e0..00000000 --- a/circle_text/lang/hu/strings.php +++ /dev/null @@ -1,9 +0,0 @@ -strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'Csak szöveges (kép nélküli) csoportválasztó használata a „csoportszerkesztés” menüben'; -$a->strings['Group Text'] = 'Csoportszöveg'; diff --git a/circle_text/lang/is/strings.php b/circle_text/lang/is/strings.php deleted file mode 100644 index d331b2f9..00000000 --- a/circle_text/lang/is/strings.php +++ /dev/null @@ -1,5 +0,0 @@ -strings["Group Text"] = ""; -$a->strings["Use a text only (non-image) group selector in the \"group edit\" menu"] = ""; -$a->strings["Submit"] = "Senda inn"; diff --git a/circle_text/lang/it/messages.po b/circle_text/lang/it/messages.po deleted file mode 100644 index daab3fb6..00000000 --- a/circle_text/lang/it/messages.po +++ /dev/null @@ -1,33 +0,0 @@ -# ADDON group_text -# Copyright (C) -# This file is distributed under the same license as the Friendica group_text addon package. -# -# -# Translators: -# fabrixxm , 2014-2015 -# Sylke Vicious , 2021 -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-02-16 12:48+0000\n" -"Last-Translator: Sylke Vicious \n" -"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: it\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: group_text.php:62 -msgid "Group Text" -msgstr "Editor Gruppi Testuale" - -#: group_text.php:64 -msgid "Use a text only (non-image) group selector in the \"group edit\" menu" -msgstr "Usa un selettore testuale (senza immagini) nella pagina \"modifica gruppo\"" - -#: group_text.php:70 -msgid "Save Settings" -msgstr "Salva Impostazioni" diff --git a/circle_text/lang/it/strings.php b/circle_text/lang/it/strings.php deleted file mode 100644 index e52683e9..00000000 --- a/circle_text/lang/it/strings.php +++ /dev/null @@ -1,10 +0,0 @@ -strings['Group Text'] = 'Editor Gruppi Testuale'; -$a->strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'Usa un selettore testuale (senza immagini) nella pagina "modifica gruppo"'; -$a->strings['Save Settings'] = 'Salva Impostazioni'; diff --git a/circle_text/lang/nb-no/strings.php b/circle_text/lang/nb-no/strings.php deleted file mode 100644 index cd9bebd4..00000000 --- a/circle_text/lang/nb-no/strings.php +++ /dev/null @@ -1,5 +0,0 @@ -strings["Group Text"] = ""; -$a->strings["Use a text only (non-image) group selector in the \"group edit\" menu"] = ""; -$a->strings["Submit"] = "Lagre"; diff --git a/circle_text/lang/nl/messages.po b/circle_text/lang/nl/messages.po deleted file mode 100644 index 56b5aae0..00000000 --- a/circle_text/lang/nl/messages.po +++ /dev/null @@ -1,36 +0,0 @@ -# ADDON group_text -# Copyright (C) -# This file is distributed under the same license as the Friendica group_text addon package. -# -# -# Translators: -# Jeroen De Meerleer , 2018 -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:48+0000\n" -"Last-Translator: Jeroen De Meerleer \n" -"Language-Team: Dutch (http://www.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" - -#: group_text.php:46 -msgid "Group Text settings updated." -msgstr "Groupsberichten instellingen opgeslagen" - -#: group_text.php:76 -msgid "Group Text" -msgstr "Groepsbericht" - -#: group_text.php:78 -msgid "Use a text only (non-image) group selector in the \"group edit\" menu" -msgstr "" - -#: group_text.php:84 -msgid "Submit" -msgstr "" diff --git a/circle_text/lang/nl/strings.php b/circle_text/lang/nl/strings.php deleted file mode 100644 index ba3cb3ec..00000000 --- a/circle_text/lang/nl/strings.php +++ /dev/null @@ -1,9 +0,0 @@ -strings['Group Text settings updated.'] = 'Groupsberichten instellingen opgeslagen'; -$a->strings['Group Text'] = 'Groepsbericht'; diff --git a/circle_text/lang/pl/messages.po b/circle_text/lang/pl/messages.po deleted file mode 100644 index a1d6a3c8..00000000 --- a/circle_text/lang/pl/messages.po +++ /dev/null @@ -1,28 +0,0 @@ -# ADDON group_text -# Copyright (C) -# This file is distributed under the same license as the Friendica group_text addon package. -# -# -# Translators: -# Waldemar Stoczkowski, 2018 -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: 2014-06-23 08:35+0000\n" -"Last-Translator: Waldemar Stoczkowski, 2018\n" -"Language-Team: Polish (http://www.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" - -#: group_text.php:58 -msgid "Use a text only (non-image) group selector in the \"group edit\" menu" -msgstr "Użyj tylko tekst (bez obrazu) selektor grupy w menu \"Edycja grupy\"" - -#: group_text.php:63 -msgid "Group Text" -msgstr "Grupuj tekst" diff --git a/circle_text/lang/pl/strings.php b/circle_text/lang/pl/strings.php deleted file mode 100644 index 96157c99..00000000 --- a/circle_text/lang/pl/strings.php +++ /dev/null @@ -1,9 +0,0 @@ -=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['Use a text only (non-image) group selector in the "group edit" menu'] = 'Użyj tylko tekst (bez obrazu) selektor grupy w menu "Edycja grupy"'; -$a->strings['Group Text'] = 'Grupuj tekst'; diff --git a/circle_text/lang/pt-br/strings.php b/circle_text/lang/pt-br/strings.php deleted file mode 100644 index 4579a5b1..00000000 --- a/circle_text/lang/pt-br/strings.php +++ /dev/null @@ -1,5 +0,0 @@ -strings["Group Text"] = ""; -$a->strings["Use a text only (non-image) group selector in the \"group edit\" menu"] = ""; -$a->strings["Submit"] = "Enviar"; diff --git a/circle_text/lang/ro/messages.po b/circle_text/lang/ro/messages.po deleted file mode 100644 index c912f113..00000000 --- a/circle_text/lang/ro/messages.po +++ /dev/null @@ -1,36 +0,0 @@ -# ADDON group_text -# Copyright (C) -# This file is distributed under the same license as the Friendica group_text addon package. -# -# -# Translators: -# Doru DEACONU , 2014 -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: 2014-11-27 14:15+0000\n" -"Last-Translator: Doru DEACONU \n" -"Language-Team: Romanian (Romania) (http://www.transifex.com/projects/p/friendica/language/ro_RO/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ro_RO\n" -"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n" - -#: group_text.php:46 -msgid "Group Text settings updated." -msgstr "Configurările Text Grup, au fost actualizate." - -#: group_text.php:76 -msgid "Group Text" -msgstr "Text Grup" - -#: group_text.php:78 -msgid "Use a text only (non-image) group selector in the \"group edit\" menu" -msgstr "Folosiți în meniul \"editare grup\" un selector de grup strict textual (fără-imagine)" - -#: group_text.php:84 -msgid "Submit" -msgstr "Trimite" diff --git a/circle_text/lang/ro/strings.php b/circle_text/lang/ro/strings.php deleted file mode 100644 index 892ffc68..00000000 --- a/circle_text/lang/ro/strings.php +++ /dev/null @@ -1,11 +0,0 @@ -19)||(($n%100==0)&&($n!=0)))) { return 2; } else { return 1; } -}} -$a->strings['Group Text settings updated.'] = 'Configurările Text Grup, au fost actualizate.'; -$a->strings['Group Text'] = 'Text Grup'; -$a->strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'Folosiți în meniul "editare grup" un selector de grup strict textual (fără-imagine)'; -$a->strings['Submit'] = 'Trimite'; diff --git a/circle_text/lang/ru/messages.po b/circle_text/lang/ru/messages.po deleted file mode 100644 index 05a25367..00000000 --- a/circle_text/lang/ru/messages.po +++ /dev/null @@ -1,36 +0,0 @@ -# ADDON group_text -# Copyright (C) -# This file is distributed under the same license as the Friendica group_text addon package. -# -# -# Translators: -# Stanislav N. , 2017 -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 17:26+0000\n" -"Last-Translator: Stanislav N. \n" -"Language-Team: Russian (http://www.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" - -#: group_text.php:46 -msgid "Group Text settings updated." -msgstr "Настройки Group Text обновлены." - -#: group_text.php:76 -msgid "Group Text" -msgstr "Group Text" - -#: group_text.php:78 -msgid "Use a text only (non-image) group selector in the \"group edit\" menu" -msgstr "Используйте текстовый (не изображение) селектор группы в режиме редактирования группы" - -#: group_text.php:84 -msgid "Submit" -msgstr "Добавить" diff --git a/circle_text/lang/ru/strings.php b/circle_text/lang/ru/strings.php deleted file mode 100644 index 0f74e7ca..00000000 --- a/circle_text/lang/ru/strings.php +++ /dev/null @@ -1,11 +0,0 @@ -=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['Group Text settings updated.'] = 'Настройки Group Text обновлены.'; -$a->strings['Group Text'] = 'Group Text'; -$a->strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'Используйте текстовый (не изображение) селектор группы в режиме редактирования группы'; -$a->strings['Submit'] = 'Добавить'; diff --git a/circle_text/lang/sv/messages.po b/circle_text/lang/sv/messages.po deleted file mode 100644 index 8ddc1806..00000000 --- a/circle_text/lang/sv/messages.po +++ /dev/null @@ -1,28 +0,0 @@ -# ADDON group_text -# Copyright (C) -# This file is distributed under the same license as the Friendica group_text addon package. -# -# -# Translators: -# Kristoffer Grundström , 2022 -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: 2022-01-16 00:35+0000\n" -"Last-Translator: Kristoffer Grundström \n" -"Language-Team: Swedish (http://www.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" - -#: group_text.php:58 -msgid "Use a text only (non-image) group selector in the \"group edit\" menu" -msgstr "" - -#: group_text.php:63 -msgid "Group Text" -msgstr "Grupptext" diff --git a/circle_text/lang/sv/strings.php b/circle_text/lang/sv/strings.php deleted file mode 100644 index 5d5e98db..00000000 --- a/circle_text/lang/sv/strings.php +++ /dev/null @@ -1,8 +0,0 @@ -strings['Group Text'] = 'Grupptext'; diff --git a/circle_text/lang/zh-cn/strings.php b/circle_text/lang/zh-cn/strings.php deleted file mode 100644 index a7b37bf2..00000000 --- a/circle_text/lang/zh-cn/strings.php +++ /dev/null @@ -1,6 +0,0 @@ -strings["Group Text settings updated."] = "组正文设置更新了。"; -$a->strings["Group Text"] = "组正文"; -$a->strings["Use a text only (non-image) group selector in the \"group edit\" menu"] = "用光正文(无图片)组选择器在「组编辑」单"; -$a->strings["Submit"] = "提交"; diff --git a/circle_text/templates/settings.tpl b/circle_text/templates/settings.tpl deleted file mode 100644 index 2f3f4ce7..00000000 --- a/circle_text/templates/settings.tpl +++ /dev/null @@ -1 +0,0 @@ -{{include file="field_checkbox.tpl" field=$enabled}} diff --git a/cld/README.md b/cld/README.md deleted file mode 100644 index 933dbcee..00000000 --- a/cld/README.md +++ /dev/null @@ -1,85 +0,0 @@ -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.2 on Debian it is: -``` -cd /etc/php/8.2/mods-available -``` - -Create the file `cld2.ini` with this content: -``` -; configuration for php cld2 module -; priority=20 -extension=cld2.so -``` - -Enable the module for all versions and all sapi: -``` -phpenmod -v ALL -s ALL cld2 -``` - -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 deleted file mode 100644 index 5ca4c932..00000000 --- a/cld/cld.php +++ /dev/null @@ -1,71 +0,0 @@ - - */ - -use Friendica\Core\Hook; -use Friendica\Core\Logger; -use Friendica\DI; - -function cld_install() -{ - Hook::register('detect_languages', __FILE__, 'cld_detect_languages'); -} - -function cld_detect_languages(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 - $cld2->setPlainText(true); - - $result = $cld2->detect($data['text']); - - if ($data['detected']) { - $original = array_key_first($data['detected']); - } else { - $original = ''; - } - - $detected = DI::l10n()->toISO6391($result['language_code']); - - // 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; - } - - 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']]); - if (($original == $detected) && ($data['detected'][$original] < $result['language_probability'] / 100)) { - $data['detected'][$original] = $result['language_probability'] / 100; - } - return; - } - - $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; - } - - 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]; - } -} diff --git a/cookienotice/lang/de/messages.po b/cookienotice/lang/de/messages.po index ec07534e..db31eea7 100644 --- a/cookienotice/lang/de/messages.po +++ b/cookienotice/lang/de/messages.po @@ -6,7 +6,7 @@ # Translators: # Tobias Diekershoff , 2019 # Ulf Rompe , 2019 -# foss , 2020 +# foss , 2020 # #, fuzzy msgid "" @@ -15,8 +15,8 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-02-01 18:15+0100\n" "PO-Revision-Date: 2019-01-23 16:01+0000\n" -"Last-Translator: foss , 2020\n" -"Language-Team: German (https://app.transifex.com/Friendica/teams/12172/de/)\n" +"Last-Translator: foss , 2020\n" +"Language-Team: German (https://www.transifex.com/Friendica/teams/12172/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/curweather/curweather.php b/curweather/curweather.php index f614840a..6b6c53cc 100644 --- a/curweather/curweather.php +++ b/curweather/curweather.php @@ -92,7 +92,7 @@ function curweather_network_mod_init(string &$body) return; } - DI::page()['htmlhead'] .= '' . "\r\n"; + DI::page()['htmlhead'] .= '' . "\r\n"; // $rpt value is needed for location // $lang will be taken from the browser session to honour user settings diff --git a/curweather/lang/cs/messages.po b/curweather/lang/cs/messages.po index eddde113..389550eb 100644 --- a/curweather/lang/cs/messages.po +++ b/curweather/lang/cs/messages.po @@ -11,116 +11,124 @@ 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: 2014-06-22 11:34+0000\n" -"Last-Translator: Aditoo, 2018\n" -"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" +"POT-Creation-Date: 2016-09-25 17:17+0200\n" +"PO-Revision-Date: 2018-07-05 17:03+0000\n" +"Last-Translator: Aditoo\n" +"Language-Team: Czech (http://www.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" -#: curweather.php:47 -msgid "Error fetching weather data. Error was: " -msgstr "" +#: curweather.php:31 +msgid "Error fetching weather data.\\nError was: " +msgstr "Chyba při získávání dat o počasí.\\nChyba:" -#: curweather.php:130 +#: curweather.php:111 curweather.php:172 msgid "Current Weather" msgstr "Aktuální počasí" -#: curweather.php:137 +#: curweather.php:118 msgid "Relative Humidity" msgstr "Relativní vlhkost vzduchu" -#: curweather.php:138 +#: curweather.php:119 msgid "Pressure" msgstr "Tlak" -#: curweather.php:139 +#: curweather.php:120 msgid "Wind" msgstr "Vítr" -#: curweather.php:140 +#: curweather.php:121 msgid "Last Updated" msgstr "Naposledy aktualizováno" -#: curweather.php:141 +#: curweather.php:122 msgid "Data by" msgstr "Data podle" -#: curweather.php:142 +#: curweather.php:123 msgid "Show on map" msgstr "Ukázat na mapě" -#: curweather.php:147 +#: curweather.php:128 msgid "There was a problem accessing the weather data. But have a look" msgstr "Při získávání dat o počasí nastala chyba. Podívejte se ale" -#: curweather.php:149 +#: curweather.php:130 msgid "at OpenWeatherMap" msgstr "na OpenWeatherMap" -#: curweather.php:178 +#: curweather.php:146 +msgid "Current Weather settings updated." +msgstr "Nastavení pro Aktuální počasí aktualizováno." + +#: curweather.php:161 msgid "No APPID found, please contact your admin to obtain one." msgstr "Žádné APPID nebylo nalezeno, prosím kontaktujte svého administrátora pro získání APPID." -#: curweather.php:188 +#: curweather.php:171 curweather.php:200 +msgid "Save Settings" +msgstr "Uložit nastavení" + +#: curweather.php:172 +msgid "Settings" +msgstr "Nastavení" + +#: curweather.php:174 msgid "Enter either the name of your location or the zip code." msgstr "Zadejte buď název místa, kde se nacházíte, nebo PSČ." -#: curweather.php:189 +#: curweather.php:175 msgid "Your Location" msgstr "Vaše poloha" -#: curweather.php:189 +#: curweather.php:175 msgid "" "Identifier of your location (name or zip code), e.g. Berlin,DE or " "14476,DE." msgstr "Identifikátor vaší polohy (název nebo PSČ), např. Praha,CZ nebo 11000,CZ." -#: curweather.php:190 +#: curweather.php:176 msgid "Units" msgstr "Jednotky" -#: curweather.php:190 +#: curweather.php:176 msgid "select if the temperature should be displayed in °C or °F" msgstr "vyberte, jestli by se teplota měla zobrazovat v °C či °F" -#: curweather.php:191 +#: curweather.php:177 msgid "Show weather data" msgstr "Ukázat data o počasí" -#: curweather.php:196 -msgid "Current Weather Settings" -msgstr "" +#: curweather.php:190 +msgid "Curweather settings saved." +msgstr "Nastavení Curwather uložena." -#: curweather.php:227 -msgid "Save Settings" -msgstr "Uložit nastavení" - -#: curweather.php:230 +#: curweather.php:201 msgid "Caching Interval" -msgstr "Interval mezipaměti" +msgstr "Ukládám interval do mezipaměti" -#: curweather.php:232 +#: curweather.php:201 msgid "" "For how long should the weather data be cached? Choose according your " "OpenWeatherMap account type." msgstr "Na jak dlouho by vaše data o počasí měla být uložena v mezipaměti? Vyberte podle typu vašeho účtu na OpenWeatherMap." -#: curweather.php:233 +#: curweather.php:201 msgid "no cache" msgstr "žádná mezipaměť" -#: curweather.php:234 curweather.php:235 curweather.php:236 curweather.php:237 +#: curweather.php:201 msgid "minutes" msgstr "minut" -#: curweather.php:240 +#: curweather.php:202 msgid "Your APPID" msgstr "Vaše APPID" -#: curweather.php:240 +#: curweather.php:202 msgid "Your API key provided by OpenWeatherMap" msgstr "Váš API klíč poskytnutý OpenWetherMap" diff --git a/curweather/lang/cs/strings.php b/curweather/lang/cs/strings.php index 78baa8a7..33529d83 100644 --- a/curweather/lang/cs/strings.php +++ b/curweather/lang/cs/strings.php @@ -5,6 +5,7 @@ function string_plural_select_cs($n){ $n = intval($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['Error fetching weather data.\nError was: '] = 'Chyba při získávání dat o počasí.\nChyba:'; $a->strings['Current Weather'] = 'Aktuální počasí'; $a->strings['Relative Humidity'] = 'Relativní vlhkost vzduchu'; $a->strings['Pressure'] = 'Tlak'; @@ -14,15 +15,18 @@ $a->strings['Data by'] = 'Data podle'; $a->strings['Show on map'] = 'Ukázat na mapě'; $a->strings['There was a problem accessing the weather data. But have a look'] = 'Při získávání dat o počasí nastala chyba. Podívejte se ale'; $a->strings['at OpenWeatherMap'] = 'na OpenWeatherMap'; +$a->strings['Current Weather settings updated.'] = 'Nastavení pro Aktuální počasí aktualizováno.'; $a->strings['No APPID found, please contact your admin to obtain one.'] = 'Žádné APPID nebylo nalezeno, prosím kontaktujte svého administrátora pro získání APPID.'; +$a->strings['Save Settings'] = 'Uložit nastavení'; +$a->strings['Settings'] = 'Nastavení'; $a->strings['Enter either the name of your location or the zip code.'] = 'Zadejte buď název místa, kde se nacházíte, nebo PSČ.'; $a->strings['Your Location'] = 'Vaše poloha'; $a->strings['Identifier of your location (name or zip code), e.g. Berlin,DE or 14476,DE.'] = 'Identifikátor vaší polohy (název nebo PSČ), např. Praha,CZ nebo 11000,CZ.'; $a->strings['Units'] = 'Jednotky'; $a->strings['select if the temperature should be displayed in °C or °F'] = 'vyberte, jestli by se teplota měla zobrazovat v °C či °F'; $a->strings['Show weather data'] = 'Ukázat data o počasí'; -$a->strings['Save Settings'] = 'Uložit nastavení'; -$a->strings['Caching Interval'] = 'Interval mezipaměti'; +$a->strings['Curweather settings saved.'] = 'Nastavení Curwather uložena.'; +$a->strings['Caching Interval'] = 'Ukládám interval do mezipaměti'; $a->strings['For how long should the weather data be cached? Choose according your OpenWeatherMap account type.'] = 'Na jak dlouho by vaše data o počasí měla být uložena v mezipaměti? Vyberte podle typu vašeho účtu na OpenWeatherMap.'; $a->strings['no cache'] = 'žádná mezipaměť'; $a->strings['minutes'] = 'minut'; diff --git a/curweather/lang/de/messages.po b/curweather/lang/de/messages.po index 15557ba5..cf6500fc 100644 --- a/curweather/lang/de/messages.po +++ b/curweather/lang/de/messages.po @@ -15,9 +15,9 @@ msgstr "" "Project-Id-Version: friendica\n" "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: Tobias Diekershoff , 2016,2021-2022\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2022-01-22 17:28+0000\n" +"Last-Translator: Tobias Diekershoff \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/diaspora/diaspora.php b/diaspora/diaspora.php index cb2eb996..2e1b3607 100644 --- a/diaspora/diaspora.php +++ b/diaspora/diaspora.php @@ -186,7 +186,7 @@ function diaspora_post_local(array &$b) function diaspora_send(array &$b) { - $hostname = DI::baseUrl()->getHost(); + $hostname = DI::baseUrl()->getHostname(); Logger::notice('diaspora_send: invoked'); @@ -205,7 +205,7 @@ function diaspora_send(array &$b) $b['body'] = Post\Media::addAttachmentsToBody($b['uri-id'], DI::contentItem()->addSharedPost($b)); // Dont't post if the post doesn't belong to us. - // This is a check for group postings + // This is a check for forum postings $self = DBA::selectFirst('contact', ['id'], ['uid' => $b['uid'], 'self' => true]); if ($b['contact-id'] != $self['id']) { diff --git a/diaspora/lang/C/messages.po b/diaspora/lang/C/messages.po index b9944720..262e4cd8 100644 --- a/diaspora/lang/C/messages.po +++ b/diaspora/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:48-0400\n" +"POT-Creation-Date: 2021-11-21 19:17-0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,84 +17,84 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: diaspora.php:43 +#: diaspora.php:44 msgid "Post to Diaspora" msgstr "" -#: diaspora.php:66 +#: diaspora.php:67 #, php-format msgid "" "Please remember: You can always be reached from Diaspora with your Friendica " "handle %s. " msgstr "" -#: diaspora.php:67 +#: diaspora.php:68 msgid "" "This connector is only meant if you still want to use your old Diaspora " "account for some time. " msgstr "" -#: diaspora.php:68 +#: diaspora.php:69 #, php-format msgid "" "However, it is preferred that you tell your Diaspora contacts the new handle " "%s instead." msgstr "" -#: diaspora.php:78 +#: diaspora.php:79 msgid "All aspects" msgstr "" -#: diaspora.php:79 +#: diaspora.php:80 msgid "Public" msgstr "" -#: diaspora.php:85 +#: diaspora.php:86 msgid "Post to aspect:" msgstr "" -#: diaspora.php:86 +#: diaspora.php:87 #, php-format msgid "Connected with your Diaspora account %s" msgstr "" -#: diaspora.php:89 +#: diaspora.php:90 msgid "" "Can't login to your Diaspora account. Please check handle (in the format " "user@domain.tld) and password." msgstr "" -#: diaspora.php:96 +#: diaspora.php:97 msgid "Information" msgstr "" -#: diaspora.php:97 +#: diaspora.php:98 msgid "Error" msgstr "" -#: diaspora.php:103 +#: diaspora.php:104 msgid "Enable Diaspora Post Addon" msgstr "" -#: diaspora.php:104 +#: diaspora.php:105 msgid "Diaspora handle" msgstr "" -#: diaspora.php:105 +#: diaspora.php:106 msgid "Diaspora password" msgstr "" -#: diaspora.php:105 +#: diaspora.php:106 msgid "" "Privacy notice: Your Diaspora password will be stored unencrypted to " "authenticate you with your Diaspora pod. This means your Friendica node " "administrator can have access to it." msgstr "" -#: diaspora.php:107 +#: diaspora.php:108 msgid "Post to Diaspora by default" msgstr "" -#: diaspora.php:112 +#: diaspora.php:113 msgid "Diaspora Export" msgstr "" diff --git a/diaspora/lang/de/messages.po b/diaspora/lang/de/messages.po index 34fd85b1..e4abd25c 100644 --- a/diaspora/lang/de/messages.po +++ b/diaspora/lang/de/messages.po @@ -4,7 +4,7 @@ # # # Translators: -# foss , 2020 +# foss , 2020 # Till Mohr , 2021 # Tobias Diekershoff , 2014 # Tobias Diekershoff , 2018,2020 @@ -14,9 +14,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:17-0500\n" -"PO-Revision-Date: 2014-06-22 11:39+0000\n" -"Last-Translator: Till Mohr , 2021\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2021-12-22 15:27+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/dwpost/lang/cs/messages.po b/dwpost/lang/cs/messages.po index fc32a371..e5a9b25d 100644 --- a/dwpost/lang/cs/messages.po +++ b/dwpost/lang/cs/messages.po @@ -10,36 +10,40 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:17-0500\n" -"PO-Revision-Date: 2014-06-22 11:41+0000\n" -"Last-Translator: Aditoo, 2018\n" -"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" +"POT-Creation-Date: 2013-02-27 05:01-0500\n" +"PO-Revision-Date: 2018-06-14 10:13+0000\n" +"Last-Translator: Aditoo\n" +"Language-Team: Czech (http://www.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" -#: dwpost.php:43 +#: dwpost.php:39 msgid "Post to Dreamwidth" -msgstr "Odeslat na Dreamwidth" +msgstr "Poslat na Dreamwidth" -#: dwpost.php:63 -msgid "Enable Dreamwidth Post Addon" -msgstr "" +#: dwpost.php:70 +msgid "Dreamwidth Post Settings" +msgstr "Nastavení Dreamwidth Post" -#: dwpost.php:64 -msgid "Dreamwidth username" -msgstr "" +#: dwpost.php:72 +msgid "Enable dreamwidth Post Addon" +msgstr "Povolit doplněk Dreamwidth Post" -#: dwpost.php:65 -msgid "Dreamwidth password" -msgstr "" +#: dwpost.php:77 +msgid "dreamwidth username" +msgstr "dreamwidth uživatelské jméno" -#: dwpost.php:66 -msgid "Post to Dreamwidth by default" -msgstr "" +#: dwpost.php:82 +msgid "dreamwidth password" +msgstr "dreamwidth heslo" -#: dwpost.php:71 -msgid "Dreamwidth Export" -msgstr "" +#: dwpost.php:87 +msgid "Post to dreamwidth by default" +msgstr "Ve výchozím stavu posílat na dreamwidth" + +#: dwpost.php:93 +msgid "Submit" +msgstr "Odeslat" diff --git a/dwpost/lang/cs/strings.php b/dwpost/lang/cs/strings.php index 7378f061..586b7707 100644 --- a/dwpost/lang/cs/strings.php +++ b/dwpost/lang/cs/strings.php @@ -5,4 +5,10 @@ function string_plural_select_cs($n){ $n = intval($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 Dreamwidth'] = 'Odeslat na Dreamwidth'; +$a->strings['Post to Dreamwidth'] = 'Poslat na Dreamwidth'; +$a->strings['Dreamwidth Post Settings'] = 'Nastavení Dreamwidth Post'; +$a->strings['Enable dreamwidth Post Addon'] = 'Povolit doplněk Dreamwidth Post'; +$a->strings['dreamwidth username'] = 'dreamwidth uživatelské jméno'; +$a->strings['dreamwidth password'] = 'dreamwidth heslo'; +$a->strings['Post to dreamwidth by default'] = 'Ve výchozím stavu posílat na dreamwidth'; +$a->strings['Submit'] = 'Odeslat'; diff --git a/dwpost/lang/de/messages.po b/dwpost/lang/de/messages.po index adfa56b1..550c2493 100644 --- a/dwpost/lang/de/messages.po +++ b/dwpost/lang/de/messages.po @@ -13,9 +13,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:17-0500\n" -"PO-Revision-Date: 2014-06-22 11:41+0000\n" -"Last-Translator: Tobias Diekershoff , 2018,2021-2022\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2022-01-22 17:33+0000\n" +"Last-Translator: Tobias Diekershoff \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/forumdirectory/forumdirectory.php b/forumdirectory/forumdirectory.php index 79267c4e..61d3efd4 100644 --- a/forumdirectory/forumdirectory.php +++ b/forumdirectory/forumdirectory.php @@ -4,8 +4,6 @@ * Description: Add a directory of forums hosted on your server, with verbose descriptions. * Version: 1.1 * Author: Thomas Willingham - * Status: Unsupported - * Note: Please use Group Directory instead */ use Friendica\App; diff --git a/forumdirectory/lang/de/messages.po b/forumdirectory/lang/de/messages.po index 35ee4a55..4ba76068 100644 --- a/forumdirectory/lang/de/messages.po +++ b/forumdirectory/lang/de/messages.po @@ -11,9 +11,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-02-01 18:15+0100\n" -"PO-Revision-Date: 2014-06-22 12:31+0000\n" -"Last-Translator: Tobias Diekershoff , 2021\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2021-02-06 16:55+0000\n" +"Last-Translator: Tobias Diekershoff \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/fromapp/lang/de/messages.po b/fromapp/lang/de/messages.po index fa4c8c63..59d5d3c5 100644 --- a/fromapp/lang/de/messages.po +++ b/fromapp/lang/de/messages.po @@ -13,9 +13,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:14-0500\n" -"PO-Revision-Date: 2014-06-22 12:33+0000\n" -"Last-Translator: Tobias Diekershoff , 2019\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2021-12-22 15:15+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/geonames/lang/de/messages.po b/geonames/lang/de/messages.po index cbb9f74d..a182d6bb 100644 --- a/geonames/lang/de/messages.po +++ b/geonames/lang/de/messages.po @@ -13,9 +13,9 @@ msgstr "" "Project-Id-Version: friendica\n" "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: Tobias Diekershoff , 2018,2021\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2021-12-22 17:23+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/gnot/lang/de/messages.po b/gnot/lang/de/messages.po index a3ffbe12..26e45848 100644 --- a/gnot/lang/de/messages.po +++ b/gnot/lang/de/messages.po @@ -13,9 +13,9 @@ msgstr "" "Project-Id-Version: friendica\n" "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: Tobias Diekershoff , 2018,2021\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2021-12-22 15:27+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/gravatar/lang/cs/messages.po b/gravatar/lang/cs/messages.po index 9950b02e..333f8be9 100644 --- a/gravatar/lang/cs/messages.po +++ b/gravatar/lang/cs/messages.po @@ -4,69 +4,72 @@ # # # Translators: -# Aditoo, 2018 -# michal_s , 2014-2015 +# Michal Šupler , 2014-2015 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: 2014-06-23 08:33+0000\n" -"Last-Translator: Aditoo, 2018\n" -"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" +"POT-Creation-Date: 2013-02-27 05:01-0500\n" +"PO-Revision-Date: 2015-02-11 19:41+0000\n" +"Last-Translator: Michal Šupler \n" +"Language-Team: Czech (http://www.transifex.com/projects/p/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" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -#: gravatar.php:78 +#: gravatar.php:71 msgid "generic profile image" msgstr "generický profilový obrázek" -#: gravatar.php:79 +#: gravatar.php:72 msgid "random geometric pattern" msgstr "náhodný geometrický vzor" -#: gravatar.php:80 +#: gravatar.php:73 msgid "monster face" msgstr "tvář příšery" -#: gravatar.php:81 +#: gravatar.php:74 msgid "computer generated face" msgstr "počítačově generovaná tvář" -#: gravatar.php:82 +#: gravatar.php:75 msgid "retro arcade style face" msgstr "tvář v retro arkádovém stylu" -#: gravatar.php:96 +#: gravatar.php:89 msgid "Information" msgstr "Informace" -#: gravatar.php:96 +#: gravatar.php:89 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 "Doplněk Libravatar je také nainstalován. Prosím zakažte doplněk Libravatar nebo tento doplněk Gravatar.
Doplněk Libravatar se přepne na Gravatar, pokud na Libravataru nebude nic nalezeno." +msgstr "Libravatar doplněk je také nainstalován. Prosím zakažte doplněk Libravatar nebo tento doplněk Gravatar.
Libravatar doplněk se vrátí k doplňku Gravatar, pokud na Libravataru nebude nic nalezeno." -#: gravatar.php:102 -msgid "Save Settings" -msgstr "" +#: gravatar.php:95 +msgid "Submit" +msgstr "Odeslat" -#: gravatar.php:103 +#: gravatar.php:96 msgid "Default avatar image" -msgstr "Výchozí avatarový obrázek" +msgstr "Defaultní obrázek avataru" -#: gravatar.php:103 +#: gravatar.php:96 msgid "Select default avatar image if none was found at Gravatar. See README" -msgstr "Nastavte výchozí avatarový obrázek, pokud ho již nemáte na Gravataru. Více viz. soubor README." +msgstr "Nastavte defaulní obrázek avatara pokud ho již nemáte na Gravatar. Více viz. soubor README." -#: gravatar.php:104 +#: gravatar.php:97 msgid "Rating of images" msgstr "Hodnocení obrázků" -#: gravatar.php:104 +#: gravatar.php:97 msgid "Select the appropriate avatar rating for your site. See README" -msgstr "Zadejte příslušné ohodnocení avataru pro vaši stránku. Viz README." +msgstr "Zadejte ohodnocení příslušného avatara pro vaši stránku. Viz README." + +#: gravatar.php:111 +msgid "Gravatar settings updated." +msgstr "Nastavení Gravatar aktualizováno." diff --git a/gravatar/lang/cs/strings.php b/gravatar/lang/cs/strings.php index 831f6ed8..61e9c03e 100644 --- a/gravatar/lang/cs/strings.php +++ b/gravatar/lang/cs/strings.php @@ -3,7 +3,7 @@ if(! function_exists("string_plural_select_cs")) { function string_plural_select_cs($n){ $n = intval($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; } + if (($n==1)) { return 0; } else if (($n>=2 && $n<=4)) { return 1; } else { return 2; } }} $a->strings['generic profile image'] = 'generický profilový obrázek'; $a->strings['random geometric pattern'] = 'náhodný geometrický vzor'; @@ -11,8 +11,10 @@ $a->strings['monster face'] = 'tvář příšery'; $a->strings['computer generated face'] = 'počítačově generovaná tvář'; $a->strings['retro arcade style face'] = 'tvář v retro arkádovém stylu'; $a->strings['Information'] = 'Informace'; -$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.'] = 'Doplněk Libravatar je také nainstalován. Prosím zakažte doplněk Libravatar nebo tento doplněk Gravatar.
Doplněk Libravatar se přepne na Gravatar, pokud na Libravataru nebude nic nalezeno.'; -$a->strings['Default avatar image'] = 'Výchozí avatarový obrázek'; -$a->strings['Select default avatar image if none was found at Gravatar. See README'] = 'Nastavte výchozí avatarový obrázek, pokud ho již nemáte na Gravataru. Více viz. soubor README.'; +$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.'] = 'Libravatar doplněk je také nainstalován. Prosím zakažte doplněk Libravatar nebo tento doplněk Gravatar.
Libravatar doplněk se vrátí k doplňku Gravatar, pokud na Libravataru nebude nic nalezeno.'; +$a->strings['Submit'] = 'Odeslat'; +$a->strings['Default avatar image'] = 'Defaultní obrázek avataru'; +$a->strings['Select default avatar image if none was found at Gravatar. See README'] = 'Nastavte defaulní obrázek avatara pokud ho již nemáte na Gravatar. Více viz. soubor README.'; $a->strings['Rating of images'] = 'Hodnocení obrázků'; -$a->strings['Select the appropriate avatar rating for your site. See README'] = 'Zadejte příslušné ohodnocení avataru pro vaši stránku. Viz README.'; +$a->strings['Select the appropriate avatar rating for your site. See README'] = 'Zadejte ohodnocení příslušného avatara pro vaši stránku. Viz README.'; +$a->strings['Gravatar settings updated.'] = 'Nastavení Gravatar aktualizováno.'; diff --git a/gravatar/lang/de/messages.po b/gravatar/lang/de/messages.po index 8f5fc3ce..14b8c3af 100644 --- a/gravatar/lang/de/messages.po +++ b/gravatar/lang/de/messages.po @@ -13,9 +13,9 @@ msgstr "" "Project-Id-Version: friendica\n" "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: Tobias Diekershoff , 2021\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2021-02-06 17:01+0000\n" +"Last-Translator: Tobias Diekershoff \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/group_text/group_text.php b/group_text/group_text.php index 02e9fd0a..8520f696 100644 --- a/group_text/group_text.php +++ b/group_text/group_text.php @@ -4,8 +4,6 @@ * Description: Disable images in group edit menu * Version: 1.0 * Author: Thomas Willingham - * Status: Unsupported - * Note: Please use Circle Text instead */ use Friendica\App; diff --git a/group_text/lang/de/messages.po b/group_text/lang/de/messages.po index e4e5d782..40ed72ee 100644 --- a/group_text/lang/de/messages.po +++ b/group_text/lang/de/messages.po @@ -13,9 +13,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:14-0500\n" -"PO-Revision-Date: 2014-06-23 08:35+0000\n" -"Last-Translator: Tobias Diekershoff , 2021\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2021-12-22 15:27+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/groupdirectory/groupdirectory.php b/groupdirectory/groupdirectory.php deleted file mode 100644 index 7bad1ef9..00000000 --- a/groupdirectory/groupdirectory.php +++ /dev/null @@ -1,155 +0,0 @@ - - */ - -use Friendica\Content\Nav; -use Friendica\Content\Pager; -use Friendica\Content\Widget; -use Friendica\Core\Hook; -use Friendica\Core\Renderer; -use Friendica\Database\DBA; -use Friendica\DI; -use Friendica\Model\Profile; -use Friendica\Model\User; - -global $groupdirectory_search; - -function groupdirectory_install() -{ - Hook::register('app_menu', __FILE__, 'groupdirectory_app_menu'); -} - -/** - * 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. - */ -/** - * 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 groupdirectory_module() {} - -function groupdirectory_app_menu(array &$b) -{ - $b['app_menu'][] = ''; -} - -function groupdirectory_init() -{ - if (DI::userSession()->getLocalUserId()) { - DI::page()['aside'] .= Widget::findPeople(); - } -} - -function groupdirectory_post() -{ - global $groupdirectory_search; - - if (!empty($_POST['search'])) { - $groupdirectory_search = $_POST['search']; - } -} - -function groupdirectory_content() -{ - global $groupdirectory_search; - - if (DI::config()->get('system', 'block_public') && !DI::userSession()->getLocalUserId() && !DI::userSession()->getRemoteUserId()) { - DI::sysmsg()->addNotice(DI::l10n()->t('Public access denied.')); - return ''; - } - - $o = ''; - $entries = []; - - Nav::setSelected('directory'); - - if (!empty($groupdirectory_search)) { - $search = trim($groupdirectory_search); - } else { - $search = (!empty($_GET['search']) ? trim(rawurldecode($_GET['search'])) : ''); - } - - $gdirpath = ''; - $dirurl = DI::config()->get('system', 'directory'); - if (strlen($dirurl)) { - $gdirpath = Profile::zrl($dirurl, true); - } - - $sql_extra = ''; - if (strlen($search)) { - $search = DBA::escape($search); - - $sql_extra = " AND ((`profile`.`name` LIKE '%$search%') OR - (`user`.`nickname` LIKE '%$search%') OR - (`profile`.`about` LIKE '%$search%') OR - (`profile`.`locality` LIKE '%$search%') OR - (`profile`.`region` LIKE '%$search%') OR - (`profile`.`country-name` LIKE '%$search%') OR - (`profile`.`pub_keywords` LIKE '%$search%') OR - (`profile`.`prv_keywords` LIKE '%$search%'))"; - } - - $publish = DI::config()->get('system', 'publish_all') ? '' : "`publish` = 1"; - - $total = 0; - $cnt = DBA::fetchFirst("SELECT COUNT(*) AS `total` FROM `profile` - INNER JOIN `user` ON `user`.`uid` = `profile`.`uid` - WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `user`.`page-flags` = ? $sql_extra", - User::PAGE_FLAGS_COMMUNITY); - if (DBA::isResult($cnt)) { - $total = $cnt['total']; - } - - $pager = new Pager(DI::l10n(), DI::args()->getQueryString(), 60); - - $order = " ORDER BY `name` ASC "; - - $limit = $pager->getStart() . "," . $pager->getItemsPerPage(); - - $r = DBA::p("SELECT `profile`.*, `user`.`nickname`, `user`.`timezone` , `user`.`page-flags`, - `contact`.`addr`, `contact`.`url` FROM `profile` - INNER JOIN `user` ON `user`.`uid` = `profile`.`uid` - INNER JOIN `contact` ON `contact`.`uid` = `user`.`uid` - WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `user`.`page-flags` = ? AND `contact`.`self` - $sql_extra $order LIMIT $limit", User::PAGE_FLAGS_COMMUNITY - ); - - if (DBA::isResult($r)) { - if (in_array('small', DI::args()->getArgv())) { - $photo = 'thumb'; - } else { - $photo = 'photo'; - } - - while ($rr = DBA::fetch($r)) { - $entries[] = Friendica\Module\Directory::formatEntry($rr, $photo); - } - DBA::close($r); - } else { - DI::sysmsg()->addNotice(DI::l10n()->t('No entries (some entries may be hidden).')); - } - - $tpl = Renderer::getMarkupTemplate('directory_header.tpl'); - $o .= Renderer::replaceMacros($tpl, [ - '$search' => $search, - '$globaldir' => DI::l10n()->t('Global Directory'), - '$gdirpath' => $gdirpath, - '$desc' => DI::l10n()->t('Find on this site'), - '$contacts' => $entries, - '$finding' => DI::l10n()->t('Results for:'), - '$findterm' => (strlen($search) ? $search : ""), - '$title' => DI::l10n()->t('Group Directory'), - '$search_mod' => 'groupdirectory', - '$submit' => DI::l10n()->t('Find'), - '$paginate' => $pager->renderFull($total), - ]); - - return $o; -} diff --git a/groupdirectory/lang/C/messages.po b/groupdirectory/lang/C/messages.po deleted file mode 100644 index f83171f4..00000000 --- a/groupdirectory/lang/C/messages.po +++ /dev/null @@ -1,46 +0,0 @@ -# ADDON groupdirectory -# Copyright (C) -# This file is distributed under the same license as the Friendica groupdirectory addon package. -# -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: \n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-06-03 15:49-0400\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" - -#: groupdirectory.php:40 groupdirectory.php:148 -msgid "Group Directory" -msgstr "" - -#: groupdirectory.php:64 -msgid "Public access denied." -msgstr "" - -#: groupdirectory.php:136 -msgid "No entries (some entries may be hidden)." -msgstr "" - -#: groupdirectory.php:142 -msgid "Global Directory" -msgstr "" - -#: groupdirectory.php:144 -msgid "Find on this site" -msgstr "" - -#: groupdirectory.php:146 -msgid "Results for:" -msgstr "" - -#: groupdirectory.php:150 -msgid "Find" -msgstr "" diff --git a/groupdirectory/lang/ar/messages.po b/groupdirectory/lang/ar/messages.po deleted file mode 100644 index 24380f0f..00000000 --- a/groupdirectory/lang/ar/messages.po +++ /dev/null @@ -1,50 +0,0 @@ -# ADDON forumdirectory -# Copyright (C) -# This file is distributed under the same license as the Friendica forumdirectory addon package. -# -# -# Translators: -# abidin toumi , 2021 -# ButterflyOfFire, 2019 -# Farida Khalaf , 2021 -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-10-29 10:27+0000\n" -"Last-Translator: abidin toumi \n" -"Language-Team: Arabic (http://www.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" - -#: forumdirectory.php:33 forumdirectory.php:137 -msgid "Forum Directory" -msgstr "دليل المنتدى" - -#: forumdirectory.php:53 -msgid "Public access denied." -msgstr "رُفض الوصول العمومي." - -#: forumdirectory.php:125 -msgid "No entries (some entries may be hidden)." -msgstr "لا توجد مدخلات (قد تكون بعض المدخلات مخفية)." - -#: forumdirectory.php:131 -msgid "Global Directory" -msgstr "الدليل العالمي" - -#: forumdirectory.php:133 -msgid "Find on this site" -msgstr "ابحث في هذا الموقع" - -#: forumdirectory.php:135 -msgid "Results for:" -msgstr "النتائج:" - -#: forumdirectory.php:139 -msgid "Find" -msgstr "ابحث" diff --git a/groupdirectory/lang/ar/strings.php b/groupdirectory/lang/ar/strings.php deleted file mode 100644 index eb6f3077..00000000 --- a/groupdirectory/lang/ar/strings.php +++ /dev/null @@ -1,14 +0,0 @@ -=3 && $n%100<=10) { return 3; } else if ($n%100>=11 && $n%100<=99) { return 4; } else { return 5; } -}} -$a->strings['Forum Directory'] = 'دليل المنتدى'; -$a->strings['Public access denied.'] = 'رُفض الوصول العمومي.'; -$a->strings['No entries (some entries may be hidden).'] = 'لا توجد مدخلات (قد تكون بعض المدخلات مخفية).'; -$a->strings['Global Directory'] = 'الدليل العالمي'; -$a->strings['Find on this site'] = 'ابحث في هذا الموقع'; -$a->strings['Results for:'] = 'النتائج:'; -$a->strings['Find'] = 'ابحث'; diff --git a/groupdirectory/lang/ca/messages.po b/groupdirectory/lang/ca/messages.po deleted file mode 100644 index 0aa19b1c..00000000 --- a/groupdirectory/lang/ca/messages.po +++ /dev/null @@ -1,80 +0,0 @@ -# ADDON forumdirectory -# Copyright (C) -# This file is distributed under the same license as the Friendica forumdirectory addon package. -# -# -# Translators: -# Joan Bar , 2019 -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: 2019-10-18 18:57+0000\n" -"Last-Translator: Joan Bar \n" -"Language-Team: Catalan (http://www.transifex.com/Friendica/friendica/language/ca/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ca\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: forumdirectory.php:22 -msgid "Forum Directory" -msgstr "Directori de fòrums" - -#: forumdirectory.php:53 -msgid "Public access denied." -msgstr "L'accés al públic s'ha denegat." - -#: forumdirectory.php:71 -msgid "Global Directory" -msgstr "Directori global" - -#: forumdirectory.php:79 -msgid "Find on this site" -msgstr "Cerqueu en aquest lloc" - -#: forumdirectory.php:81 -msgid "Finding: " -msgstr "Trobament:" - -#: forumdirectory.php:82 -msgid "Site Directory" -msgstr "Directori de llocs" - -#: forumdirectory.php:83 -msgid "Find" -msgstr "trobar" - -#: forumdirectory.php:133 -msgid "Age: " -msgstr "Edat:" - -#: forumdirectory.php:136 -msgid "Gender: " -msgstr "Gènere:" - -#: forumdirectory.php:156 -msgid "Location:" -msgstr "Ubicació:" - -#: forumdirectory.php:158 -msgid "Gender:" -msgstr "Gènere:" - -#: forumdirectory.php:160 -msgid "Status:" -msgstr "Estat:" - -#: forumdirectory.php:162 -msgid "Homepage:" -msgstr "Pàgina inicial:" - -#: forumdirectory.php:164 -msgid "About:" -msgstr "Sobre:" - -#: forumdirectory.php:201 -msgid "No entries (some entries may be hidden)." -msgstr "No hi ha entrades (algunes entrades poden estar ocultes)." diff --git a/groupdirectory/lang/ca/strings.php b/groupdirectory/lang/ca/strings.php deleted file mode 100644 index 07a39488..00000000 --- a/groupdirectory/lang/ca/strings.php +++ /dev/null @@ -1,22 +0,0 @@ -strings['Forum Directory'] = 'Directori de fòrums'; -$a->strings['Public access denied.'] = 'L\'accés al públic s\'ha denegat.'; -$a->strings['Global Directory'] = 'Directori global'; -$a->strings['Find on this site'] = 'Cerqueu en aquest lloc'; -$a->strings['Finding: '] = 'Trobament:'; -$a->strings['Site Directory'] = 'Directori de llocs'; -$a->strings['Find'] = 'trobar'; -$a->strings['Age: '] = 'Edat:'; -$a->strings['Gender: '] = 'Gènere:'; -$a->strings['Location:'] = 'Ubicació:'; -$a->strings['Gender:'] = 'Gènere:'; -$a->strings['Status:'] = 'Estat:'; -$a->strings['Homepage:'] = 'Pàgina inicial:'; -$a->strings['About:'] = 'Sobre:'; -$a->strings['No entries (some entries may be hidden).'] = 'No hi ha entrades (algunes entrades poden estar ocultes).'; diff --git a/groupdirectory/lang/cs/messages.po b/groupdirectory/lang/cs/messages.po deleted file mode 100644 index 138c26f3..00000000 --- a/groupdirectory/lang/cs/messages.po +++ /dev/null @@ -1,81 +0,0 @@ -# ADDON forumdirectory -# Copyright (C) -# This file is distributed under the same license as the Friendica forumdirectory addon package. -# -# -# Translators: -# Aditoo, 2018 -# michal_s , 2014 -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-09-11 19:04+0000\n" -"Last-Translator: Aditoo\n" -"Language-Team: Czech (http://www.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" - -#: forumdirectory.php:22 -msgid "Forum Directory" -msgstr "Adresář fór" - -#: forumdirectory.php:53 -msgid "Public access denied." -msgstr "Veřejný přístup odepřen." - -#: forumdirectory.php:71 -msgid "Global Directory" -msgstr "Globální adresář" - -#: forumdirectory.php:79 -msgid "Find on this site" -msgstr "Najít na tomto webu" - -#: forumdirectory.php:81 -msgid "Finding: " -msgstr "Hledání: " - -#: forumdirectory.php:82 -msgid "Site Directory" -msgstr "Adresář serveru" - -#: forumdirectory.php:83 -msgid "Find" -msgstr "Najít" - -#: forumdirectory.php:133 -msgid "Age: " -msgstr "Věk: " - -#: forumdirectory.php:136 -msgid "Gender: " -msgstr "Pohlaví: " - -#: forumdirectory.php:156 -msgid "Location:" -msgstr "Poloha:" - -#: forumdirectory.php:158 -msgid "Gender:" -msgstr "Pohlaví:" - -#: forumdirectory.php:160 -msgid "Status:" -msgstr "Stav:" - -#: forumdirectory.php:162 -msgid "Homepage:" -msgstr "Domovská stránka:" - -#: forumdirectory.php:164 -msgid "About:" -msgstr "O mě:" - -#: forumdirectory.php:201 -msgid "No entries (some entries may be hidden)." -msgstr "Žádné záznamy (některé položky mohou být skryty)." diff --git a/groupdirectory/lang/cs/strings.php b/groupdirectory/lang/cs/strings.php deleted file mode 100644 index 2e7d6378..00000000 --- a/groupdirectory/lang/cs/strings.php +++ /dev/null @@ -1,22 +0,0 @@ -= 2 && $n <= 4 && $n % 1 == 0)) { return 1; } else if (($n % 1 != 0 )) { return 2; } else { return 3; } -}} -$a->strings['Forum Directory'] = 'Adresář fór'; -$a->strings['Public access denied.'] = 'Veřejný přístup odepřen.'; -$a->strings['Global Directory'] = 'Globální adresář'; -$a->strings['Find on this site'] = 'Najít na tomto webu'; -$a->strings['Finding: '] = 'Hledání: '; -$a->strings['Site Directory'] = 'Adresář serveru'; -$a->strings['Find'] = 'Najít'; -$a->strings['Age: '] = 'Věk: '; -$a->strings['Gender: '] = 'Pohlaví: '; -$a->strings['Location:'] = 'Poloha:'; -$a->strings['Gender:'] = 'Pohlaví:'; -$a->strings['Status:'] = 'Stav:'; -$a->strings['Homepage:'] = 'Domovská stránka:'; -$a->strings['About:'] = 'O mě:'; -$a->strings['No entries (some entries may be hidden).'] = 'Žádné záznamy (některé položky mohou být skryty).'; diff --git a/groupdirectory/lang/da-dk/messages.po b/groupdirectory/lang/da-dk/messages.po deleted file mode 100644 index 882c896e..00000000 --- a/groupdirectory/lang/da-dk/messages.po +++ /dev/null @@ -1,48 +0,0 @@ -# ADDON forumdirectory -# Copyright (C) -# This file is distributed under the same license as the Friendica forumdirectory addon package. -# -# -# Translators: -# Anton , 2022 -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: 2014-06-22 12:31+0000\n" -"Last-Translator: Anton , 2022\n" -"Language-Team: Danish (Denmark) (http://www.transifex.com/Friendica/friendica/language/da_DK/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: da_DK\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: forumdirectory.php:33 forumdirectory.php:137 -msgid "Forum Directory" -msgstr "Forum adressebog" - -#: forumdirectory.php:53 -msgid "Public access denied." -msgstr "Offentlig adgang nægtet." - -#: forumdirectory.php:125 -msgid "No entries (some entries may be hidden)." -msgstr "Ingen poster (nogle poster er måske skjulte)." - -#: forumdirectory.php:131 -msgid "Global Directory" -msgstr "Global adressebog" - -#: forumdirectory.php:133 -msgid "Find on this site" -msgstr "Find på denne side" - -#: forumdirectory.php:135 -msgid "Results for:" -msgstr "Resultater for:" - -#: forumdirectory.php:139 -msgid "Find" -msgstr "Find" diff --git a/groupdirectory/lang/da-dk/strings.php b/groupdirectory/lang/da-dk/strings.php deleted file mode 100644 index fecaed71..00000000 --- a/groupdirectory/lang/da-dk/strings.php +++ /dev/null @@ -1,14 +0,0 @@ -strings['Forum Directory'] = 'Forum adressebog'; -$a->strings['Public access denied.'] = 'Offentlig adgang nægtet.'; -$a->strings['No entries (some entries may be hidden).'] = 'Ingen poster (nogle poster er måske skjulte).'; -$a->strings['Global Directory'] = 'Global adressebog'; -$a->strings['Find on this site'] = 'Find på denne side'; -$a->strings['Results for:'] = 'Resultater for:'; -$a->strings['Find'] = 'Find'; diff --git a/groupdirectory/lang/de/messages.po b/groupdirectory/lang/de/messages.po deleted file mode 100644 index 35ee4a55..00000000 --- a/groupdirectory/lang/de/messages.po +++ /dev/null @@ -1,49 +0,0 @@ -# ADDON forumdirectory -# Copyright (C) -# This file is distributed under the same license as the Friendica forumdirectory addon package. -# -# -# Translators: -# Tobias Diekershoff , 2014 -# Tobias Diekershoff , 2021 -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: 2014-06-22 12:31+0000\n" -"Last-Translator: Tobias Diekershoff , 2021\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" -"Content-Transfer-Encoding: 8bit\n" -"Language: de\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: forumdirectory.php:33 forumdirectory.php:137 -msgid "Forum Directory" -msgstr "Foren Verzeichnis" - -#: forumdirectory.php:53 -msgid "Public access denied." -msgstr "Öffentlicher Zugriff verweigert." - -#: forumdirectory.php:125 -msgid "No entries (some entries may be hidden)." -msgstr "Keine Einträge (einige Einträge könnten versteckt sein)." - -#: forumdirectory.php:131 -msgid "Global Directory" -msgstr "Weltweites Verzeichnis" - -#: forumdirectory.php:133 -msgid "Find on this site" -msgstr "Auf diesem Server suchen" - -#: forumdirectory.php:135 -msgid "Results for:" -msgstr "Ergebnis für:" - -#: forumdirectory.php:139 -msgid "Find" -msgstr "Finde" diff --git a/groupdirectory/lang/de/strings.php b/groupdirectory/lang/de/strings.php deleted file mode 100644 index 081f3152..00000000 --- a/groupdirectory/lang/de/strings.php +++ /dev/null @@ -1,14 +0,0 @@ -strings['Forum Directory'] = 'Foren Verzeichnis'; -$a->strings['Public access denied.'] = 'Öffentlicher Zugriff verweigert.'; -$a->strings['No entries (some entries may be hidden).'] = 'Keine Einträge (einige Einträge könnten versteckt sein).'; -$a->strings['Global Directory'] = 'Weltweites Verzeichnis'; -$a->strings['Find on this site'] = 'Auf diesem Server suchen'; -$a->strings['Results for:'] = 'Ergebnis für:'; -$a->strings['Find'] = 'Finde'; diff --git a/groupdirectory/lang/eo/strings.php b/groupdirectory/lang/eo/strings.php deleted file mode 100644 index 4ec15e76..00000000 --- a/groupdirectory/lang/eo/strings.php +++ /dev/null @@ -1,16 +0,0 @@ -strings["Public access denied."] = "Publika atingo ne permesita."; -$a->strings["Global Directory"] = "Tutmonda Katalogo"; -$a->strings["Find on this site"] = "Trovi en ĉi retejo"; -$a->strings["Finding: "] = "Trovata:"; -$a->strings["Site Directory"] = "Reteja Katalogo"; -$a->strings["Find"] = "Trovi"; -$a->strings["Age: "] = "Aĝo:"; -$a->strings["Gender: "] = "Sekso:"; -$a->strings["Location:"] = "Loko:"; -$a->strings["Gender:"] = "Sekso:"; -$a->strings["Status:"] = "Stato:"; -$a->strings["Homepage:"] = "Hejmpaĝo:"; -$a->strings["About:"] = "Pri:"; -$a->strings["No entries (some entries may be hidden)."] = "Neniom da afiŝoj (kelkaj afiŝoj eble ne estas videbla)."; diff --git a/groupdirectory/lang/es/messages.po b/groupdirectory/lang/es/messages.po deleted file mode 100644 index 74948223..00000000 --- a/groupdirectory/lang/es/messages.po +++ /dev/null @@ -1,49 +0,0 @@ -# ADDON forumdirectory -# Copyright (C) -# This file is distributed under the same license as the Friendica forumdirectory addon package. -# -# -# Translators: -# Albert, 2016 -# Senex Petrovic , 2021 -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-01 09:54+0000\n" -"Last-Translator: Senex Petrovic \n" -"Language-Team: Spanish (http://www.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" - -#: forumdirectory.php:33 forumdirectory.php:137 -msgid "Forum Directory" -msgstr "Directorio de foro" - -#: forumdirectory.php:53 -msgid "Public access denied." -msgstr "Acceso público denegado." - -#: forumdirectory.php:125 -msgid "No entries (some entries may be hidden)." -msgstr "Sin entradas (algunas entradas pueden estar ocultas)." - -#: forumdirectory.php:131 -msgid "Global Directory" -msgstr "Directorio global" - -#: forumdirectory.php:133 -msgid "Find on this site" -msgstr "Encontrar en esta página" - -#: forumdirectory.php:135 -msgid "Results for:" -msgstr "Resultados para:" - -#: forumdirectory.php:139 -msgid "Find" -msgstr "Encontrar" diff --git a/groupdirectory/lang/es/strings.php b/groupdirectory/lang/es/strings.php deleted file mode 100644 index 4f1a59f1..00000000 --- a/groupdirectory/lang/es/strings.php +++ /dev/null @@ -1,14 +0,0 @@ -strings['Forum Directory'] = 'Directorio de foro'; -$a->strings['Public access denied.'] = 'Acceso público denegado.'; -$a->strings['No entries (some entries may be hidden).'] = 'Sin entradas (algunas entradas pueden estar ocultas).'; -$a->strings['Global Directory'] = 'Directorio global'; -$a->strings['Find on this site'] = 'Encontrar en esta página'; -$a->strings['Results for:'] = 'Resultados para:'; -$a->strings['Find'] = 'Encontrar'; diff --git a/groupdirectory/lang/fi-fi/messages.po b/groupdirectory/lang/fi-fi/messages.po deleted file mode 100644 index 6c4f08c9..00000000 --- a/groupdirectory/lang/fi-fi/messages.po +++ /dev/null @@ -1,81 +0,0 @@ -# ADDON forumdirectory -# Copyright (C) -# This file is distributed under the same license as the Friendica forumdirectory addon package. -# -# -# Translators: -# Kris, 2018 -# Kris, 2018 -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-05-12 12:50+0000\n" -"Last-Translator: Kris\n" -"Language-Team: Finnish (Finland) (http://www.transifex.com/Friendica/friendica/language/fi_FI/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: fi_FI\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: forumdirectory.php:22 -msgid "Forum Directory" -msgstr "Foorumihakemisto" - -#: forumdirectory.php:53 -msgid "Public access denied." -msgstr "Julkinen käyttö estetty." - -#: forumdirectory.php:71 -msgid "Global Directory" -msgstr "Maailmanlaajuinen hakemisto" - -#: forumdirectory.php:79 -msgid "Find on this site" -msgstr "Sivustohaku" - -#: forumdirectory.php:81 -msgid "Finding: " -msgstr "" - -#: forumdirectory.php:82 -msgid "Site Directory" -msgstr "Sivustoluettelo" - -#: forumdirectory.php:83 -msgid "Find" -msgstr "Etsi" - -#: forumdirectory.php:133 -msgid "Age: " -msgstr "Ikä:" - -#: forumdirectory.php:136 -msgid "Gender: " -msgstr "Sukupuoli:" - -#: forumdirectory.php:156 -msgid "Location:" -msgstr "Sijainti:" - -#: forumdirectory.php:158 -msgid "Gender:" -msgstr "Sukupuoli:" - -#: forumdirectory.php:160 -msgid "Status:" -msgstr "Tila:" - -#: forumdirectory.php:162 -msgid "Homepage:" -msgstr "Kotisivu:" - -#: forumdirectory.php:164 -msgid "About:" -msgstr "Lisätietoja:" - -#: forumdirectory.php:201 -msgid "No entries (some entries may be hidden)." -msgstr "Ei kohteita (jotkut kohteet saattaa olla piilotettuja)." diff --git a/groupdirectory/lang/fi-fi/strings.php b/groupdirectory/lang/fi-fi/strings.php deleted file mode 100644 index 70657d3c..00000000 --- a/groupdirectory/lang/fi-fi/strings.php +++ /dev/null @@ -1,21 +0,0 @@ -strings['Forum Directory'] = 'Foorumihakemisto'; -$a->strings['Public access denied.'] = 'Julkinen käyttö estetty.'; -$a->strings['Global Directory'] = 'Maailmanlaajuinen hakemisto'; -$a->strings['Find on this site'] = 'Sivustohaku'; -$a->strings['Site Directory'] = 'Sivustoluettelo'; -$a->strings['Find'] = 'Etsi'; -$a->strings['Age: '] = 'Ikä:'; -$a->strings['Gender: '] = 'Sukupuoli:'; -$a->strings['Location:'] = 'Sijainti:'; -$a->strings['Gender:'] = 'Sukupuoli:'; -$a->strings['Status:'] = 'Tila:'; -$a->strings['Homepage:'] = 'Kotisivu:'; -$a->strings['About:'] = 'Lisätietoja:'; -$a->strings['No entries (some entries may be hidden).'] = 'Ei kohteita (jotkut kohteet saattaa olla piilotettuja).'; diff --git a/groupdirectory/lang/fr/messages.po b/groupdirectory/lang/fr/messages.po deleted file mode 100644 index 7f9e2458..00000000 --- a/groupdirectory/lang/fr/messages.po +++ /dev/null @@ -1,51 +0,0 @@ -# ADDON forumdirectory -# Copyright (C) -# This file is distributed under the same license as the Friendica forumdirectory addon package. -# -# -# Translators: -# bob lebonche , 2021 -# Hypolite Petovan , 2016 -# StefOfficiel , 2015 -# Valvin , 2019 -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: 2014-06-22 12:31+0000\n" -"Last-Translator: bob lebonche , 2021\n" -"Language-Team: French (http://www.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" - -#: forumdirectory.php:33 forumdirectory.php:137 -msgid "Forum Directory" -msgstr "Annuaire de Forums" - -#: forumdirectory.php:53 -msgid "Public access denied." -msgstr "Accès public refusé." - -#: forumdirectory.php:125 -msgid "No entries (some entries may be hidden)." -msgstr "Pas de résultats (certains résultats peuvent être cachés)." - -#: forumdirectory.php:131 -msgid "Global Directory" -msgstr "Annuaire Global" - -#: forumdirectory.php:133 -msgid "Find on this site" -msgstr "Trouver sur cette instance" - -#: forumdirectory.php:135 -msgid "Results for:" -msgstr "Résultats pour :" - -#: forumdirectory.php:139 -msgid "Find" -msgstr "Chercher" diff --git a/groupdirectory/lang/fr/strings.php b/groupdirectory/lang/fr/strings.php deleted file mode 100644 index ac0e2323..00000000 --- a/groupdirectory/lang/fr/strings.php +++ /dev/null @@ -1,14 +0,0 @@ -strings['Forum Directory'] = 'Annuaire de Forums'; -$a->strings['Public access denied.'] = 'Accès public refusé.'; -$a->strings['No entries (some entries may be hidden).'] = 'Pas de résultats (certains résultats peuvent être cachés).'; -$a->strings['Global Directory'] = 'Annuaire Global'; -$a->strings['Find on this site'] = 'Trouver sur cette instance'; -$a->strings['Results for:'] = 'Résultats pour :'; -$a->strings['Find'] = 'Chercher'; diff --git a/groupdirectory/lang/hu/messages.po b/groupdirectory/lang/hu/messages.po deleted file mode 100644 index 996d310c..00000000 --- a/groupdirectory/lang/hu/messages.po +++ /dev/null @@ -1,48 +0,0 @@ -# ADDON forumdirectory -# Copyright (C) -# This file is distributed under the same license as the Friendica forumdirectory addon package. -# -# -# Translators: -# Balázs Úr, 2020-2021 -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: 2014-06-22 12:31+0000\n" -"Last-Translator: Balázs Úr, 2020-2021\n" -"Language-Team: Hungarian (http://www.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" - -#: forumdirectory.php:33 forumdirectory.php:137 -msgid "Forum Directory" -msgstr "Fórumkönyvtár" - -#: forumdirectory.php:53 -msgid "Public access denied." -msgstr "Nyilvános hozzáférés megtagadva." - -#: forumdirectory.php:125 -msgid "No entries (some entries may be hidden)." -msgstr "Nincsenek bejegyzések (néhány bejegyzés rejtve lehet)." - -#: forumdirectory.php:131 -msgid "Global Directory" -msgstr "Globális könyvtár" - -#: forumdirectory.php:133 -msgid "Find on this site" -msgstr "Keresés ezen az oldalon" - -#: forumdirectory.php:135 -msgid "Results for:" -msgstr "Találatok ehhez:" - -#: forumdirectory.php:139 -msgid "Find" -msgstr "Keresés" diff --git a/groupdirectory/lang/hu/strings.php b/groupdirectory/lang/hu/strings.php deleted file mode 100644 index 290cf7ed..00000000 --- a/groupdirectory/lang/hu/strings.php +++ /dev/null @@ -1,14 +0,0 @@ -strings['Forum Directory'] = 'Fórumkönyvtár'; -$a->strings['Public access denied.'] = 'Nyilvános hozzáférés megtagadva.'; -$a->strings['No entries (some entries may be hidden).'] = 'Nincsenek bejegyzések (néhány bejegyzés rejtve lehet).'; -$a->strings['Global Directory'] = 'Globális könyvtár'; -$a->strings['Find on this site'] = 'Keresés ezen az oldalon'; -$a->strings['Results for:'] = 'Találatok ehhez:'; -$a->strings['Find'] = 'Keresés'; diff --git a/groupdirectory/lang/is/strings.php b/groupdirectory/lang/is/strings.php deleted file mode 100644 index da710b73..00000000 --- a/groupdirectory/lang/is/strings.php +++ /dev/null @@ -1,16 +0,0 @@ -strings["Public access denied."] = "Alemennings aðgangur ekki veittur."; -$a->strings["Global Directory"] = "Heims tengiliða skrá"; -$a->strings["Find on this site"] = "Leita á þessum vef"; -$a->strings["Finding: "] = "Niðurstöður:"; -$a->strings["Site Directory"] = "Vef tengiliða skrá"; -$a->strings["Find"] = "Finna"; -$a->strings["Age: "] = "Aldur:"; -$a->strings["Gender: "] = "Kyn:"; -$a->strings["Location:"] = "Staðsetning:"; -$a->strings["Gender:"] = "Kyn:"; -$a->strings["Status:"] = "Staða:"; -$a->strings["Homepage:"] = "Heimasíða:"; -$a->strings["About:"] = "Um:"; -$a->strings["No entries (some entries may be hidden)."] = "Engar færslur (sumar geta verið faldar)."; diff --git a/groupdirectory/lang/it/messages.po b/groupdirectory/lang/it/messages.po deleted file mode 100644 index 8e3e5fa3..00000000 --- a/groupdirectory/lang/it/messages.po +++ /dev/null @@ -1,49 +0,0 @@ -# ADDON forumdirectory -# Copyright (C) -# This file is distributed under the same license as the Friendica forumdirectory addon package. -# -# -# Translators: -# fabrixxm , 2014 -# Sylke Vicious , 2021 -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-02-16 12:56+0000\n" -"Last-Translator: Sylke Vicious \n" -"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: it\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: forumdirectory.php:33 forumdirectory.php:137 -msgid "Forum Directory" -msgstr "Elenco Forum" - -#: forumdirectory.php:53 -msgid "Public access denied." -msgstr "Accesso negato." - -#: forumdirectory.php:125 -msgid "No entries (some entries may be hidden)." -msgstr "Nessuna voce (qualche voce potrebbe essere nascosta)." - -#: forumdirectory.php:131 -msgid "Global Directory" -msgstr "Elenco globale" - -#: forumdirectory.php:133 -msgid "Find on this site" -msgstr "Cerca nel sito" - -#: forumdirectory.php:135 -msgid "Results for:" -msgstr "Risultati per:" - -#: forumdirectory.php:139 -msgid "Find" -msgstr "Trova" diff --git a/groupdirectory/lang/it/strings.php b/groupdirectory/lang/it/strings.php deleted file mode 100644 index 4378cec3..00000000 --- a/groupdirectory/lang/it/strings.php +++ /dev/null @@ -1,14 +0,0 @@ -strings['Forum Directory'] = 'Elenco Forum'; -$a->strings['Public access denied.'] = 'Accesso negato.'; -$a->strings['No entries (some entries may be hidden).'] = 'Nessuna voce (qualche voce potrebbe essere nascosta).'; -$a->strings['Global Directory'] = 'Elenco globale'; -$a->strings['Find on this site'] = 'Cerca nel sito'; -$a->strings['Results for:'] = 'Risultati per:'; -$a->strings['Find'] = 'Trova'; diff --git a/groupdirectory/lang/nb-no/strings.php b/groupdirectory/lang/nb-no/strings.php deleted file mode 100644 index bcc94233..00000000 --- a/groupdirectory/lang/nb-no/strings.php +++ /dev/null @@ -1,17 +0,0 @@ -strings["Forum Directory"] = ""; -$a->strings["Public access denied."] = "Offentlig tilgang ikke tillatt."; -$a->strings["Global Directory"] = "Global katalog"; -$a->strings["Find on this site"] = ""; -$a->strings["Finding: "] = "Fant:"; -$a->strings["Site Directory"] = "Stedets katalog"; -$a->strings["Find"] = "Finn"; -$a->strings["Age: "] = "Alder:"; -$a->strings["Gender: "] = "Kjønn:"; -$a->strings["Location:"] = "Plassering:"; -$a->strings["Gender:"] = "Kjønn:"; -$a->strings["Status:"] = "Status:"; -$a->strings["Homepage:"] = "Hjemmeside:"; -$a->strings["About:"] = "Om:"; -$a->strings["No entries (some entries may be hidden)."] = "Ingen oppføringer (noen oppføringer kan være skjulte)."; diff --git a/groupdirectory/lang/nl/messages.po b/groupdirectory/lang/nl/messages.po deleted file mode 100644 index 746e1bff..00000000 --- a/groupdirectory/lang/nl/messages.po +++ /dev/null @@ -1,80 +0,0 @@ -# ADDON forumdirectory -# Copyright (C) -# This file is distributed under the same license as the Friendica forumdirectory addon package. -# -# -# Translators: -# Jeroen De Meerleer , 2018 -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:21+0000\n" -"Last-Translator: Jeroen De Meerleer \n" -"Language-Team: Dutch (http://www.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" - -#: forumdirectory.php:22 -msgid "Forum Directory" -msgstr "Forum index" - -#: forumdirectory.php:53 -msgid "Public access denied." -msgstr "Publieke toegang geweigerd" - -#: forumdirectory.php:71 -msgid "Global Directory" -msgstr "Globaal overzicht" - -#: forumdirectory.php:79 -msgid "Find on this site" -msgstr "Zoeken" - -#: forumdirectory.php:81 -msgid "Finding: " -msgstr "Zoeken..." - -#: forumdirectory.php:82 -msgid "Site Directory" -msgstr "Site overzicht" - -#: forumdirectory.php:83 -msgid "Find" -msgstr "Zoek" - -#: forumdirectory.php:133 -msgid "Age: " -msgstr "Leeftijd:" - -#: forumdirectory.php:136 -msgid "Gender: " -msgstr "Geslacht:" - -#: forumdirectory.php:156 -msgid "Location:" -msgstr "Woonplaats:" - -#: forumdirectory.php:158 -msgid "Gender:" -msgstr "Geslacht:" - -#: forumdirectory.php:160 -msgid "Status:" -msgstr "Status:" - -#: forumdirectory.php:162 -msgid "Homepage:" -msgstr "Website:" - -#: forumdirectory.php:164 -msgid "About:" -msgstr "Over:" - -#: forumdirectory.php:201 -msgid "No entries (some entries may be hidden)." -msgstr "Geen berichten (sommige berichten kunnen verborgen zijn)." diff --git a/groupdirectory/lang/nl/strings.php b/groupdirectory/lang/nl/strings.php deleted file mode 100644 index ae764ed7..00000000 --- a/groupdirectory/lang/nl/strings.php +++ /dev/null @@ -1,22 +0,0 @@ -strings['Forum Directory'] = 'Forum index'; -$a->strings['Public access denied.'] = 'Publieke toegang geweigerd'; -$a->strings['Global Directory'] = 'Globaal overzicht'; -$a->strings['Find on this site'] = 'Zoeken'; -$a->strings['Finding: '] = 'Zoeken...'; -$a->strings['Site Directory'] = 'Site overzicht'; -$a->strings['Find'] = 'Zoek'; -$a->strings['Age: '] = 'Leeftijd:'; -$a->strings['Gender: '] = 'Geslacht:'; -$a->strings['Location:'] = 'Woonplaats:'; -$a->strings['Gender:'] = 'Geslacht:'; -$a->strings['Status:'] = 'Status:'; -$a->strings['Homepage:'] = 'Website:'; -$a->strings['About:'] = 'Over:'; -$a->strings['No entries (some entries may be hidden).'] = 'Geen berichten (sommige berichten kunnen verborgen zijn).'; diff --git a/groupdirectory/lang/pl/messages.po b/groupdirectory/lang/pl/messages.po deleted file mode 100644 index 49226ac0..00000000 --- a/groupdirectory/lang/pl/messages.po +++ /dev/null @@ -1,50 +0,0 @@ -# ADDON forumdirectory -# Copyright (C) -# This file is distributed under the same license as the Friendica forumdirectory addon package. -# -# -# Translators: -# TORminator , 2015 -# Piotr Strębski , 2022 -# Waldemar Stoczkowski, 2018 -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: 2014-06-22 12:31+0000\n" -"Last-Translator: Piotr Strębski , 2022\n" -"Language-Team: Polish (http://www.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" - -#: forumdirectory.php:33 forumdirectory.php:137 -msgid "Forum Directory" -msgstr "Katalog forum" - -#: forumdirectory.php:53 -msgid "Public access denied." -msgstr "Odmowa dostępu publicznego." - -#: forumdirectory.php:125 -msgid "No entries (some entries may be hidden)." -msgstr "Brak wpisów (niektóre wpisy mogą być ukryte)." - -#: forumdirectory.php:131 -msgid "Global Directory" -msgstr "Globalny katalog" - -#: forumdirectory.php:133 -msgid "Find on this site" -msgstr "Znajdź na tej stronie" - -#: forumdirectory.php:135 -msgid "Results for:" -msgstr "Wyniki dla:" - -#: forumdirectory.php:139 -msgid "Find" -msgstr "Szukaj" diff --git a/groupdirectory/lang/pl/strings.php b/groupdirectory/lang/pl/strings.php deleted file mode 100644 index 9bf60bd7..00000000 --- a/groupdirectory/lang/pl/strings.php +++ /dev/null @@ -1,14 +0,0 @@ -=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['Forum Directory'] = 'Katalog forum'; -$a->strings['Public access denied.'] = 'Odmowa dostępu publicznego.'; -$a->strings['No entries (some entries may be hidden).'] = 'Brak wpisów (niektóre wpisy mogą być ukryte).'; -$a->strings['Global Directory'] = 'Globalny katalog'; -$a->strings['Find on this site'] = 'Znajdź na tej stronie'; -$a->strings['Results for:'] = 'Wyniki dla:'; -$a->strings['Find'] = 'Szukaj'; diff --git a/groupdirectory/lang/pt-br/messages.po b/groupdirectory/lang/pt-br/messages.po deleted file mode 100644 index c8d528ed..00000000 --- a/groupdirectory/lang/pt-br/messages.po +++ /dev/null @@ -1,80 +0,0 @@ -# ADDON forumdirectory -# Copyright (C) -# This file is distributed under the same license as the Friendica forumdirectory addon package. -# -# -# Translators: -# Beatriz Vital , 2016 -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: 2016-08-19 17:03+0000\n" -"Last-Translator: Beatriz Vital \n" -"Language-Team: Portuguese (Brazil) (http://www.transifex.com/Friendica/friendica/language/pt_BR/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: pt_BR\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -#: forumdirectory.php:22 -msgid "Forum Directory" -msgstr "Diretório de Fóruns" - -#: forumdirectory.php:53 -msgid "Public access denied." -msgstr "Acesso do público negado." - -#: forumdirectory.php:71 -msgid "Global Directory" -msgstr "Diretório Global" - -#: forumdirectory.php:79 -msgid "Find on this site" -msgstr "Procurar neste site" - -#: forumdirectory.php:81 -msgid "Finding: " -msgstr "Procurando:" - -#: forumdirectory.php:82 -msgid "Site Directory" -msgstr "Diretório do Site" - -#: forumdirectory.php:83 -msgid "Find" -msgstr "Procurar" - -#: forumdirectory.php:133 -msgid "Age: " -msgstr "Idade:" - -#: forumdirectory.php:136 -msgid "Gender: " -msgstr "Sexo:" - -#: forumdirectory.php:156 -msgid "Location:" -msgstr "Local:" - -#: forumdirectory.php:158 -msgid "Gender:" -msgstr "Sexo:" - -#: forumdirectory.php:160 -msgid "Status:" -msgstr "Estado:" - -#: forumdirectory.php:162 -msgid "Homepage:" -msgstr "Página principal:" - -#: forumdirectory.php:164 -msgid "About:" -msgstr "Sobre:" - -#: forumdirectory.php:201 -msgid "No entries (some entries may be hidden)." -msgstr "Sem resultados (alguns resultados podem estar ocultos)." diff --git a/groupdirectory/lang/pt-br/strings.php b/groupdirectory/lang/pt-br/strings.php deleted file mode 100644 index 8c6d216e..00000000 --- a/groupdirectory/lang/pt-br/strings.php +++ /dev/null @@ -1,22 +0,0 @@ - 1); -}} -$a->strings['Forum Directory'] = 'Diretório de Fóruns'; -$a->strings['Public access denied.'] = 'Acesso do público negado.'; -$a->strings['Global Directory'] = 'Diretório Global'; -$a->strings['Find on this site'] = 'Procurar neste site'; -$a->strings['Finding: '] = 'Procurando:'; -$a->strings['Site Directory'] = 'Diretório do Site'; -$a->strings['Find'] = 'Procurar'; -$a->strings['Age: '] = 'Idade:'; -$a->strings['Gender: '] = 'Sexo:'; -$a->strings['Location:'] = 'Local:'; -$a->strings['Gender:'] = 'Sexo:'; -$a->strings['Status:'] = 'Estado:'; -$a->strings['Homepage:'] = 'Página principal:'; -$a->strings['About:'] = 'Sobre:'; -$a->strings['No entries (some entries may be hidden).'] = 'Sem resultados (alguns resultados podem estar ocultos).'; diff --git a/groupdirectory/lang/ro/messages.po b/groupdirectory/lang/ro/messages.po deleted file mode 100644 index 84de16f3..00000000 --- a/groupdirectory/lang/ro/messages.po +++ /dev/null @@ -1,79 +0,0 @@ -# ADDON forumdirectory -# Copyright (C) -# This file is distributed under the same license as the Friendica forumdirectory addon package. -# -# -# Translators: -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: 2014-07-08 11:49+0000\n" -"Last-Translator: Arian - Cazare Muncitori \n" -"Language-Team: Romanian (Romania) (http://www.transifex.com/projects/p/friendica/language/ro_RO/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ro_RO\n" -"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n" - -#: forumdirectory.php:22 -msgid "Forum Directory" -msgstr "Director Forum" - -#: forumdirectory.php:53 -msgid "Public access denied." -msgstr "Acces public refuzat." - -#: forumdirectory.php:71 -msgid "Global Directory" -msgstr "Director Global" - -#: forumdirectory.php:79 -msgid "Find on this site" -msgstr "Căutați pe acest site" - -#: forumdirectory.php:81 -msgid "Finding: " -msgstr "Căutare:" - -#: forumdirectory.php:82 -msgid "Site Directory" -msgstr "Director Site" - -#: forumdirectory.php:83 -msgid "Find" -msgstr "Căutați" - -#: forumdirectory.php:133 -msgid "Age: " -msgstr "Vârsta:" - -#: forumdirectory.php:136 -msgid "Gender: " -msgstr "Sex:" - -#: forumdirectory.php:156 -msgid "Location:" -msgstr "Locație:" - -#: forumdirectory.php:158 -msgid "Gender:" -msgstr "Sex:" - -#: forumdirectory.php:160 -msgid "Status:" -msgstr "Status:" - -#: forumdirectory.php:162 -msgid "Homepage:" -msgstr "Pagină web:" - -#: forumdirectory.php:164 -msgid "About:" -msgstr "Despre:" - -#: forumdirectory.php:201 -msgid "No entries (some entries may be hidden)." -msgstr "Fără înregistrări (unele înregistrări pot fi ascunse)." diff --git a/groupdirectory/lang/ro/strings.php b/groupdirectory/lang/ro/strings.php deleted file mode 100644 index 750fe1e1..00000000 --- a/groupdirectory/lang/ro/strings.php +++ /dev/null @@ -1,22 +0,0 @@ -19)||(($n%100==0)&&($n!=0)))) { return 2; } else { return 1; } -}} -$a->strings['Forum Directory'] = 'Director Forum'; -$a->strings['Public access denied.'] = 'Acces public refuzat.'; -$a->strings['Global Directory'] = 'Director Global'; -$a->strings['Find on this site'] = 'Căutați pe acest site'; -$a->strings['Finding: '] = 'Căutare:'; -$a->strings['Site Directory'] = 'Director Site'; -$a->strings['Find'] = 'Căutați'; -$a->strings['Age: '] = 'Vârsta:'; -$a->strings['Gender: '] = 'Sex:'; -$a->strings['Location:'] = 'Locație:'; -$a->strings['Gender:'] = 'Sex:'; -$a->strings['Status:'] = 'Status:'; -$a->strings['Homepage:'] = 'Pagină web:'; -$a->strings['About:'] = 'Despre:'; -$a->strings['No entries (some entries may be hidden).'] = 'Fără înregistrări (unele înregistrări pot fi ascunse).'; diff --git a/groupdirectory/lang/ru/messages.po b/groupdirectory/lang/ru/messages.po deleted file mode 100644 index 48250ba6..00000000 --- a/groupdirectory/lang/ru/messages.po +++ /dev/null @@ -1,80 +0,0 @@ -# ADDON forumdirectory -# Copyright (C) -# This file is distributed under the same license as the Friendica forumdirectory addon package. -# -# -# Translators: -# Stanislav N. , 2017 -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 17:12+0000\n" -"Last-Translator: Stanislav N. \n" -"Language-Team: Russian (http://www.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" - -#: forumdirectory.php:22 -msgid "Forum Directory" -msgstr "Каталог форумов" - -#: forumdirectory.php:53 -msgid "Public access denied." -msgstr "Свободный доступ закрыт." - -#: forumdirectory.php:71 -msgid "Global Directory" -msgstr "Глобальный каталог" - -#: forumdirectory.php:79 -msgid "Find on this site" -msgstr "Найти на этом сайте" - -#: forumdirectory.php:81 -msgid "Finding: " -msgstr "Результат поиска: " - -#: forumdirectory.php:82 -msgid "Site Directory" -msgstr "Каталог сайта" - -#: forumdirectory.php:83 -msgid "Find" -msgstr "Найти" - -#: forumdirectory.php:133 -msgid "Age: " -msgstr "Возраст: " - -#: forumdirectory.php:136 -msgid "Gender: " -msgstr "Пол: " - -#: forumdirectory.php:156 -msgid "Location:" -msgstr "Откуда:" - -#: forumdirectory.php:158 -msgid "Gender:" -msgstr "Пол:" - -#: forumdirectory.php:160 -msgid "Status:" -msgstr "Статус:" - -#: forumdirectory.php:162 -msgid "Homepage:" -msgstr "Домашняя страничка:" - -#: forumdirectory.php:164 -msgid "About:" -msgstr "О себе:" - -#: forumdirectory.php:201 -msgid "No entries (some entries may be hidden)." -msgstr "Нет записей (некоторые записи могут быть скрыты)." diff --git a/groupdirectory/lang/ru/strings.php b/groupdirectory/lang/ru/strings.php deleted file mode 100644 index 54954d72..00000000 --- a/groupdirectory/lang/ru/strings.php +++ /dev/null @@ -1,22 +0,0 @@ -=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['Forum Directory'] = 'Каталог форумов'; -$a->strings['Public access denied.'] = 'Свободный доступ закрыт.'; -$a->strings['Global Directory'] = 'Глобальный каталог'; -$a->strings['Find on this site'] = 'Найти на этом сайте'; -$a->strings['Finding: '] = 'Результат поиска: '; -$a->strings['Site Directory'] = 'Каталог сайта'; -$a->strings['Find'] = 'Найти'; -$a->strings['Age: '] = 'Возраст: '; -$a->strings['Gender: '] = 'Пол: '; -$a->strings['Location:'] = 'Откуда:'; -$a->strings['Gender:'] = 'Пол:'; -$a->strings['Status:'] = 'Статус:'; -$a->strings['Homepage:'] = 'Домашняя страничка:'; -$a->strings['About:'] = 'О себе:'; -$a->strings['No entries (some entries may be hidden).'] = 'Нет записей (некоторые записи могут быть скрыты).'; diff --git a/groupdirectory/lang/sv/messages.po b/groupdirectory/lang/sv/messages.po deleted file mode 100644 index cf3ebfde..00000000 --- a/groupdirectory/lang/sv/messages.po +++ /dev/null @@ -1,49 +0,0 @@ -# ADDON forumdirectory -# Copyright (C) -# This file is distributed under the same license as the Friendica forumdirectory addon package. -# -# -# Translators: -# Hypolite Petovan , 2019 -# Kristoffer Grundström , 2022 -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-15 23:39+0000\n" -"Last-Translator: Kristoffer Grundström \n" -"Language-Team: Swedish (http://www.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" - -#: forumdirectory.php:33 forumdirectory.php:137 -msgid "Forum Directory" -msgstr "Forum-mapp" - -#: forumdirectory.php:53 -msgid "Public access denied." -msgstr "Publik åtkomst nekades." - -#: forumdirectory.php:125 -msgid "No entries (some entries may be hidden)." -msgstr "Inget att visa. (Man kan välja att inte synas här)" - -#: forumdirectory.php:131 -msgid "Global Directory" -msgstr "Medlemskatalog för flera sajter (global)" - -#: forumdirectory.php:133 -msgid "Find on this site" -msgstr "Hitta på den här sidan" - -#: forumdirectory.php:135 -msgid "Results for:" -msgstr "" - -#: forumdirectory.php:139 -msgid "Find" -msgstr "Sök" diff --git a/groupdirectory/lang/sv/strings.php b/groupdirectory/lang/sv/strings.php deleted file mode 100644 index 0f06eaa3..00000000 --- a/groupdirectory/lang/sv/strings.php +++ /dev/null @@ -1,13 +0,0 @@ -strings['Forum Directory'] = 'Forum-mapp'; -$a->strings['Public access denied.'] = 'Publik åtkomst nekades.'; -$a->strings['No entries (some entries may be hidden).'] = 'Inget att visa. (Man kan välja att inte synas här)'; -$a->strings['Global Directory'] = 'Medlemskatalog för flera sajter (global)'; -$a->strings['Find on this site'] = 'Hitta på den här sidan'; -$a->strings['Find'] = 'Sök'; diff --git a/groupdirectory/lang/zh-cn/strings.php b/groupdirectory/lang/zh-cn/strings.php deleted file mode 100644 index 4b5c78ba..00000000 --- a/groupdirectory/lang/zh-cn/strings.php +++ /dev/null @@ -1,17 +0,0 @@ -strings["Forum Directory"] = "评坛目录"; -$a->strings["Public access denied."] = "公众看拒绝"; -$a->strings["Global Directory"] = "综合目录"; -$a->strings["Find on this site"] = "找在这网站"; -$a->strings["Finding: "] = "找着:"; -$a->strings["Site Directory"] = "网站目录"; -$a->strings["Find"] = "搜索"; -$a->strings["Age: "] = "年纪:"; -$a->strings["Gender: "] = "性别:"; -$a->strings["Location:"] = "位置:"; -$a->strings["Gender:"] = "性别:"; -$a->strings["Status:"] = "现状:"; -$a->strings["Homepage:"] = "主页:"; -$a->strings["About:"] = "关于:"; -$a->strings["No entries (some entries may be hidden)."] = "没有文章(有的文章会被隐藏)。"; diff --git a/ifttt/ifttt.php b/ifttt/ifttt.php index 6d4f402c..d0606fac 100644 --- a/ifttt/ifttt.php +++ b/ifttt/ifttt.php @@ -55,7 +55,7 @@ function ifttt_settings(array &$data) 'new_photo_upload_body' => DI::l10n()->t('Body for "new photo upload"'), 'new_link_post_body' => DI::l10n()->t('Body for "new link post"'), ], - '$url' => DI::baseUrl() . '/ifttt/' . DI::userSession()->getLocalUserNickname(), + '$url' => DI::baseUrl()->get() . '/ifttt/' . DI::userSession()->getLocalUserNickname(), '$new_status_message_body' => 'key=' . $key . '&type=status&msg=<<<{{Message}}>>>&date=<<<{{UpdatedAt}}>>>&url=<<<{{PageUrl}}>>>', '$new_photo_upload_body' => 'key=' . $key . '&type=photo&link=<<<{{Link}}>>>&image=<<<{{ImageSource}}>>>&msg=<<<{{Caption}}>>>&date=<<<{{CreatedAt}}>>>&url=<<<{{PageUrl}}>>>', '$new_link_post_body' => 'key=' . $key . '&type=link&link=<<<{{Link}}>>>&title=<<<{{Title}}>>>&msg=<<<{{Message}}>>>&description=<<<{{Description}}>>>&date=<<<{{CreatedAt}}>>>&url=<<<{{PageUrl}}>>>', diff --git a/ifttt/lang/de/messages.po b/ifttt/lang/de/messages.po index b36f4112..1a7e1222 100644 --- a/ifttt/lang/de/messages.po +++ b/ifttt/lang/de/messages.po @@ -16,7 +16,7 @@ msgstr "" "POT-Creation-Date: 2021-11-21 19:17-0500\n" "PO-Revision-Date: 2017-11-27 10:37+0000\n" "Last-Translator: Tobias Diekershoff , 2022\n" -"Language-Team: German (https://app.transifex.com/Friendica/teams/12172/de/)\n" +"Language-Team: German (https://www.transifex.com/Friendica/teams/12172/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/ijpost/lang/de/messages.po b/ijpost/lang/de/messages.po index 8dac5676..fef0eddc 100644 --- a/ijpost/lang/de/messages.po +++ b/ijpost/lang/de/messages.po @@ -13,9 +13,9 @@ msgstr "" "Project-Id-Version: friendica\n" "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: Tobias Diekershoff , 2018,2021\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2021-12-22 16:19+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/impressum/impressum.php b/impressum/impressum.php index 754cb828..f2564a50 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\Model\User; +use Friendica\Util\Proxy as ProxyUtils; function impressum_install() { @@ -45,10 +45,10 @@ function obfuscate_email (string $s): string function impressum_footer(string &$body) { - $text = BBCode::convertForUriId(User::getSystemUriId(), DI::config()->get('impressum', 'footer_text')); + $text = ProxyUtils::proxifyHtml(BBCode::convert(DI::config()->get('impressum', 'footer_text'))); if ($text != '') { - DI::page()['htmlhead'] .= ''; + DI::page()['htmlhead'] .= ''; $body .= '
'; $body .= ''; } @@ -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 = BBCode::convertForUriId(User::getSystemUriId(), DI::config()->get('impressum', 'postal')); - $notes = BBCode::convertForUriId(User::getSystemUriId(), DI::config()->get('impressum', 'notes')); + $postal = ProxyUtils::proxifyHtml(BBCode::convert(DI::config()->get('impressum', 'postal'))); + $notes = ProxyUtils::proxifyHtml(BBCode::convert(DI::config()->get('impressum', 'notes'))); if ($owner) { if ($owner_profile) { diff --git a/impressum/lang/de/messages.po b/impressum/lang/de/messages.po index 9a51a73d..745504b4 100644 --- a/impressum/lang/de/messages.po +++ b/impressum/lang/de/messages.po @@ -13,9 +13,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-02-01 18:15+0100\n" -"PO-Revision-Date: 2014-06-23 08:39+0000\n" -"Last-Translator: Tobias Diekershoff , 2021\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2021-03-29 05:29+0000\n" +"Last-Translator: Tobias Diekershoff \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/infiniteimprobabilitydrive/infiniteimprobabilitydrive.php b/infiniteimprobabilitydrive/infiniteimprobabilitydrive.php index aff7aec0..b602d4ad 100644 --- a/infiniteimprobabilitydrive/infiniteimprobabilitydrive.php +++ b/infiniteimprobabilitydrive/infiniteimprobabilitydrive.php @@ -30,12 +30,13 @@ function infiniteimprobabilitydrive_module() {} function infiniteimprobabilitydrive_content() { + $baseurl = DI::baseUrl()->get() . '/addon/infiniteimprobabilitydrive'; $o = ''; - DI::page()['htmlhead'] .= ''; + DI::page()['htmlhead'] .= ''; - $baseurl = (string)DI::baseUrl(); + $baseurl = DI::baseUrl()->get(); $o .= <<< EOT diff --git a/infiniteimprobabilitydrive/lang/cs/messages.po b/infiniteimprobabilitydrive/lang/cs/messages.po index be0f3ddd..e264d190 100644 --- a/infiniteimprobabilitydrive/lang/cs/messages.po +++ b/infiniteimprobabilitydrive/lang/cs/messages.po @@ -4,21 +4,21 @@ # # # Translators: -# michal_s , 2014 +# Michal Šupler , 2014 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: 2014-06-23 08:41+0000\n" -"Last-Translator: michal_s , 2014\n" -"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" +"POT-Creation-Date: 2014-06-22 13:18+0200\n" +"PO-Revision-Date: 2014-07-07 19:12+0000\n" +"Last-Translator: Michal Šupler \n" +"Language-Team: Czech (http://www.transifex.com/projects/p/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" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -#: infiniteimprobabilitydrive.php:18 +#: infiniteimprobabilitydrive.php:19 msgid "Infinite Improbability Drive" msgstr "Infinite Improbability Drive" diff --git a/infiniteimprobabilitydrive/lang/cs/strings.php b/infiniteimprobabilitydrive/lang/cs/strings.php index 72422ae6..348eaff3 100644 --- a/infiniteimprobabilitydrive/lang/cs/strings.php +++ b/infiniteimprobabilitydrive/lang/cs/strings.php @@ -3,6 +3,6 @@ if(! function_exists("string_plural_select_cs")) { function string_plural_select_cs($n){ $n = intval($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; } + if (($n==1)) { return 0; } else if (($n>=2 && $n<=4)) { return 1; } else { return 2; } }} $a->strings['Infinite Improbability Drive'] = 'Infinite Improbability Drive'; diff --git a/infiniteimprobabilitydrive/lang/de/messages.po b/infiniteimprobabilitydrive/lang/de/messages.po index 3fc09443..e9ecccb5 100644 --- a/infiniteimprobabilitydrive/lang/de/messages.po +++ b/infiniteimprobabilitydrive/lang/de/messages.po @@ -4,21 +4,21 @@ # # # Translators: -# Tobias Diekershoff , 2014 +# bavatar , 2014 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: 2014-06-23 08:41+0000\n" -"Last-Translator: Tobias Diekershoff , 2014\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"POT-Creation-Date: 2014-06-22 13:18+0200\n" +"PO-Revision-Date: 2014-07-06 12:15+0000\n" +"Last-Translator: bavatar \n" +"Language-Team: German (http://www.transifex.com/projects/p/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: infiniteimprobabilitydrive.php:18 +#: infiniteimprobabilitydrive.php:19 msgid "Infinite Improbability Drive" msgstr "Infinite Improbability Drive" diff --git a/infiniteimprobabilitydrive/lang/it/messages.po b/infiniteimprobabilitydrive/lang/it/messages.po index 41110b5a..be86c98b 100644 --- a/infiniteimprobabilitydrive/lang/it/messages.po +++ b/infiniteimprobabilitydrive/lang/it/messages.po @@ -9,16 +9,16 @@ 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: 2014-06-23 08:41+0000\n" -"Last-Translator: fabrixxm , 2014\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"POT-Creation-Date: 2013-02-27 05:01-0500\n" +"PO-Revision-Date: 2017-09-20 06:08+0000\n" +"Last-Translator: fabrixxm \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: infiniteimprobabilitydrive.php:18 +#: infiniteimprobabilitydrive.php:19 msgid "Infinite Improbability Drive" msgstr "Motore ad Improbabilità Infinita" diff --git a/infiniteimprobabilitydrive/lang/it/strings.php b/infiniteimprobabilitydrive/lang/it/strings.php index fc7dda5c..d43da316 100644 --- a/infiniteimprobabilitydrive/lang/it/strings.php +++ b/infiniteimprobabilitydrive/lang/it/strings.php @@ -3,6 +3,6 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $a->strings['Infinite Improbability Drive'] = 'Motore ad Improbabilità Infinita'; diff --git a/invidious/README.md b/invidious/README.md deleted file mode 100644 index 0f91fa02..00000000 --- a/invidious/README.md +++ /dev/null @@ -1,4 +0,0 @@ -invidious Addon for Friendica -========================== - -This addon will replace "youtube.com" with the chosen Invidious instance diff --git a/invidious/invidious.php b/invidious/invidious.php deleted file mode 100644 index ec16b4dc..00000000 --- a/invidious/invidious.php +++ /dev/null @@ -1,103 +0,0 @@ - - * Author: Michael Vogel - * - */ - -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', __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', trim($_POST['invidiousserver'], " \n\r\t\v\x00/")); -} - -/* 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', 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) -{ - 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) -{ - 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']); - - 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 deleted file mode 100644 index b9de496c..00000000 --- a/invidious/lang/C/messages.po +++ /dev/null @@ -1,58 +0,0 @@ -# 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-18 17:23+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" - -#: invidious.php:39 -#, 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:40 invidious.php:57 -msgid "Invidious server" -msgstr "" - -#: 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: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/admin.tpl b/invidious/templates/admin.tpl deleted file mode 100644 index 1db85ff9..00000000 --- a/invidious/templates/admin.tpl +++ /dev/null @@ -1,5 +0,0 @@ -

{{$settingdescription}}

- -{{include file="field_input.tpl" field=$invidiousserver}} - -
diff --git a/invidious/templates/settings.tpl b/invidious/templates/settings.tpl deleted file mode 100644 index 387286ef..00000000 --- a/invidious/templates/settings.tpl +++ /dev/null @@ -1,2 +0,0 @@ -{{include file="field_checkbox.tpl" field=$enabled}} -{{include file="field_input.tpl" field=$server}} diff --git a/irc/irc.php b/irc/irc.php index d4435851..8bd05fb7 100644 --- a/irc/irc.php +++ b/irc/irc.php @@ -73,7 +73,7 @@ function irc_module() {} function irc_content() { - $baseurl = DI::baseUrl() . '/addon/irc'; + $baseurl = DI::baseUrl()->get() . '/addon/irc'; $o = ''; /* set the list of popular channels */ @@ -95,7 +95,7 @@ function irc_content() DI::page()['aside'] .= '

' . DI::l10n()->t('Popular Channels') . '

'; diff --git a/irc/lang/cs/messages.po b/irc/lang/cs/messages.po index 8f25d7ed..29d5fcea 100644 --- a/irc/lang/cs/messages.po +++ b/irc/lang/cs/messages.po @@ -11,55 +11,59 @@ 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: 2014-06-23 08:41+0000\n" -"Last-Translator: Aditoo, 2018\n" -"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" +"POT-Creation-Date: 2015-07-08 13:17+0200\n" +"PO-Revision-Date: 2018-06-14 14:36+0000\n" +"Last-Translator: Aditoo\n" +"Language-Team: Czech (http://www.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" -#: irc.php:32 +#: irc.php:37 +msgid "IRC Settings" +msgstr "Nastavení IRC" + +#: irc.php:38 msgid "" "Here you can change the system wide settings for the channels to " "automatically join and access via the side bar. Note the changes you do " "here, only effect the channel selection if you are logged in." -msgstr "Zde můžete změnit systémová nastavení pro kanály pro automatické spojení a přístup přes postranní lištu. Mějte na paměti, že změny, které zde provedete, ovlivní výběr kanálů pouze, pokud jste přihlášen/a." +msgstr "" -#: irc.php:33 irc.php:133 +#: irc.php:39 irc.php:136 +msgid "Save Settings" +msgstr "Uložit nastavení" + +#: irc.php:40 irc.php:137 msgid "Channel(s) to auto connect (comma separated)" msgstr "Kanál(y) pro automatické připojení (oddělené čárkami)" -#: irc.php:33 irc.php:133 +#: irc.php:40 irc.php:137 msgid "" "List of channels that shall automatically connected to when the app is " "launched." msgstr "Seznam kanálů, které budou při spuštění aplikace automaticky připojeny." -#: irc.php:34 irc.php:134 +#: irc.php:41 irc.php:138 msgid "Popular Channels (comma separated)" msgstr "Populární kanály (oddělené čárkami)" -#: irc.php:34 irc.php:134 +#: irc.php:41 irc.php:138 msgid "" "List of popular channels, will be displayed at the side and hotlinked for " "easy joining." msgstr "Seznam populárních kanálů, bude zobrazen na straně a bude obsahovat odkazy pro snadné připojení." -#: irc.php:39 -msgid "IRC Settings" -msgstr "Nastavení IRC" +#: irc.php:57 irc.php:128 +msgid "IRC settings saved." +msgstr "IRC Nastavení uloženo." -#: irc.php:60 +#: irc.php:62 msgid "IRC Chatroom" msgstr "IRC Místnost" -#: irc.php:88 +#: irc.php:90 msgid "Popular Channels" msgstr "Populární kanály" - -#: irc.php:132 -msgid "Save Settings" -msgstr "Uložit nastavení" diff --git a/irc/lang/cs/strings.php b/irc/lang/cs/strings.php index 6c6d5aea..89431a1c 100644 --- a/irc/lang/cs/strings.php +++ b/irc/lang/cs/strings.php @@ -5,12 +5,12 @@ function string_plural_select_cs($n){ $n = intval($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['Here you can change the system wide settings for the channels to automatically join and access via the side bar. Note the changes you do here, only effect the channel selection if you are logged in.'] = 'Zde můžete změnit systémová nastavení pro kanály pro automatické spojení a přístup přes postranní lištu. Mějte na paměti, že změny, které zde provedete, ovlivní výběr kanálů pouze, pokud jste přihlášen/a.'; +$a->strings['IRC Settings'] = 'Nastavení IRC'; +$a->strings['Save Settings'] = 'Uložit nastavení'; $a->strings['Channel(s) to auto connect (comma separated)'] = 'Kanál(y) pro automatické připojení (oddělené čárkami)'; $a->strings['List of channels that shall automatically connected to when the app is launched.'] = 'Seznam kanálů, které budou při spuštění aplikace automaticky připojeny.'; $a->strings['Popular Channels (comma separated)'] = 'Populární kanály (oddělené čárkami)'; $a->strings['List of popular channels, will be displayed at the side and hotlinked for easy joining.'] = 'Seznam populárních kanálů, bude zobrazen na straně a bude obsahovat odkazy pro snadné připojení.'; -$a->strings['IRC Settings'] = 'Nastavení IRC'; +$a->strings['IRC settings saved.'] = 'IRC Nastavení uloženo.'; $a->strings['IRC Chatroom'] = 'IRC Místnost'; $a->strings['Popular Channels'] = 'Populární kanály'; -$a->strings['Save Settings'] = 'Uložit nastavení'; diff --git a/irc/lang/de/messages.po b/irc/lang/de/messages.po index 84c95f4a..4b47999b 100644 --- a/irc/lang/de/messages.po +++ b/irc/lang/de/messages.po @@ -12,9 +12,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:14-0500\n" -"PO-Revision-Date: 2014-06-23 08:41+0000\n" -"Last-Translator: Ulf Rompe , 2019\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2021-02-01 18:19+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/irc/lang/it/messages.po b/irc/lang/it/messages.po index 8144342b..bbd199b8 100644 --- a/irc/lang/it/messages.po +++ b/irc/lang/it/messages.po @@ -10,55 +10,59 @@ 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: 2014-06-23 08:41+0000\n" -"Last-Translator: Sylke Vicious , 2020\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"POT-Creation-Date: 2015-07-08 13:17+0200\n" +"PO-Revision-Date: 2020-09-17 11:40+0000\n" +"Last-Translator: Sylke Vicious \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: irc.php:32 +#: irc.php:37 +msgid "IRC Settings" +msgstr "Impostazioni IRC" + +#: irc.php:38 msgid "" "Here you can change the system wide settings for the channels to " "automatically join and access via the side bar. Note the changes you do " "here, only effect the channel selection if you are logged in." msgstr "Qui puoi modificare le impostazioni globali di sistema per i canali a cui accedere automaticamente attraverso la barra laterale. Nota che le modifiche che effetti qui hanno effetto sulla selezione di canali solo se sei loggato." -#: irc.php:33 irc.php:133 +#: irc.php:39 irc.php:136 +msgid "Save Settings" +msgstr "Salva Impostazioni" + +#: irc.php:40 irc.php:137 msgid "Channel(s) to auto connect (comma separated)" msgstr "Canale(i) a cui autocollegarsi (separati da virgola)" -#: irc.php:33 irc.php:133 +#: irc.php:40 irc.php:137 msgid "" "List of channels that shall automatically connected to when the app is " "launched." msgstr "Lista di canali che a cui connettersi automaticamente quando l'app è avviata." -#: irc.php:34 irc.php:134 +#: irc.php:41 irc.php:138 msgid "Popular Channels (comma separated)" msgstr "Canali popolari (separati da virgola)" -#: irc.php:34 irc.php:134 +#: irc.php:41 irc.php:138 msgid "" "List of popular channels, will be displayed at the side and hotlinked for " "easy joining." msgstr "Lista di canali popolari: sarà visualizzata a lato e provvista di collegamento per facilitare l'adesione." -#: irc.php:39 -msgid "IRC Settings" -msgstr "Impostazioni IRC" +#: irc.php:57 irc.php:128 +msgid "IRC settings saved." +msgstr "Impostazioni IRC salvate." -#: irc.php:60 +#: irc.php:62 msgid "IRC Chatroom" msgstr "Stanza IRC" -#: irc.php:88 +#: irc.php:90 msgid "Popular Channels" msgstr "Canali Popolari" - -#: irc.php:132 -msgid "Save Settings" -msgstr "Salva Impostazioni" diff --git a/irc/lang/it/strings.php b/irc/lang/it/strings.php index 09aafe6e..42cf7c0d 100644 --- a/irc/lang/it/strings.php +++ b/irc/lang/it/strings.php @@ -3,14 +3,15 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} +$a->strings['IRC Settings'] = 'Impostazioni IRC'; $a->strings['Here you can change the system wide settings for the channels to automatically join and access via the side bar. Note the changes you do here, only effect the channel selection if you are logged in.'] = 'Qui puoi modificare le impostazioni globali di sistema per i canali a cui accedere automaticamente attraverso la barra laterale. Nota che le modifiche che effetti qui hanno effetto sulla selezione di canali solo se sei loggato.'; +$a->strings['Save Settings'] = 'Salva Impostazioni'; $a->strings['Channel(s) to auto connect (comma separated)'] = 'Canale(i) a cui autocollegarsi (separati da virgola)'; $a->strings['List of channels that shall automatically connected to when the app is launched.'] = 'Lista di canali che a cui connettersi automaticamente quando l\'app è avviata.'; $a->strings['Popular Channels (comma separated)'] = 'Canali popolari (separati da virgola)'; $a->strings['List of popular channels, will be displayed at the side and hotlinked for easy joining.'] = 'Lista di canali popolari: sarà visualizzata a lato e provvista di collegamento per facilitare l\'adesione.'; -$a->strings['IRC Settings'] = 'Impostazioni IRC'; +$a->strings['IRC settings saved.'] = 'Impostazioni IRC salvate.'; $a->strings['IRC Chatroom'] = 'Stanza IRC'; $a->strings['Popular Channels'] = 'Canali Popolari'; -$a->strings['Save Settings'] = 'Salva Impostazioni'; diff --git a/js_upload/lang/C/messages.po b/js_upload/lang/C/messages.po index 0d607bd5..4d16fe17 100644 --- a/js_upload/lang/C/messages.po +++ b/js_upload/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:49-0400\n" +"POT-Creation-Date: 2021-03-23 23:53-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,40 +17,40 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: js_upload.php:37 +#: js_upload.php:34 msgid "Select files for upload" msgstr "" -#: js_upload.php:38 +#: js_upload.php:35 msgid "Drop files here to upload" msgstr "" -#: js_upload.php:39 +#: js_upload.php:36 msgid "Cancel" msgstr "" -#: js_upload.php:40 +#: js_upload.php:37 msgid "Failed" msgstr "" -#: js_upload.php:209 +#: js_upload.php:215 msgid "No files were uploaded." msgstr "" -#: js_upload.php:215 +#: js_upload.php:221 msgid "Uploaded file is empty" msgstr "" -#: js_upload.php:227 +#: js_upload.php:233 #, php-format msgid "Image exceeds size limit of %s" msgstr "" -#: js_upload.php:239 +#: js_upload.php:245 #, php-format msgid "File has an invalid extension, it should be one of %s." msgstr "" -#: js_upload.php:250 +#: js_upload.php:256 msgid "Upload was cancelled, or server error encountered" msgstr "" diff --git a/js_upload/lang/cs/messages.po b/js_upload/lang/cs/messages.po index 1241523f..731d165c 100644 --- a/js_upload/lang/cs/messages.po +++ b/js_upload/lang/cs/messages.po @@ -4,56 +4,53 @@ # # # Translators: -# Aditoo, 2018 -# michal_s , 2014 +# Michal Šupler , 2014 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-03-23 23:53-0400\n" -"PO-Revision-Date: 2014-06-23 08:46+0000\n" -"Last-Translator: Aditoo, 2018\n" -"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" +"POT-Creation-Date: 2013-02-27 05:01-0500\n" +"PO-Revision-Date: 2014-07-07 19:13+0000\n" +"Last-Translator: Michal Šupler \n" +"Language-Team: Czech (http://www.transifex.com/projects/p/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" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -#: js_upload.php:34 -msgid "Select files for upload" -msgstr "" +#: js_upload.php:43 +msgid "Upload a file" +msgstr "Nahrát soubor" -#: js_upload.php:35 +#: js_upload.php:44 msgid "Drop files here to upload" -msgstr "Přetáhněte sem soubory k nahrání" +msgstr "Přeneste sem soubory k nahrání" -#: js_upload.php:36 +#: js_upload.php:45 msgid "Cancel" msgstr "Zrušit" -#: js_upload.php:37 +#: js_upload.php:46 msgid "Failed" msgstr "Neúspěch" -#: js_upload.php:215 +#: js_upload.php:303 msgid "No files were uploaded." msgstr "Žádné soubory nebyly nahrány." -#: js_upload.php:221 +#: js_upload.php:309 msgid "Uploaded file is empty" msgstr "Nahraný soubor je prázdný" -#: js_upload.php:233 -#, php-format -msgid "Image exceeds size limit of %s" -msgstr "" +#: js_upload.php:321 +msgid "Image exceeds size limit of " +msgstr "Velikost obrázku překračuje limit velikosti" -#: js_upload.php:245 -#, php-format -msgid "File has an invalid extension, it should be one of %s." -msgstr "" +#: js_upload.php:332 +msgid "File has an invalid extension, it should be one of " +msgstr "Soubor má neplatnou příponu, ta by měla být jednou z" -#: js_upload.php:256 +#: js_upload.php:343 msgid "Upload was cancelled, or server error encountered" msgstr "Nahrávání bylo zrušeno nebo došlo k chybě na serveru" diff --git a/js_upload/lang/cs/strings.php b/js_upload/lang/cs/strings.php index 55ec72a2..e03aceb0 100644 --- a/js_upload/lang/cs/strings.php +++ b/js_upload/lang/cs/strings.php @@ -3,11 +3,14 @@ if(! function_exists("string_plural_select_cs")) { function string_plural_select_cs($n){ $n = intval($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; } + if (($n==1)) { return 0; } else if (($n>=2 && $n<=4)) { return 1; } else { return 2; } }} -$a->strings['Drop files here to upload'] = 'Přetáhněte sem soubory k nahrání'; +$a->strings['Upload a file'] = 'Nahrát soubor'; +$a->strings['Drop files here to upload'] = 'Přeneste sem soubory k nahrání'; $a->strings['Cancel'] = 'Zrušit'; $a->strings['Failed'] = 'Neúspěch'; $a->strings['No files were uploaded.'] = 'Žádné soubory nebyly nahrány.'; $a->strings['Uploaded file is empty'] = 'Nahraný soubor je prázdný'; +$a->strings['Image exceeds size limit of '] = 'Velikost obrázku překračuje limit velikosti'; +$a->strings['File has an invalid extension, it should be one of '] = 'Soubor má neplatnou příponu, ta by měla být jednou z'; $a->strings['Upload was cancelled, or server error encountered'] = 'Nahrávání bylo zrušeno nebo došlo k chybě na serveru'; diff --git a/js_upload/lang/de/messages.po b/js_upload/lang/de/messages.po index 010704c5..6cbf8445 100644 --- a/js_upload/lang/de/messages.po +++ b/js_upload/lang/de/messages.po @@ -12,9 +12,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-03-23 23:53-0400\n" -"PO-Revision-Date: 2014-06-23 08:46+0000\n" -"Last-Translator: Tobias Diekershoff , 2021\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2021-12-05 08:34+0000\n" +"Last-Translator: Tobias Diekershoff \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/js_upload/lang/es/messages.po b/js_upload/lang/es/messages.po index a105d93e..0b737806 100644 --- a/js_upload/lang/es/messages.po +++ b/js_upload/lang/es/messages.po @@ -5,55 +5,52 @@ # # Translators: # Albert, 2016 -# Senex Petrovic , 2021 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-03-23 23:53-0400\n" -"PO-Revision-Date: 2014-06-23 08:46+0000\n" -"Last-Translator: Senex Petrovic , 2021\n" -"Language-Team: Spanish (http://app.transifex.com/Friendica/friendica/language/es/)\n" +"POT-Creation-Date: 2013-02-27 05:01-0500\n" +"PO-Revision-Date: 2016-11-17 18:59+0000\n" +"Last-Translator: Albert\n" +"Language-Team: Spanish (http://www.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=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: js_upload.php:34 -msgid "Select files for upload" -msgstr "Seleciona archivos a subir" +#: js_upload.php:43 +msgid "Upload a file" +msgstr "Subir un archivo" -#: js_upload.php:35 +#: js_upload.php:44 msgid "Drop files here to upload" msgstr "Soltar archivos aquí para subir" -#: js_upload.php:36 +#: js_upload.php:45 msgid "Cancel" msgstr "Cancelar" -#: js_upload.php:37 +#: js_upload.php:46 msgid "Failed" msgstr "Fallido" -#: js_upload.php:215 +#: js_upload.php:303 msgid "No files were uploaded." msgstr "No se subió ningún archivo." -#: js_upload.php:221 +#: js_upload.php:309 msgid "Uploaded file is empty" msgstr "El archivo subido está vacío" -#: js_upload.php:233 -#, php-format -msgid "Image exceeds size limit of %s" -msgstr "" +#: js_upload.php:321 +msgid "Image exceeds size limit of " +msgstr "La imagen excede el tamaño de" -#: js_upload.php:245 -#, php-format -msgid "File has an invalid extension, it should be one of %s." -msgstr "" +#: js_upload.php:332 +msgid "File has an invalid extension, it should be one of " +msgstr "El archivo tiene una extensión inválida, debería ser una de" -#: js_upload.php:256 +#: js_upload.php:343 msgid "Upload was cancelled, or server error encountered" msgstr "La subida fue cancelada, o el servidor tuvo un error" diff --git a/js_upload/lang/es/strings.php b/js_upload/lang/es/strings.php index 4c0dc66b..e15c1149 100644 --- a/js_upload/lang/es/strings.php +++ b/js_upload/lang/es/strings.php @@ -3,12 +3,14 @@ if(! function_exists("string_plural_select_es")) { function string_plural_select_es($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} -$a->strings['Select files for upload'] = 'Seleciona archivos a subir'; +$a->strings['Upload a file'] = 'Subir un archivo'; $a->strings['Drop files here to upload'] = 'Soltar archivos aquí para subir'; $a->strings['Cancel'] = 'Cancelar'; $a->strings['Failed'] = 'Fallido'; $a->strings['No files were uploaded.'] = 'No se subió ningún archivo.'; $a->strings['Uploaded file is empty'] = 'El archivo subido está vacío'; +$a->strings['Image exceeds size limit of '] = 'La imagen excede el tamaño de'; +$a->strings['File has an invalid extension, it should be one of '] = 'El archivo tiene una extensión inválida, debería ser una de'; $a->strings['Upload was cancelled, or server error encountered'] = 'La subida fue cancelada, o el servidor tuvo un error'; diff --git a/js_upload/lang/it/messages.po b/js_upload/lang/it/messages.po index 172ee90d..271057cb 100644 --- a/js_upload/lang/it/messages.po +++ b/js_upload/lang/it/messages.po @@ -11,14 +11,14 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-03-23 23:53-0400\n" -"PO-Revision-Date: 2014-06-23 08:46+0000\n" -"Last-Translator: Sylke Vicious , 2021\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"PO-Revision-Date: 2021-05-05 10:50+0000\n" +"Last-Translator: Sylke Vicious \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: js_upload.php:34 msgid "Select files for upload" diff --git a/js_upload/lang/it/strings.php b/js_upload/lang/it/strings.php index 5c961761..f2ebfe0b 100644 --- a/js_upload/lang/it/strings.php +++ b/js_upload/lang/it/strings.php @@ -3,7 +3,7 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $a->strings['Select files for upload'] = 'Seleziona file per il caricamento'; $a->strings['Drop files here to upload'] = 'Trascina un file qui per caricarlo'; diff --git a/js_upload/lang/nl/messages.po b/js_upload/lang/nl/messages.po index 8b3179ff..713ba3a2 100644 --- a/js_upload/lang/nl/messages.po +++ b/js_upload/lang/nl/messages.po @@ -5,55 +5,52 @@ # # Translators: # Jeroen De Meerleer , 2018 -# Ruud Schilders , 2020 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-03-23 23:53-0400\n" -"PO-Revision-Date: 2014-06-23 08:46+0000\n" -"Last-Translator: Ruud Schilders , 2020\n" -"Language-Team: Dutch (http://app.transifex.com/Friendica/friendica/language/nl/)\n" +"POT-Creation-Date: 2013-02-27 05:01-0500\n" +"PO-Revision-Date: 2018-08-24 11:48+0000\n" +"Last-Translator: Jeroen De Meerleer \n" +"Language-Team: Dutch (http://www.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" -#: js_upload.php:34 -msgid "Select files for upload" -msgstr "" +#: js_upload.php:43 +msgid "Upload a file" +msgstr "Upload een bestand" -#: js_upload.php:35 +#: js_upload.php:44 msgid "Drop files here to upload" msgstr "Sleep uw bestanden hier om ze te uploaden" -#: js_upload.php:36 +#: js_upload.php:45 msgid "Cancel" -msgstr "Afbreken" +msgstr "" -#: js_upload.php:37 +#: js_upload.php:46 msgid "Failed" -msgstr "Mislukt" +msgstr "" -#: js_upload.php:215 +#: js_upload.php:303 msgid "No files were uploaded." -msgstr "Er waren geen bestanden geüpload." +msgstr "" -#: js_upload.php:221 +#: js_upload.php:309 msgid "Uploaded file is empty" -msgstr "Het geüploade bestand is leeg" - -#: js_upload.php:233 -#, php-format -msgid "Image exceeds size limit of %s" msgstr "" -#: js_upload.php:245 -#, php-format -msgid "File has an invalid extension, it should be one of %s." +#: js_upload.php:321 +msgid "Image exceeds size limit of " msgstr "" -#: js_upload.php:256 +#: js_upload.php:332 +msgid "File has an invalid extension, it should be one of " +msgstr "" + +#: js_upload.php:343 msgid "Upload was cancelled, or server error encountered" msgstr "" diff --git a/js_upload/lang/nl/strings.php b/js_upload/lang/nl/strings.php index 4ba709a4..dcdf634a 100644 --- a/js_upload/lang/nl/strings.php +++ b/js_upload/lang/nl/strings.php @@ -5,8 +5,5 @@ function string_plural_select_nl($n){ $n = intval($n); return intval($n != 1); }} +$a->strings['Upload a file'] = 'Upload een bestand'; $a->strings['Drop files here to upload'] = 'Sleep uw bestanden hier om ze te uploaden'; -$a->strings['Cancel'] = 'Afbreken'; -$a->strings['Failed'] = 'Mislukt'; -$a->strings['No files were uploaded.'] = 'Er waren geen bestanden geüpload.'; -$a->strings['Uploaded file is empty'] = 'Het geüploade bestand is leeg'; diff --git a/js_upload/templates/js_upload.tpl b/js_upload/templates/js_upload.tpl index b482cd2b..f45b495c 100644 --- a/js_upload/templates/js_upload.tpl +++ b/js_upload/templates/js_upload.tpl @@ -35,18 +35,18 @@ let albumElm = document.getElementById('photos-upload-album-select'); let contact_allow = document.querySelector('[name="contact_allow"]:not(:disabled)'); - let circle_allow = document.querySelector('[name="circle_allow"]:not(:disabled)'); - let contact_deny = document.querySelector('[name="contact_deny"]:not(:disabled)'); - let circle_deny = document.querySelector('[name="circle_deny"]:not(:disabled)'); + let group_allow = document.querySelector('[name="group_allow"]:not(:disabled)'); + let contact_deny = document.querySelector('[name="contact_deny"]:not(:disabled)'); + let group_deny = document.querySelector('[name="group_deny"]:not(:disabled)'); uploader.setParams({ newalbum : newalbumElm ? newalbumElm.value : '', album : albumElm ? albumElm.value : '', not_visible : document.getElementById('photos-upload-noshare').checked, contact_allow : contact_allow ? contact_allow.value : '', - circle_allow : circle_allow ? circle_allow.value : '', + group_allow : group_allow ? group_allow.value : '', contact_deny : contact_deny ? contact_deny.value : '', - circle_deny : circle_deny ? circle_deny.value : '', + group_deny : group_deny ? group_deny.value : '', }); } }); diff --git a/krynn/lang/de/messages.po b/krynn/lang/de/messages.po index 1159354b..5dfa7269 100644 --- a/krynn/lang/de/messages.po +++ b/krynn/lang/de/messages.po @@ -14,9 +14,9 @@ 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: Tobias Diekershoff , 2018,2021\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2021-12-22 16:22+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/krynn/lang/it/messages.po b/krynn/lang/it/messages.po index d9614ca1..c1bb0949 100644 --- a/krynn/lang/it/messages.po +++ b/krynn/lang/it/messages.po @@ -10,20 +10,28 @@ 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: Sylke Vicious , 2021\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"POT-Creation-Date: 2021-02-01 18:15+0100\n" +"PO-Revision-Date: 2021-04-19 11:11+0000\n" +"Last-Translator: Sylke Vicious \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: krynn.php:127 +#: krynn.php:132 krynn.php:136 +msgid "Krynn" +msgstr "Krynn" + +#: krynn.php:141 +msgid "Krynn Settings" +msgstr "Impostazioni Krynn" + +#: krynn.php:143 msgid "Enable Krynn Addon" msgstr "Abilita componente aggiuntivo Krynn" -#: krynn.php:132 -msgid "Krynn Settings" -msgstr "Impostazioni Krynn" +#: krynn.php:148 +msgid "Save Settings" +msgstr "Salva Impostazioni" diff --git a/krynn/lang/it/strings.php b/krynn/lang/it/strings.php index 727d2877..6322a0c2 100644 --- a/krynn/lang/it/strings.php +++ b/krynn/lang/it/strings.php @@ -3,7 +3,9 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} -$a->strings['Enable Krynn Addon'] = 'Abilita componente aggiuntivo Krynn'; +$a->strings['Krynn'] = 'Krynn'; $a->strings['Krynn Settings'] = 'Impostazioni Krynn'; +$a->strings['Enable Krynn Addon'] = 'Abilita componente aggiuntivo Krynn'; +$a->strings['Save Settings'] = 'Salva Impostazioni'; diff --git a/langfilter/lang/ar/messages.po b/langfilter/lang/ar/messages.po index e68e49fb..6bcc67f9 100644 --- a/langfilter/lang/ar/messages.po +++ b/langfilter/lang/ar/messages.po @@ -4,74 +4,73 @@ # # # Translators: -# abidin toumi , 2021 # Farida Khalaf , 2021 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:15-0500\n" -"PO-Revision-Date: 2015-07-25 08:05+0000\n" -"Last-Translator: abidin toumi , 2021\n" -"Language-Team: Arabic (http://app.transifex.com/Friendica/friendica/language/ar/)\n" +"POT-Creation-Date: 2021-02-01 18:15+0100\n" +"PO-Revision-Date: 2021-04-26 09:14+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Arabic (http://www.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" -#: langfilter.php:49 +#: langfilter.php:50 +msgid "Language Filter" +msgstr "اللغة" + +#: langfilter.php:51 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 "" -#: langfilter.php:50 +#: langfilter.php:52 msgid "Use the language filter" msgstr "اختيار اللغة" -#: langfilter.php:51 +#: langfilter.php:53 msgid "Able to read" msgstr " قابل للقراءة" -#: langfilter.php:51 +#: langfilter.php:53 msgid "" "List of abbreviations (ISO 639-1 codes) for languages you speak, comma " "separated. For example \"de,it\"." msgstr "قائمة الرموز ( ISO 639-1) للغات ، مفصولة بفواصل. على سبيل المثال \"de، it\"" -#: langfilter.php:52 +#: langfilter.php:54 msgid "Minimum confidence in language detection" msgstr "الحد الأدنى من نسبة اكتشاف اللغة" -#: langfilter.php:52 +#: langfilter.php:54 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:53 +#: langfilter.php:55 msgid "Minimum length of message body" msgstr "الحد الأدنى لنص الرسالة" -#: langfilter.php:53 +#: langfilter.php:55 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 " "unreliable for short content (<200 characters)." msgstr "الحد الأدنى لأحرف نص الرسالة لاستخدام الفلتر. لن يتم فلترة المشاركات الأقصر من هذا. ملاحظة: لا يمكن الاعتماد على اكتشاف اللغة للمحتوى القصير (<200 حرف)." -#: langfilter.php:58 -msgid "Language Filter" -msgstr "مرشح اللغة" - -#: langfilter.php:60 +#: langfilter.php:56 msgid "Save Settings" msgstr "حفظ الإعدادات" -#: langfilter.php:193 +#: langfilter.php:187 #, php-format msgid "Filtered language: %s" msgstr "اختيار اللغة: %s" diff --git a/langfilter/lang/ar/strings.php b/langfilter/lang/ar/strings.php index cf8a7632..0c07842c 100644 --- a/langfilter/lang/ar/strings.php +++ b/langfilter/lang/ar/strings.php @@ -5,6 +5,7 @@ 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['Language Filter'] = 'اللغة'; $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) للغات ، مفصولة بفواصل. على سبيل المثال "de، it"'; @@ -12,6 +13,5 @@ $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/langfilter/lang/de/messages.po b/langfilter/lang/de/messages.po index 9a9c2b24..baac99d2 100644 --- a/langfilter/lang/de/messages.po +++ b/langfilter/lang/de/messages.po @@ -5,7 +5,7 @@ # # Translators: # Andreas H., 2018 -# Copiis Praeesse , 2018 +# Copiis Praeesse , 2018 # Ralf Thees , 2019 # Tobias Diekershoff , 2015 # Tobias Diekershoff , 2020-2021 @@ -15,9 +15,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:15-0500\n" -"PO-Revision-Date: 2015-07-25 08:05+0000\n" -"Last-Translator: Tobias Diekershoff , 2020-2021\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2021-10-19 18:08+0000\n" +"Last-Translator: Tobias Diekershoff \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/langfilter/lang/it/messages.po b/langfilter/lang/it/messages.po index a1dab65a..3bf7baed 100644 --- a/langfilter/lang/it/messages.po +++ b/langfilter/lang/it/messages.po @@ -12,68 +12,68 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:15-0500\n" -"PO-Revision-Date: 2015-07-25 08:05+0000\n" -"Last-Translator: SickShark X, 2021\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"POT-Creation-Date: 2021-02-01 18:15+0100\n" +"PO-Revision-Date: 2021-10-17 21:25+0000\n" +"Last-Translator: SickShark X\n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: langfilter.php:49 +#: langfilter.php:50 +msgid "Language Filter" +msgstr "Filtro Lingua" + +#: langfilter.php:51 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 "Questo plug-in prova a identificare la lingua con cui sono stati scritti i posts. Se non corrisponde a nessuna delle lingue specificate qui sotto, i post verranno nascosti." -#: langfilter.php:50 +#: langfilter.php:52 msgid "Use the language filter" msgstr "Usa il filtro lingua" -#: langfilter.php:51 +#: langfilter.php:53 msgid "Able to read" msgstr "In grado di leggere" -#: langfilter.php:51 +#: langfilter.php:53 msgid "" "List of abbreviations (ISO 639-1 codes) for languages you speak, comma " "separated. For example \"de,it\"." msgstr "Lista di abbreviazioni (codici ISO 639-1) per le lingue che parli, separate da virgola. Per esempio \"it,de\"." -#: langfilter.php:52 +#: langfilter.php:54 msgid "Minimum confidence in language detection" msgstr "Fiducia minima nel rilevamento della lingua" -#: langfilter.php:52 +#: langfilter.php:54 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 "Fiducia minima che il rilevamento della lingua sia corretto, da 0 a 100. I messaggi non saranno filtrati quando la fiducia nel rilevamento della lingua è sotto questo valore percentuale." -#: langfilter.php:53 +#: langfilter.php:55 msgid "Minimum length of message body" msgstr "Lunghezza minima del corpo del messaggio" -#: langfilter.php:53 +#: langfilter.php:55 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 " "unreliable for short content (<200 characters)." msgstr "Numero di caratteri minimo perché il filtro venga usato. I messaggio più corti non saranno filtrati. Nota: la rilevazione della lingua non è affidabile con messaggi brevi (<200 caratteri)" -#: langfilter.php:58 -msgid "Language Filter" -msgstr "Filtro Lingua" - -#: langfilter.php:60 +#: langfilter.php:56 msgid "Save Settings" msgstr "Salva Impostazioni" -#: langfilter.php:193 +#: langfilter.php:187 #, php-format msgid "Filtered language: %s" msgstr "Lingua filtrata: %s" diff --git a/langfilter/lang/it/strings.php b/langfilter/lang/it/strings.php index 8cae0b57..f1afafad 100644 --- a/langfilter/lang/it/strings.php +++ b/langfilter/lang/it/strings.php @@ -3,8 +3,9 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} +$a->strings['Language Filter'] = 'Filtro Lingua'; $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.'] = 'Questo plug-in prova a identificare la lingua con cui sono stati scritti i posts. Se non corrisponde a nessuna delle lingue specificate qui sotto, i post verranno nascosti.'; $a->strings['Use the language filter'] = 'Usa il filtro lingua'; $a->strings['Able to read'] = 'In grado di leggere'; @@ -13,6 +14,5 @@ $a->strings['Minimum confidence in language detection'] = 'Fiducia minima nel ri $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.'] = 'Fiducia minima che il rilevamento della lingua sia corretto, da 0 a 100. I messaggi non saranno filtrati quando la fiducia nel rilevamento della lingua è sotto questo valore percentuale.'; $a->strings['Minimum length of message body'] = 'Lunghezza minima del corpo del messaggio'; $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).'] = 'Numero di caratteri minimo perché il filtro venga usato. I messaggio più corti non saranno filtrati. Nota: la rilevazione della lingua non è affidabile con messaggi brevi (<200 caratteri)'; -$a->strings['Language Filter'] = 'Filtro Lingua'; $a->strings['Save Settings'] = 'Salva Impostazioni'; $a->strings['Filtered language: %s'] = 'Lingua filtrata: %s'; diff --git a/langfilter/lang/ru/messages.po b/langfilter/lang/ru/messages.po index 45ad7b3d..e1fbc9e8 100644 --- a/langfilter/lang/ru/messages.po +++ b/langfilter/lang/ru/messages.po @@ -4,59 +4,63 @@ # # # Translators: -# Alexander An , 2020,2023 +# Alexander An , 2020 # Stanislav N. , 2018 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \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" +"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" "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:49 +#: langfilter.php:52 +msgid "Language Filter" +msgstr "Языковой фильтр" + +#: langfilter.php:53 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:50 +#: langfilter.php:54 msgid "Use the language filter" msgstr "Использовать языковой фильтр" -#: langfilter.php:51 +#: langfilter.php:55 msgid "Able to read" msgstr "Возможность читать" -#: langfilter.php:51 +#: langfilter.php:55 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:52 +#: langfilter.php:56 msgid "Minimum confidence in language detection" msgstr "Минимальная уверенность в определении языка" -#: langfilter.php:52 +#: langfilter.php:56 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:53 +#: langfilter.php:57 msgid "Minimum length of message body" msgstr "Минимальная длина тела сообщения" -#: langfilter.php:53 +#: langfilter.php:57 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 " @@ -64,14 +68,10 @@ msgid "" msgstr "Минимальное количество знаков в теле сообщения для применения фильтрации. Посты, длина которых меньше указанного значения, не будут отфильтрованы. Обратите внимание, что определение языка работает ненадежно для небольших постов (<200 символов)." #: langfilter.php:58 -msgid "Language Filter" -msgstr "Языковой фильтр" - -#: langfilter.php:60 msgid "Save Settings" msgstr "Сохранить настройки" -#: langfilter.php:193 +#: langfilter.php:189 #, php-format msgid "Filtered language: %s" msgstr "Отфильтрованный язык: %s" diff --git a/langfilter/lang/ru/strings.php b/langfilter/lang/ru/strings.php index 1f5619f7..0489bd4f 100644 --- a/langfilter/lang/ru/strings.php +++ b/langfilter/lang/ru/strings.php @@ -5,7 +5,8 @@ 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['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['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['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".'; @@ -13,6 +14,5 @@ $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/langfilter/langfilter.php b/langfilter/langfilter.php index e5efa8fb..020a32df 100644 --- a/langfilter/langfilter.php +++ b/langfilter/langfilter.php @@ -107,7 +107,7 @@ function langfilter_prepare_body_content_filter(&$hook_data) // Never filter own messages // TODO: find a better way to extract this - $logged_user_profile = DI::baseUrl() . '/profile/' . DI::userSession()->getLocalUserNickname(); + $logged_user_profile = DI::baseUrl()->get() . '/profile/' . DI::userSession()->getLocalUserNickname(); if ($logged_user_profile == $hook_data['item']['author-link']) { return; } @@ -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::convertForUriId($hook_data['item']['uri-id'], $hook_data['item']['body'], BBCode::ACTIVITYPUB) + BBCode::convert($hook_data['item']['body'], false, BBCode::ACTIVITYPUB, true) ); $naked_body = preg_replace('#\s+#', ' ', trim($naked_body)); @@ -163,7 +163,7 @@ function langfilter_prepare_body_content_filter(&$hook_data) return; } - $lang = $iso639->languageByCode1(substr($iso2, 0, 2)); + $lang = $iso639->languageByCode1($iso2); } else { $opts = $hook_data['item']['postopts']; if (!$opts) { diff --git a/libertree/lang/C/messages.po b/libertree/lang/C/messages.po index 3162b6a7..6feeef8d 100644 --- a/libertree/lang/C/messages.po +++ b/libertree/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:49-0400\n" +"POT-Creation-Date: 2021-11-21 19:17-0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -21,22 +21,22 @@ msgstr "" msgid "Post to libertree" msgstr "" -#: libertree.php:59 +#: libertree.php:60 msgid "Enable Libertree Post Addon" msgstr "" -#: libertree.php:60 +#: libertree.php:61 msgid "Libertree site URL" msgstr "" -#: libertree.php:61 +#: libertree.php:62 msgid "Libertree API token" msgstr "" -#: libertree.php:62 +#: libertree.php:63 msgid "Post to Libertree by default" msgstr "" -#: libertree.php:67 +#: libertree.php:68 msgid "Libertree Export" msgstr "" diff --git a/libertree/lang/cs/messages.po b/libertree/lang/cs/messages.po index 649fef00..b97b17ed 100644 --- a/libertree/lang/cs/messages.po +++ b/libertree/lang/cs/messages.po @@ -4,42 +4,45 @@ # # # Translators: -# Aditoo, 2018 -# michal_s , 2014-2015 +# Michal Šupler , 2014-2015 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:17-0500\n" -"PO-Revision-Date: 2014-06-23 09:44+0000\n" -"Last-Translator: Aditoo, 2018\n" -"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" +"POT-Creation-Date: 2013-02-27 05:01-0500\n" +"PO-Revision-Date: 2015-02-11 19:39+0000\n" +"Last-Translator: Michal Šupler \n" +"Language-Team: Czech (http://www.transifex.com/projects/p/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" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -#: libertree.php:39 +#: libertree.php:36 msgid "Post to libertree" msgstr "Poslat na libertree" -#: libertree.php:60 +#: libertree.php:67 +msgid "libertree Post Settings" +msgstr "libertree nastavení příspěvků" + +#: libertree.php:69 msgid "Enable Libertree Post Addon" -msgstr "Povolit doplněk Libertree Post" +msgstr "Povolit Libertree Post rozšíření" -#: libertree.php:61 -msgid "Libertree site URL" -msgstr "URL adresa Libertree " - -#: libertree.php:62 +#: libertree.php:74 msgid "Libertree API token" msgstr "Libertree API token" -#: libertree.php:63 -msgid "Post to Libertree by default" -msgstr "Ve výchozím stavu posílat na Libertree" +#: libertree.php:79 +msgid "Libertree site URL" +msgstr "URL adresa Libertree " -#: libertree.php:68 -msgid "Libertree Export" -msgstr "" +#: libertree.php:84 +msgid "Post to Libertree by default" +msgstr "Defaultně poslat na Libertree" + +#: libertree.php:90 +msgid "Submit" +msgstr "Odeslat" diff --git a/libertree/lang/cs/strings.php b/libertree/lang/cs/strings.php index 49a3dd54..2bd6ed4d 100644 --- a/libertree/lang/cs/strings.php +++ b/libertree/lang/cs/strings.php @@ -3,10 +3,12 @@ if(! function_exists("string_plural_select_cs")) { function string_plural_select_cs($n){ $n = intval($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; } + if (($n==1)) { return 0; } else if (($n>=2 && $n<=4)) { return 1; } else { return 2; } }} $a->strings['Post to libertree'] = 'Poslat na libertree'; -$a->strings['Enable Libertree Post Addon'] = 'Povolit doplněk Libertree Post'; -$a->strings['Libertree site URL'] = 'URL adresa Libertree '; +$a->strings['libertree Post Settings'] = 'libertree nastavení příspěvků'; +$a->strings['Enable Libertree Post Addon'] = 'Povolit Libertree Post rozšíření'; $a->strings['Libertree API token'] = 'Libertree API token'; -$a->strings['Post to Libertree by default'] = 'Ve výchozím stavu posílat na Libertree'; +$a->strings['Libertree site URL'] = 'URL adresa Libertree '; +$a->strings['Post to Libertree by default'] = 'Defaultně poslat na Libertree'; +$a->strings['Submit'] = 'Odeslat'; diff --git a/libertree/lang/de/messages.po b/libertree/lang/de/messages.po index 434b64ab..ae86cb53 100644 --- a/libertree/lang/de/messages.po +++ b/libertree/lang/de/messages.po @@ -13,9 +13,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:17-0500\n" -"PO-Revision-Date: 2014-06-23 09:44+0000\n" -"Last-Translator: Tobias Diekershoff , 2018,2021-2022\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2022-01-22 17:34+0000\n" +"Last-Translator: Tobias Diekershoff \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/libertree/libertree.php b/libertree/libertree.php index c0f896c0..0a909f35 100644 --- a/libertree/libertree.php +++ b/libertree/libertree.php @@ -151,7 +151,7 @@ function libertree_send(array &$b) } // Dont't post if the post doesn't belong to us. - // This is a check for group postings + // This is a check for forum postings $self = DBA::selectFirst('contact', ['id'], ['uid' => $b['uid'], 'self' => true]); if ($b['contact-id'] != $self['id']) { return; @@ -162,7 +162,7 @@ function libertree_send(array &$b) $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(); + $ltree_source = DI::baseUrl()->getHostname(); if ($b['app'] != "") $ltree_source .= " (".$b['app'].")"; diff --git a/libravatar/lang/de/messages.po b/libravatar/lang/de/messages.po index 6c0d7c01..60575f0c 100644 --- a/libravatar/lang/de/messages.po +++ b/libravatar/lang/de/messages.po @@ -12,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" -"PO-Revision-Date: 2014-06-23 09:49+0000\n" -"Last-Translator: Tobias Diekershoff , 2021\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"POT-Creation-Date: 2020-12-08 07:16+0000\n" +"PO-Revision-Date: 2021-02-01 06:30+0000\n" +"Last-Translator: Tobias Diekershoff \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/libravatar/lang/it/messages.po b/libravatar/lang/it/messages.po index 931fefb8..7036dc1c 100644 --- a/libravatar/lang/it/messages.po +++ b/libravatar/lang/it/messages.po @@ -11,14 +11,14 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-02-01 18:15+0100\n" -"PO-Revision-Date: 2014-06-23 09:49+0000\n" -"Last-Translator: Sylke Vicious , 2021\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"PO-Revision-Date: 2021-05-05 11:06+0000\n" +"Last-Translator: Sylke Vicious \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: libravatar.php:68 msgid "generic profile image" diff --git a/libravatar/lang/it/strings.php b/libravatar/lang/it/strings.php index 75fa4190..08b1503b 100644 --- a/libravatar/lang/it/strings.php +++ b/libravatar/lang/it/strings.php @@ -3,7 +3,7 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $a->strings['generic profile image'] = 'immagine generica del profilo'; $a->strings['random geometric pattern'] = 'schema geometrico casuale'; diff --git a/ljpost/lang/cs/messages.po b/ljpost/lang/cs/messages.po index 1578bf38..74a88433 100644 --- a/ljpost/lang/cs/messages.po +++ b/ljpost/lang/cs/messages.po @@ -4,42 +4,45 @@ # # # Translators: -# Aditoo, 2018 -# michal_s , 2014-2015 +# Michal Šupler , 2014-2015 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:17-0500\n" -"PO-Revision-Date: 2014-06-23 09:51+0000\n" -"Last-Translator: Aditoo, 2018\n" -"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" +"POT-Creation-Date: 2013-02-27 05:01-0500\n" +"PO-Revision-Date: 2015-02-11 19:38+0000\n" +"Last-Translator: Michal Šupler \n" +"Language-Team: Czech (http://www.transifex.com/projects/p/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" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -#: ljpost.php:43 +#: ljpost.php:39 msgid "Post to LiveJournal" -msgstr "Odeslat na LiveJournal" +msgstr "Poslat na LiveJournal" -#: ljpost.php:63 +#: ljpost.php:70 +msgid "LiveJournal Post Settings" +msgstr "Nastavení LiveJournal Post" + +#: ljpost.php:72 msgid "Enable LiveJournal Post Addon" -msgstr "Povolit doplněk LiveJournal Post" +msgstr "Povolit LiveJournal Post addon" -#: ljpost.php:64 +#: ljpost.php:77 msgid "LiveJournal username" msgstr "LiveJournal uživatelské jméno" -#: ljpost.php:65 +#: ljpost.php:82 msgid "LiveJournal password" msgstr "LiveJournal heslo" -#: ljpost.php:66 +#: ljpost.php:87 msgid "Post to LiveJournal by default" msgstr "Defaultně umístit na LiveJournal" -#: ljpost.php:71 -msgid "LiveJournal Export" -msgstr "" +#: ljpost.php:93 +msgid "Submit" +msgstr "Odeslat" diff --git a/ljpost/lang/cs/strings.php b/ljpost/lang/cs/strings.php index 2430efbd..76721b77 100644 --- a/ljpost/lang/cs/strings.php +++ b/ljpost/lang/cs/strings.php @@ -3,10 +3,12 @@ if(! function_exists("string_plural_select_cs")) { function string_plural_select_cs($n){ $n = intval($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; } + if (($n==1)) { return 0; } else if (($n>=2 && $n<=4)) { return 1; } else { return 2; } }} -$a->strings['Post to LiveJournal'] = 'Odeslat na LiveJournal'; -$a->strings['Enable LiveJournal Post Addon'] = 'Povolit doplněk LiveJournal Post'; +$a->strings['Post to LiveJournal'] = 'Poslat na LiveJournal'; +$a->strings['LiveJournal Post Settings'] = 'Nastavení LiveJournal Post'; +$a->strings['Enable LiveJournal Post Addon'] = 'Povolit LiveJournal Post addon'; $a->strings['LiveJournal username'] = 'LiveJournal uživatelské jméno'; $a->strings['LiveJournal password'] = 'LiveJournal heslo'; $a->strings['Post to LiveJournal by default'] = 'Defaultně umístit na LiveJournal'; +$a->strings['Submit'] = 'Odeslat'; diff --git a/ljpost/lang/de/messages.po b/ljpost/lang/de/messages.po index 7a41438f..13d7d6c7 100644 --- a/ljpost/lang/de/messages.po +++ b/ljpost/lang/de/messages.po @@ -6,16 +6,16 @@ # Translators: # Andreas H., 2014 # Tobias Diekershoff , 2014 -# Tobias Diekershoff , 2018,2021-2022 +# Tobias Diekershoff , 2018,2021 # Ulf Rompe , 2019 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:17-0500\n" -"PO-Revision-Date: 2014-06-23 09:51+0000\n" -"Last-Translator: Tobias Diekershoff , 2018,2021-2022\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2021-12-22 17:23+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -44,4 +44,4 @@ msgstr "Standardmäßig bei LiveJournal veröffentlichen" #: ljpost.php:71 msgid "LiveJournal Export" -msgstr "LiveJournal Export" +msgstr "" diff --git a/ljpost/lang/de/strings.php b/ljpost/lang/de/strings.php index 88c98dd0..99641213 100644 --- a/ljpost/lang/de/strings.php +++ b/ljpost/lang/de/strings.php @@ -10,4 +10,3 @@ $a->strings['Enable LiveJournal Post Addon'] = 'LiveJournal-Post-Addon aktiviere $a->strings['LiveJournal username'] = 'LiveJournal-Benutzername'; $a->strings['LiveJournal password'] = 'LiveJournal-Passwort'; $a->strings['Post to LiveJournal by default'] = 'Standardmäßig bei LiveJournal veröffentlichen'; -$a->strings['LiveJournal Export'] = 'LiveJournal Export'; diff --git a/ljpost/lang/it/messages.po b/ljpost/lang/it/messages.po index f24ca580..c7a8c3cb 100644 --- a/ljpost/lang/it/messages.po +++ b/ljpost/lang/it/messages.po @@ -5,41 +5,45 @@ # # Translators: # fabrixxm , 2014-2015,2018 -# Sylke Vicious , 2021,2023 +# Sylke Vicious , 2021 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:17-0500\n" -"PO-Revision-Date: 2014-06-23 09:51+0000\n" -"Last-Translator: Sylke Vicious , 2021,2023\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"POT-Creation-Date: 2021-02-01 18:15+0100\n" +"PO-Revision-Date: 2021-02-16 12:57+0000\n" +"Last-Translator: Sylke Vicious \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ljpost.php:43 +#: ljpost.php:39 msgid "Post to LiveJournal" msgstr "Invia a LiveJournal" -#: ljpost.php:63 +#: ljpost.php:73 +msgid "LiveJournal Post Settings" +msgstr "Impostazioni invio a LiveJournal" + +#: ljpost.php:75 msgid "Enable LiveJournal Post Addon" msgstr "Abilita il componente aggiuntivo di invio a LiveJournal" -#: ljpost.php:64 +#: ljpost.php:80 msgid "LiveJournal username" msgstr "Nome utente LiveJournal" -#: ljpost.php:65 +#: ljpost.php:85 msgid "LiveJournal password" msgstr "Password LiveJournal" -#: ljpost.php:66 +#: ljpost.php:90 msgid "Post to LiveJournal by default" msgstr "Invia sempre a LiveJournal" -#: ljpost.php:71 -msgid "LiveJournal Export" -msgstr "Esporta LiveJournal" +#: ljpost.php:96 +msgid "Save Settings" +msgstr "Salva Impostazioni" diff --git a/ljpost/lang/it/strings.php b/ljpost/lang/it/strings.php index 3f857ed8..c52326e0 100644 --- a/ljpost/lang/it/strings.php +++ b/ljpost/lang/it/strings.php @@ -3,11 +3,12 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $a->strings['Post to LiveJournal'] = 'Invia a LiveJournal'; +$a->strings['LiveJournal Post Settings'] = 'Impostazioni invio a LiveJournal'; $a->strings['Enable LiveJournal Post Addon'] = 'Abilita il componente aggiuntivo di invio a LiveJournal'; $a->strings['LiveJournal username'] = 'Nome utente LiveJournal'; $a->strings['LiveJournal password'] = 'Password LiveJournal'; $a->strings['Post to LiveJournal by default'] = 'Invia sempre a LiveJournal'; -$a->strings['LiveJournal Export'] = 'Esporta LiveJournal'; +$a->strings['Save Settings'] = 'Salva Impostazioni'; diff --git a/mailstream/lang/C/messages.po b/mailstream/lang/C/messages.po index 666181b8..5115d8cb 100644 --- a/mailstream/lang/C/messages.po +++ b/mailstream/lang/C/messages.po @@ -29,72 +29,68 @@ msgstr "" msgid "Save Settings" msgstr "" -#: mailstream.php:311 +#: mailstream.php:301 msgid "Re:" msgstr "" -#: mailstream.php:324 mailstream.php:327 +#: mailstream.php:314 mailstream.php:317 msgid "Friendica post" msgstr "" -#: mailstream.php:330 +#: mailstream.php:320 msgid "Diaspora post" msgstr "" -#: mailstream.php:340 +#: mailstream.php:330 msgid "Feed item" msgstr "" -#: mailstream.php:343 +#: mailstream.php:333 msgid "Email" msgstr "" -#: mailstream.php:345 +#: mailstream.php:335 msgid "Friendica Item" msgstr "" -#: mailstream.php:419 +#: mailstream.php:404 msgid "Upstream" msgstr "" -#: mailstream.php:420 -msgid "URI" -msgstr "" - -#: mailstream.php:421 +#: mailstream.php:405 msgid "Local" msgstr "" -#: mailstream.php:499 +#: mailstream.php:481 msgid "Enabled" msgstr "" -#: mailstream.php:504 +#: mailstream.php:486 msgid "Email Address" msgstr "" -#: mailstream.php:506 +#: mailstream.php:488 msgid "Leave blank to use your account email address" msgstr "" -#: mailstream.php:510 +#: mailstream.php:492 msgid "Exclude Likes" msgstr "" -#: mailstream.php:512 +#: mailstream.php:494 msgid "Check this to omit mailing \"Like\" notifications" msgstr "" -#: mailstream.php:516 +#: mailstream.php:498 msgid "Attach Images" msgstr "" -#: mailstream.php:518 +#: mailstream.php:500 msgid "" "Download images in posts and attach them to the email. Useful for reading " "email while offline." msgstr "" -#: mailstream.php:525 +#: mailstream.php:507 msgid "Mail Stream Settings" msgstr "" diff --git a/mailstream/lang/fr/messages.po b/mailstream/lang/fr/messages.po index 043181c5..488d4c08 100644 --- a/mailstream/lang/fr/messages.po +++ b/mailstream/lang/fr/messages.po @@ -4,7 +4,6 @@ # # # Translators: -# Florent C., 2023 # Nicolas Derive, 2022 # ea1cd8241cb389ffb6f92bc6891eff5d_dc12308 <70dced5587d47e18d88f9298024d96f8_93383>, 2015 # StefOfficiel , 2015 @@ -14,8 +13,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: Florent C., 2023\n" -"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n" +"Last-Translator: Nicolas Derive, 2022\n" +"Language-Team: French (http://www.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" @@ -34,72 +33,68 @@ msgstr "Adresse de courriel de laquelle les éléments du flux sembleront proven msgid "Save Settings" msgstr "Sauvegarder les paramètres" -#: mailstream.php:311 +#: mailstream.php:301 msgid "Re:" msgstr "Re :" -#: mailstream.php:324 mailstream.php:327 +#: mailstream.php:314 mailstream.php:317 msgid "Friendica post" msgstr "Message Friendica" -#: mailstream.php:330 +#: mailstream.php:320 msgid "Diaspora post" msgstr "Message Diaspora" -#: mailstream.php:340 +#: mailstream.php:330 msgid "Feed item" msgstr "Élément du flux" -#: mailstream.php:343 +#: mailstream.php:333 msgid "Email" msgstr "Courriel" -#: mailstream.php:345 +#: mailstream.php:335 msgid "Friendica Item" msgstr "Élément de Friendica" -#: mailstream.php:419 +#: mailstream.php:404 msgid "Upstream" msgstr "En amont" -#: mailstream.php:420 -msgid "URI" -msgstr "URI" - -#: mailstream.php:421 +#: mailstream.php:405 msgid "Local" msgstr "Local" -#: mailstream.php:499 +#: mailstream.php:481 msgid "Enabled" msgstr "Activer" -#: mailstream.php:504 +#: mailstream.php:486 msgid "Email Address" msgstr "Adresse de courriel" -#: mailstream.php:506 +#: mailstream.php:488 msgid "Leave blank to use your account email address" msgstr "Laissez vide pour utiliser l'adresse de courriel de votre compte" -#: mailstream.php:510 +#: mailstream.php:492 msgid "Exclude Likes" msgstr "Exclure les \"j'aime\"" -#: mailstream.php:512 +#: mailstream.php:494 msgid "Check this to omit mailing \"Like\" notifications" msgstr "Cochez ceci pour éviter d'envoyer les notifications des \"J'aime\"" -#: mailstream.php:516 +#: mailstream.php:498 msgid "Attach Images" msgstr "Attacher les images" -#: mailstream.php:518 +#: mailstream.php:500 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:525 +#: mailstream.php:507 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 a21d80b8..bfaf4389 100644 --- a/mailstream/lang/fr/strings.php +++ b/mailstream/lang/fr/strings.php @@ -15,7 +15,6 @@ $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/mailstream/lang/hu/messages.po b/mailstream/lang/hu/messages.po index 66d09299..3302564d 100644 --- a/mailstream/lang/hu/messages.po +++ b/mailstream/lang/hu/messages.po @@ -4,15 +4,15 @@ # # # Translators: -# Balázs Úr, 2020-2021,2023 +# Balázs Úr, 2020-2021 msgid "" msgstr "" "Project-Id-Version: friendica\n" "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: Balázs Úr, 2020-2021,2023\n" -"Language-Team: Hungarian (http://app.transifex.com/Friendica/friendica/language/hu/)\n" +"Last-Translator: Balázs Úr, 2020-2021\n" +"Language-Team: Hungarian (http://www.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" @@ -31,72 +31,68 @@ msgstr "E-mail-cím, ahonnan úgy tűnik, hogy a folyam elemei származnak." msgid "Save Settings" msgstr "Beállítások mentése" -#: mailstream.php:311 +#: mailstream.php:301 msgid "Re:" msgstr "Vá:" -#: mailstream.php:324 mailstream.php:327 +#: mailstream.php:314 mailstream.php:317 msgid "Friendica post" msgstr "Friendica-bejegyzés" -#: mailstream.php:330 +#: mailstream.php:320 msgid "Diaspora post" msgstr "Diaspora-bejegyzés" -#: mailstream.php:340 +#: mailstream.php:330 msgid "Feed item" msgstr "Hírforráselem" -#: mailstream.php:343 +#: mailstream.php:333 msgid "Email" msgstr "E-mail" -#: mailstream.php:345 +#: mailstream.php:335 msgid "Friendica Item" msgstr "Friendica-elem" -#: mailstream.php:419 +#: mailstream.php:404 msgid "Upstream" msgstr "Távoli" -#: mailstream.php:420 -msgid "URI" -msgstr "URI" - -#: mailstream.php:421 +#: mailstream.php:405 msgid "Local" msgstr "Helyi" -#: mailstream.php:499 +#: mailstream.php:481 msgid "Enabled" msgstr "Engedélyezve" -#: mailstream.php:504 +#: mailstream.php:486 msgid "Email Address" msgstr "E-mail-cím" -#: mailstream.php:506 +#: mailstream.php:488 msgid "Leave blank to use your account email address" msgstr "Hagyja üresen a fiókja e-mail-címének használatához" -#: mailstream.php:510 +#: mailstream.php:492 msgid "Exclude Likes" msgstr "Kedvelések kizárása" -#: mailstream.php:512 +#: mailstream.php:494 msgid "Check this to omit mailing \"Like\" notifications" msgstr "Jelölje be ezt a „Tetszik” értesítések elküldésének kihagyásához" -#: mailstream.php:516 +#: mailstream.php:498 msgid "Attach Images" msgstr "Képek csatolása" -#: mailstream.php:518 +#: mailstream.php:500 msgid "" "Download images in posts and attach them to the email. Useful for reading " "email while offline." msgstr "Képek letöltése a bejegyzésekből és csatolás az e-mailhez. Hasznos az e-mailek kapcsolat nélküli olvasásakor." -#: mailstream.php:525 +#: mailstream.php:507 msgid "Mail Stream Settings" msgstr "Levelezőfolyam beállításai" diff --git a/mailstream/lang/hu/strings.php b/mailstream/lang/hu/strings.php index 5b1e5a51..5a7383bd 100644 --- a/mailstream/lang/hu/strings.php +++ b/mailstream/lang/hu/strings.php @@ -15,7 +15,6 @@ $a->strings['Feed item'] = 'Hírforráselem'; $a->strings['Email'] = 'E-mail'; $a->strings['Friendica Item'] = 'Friendica-elem'; $a->strings['Upstream'] = 'Távoli'; -$a->strings['URI'] = 'URI'; $a->strings['Local'] = 'Helyi'; $a->strings['Enabled'] = 'Engedélyezve'; $a->strings['Email Address'] = 'E-mail-cím'; diff --git a/mailstream/mailstream.php b/mailstream/mailstream.php index d76ccf86..bf4c9906 100644 --- a/mailstream/mailstream.php +++ b/mailstream/mailstream.php @@ -32,6 +32,7 @@ function mailstream_install() Hook::register('addon_settings_post', 'addon/mailstream/mailstream.php', 'mailstream_addon_settings_post'); Hook::register('post_local_end', 'addon/mailstream/mailstream.php', 'mailstream_post_hook'); Hook::register('post_remote_end', 'addon/mailstream/mailstream.php', 'mailstream_post_hook'); + Hook::register('cron', 'addon/mailstream/mailstream.php', 'mailstream_cron'); Hook::register('mailstream_send_hook', 'addon/mailstream/mailstream.php', 'mailstream_send_hook'); Logger::info("mailstream: installed"); @@ -102,7 +103,7 @@ function mailstream_addon_admin_post() */ function mailstream_generate_id(string $uri): string { - $host = DI::baseUrl()->getHost(); + $host = DI::baseUrl()->getHostname(); $resource = hash('md5', $uri); $message_id = "<" . $resource . "@" . $host . ">"; Logger::debug('mailstream: Generated message ID ' . $message_id . ' for URI ' . $uri); @@ -145,7 +146,7 @@ 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 for item ' . $item['id']); return; } if (!$item['uid']) { @@ -160,8 +161,8 @@ function mailstream_post_hook(array &$item) Logger::debug('mailstream: no uri for item ' . $item['id']); return; } - if ($item['verb'] == Activity::ANNOUNCE) { - Logger::debug('mailstream: announce item ', ['item' => $item['id']]); + if (!$item['plink']) { + Logger::debug('mailstream: no plink for item ' . $item['id']); return; } if (DI::pConfig()->get($item['uid'], 'mailstream', 'nolikes')) { @@ -214,12 +215,7 @@ function mailstream_do_images(array &$item, array &$attachments) } $cookiejar = tempnam(System::getTempPath(), 'cookiejar-mailstream-'); - 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']]); - continue; - } + $curlResult = DI::httpClient()->fetchFull($url, HttpClientAccept::DEFAULT, 0, $cookiejar); $attachments[$url] = [ 'data' => $curlResult->getBody(), 'guid' => hash('crc32', $url), @@ -258,13 +254,12 @@ 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, int $uri_id): string +function mailstream_decode_subject(string $subject): string { - $html = BBCode::convertForUriId($uri_id, $subject); + $html = BBCode::convert($subject); if (!$html) { return $subject; } @@ -299,7 +294,7 @@ function mailstream_decode_subject(string $subject, int $uri_id): string function mailstream_subject(array $item): string { if ($item['title']) { - return mailstream_decode_subject($item['title'], $item['uri-id']); + return mailstream_decode_subject($item['title']); } $parent = $item['thr-parent']; // Don't look more than 100 levels deep for a subject, in case of loops @@ -312,7 +307,7 @@ function mailstream_subject(array $item): string break; } if ($parent_item['title']) { - return DI::l10n()->t('Re:') . ' ' . mailstream_decode_subject($parent_item['title'], $item['uri-id']); + return DI::l10n()->t('Re:') . ' ' . mailstream_decode_subject($parent_item['title']); } $parent = $parent_item['thr-parent']; } @@ -334,7 +329,7 @@ function mailstream_subject(array $item): string return DI::l10n()->t("Diaspora post"); } if ($contact['network'] === 'face') { - $text = mailstream_decode_subject($item['body'], $item['uri-id']); + $text = mailstream_decode_subject($item['body']); // For some reason these do show up in Facebook $text = preg_replace('/\xA0$/', '', $text); $subject = (strlen($text) > 150) ? (substr($text, 0, 140) . '...') : $text; @@ -400,9 +395,7 @@ function mailstream_send(string $message_id, array $item, array $user): bool $mail->addCustomHeader('In-Reply-To: ' . mailstream_generate_id($item['thr-parent'])); } $mail->addCustomHeader('X-Friendica-Mailstream-URI: ' . $item['uri']); - if ($item['plink']) { - $mail->addCustomHeader('X-Friendica-Mailstream-Plink: ' . $item['plink']); - } + $mail->addCustomHeader('X-Friendica-Mailstream-Plink: ' . $item['plink']); $encoding = 'base64'; foreach ($attachments as $url => $image) { $mail->AddStringEmbeddedImage( @@ -418,13 +411,12 @@ function mailstream_send(string $message_id, array $item, array $user): bool $template = Renderer::getMarkupTemplate('mail.tpl', 'addon/mailstream/'); $mail->AltBody = BBCode::toPlaintext($item['body']); $item['body'] = BBCode::convertForUriId($item['uri-id'], $item['body'], BBCode::CONNECTORS); - $item['url'] = DI::baseUrl() . '/display/' . $item['guid']; + $item['url'] = DI::baseUrl()->get() . '/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]); - $mail->Body = mailstream_html_wrap($mail->Body); + mailstream_html_wrap($mail->Body); if (!$mail->Send()) { throw new Exception($mail->ErrorInfo); } @@ -445,8 +437,7 @@ function mailstream_send(string $message_id, array $item, array $user): bool * bbcode's output suitable for transmission, we try to break things * up so that lines are about 200 characters. * - * @param string $text text to word wrap - * @return string wrapped text + * @param string $text text to word wrap - modified in-place */ function mailstream_html_wrap(string &$text) { @@ -455,7 +446,6 @@ function mailstream_html_wrap(string &$text) $lines[$i] = preg_replace('/ /', "\n", $lines[$i], 1); } $text = implode($lines); - return $text; } /** @@ -472,7 +462,8 @@ 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']]); + Logger::info('mailstream_cron: Item ' . + $ms_item_id['id'] . ' URI ' . $ms_item_id['uri'] . ' has no message-id'); continue; } Logger::info('mailstream_convert_table_entries: convert item to workerqueue', $send_hook_data); diff --git a/mailstream/templates/mail.tpl b/mailstream/templates/mail.tpl index 8015b45f..526ca4ef 100644 --- a/mailstream/templates/mail.tpl +++ b/mailstream/templates/mail.tpl @@ -6,6 +6,5 @@
{{$item.body nofilter}}
{{if $item.plink}}
{{$upstream}}: {{$item.plink}}
-
{{$uri}}: {{$item.uri}}
{{$local}}: {{$item.url}}
{{/if}} diff --git a/mathjax/lang/cs/messages.po b/mathjax/lang/cs/messages.po index ae2968be..66d201f6 100644 --- a/mathjax/lang/cs/messages.po +++ b/mathjax/lang/cs/messages.po @@ -4,29 +4,50 @@ # # # Translators: -# Aditoo, 2018 -# michal_s , 2014-2015 +# Michal Šupler , 2014-2015 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:15-0500\n" -"PO-Revision-Date: 2014-06-23 09:55+0000\n" -"Last-Translator: Aditoo, 2018\n" -"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" +"POT-Creation-Date: 2013-02-27 05:01-0500\n" +"PO-Revision-Date: 2015-02-11 19:38+0000\n" +"Last-Translator: Michal Šupler \n" +"Language-Team: Czech (http://www.transifex.com/projects/p/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" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -#: mathjax.php:42 +#: mathjax.php:36 +msgid "Settings" +msgstr "Nastavení" + +#: mathjax.php:37 msgid "" "The MathJax addon renders mathematical formulae written using the LaTeX " "syntax surrounded by the usual $$ or an eqnarray block in the postings of " "your wall,network tab and private mail." -msgstr "Doplněk MathJax vykresluje matematické vzorce zapsané s použitím syntaxe LaTeX označené obvyklými znaky $$, nebo blok \"eqnarray\" v příspěvcích na Vaší zdi, záložce Síť a soukromých zprávách." +msgstr "Rozšíření MathJax vykresluje matematické vzorce zapsané s použitím syntaxe LaTeX označené obvyklými znaky $$ nebo v bloku \"eqnarray\" v příspěvcích na vaší zdi, záložce síť a soukromých zprávách." -#: mathjax.php:43 +#: mathjax.php:38 msgid "Use the MathJax renderer" -msgstr "Použít vykreslování MathJax" +msgstr "Použít Mathjax vykreslování" + +#: mathjax.php:42 +msgid "Submit" +msgstr "Odeslat" + +#: mathjax.php:66 +msgid "Settings updated." +msgstr "Nastavení aktualizováno." + +#: mathjax.php:75 +msgid "MathJax Base URL" +msgstr "Základní MathJax adresa URL" + +#: mathjax.php:75 +msgid "" +"The URL for the javascript file that should be included to use MathJax. Can " +"be either the MathJax CDN or another installation of MathJax." +msgstr "URL adresa na javascriptový soubor, který musí být obsažen pro použití MathJax. Může to být MathJax CDN nebo or jiná instalace MathJax." diff --git a/mathjax/lang/cs/strings.php b/mathjax/lang/cs/strings.php index f73b931a..a591bb3c 100644 --- a/mathjax/lang/cs/strings.php +++ b/mathjax/lang/cs/strings.php @@ -3,7 +3,12 @@ if(! function_exists("string_plural_select_cs")) { function string_plural_select_cs($n){ $n = intval($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; } + if (($n==1)) { return 0; } else if (($n>=2 && $n<=4)) { return 1; } else { return 2; } }} -$a->strings['The MathJax addon renders mathematical formulae written using the LaTeX syntax surrounded by the usual $$ or an eqnarray block in the postings of your wall,network tab and private mail.'] = 'Doplněk MathJax vykresluje matematické vzorce zapsané s použitím syntaxe LaTeX označené obvyklými znaky $$, nebo blok "eqnarray" v příspěvcích na Vaší zdi, záložce Síť a soukromých zprávách.'; -$a->strings['Use the MathJax renderer'] = 'Použít vykreslování MathJax'; +$a->strings['Settings'] = 'Nastavení'; +$a->strings['The MathJax addon renders mathematical formulae written using the LaTeX syntax surrounded by the usual $$ or an eqnarray block in the postings of your wall,network tab and private mail.'] = 'Rozšíření MathJax vykresluje matematické vzorce zapsané s použitím syntaxe LaTeX označené obvyklými znaky $$ nebo v bloku "eqnarray" v příspěvcích na vaší zdi, záložce síť a soukromých zprávách.'; +$a->strings['Use the MathJax renderer'] = 'Použít Mathjax vykreslování'; +$a->strings['Submit'] = 'Odeslat'; +$a->strings['Settings updated.'] = 'Nastavení aktualizováno.'; +$a->strings['MathJax Base URL'] = 'Základní MathJax adresa URL'; +$a->strings['The URL for the javascript file that should be included to use MathJax. Can be either the MathJax CDN or another installation of MathJax.'] = 'URL adresa na javascriptový soubor, který musí být obsažen pro použití MathJax. Může to být MathJax CDN nebo or jiná instalace MathJax.'; diff --git a/mathjax/lang/de/messages.po b/mathjax/lang/de/messages.po index e60d9676..cbc9d2ca 100644 --- a/mathjax/lang/de/messages.po +++ b/mathjax/lang/de/messages.po @@ -13,9 +13,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:15-0500\n" -"PO-Revision-Date: 2014-06-23 09:55+0000\n" -"Last-Translator: Tobias Diekershoff , 2021\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2021-12-22 16:24+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/mathjax/lang/it/messages.po b/mathjax/lang/it/messages.po index 9aa6154f..eef9ca86 100644 --- a/mathjax/lang/it/messages.po +++ b/mathjax/lang/it/messages.po @@ -10,23 +10,27 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:15-0500\n" -"PO-Revision-Date: 2014-06-23 09:55+0000\n" -"Last-Translator: Sylke Vicious , 2021\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"POT-Creation-Date: 2021-02-01 18:15+0100\n" +"PO-Revision-Date: 2021-02-16 12:51+0000\n" +"Last-Translator: Sylke Vicious \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: mathjax.php:42 +#: mathjax.php:43 msgid "" "The MathJax addon renders mathematical formulae written using the LaTeX " "syntax surrounded by the usual $$ or an eqnarray block in the postings of " "your wall,network tab and private mail." msgstr "Il plugin \"MatJax\" renderizza formule matematiche scritta usando la sintassi LaTeX circondate dalle usuali $$ o un blocco eqnarray nei messaggi della tua bacheca, pagina Rete e messaggi privati." -#: mathjax.php:43 +#: mathjax.php:44 msgid "Use the MathJax renderer" msgstr "Usa il render MathJax" + +#: mathjax.php:45 +msgid "Save Settings" +msgstr "Salva Impostazioni" diff --git a/mathjax/lang/it/strings.php b/mathjax/lang/it/strings.php index f5580a39..4ba4f721 100644 --- a/mathjax/lang/it/strings.php +++ b/mathjax/lang/it/strings.php @@ -3,7 +3,8 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $a->strings['The MathJax addon renders mathematical formulae written using the LaTeX syntax surrounded by the usual $$ or an eqnarray block in the postings of your wall,network tab and private mail.'] = 'Il plugin "MatJax" renderizza formule matematiche scritta usando la sintassi LaTeX circondate dalle usuali $$ o un blocco eqnarray nei messaggi della tua bacheca, pagina Rete e messaggi privati.'; $a->strings['Use the MathJax renderer'] = 'Usa il render MathJax'; +$a->strings['Save Settings'] = 'Salva Impostazioni'; diff --git a/monolog/composer.json b/monolog/composer.json index 7bcb4995..e2117166 100644 --- a/monolog/composer.json +++ b/monolog/composer.json @@ -12,7 +12,7 @@ ], "require": { "php": ">=7.3", - "monolog/monolog": "^2.9" + "monolog/monolog": "^2.8" }, "license": "3-clause BSD license", "config": { diff --git a/monolog/composer.lock b/monolog/composer.lock index f73b2ef0..3f4b225a 100644 --- a/monolog/composer.lock +++ b/monolog/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6fd294bd163b37ac6cc400e0f8785222", + "content-hash": "d360e9eb0b5580e44579a3780be74dec", "packages": [ { "name": "monolog/monolog", - "version": "2.9.1", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1" + "reference": "720488632c590286b88b80e62aa3d3d551ad4a50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f259e2b15fb95494c83f52d3caad003bbf5ffaa1", - "reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/720488632c590286b88b80e62aa3d3d551ad4a50", + "reference": "720488632c590286b88b80e62aa3d3d551ad4a50", "shasum": "" }, "require": { @@ -32,7 +32,7 @@ "doctrine/couchdb": "~1.0@dev", "elasticsearch/elasticsearch": "^7 || ^8", "ext-json": "*", - "graylog2/gelf-php": "^1.4.2 || ^2@dev", + "graylog2/gelf-php": "^1.4.2", "guzzlehttp/guzzle": "^7.4", "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8", @@ -102,7 +102,7 @@ "type": "tidelift" } ], - "time": "2023-02-06T13:44:46+00:00" + "time": "2022-07-24T11:55:47+00:00" }, { "name": "psr/log", diff --git a/monolog/monolog.php b/monolog/monolog.php deleted file mode 100644 index b13efff9..00000000 --- a/monolog/monolog.php +++ /dev/null @@ -1,7 +0,0 @@ -. + * + */ namespace Friendica\Addon\monolog\src\Factory; +use Friendica\Core\Hooks\Capabilities\IAmAStrategy; +use Friendica\Core\Logger\Capabilities\IHaveCallIntrospections; +use Friendica\Core\Logger\Exception\LoggerException; +use Monolog as MonologModel; use Friendica\Addon\monolog\src\Monolog\IntrospectionProcessor; use Friendica\Core\Config\Capability\IManageConfigValues; -use Friendica\Core\Logger\Factory\AbstractLoggerTypeFactory; -use Monolog\Formatter\LineFormatter; -use Monolog\Handler\StreamHandler; -use Monolog\Logger; -use Monolog\Processor\ProcessIdProcessor; -use Monolog\Processor\PsrLogMessageProcessor; -use Monolog\Processor\UidProcessor; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; -require_once __DIR__ . '/../../vendor/autoload.php'; - -class Monolog extends AbstractLoggerTypeFactory +class Monolog implements IAmAStrategy { - public function create(IManageConfigValues $config, string $loglevel = null): LoggerInterface + /** @var IManageConfigValues */ + protected $config; + /** @var string */ + protected $channel = ''; + /** @var string */ + protected $loglevel = LogLevel::NOTICE; + /** @var IHaveCallIntrospections */ + protected $introspection; + + public function __construct(IManageConfigValues $config, IHaveCallIntrospections $introspection, string $channel = '', string $loglevel = LogLevel::NOTICE) + { + $this->config = $config; + $this->channel = $channel; + $this->loglevel = $loglevel; + $this->introspection = $introspection; + } + + public function create(): LoggerInterface { $loggerTimeZone = new \DateTimeZone('UTC'); - $logger = new Logger($this->channel); + $logger = new MonologModel\Logger($this->channel); $logger->setTimezone($loggerTimeZone); - $logger->pushProcessor(new PsrLogMessageProcessor()); - $logger->pushProcessor(new ProcessIdProcessor()); - $logger->pushProcessor(new UidProcessor()); + $logger->pushProcessor(new MonologModel\Processor\PsrLogMessageProcessor()); + $logger->pushProcessor(new MonologModel\Processor\ProcessIdProcessor()); + $logger->pushProcessor(new MonologModel\Processor\UidProcessor()); $logger->pushProcessor(new IntrospectionProcessor($this->introspection, LogLevel::DEBUG)); - $logfile = $config->get('system', 'logfile'); + $stream = $this->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); + if (!is_file($stream) || is_writable($stream)) { + try { + $loglevel = MonologModel\Logger::toMonologLevel($this->loglevel); - // fallback to notice if an invalid loglevel is set - if (!is_int($loglevel)) { - $loglevel = LogLevel::NOTICE; + // fallback to notice if an invalid loglevel is set + if (!is_int($loglevel)) { + $loglevel = LogLevel::NOTICE; + } + + $fileHandler = new MonologModel\Handler\StreamHandler($stream, $loglevel); + + $formatter = new MonologModel\Formatter\LineFormatter("%datetime% %channel% [%level_name%]: %message% %context% %extra%\n"); + $fileHandler->setFormatter($formatter); + + $logger->pushHandler($fileHandler); + + return $logger; + } catch (\Throwable $e) { + throw new LoggerException('Cannot create Loger', $e); } - - $fileHandler = new StreamHandler($logfile, $loglevel); - - $formatter = new LineFormatter("%datetime% %channel% [%level_name%]: %message% %context% %extra%\n"); - $fileHandler->setFormatter($formatter); - - $logger->pushHandler($fileHandler); + } else { + throw new LoggerException(sprintf('Cannot write to file or stream %s', $stream)); } - - return $logger; } } diff --git a/monolog/src/Monolog/IntrospectionProcessor.php b/monolog/src/Monolog/IntrospectionProcessor.php index 2df0e21a..e06e9de1 100644 --- a/monolog/src/Monolog/IntrospectionProcessor.php +++ b/monolog/src/Monolog/IntrospectionProcessor.php @@ -41,7 +41,7 @@ class IntrospectionProcessor implements ProcessorInterface public function __construct(Introspection $introspection, $level = Logger::DEBUG) { $this->level = Logger::toMonologLevel($level); - $introspection->addClasses(['Monolog\\', static::class]); + $introspection->addClasses(['Monolog\\', IntrospectionProcessor::class]); $this->introspection = $introspection; } diff --git a/monolog/static/addon.config.php b/monolog/static/addon.config.php new file mode 100644 index 00000000..155bd60d --- /dev/null +++ b/monolog/static/addon.config.php @@ -0,0 +1,35 @@ +. + * + */ + +$ADDON = [ + 'name' => 'monolog', + 'description' => 'Monolog can send your logs to files, sockets, inboxes, database, etc..', + 'author' => [ + 'name' => 'Philipp Holzer', + 'email' => 'admin@philipp.info', + ], + 'maintainer' => [ + 'name' => 'Philipp Holzer', + 'email' => 'admin@philipp.info', + ], + 'version' => '1.0', + 'status' => 'supported', +]; diff --git a/monolog/static/dependencies.config.php b/monolog/static/dependencies.config.php index e3066594..2da375f7 100644 --- a/monolog/static/dependencies.config.php +++ b/monolog/static/dependencies.config.php @@ -2,7 +2,7 @@ /** * @copyright Copyright (C) 2010-2023, the Friendica project * - * @license GNU AGPL version 3 or any later version + * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -19,11 +19,13 @@ * */ +use Dice\Dice; +use Friendica\Addon\monolog\src\Factory\Monolog; + return [ - \Monolog\Logger::class => [ - 'instanceOf' => \Friendica\Addon\monolog\src\Factory\Monolog::class, + Monolog::class => [ 'call' => [ - ['create', [], \Dice\Dice::CHAIN_CALL], + ['create', [], Dice::CHAIN_CALL], ], ], ]; diff --git a/monolog/static/strategies.config.php b/monolog/static/hooks.config.php similarity index 71% rename from monolog/static/strategies.config.php rename to monolog/static/hooks.config.php index 87153839..31f58f40 100644 --- a/monolog/static/strategies.config.php +++ b/monolog/static/hooks.config.php @@ -2,7 +2,7 @@ /** * @copyright Copyright (C) 2010-2023, the Friendica project * - * @license GNU AGPL version 3 or any later version + * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -19,8 +19,14 @@ * */ +use Friendica\Addon\monolog\src\Factory\Monolog; +use Friendica\Core\Addons\Capabilities\IManageAddons; +use Psr\Log\LoggerInterface; + return [ - \Psr\Log\LoggerInterface::class => [ - \Monolog\Logger::class => ['monolog'], + IManageAddons::ADDON_HOOK_STRATEGIES => [ + LoggerInterface::class => [ + 'monolog' => [Monolog::class, []], + ], ], ]; diff --git a/monolog/tests/MonologTest.php b/monolog/tests/MonologTest.php new file mode 100644 index 00000000..69e2ebec --- /dev/null +++ b/monolog/tests/MonologTest.php @@ -0,0 +1,81 @@ +setUpVfsDir(); + } + + protected function getContent() + { + return $this->logfile->getContent(); + } + + protected function getInstance($level = LogLevel::DEBUG) + { + $this->logfile = vfsStream::newFile('friendica.log') + ->at($this->root); + + $this->config->shouldReceive('get')->with('system', 'logfile')->andReturn($this->logfile->url())->once(); + $this->introspection->shouldReceive('addClasses')->with(['Monolog\\']); + + $loggerFactory = new Monolog($this->config, $this->introspection, 'test', $level); + return $loggerFactory->create(); + } + + /** + * Test if a log entry is correctly interpolated + * + * @note - override the base class, because Monolog adds an "array" prefix to the PsrInterpolate when using arrays + */ + public function testPsrInterpolate() + { + $logger = $this->getInstance(); + + $logger->emergency('A {psr} test', ['psr' => 'working']); + $logger->alert('An {array} test', ['array' => ['it', 'is', 'working']]); + $text = $this->getContent(); + self::assertStringContainsString('A working test', $text); + self::assertStringContainsString('An array["it","is","working"] test', $text); + } + + /** + * Test a message with an exception + * + * @note - override the base class, because Monolog has an own formatter logic for printing exceptions + */ + public function testExceptionHandling() + { + $e = new \Exception("Test String", 123); + $eFollowUp = new \Exception("FollowUp", 456, $e); + + $assertion = '[object] (Exception(code: 456)'; + + $logger = $this->getInstance(); + $logger->alert('test', ['e' => $eFollowUp]); + $text = $this->getContent(); + + self::assertLogline($text); + + self::assertStringContainsString($assertion, $this->getContent()); + } +} diff --git a/monolog/vendor/composer/installed.json b/monolog/vendor/composer/installed.json index ea2bb178..88238fe7 100644 --- a/monolog/vendor/composer/installed.json +++ b/monolog/vendor/composer/installed.json @@ -1,17 +1,17 @@ [ { "name": "monolog/monolog", - "version": "2.9.1", - "version_normalized": "2.9.1.0", + "version": "2.8.0", + "version_normalized": "2.8.0.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1" + "reference": "720488632c590286b88b80e62aa3d3d551ad4a50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f259e2b15fb95494c83f52d3caad003bbf5ffaa1", - "reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/720488632c590286b88b80e62aa3d3d551ad4a50", + "reference": "720488632c590286b88b80e62aa3d3d551ad4a50", "shasum": "" }, "require": { @@ -26,7 +26,7 @@ "doctrine/couchdb": "~1.0@dev", "elasticsearch/elasticsearch": "^7 || ^8", "ext-json": "*", - "graylog2/gelf-php": "^1.4.2 || ^2@dev", + "graylog2/gelf-php": "^1.4.2", "guzzlehttp/guzzle": "^7.4", "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8", @@ -57,7 +57,7 @@ "rollbar/rollbar": "Allow sending log messages to Rollbar", "ruflin/elastica": "Allow sending log messages to an Elastic Search server" }, - "time": "2023-02-06T13:44:46+00:00", + "time": "2022-07-24T11:55:47+00:00", "type": "library", "extra": { "branch-alias": { diff --git a/monolog/vendor/monolog/monolog/CHANGELOG.md b/monolog/vendor/monolog/monolog/CHANGELOG.md index 8a8c6512..7f9db2b0 100644 --- a/monolog/vendor/monolog/monolog/CHANGELOG.md +++ b/monolog/vendor/monolog/monolog/CHANGELOG.md @@ -1,18 +1,3 @@ -### 2.9.1 (2023-02-06) - - * Fixed Logger not being serializable anymore (#1792) - -### 2.9.0 (2023-02-05) - - * 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) * Deprecated `CubeHandler` and `PHPConsoleHandler` as both projects are abandoned and those should not be used anymore (#1734) diff --git a/monolog/vendor/monolog/monolog/composer.json b/monolog/vendor/monolog/monolog/composer.json index b9437d6d..ab775ad6 100644 --- a/monolog/vendor/monolog/monolog/composer.json +++ b/monolog/vendor/monolog/monolog/composer.json @@ -21,7 +21,7 @@ "aws/aws-sdk-php": "^2.4.9 || ^3.0", "doctrine/couchdb": "~1.0@dev", "elasticsearch/elasticsearch": "^7 || ^8", - "graylog2/gelf-php": "^1.4.2 || ^2@dev", + "graylog2/gelf-php": "^1.4.2", "guzzlehttp/guzzle": "^7.4", "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8", diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php index 867ae586..41b56b3c 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php @@ -15,7 +15,6 @@ namespace Monolog\Formatter; * 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 { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php index 3b3e1e7f..a1a79372 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php @@ -47,11 +47,6 @@ class GelfMessageFormatter extends NormalizerFormatter */ protected $maxLength; - /** - * @var int - */ - private $gelfVersion = 2; - /** * Translates Monolog log levels to Graylog2 log priorities. * @@ -83,10 +78,6 @@ class GelfMessageFormatter extends NormalizerFormatter $this->extraPrefix = is_null($extraPrefix) ? '' : $extraPrefix; $this->contextPrefix = $contextPrefix; $this->maxLength = is_null($maxLength) ? self::DEFAULT_MAX_LENGTH : $maxLength; - - if (method_exists(Message::class, 'setFacility')) { - $this->gelfVersion = 1; - } } /** @@ -122,20 +113,16 @@ class GelfMessageFormatter extends NormalizerFormatter $message->setShortMessage(Utils::substr($record['message'], 0, $this->maxLength)); } - 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']); + 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']); } foreach ($extra as $key => $val) { @@ -160,13 +147,11 @@ class GelfMessageFormatter extends NormalizerFormatter $message->setAdditional($this->contextPrefix . $key, $val); } - 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]); - } + /** @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 ca52ebf4..0cd287f5 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/GoogleCloudLoggingFormatter.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/GoogleCloudLoggingFormatter.php @@ -17,7 +17,6 @@ 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 @@ -29,7 +28,7 @@ final class GoogleCloudLoggingFormatter extends JsonFormatter { // Re-key level for GCP logging $record['severity'] = $record['level_name']; - $record['time'] = $record['datetime']->format(DateTimeInterface::RFC3339_EXTENDED); + $record['timestamp'] = $record['datetime']->format(DateTimeInterface::RFC3339_EXTENDED); // Remove keys that are not used by GCP unset($record['level'], $record['level_name'], $record['datetime']); diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php index 994872ce..c4997482 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php @@ -151,14 +151,13 @@ class AmqpHandler extends AbstractProcessingHandler private function createAmqpMessage(string $data): AMQPMessage { - $attributes = [ - 'delivery_mode' => 2, - 'content_type' => 'application/json', - ]; - if ($this->extraAttributes) { - $attributes = array_merge($attributes, $this->extraAttributes); - } - return new AMQPMessage($data, $attributes); + return new AMQPMessage( + $data, + [ + 'delivery_mode' => 2, + 'content_type' => 'application/json', + ] + ); } /** diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php index 95bbfed4..fa383f1c 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php @@ -14,7 +14,6 @@ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\LineFormatter; use Monolog\Utils; -use Monolog\Logger; use function count; use function headers_list; @@ -178,7 +177,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler $extra = static::dump('Extra', $record['extra']); if (empty($context) && empty($extra)) { - $script[] = static::call_array(static::getConsoleMethodForLevel($record['level']), static::handleStyles($record['formatted'])); + $script[] = static::call_array('log', static::handleStyles($record['formatted'])); } else { $script = array_merge( $script, @@ -193,20 +192,6 @@ 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[] */ diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php index 5715d580..b837bdb6 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php @@ -28,7 +28,6 @@ use Monolog\Formatter\FormatterInterface; * @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 { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php index b6d3d3b1..2dd13672 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php @@ -64,18 +64,4 @@ class WhatFailureGroupHandler extends GroupHandler } } } - - /** - * {@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/Logger.php b/monolog/vendor/monolog/monolog/src/Monolog/Logger.php index 84a2f551..1ab75b9e 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Logger.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Logger.php @@ -168,11 +168,6 @@ class Logger implements LoggerInterface, ResettableInterface */ 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 * @@ -194,13 +189,6 @@ class Logger implements LoggerInterface, ResettableInterface $this->setHandlers($handlers); $this->processors = $processors; $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 @@ -344,20 +332,12 @@ class Logger implements LoggerInterface, ResettableInterface } if ($this->detectCycles) { - 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; + $this->logDepth += 1; } - - if ($logDepth === 3) { + if ($this->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 ($logDepth >= 5) { // log depth 4 is let through, so we can log the warning above + } elseif ($this->logDepth >= 5) { // log depth 4 is let through so we can log the warning above return false; } @@ -407,11 +387,7 @@ class Logger implements LoggerInterface, ResettableInterface } } finally { if ($this->detectCycles) { - if (isset($fiber)) { - $this->fiberLogDepth[$fiber]--; - } else { - $this->logDepth--; - } + $this->logDepth--; } } @@ -722,40 +698,4 @@ class Logger implements LoggerInterface, ResettableInterface ($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/PsrLogMessageProcessor.php b/monolog/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php index e7c12176..2c2a00e7 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php @@ -66,8 +66,6 @@ class PsrLogMessageProcessor implements ProcessorInterface } else { $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)) { diff --git a/newmemberwidget/README.md b/newmemberwidget/README.md index e467708e..39522238 100644 --- a/newmemberwidget/README.md +++ b/newmemberwidget/README.md @@ -5,8 +5,8 @@ With this addon you can enable a widget for the sidebar of the network tab, which will be displayed for new members. It contains a linkt to friendicas introduction pages at /newmember and optionally - * a link to the global support group - * a link to an eventually existing local support group + * a link to the global support forum + * a link to an eventually existing local support forum * a welcome message you might want to send to your new members. There is no extra styling added for this added, so it should work with any diff --git a/newmemberwidget/lang/C/messages.po b/newmemberwidget/lang/C/messages.po index 0dc91e13..1e7d608a 100644 --- a/newmemberwidget/lang/C/messages.po +++ b/newmemberwidget/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: 2021-02-01 18:15+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -26,48 +26,48 @@ msgid "Tips for New Members" msgstr "" #: newmemberwidget.php:33 -msgid "Global Support Group" +msgid "Global Support Forum" msgstr "" #: newmemberwidget.php:37 -msgid "Local Support Group" +msgid "Local Support Forum" msgstr "" -#: newmemberwidget.php:62 +#: newmemberwidget.php:65 msgid "Save Settings" msgstr "" -#: newmemberwidget.php:63 +#: newmemberwidget.php:66 msgid "Message" msgstr "" -#: newmemberwidget.php:63 +#: newmemberwidget.php:66 msgid "Your message for new members. You can use bbcode here." msgstr "" -#: newmemberwidget.php:64 -msgid "Add a link to global support group" +#: newmemberwidget.php:67 +msgid "Add a link to global support forum" msgstr "" -#: newmemberwidget.php:64 -msgid "Should a link to the global support group be displayed?" +#: newmemberwidget.php:67 +msgid "Should a link to the global support forum be displayed?" msgstr "" -#: newmemberwidget.php:65 -msgid "Add a link to the local support group" +#: newmemberwidget.php:68 +msgid "Add a link to the local support forum" msgstr "" -#: newmemberwidget.php:65 +#: newmemberwidget.php:68 msgid "" -"If you have a local support group and want to have a link displayed in the " +"If you have a local support forum and want to have a link displayed in the " "widget, check this box." msgstr "" -#: newmemberwidget.php:66 +#: newmemberwidget.php:69 msgid "Name of the local support group" msgstr "" -#: newmemberwidget.php:66 +#: newmemberwidget.php:69 msgid "" "If you checked the above, specify the nickname of the local support " "group here (i.e. helpers)" diff --git a/newmemberwidget/lang/cs/messages.po b/newmemberwidget/lang/cs/messages.po index 387144ab..c774e302 100644 --- a/newmemberwidget/lang/cs/messages.po +++ b/newmemberwidget/lang/cs/messages.po @@ -4,74 +4,73 @@ # # # Translators: -# Aditoo, 2018 -# michal_s , 2014 +# Michal Šupler , 2014 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \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" +"POT-Creation-Date: 2014-06-01 14:12+0200\n" +"PO-Revision-Date: 2014-07-07 19:25+0000\n" +"Last-Translator: Michal Šupler \n" +"Language-Team: Czech (http://www.transifex.com/projects/p/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" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -#: newmemberwidget.php:29 +#: newmemberwidget.php:21 msgid "New Member" msgstr "Nový člen" -#: newmemberwidget.php:30 +#: newmemberwidget.php:22 msgid "Tips for New Members" msgstr "Tipy pro nové členy" -#: newmemberwidget.php:33 -msgid "Global Support Group" -msgstr "" +#: newmemberwidget.php:24 +msgid "Global Support Forum" +msgstr "Globální fórum podpory" -#: newmemberwidget.php:37 -msgid "Local Support Group" -msgstr "" +#: newmemberwidget.php:26 +msgid "Local Support Forum" +msgstr "Lokální fórum podpory" -#: newmemberwidget.php:62 +#: newmemberwidget.php:49 msgid "Save Settings" -msgstr "Uložit nastavení" +msgstr "Uložit Nastavení" -#: newmemberwidget.php:63 +#: newmemberwidget.php:50 msgid "Message" msgstr "Zpráva" -#: newmemberwidget.php:63 +#: newmemberwidget.php:50 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:64 -msgid "Add a link to global support group" -msgstr "" +#: newmemberwidget.php:51 +msgid "Add a link to global support forum" +msgstr "Přidejte odkaz na globální fórum podpory" -#: newmemberwidget.php:64 -msgid "Should a link to the global support group be displayed?" -msgstr "" +#: newmemberwidget.php:51 +msgid "Should a link to the global support forum be displayed?" +msgstr "Má být odkaz na globální fórum podpory zobrazen?" -#: newmemberwidget.php:65 -msgid "Add a link to the local support group" -msgstr "" +#: newmemberwidget.php:52 +msgid "Add a link to the local support forum" +msgstr "Přidejte odkaz na lokální fórum podpory" -#: newmemberwidget.php:65 +#: newmemberwidget.php:52 msgid "" -"If you have a local support group and want to have a link displayed in the " +"If you have a local support forum and wand to have a link displayed in the " "widget, check this box." -msgstr "" +msgstr "Pokud máte lokální fórum podpory a chcete mít zobrazen jeho odkaz, zvolte tuto volbu." -#: newmemberwidget.php:66 +#: newmemberwidget.php:53 msgid "Name of the local support group" -msgstr "Název místního fóra podpory" +msgstr "Název lokálního fóra podpory" -#: newmemberwidget.php:66 +#: newmemberwidget.php:53 msgid "" "If you checked the above, specify the nickname of the local support" " group here (i.e. helpers)" -msgstr "Pokud jste zaškrtl/a výše uvedenou možnost, specifikujte zde přezdívku místní skupiny podpory (např. pomocnici)" +msgstr "Pokud jste výše uvedené zaškrtli, specifikujte zde přezdívku lokální podpůrné skupiny (např. pomahači)" diff --git a/newmemberwidget/lang/cs/strings.php b/newmemberwidget/lang/cs/strings.php index 2f150466..62673df9 100644 --- a/newmemberwidget/lang/cs/strings.php +++ b/newmemberwidget/lang/cs/strings.php @@ -3,12 +3,18 @@ if(! function_exists("string_plural_select_cs")) { function string_plural_select_cs($n){ $n = intval($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; } + if (($n==1)) { return 0; } else if (($n>=2 && $n<=4)) { return 1; } else { return 2; } }} $a->strings['New Member'] = 'Nový člen'; $a->strings['Tips for New Members'] = 'Tipy pro nové členy'; -$a->strings['Save Settings'] = 'Uložit nastavení'; +$a->strings['Global Support Forum'] = 'Globální fórum podpory'; +$a->strings['Local Support Forum'] = 'Lokální 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['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)'; +$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 odkaz na globální fórum podpory zobrazen?'; +$a->strings['Add a link to the local support forum'] = 'Přidejte odkaz na lokální fórum podpory'; +$a->strings['If you have a local support forum and wand to have a link displayed in the widget, check this box.'] = 'Pokud máte lokální fórum podpory a chcete mít zobrazen jeho odkaz, zvolte tuto volbu.'; +$a->strings['Name of the local support group'] = 'Název lokální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 výše uvedené zaškrtli, specifikujte zde přezdívku lokální podpůrné skupiny (např. pomahači)'; diff --git a/newmemberwidget/lang/de/messages.po b/newmemberwidget/lang/de/messages.po index 87289e3e..17696cfd 100644 --- a/newmemberwidget/lang/de/messages.po +++ b/newmemberwidget/lang/de/messages.po @@ -4,17 +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: 2023-06-03 15:50-0400\n" -"PO-Revision-Date: 2014-06-23 10:26+0000\n" -"Last-Translator: Raroun, 2023\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"POT-Creation-Date: 2021-02-01 18:15+0100\n" +"PO-Revision-Date: 2021-03-29 05:38+0000\n" +"Last-Translator: Tobias Diekershoff \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -30,48 +29,48 @@ msgid "Tips for New Members" msgstr "Tipps für neue Nutzer" #: newmemberwidget.php:33 -msgid "Global Support Group" -msgstr "Globale Support-Gruppe" +msgid "Global Support Forum" +msgstr "Globales Forum für Hilfsanfragen" #: newmemberwidget.php:37 -msgid "Local Support Group" -msgstr "Lokale Support-Gruppe" +msgid "Local Support Forum" +msgstr "Lokales Forum für Hilfsanfragen" -#: newmemberwidget.php:62 +#: newmemberwidget.php:65 msgid "Save Settings" msgstr "Einstellungen speichern" -#: newmemberwidget.php:63 +#: newmemberwidget.php:66 msgid "Message" msgstr "Nachricht" -#: newmemberwidget.php:63 +#: newmemberwidget.php:66 msgid "Your message for new members. You can use bbcode here." msgstr "Deine Nachricht für neue Nutzer. BBCode kann verwendet werden." -#: 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 "Add a link to global support forum" +msgstr "Link zum globalen Support-Forum anzeigen" -#: 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:67 +msgid "Should a link to the global support forum be displayed?" +msgstr "Soll ein Link zum globalen Support-Forum angezeigt werden?" -#: 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 +msgid "Add a link to the local support forum" +msgstr "Link zum lokalen Support-Forum anzeigen" -#: newmemberwidget.php:65 +#: newmemberwidget.php:68 msgid "" -"If you have a local support group and want to have a link displayed in the " +"If you have a local support forum and want to have a link displayed in the " "widget, check this box." -msgstr "Wenn Sie eine lokale Support-Gruppe haben und einen Link im Widget anzeigen lassen möchten, markieren Sie dieses Feld." +msgstr "Wenn du ein lokales Support-Forum eingerichtet hast und ein Link darauf angezeigt werden soll, schalte dies ein." -#: newmemberwidget.php:66 +#: newmemberwidget.php:69 msgid "Name of the local support group" msgstr "Name des lokalen Support-Forums" -#: newmemberwidget.php:66 +#: newmemberwidget.php:69 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 aa3e0f88..c7dc503c 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 Group'] = 'Globale Support-Gruppe'; -$a->strings['Local Support Group'] = 'Lokale Support-Gruppe'; +$a->strings['Global Support Forum'] = 'Globales Forum für Hilfsanfragen'; +$a->strings['Local Support Forum'] = 'Lokales Forum für Hilfsanfragen'; $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 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['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['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 b731a041..fb31e143 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: 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" +"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" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: es\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\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 Group" -msgstr "" +msgid "Global Support Forum" +msgstr "Foro de Soporte Global" #: newmemberwidget.php:37 -msgid "Local Support Group" -msgstr "" +msgid "Local Support Forum" +msgstr "Foro de Soporte Local" -#: newmemberwidget.php:62 +#: newmemberwidget.php:65 msgid "Save Settings" msgstr "Guardar Ajustes" -#: newmemberwidget.php:63 +#: newmemberwidget.php:66 msgid "Message" msgstr "Mensaje" -#: newmemberwidget.php:63 +#: newmemberwidget.php:66 msgid "Your message for new members. You can use bbcode here." msgstr "Su mensaje para los nuevos miembros. Puede usar bbcode aquí" -#: newmemberwidget.php:64 -msgid "Add a link to global support group" -msgstr "" +#: 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 "Should a link to the global support group be displayed?" -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:65 -msgid "Add a link to the local support group" -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 +#: newmemberwidget.php:68 msgid "" -"If you have a local support group and want to have a link displayed in the " +"If you have a local support forum and want to have a link displayed in the " "widget, check this box." -msgstr "" +msgstr "Si tiene foro de soporte local y desea que se muestre un enlace en el widget, marque esta casilla." -#: newmemberwidget.php:66 +#: newmemberwidget.php:69 msgid "Name of the local support group" msgstr "Nombre del grupo de soporte local" -#: newmemberwidget.php:66 +#: newmemberwidget.php:69 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 8798813a..28253b73 100644 --- a/newmemberwidget/lang/es/strings.php +++ b/newmemberwidget/lang/es/strings.php @@ -3,12 +3,18 @@ if(! function_exists("string_plural_select_es")) { function string_plural_select_es($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $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 6f52dff8..969efad9 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: 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" +"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" "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:29 +#: newmemberwidget.php:21 msgid "New Member" msgstr "Uus liige" -#: newmemberwidget.php:30 +#: newmemberwidget.php:22 msgid "Tips for New Members" msgstr "Nippe uutele liikmetele" -#: newmemberwidget.php:33 -msgid "Global Support Group" -msgstr "" +#: newmemberwidget.php:24 +msgid "Global Support Forum" +msgstr "Globaalne tugifoorum" -#: newmemberwidget.php:37 -msgid "Local Support Group" -msgstr "" +#: newmemberwidget.php:26 +msgid "Local Support Forum" +msgstr "Lokaalne tugifoorum" -#: newmemberwidget.php:62 +#: newmemberwidget.php:49 msgid "Save Settings" msgstr "Salvesta sätted" -#: newmemberwidget.php:63 +#: newmemberwidget.php:50 msgid "Message" msgstr "Sõnum" -#: newmemberwidget.php:63 +#: newmemberwidget.php:50 msgid "Your message for new members. You can use bbcode here." msgstr "" -#: newmemberwidget.php:64 -msgid "Add a link to global support group" +#: newmemberwidget.php:51 +msgid "Add a link to global support forum" msgstr "" -#: newmemberwidget.php:64 -msgid "Should a link to the global support group be displayed?" +#: newmemberwidget.php:51 +msgid "Should a link to the global support forum be displayed?" msgstr "" -#: newmemberwidget.php:65 -msgid "Add a link to the local support group" +#: newmemberwidget.php:52 +msgid "Add a link to the local support forum" msgstr "" -#: newmemberwidget.php:65 +#: newmemberwidget.php:52 msgid "" -"If you have a local support group and want to have a link displayed in the " +"If you have a local support forum and wand to have a link displayed in the " "widget, check this box." msgstr "" -#: newmemberwidget.php:66 +#: newmemberwidget.php:53 msgid "Name of the local support group" msgstr "" -#: newmemberwidget.php:66 +#: newmemberwidget.php:53 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 e4465d99..3d4f8167 100644 --- a/newmemberwidget/lang/et/strings.php +++ b/newmemberwidget/lang/et/strings.php @@ -7,5 +7,7 @@ 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 3e1f2505..296c2755 100644 --- a/newmemberwidget/lang/fr/messages.po +++ b/newmemberwidget/lang/fr/messages.po @@ -4,7 +4,6 @@ # # # Translators: -# Florent C., 2023 # Hypolite Petovan , 2022 # Nicolas Derive, 2022 # StefOfficiel , 2015 @@ -12,10 +11,10 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-06-03 15:50-0400\n" +"POT-Creation-Date: 2021-02-01 18:15+0100\n" "PO-Revision-Date: 2014-06-23 10:26+0000\n" -"Last-Translator: Florent C., 2023\n" -"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n" +"Last-Translator: Nicolas Derive, 2022\n" +"Language-Team: French (http://www.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" @@ -31,48 +30,48 @@ msgid "Tips for New Members" msgstr "Conseils aux nouveaux venus" #: newmemberwidget.php:33 -msgid "Global Support Group" -msgstr "Groupe de support global" +msgid "Global Support Forum" +msgstr "Forum de support global" #: newmemberwidget.php:37 -msgid "Local Support Group" -msgstr "Groupe de support local" +msgid "Local Support Forum" +msgstr "Forum de support local" -#: newmemberwidget.php:62 +#: newmemberwidget.php:65 msgid "Save Settings" msgstr "Enregistrer les paramètres" -#: newmemberwidget.php:63 +#: newmemberwidget.php:66 msgid "Message" msgstr "Message" -#: newmemberwidget.php:63 +#: newmemberwidget.php:66 msgid "Your message for new members. You can use bbcode here." msgstr "Votre messages aux nouveaux venus. Vous pouvez utiliser des BBCodes." -#: 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 "Add a link to global support forum" +msgstr "Ajouter 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:67 +msgid "Should a link to the global support forum be displayed?" +msgstr "Montrer un lien vers le forum de support global?" -#: 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 +msgid "Add a link to the local support forum" +msgstr "Ajouter un lien vers le forum de support local" -#: newmemberwidget.php:65 +#: newmemberwidget.php:68 msgid "" -"If you have a local support group and want to have a link displayed in the " +"If you have a local support forum and want to have a link displayed in the " "widget, check this box." -msgstr "Si vous avez un groupe de support local et désirez avoir un lien affiché dans l'appliquette/widget, cochez cette case." +msgstr "Si vous avez un forum d'assistance local et désirez avoir un lien affiché dans l'appliquette/widget, cochez cette case." -#: newmemberwidget.php:66 +#: newmemberwidget.php:69 msgid "Name of the local support group" msgstr "Nom du groupe de support local" -#: newmemberwidget.php:66 +#: newmemberwidget.php:69 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 cc437f89..8de178f2 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 Group'] = 'Groupe de support global'; -$a->strings['Local Support Group'] = 'Groupe de support local'; +$a->strings['Global Support Forum'] = 'Forum de support global'; +$a->strings['Local Support Forum'] = 'Forum 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 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['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['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 f3babd21..41453463 100644 --- a/newmemberwidget/lang/hu/messages.po +++ b/newmemberwidget/lang/hu/messages.po @@ -4,15 +4,15 @@ # # # Translators: -# Balázs Úr, 2020-2021,2023 +# Balázs Úr, 2020-2021 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-06-03 15:50-0400\n" +"POT-Creation-Date: 2021-02-01 18:15+0100\n" "PO-Revision-Date: 2014-06-23 10:26+0000\n" -"Last-Translator: Balázs Úr, 2020-2021,2023\n" -"Language-Team: Hungarian (http://app.transifex.com/Friendica/friendica/language/hu/)\n" +"Last-Translator: Balázs Úr, 2020-2021\n" +"Language-Team: Hungarian (http://www.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 Group" -msgstr "Globális támogatási csoport" +msgid "Global Support Forum" +msgstr "Globális támogató fórum" #: newmemberwidget.php:37 -msgid "Local Support Group" -msgstr "Helyi támogatási csoport" +msgid "Local Support Forum" +msgstr "Helyi támogató fórum" -#: newmemberwidget.php:62 +#: newmemberwidget.php:65 msgid "Save Settings" msgstr "Beállítások mentése" -#: newmemberwidget.php:63 +#: newmemberwidget.php:66 msgid "Message" msgstr "Üzenet" -#: newmemberwidget.php:63 +#: newmemberwidget.php:66 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: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 "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 "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: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: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 +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 +#: newmemberwidget.php:68 msgid "" -"If you have a local support group and want to have a link displayed in the " +"If you have a local support forum and want to have a link displayed in the " "widget, check this box." -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." +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." -#: newmemberwidget.php:66 +#: newmemberwidget.php:69 msgid "Name of the local support group" msgstr "A helyi támogató csoport neve" -#: newmemberwidget.php:66 +#: newmemberwidget.php:69 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 2f0066cd..edf2a003 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 Group'] = 'Globális támogatási csoport'; -$a->strings['Local Support Group'] = 'Helyi támogatási csoport'; +$a->strings['Global Support Forum'] = 'Globális támogató fórum'; +$a->strings['Local Support Forum'] = 'Helyi támogató fórum'; $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 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['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['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 91d5c03e..e1a075a9 100644 --- a/newmemberwidget/lang/it/messages.po +++ b/newmemberwidget/lang/it/messages.po @@ -10,15 +10,15 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \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" +"POT-Creation-Date: 2021-02-01 18:15+0100\n" +"PO-Revision-Date: 2021-02-16 12:48+0000\n" +"Last-Translator: Sylke Vicious \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: newmemberwidget.php:29 msgid "New Member" @@ -29,48 +29,48 @@ msgid "Tips for New Members" msgstr "Consigli per i Nuovi Utenti" #: newmemberwidget.php:33 -msgid "Global Support Group" -msgstr "" +msgid "Global Support Forum" +msgstr "Forum Globale di Supporto" #: newmemberwidget.php:37 -msgid "Local Support Group" -msgstr "" +msgid "Local Support Forum" +msgstr "Forum Locale di Supporto" -#: newmemberwidget.php:62 +#: newmemberwidget.php:65 msgid "Save Settings" msgstr "Salva Impostazioni" -#: newmemberwidget.php:63 +#: newmemberwidget.php:66 msgid "Message" msgstr "Messaggio" -#: newmemberwidget.php:63 +#: newmemberwidget.php:66 msgid "Your message for new members. You can use bbcode here." msgstr "Il tuo messaggio per i nuovi utenti. Puoi usare BBCode" -#: newmemberwidget.php:64 -msgid "Add a link to global support group" -msgstr "" +#: newmemberwidget.php:67 +msgid "Add a link to global support forum" +msgstr "Aggiunge un collegamento al forum di supporto globale" -#: newmemberwidget.php:64 -msgid "Should a link to the global support group be displayed?" -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:65 -msgid "Add a link to the local support group" -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 +#: newmemberwidget.php:68 msgid "" -"If you have a local support group and want to have a link displayed in the " +"If you have a local support forum and want to have a link displayed in the " "widget, check this box." -msgstr "" +msgstr "Se hai un forum di supporto locale e vuoi che sia mostrato il collegamento nel widget, seleziona questo box." -#: newmemberwidget.php:66 +#: newmemberwidget.php:69 msgid "Name of the local support group" msgstr "Nome del gruppo locale di supporto" -#: newmemberwidget.php:66 +#: newmemberwidget.php:69 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 56798c2a..8e8ae7c7 100644 --- a/newmemberwidget/lang/it/strings.php +++ b/newmemberwidget/lang/it/strings.php @@ -3,12 +3,18 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $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/nl/messages.po b/newmemberwidget/lang/nl/messages.po index 232ae370..a1ce7269 100644 --- a/newmemberwidget/lang/nl/messages.po +++ b/newmemberwidget/lang/nl/messages.po @@ -4,73 +4,72 @@ # # # Translators: -# a a , 2019 # Jeroen De Meerleer , 2018 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: 2014-06-23 10:26+0000\n" -"Last-Translator: a a , 2019\n" -"Language-Team: Dutch (http://app.transifex.com/Friendica/friendica/language/nl/)\n" +"POT-Creation-Date: 2014-06-01 14:12+0200\n" +"PO-Revision-Date: 2018-08-24 13:40+0000\n" +"Last-Translator: Jeroen De Meerleer \n" +"Language-Team: Dutch (http://www.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" -#: newmemberwidget.php:29 +#: newmemberwidget.php:21 msgid "New Member" msgstr "Nieuw lid" -#: newmemberwidget.php:30 +#: newmemberwidget.php:22 msgid "Tips for New Members" msgstr "Tips voor nieuwe leden" -#: newmemberwidget.php:33 +#: newmemberwidget.php:24 msgid "Global Support Forum" msgstr "" -#: newmemberwidget.php:37 +#: newmemberwidget.php:26 msgid "Local Support Forum" msgstr "" -#: newmemberwidget.php:65 +#: newmemberwidget.php:49 msgid "Save Settings" msgstr "Instellingen opslaan" -#: newmemberwidget.php:66 +#: newmemberwidget.php:50 msgid "Message" -msgstr "Bericht" +msgstr "" -#: newmemberwidget.php:66 +#: newmemberwidget.php:50 msgid "Your message for new members. You can use bbcode here." -msgstr "Uw bericht aan nieuwe leden. U kunt hier bbcode gebruiken." +msgstr "" -#: newmemberwidget.php:67 +#: newmemberwidget.php:51 msgid "Add a link to global support forum" msgstr "" -#: newmemberwidget.php:67 +#: newmemberwidget.php:51 msgid "Should a link to the global support forum be displayed?" msgstr "" -#: newmemberwidget.php:68 +#: newmemberwidget.php:52 msgid "Add a link to the local support forum" msgstr "" -#: newmemberwidget.php:68 +#: newmemberwidget.php:52 msgid "" -"If you have a local support forum and want to have a link displayed in the " +"If you have a local support forum and wand to have a link displayed in the " "widget, check this box." msgstr "" -#: newmemberwidget.php:69 +#: newmemberwidget.php:53 msgid "Name of the local support group" msgstr "" -#: newmemberwidget.php:69 +#: newmemberwidget.php:53 msgid "" "If you checked the above, specify the nickname of the local support" " group here (i.e. helpers)" diff --git a/newmemberwidget/lang/nl/strings.php b/newmemberwidget/lang/nl/strings.php index e81e7fcd..0d492eea 100644 --- a/newmemberwidget/lang/nl/strings.php +++ b/newmemberwidget/lang/nl/strings.php @@ -8,5 +8,3 @@ function string_plural_select_nl($n){ $a->strings['New Member'] = 'Nieuw lid'; $a->strings['Tips for New Members'] = 'Tips voor nieuwe leden'; $a->strings['Save Settings'] = 'Instellingen opslaan'; -$a->strings['Message'] = 'Bericht'; -$a->strings['Your message for new members. You can use bbcode here.'] = 'Uw bericht aan nieuwe leden. U kunt hier bbcode gebruiken.'; diff --git a/newmemberwidget/lang/pl/messages.po b/newmemberwidget/lang/pl/messages.po index 90dda1ff..3f1838b5 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: 2023-06-03 15:50-0400\n" +"POT-Creation-Date: 2021-02-01 18:15+0100\n" "PO-Revision-Date: 2014-06-23 10:26+0000\n" "Last-Translator: Piotr Strębski , 2022\n" -"Language-Team: Polish (http://app.transifex.com/Friendica/friendica/language/pl/)\n" +"Language-Team: Polish (http://www.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 Group" -msgstr "" +msgid "Global Support Forum" +msgstr "Globalne forum pomocy technicznej" #: newmemberwidget.php:37 -msgid "Local Support Group" -msgstr "" +msgid "Local Support Forum" +msgstr "Lokalne Forum Wsparcia" -#: newmemberwidget.php:62 +#: newmemberwidget.php:65 msgid "Save Settings" msgstr "Zapisz ustawienia" -#: newmemberwidget.php:63 +#: newmemberwidget.php:66 msgid "Message" msgstr "Wiadomość" -#: newmemberwidget.php:63 +#: newmemberwidget.php:66 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:64 -msgid "Add a link to global support group" -msgstr "" +#: newmemberwidget.php:67 +msgid "Add a link to global support forum" +msgstr "Dodaj odnośnik do globalnego forum pomocy technicznej" -#: newmemberwidget.php:64 -msgid "Should a link to the global support group be displayed?" -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:65 -msgid "Add a link to the local support group" -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 +#: newmemberwidget.php:68 msgid "" -"If you have a local support group and want to have a link displayed in the " +"If you have a local support forum and want to have a link displayed in the " "widget, check this box." -msgstr "" +msgstr "Jeżeli masz lokalne wsparcie forum i chcesz mieć łącze wyświetlane w widżecie, zaznacz to pole wyboru." -#: newmemberwidget.php:66 +#: newmemberwidget.php:69 msgid "Name of the local support group" msgstr "Nazwa grupy lokalnej pomocy technicznej" -#: newmemberwidget.php:66 +#: newmemberwidget.php:69 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 22a9e9a9..97103add 100644 --- a/newmemberwidget/lang/pl/strings.php +++ b/newmemberwidget/lang/pl/strings.php @@ -7,8 +7,14 @@ 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 1fe611e9..94d61e3f 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: 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" +"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" "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:29 +#: newmemberwidget.php:21 msgid "New Member" msgstr "Новичок" -#: newmemberwidget.php:30 +#: newmemberwidget.php:22 msgid "Tips for New Members" msgstr "Советы новичкам" -#: newmemberwidget.php:33 -msgid "Global Support Group" -msgstr "" +#: newmemberwidget.php:24 +msgid "Global Support Forum" +msgstr "Общий форум поддержки" -#: newmemberwidget.php:37 -msgid "Local Support Group" -msgstr "" +#: newmemberwidget.php:26 +msgid "Local Support Forum" +msgstr "Местный форум поддержки" -#: newmemberwidget.php:62 +#: newmemberwidget.php:49 msgid "Save Settings" msgstr "Сохранить настройки" -#: newmemberwidget.php:63 +#: newmemberwidget.php:50 msgid "Message" msgstr "Сообщение" -#: newmemberwidget.php:63 +#: newmemberwidget.php:50 msgid "Your message for new members. You can use bbcode here." msgstr "Ваше сообщение новичкам. Вы можете использовать BBCode." -#: newmemberwidget.php:64 -msgid "Add a link to global support group" -msgstr "" +#: newmemberwidget.php:51 +msgid "Add a link to global support forum" +msgstr "Добавить ссылку на общий форум поддержки" -#: newmemberwidget.php:64 -msgid "Should a link to the global support group be displayed?" -msgstr "" +#: newmemberwidget.php:51 +msgid "Should a link to the global support forum be displayed?" +msgstr "Показывать ссылку на общий форум поддержки?" -#: newmemberwidget.php:65 -msgid "Add a link to the local support group" -msgstr "" +#: newmemberwidget.php:52 +msgid "Add a link to the local support forum" +msgstr "Добавить ссылку на местный форум поддержки" -#: newmemberwidget.php:65 +#: newmemberwidget.php:52 msgid "" -"If you have a local support group and want to have a link displayed in the " +"If you have a local support forum and wand to have a link displayed in the " "widget, check this box." -msgstr "" +msgstr "Если у вас есть местный форум поддержки и вы хотите добавить ссылку на него, включите это." -#: newmemberwidget.php:66 +#: newmemberwidget.php:53 msgid "Name of the local support group" msgstr "Название местной группы поддержки" -#: newmemberwidget.php:66 +#: newmemberwidget.php:53 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 6f27bb1a..7992e64b 100644 --- a/newmemberwidget/lang/ru/strings.php +++ b/newmemberwidget/lang/ru/strings.php @@ -7,8 +7,14 @@ 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 a1a6167a..0d6171b2 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: 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" +"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" "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 Group" +msgid "Global Support Forum" msgstr "" #: newmemberwidget.php:37 -msgid "Local Support Group" -msgstr "" +msgid "Local Support Forum" +msgstr "Lokalt hjälpforum" -#: newmemberwidget.php:62 +#: newmemberwidget.php:65 msgid "Save Settings" msgstr "Spara inställningar" -#: newmemberwidget.php:63 +#: newmemberwidget.php:66 msgid "Message" msgstr "Meddelande" -#: newmemberwidget.php:63 +#: newmemberwidget.php:66 msgid "Your message for new members. You can use bbcode here." msgstr "" -#: newmemberwidget.php:64 -msgid "Add a link to global support group" +#: newmemberwidget.php:67 +msgid "Add a link to global support forum" msgstr "" -#: newmemberwidget.php:64 -msgid "Should a link to the global support group be displayed?" +#: newmemberwidget.php:67 +msgid "Should a link to the global support forum be displayed?" msgstr "" -#: newmemberwidget.php:65 -msgid "Add a link to the local support group" +#: newmemberwidget.php:68 +msgid "Add a link to the local support forum" msgstr "" -#: newmemberwidget.php:65 +#: newmemberwidget.php:68 msgid "" -"If you have a local support group and want to have a link displayed in the " +"If you have a local support forum and want to have a link displayed in the " "widget, check this box." msgstr "" -#: newmemberwidget.php:66 +#: newmemberwidget.php:69 msgid "Name of the local support group" msgstr "" -#: newmemberwidget.php:66 +#: newmemberwidget.php:69 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 e92a428f..38292306 100644 --- a/newmemberwidget/lang/sv/strings.php +++ b/newmemberwidget/lang/sv/strings.php @@ -7,5 +7,6 @@ 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/newmemberwidget/newmemberwidget.php b/newmemberwidget/newmemberwidget.php index 01977d0c..5689971b 100644 --- a/newmemberwidget/newmemberwidget.php +++ b/newmemberwidget/newmemberwidget.php @@ -12,7 +12,6 @@ use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; -use Friendica\Model\User; function newmemberwidget_install() { @@ -31,16 +30,16 @@ function newmemberwidget_network_mod_init ($b) $t .= '' . DI::l10n()->t('Tips for New Members') . '
'; if (DI::config()->get('newmemberwidget','linkglobalsupport', false)) { - $t .= '' . DI::l10n()->t('Global Support Group') . '
'; + $t .= ''.DI::l10n()->t('Global Support Forum').'
'; } if (DI::config()->get('newmemberwidget','linklocalsupport', false)) { - $t .= '' . DI::l10n()->t('Local Support Group') . '
'; + $t .= ''.DI::l10n()->t('Local Support Forum').'
'; } $ft = DI::config()->get('newmemberwidget','freetext', ''); if (!empty($ft)) { - $t .= '

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

'; + $t .= '

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

'; } $t .= '
'; @@ -62,8 +61,8 @@ function newmemberwidget_addon_admin(string &$o) $o = Renderer::replaceMacros($t, [ '$submit' => DI::l10n()->t('Save Settings'), '$freetext' => ["freetext", DI::l10n()->t("Message"), DI::config()->get("newmemberwidget", "freetext"), DI::l10n()->t("Your message for new members. You can use bbcode here.")], - '$linkglobalsupport' => ["linkglobalsupport", DI::l10n()->t('Add a link to global support group'), DI::config()->get('newmemberwidget', 'linkglobalsupport'), DI::l10n()->t('Should a link to the global support group be displayed?')." (@helpers)"], - '$linklocalsupport' => ["linklocalsupport", DI::l10n()->t('Add a link to the local support group'), DI::config()->get('newmemberwidget', 'linklocalsupport'), DI::l10n()->t('If you have a local support group and want to have a link displayed in the widget, check this box.')], + '$linkglobalsupport' => ["linkglobalsupport", DI::l10n()->t('Add a link to global support forum'), DI::config()->get('newmemberwidget', 'linkglobalsupport'), DI::l10n()->t('Should a link to the global support forum be displayed?')." (@helpers)"], + '$linklocalsupport' => ["linklocalsupport", DI::l10n()->t('Add a link to the local support forum'), DI::config()->get('newmemberwidget', 'linklocalsupport'), DI::l10n()->t('If you have a local support forum and want to have a link displayed in the widget, check this box.')], '$localsupportname' => ["localsupportname", DI::l10n()->t('Name of the local support group'), DI::config()->get('newmemberwidget', 'localsupport'), DI::l10n()->t('If you checked the above, specify the nickname of the local support group here (i.e. helpers)')], ]); } diff --git a/notifyall/NotifyAllEmail.php b/notifyall/NotifyAllEmail.php index 7a00a2c9..abdb9549 100644 --- a/notifyall/NotifyAllEmail.php +++ b/notifyall/NotifyAllEmail.php @@ -25,7 +25,6 @@ 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; /** @@ -44,16 +43,16 @@ class NotifyAllEmail extends Email } if (!$config->get('config', 'sender_email')) { - $sender_email = 'noreply@' . $baseUrl->getHost(); + $sender_email = 'noreply@' . $baseUrl->getHostname(); } else { $sender_email = $config->get('config', 'sender_email'); } $subject = $_REQUEST['subject']; - $textversion = strip_tags(html_entity_decode(BBCode::convertForUriId(User::getSystemUriId(), stripslashes(str_replace(["\\r", "\\n"], ["", "\n"], $text))), ENT_QUOTES, 'UTF-8')); + $textversion = strip_tags(html_entity_decode(BBCode::convert(stripslashes(str_replace(["\\r", "\\n"], ["", "\n"], $text))), ENT_QUOTES, 'UTF-8')); - $htmlversion = BBCode::convertForUriId(User::getSystemUriId(), stripslashes(str_replace(["\\r", "\\n"], ["", "
\n"], $text))); + $htmlversion = BBCode::convert(stripslashes(str_replace(["\\r", "\\n"], ["", "
\n"], $text))); parent::__construct($sender_name, $sender_email, $sender_email, '', $subject, $htmlversion, $textversion); } diff --git a/notifyall/lang/de/messages.po b/notifyall/lang/de/messages.po index 372694ef..c8b4deac 100644 --- a/notifyall/lang/de/messages.po +++ b/notifyall/lang/de/messages.po @@ -15,7 +15,7 @@ msgstr "" "POT-Creation-Date: 2021-02-01 18:15+0100\n" "PO-Revision-Date: 2016-08-14 19:29+0000\n" "Last-Translator: Ulf Rompe , 2019\n" -"Language-Team: German (https://app.transifex.com/Friendica/teams/12172/de/)\n" +"Language-Team: German (https://www.transifex.com/Friendica/teams/12172/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/notifyall/lang/hu/messages.po b/notifyall/lang/hu/messages.po index 8d030ab8..808d22ea 100644 --- a/notifyall/lang/hu/messages.po +++ b/notifyall/lang/hu/messages.po @@ -14,7 +14,7 @@ msgstr "" "POT-Creation-Date: 2021-02-01 18:15+0100\n" "PO-Revision-Date: 2016-08-14 19:29+0000\n" "Last-Translator: Balázs Úr, 2021\n" -"Language-Team: Hungarian (https://app.transifex.com/Friendica/teams/12172/hu/)\n" +"Language-Team: Hungarian (https://www.transifex.com/Friendica/teams/12172/hu/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/notifyall/lang/it/messages.po b/notifyall/lang/it/messages.po index d590306b..1667afe8 100644 --- a/notifyall/lang/it/messages.po +++ b/notifyall/lang/it/messages.po @@ -15,12 +15,12 @@ msgstr "" "POT-Creation-Date: 2021-02-01 18:15+0100\n" "PO-Revision-Date: 2016-08-14 19:29+0000\n" "Last-Translator: fabrixxm , 2017\n" -"Language-Team: Italian (https://app.transifex.com/Friendica/teams/12172/it/)\n" +"Language-Team: Italian (https://www.transifex.com/Friendica/teams/12172/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: NotifyAllEmail.php:40 #, php-format diff --git a/notifyall/lang/it/strings.php b/notifyall/lang/it/strings.php index 630f693a..0d719df1 100644 --- a/notifyall/lang/it/strings.php +++ b/notifyall/lang/it/strings.php @@ -3,7 +3,7 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $a->strings['%s Administrator'] = 'Amministratore %s'; $a->strings['%1$s, %2$s Administrator'] = '%1$s, amministratore di %2$s'; diff --git a/notifyall/notifyall.php b/notifyall/notifyall.php index 966a9184..0c291f04 100644 --- a/notifyall/notifyall.php +++ b/notifyall/notifyall.php @@ -24,7 +24,7 @@ function notifyall_module() {} function notifyall_addon_admin(string &$o) { - $o = '
    ' . DI::l10n()->t('Send email to all members') . '
'; + $o = '
    ' . DI::l10n()->t('Send email to all members') . '
'; } diff --git a/nsfw/lang/cs/messages.po b/nsfw/lang/cs/messages.po index 34a931ad..fc585d80 100644 --- a/nsfw/lang/cs/messages.po +++ b/nsfw/lang/cs/messages.po @@ -11,17 +11,21 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "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: Aditoo, 2018\n" -"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" +"POT-Creation-Date: 2018-04-01 11:11-0400\n" +"PO-Revision-Date: 2018-08-16 10:09+0000\n" +"Last-Translator: Aditoo\n" +"Language-Team: Czech (http://www.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" -#: nsfw.php:65 +#: nsfw.php:77 nsfw.php:81 +msgid "Content Filter (NSFW and more)" +msgstr "Filtr obsahu (citlivý obsah a další)" + +#: nsfw.php:85 msgid "" "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 " @@ -29,35 +33,32 @@ msgid "" "is also useful for hiding irrelevant or annoying content from direct view." msgstr "Tento doplněk vyhledává specifikovaná slova/text v příspěvcích a skrývá je. Může být použit pro filtrování obsahu označeného štítky, jako například #NSFW, který může být považován za nevhodný v určitých časech či místech, například když jste v práci. Může být také užitečný ke skrývání nepodstatného či nepříjemného obsahu z přímého pohledu." -#: nsfw.php:66 +#: nsfw.php:86 msgid "Enable Content filter" msgstr "Povolit filtr obsahu" -#: nsfw.php:67 +#: nsfw.php:89 msgid "Comma separated list of keywords to hide" -msgstr "Seznam klíčových slov ke skrytí, oddělených čárkami" +msgstr "Čárkou oddělený seznam klíčových slov ke skrytí" -#: nsfw.php:67 -msgid "" -"Use /expression/ to provide regular expressions, #tag to specfically match " -"hashtags (case-insensitive), or regular words (case-sensitive)" -msgstr "" +#: nsfw.php:93 +msgid "Save Settings" +msgstr "Uložit nastavení" -#: nsfw.php:72 -msgid "Content Filter (NSFW and more)" -msgstr "Filtr obsahu (citlivý obsah a další)" +#: nsfw.php:94 +msgid "Use /expression/ to provide regular expressions" +msgstr "Použijte /výraz/ pro použití regulárních výrazů" -#: nsfw.php:96 -#, php-format -msgid "Regular expression \"%s\" fails to compile" -msgstr "" +#: nsfw.php:109 +msgid "NSFW Settings saved." +msgstr "Nastavení NSFW uloženo" -#: nsfw.php:154 +#: nsfw.php:162 #, php-format msgid "Filtered tag: %s" -msgstr "Filtrovaný štítek: %s" +msgstr "Filtrovaná značka: %s" -#: nsfw.php:156 +#: nsfw.php:164 #, php-format msgid "Filtered word: %s" msgstr "Filtrované slovo: %s" diff --git a/nsfw/lang/cs/strings.php b/nsfw/lang/cs/strings.php index 4898f2f1..8b5fccca 100644 --- a/nsfw/lang/cs/strings.php +++ b/nsfw/lang/cs/strings.php @@ -5,9 +5,12 @@ function string_plural_select_cs($n){ $n = intval($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['Content Filter (NSFW and more)'] = 'Filtr obsahu (citlivý obsah a další)'; $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.'] = 'Tento doplněk vyhledává specifikovaná slova/text v příspěvcích a skrývá je. Může být použit pro filtrování obsahu označeného štítky, jako například #NSFW, který může být považován za nevhodný v určitých časech či místech, například když jste v práci. Může být také užitečný ke skrývání nepodstatného či nepříjemného obsahu z přímého pohledu.'; $a->strings['Enable Content filter'] = 'Povolit filtr obsahu'; -$a->strings['Comma separated list of keywords to hide'] = 'Seznam klíčových slov ke skrytí, oddělených čárkami'; -$a->strings['Content Filter (NSFW and more)'] = 'Filtr obsahu (citlivý obsah a další)'; -$a->strings['Filtered tag: %s'] = 'Filtrovaný štítek: %s'; +$a->strings['Comma separated list of keywords to hide'] = 'Čárkou oddělený seznam klíčových slov ke skrytí'; +$a->strings['Save Settings'] = 'Uložit nastavení'; +$a->strings['Use /expression/ to provide regular expressions'] = 'Použijte /výraz/ pro použití regulárních výrazů'; +$a->strings['NSFW Settings saved.'] = 'Nastavení NSFW uloženo'; +$a->strings['Filtered tag: %s'] = 'Filtrovaná značka: %s'; $a->strings['Filtered word: %s'] = 'Filtrované slovo: %s'; diff --git a/nsfw/lang/de/messages.po b/nsfw/lang/de/messages.po index 4fefb60c..350b2bbe 100644 --- a/nsfw/lang/de/messages.po +++ b/nsfw/lang/de/messages.po @@ -6,7 +6,6 @@ # Translators: # Andreas H., 2014 # hoergen , 2018 -# foss , 2022 # Tobias Diekershoff , 2014 # Tobias Diekershoff , 2018,2022 # Ulf Rompe , 2019 @@ -14,10 +13,10 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-12-10 14:42-0500\n" +"POT-Creation-Date: 2022-11-18 11:57-0500\n" "PO-Revision-Date: 2014-06-23 10:34+0000\n" -"Last-Translator: foss , 2022\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"Last-Translator: Tobias Diekershoff , 2018,2022\n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -50,17 +49,12 @@ msgstr "Verwende /ausdruck/ für reguläre Ausdrücke, #tag um einen speziellen msgid "Content Filter (NSFW and more)" msgstr "Inhaltsfilter (NSFW und mehr)" -#: nsfw.php:96 -#, php-format -msgid "Regular expression \"%s\" fails to compile" -msgstr "Regulärer Ausdruck \"%s\" schlägt beim Kompiliern fehl." - -#: nsfw.php:154 +#: nsfw.php:140 #, php-format msgid "Filtered tag: %s" msgstr "Gefiltertes Schlagwort: %s" -#: nsfw.php:156 +#: nsfw.php:142 #, php-format msgid "Filtered word: %s" msgstr "Gefilterter Begriff: %s" diff --git a/nsfw/lang/de/strings.php b/nsfw/lang/de/strings.php index 9e0546ad..e538e37c 100644 --- a/nsfw/lang/de/strings.php +++ b/nsfw/lang/de/strings.php @@ -10,6 +10,5 @@ $a->strings['Enable Content filter'] = 'Aktiviere den Inhaltsfilter'; $a->strings['Comma separated list of keywords to hide'] = 'Durch Kommata getrennte Liste von Schlüsselwörtern, die verborgen werden sollen'; $a->strings['Use /expression/ to provide regular expressions, #tag to specfically match hashtags (case-insensitive), or regular words (case-sensitive)'] = 'Verwende /ausdruck/ für reguläre Ausdrücke, #tag um einen speziellen Hashtag zu filtern (unabhängig von der Groß- und Kleinschreibung) oder einfache Wörter (Groß- und Kleinschreibung beachten).'; $a->strings['Content Filter (NSFW and more)'] = 'Inhaltsfilter (NSFW und mehr)'; -$a->strings['Regular expression "%s" fails to compile'] = 'Regulärer Ausdruck "%s" schlägt beim Kompiliern fehl.'; $a->strings['Filtered tag: %s'] = 'Gefiltertes Schlagwort: %s'; $a->strings['Filtered word: %s'] = 'Gefilterter Begriff: %s'; diff --git a/nsfw/lang/es/messages.po b/nsfw/lang/es/messages.po index 43fde3cb..d1a72567 100644 --- a/nsfw/lang/es/messages.po +++ b/nsfw/lang/es/messages.po @@ -10,17 +10,21 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "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: Senex Petrovic , 2021\n" -"Language-Team: Spanish (http://app.transifex.com/Friendica/friendica/language/es/)\n" +"POT-Creation-Date: 2021-02-01 18:15+0100\n" +"PO-Revision-Date: 2021-04-06 01:49+0000\n" +"Last-Translator: Senex Petrovic \n" +"Language-Team: Spanish (http://www.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=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: nsfw.php:65 +#: nsfw.php:68 nsfw.php:72 +msgid "Content Filter (NSFW and more)" +msgstr "Filtro de contenido (NSFW y más)" + +#: nsfw.php:76 msgid "" "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 " @@ -28,35 +32,28 @@ msgid "" "is also useful for hiding irrelevant or annoying content from direct view." msgstr "Este complemento busca palabras / texto específicos en las publicaciones y las contrae. Se puede utilizar para filtrar contenido etiquetado con, por ejemplo, #NSFW que puede considerarse inapropiado en determinados momentos o lugares, como en el trabajo. También es útil para ocultar contenido irrelevante o molesto de la vista directa." -#: nsfw.php:66 +#: nsfw.php:77 msgid "Enable Content filter" msgstr "Habilitar filtro de contenido" -#: nsfw.php:67 +#: nsfw.php:80 msgid "Comma separated list of keywords to hide" msgstr "Lista de palabras claves separadas por coma para colapsar el contenido correspondiente." -#: nsfw.php:67 -msgid "" -"Use /expression/ to provide regular expressions, #tag to specfically match " -"hashtags (case-insensitive), or regular words (case-sensitive)" -msgstr "" +#: nsfw.php:84 +msgid "Save Settings" +msgstr "Grabar ajustes" -#: nsfw.php:72 -msgid "Content Filter (NSFW and more)" -msgstr "Filtro de contenido (NSFW y más)" +#: nsfw.php:85 +msgid "Use /expression/ to provide regular expressions" +msgstr "Utiliza /expresión/ para proveer expresiones regulares." -#: nsfw.php:96 -#, php-format -msgid "Regular expression \"%s\" fails to compile" -msgstr "" - -#: nsfw.php:154 +#: nsfw.php:152 #, php-format msgid "Filtered tag: %s" msgstr "Etiqueta filtrada: %s" -#: nsfw.php:156 +#: nsfw.php:154 #, php-format msgid "Filtered word: %s" msgstr "Palabra filtrada: %s" diff --git a/nsfw/lang/es/strings.php b/nsfw/lang/es/strings.php index 4b41bd14..e46967a6 100644 --- a/nsfw/lang/es/strings.php +++ b/nsfw/lang/es/strings.php @@ -3,11 +3,13 @@ if(! function_exists("string_plural_select_es")) { function string_plural_select_es($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} +$a->strings['Content Filter (NSFW and more)'] = 'Filtro de contenido (NSFW y más)'; $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.'] = 'Este complemento busca palabras / texto específicos en las publicaciones y las contrae. Se puede utilizar para filtrar contenido etiquetado con, por ejemplo, #NSFW que puede considerarse inapropiado en determinados momentos o lugares, como en el trabajo. También es útil para ocultar contenido irrelevante o molesto de la vista directa.'; $a->strings['Enable Content filter'] = 'Habilitar filtro de contenido'; $a->strings['Comma separated list of keywords to hide'] = 'Lista de palabras claves separadas por coma para colapsar el contenido correspondiente.'; -$a->strings['Content Filter (NSFW and more)'] = 'Filtro de contenido (NSFW y más)'; +$a->strings['Save Settings'] = 'Grabar ajustes'; +$a->strings['Use /expression/ to provide regular expressions'] = 'Utiliza /expresión/ para proveer expresiones regulares.'; $a->strings['Filtered tag: %s'] = 'Etiqueta filtrada: %s'; $a->strings['Filtered word: %s'] = 'Palabra filtrada: %s'; diff --git a/nsfw/lang/fr/messages.po b/nsfw/lang/fr/messages.po index 36fd22cc..58066902 100644 --- a/nsfw/lang/fr/messages.po +++ b/nsfw/lang/fr/messages.po @@ -4,18 +4,17 @@ # # # Translators: -# Florent C., 2023 -# Nicolas Derive, 2022-2023 +# Nicolas Derive, 2022 # StefOfficiel , 2015 # Vincent Vindarel , 2018 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-12-10 14:42-0500\n" +"POT-Creation-Date: 2022-11-18 11:57-0500\n" "PO-Revision-Date: 2014-06-23 10:34+0000\n" -"Last-Translator: Florent C., 2023\n" -"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n" +"Last-Translator: Nicolas Derive, 2022\n" +"Language-Team: French (http://www.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" @@ -42,23 +41,18 @@ 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 tag (insensible à la casse), ou des mots classiques (sensible à la casse)" +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)" #: nsfw.php:72 msgid "Content Filter (NSFW and more)" msgstr "Filtre de contenu (NSFW et autres)" -#: nsfw.php:96 -#, php-format -msgid "Regular expression \"%s\" fails to compile" -msgstr "La compilation de l'expression régulière \"%s\" a échoué" - -#: nsfw.php:154 +#: nsfw.php:140 #, php-format msgid "Filtered tag: %s" -msgstr "Tag filtré : %s" +msgstr "Tag filtré: %s" -#: nsfw.php:156 +#: nsfw.php:142 #, php-format msgid "Filtered word: %s" msgstr "Mot filtré: %s" diff --git a/nsfw/lang/fr/strings.php b/nsfw/lang/fr/strings.php index fc03d5ad..7b334956 100644 --- a/nsfw/lang/fr/strings.php +++ b/nsfw/lang/fr/strings.php @@ -8,8 +8,7 @@ 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 tag (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 mot-dièse (hashtag, 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/nsfw/lang/hu/messages.po b/nsfw/lang/hu/messages.po index 9632a2ff..a862c0da 100644 --- a/nsfw/lang/hu/messages.po +++ b/nsfw/lang/hu/messages.po @@ -4,15 +4,15 @@ # # # Translators: -# Balázs Úr, 2020-2023 +# Balázs Úr, 2020-2022 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-12-10 14:42-0500\n" +"POT-Creation-Date: 2022-11-18 11:57-0500\n" "PO-Revision-Date: 2014-06-23 10:34+0000\n" -"Last-Translator: Balázs Úr, 2020-2023\n" -"Language-Team: Hungarian (http://app.transifex.com/Friendica/friendica/language/hu/)\n" +"Last-Translator: Balázs Úr, 2020-2022\n" +"Language-Team: Hungarian (http://www.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" @@ -45,17 +45,12 @@ msgstr "Használjon /kifejezést/ reguláris kifejezések megadásához, #címk msgid "Content Filter (NSFW and more)" msgstr "Tartalomszűrő (érzékeny tartalmak és egyebek)" -#: nsfw.php:96 -#, php-format -msgid "Regular expression \"%s\" fails to compile" -msgstr "A(z) „%s” reguláris kifejezés nem fordítható le" - -#: nsfw.php:154 +#: nsfw.php:140 #, php-format msgid "Filtered tag: %s" msgstr "Kiszűrt címke: %s" -#: nsfw.php:156 +#: nsfw.php:142 #, php-format msgid "Filtered word: %s" msgstr "Kiszűrt szó: %s" diff --git a/nsfw/lang/hu/strings.php b/nsfw/lang/hu/strings.php index 5f335b3e..c837a423 100644 --- a/nsfw/lang/hu/strings.php +++ b/nsfw/lang/hu/strings.php @@ -10,6 +10,5 @@ $a->strings['Enable Content filter'] = 'Tartalomszűrő engedélyezése'; $a->strings['Comma separated list of keywords to hide'] = 'Kulcsszavak vesszővel elválasztott listája az elrejtéshez'; $a->strings['Use /expression/ to provide regular expressions, #tag to specfically match hashtags (case-insensitive), or regular words (case-sensitive)'] = 'Használjon /kifejezést/ reguláris kifejezések megadásához, #címkét a kettőskeresztescímkék kifejezett illesztéséhez (nem érzékeny a kis- és nagybetűkre) vagy szabályos szavakat (kis- és nagybetűérzékeny)'; $a->strings['Content Filter (NSFW and more)'] = 'Tartalomszűrő (érzékeny tartalmak és egyebek)'; -$a->strings['Regular expression "%s" fails to compile'] = 'A(z) „%s” reguláris kifejezés nem fordítható le'; $a->strings['Filtered tag: %s'] = 'Kiszűrt címke: %s'; $a->strings['Filtered word: %s'] = 'Kiszűrt szó: %s'; diff --git a/nsfw/lang/it/messages.po b/nsfw/lang/it/messages.po index eadbb1aa..a84d0a13 100644 --- a/nsfw/lang/it/messages.po +++ b/nsfw/lang/it/messages.po @@ -5,22 +5,26 @@ # # Translators: # fabrixxm , 2014-2015,2018 -# Sylke Vicious , 2020,2023 +# Sylke Vicious , 2020 msgid "" msgstr "" "Project-Id-Version: friendica\n" "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: Sylke Vicious , 2020,2023\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"POT-Creation-Date: 2018-04-01 11:11-0400\n" +"PO-Revision-Date: 2020-09-17 11:25+0000\n" +"Last-Translator: Sylke Vicious \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: nsfw.php:65 +#: nsfw.php:77 nsfw.php:81 +msgid "Content Filter (NSFW and more)" +msgstr "Filtro Contenuto (NSFW e altro)" + +#: nsfw.php:85 msgid "" "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 " @@ -28,35 +32,32 @@ msgid "" "is also useful for hiding irrelevant or annoying content from direct view." msgstr "Questo componente aggiuntivo cerca per le parole specificate nei messaggi e li collassa. Può essere usato per filtrare contenuto taggato, per esempio, #NSFW (non sicuro per il lavoro), che può risultare inappropriato in certi orari o in certi luoghi, come appunto al lavoro. È anche utile per nascondere contenuto irrilevante o fastidioso." -#: nsfw.php:66 +#: nsfw.php:86 msgid "Enable Content filter" msgstr "Abilita il Filtro Contenuti" -#: nsfw.php:67 +#: nsfw.php:89 msgid "Comma separated list of keywords to hide" msgstr "Elenco separato da virgole di parole da nascondere" -#: nsfw.php:67 -msgid "" -"Use /expression/ to provide regular expressions, #tag to specfically match " -"hashtags (case-insensitive), or regular words (case-sensitive)" -msgstr "Usa /expression/ per fornire espressioni regolari, #tag per gli hashtag che coincidono specificatamente (insensibile alle maiuscole), o parole normali (sensibile alle maiuscole)" +#: nsfw.php:93 +msgid "Save Settings" +msgstr "Salva Impostazioni" -#: nsfw.php:72 -msgid "Content Filter (NSFW and more)" -msgstr "Filtro Contenuto (NSFW e altro)" +#: nsfw.php:94 +msgid "Use /expression/ to provide regular expressions" +msgstr "Utilizza /espressione/ per inserire espressioni regolari" -#: nsfw.php:96 -#, php-format -msgid "Regular expression \"%s\" fails to compile" -msgstr "L'espressione regolare \"%s\" fallisce la compilazione" +#: nsfw.php:109 +msgid "NSFW Settings saved." +msgstr "Impostazioni NSFW salvate." -#: nsfw.php:154 +#: nsfw.php:162 #, php-format msgid "Filtered tag: %s" msgstr "Tag filtrato: %s" -#: nsfw.php:156 +#: nsfw.php:164 #, php-format msgid "Filtered word: %s" msgstr "Parola filtrata: %s" diff --git a/nsfw/lang/it/strings.php b/nsfw/lang/it/strings.php index ff963972..05bd0112 100644 --- a/nsfw/lang/it/strings.php +++ b/nsfw/lang/it/strings.php @@ -3,13 +3,14 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} +$a->strings['Content Filter (NSFW and more)'] = 'Filtro Contenuto (NSFW e altro)'; $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.'] = 'Questo componente aggiuntivo cerca per le parole specificate nei messaggi e li collassa. Può essere usato per filtrare contenuto taggato, per esempio, #NSFW (non sicuro per il lavoro), che può risultare inappropriato in certi orari o in certi luoghi, come appunto al lavoro. È anche utile per nascondere contenuto irrilevante o fastidioso.'; $a->strings['Enable Content filter'] = 'Abilita il Filtro Contenuti'; $a->strings['Comma separated list of keywords to hide'] = 'Elenco separato da virgole di parole da nascondere'; -$a->strings['Use /expression/ to provide regular expressions, #tag to specfically match hashtags (case-insensitive), or regular words (case-sensitive)'] = 'Usa /expression/ per fornire espressioni regolari, #tag per gli hashtag che coincidono specificatamente (insensibile alle maiuscole), o parole normali (sensibile alle maiuscole)'; -$a->strings['Content Filter (NSFW and more)'] = 'Filtro Contenuto (NSFW e altro)'; -$a->strings['Regular expression "%s" fails to compile'] = 'L\'espressione regolare "%s" fallisce la compilazione'; +$a->strings['Save Settings'] = 'Salva Impostazioni'; +$a->strings['Use /expression/ to provide regular expressions'] = 'Utilizza /espressione/ per inserire espressioni regolari'; +$a->strings['NSFW Settings saved.'] = 'Impostazioni NSFW salvate.'; $a->strings['Filtered tag: %s'] = 'Tag filtrato: %s'; $a->strings['Filtered word: %s'] = 'Parola filtrata: %s'; diff --git a/nsfw/lang/ru/messages.po b/nsfw/lang/ru/messages.po index b3298e11..caa7ef3a 100644 --- a/nsfw/lang/ru/messages.po +++ b/nsfw/lang/ru/messages.po @@ -9,17 +9,21 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "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: Alexander An , 2020\n" -"Language-Team: Russian (http://app.transifex.com/Friendica/friendica/language/ru/)\n" +"POT-Creation-Date: 2018-04-01 11:11-0400\n" +"PO-Revision-Date: 2020-09-01 05:38+0000\n" +"Last-Translator: Alexander An \n" +"Language-Team: Russian (http://www.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" -#: nsfw.php:65 +#: nsfw.php:77 nsfw.php:81 +msgid "Content Filter (NSFW and more)" +msgstr "Фильтр контента (NSFW и прочее)" + +#: nsfw.php:85 msgid "" "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 " @@ -27,35 +31,32 @@ msgid "" "is also useful for hiding irrelevant or annoying content from direct view." msgstr "Это дополнение ищет указанные слова и выражения в записях и сворачивает запись, если найдёт. Это можно использовать для скрытия записей с тэгом #NSFW, просмотр которых может быть нежелателен в определённое время, например, на работе. Так же можно использовать для скрытия иного контента." -#: nsfw.php:66 +#: nsfw.php:86 msgid "Enable Content filter" msgstr "Включить фильтр контента" -#: nsfw.php:67 +#: nsfw.php:89 msgid "Comma separated list of keywords to hide" msgstr "Ключевые слова для скрытия, через запятую" -#: nsfw.php:67 -msgid "" -"Use /expression/ to provide regular expressions, #tag to specfically match " -"hashtags (case-insensitive), or regular words (case-sensitive)" -msgstr "" +#: nsfw.php:93 +msgid "Save Settings" +msgstr "Сохранить настройки" -#: nsfw.php:72 -msgid "Content Filter (NSFW and more)" -msgstr "Фильтр контента (NSFW и прочее)" +#: nsfw.php:94 +msgid "Use /expression/ to provide regular expressions" +msgstr "Используйте формат /expression/ для регулярных выражений" -#: nsfw.php:96 -#, php-format -msgid "Regular expression \"%s\" fails to compile" -msgstr "" +#: nsfw.php:109 +msgid "NSFW Settings saved." +msgstr "Настройки NSFW сохранены" -#: nsfw.php:154 +#: nsfw.php:162 #, php-format msgid "Filtered tag: %s" msgstr "Скрыт тэг: %s" -#: nsfw.php:156 +#: nsfw.php:164 #, php-format msgid "Filtered word: %s" msgstr "Скрыто слово: %s" diff --git a/nsfw/lang/ru/strings.php b/nsfw/lang/ru/strings.php index c9035421..71a02e12 100644 --- a/nsfw/lang/ru/strings.php +++ b/nsfw/lang/ru/strings.php @@ -5,9 +5,12 @@ 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['Content Filter (NSFW and more)'] = 'Фильтр контента (NSFW и прочее)'; $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.'] = 'Это дополнение ищет указанные слова и выражения в записях и сворачивает запись, если найдёт. Это можно использовать для скрытия записей с тэгом #NSFW, просмотр которых может быть нежелателен в определённое время, например, на работе. Так же можно использовать для скрытия иного контента.'; $a->strings['Enable Content filter'] = 'Включить фильтр контента'; $a->strings['Comma separated list of keywords to hide'] = 'Ключевые слова для скрытия, через запятую'; -$a->strings['Content Filter (NSFW and more)'] = 'Фильтр контента (NSFW и прочее)'; +$a->strings['Save Settings'] = 'Сохранить настройки'; +$a->strings['Use /expression/ to provide regular expressions'] = 'Используйте формат /expression/ для регулярных выражений'; +$a->strings['NSFW Settings saved.'] = 'Настройки NSFW сохранены'; $a->strings['Filtered tag: %s'] = 'Скрыт тэг: %s'; $a->strings['Filtered word: %s'] = 'Скрыто слово: %s'; diff --git a/nsfw/nsfw.php b/nsfw/nsfw.php index 4a54d899..2c8235dd 100644 --- a/nsfw/nsfw.php +++ b/nsfw/nsfw.php @@ -88,7 +88,7 @@ function nsfw_addon_settings_post(array &$b) $word_list = explode(',', $words); foreach ($word_list as $word) { $word = trim($word); - if (!$words || strpos($word, '/') !== 0) { + if (!$words || $word[0] != '/') { continue; } diff --git a/numfriends/lang/cs/messages.po b/numfriends/lang/cs/messages.po index 1598bc1d..1c2b092e 100644 --- a/numfriends/lang/cs/messages.po +++ b/numfriends/lang/cs/messages.po @@ -10,20 +10,28 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:15-0500\n" -"PO-Revision-Date: 2014-06-23 10:58+0000\n" -"Last-Translator: Aditoo, 2018\n" -"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" +"POT-Creation-Date: 2013-02-27 05:01-0500\n" +"PO-Revision-Date: 2018-07-03 14:45+0000\n" +"Last-Translator: Aditoo\n" +"Language-Team: Czech (http://www.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" -#: numfriends.php:55 -msgid "How many contacts to display on profile sidebar" -msgstr "Počet kontaktů k zobrazení na profilové postranní liště" +#: numfriends.php:46 +msgid "Numfriends settings updated." +msgstr "Nastavení Numfriends aktualizováno" -#: numfriends.php:60 +#: numfriends.php:77 msgid "Numfriends Settings" msgstr "Nastavení Numfriends" + +#: numfriends.php:79 +msgid "How many contacts to display on profile sidebar" +msgstr "Kolik kontaktů zobrazit na profilové postranní liště" + +#: numfriends.php:85 +msgid "Submit" +msgstr "Odeslat" diff --git a/numfriends/lang/cs/strings.php b/numfriends/lang/cs/strings.php index 2f58574d..d7535632 100644 --- a/numfriends/lang/cs/strings.php +++ b/numfriends/lang/cs/strings.php @@ -5,5 +5,7 @@ function string_plural_select_cs($n){ $n = intval($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['How many contacts to display on profile sidebar'] = 'Počet kontaktů k zobrazení na profilové postranní liště'; +$a->strings['Numfriends settings updated.'] = 'Nastavení Numfriends aktualizováno'; $a->strings['Numfriends Settings'] = 'Nastavení Numfriends'; +$a->strings['How many contacts to display on profile sidebar'] = 'Kolik kontaktů zobrazit na profilové postranní liště'; +$a->strings['Submit'] = 'Odeslat'; diff --git a/numfriends/lang/it/messages.po b/numfriends/lang/it/messages.po index 55ac96af..167ad9e1 100644 --- a/numfriends/lang/it/messages.po +++ b/numfriends/lang/it/messages.po @@ -10,20 +10,24 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:15-0500\n" -"PO-Revision-Date: 2014-06-23 10:58+0000\n" -"Last-Translator: Sylke Vicious , 2021\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"POT-Creation-Date: 2021-02-01 18:15+0100\n" +"PO-Revision-Date: 2021-02-16 12:44+0000\n" +"Last-Translator: Sylke Vicious \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: numfriends.php:55 +#: numfriends.php:59 +msgid "Numfriends Settings" +msgstr "Impostazioni Numfriends" + +#: numfriends.php:61 msgid "How many contacts to display on profile sidebar" msgstr "Quanti contatti visualizzare nella barra laterale del profilo" -#: numfriends.php:60 -msgid "Numfriends Settings" -msgstr "Impostazioni Numfriends" +#: numfriends.php:67 +msgid "Save Settings" +msgstr "Salva Impostazioni" diff --git a/numfriends/lang/it/strings.php b/numfriends/lang/it/strings.php index d593d0ea..208af559 100644 --- a/numfriends/lang/it/strings.php +++ b/numfriends/lang/it/strings.php @@ -3,7 +3,8 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} -$a->strings['How many contacts to display on profile sidebar'] = 'Quanti contatti visualizzare nella barra laterale del profilo'; $a->strings['Numfriends Settings'] = 'Impostazioni Numfriends'; +$a->strings['How many contacts to display on profile sidebar'] = 'Quanti contatti visualizzare nella barra laterale del profilo'; +$a->strings['Save Settings'] = 'Salva Impostazioni'; diff --git a/openstreetmap/lang/cs/messages.po b/openstreetmap/lang/cs/messages.po index ee350a4e..6385626b 100644 --- a/openstreetmap/lang/cs/messages.po +++ b/openstreetmap/lang/cs/messages.po @@ -4,63 +4,43 @@ # # # Translators: -# Aditoo, 2018 -# michal_s , 2014-2015 +# Michal Šupler , 2014-2015 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: 2014-06-23 11:01+0000\n" -"Last-Translator: Aditoo, 2018\n" -"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" +"POT-Creation-Date: 2013-02-27 05:01-0500\n" +"PO-Revision-Date: 2015-02-11 19:39+0000\n" +"Last-Translator: Michal Šupler \n" +"Language-Team: Czech (http://www.transifex.com/projects/p/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" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -#: openstreetmap.php:167 -msgid "View Larger" -msgstr "" - -#: openstreetmap.php:194 +#: openstreetmap.php:94 msgid "Submit" msgstr "Odeslat" -#: openstreetmap.php:195 +#: openstreetmap.php:95 msgid "Tile Server URL" msgstr "URL adresa Tile serveru" -#: openstreetmap.php:195 +#: openstreetmap.php:95 msgid "" "A list of public tile servers" -msgstr "" +"target=\"_blank\">public tile servers" +msgstr "Seznam veřejných tile serverů" -#: openstreetmap.php:196 -msgid "Nominatim (reverse geocoding) Server URL" -msgstr "" - -#: openstreetmap.php:196 -msgid "" -"A list of Nominatim servers" -msgstr "" - -#: openstreetmap.php:197 +#: openstreetmap.php:96 msgid "Default zoom" -msgstr "Výchozí zvětšení" +msgstr "Defaultní lupa" -#: openstreetmap.php:197 -msgid "" -"The default zoom level. (1:world, 18:highest, also depends on tile server)" -msgstr "" +#: openstreetmap.php:96 +msgid "The default zoom level. (1:world, 18:highest)" +msgstr "Defaultní nastavení lupy (1:svět, 18:nejvyšší)" -#: openstreetmap.php:198 -msgid "Include marker on map" -msgstr "" - -#: openstreetmap.php:198 -msgid "Include a marker on the map." -msgstr "" +#: openstreetmap.php:104 +msgid "Settings updated." +msgstr "Nastavení aktualizováno." diff --git a/openstreetmap/lang/cs/strings.php b/openstreetmap/lang/cs/strings.php index dc941275..fd4d896d 100644 --- a/openstreetmap/lang/cs/strings.php +++ b/openstreetmap/lang/cs/strings.php @@ -3,8 +3,11 @@ if(! function_exists("string_plural_select_cs")) { function string_plural_select_cs($n){ $n = intval($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; } + if (($n==1)) { return 0; } else if (($n>=2 && $n<=4)) { return 1; } else { return 2; } }} $a->strings['Submit'] = 'Odeslat'; $a->strings['Tile Server URL'] = 'URL adresa Tile serveru'; -$a->strings['Default zoom'] = 'Výchozí zvětšení'; +$a->strings['A list of public tile servers'] = 'Seznam veřejných tile serverů'; +$a->strings['Default zoom'] = 'Defaultní lupa'; +$a->strings['The default zoom level. (1:world, 18:highest)'] = 'Defaultní nastavení lupy (1:svět, 18:nejvyšší)'; +$a->strings['Settings updated.'] = 'Nastavení aktualizováno.'; diff --git a/openstreetmap/lang/de/messages.po b/openstreetmap/lang/de/messages.po index f99bdb2f..693ed136 100644 --- a/openstreetmap/lang/de/messages.po +++ b/openstreetmap/lang/de/messages.po @@ -13,9 +13,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-02-01 18:15+0100\n" -"PO-Revision-Date: 2014-06-23 11:01+0000\n" -"Last-Translator: Tobias Diekershoff , 2021\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2021-12-13 05:55+0000\n" +"Last-Translator: Tobias Diekershoff \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/openstreetmap/openstreetmap.php b/openstreetmap/openstreetmap.php index 3b7c4a58..3c21a51f 100644 --- a/openstreetmap/openstreetmap.php +++ b/openstreetmap/openstreetmap.php @@ -42,7 +42,7 @@ function openstreetmap_load_config(ConfigFileManager $loader) function openstreetmap_alterheader(&$navHtml) { - $addScriptTag = '' . "\r\n"; + $addScriptTag = '' . "\r\n"; DI::page()['htmlhead'] .= $addScriptTag; } @@ -145,7 +145,7 @@ function openstreetmap_generate_map(array &$b) { $tmsserver = DI::config()->get('openstreetmap', 'tmsserver', OSM_TMS); - if (strpos(DI::baseUrl(), 'https:') !== false) { + if (strpos(DI::baseUrl()->get(true), 'https:') !== false) { $tmsserver = str_replace('http:','https:',$tmsserver); } diff --git a/pageheader/lang/cs/messages.po b/pageheader/lang/cs/messages.po index 4caf402e..1621e180 100644 --- a/pageheader/lang/cs/messages.po +++ b/pageheader/lang/cs/messages.po @@ -4,37 +4,40 @@ # # # Translators: -# Aditoo, 2018 -# Aditoo, 2018 +# Lorem Ipsum , 2018 # michal_s , 2014-2015 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: 2014-06-23 11:17+0000\n" -"Last-Translator: Aditoo, 2018\n" -"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" +"POT-Creation-Date: 2018-03-11 18:52+0100\n" +"PO-Revision-Date: 2018-06-10 09:12+0000\n" +"Last-Translator: Lorem Ipsum \n" +"Language-Team: Czech (http://www.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" -#: pageheader.php:36 +#: pageheader.php:53 msgid "\"pageheader\" Settings" msgstr "Nastavení záhlaví stránky" -#: pageheader.php:37 +#: pageheader.php:54 msgid "Message" msgstr "Zpráva" -#: pageheader.php:37 +#: pageheader.php:54 msgid "" "Message to display on every page on this server (or put a pageheader.html " "file in your docroot)" -msgstr "Zpráva, která má být zobrazena na každé stránce tohoto serveru (nebo vložte do kořenové složky Vašeho serveru soubor pageheader.html)" +msgstr "Zpráva, která má být zobrazena na každé stránce tohoto serveru (nebo vložte soubor pageheader.html do kořenové složky Vašeho serveru)" -#: pageheader.php:38 +#: pageheader.php:55 msgid "Save Settings" msgstr "Uložit nastavení" + +#: pageheader.php:69 +msgid "pageheader Settings saved." +msgstr "Nastavení záhlaví stránky uloženo." diff --git a/pageheader/lang/cs/strings.php b/pageheader/lang/cs/strings.php index 3cb727cc..0675ea52 100644 --- a/pageheader/lang/cs/strings.php +++ b/pageheader/lang/cs/strings.php @@ -7,5 +7,6 @@ function string_plural_select_cs($n){ }} $a->strings['"pageheader" Settings'] = 'Nastavení záhlaví stránky'; $a->strings['Message'] = 'Zpráva'; -$a->strings['Message to display on every page on this server (or put a pageheader.html file in your docroot)'] = 'Zpráva, která má být zobrazena na každé stránce tohoto serveru (nebo vložte do kořenové složky Vašeho serveru soubor pageheader.html)'; +$a->strings['Message to display on every page on this server (or put a pageheader.html file in your docroot)'] = 'Zpráva, která má být zobrazena na každé stránce tohoto serveru (nebo vložte soubor pageheader.html do kořenové složky Vašeho serveru)'; $a->strings['Save Settings'] = 'Uložit nastavení'; +$a->strings['pageheader Settings saved.'] = 'Nastavení záhlaví stránky uloženo.'; diff --git a/pageheader/lang/it/messages.po b/pageheader/lang/it/messages.po index 2da356d0..f3ac805c 100644 --- a/pageheader/lang/it/messages.po +++ b/pageheader/lang/it/messages.po @@ -9,30 +9,34 @@ 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: 2014-06-23 11:17+0000\n" -"Last-Translator: fabrixxm , 2014-2015,2018\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"POT-Creation-Date: 2018-03-11 18:52+0100\n" +"PO-Revision-Date: 2018-03-19 13:19+0000\n" +"Last-Translator: fabrixxm \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: pageheader.php:36 +#: pageheader.php:53 msgid "\"pageheader\" Settings" msgstr "Impostazioni \"Intestazione pagina\"" -#: pageheader.php:37 +#: pageheader.php:54 msgid "Message" msgstr "Messaggio" -#: pageheader.php:37 +#: pageheader.php:54 msgid "" "Message to display on every page on this server (or put a pageheader.html " "file in your docroot)" msgstr "Il messaggio da mostrare su ogni pagina di questo server (puoi anche aggiungere un file pageheader.html nella root)" -#: pageheader.php:38 +#: pageheader.php:55 msgid "Save Settings" msgstr "Salva Impostazioni" + +#: pageheader.php:69 +msgid "pageheader Settings saved." +msgstr "Impostazioni \"Intestazione pagina\" salvate." diff --git a/pageheader/lang/it/strings.php b/pageheader/lang/it/strings.php index deed2ed9..ed5257f7 100644 --- a/pageheader/lang/it/strings.php +++ b/pageheader/lang/it/strings.php @@ -3,9 +3,10 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $a->strings['"pageheader" Settings'] = 'Impostazioni "Intestazione pagina"'; $a->strings['Message'] = 'Messaggio'; $a->strings['Message to display on every page on this server (or put a pageheader.html file in your docroot)'] = 'Il messaggio da mostrare su ogni pagina di questo server (puoi anche aggiungere un file pageheader.html nella root)'; $a->strings['Save Settings'] = 'Salva Impostazioni'; +$a->strings['pageheader Settings saved.'] = 'Impostazioni "Intestazione pagina" salvate.'; diff --git a/pageheader/pageheader.css b/pageheader/pageheader.css index f6c28fbf..8b3282fb 100644 --- a/pageheader/pageheader.css +++ b/pageheader/pageheader.css @@ -20,9 +20,4 @@ width: 100%; margin-top: 25px; font-size: 20px; - /* The pageheader box */ - padding: 20px; - border: 1px solid transparent; - border-radius: 2px; - margin-bottom: 15px; } diff --git a/piwik/README.md b/piwik/README.md index c7e57a0f..59cf5771 100644 --- a/piwik/README.md +++ b/piwik/README.md @@ -31,7 +31,7 @@ Open the `config/node.config.php` file and add "piwik" to the list of activated ], ] -You can change 5 more configuration variables for the addon in the `config/piwik.config.php` file: +You can change 4 more configuration variables for the addon in the `config/piwik.config.php` file: return [ 'piwik' => [ @@ -39,7 +39,6 @@ You can change 5 more configuration variables for the addon in the `config/piwik 'sideid' => 1, 'optout' => true, 'async' => false, - 'shortendpoint' => false, ], ]; @@ -51,7 +50,7 @@ Configuration fields * The *optout* parameter (true|false) defines whether or not a short notice about the utilization of Piwik will be displayed on every page of your Friendica site (at the bottom of the page with some spacing to the other content). Part of the note is a link that allows the visitor to set an _opt-out_ cookie which will prevent visits from that user be tracked by piwik. * The *async* parameter (true|false) defines whether or not to use asynchronous tracking so pages load (or appear to load) faster. -* The *shortendpoint* parameter (true|false) defines whether or not to use a short path to the tracking script: "/js/" instead of "/piwik.js". + Currently the optional notice states the following: > This website is tracked using the Piwik analytics tool. If you do not want that your visits are logged this way you can set a cookie to prevent Piwik from tracking further visits of the site (opt-out). diff --git a/piwik/config/piwik.config.php b/piwik/config/piwik.config.php index 66f71dc7..ba59b63d 100644 --- a/piwik/config/piwik.config.php +++ b/piwik/config/piwik.config.php @@ -25,9 +25,5 @@ return [ // async (Boolean) // This defines whether or not to use asynchronous tracking so pages load (or appear to load) faster. 'async' => false, - - // shortendpoint (Boolean) - // This defines whether or not to use a short path to the tracking script: "/js/" instead of "/piwik.js". - 'shortendpoint' => false, ], ]; diff --git a/piwik/lang/C/messages.po b/piwik/lang/C/messages.po index 881bd796..5a078056 100644 --- a/piwik/lang/C/messages.po +++ b/piwik/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-05-01 07:39+0200\n" +"POT-Creation-Date: 2021-02-01 18:15+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,13 +17,13 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: piwik.php:96 +#: piwik.php:87 msgid "" "This website is tracked using the Matomo " "analytics tool." msgstr "" -#: piwik.php:99 +#: piwik.php:90 #, php-format msgid "" "If you do not want that your visits are logged in this way you (opt-out)." msgstr "" -#: piwik.php:108 +#: piwik.php:97 msgid "Save Settings" msgstr "" -#: piwik.php:109 +#: piwik.php:98 msgid "Matomo (Piwik) Base URL" msgstr "" -#: piwik.php:109 +#: piwik.php:98 msgid "" "Absolute path to your Matomo (Piwik) installation. (without protocol (http/" "s), with trailing slash)" msgstr "" -#: piwik.php:110 +#: piwik.php:99 msgid "Site ID" msgstr "" -#: piwik.php:111 +#: piwik.php:100 msgid "Show opt-out cookie link?" msgstr "" -#: piwik.php:112 +#: piwik.php:101 msgid "Asynchronous tracking" msgstr "" - -#: piwik.php:113 -msgid "Shortcut path to the script ('/js/' instead of '/piwik.js')" -msgstr "" diff --git a/piwik/lang/de/messages.po b/piwik/lang/de/messages.po index 0fdaa7b3..83f1fe0f 100644 --- a/piwik/lang/de/messages.po +++ b/piwik/lang/de/messages.po @@ -7,29 +7,29 @@ # Andreas H., 2014-2015 # Till Mohr , 2021 # Tobias Diekershoff , 2014 -# Tobias Diekershoff , 2019,2023 +# Tobias Diekershoff , 2019 # Ulf Rompe , 2019 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-05-01 07:39+0200\n" -"PO-Revision-Date: 2014-06-23 11:18+0000\n" -"Last-Translator: Tobias Diekershoff , 2019,2023\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"POT-Creation-Date: 2021-02-01 18:15+0100\n" +"PO-Revision-Date: 2021-05-23 19:52+0000\n" +"Last-Translator: Till Mohr \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: piwik.php:96 +#: piwik.php:87 msgid "" "This website is tracked using the Matomo" " analytics tool." msgstr "Diese Website benutzt Matomo, eine Open-Source-Software zur statistischen Auswertung der Besucherzugriffe." -#: piwik.php:99 +#: piwik.php:90 #, php-format msgid "" "If you do not want that your visits are logged in this way you (opt-out)." msgstr "Wenn du nicht willst, dass Deine Besuche auf diese Weise gespeichert werden, kannst du ein Cookie setzen. Dann wird Matomo / Piwik dich auf dieser Website nicht mehr verfolgen (opt-out)." -#: piwik.php:108 +#: piwik.php:97 msgid "Save Settings" msgstr "Einstellungen speichern" -#: piwik.php:109 +#: piwik.php:98 msgid "Matomo (Piwik) Base URL" msgstr "Matomo-Basis-URL (Piwik-Basis-URL)" -#: piwik.php:109 +#: piwik.php:98 msgid "" "Absolute path to your Matomo (Piwik) installation. (without protocol " "(http/s), with trailing slash)" msgstr "Absoluter Pfad zu deiner Matomo-/Piwik-Installation (ohne \"http://\" oder \"https://\"), mit abschließendem Schrägstrich" -#: piwik.php:110 +#: piwik.php:99 msgid "Site ID" msgstr "Seiten-ID" -#: piwik.php:111 +#: piwik.php:100 msgid "Show opt-out cookie link?" msgstr "Link zum Setzen des Opt-Out-Cookies anzeigen?" -#: piwik.php:112 +#: piwik.php:101 msgid "Asynchronous tracking" msgstr "Asynchrones Tracking" - -#: piwik.php:113 -msgid "Shortcut path to the script ('/js/' instead of '/piwik.js')" -msgstr "Shortcut Pfad zum Script ('/js/' anstelle von '/piwik.js')" diff --git a/piwik/lang/de/strings.php b/piwik/lang/de/strings.php index 9e126972..e218d6e3 100644 --- a/piwik/lang/de/strings.php +++ b/piwik/lang/de/strings.php @@ -13,4 +13,3 @@ $a->strings['Absolute path to your Matomo (Piwik) installation. (without protoco $a->strings['Site ID'] = 'Seiten-ID'; $a->strings['Show opt-out cookie link?'] = 'Link zum Setzen des Opt-Out-Cookies anzeigen?'; $a->strings['Asynchronous tracking'] = 'Asynchrones Tracking'; -$a->strings['Shortcut path to the script (\'/js/\' instead of \'/piwik.js\')'] = 'Shortcut Pfad zum Script (\'/js/\' anstelle von \'/piwik.js\')'; diff --git a/piwik/lang/en-gb/messages.po b/piwik/lang/en-gb/messages.po index 74c95ed7..e55e1a66 100644 --- a/piwik/lang/en-gb/messages.po +++ b/piwik/lang/en-gb/messages.po @@ -20,13 +20,13 @@ msgstr "" "Language: en_GB\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: piwik.php:95 +#: piwik.php:94 msgid "" "This website is tracked using the Matomo" " analytics tool." msgstr "This website is tracking, using the Matomo analytics tool." -#: piwik.php:98 +#: piwik.php:97 #, php-format msgid "" "If you do not want that your visits are logged in this way you (opt-out)." msgstr "If you do not want that your visits logged in this way you can set a cookie to prevent Matomo / Piwik from tracking further visits of the site (opt-out)." -#: piwik.php:107 +#: piwik.php:104 msgid "Save Settings" msgstr "Save settings" -#: piwik.php:108 +#: piwik.php:105 msgid "Matomo (Piwik) Base URL" msgstr "Matomo (Piwik) Base URL" -#: piwik.php:108 +#: piwik.php:105 msgid "" "Absolute path to your Matomo (Piwik) installation. (without protocol " "(http/s), with trailing slash)" msgstr "Absolute path to your Matomo (Piwik) installation. (without protocol (http/s), with trailing slash)" -#: piwik.php:109 +#: piwik.php:106 msgid "Site ID" msgstr "Site ID" -#: piwik.php:110 +#: piwik.php:107 msgid "Show opt-out cookie link?" msgstr "Show opt-out cookie link?" -#: piwik.php:111 +#: piwik.php:108 msgid "Asynchronous tracking" msgstr "Asynchronous tracking" -#: piwik.php:112 -msgid "Shortcut path to the script ('/js/' instead of '/piwik.js')" -msgstr "Shortcut path to the script ('/js/' instead of '/piwik.js')" - #: piwik.php:120 msgid "Settings updated." -msgstr "Settings updated." \ No newline at end of file +msgstr "Settings updated." diff --git a/piwik/lang/en-gb/strings.php b/piwik/lang/en-gb/strings.php index ab46f859..7056f878 100644 --- a/piwik/lang/en-gb/strings.php +++ b/piwik/lang/en-gb/strings.php @@ -13,5 +13,4 @@ $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.'; diff --git a/piwik/lang/fr/messages.po b/piwik/lang/fr/messages.po index b8bf84ce..8e832d79 100644 --- a/piwik/lang/fr/messages.po +++ b/piwik/lang/fr/messages.po @@ -4,7 +4,6 @@ # # # Translators: -# Florent C., 2023 # Hypolite Petovan , 2022 # Nicolas Derive, 2022 # ea1cd8241cb389ffb6f92bc6891eff5d_dc12308 <70dced5587d47e18d88f9298024d96f8_93383>, 2015 @@ -13,23 +12,23 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-05-01 07:39+0200\n" +"POT-Creation-Date: 2021-02-01 18:15+0100\n" "PO-Revision-Date: 2014-06-23 11:18+0000\n" -"Last-Translator: Florent C., 2023\n" -"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n" +"Last-Translator: Nicolas Derive, 2022\n" +"Language-Team: French (http://www.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:96 +#: piwik.php:87 msgid "" "This website is tracked using the Matomo" " analytics tool." msgstr "Ce site Internet utilise Matomo pour mesurer son audience." -#: piwik.php:99 +#: piwik.php:90 #, 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:108 +#: piwik.php:97 msgid "Save Settings" msgstr "Sauvegarder les paramètres" -#: piwik.php:109 +#: piwik.php:98 msgid "Matomo (Piwik) Base URL" msgstr "URL de base de Matomo (Piwik)" -#: piwik.php:109 +#: piwik.php:98 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:110 +#: piwik.php:99 msgid "Site ID" msgstr "ID du site" -#: piwik.php:111 +#: piwik.php:100 msgid "Show opt-out cookie link?" msgstr "Montrer le lien d'opt-out pour les cookies ?" -#: piwik.php:112 +#: piwik.php:101 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 3c150e01..23899d0f 100644 --- a/piwik/lang/fr/strings.php +++ b/piwik/lang/fr/strings.php @@ -13,4 +13,3 @@ $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/piwik/lang/hu/messages.po b/piwik/lang/hu/messages.po index 62644161..cbaa8df2 100644 --- a/piwik/lang/hu/messages.po +++ b/piwik/lang/hu/messages.po @@ -4,28 +4,28 @@ # # # Translators: -# Balázs Úr, 2020-2021,2023 +# Balázs Úr, 2020-2021 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-05-01 07:39+0200\n" +"POT-Creation-Date: 2021-02-01 18:15+0100\n" "PO-Revision-Date: 2014-06-23 11:18+0000\n" -"Last-Translator: Balázs Úr, 2020-2021,2023\n" -"Language-Team: Hungarian (http://app.transifex.com/Friendica/friendica/language/hu/)\n" +"Last-Translator: Balázs Úr, 2020-2021\n" +"Language-Team: Hungarian (http://www.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" -#: piwik.php:96 +#: piwik.php:87 msgid "" "This website is tracked using the Matomo" " analytics tool." msgstr "Ez a weboldal a Matomo analitikai eszköz használatával van követve." -#: piwik.php:99 +#: piwik.php:90 #, php-format msgid "" "If you do not want that your visits are logged in this way you (opt-out)." msgstr "Ha nem szeretné, hogy a látogatásai ilyen módon naplózva legyenek, akkor beállíthat egy sütit annak megakadályozásához, hogy a Matomo vagy a Piwik kövesse az oldal további meglátogatásait (lemondás)." -#: piwik.php:108 +#: piwik.php:97 msgid "Save Settings" msgstr "Beállítások mentése" -#: piwik.php:109 +#: piwik.php:98 msgid "Matomo (Piwik) Base URL" msgstr "Matomo (Piwik) alap URL" -#: piwik.php:109 +#: piwik.php:98 msgid "" "Absolute path to your Matomo (Piwik) installation. (without protocol " "(http/s), with trailing slash)" msgstr "Abszolút útvonal a Matomo (Piwik) telepítéséhez (http vagy https protokoll nélkül, de lezáró perjellel)." -#: piwik.php:110 +#: piwik.php:99 msgid "Site ID" msgstr "Oldalazonosító" -#: piwik.php:111 +#: piwik.php:100 msgid "Show opt-out cookie link?" msgstr "Megjeleníti a lemondó süti hivatkozását?" -#: piwik.php:112 +#: piwik.php:101 msgid "Asynchronous tracking" msgstr "Aszinkron követés" - -#: piwik.php:113 -msgid "Shortcut path to the script ('/js/' instead of '/piwik.js')" -msgstr "A parancsfájl rövidített útvonala („/js/” a „/piwik.js” helyett)" diff --git a/piwik/lang/hu/strings.php b/piwik/lang/hu/strings.php index 4b249396..8eff504e 100644 --- a/piwik/lang/hu/strings.php +++ b/piwik/lang/hu/strings.php @@ -13,4 +13,3 @@ $a->strings['Absolute path to your Matomo (Piwik) installation. (without protoco $a->strings['Site ID'] = 'Oldalazonosító'; $a->strings['Show opt-out cookie link?'] = 'Megjeleníti a lemondó süti hivatkozását?'; $a->strings['Asynchronous tracking'] = 'Aszinkron követés'; -$a->strings['Shortcut path to the script (\'/js/\' instead of \'/piwik.js\')'] = 'A parancsfájl rövidített útvonala („/js/” a „/piwik.js” helyett)'; diff --git a/piwik/lang/it/messages.po b/piwik/lang/it/messages.po index f169f383..033fc736 100644 --- a/piwik/lang/it/messages.po +++ b/piwik/lang/it/messages.po @@ -10,23 +10,23 @@ 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: 2014-06-23 11:18+0000\n" -"Last-Translator: Sylke Vicious , 2020\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"POT-Creation-Date: 2019-02-19 10:42+0100\n" +"PO-Revision-Date: 2020-09-17 11:39+0000\n" +"Last-Translator: Sylke Vicious \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: piwik.php:87 +#: piwik.php:94 msgid "" "This website is tracked using the Matomo" " analytics tool." msgstr "Questo sito è monitorato con lo strumento di analisi Matomo." -#: piwik.php:90 +#: piwik.php:97 #, php-format msgid "" "If you do not want that your visits are logged in this way you (opt-out)." msgstr "Se non vuoi che le tue visite vengano registrate in questo modo è possibile impostare un cookie per evitare che Matomo / Piwik rintracci ulteriori visite del sito (opt-out)." -#: piwik.php:97 +#: piwik.php:104 msgid "Save Settings" msgstr "Salva Impostazioni" -#: piwik.php:98 +#: piwik.php:105 msgid "Matomo (Piwik) Base URL" msgstr "Indirizzo di base di Matomo (Piwik)" -#: piwik.php:98 +#: piwik.php:105 msgid "" "Absolute path to your Matomo (Piwik) installation. (without protocol " "(http/s), with trailing slash)" msgstr "Percorso assoluto alla tua installazione di Matomo (Piwik) (senza il protocollo (http/https), con la barra alla fine)" -#: piwik.php:99 +#: piwik.php:106 msgid "Site ID" msgstr "ID del sito" -#: piwik.php:100 +#: piwik.php:107 msgid "Show opt-out cookie link?" msgstr "Mostra il collegamento per l'opt-out dei cookie?" -#: piwik.php:101 +#: piwik.php:108 msgid "Asynchronous tracking" msgstr "Tracciamento asincrono" + +#: piwik.php:120 +msgid "Settings updated." +msgstr "Impostazioni aggiornate." diff --git a/piwik/lang/it/strings.php b/piwik/lang/it/strings.php index 0080af7e..5ca713c4 100644 --- a/piwik/lang/it/strings.php +++ b/piwik/lang/it/strings.php @@ -3,7 +3,7 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $a->strings['This website is tracked using the Matomo analytics tool.'] = 'Questo sito è monitorato con lo strumento di analisi Matomo.'; $a->strings['If you do not want that your visits are logged in this way you can set a cookie to prevent Matomo / Piwik from tracking further visits of the site (opt-out).'] = 'Se non vuoi che le tue visite vengano registrate in questo modo è possibile impostare un cookie per evitare che Matomo / Piwik rintracci ulteriori visite del sito (opt-out).'; @@ -13,3 +13,4 @@ $a->strings['Absolute path to your Matomo (Piwik) installation. (without protoco $a->strings['Site ID'] = 'ID del sito'; $a->strings['Show opt-out cookie link?'] = 'Mostra il collegamento per l\'opt-out dei cookie?'; $a->strings['Asynchronous tracking'] = 'Tracciamento asincrono'; +$a->strings['Settings updated.'] = 'Impostazioni aggiornate.'; diff --git a/piwik/lang/ru/strings.php b/piwik/lang/ru/strings.php index 74ad22a5..8f58ef45 100644 --- a/piwik/lang/ru/strings.php +++ b/piwik/lang/ru/strings.php @@ -9,4 +9,3 @@ $a->strings["Site ID"] = "ID сайта"; $a->strings["Show opt-out cookie link?"] = "Показать ссылку opt-out cookie?"; $a->strings["Asynchronous tracking"] = "Асинхронное отслеживание"; $a->strings["Settings updated."] = "Настройки обновлены."; -$a->strings["Shortcut path to the script ('/js/' instead of '/piwik.js')"] = "Сокращенный путь к скрипту ('/js/' вместо '/piwik.js')"; \ No newline at end of file diff --git a/piwik/piwik.php b/piwik/piwik.php index fd6d5fc9..ad2bed75 100644 --- a/piwik/piwik.php +++ b/piwik/piwik.php @@ -25,7 +25,6 @@ * 'sideid' => '', * 'optout' => true, * 'async' => false, - * 'shortendpoint' => false, * ], * ]; * @@ -61,7 +60,7 @@ function piwik_analytics(string &$b) * associated CSS file. We just have to tell Friendica to get it * into the page header. */ - DI::page()->registerStylesheet('addon/piwik/piwik.css', 'all'); + DI::page()['htmlhead'] .= ''; /* * Get the configuration values. @@ -70,21 +69,16 @@ function piwik_analytics(string &$b) $siteid = DI::config()->get('piwik', 'siteid'); $optout = DI::config()->get('piwik', 'optout'); $async = DI::config()->get('piwik', 'async'); - $shortendpoint = DI::config()->get('piwik', 'shortendpoint'); /* * 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'; - - $b .= " \r\n"; - if ($async) { - $b .= "
\r\n\r\n
"; + $b .= " \r\n"; + $b .= "
\r\n\r\n
"; + } else { + $b .= " \r\n"; } /* @@ -95,7 +89,7 @@ function piwik_analytics(string &$b) $b .= ""; } @@ -110,7 +104,6 @@ function piwik_addon_admin (string &$o) '$siteid' => ['siteid', DI::l10n()->t('Site ID'), DI::config()->get('piwik','siteid' ), ''], '$optout' => ['optout', DI::l10n()->t('Show opt-out cookie link?'), DI::config()->get('piwik','optout' ), ''], '$async' => ['async', DI::l10n()->t('Asynchronous tracking'), DI::config()->get('piwik','async' ), ''], - '$shortendpoint' => ['shortendpoint', DI::l10n()->t("Shortcut path to the script ('/js/' instead of '/piwik.js')"), DI::config()->get('piwik','shortendpoint' ), ''], ]); } @@ -120,5 +113,4 @@ function piwik_addon_admin_post() DI::config()->set('piwik', 'siteid', trim($_POST['siteid'] ?? '')); DI::config()->set('piwik', 'optout', trim($_POST['optout'] ?? '')); DI::config()->set('piwik', 'async', trim($_POST['async'] ?? '')); - DI::config()->set('piwik', 'shortendpoint', trim($_POST['shortendpoint'] ?? '')); } diff --git a/piwik/templates/admin.tpl b/piwik/templates/admin.tpl index 7a9b5d71..2ab1869b 100644 --- a/piwik/templates/admin.tpl +++ b/piwik/templates/admin.tpl @@ -2,5 +2,4 @@ {{include file="field_input.tpl" field=$siteid}} {{include file="field_checkbox.tpl" field=$optout}} {{include file="field_checkbox.tpl" field=$async}} -{{include file="field_checkbox.tpl" field=$shortendpoint}}
diff --git a/planets/lang/de/messages.po b/planets/lang/de/messages.po index c06493e2..507bbbf5 100644 --- a/planets/lang/de/messages.po +++ b/planets/lang/de/messages.po @@ -14,9 +14,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:15-0500\n" -"PO-Revision-Date: 2014-06-23 11:19+0000\n" -"Last-Translator: Steffen K9, 2021\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2021-12-22 16:22+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/planets/lang/it/messages.po b/planets/lang/it/messages.po index c15d7460..b3a93820 100644 --- a/planets/lang/it/messages.po +++ b/planets/lang/it/messages.po @@ -10,20 +10,28 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:15-0500\n" -"PO-Revision-Date: 2014-06-23 11:19+0000\n" -"Last-Translator: Sylke Vicious , 2021\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"POT-Creation-Date: 2021-02-01 18:15+0100\n" +"PO-Revision-Date: 2021-02-16 12:56+0000\n" +"Last-Translator: Sylke Vicious \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: planets.php:126 +#: planets.php:131 planets.php:135 +msgid "Planets" +msgstr "Pianeti" + +#: planets.php:139 +msgid "Planets Settings" +msgstr "Impostazioni \"Pianeti\"" + +#: planets.php:141 msgid "Enable Planets Addon" msgstr "Abilita il componente aggiuntivo Pianeti" -#: planets.php:131 -msgid "Planets Settings" -msgstr "Impostazioni \"Pianeti\"" +#: planets.php:147 +msgid "Save Settings" +msgstr "Salva Impostazioni" diff --git a/planets/lang/it/strings.php b/planets/lang/it/strings.php index 040f65ad..7d5ac516 100644 --- a/planets/lang/it/strings.php +++ b/planets/lang/it/strings.php @@ -3,7 +3,9 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} -$a->strings['Enable Planets Addon'] = 'Abilita il componente aggiuntivo Pianeti'; +$a->strings['Planets'] = 'Pianeti'; $a->strings['Planets Settings'] = 'Impostazioni "Pianeti"'; +$a->strings['Enable Planets Addon'] = 'Abilita il componente aggiuntivo Pianeti'; +$a->strings['Save Settings'] = 'Salva Impostazioni'; diff --git a/public_server/lang/de/messages.po b/public_server/lang/de/messages.po index cc2cf617..514d579d 100644 --- a/public_server/lang/de/messages.po +++ b/public_server/lang/de/messages.po @@ -12,9 +12,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-02-01 18:15+0100\n" -"PO-Revision-Date: 2014-06-23 11:24+0000\n" -"Last-Translator: Till Mohr , 2021\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2021-05-23 19:49+0000\n" +"Last-Translator: Till Mohr \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/public_server/lang/it/messages.po b/public_server/lang/it/messages.po index c091cfd6..5c46ab33 100644 --- a/public_server/lang/it/messages.po +++ b/public_server/lang/it/messages.po @@ -11,14 +11,14 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-02-01 18:15+0100\n" -"PO-Revision-Date: 2014-06-23 11:24+0000\n" -"Last-Translator: Sylke Vicious , 2021\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"PO-Revision-Date: 2021-02-16 12:57+0000\n" +"Last-Translator: Sylke Vicious \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: public_server.php:64 msgid "Administrator" diff --git a/public_server/lang/it/strings.php b/public_server/lang/it/strings.php index 41d5b0e9..a095f2a6 100644 --- a/public_server/lang/it/strings.php +++ b/public_server/lang/it/strings.php @@ -3,7 +3,7 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $a->strings['Administrator'] = 'Amministratore'; $a->strings['Your account on %s will expire in a few days.'] = 'Il tuo account su %s scadrà tra pochi giorni.'; diff --git a/public_server/public_server.php b/public_server/public_server.php index 7591c7d0..79201007 100644 --- a/public_server/public_server.php +++ b/public_server/public_server.php @@ -59,8 +59,8 @@ function public_server_cron($b) 'uid' => $rr['uid'], 'system_type' => 'public_server_expire', 'source_name' => DI::l10n()->t('Administrator'), - 'source_link' => DI::baseUrl(), - 'source_photo' => DI::baseUrl() . '/images/person-80.jpg', + 'source_link' => DI::baseUrl()->get(), + 'source_photo' => DI::baseUrl()->get() . '/images/person-80.jpg', ]); $fields = ['expire_notification_sent' => DateTimeFormat::utcNow()]; @@ -104,7 +104,7 @@ function public_server_enotify(array &$b) { if (!empty($b['params']) && $b['params']['type'] == Notification\Type::SYSTEM && !empty($b['params']['system_type']) && $b['params']['system_type'] === 'public_server_expire') { - $b['itemlink'] = DI::baseUrl(); + $b['itemlink'] = DI::baseUrl()->get(); $b['epreamble'] = $b['preamble'] = DI::l10n()->t('Your account on %s will expire in a few days.', DI::config()->get('system', 'sitename')); $b['subject'] = DI::l10n()->t('Your Friendica account is about to expire.'); $b['body'] = DI::l10n()->t("Hi %1\$s,\n\nYour account on %2\$s will expire in less than five days. You may keep your account by logging in at least once every 30 days", $b['params']['to_name'], "[url=" . DI::config()->get('system', 'url') . "]" . DI::config()->get('config', 'sitename') . "[/url]"); diff --git a/pumpio/lang/C/messages.po b/pumpio/lang/C/messages.po index 7e14cd79..baac56e6 100644 --- a/pumpio/lang/C/messages.po +++ b/pumpio/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: 2021-11-21 19:17-0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,76 +17,76 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: pumpio.php:62 +#: pumpio.php:57 msgid "Permission denied." msgstr "" -#: pumpio.php:156 +#: pumpio.php:152 #, php-format msgid "Unable to register the client at the pump.io server '%s'." msgstr "" -#: pumpio.php:196 +#: pumpio.php:192 msgid "You are now authenticated to pumpio." msgstr "" -#: pumpio.php:197 +#: pumpio.php:193 msgid "return to the connector page" msgstr "" -#: pumpio.php:217 +#: pumpio.php:213 msgid "Post to pumpio" msgstr "" -#: pumpio.php:241 +#: pumpio.php:237 msgid "Save Settings" msgstr "" -#: pumpio.php:243 +#: pumpio.php:239 msgid "Delete this preset" msgstr "" -#: pumpio.php:249 +#: pumpio.php:245 msgid "Authenticate your pump.io connection" msgstr "" -#: pumpio.php:256 +#: pumpio.php:252 msgid "Pump.io servername (without \"http://\" or \"https://\" )" msgstr "" -#: pumpio.php:257 +#: pumpio.php:253 msgid "Pump.io username (without the servername)" msgstr "" -#: pumpio.php:258 +#: pumpio.php:254 msgid "Import the remote timeline" msgstr "" -#: pumpio.php:259 +#: pumpio.php:255 msgid "Enable Pump.io Post Addon" msgstr "" -#: pumpio.php:260 +#: pumpio.php:256 msgid "Post to Pump.io by default" msgstr "" -#: pumpio.php:261 +#: pumpio.php:257 msgid "Should posts be public?" msgstr "" -#: pumpio.php:262 +#: pumpio.php:258 msgid "Mirror all public posts" msgstr "" -#: pumpio.php:267 +#: pumpio.php:263 msgid "Pump.io Import/Export/Mirror" msgstr "" -#: pumpio.php:924 +#: pumpio.php:920 msgid "status" msgstr "" -#: pumpio.php:928 +#: pumpio.php:924 #, php-format msgid "%1$s likes %2$s's %3$s" msgstr "" diff --git a/pumpio/lang/cs/messages.po b/pumpio/lang/cs/messages.po index 64293afb..73453e94 100644 --- a/pumpio/lang/cs/messages.po +++ b/pumpio/lang/cs/messages.po @@ -10,86 +10,94 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:17-0500\n" -"PO-Revision-Date: 2014-06-23 11:30+0000\n" -"Last-Translator: Aditoo, 2018\n" -"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" +"POT-Creation-Date: 2014-06-23 14:45+0200\n" +"PO-Revision-Date: 2018-06-11 19:43+0000\n" +"Last-Translator: Aditoo\n" +"Language-Team: Czech (http://www.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" -#: pumpio.php:57 +#: pumpio.php:38 msgid "Permission denied." msgstr "Přístup odmítnut." -#: pumpio.php:152 +#: pumpio.php:124 #, php-format msgid "Unable to register the client at the pump.io server '%s'." -msgstr "Nebylo možné registrovat klienta na serveru pump.io \"%s\"." +msgstr "Nebylo možné registrovat klienta na pump.io serveru '%s'." -#: pumpio.php:192 +#: pumpio.php:164 msgid "You are now authenticated to pumpio." -msgstr "Nyní jste přihlášen/a na pump.io." +msgstr "Nyní jste přihlášen k pumpio." -#: pumpio.php:193 +#: pumpio.php:165 msgid "return to the connector page" -msgstr "návrat na stránku konektoru" +msgstr "návrat ke stránce konektor" -#: pumpio.php:213 +#: pumpio.php:183 msgid "Post to pumpio" -msgstr "Posílat na pump.io" +msgstr "Příspěvek na pumpio" -#: pumpio.php:237 -msgid "Save Settings" -msgstr "Uložit nastavení" +#: pumpio.php:221 pumpio.php:225 +msgid "Pump.io Import/Export/Mirror" +msgstr "Pump.oi Import/Export/Zrcadlení" -#: pumpio.php:239 -msgid "Delete this preset" -msgstr "" +#: pumpio.php:229 +msgid "pump.io username (without the servername)" +msgstr "uživatelské jméno pump.io (bez jména serveru)" -#: pumpio.php:245 +#: pumpio.php:234 +msgid "pump.io servername (without \"http://\" or \"https://\" )" +msgstr "jméno serveru pump.io (bez \"http://\" nebo \"https://\" )" + +#: pumpio.php:246 msgid "Authenticate your pump.io connection" msgstr "Přihlásit ke spojení na pump.io" -#: pumpio.php:252 -msgid "Pump.io servername (without \"http://\" or \"https://\" )" -msgstr "" - -#: pumpio.php:253 -msgid "Pump.io username (without the servername)" -msgstr "" - -#: pumpio.php:254 +#: pumpio.php:250 msgid "Import the remote timeline" msgstr "Importovat vzdálenou časovou osu" #: pumpio.php:255 -msgid "Enable Pump.io Post Addon" -msgstr "" +msgid "Enable pump.io Post Addon" +msgstr "Povolit doplněk pumo.io Post" -#: pumpio.php:256 -msgid "Post to Pump.io by default" -msgstr "" +#: pumpio.php:260 +msgid "Post to pump.io by default" +msgstr "Posílat příspěvky na pump.io automaticky" -#: pumpio.php:257 +#: pumpio.php:265 msgid "Should posts be public?" msgstr "Mají být příspěvky veřejné?" -#: pumpio.php:258 +#: pumpio.php:270 msgid "Mirror all public posts" msgstr "Zrcadlit všechny veřejné příspěvky" -#: pumpio.php:263 -msgid "Pump.io Import/Export/Mirror" -msgstr "Import/Export/Zrcadlení Pump.io" +#: pumpio.php:275 +msgid "Check to delete this preset" +msgstr "Zaškrtnout pro smazání tohoto nastavení" -#: pumpio.php:920 +#: pumpio.php:285 +msgid "Save Settings" +msgstr "Uložit Nastavení" + +#: pumpio.php:515 +msgid "Pump.io post failed. Queued for retry." +msgstr "Zaslání příspěvku na Pump.io selhalo. Příspěvek byl zařazen do fronty pro opakované odeslání." + +#: pumpio.php:587 +msgid "Pump.io like failed. Queued for retry." +msgstr "Zaslání příspěvku na Pump.io zřejmě selhalo. Příspěvek byl zařazen do fronty pro opakované odeslání." + +#: pumpio.php:875 msgid "status" msgstr "stav" -#: pumpio.php:924 +#: pumpio.php:879 #, php-format msgid "%1$s likes %2$s's %3$s" -msgstr "Uživateli %1$s se líbí %3$s uživatele %2$s" +msgstr "%1$s se líbí %3$s %2$s" diff --git a/pumpio/lang/cs/strings.php b/pumpio/lang/cs/strings.php index 9e90d014..b05b20d7 100644 --- a/pumpio/lang/cs/strings.php +++ b/pumpio/lang/cs/strings.php @@ -6,15 +6,22 @@ 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['Permission denied.'] = 'Přístup odmítnut.'; -$a->strings['Unable to register the client at the pump.io server \'%s\'.'] = 'Nebylo možné registrovat klienta na serveru pump.io "%s".'; -$a->strings['You are now authenticated to pumpio.'] = 'Nyní jste přihlášen/a na pump.io.'; -$a->strings['return to the connector page'] = 'návrat na stránku konektoru'; -$a->strings['Post to pumpio'] = 'Posílat na pump.io'; -$a->strings['Save Settings'] = 'Uložit nastavení'; +$a->strings['Unable to register the client at the pump.io server \'%s\'.'] = 'Nebylo možné registrovat klienta na pump.io serveru \'%s\'.'; +$a->strings['You are now authenticated to pumpio.'] = 'Nyní jste přihlášen k pumpio.'; +$a->strings['return to the connector page'] = 'návrat ke stránce konektor'; +$a->strings['Post to pumpio'] = 'Příspěvek na pumpio'; +$a->strings['Pump.io Import/Export/Mirror'] = 'Pump.oi Import/Export/Zrcadlení'; +$a->strings['pump.io username (without the servername)'] = 'uživatelské jméno pump.io (bez jména serveru)'; +$a->strings['pump.io servername (without "http://" or "https://" )'] = 'jméno serveru pump.io (bez "http://" nebo "https://" )'; $a->strings['Authenticate your pump.io connection'] = 'Přihlásit ke spojení na pump.io'; $a->strings['Import the remote timeline'] = 'Importovat vzdálenou časovou osu'; +$a->strings['Enable pump.io Post Addon'] = 'Povolit doplněk pumo.io Post'; +$a->strings['Post to pump.io by default'] = 'Posílat příspěvky na pump.io automaticky'; $a->strings['Should posts be public?'] = 'Mají být příspěvky veřejné?'; $a->strings['Mirror all public posts'] = 'Zrcadlit všechny veřejné příspěvky'; -$a->strings['Pump.io Import/Export/Mirror'] = 'Import/Export/Zrcadlení Pump.io'; +$a->strings['Check to delete this preset'] = 'Zaškrtnout pro smazání tohoto nastavení'; +$a->strings['Save Settings'] = 'Uložit Nastavení'; +$a->strings['Pump.io post failed. Queued for retry.'] = 'Zaslání příspěvku na Pump.io selhalo. Příspěvek byl zařazen do fronty pro opakované odeslání.'; +$a->strings['Pump.io like failed. Queued for retry.'] = 'Zaslání příspěvku na Pump.io zřejmě selhalo. Příspěvek byl zařazen do fronty pro opakované odeslání.'; $a->strings['status'] = 'stav'; -$a->strings['%1$s likes %2$s\'s %3$s'] = 'Uživateli %1$s se líbí %3$s uživatele %2$s'; +$a->strings['%1$s likes %2$s\'s %3$s'] = '%1$s se líbí %3$s %2$s'; diff --git a/pumpio/lang/de/messages.po b/pumpio/lang/de/messages.po index 40119f32..5b33d2e3 100644 --- a/pumpio/lang/de/messages.po +++ b/pumpio/lang/de/messages.po @@ -12,9 +12,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:17-0500\n" -"PO-Revision-Date: 2014-06-23 11:30+0000\n" -"Last-Translator: Tobias Diekershoff , 2018,2022\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2022-01-22 17:36+0000\n" +"Last-Translator: Tobias Diekershoff \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/pumpio/lang/fr/messages.po b/pumpio/lang/fr/messages.po index 22b98743..2966c49c 100644 --- a/pumpio/lang/fr/messages.po +++ b/pumpio/lang/fr/messages.po @@ -4,7 +4,6 @@ # # # Translators: -# Florent C., 2023 # Hypolite Petovan , 2022 # ea1cd8241cb389ffb6f92bc6891eff5d_dc12308 <70dced5587d47e18d88f9298024d96f8_93383>, 2015 # StefOfficiel , 2015 @@ -12,86 +11,86 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-06-03 15:50-0400\n" +"POT-Creation-Date: 2021-11-21 19:17-0500\n" "PO-Revision-Date: 2014-06-23 11:30+0000\n" -"Last-Translator: Florent C., 2023\n" -"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n" +"Last-Translator: Hypolite Petovan , 2022\n" +"Language-Team: French (http://www.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:62 +#: pumpio.php:57 msgid "Permission denied." msgstr "Permission refusée." -#: pumpio.php:156 +#: pumpio.php:152 #, 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:196 +#: pumpio.php:192 msgid "You are now authenticated to pumpio." msgstr "Vous êtes maintenant authentifié sur pump.io." -#: pumpio.php:197 +#: pumpio.php:193 msgid "return to the connector page" msgstr "Retourner à la page du connecteur" -#: pumpio.php:217 +#: pumpio.php:213 msgid "Post to pumpio" msgstr "Publier sur pump.io" -#: pumpio.php:241 +#: pumpio.php:237 msgid "Save Settings" msgstr "Sauvegarder les paramètres" -#: pumpio.php:243 +#: pumpio.php:239 msgid "Delete this preset" msgstr "Supprimer ce préréglage" -#: pumpio.php:249 +#: pumpio.php:245 msgid "Authenticate your pump.io connection" msgstr "Identifiez votre connexion à pump.io" -#: pumpio.php:256 +#: pumpio.php:252 msgid "Pump.io servername (without \"http://\" or \"https://\" )" msgstr "Domaine du serveur Pump.io (sans \"http://\" ou \"https://\")" -#: pumpio.php:257 +#: pumpio.php:253 msgid "Pump.io username (without the servername)" msgstr "Nom d'utilisateur Pump.io (sans le domaine de serveur)" -#: pumpio.php:258 +#: pumpio.php:254 msgid "Import the remote timeline" -msgstr "Importer le flux distant" +msgstr "Importer la timeline distante" -#: pumpio.php:259 +#: pumpio.php:255 msgid "Enable Pump.io Post Addon" msgstr "Activer l'extension Pump.io" -#: pumpio.php:260 +#: pumpio.php:256 msgid "Post to Pump.io by default" msgstr "Publier sur Pump.io par défaut" -#: pumpio.php:261 +#: pumpio.php:257 msgid "Should posts be public?" msgstr "Les messages devraient être publiques ?" -#: pumpio.php:262 +#: pumpio.php:258 msgid "Mirror all public posts" msgstr "Refléter toutes les publications publiques" -#: pumpio.php:267 +#: pumpio.php:263 msgid "Pump.io Import/Export/Mirror" msgstr "Import/Export/Miroir Pump.io" -#: pumpio.php:924 +#: pumpio.php:920 msgid "status" msgstr "statut" -#: pumpio.php:928 +#: pumpio.php:924 #, 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 14ddade1..bdbbc462 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 le flux distant'; +$a->strings['Import the remote timeline'] = 'Importer la timeline distante'; $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/pumpio/lang/it/messages.po b/pumpio/lang/it/messages.po index 052e8797..2ab7e050 100644 --- a/pumpio/lang/it/messages.po +++ b/pumpio/lang/it/messages.po @@ -5,91 +5,98 @@ # # Translators: # fabrixxm , 2014,2018 -# Sylke Vicious , 2023 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:17-0500\n" -"PO-Revision-Date: 2014-06-23 11:30+0000\n" -"Last-Translator: Sylke Vicious , 2023\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"POT-Creation-Date: 2014-06-23 14:45+0200\n" +"PO-Revision-Date: 2018-03-19 13:25+0000\n" +"Last-Translator: fabrixxm \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: pumpio.php:57 +#: pumpio.php:38 msgid "Permission denied." msgstr "Permesso negato." -#: pumpio.php:152 +#: pumpio.php:124 #, php-format msgid "Unable to register the client at the pump.io server '%s'." msgstr "Impossibile registrare il client sul server pump.io '%s'" -#: pumpio.php:192 +#: pumpio.php:164 msgid "You are now authenticated to pumpio." msgstr "Sei autenticato su pump.io" -#: pumpio.php:193 +#: pumpio.php:165 msgid "return to the connector page" msgstr "ritorna alla pagina del connettore" -#: pumpio.php:213 +#: pumpio.php:183 msgid "Post to pumpio" msgstr "Invia a pump.io" -#: pumpio.php:237 -msgid "Save Settings" -msgstr "Salva Impostazioni" +#: pumpio.php:221 pumpio.php:225 +msgid "Pump.io Import/Export/Mirror" +msgstr "Esporta/Importa/Clona pump.io" -#: pumpio.php:239 -msgid "Delete this preset" -msgstr "Elimina questa preimpostazione" +#: pumpio.php:229 +msgid "pump.io username (without the servername)" +msgstr "nome utente pump.io (senza il nome del server)" -#: pumpio.php:245 +#: pumpio.php:234 +msgid "pump.io servername (without \"http://\" or \"https://\" )" +msgstr "nome del server pump.io (senza \"http://\" o \"https://\")" + +#: pumpio.php:246 msgid "Authenticate your pump.io connection" msgstr "Autentica la tua connessione pump.io" -#: pumpio.php:252 -msgid "Pump.io servername (without \"http://\" or \"https://\" )" -msgstr "Nome server Pump.io (senza \"http://\" o \"https://\" )" - -#: pumpio.php:253 -msgid "Pump.io username (without the servername)" -msgstr "Nome utente Pump.io (senza nome server)" - -#: pumpio.php:254 +#: pumpio.php:250 msgid "Import the remote timeline" msgstr "Importa la timeline remota" #: pumpio.php:255 -msgid "Enable Pump.io Post Addon" -msgstr "Abilita componente aggiuntivo di pubblicazione Pump.io" +msgid "Enable pump.io Post Addon" +msgstr "Abilita il componente aggiuntivo di invio ad pump.io" -#: pumpio.php:256 -msgid "Post to Pump.io by default" -msgstr "Pubblica su Pump.io per impostazione predefinita" +#: pumpio.php:260 +msgid "Post to pump.io by default" +msgstr "Invia sempre a pump.io" -#: pumpio.php:257 +#: pumpio.php:265 msgid "Should posts be public?" msgstr "I messaggi devono essere pubblici?" -#: pumpio.php:258 +#: pumpio.php:270 msgid "Mirror all public posts" msgstr "Clona tutti i messaggi pubblici" -#: pumpio.php:263 -msgid "Pump.io Import/Export/Mirror" -msgstr "Esporta/Importa/Clona pump.io" +#: pumpio.php:275 +msgid "Check to delete this preset" +msgstr "Seleziona per elimiare queto preset" -#: pumpio.php:920 +#: pumpio.php:285 +msgid "Save Settings" +msgstr "Salva Impostazioni" + +#: pumpio.php:515 +msgid "Pump.io post failed. Queued for retry." +msgstr "Invio a pump.io fallito. In attesa di riprovare." + +#: pumpio.php:587 +msgid "Pump.io like failed. Queued for retry." +msgstr "Invio 'mi piace' a pump.io fallito. In attesa di riprovare." + +#: pumpio.php:875 msgid "status" msgstr "stato" -#: pumpio.php:924 +#: pumpio.php:879 #, php-format msgid "%1$s likes %2$s's %3$s" msgstr "a %1$s piace %2$s di %3$s" diff --git a/pumpio/lang/it/strings.php b/pumpio/lang/it/strings.php index 512d3e7f..8721222c 100644 --- a/pumpio/lang/it/strings.php +++ b/pumpio/lang/it/strings.php @@ -3,23 +3,25 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $a->strings['Permission denied.'] = 'Permesso negato.'; $a->strings['Unable to register the client at the pump.io server \'%s\'.'] = 'Impossibile registrare il client sul server pump.io \'%s\''; $a->strings['You are now authenticated to pumpio.'] = 'Sei autenticato su pump.io'; $a->strings['return to the connector page'] = 'ritorna alla pagina del connettore'; $a->strings['Post to pumpio'] = 'Invia a pump.io'; -$a->strings['Save Settings'] = 'Salva Impostazioni'; -$a->strings['Delete this preset'] = 'Elimina questa preimpostazione'; +$a->strings['Pump.io Import/Export/Mirror'] = 'Esporta/Importa/Clona pump.io'; +$a->strings['pump.io username (without the servername)'] = 'nome utente pump.io (senza il nome del server)'; +$a->strings['pump.io servername (without "http://" or "https://" )'] = 'nome del server pump.io (senza "http://" o "https://")'; $a->strings['Authenticate your pump.io connection'] = 'Autentica la tua connessione pump.io'; -$a->strings['Pump.io servername (without "http://" or "https://" )'] = 'Nome server Pump.io (senza "http://" o "https://" )'; -$a->strings['Pump.io username (without the servername)'] = 'Nome utente Pump.io (senza nome server)'; $a->strings['Import the remote timeline'] = 'Importa la timeline remota'; -$a->strings['Enable Pump.io Post Addon'] = 'Abilita componente aggiuntivo di pubblicazione Pump.io'; -$a->strings['Post to Pump.io by default'] = 'Pubblica su Pump.io per impostazione predefinita'; +$a->strings['Enable pump.io Post Addon'] = 'Abilita il componente aggiuntivo di invio ad pump.io'; +$a->strings['Post to pump.io by default'] = 'Invia sempre a pump.io'; $a->strings['Should posts be public?'] = 'I messaggi devono essere pubblici?'; $a->strings['Mirror all public posts'] = 'Clona tutti i messaggi pubblici'; -$a->strings['Pump.io Import/Export/Mirror'] = 'Esporta/Importa/Clona pump.io'; +$a->strings['Check to delete this preset'] = 'Seleziona per elimiare queto preset'; +$a->strings['Save Settings'] = 'Salva Impostazioni'; +$a->strings['Pump.io post failed. Queued for retry.'] = 'Invio a pump.io fallito. In attesa di riprovare.'; +$a->strings['Pump.io like failed. Queued for retry.'] = 'Invio \'mi piace\' a pump.io fallito. In attesa di riprovare.'; $a->strings['status'] = 'stato'; $a->strings['%1$s likes %2$s\'s %3$s'] = 'a %1$s piace %2$s di %3$s'; diff --git a/pumpio/pumpio.php b/pumpio/pumpio.php index 6600696e..11cac8cd 100644 --- a/pumpio/pumpio.php +++ b/pumpio/pumpio.php @@ -18,7 +18,7 @@ use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Contact; -use Friendica\Model\Circle; +use Friendica\Model\Group; use Friendica\Model\Item; use Friendica\Model\Post; use Friendica\Model\User; @@ -96,7 +96,7 @@ function pumpio_registerclient($host) $application_name = DI::config()->get('pumpio', 'application_name'); if ($application_name == '') { - $application_name = DI::baseUrl()->getHost(); + $application_name = DI::baseUrl()->getHostname(); } $firstAdmin = User::getFirstAdmin(['email']); @@ -105,8 +105,8 @@ function pumpio_registerclient($host) $params['contacts'] = $firstAdmin['email']; $params['application_type'] = 'native'; $params['application_name'] = $application_name; - $params['logo_url'] = DI::baseUrl() . '/images/friendica-256.png'; - $params['redirect_uris'] = DI::baseUrl() . '/pumpio/connect'; + $params['logo_url'] = DI::baseUrl()->get() . '/images/friendica-256.png'; + $params['redirect_uris'] = DI::baseUrl()->get() . '/pumpio/connect'; Logger::info('pumpio_registerclient: ' . $url . ' parameters', $params); @@ -157,7 +157,7 @@ function pumpio_connect() } // The callback URL is the script that gets called after the user authenticates with pumpio - $callback_url = DI::baseUrl() . '/pumpio/connect'; + $callback_url = DI::baseUrl()->get() . '/pumpio/connect'; // Let's begin. First we need a Request Token. The request token is required to send the user // to pumpio's login page. @@ -194,7 +194,7 @@ function pumpio_connect() if ($success) { Logger::notice('pumpio_connect: authenticated'); $o = DI::l10n()->t('You are now authenticated to pumpio.'); - $o .= '
' . DI::l10n()->t('return to the connector page') . ''; + $o .= '
' . DI::l10n()->t('return to the connector page') . ''; } else { Logger::notice('pumpio_connect: could not connect'); $o = 'Could not connect to pumpio. Refresh the page or try again later.'; @@ -252,7 +252,7 @@ function pumpio_settings(array &$data) '$pumpio_user' => $pumpio_user, '$oauth_token' => $oauth_token, '$oauth_token_secret' => $oauth_token_secret, - '$authenticate_url' => DI::baseUrl() . '/pumpio/connect', + '$authenticate_url' => DI::baseUrl()->get() . '/pumpio/connect', '$servername' => ['pumpio_host', DI::l10n()->t('Pump.io servername (without "http://" or "https://" )'), $pumpio_host], '$username' => ['pumpio_user', DI::l10n()->t('Pump.io username (without the servername)'), $pumpio_user], '$import' => ['pumpio_import', DI::l10n()->t('Import the remote timeline'), $import_enabled], @@ -417,7 +417,7 @@ function pumpio_send(array &$b) } // Dont't post if the post doesn't belong to us. - // This is a check for group postings + // This is a check for forum postings $self = User::getOwnerDataById($b['uid']); if ($b['contact-id'] != $self['id']) { return; @@ -711,7 +711,7 @@ function pumpio_fetchtimeline(int $uid) $application_name = DI::config()->get('pumpio', 'application_name'); } if ($application_name == '') { - $application_name = DI::baseUrl()->getHost(); + $application_name = DI::baseUrl()->getHostname(); } $first_time = ($lastdate == ''); @@ -976,7 +976,7 @@ function pumpio_get_contact($uid, $contact, $no_insert = false) $contact_id = $r['id']; - Circle::addMember(User::getDefaultCircle($uid), $contact_id); + Group::addMember(User::getDefaultGroup($uid), $contact_id); } else { $contact_id = $r['id']; } @@ -1353,8 +1353,8 @@ function pumpio_getreceiver(array $b) $gid = trim($gid, ' <>'); $contacts = DBA::p("SELECT `contact`.`name`, `contact`.`nick`, `contact`.`url`, `contact`.`network` - FROM `group_member` AS `circle_member`, `contact` WHERE `circle_member`.`gid` = ? - AND `contact`.`id` = `circle_member`.`contact-id` AND `contact`.`network` = ?", + FROM `group_member`, `contact` WHERE `group_member`.`gid` = ? + AND `contact`.`id` = `group_member`.`contact-id` AND `contact`.`network` = ?", $gid, Protocol::PUMPIO); while ($row = DBA::fetch($contacts)) { diff --git a/qcomment/lang/cs/messages.po b/qcomment/lang/cs/messages.po index deb0b4ec..d2a204e3 100644 --- a/qcomment/lang/cs/messages.po +++ b/qcomment/lang/cs/messages.po @@ -10,38 +10,46 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:16-0500\n" -"PO-Revision-Date: 2014-06-23 12:30+0000\n" -"Last-Translator: Aditoo, 2018\n" -"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" +"POT-Creation-Date: 2013-02-27 05:01-0500\n" +"PO-Revision-Date: 2018-06-13 18:00+0000\n" +"Last-Translator: Aditoo\n" +"Language-Team: Czech (http://www.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" -#: qcomment.php:45 +#: qcomment.php:51 msgid ":-)" msgstr ":-)" -#: qcomment.php:45 +#: qcomment.php:51 msgid ":-(" msgstr ":-(" -#: qcomment.php:45 +#: qcomment.php:51 msgid "lol" msgstr "lol" -#: qcomment.php:49 +#: qcomment.php:54 +msgid "Quick Comment Settings" +msgstr "Nastavení rychlých komentářů" + +#: qcomment.php:56 msgid "" "Quick comments are found near comment boxes, sometimes hidden. Click them to" " provide simple replies." -msgstr "Rychlé komentáře jsou k nalezení blízko polí s komentáři, někdy jsou skryté. Klikněte na ně pro poskytnutí jednoduchých odpovědí." +msgstr "Rychlé komentáře jsou k nalezení blízko polí s komentáři, někdy jsou skryté. Klikněte na ně k poskytnutí jednoduchých odpovědí." -#: qcomment.php:50 +#: qcomment.php:57 msgid "Enter quick comments, one per line" msgstr "Zadejte rychlé komentáře, každý na nový řádek" -#: qcomment.php:55 -msgid "Quick Comment Settings" -msgstr "Nastavení rychlých komentářů" +#: qcomment.php:61 +msgid "Submit" +msgstr "Odeslat" + +#: qcomment.php:75 +msgid "Quick Comment settings saved." +msgstr "Nastavení Quick Comment uloženo." diff --git a/qcomment/lang/cs/strings.php b/qcomment/lang/cs/strings.php index 08df5fb4..3d70952f 100644 --- a/qcomment/lang/cs/strings.php +++ b/qcomment/lang/cs/strings.php @@ -8,6 +8,8 @@ function string_plural_select_cs($n){ $a->strings[':-)'] = ':-)'; $a->strings[':-('] = ':-('; $a->strings['lol'] = 'lol'; -$a->strings['Quick comments are found near comment boxes, sometimes hidden. Click them to provide simple replies.'] = 'Rychlé komentáře jsou k nalezení blízko polí s komentáři, někdy jsou skryté. Klikněte na ně pro poskytnutí jednoduchých odpovědí.'; -$a->strings['Enter quick comments, one per line'] = 'Zadejte rychlé komentáře, každý na nový řádek'; $a->strings['Quick Comment Settings'] = 'Nastavení rychlých komentářů'; +$a->strings['Quick comments are found near comment boxes, sometimes hidden. Click them to provide simple replies.'] = 'Rychlé komentáře jsou k nalezení blízko polí s komentáři, někdy jsou skryté. Klikněte na ně k poskytnutí jednoduchých odpovědí.'; +$a->strings['Enter quick comments, one per line'] = 'Zadejte rychlé komentáře, každý na nový řádek'; +$a->strings['Submit'] = 'Odeslat'; +$a->strings['Quick Comment settings saved.'] = 'Nastavení Quick Comment uloženo.'; diff --git a/qcomment/lang/de/messages.po b/qcomment/lang/de/messages.po index bab1515f..323ef82d 100644 --- a/qcomment/lang/de/messages.po +++ b/qcomment/lang/de/messages.po @@ -12,9 +12,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:16-0500\n" -"PO-Revision-Date: 2014-06-23 12:30+0000\n" -"Last-Translator: Steffen K9, 2021\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2021-12-22 16:24+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/qcomment/lang/it/messages.po b/qcomment/lang/it/messages.po index 2347a0dd..5772fcd2 100644 --- a/qcomment/lang/it/messages.po +++ b/qcomment/lang/it/messages.po @@ -5,43 +5,50 @@ # # Translators: # fabrixxm , 2014-2015 -# Sylke Vicious , 2021 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:16-0500\n" -"PO-Revision-Date: 2014-06-23 12:30+0000\n" -"Last-Translator: Sylke Vicious , 2021\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"POT-Creation-Date: 2013-02-27 05:01-0500\n" +"PO-Revision-Date: 2017-09-20 06:08+0000\n" +"Last-Translator: fabrixxm \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: qcomment.php:45 +#: qcomment.php:51 msgid ":-)" msgstr ":-)" -#: qcomment.php:45 +#: qcomment.php:51 msgid ":-(" msgstr ":-(" -#: qcomment.php:45 +#: qcomment.php:51 msgid "lol" msgstr "lol" -#: qcomment.php:49 +#: qcomment.php:54 +msgid "Quick Comment Settings" +msgstr "Impostazioni commento rapido" + +#: qcomment.php:56 msgid "" "Quick comments are found near comment boxes, sometimes hidden. Click them to" " provide simple replies." msgstr "Trovi i commenti rapidi vicino al box dei commenti, a volte nascosti. Cliccali per inviare semplici risposte." -#: qcomment.php:50 +#: qcomment.php:57 msgid "Enter quick comments, one per line" msgstr "Inserire un commento rapido, uno per linea" -#: qcomment.php:55 -msgid "Quick Comment Settings" -msgstr "Impostazioni commento rapido" +#: qcomment.php:61 +msgid "Submit" +msgstr "Invia" + +#: qcomment.php:75 +msgid "Quick Comment settings saved." +msgstr "Impostazioni commento rapido salvate." diff --git a/qcomment/lang/it/strings.php b/qcomment/lang/it/strings.php index 26f8229a..59edbe06 100644 --- a/qcomment/lang/it/strings.php +++ b/qcomment/lang/it/strings.php @@ -3,11 +3,13 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $a->strings[':-)'] = ':-)'; $a->strings[':-('] = ':-('; $a->strings['lol'] = 'lol'; +$a->strings['Quick Comment Settings'] = 'Impostazioni commento rapido'; $a->strings['Quick comments are found near comment boxes, sometimes hidden. Click them to provide simple replies.'] = 'Trovi i commenti rapidi vicino al box dei commenti, a volte nascosti. Cliccali per inviare semplici risposte.'; $a->strings['Enter quick comments, one per line'] = 'Inserire un commento rapido, uno per linea'; -$a->strings['Quick Comment Settings'] = 'Impostazioni commento rapido'; +$a->strings['Submit'] = 'Invia'; +$a->strings['Quick Comment settings saved.'] = 'Impostazioni commento rapido salvate.'; diff --git a/randplace/lang/de/messages.po b/randplace/lang/de/messages.po index abbaefd8..f2d1fb54 100644 --- a/randplace/lang/de/messages.po +++ b/randplace/lang/de/messages.po @@ -12,9 +12,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:16-0500\n" -"PO-Revision-Date: 2014-06-23 12:34+0000\n" -"Last-Translator: Steffen K9, 2021\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2021-12-22 17:21+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/randplace/lang/it/messages.po b/randplace/lang/it/messages.po index 673d0f6f..708a60ac 100644 --- a/randplace/lang/it/messages.po +++ b/randplace/lang/it/messages.po @@ -10,20 +10,24 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:16-0500\n" -"PO-Revision-Date: 2014-06-23 12:34+0000\n" -"Last-Translator: Sylke Vicious , 2021\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"POT-Creation-Date: 2021-02-01 18:15+0100\n" +"PO-Revision-Date: 2021-02-16 12:57+0000\n" +"Last-Translator: Sylke Vicious \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" - -#: randplace.php:161 -msgid "Enable Randplace Addon" -msgstr "Abilita il componente aggiuntivo Posizione Casuale" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: randplace.php:166 msgid "Randplace Settings" msgstr "Impostazioni \"Posizione casuale\"" + +#: randplace.php:168 +msgid "Enable Randplace Addon" +msgstr "Abilita il componente aggiuntivo Posizione Casuale" + +#: randplace.php:174 +msgid "Save Settings" +msgstr "Salva Impostazioni" diff --git a/randplace/lang/it/strings.php b/randplace/lang/it/strings.php index 5d71eba3..7b4a9947 100644 --- a/randplace/lang/it/strings.php +++ b/randplace/lang/it/strings.php @@ -3,7 +3,8 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} -$a->strings['Enable Randplace Addon'] = 'Abilita il componente aggiuntivo Posizione Casuale'; $a->strings['Randplace Settings'] = 'Impostazioni "Posizione casuale"'; +$a->strings['Enable Randplace Addon'] = 'Abilita il componente aggiuntivo Posizione Casuale'; +$a->strings['Save Settings'] = 'Salva Impostazioni'; diff --git a/rendertime/lang/cs/messages.po b/rendertime/lang/cs/messages.po index e9fc0c9b..1a2404d7 100644 --- a/rendertime/lang/cs/messages.po +++ b/rendertime/lang/cs/messages.po @@ -4,52 +4,24 @@ # # # Translators: -# Aditoo, 2018 -# michal_s , 2014 +# Michal Šupler , 2014 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-12-12 22:09+0000\n" -"PO-Revision-Date: 2014-06-23 12:36+0000\n" -"Last-Translator: Aditoo, 2018\n" -"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" +"POT-Creation-Date: 2014-06-22 13:18+0200\n" +"PO-Revision-Date: 2014-07-28 18:10+0000\n" +"Last-Translator: Michal Šupler \n" +"Language-Team: Czech (http://www.transifex.com/projects/p/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" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" #: rendertime.php:30 -msgid "Save Settings" -msgstr "" - -#: rendertime.php:31 -msgid "Show callstack" -msgstr "" - -#: rendertime.php:31 -msgid "" -"Show detailed performance measures in the callstack. When deactivated, only " -"the summary will be displayed." -msgstr "" - -#: rendertime.php:32 -msgid "Minimal time" -msgstr "" - -#: rendertime.php:32 -msgid "Minimal time that an activity needs to be listed in the callstack." -msgstr "" - -#: rendertime.php:57 #, php-format msgid "" -"Database: %s/%s, Network: %s, Rendering: %s, Session: %s, I/O: %s, Other: " -"%s, Total: %s" -msgstr "" - -#: rendertime.php:74 -#, php-format -msgid "Class-Init: %s, Boot: %s, Init: %s, Content: %s, Other: %s, Total: %s" -msgstr "" +"Performance: Database: %s, Network: %s, Rendering: %s, Parser: %s, I/O: %s, " +"Other: %s, Total: %s" +msgstr "Výkonnost: Databáze: %s, Síť: %s, Rendering: %s, Parser: %s, I/O: %s, Ostatní: %s, Celkem: %s" diff --git a/rendertime/lang/cs/strings.php b/rendertime/lang/cs/strings.php index ce2e465e..1fc547fa 100644 --- a/rendertime/lang/cs/strings.php +++ b/rendertime/lang/cs/strings.php @@ -3,5 +3,6 @@ if(! function_exists("string_plural_select_cs")) { function string_plural_select_cs($n){ $n = intval($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; } + if (($n==1)) { return 0; } else if (($n>=2 && $n<=4)) { return 1; } else { return 2; } }} +$a->strings['Performance: Database: %s, Network: %s, Rendering: %s, Parser: %s, I/O: %s, Other: %s, Total: %s'] = 'Výkonnost: Databáze: %s, Síť: %s, Rendering: %s, Parser: %s, I/O: %s, Ostatní: %s, Celkem: %s'; diff --git a/rendertime/lang/de/messages.po b/rendertime/lang/de/messages.po index 293ed698..f615f1b3 100644 --- a/rendertime/lang/de/messages.po +++ b/rendertime/lang/de/messages.po @@ -11,9 +11,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-12-12 22:09+0000\n" -"PO-Revision-Date: 2014-06-23 12:36+0000\n" -"Last-Translator: Tobias Diekershoff , 2021-2022\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2022-01-22 17:39+0000\n" +"Last-Translator: Tobias Diekershoff \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/rendertime/lang/it/messages.po b/rendertime/lang/it/messages.po index 482abb02..abbc63e6 100644 --- a/rendertime/lang/it/messages.po +++ b/rendertime/lang/it/messages.po @@ -10,46 +10,24 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-12-12 22:09+0000\n" -"PO-Revision-Date: 2014-06-23 12:36+0000\n" -"Last-Translator: Sylke Vicious , 2021\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"POT-Creation-Date: 2021-02-01 18:15+0100\n" +"PO-Revision-Date: 2021-02-16 13:01+0000\n" +"Last-Translator: Sylke Vicious \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: rendertime.php:30 -msgid "Save Settings" -msgstr "" - -#: rendertime.php:31 -msgid "Show callstack" -msgstr "" - -#: rendertime.php:31 -msgid "" -"Show detailed performance measures in the callstack. When deactivated, only " -"the summary will be displayed." -msgstr "" - -#: rendertime.php:32 -msgid "Minimal time" -msgstr "" - -#: rendertime.php:32 -msgid "Minimal time that an activity needs to be listed in the callstack." -msgstr "" - -#: rendertime.php:57 +#: rendertime.php:36 #, php-format msgid "" "Database: %s/%s, Network: %s, Rendering: %s, Session: %s, I/O: %s, Other: " "%s, Total: %s" msgstr "Database: %s/%s, Rete: %s, Rendering: %s, Sessione: %s, I/O: %s, Altro: %s, Totale: %s" -#: rendertime.php:74 +#: rendertime.php:53 #, php-format msgid "Class-Init: %s, Boot: %s, Init: %s, Content: %s, Other: %s, Total: %s" msgstr "Class-Init: %s, Boot: %s, Init: %s, Content: %s, Altro: %s, Totale: %s" diff --git a/rendertime/lang/it/strings.php b/rendertime/lang/it/strings.php index 5b05d933..6eaf200c 100644 --- a/rendertime/lang/it/strings.php +++ b/rendertime/lang/it/strings.php @@ -3,7 +3,7 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $a->strings['Database: %s/%s, Network: %s, Rendering: %s, Session: %s, I/O: %s, Other: %s, Total: %s'] = 'Database: %s/%s, Rete: %s, Rendering: %s, Sessione: %s, I/O: %s, Altro: %s, Totale: %s'; $a->strings['Class-Init: %s, Boot: %s, Init: %s, Content: %s, Other: %s, Total: %s'] = 'Class-Init: %s, Boot: %s, Init: %s, Content: %s, Altro: %s, Totale: %s'; diff --git a/s3_storage/composer.lock b/s3_storage/composer.lock index 992e5a9e..78b10dd9 100644 --- a/s3_storage/composer.lock +++ b/s3_storage/composer.lock @@ -8,35 +8,32 @@ "packages": [ { "name": "akeeba/s3", - "version": "2.3.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/akeeba/s3.git", - "reference": "7f5b3e929c93eb02ba24472560c0cbbef735aed9" + "reference": "01520dae1f736555e08efda0ddc1044701bd340a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/akeeba/s3/zipball/7f5b3e929c93eb02ba24472560c0cbbef735aed9", - "reference": "7f5b3e929c93eb02ba24472560c0cbbef735aed9", + "url": "https://api.github.com/repos/akeeba/s3/zipball/01520dae1f736555e08efda0ddc1044701bd340a", + "reference": "01520dae1f736555e08efda0ddc1044701bd340a", "shasum": "" }, "require": { "ext-curl": "*", "ext-simplexml": "*", - "php": ">=7.1.0 <8.4" + "php": ">=7.1.0 <8.1" }, "type": "library", "autoload": { - "files": [ - "src/aliasing.php" - ], "psr-4": { - "Akeeba\\S3\\": "src" + "Akeeba\\Engine\\Postproc\\Connector\\S3v4\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "GPL-3.0-or-later" + "GPL-3.0+" ], "authors": [ { @@ -51,7 +48,7 @@ "keywords": [ "s3" ], - "time": "2023-09-26T11:40:10+00:00" + "time": "2020-11-30T14:03:55+00:00" } ], "packages-dev": [], diff --git a/s3_storage/vendor/akeeba/s3/.gitignore b/s3_storage/vendor/akeeba/s3/.gitignore index 09e75c29..54f46f28 100644 --- a/s3_storage/vendor/akeeba/s3/.gitignore +++ b/s3_storage/vendor/akeeba/s3/.gitignore @@ -1,6 +1,5 @@ /.idea/ /000/ -/minitest/config.* -!/minitest/config.dist.php +/minitest/config.php /minitest/tmp /vendor/ diff --git a/s3_storage/vendor/akeeba/s3/README.md b/s3_storage/vendor/akeeba/s3/README.md index eb3c5b53..d082720c 100644 --- a/s3_storage/vendor/akeeba/s3/README.md +++ b/s3_storage/vendor/akeeba/s3/README.md @@ -4,53 +4,29 @@ 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 a 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 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 GPL-3.0-or-later, as noted in composer.json. +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+". -## Important notes about version 2 +## Important note about version 2 -### PHP version support since 2.0 +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. -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. +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. ## 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\S3\Configuration( +$configuration = new \Akeeba\Engine\Postproc\Connector\S3v4\Configuration( 'YourAmazonAccessKey', 'YourAmazonSecretKey' ); -$connector = new \Akeeba\S3\Connector($configuration); +$connector = new \Akeeba\Engine\Postproc\Connector\S3v4\Connector($configuration); ``` If you are running inside an Amazon EC2 instance you can fetch temporary credentials from the instance's metadata @@ -61,7 +37,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\S3\Configuration( +$configuration = new \Akeeba\Engine\Postproc\Connector\S3v4\Configuration( $credentials['AccessKeyId'], $credentials['SecretAccessKey'], 'v4', @@ -69,14 +45,14 @@ $configuration = new \Akeeba\S3\Configuration( ); $configuration->setToken($credentials['Token']); -$connector = new \Akeeba\S3\Connector($configuration); +$connector = new \Akeeba\Engine\Postproc\Connector\S3v4\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. -Another point worth noting is that the temporary credentials don't last forever. Check the `$credentials['Expiration']` to see +Also 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. @@ -144,21 +120,21 @@ The last parameter (common prefixes) controls the listing of "subdirectories" From a file: ```php -$input = \Akeeba\S3\Input::createFromFile($sourceFile); +$input = \Akeeba\Engine\Postproc\Connector\S3v4\Input::createFromFile($sourceFile); $connector->putObject($input, 'mybucket', 'path/to/myfile.txt'); ``` From a string: ```php -$input = \Akeeba\S3\Input::createFromData($sourceString); +$input = \Akeeba\Engine\Postproc\Connector\S3v4\Input::createFromData($sourceString); $connector->putObject($input, 'mybucket', 'path/to/myfile.txt'); ``` From a stream resource: ```php -$input = \Akeeba\S3\Input::createFromResource($streamHandle, false); +$input = \Akeeba\Engine\Postproc\Connector\S3v4\Input::createFromResource($streamHandle, false); $connector->putObject($input, 'mybucket', 'path/to/myfile.txt'); ``` @@ -169,7 +145,7 @@ In all cases the entirety of the file has to be loaded in memory. Files are uploaded in 5Mb chunks. ```php -$input = \Akeeba\S3\Input::createFromFile($sourceFile); +$input = \Akeeba\Engine\Postproc\Connector\S3v4\Input::createFromFile($sourceFile); $uploadId = $connector->startMultipart($input, 'mybucket', 'mypath/movie.mov'); $eTags = array(); @@ -179,7 +155,7 @@ $partNumber = 0; do { // IMPORTANT: You MUST create the input afresh before each uploadMultipart call - $input = \Akeeba\S3\Input::createFromFile($sourceFile); + $input = \Akeeba\Engine\Postproc\Connector\S3v4\Input::createFromFile($sourceFile); $input->setUploadID($uploadId); $input->setPartNumber(++$partNumber); @@ -193,7 +169,7 @@ do while (!is_null($eTag)); // IMPORTANT: You MUST create the input afresh before finalising the multipart upload -$input = \Akeeba\S3\Input::createFromFile($sourceFile); +$input = \Akeeba\Engine\Postproc\Connector\S3v4\Input::createFromFile($sourceFile); $input->setUploadID($uploadId); $input->setEtags($eTags); @@ -233,23 +209,6 @@ $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. @@ -257,7 +216,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\S3\Configuration( +$configuration = new \Akeeba\Engine\Postproc\Connector\S3v4\Configuration( 'YourAmazonAccessKey', 'YourAmazonSecretKey' ); @@ -266,7 +225,7 @@ $configuration = new \Akeeba\S3\Configuration( $configuration->setSignatureMethod('v4'); $configuration->setUseDualstackUrl(true); -$connector = new \Akeeba\S3\Connector($configuration); +$connector = new \Akeeba\Engine\Postproc\Connector\S3v4\Connector($configuration); ``` ### HTTPS vs plain HTTP @@ -286,7 +245,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\S3\Configuration( +$configuration = new \Akeeba\Engine\Postproc\Connector\S3v4\Configuration( '532SZONTQ6ALKBCU94OU', 'zCkY83KVDXD8u83RouEYPKEm/dhPSPB45XsfnWj8fxQ', 'v4', @@ -294,7 +253,7 @@ $configuration = new \Akeeba\S3\Configuration( ); $configuration->setEndpoint('nyc3.digitaloceanspaces.com'); -$connector = new \Akeeba\S3\Connector($configuration); +$connector = new \Akeeba\Engine\Postproc\Connector\S3v4\Connector($configuration); ``` If your S3-compatible API uses v2 signatures you do not need to specify a region. @@ -302,14 +261,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\S3\Configuration( +$configuration = new \Akeeba\Engine\Postproc\Connector\S3v4\Configuration( '532SZONTQ6ALKBCU94OU', 'zCkY83KVDXD8u83RouEYPKEm/dhPSPB45XsfnWj8fxQ', 'v2' ); $configuration->setEndpoint('nyc3.digitaloceanspaces.com'); -$connector = new \Akeeba\S3\Connector($configuration); +$connector = new \Akeeba\Engine\Postproc\Connector\S3v4\Connector($configuration); ``` ### Legacy path-style access @@ -323,7 +282,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 very likely work with the v2 signatures if you are using a custom endpoint, though. +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. ### Dualstack (IPv4 and IPv6) support diff --git a/s3_storage/vendor/akeeba/s3/TODO.md b/s3_storage/vendor/akeeba/s3/TODO.md new file mode 100644 index 00000000..e19fb64c --- /dev/null +++ b/s3_storage/vendor/akeeba/s3/TODO.md @@ -0,0 +1,13 @@ +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 2d3ef59f..bfb1943c 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.4", + "php": ">=7.1.0 <8.1", "ext-curl": "*", "ext-simplexml": "*" }, @@ -11,7 +11,7 @@ "s3" ], "homepage": "https://github.com/akeeba/s3", - "license": "GPL-3.0-or-later", + "license": "GPL-3.0+", "authors": [ { "name": "Nicholas K. Dionysopoulos", @@ -22,16 +22,7 @@ ], "autoload": { "psr-4": { - "Akeeba\\S3\\": "src" - }, - "files": [ - "src/aliasing.php" - ] - }, - "archive": { - "exclude": [ - "minitest", - "TODO.md" - ] + "Akeeba\\Engine\\Postproc\\Connector\\S3v4\\": "src" + } } } diff --git a/s3_storage/vendor/akeeba/s3/composer.lock b/s3_storage/vendor/akeeba/s3/composer.lock index a7e203f9..e7cbd746 100644 --- a/s3_storage/vendor/akeeba/s3/composer.lock +++ b/s3_storage/vendor/akeeba/s3/composer.lock @@ -1,22 +1,19 @@ { - "_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" + "_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": [] } diff --git a/s3_storage/vendor/akeeba/s3/minitest/NOTES.md b/s3_storage/vendor/akeeba/s3/minitest/NOTES.md deleted file mode 100644 index b31f4f0a..00000000 --- a/s3_storage/vendor/akeeba/s3/minitest/NOTES.md +++ /dev/null @@ -1,62 +0,0 @@ -# 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 895259dd..8470e260 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\S3\Connector; +use Akeeba\Engine\Postproc\Connector\S3v4\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(static::getTempFolder(), 'as3'); + $tempFilePath = tempnam(self::getTempFolder(), 'as3'); if ($tempFilePath === false) { throw new RuntimeException("Cannot create a temporary file."); } - $fp = @fopen($tempFilePath, 'w', false); + $fp = @fopen($tempFilePath, 'wb', false); if ($fp === false) { throw new RuntimeException("Cannot write to the temporary file."); } - $blockSize = static::BLOCK_SIZE; + $blockSize = self::BLOCK_SIZE; $lastBlockSize = $size % $blockSize; $wholeBlocks = (int) (($size - $lastBlockSize) / $blockSize); - $blockData = static::getRandomData(); + $blockData = self::getRandomData(); for ($i = 0; $i < $wholeBlocks; $i++) { @@ -83,7 +83,7 @@ abstract class AbstractTest if (!$reuseBlock) { - $blockData = static::getRandomData($blockSize); + $blockData = self::getRandomData($blockSize); } } @@ -155,7 +155,7 @@ abstract class AbstractTest return false; } - return hash_file(static::FILE_HASHING_ALGORITHM, $referenceFilePath) === hash_file(static::FILE_HASHING_ALGORITHM, $unknownFilePath); + return hash_file(self::FILE_HASHING_ALGORITHM, $referenceFilePath) === hash_file(self::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 437d73ed..b7273bad 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\S3\Connector; -use Akeeba\S3\Input; +use Akeeba\Engine\Postproc\Connector\S3v4\Connector; +use Akeeba\Engine\Postproc\Connector\S3v4\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 static::upload(). Zero for single part uploads, non-zero for multipart uploads. + * This is set by self::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 static::upload($s3, $options, static::FIVE_MB, 'bigtest_5mb.dat'); + return self::upload($s3, $options, self::FIVE_MB, 'bigtest_5mb.dat'); } public static function upload6MBString(Connector $s3, array $options): bool { - return static::upload($s3, $options, static::SIX_MB, 'bigtest_6mb.dat'); + return self::upload($s3, $options, self::SIX_MB, 'bigtest_6mb.dat'); } public static function upload10MBString(Connector $s3, array $options): bool { - return static::upload($s3, $options, static::TEN_MB, 'bigtest_10mb.dat'); + return self::upload($s3, $options, self::TEN_MB, 'bigtest_10mb.dat'); } public static function upload11MBString(Connector $s3, array $options): bool { - return static::upload($s3, $options, static::ELEVEN_MB, 'bigtest_11mb.dat'); + return self::upload($s3, $options, self::ELEVEN_MB, 'bigtest_11mb.dat'); } public static function upload5MBFile(Connector $s3, array $options): bool { - return static::upload($s3, $options, static::FIVE_MB, 'bigtest_5mb.dat', false); + return self::upload($s3, $options, self::FIVE_MB, 'bigtest_5mb.dat', false); } public static function upload6MBFile(Connector $s3, array $options): bool { - return static::upload($s3, $options, static::SIX_MB, 'bigtest_6mb.dat', false); + return self::upload($s3, $options, self::SIX_MB, 'bigtest_6mb.dat', false); } public static function upload10MBFile(Connector $s3, array $options): bool { - return static::upload($s3, $options, static::TEN_MB, 'bigtest_10mb.dat', false); + return self::upload($s3, $options, self::TEN_MB, 'bigtest_10mb.dat', false); } public static function upload11MBFile(Connector $s3, array $options): bool { - return static::upload($s3, $options, static::ELEVEN_MB, 'bigtest_11mb.dat', false); + return self::upload($s3, $options, self::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); - static::$numberOfChunks = 0; + self::$numberOfChunks = 0; if ($useString) { - $sourceData = static::getRandomData($size); + $sourceData = self::getRandomData($size); $input = Input::createFromData($sourceData); } else { // Create a file with random data - $sourceFile = static::createFile($size); + $sourceFile = self::createFile($size); $input = Input::createFromFile($sourceFile); } // Upload the file. Throws exception if it fails. $bucket = $options['bucket']; - if (!static::$multipart) + if (!self::$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, [], static::$uploadChunkSize); + $etag = $s3->uploadMultipart($input, $bucket, $uri, [], self::$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++; } - static::$numberOfChunks = count($eTags); + self::$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 (static::$downloadAfter) + if (self::$downloadAfter) { if ($useString) { @@ -184,16 +184,16 @@ class BigFiles extends AbstractTest $downloadedData = $s3->getObject($bucket, $uri); // Compare the file contents. - $result = static::areStringsEqual($sourceData, $downloadedData); + $result = self::areStringsEqual($sourceData, $downloadedData); } else { // Download the data. Throws exception if it fails. - $downloadedFile = tempnam(static::getTempFolder(), 'as3'); + $downloadedFile = tempnam(self::getTempFolder(), 'as3'); $s3->getObject($bucket, $uri, $downloadedFile); // Compare the file contents. - $result = static::areFilesEqual($sourceFile, $downloadedFile); + $result = self::areFilesEqual($sourceFile, $downloadedFile); @unlink($downloadedFile); } @@ -206,7 +206,7 @@ class BigFiles extends AbstractTest } // Should I delete the remotely stored file? - if (static::$deleteRemote) + if (self::$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 ff04f58a..6ba388b4 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\S3\Connector; +use Akeeba\Engine\Postproc\Connector\S3v4\Connector; class BucketLocation extends AbstractTest { @@ -18,7 +18,7 @@ class BucketLocation extends AbstractTest { $location = $s3->getBucketLocation($options['bucket']); - static::assert($location === $options['region'], "Bucket ‘{$options['bucket']}′ reports being in region ‘{$location}′ instead of expected ‘{$options['region']}′"); + self::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 4dab491d..33925cd2 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\S3\Connector; +use Akeeba\Engine\Postproc\Connector\S3v4\Connector; use RuntimeException; class BucketsList extends AbstractTest @@ -19,16 +19,16 @@ class BucketsList extends AbstractTest { $buckets = $s3->listBuckets(true); - 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"); + 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"); foreach ($buckets['buckets'] as $bucketInfo) { - 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"); + 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"); if ($bucketInfo['name'] === $options['bucket']) { @@ -43,8 +43,8 @@ class BucketsList extends AbstractTest { $buckets = $s3->listBuckets(false); - 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']}′"); + 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']}′"); return true; } diff --git a/s3_storage/vendor/akeeba/s3/minitest/Test/HeadObject.php b/s3_storage/vendor/akeeba/s3/minitest/Test/HeadObject.php deleted file mode 100644 index 535afdbd..00000000 --- a/s3_storage/vendor/akeeba/s3/minitest/Test/HeadObject.php +++ /dev/null @@ -1,67 +0,0 @@ -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 00b5fdbf..53893922 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\S3\Connector; -use Akeeba\S3\Exception\CannotPutFile; -use Akeeba\S3\Input; +use Akeeba\Engine\Postproc\Connector\S3v4\Connector; +use Akeeba\Engine\Postproc\Connector\S3v4\Exception\CannotPutFile; +use Akeeba\Engine\Postproc\Connector\S3v4\Input; class ListFiles extends AbstractTest { @@ -34,9 +34,9 @@ class ListFiles extends AbstractTest public static function setup(Connector $s3, array $options): void { - $data = static::getRandomData(static::TEN_KB); + $data = self::getRandomData(self::TEN_KB); - foreach (static::$paths as $uri) + foreach (self::$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 (static::$paths as $uri) + foreach (self::$paths as $uri) { try { @@ -69,29 +69,29 @@ class ListFiles extends AbstractTest { $listing = $s3->getBucket($options['bucket'], 'listtest_'); - static::assert(is_array($listing), "The files listing must be an array"); - static::assert(count($listing) == 3, "I am expecting to see 3 files"); + self::assert(is_array($listing), "The files listing must be an array"); + self::assert(count($listing) == 3, "I am expecting to see 3 files"); // Make sure I have the expected files - 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"); + 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"); // I must not see the files in subdirectories - 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"); + 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"); // I must not see the files not matching the prefix I gave - 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"); + 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"); foreach ($listing as $fileName => $info) { - 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"); + 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"); } return true; @@ -101,37 +101,37 @@ class ListFiles extends AbstractTest { $listing = $s3->getBucket($options['bucket'], 'listtest_', null, 1); - 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))); + 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))); $files = array_keys($listing); $continued = $s3->getBucket($options['bucket'], 'listtest_', array_shift($files)); - 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))); + 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))); $listing = array_merge($listing, $continued); // Make sure I have the expected files - 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"); + 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"); // I must not see the files in subdirectories - 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"); + 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"); // I must not see the files not matching the prefix I gave - 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"); + 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"); foreach ($listing as $fileName => $info) { - 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"); + 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"); } return true; @@ -141,30 +141,30 @@ class ListFiles extends AbstractTest { $listing = $s3->getBucket($options['bucket'], 'list_deeper/test_'); - static::assert(is_array($listing), "The files listing must be an array"); - static::assert(count($listing) == 3, "I am expecting to see 3 files"); + self::assert(is_array($listing), "The files listing must be an array"); + self::assert(count($listing) == 3, "I am expecting to see 3 files"); // Make sure I have the expected files - 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"); + 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"); // I must not see the files with different prefix - 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"); + 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"); // I must not see the files in subdirectories - 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"); + 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"); foreach ($listing as $fileName => $info) { - 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"); + 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"); } return true; @@ -174,41 +174,41 @@ class ListFiles extends AbstractTest { $listing = $s3->getBucket($options['bucket'], 'list_deeper/test_', null, 1); - 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))); + 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))); $files = array_keys($listing); $continued = $s3->getBucket($options['bucket'], 'list_deeper/test_', array_shift($files)); - 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))); + 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))); $listing = array_merge($listing, $continued); - static::assert(is_array($listing), "The files listing must be an array"); - static::assert(count($listing) == 3, "I am expecting to see 3 files"); + self::assert(is_array($listing), "The files listing must be an array"); + self::assert(count($listing) == 3, "I am expecting to see 3 files"); // Make sure I have the expected files - 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"); + 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"); // I must not see the files with different prefix - 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"); + 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"); // I must not see the files in subdirectories - 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"); + 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"); foreach ($listing as $fileName => $info) { - 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"); + 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"); } return true; @@ -224,42 +224,42 @@ class ListFiles extends AbstractTest */ $listing = $s3->getBucket($options['bucket'], 'list_deeper/listtest_', null, 1); - 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))); + 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))); $files = array_keys($listing); $continued = $s3->getBucket($options['bucket'], 'list_deeper/listtest_', array_shift($files)); - 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))); + 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))); $listing = array_merge($listing, $continued); - static::assert(is_array($listing), "The files listing must be an array"); - static::assert(count($listing) == 3, "I am expecting to see 3 files"); + self::assert(is_array($listing), "The files listing must be an array"); + self::assert(count($listing) == 3, "I am expecting to see 3 files"); // Make sure I have the expected files - 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"); + 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"); // I must not see the files with different prefix - 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"); + 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"); // I must not see the files in subdirectories - 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"); + 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"); foreach ($listing as $fileName => $info) { - 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"); + 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"); } return true; @@ -269,37 +269,37 @@ class ListFiles extends AbstractTest { $listing = $s3->getBucket($options['bucket'], 'list_deeper/listtest_', null, null, '/', true); - 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))); + 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))); // Make sure I have the expected files - 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"); + 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"); // I must not see the files in subdirectories - 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"); + 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"); // I must not see the files with different prefix - 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"); + 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"); foreach ($listing as $fileName => $info) { if (substr($fileName, -1) !== '/') { - 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"); + 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"); } else { - static::assert(isset($info['prefix']), "Folder entries must return a prefix"); + self::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 deleted file mode 100644 index 8146d4cd..00000000 --- a/s3_storage/vendor/akeeba/s3/minitest/Test/ListThousandsOfFiles.php +++ /dev/null @@ -1,111 +0,0 @@ -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 df097e96..e4c7c284 100644 --- a/s3_storage/vendor/akeeba/s3/minitest/Test/Multipart.php +++ b/s3_storage/vendor/akeeba/s3/minitest/Test/Multipart.php @@ -1,22 +1,16 @@ 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 82b2027f..52f49e58 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\S3\Connector; -use Akeeba\S3\Input; +use Akeeba\Engine\Postproc\Connector\S3v4\Connector; +use Akeeba\Engine\Postproc\Connector\S3v4\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 static::upload($s3, $options, AbstractTest::TEN_KB, 'root_10kb.dat'); + return self::upload($s3, $options, AbstractTest::TEN_KB, 'root_10kb.dat'); } public static function upload10KbRootGreek(Connector $s3, array $options): bool { - return static::upload($s3, $options, AbstractTest::TEN_KB, 'δοκιμή_10kb.dat'); + return self::upload($s3, $options, AbstractTest::TEN_KB, 'δοκιμή_10kb.dat'); } public static function upload10KbFolderGreek(Connector $s3, array $options): bool { - return static::upload($s3, $options, AbstractTest::TEN_KB, 'ο_φάκελός_μου/δοκιμή_10kb.dat'); + return self::upload($s3, $options, AbstractTest::TEN_KB, 'ο_φάκελός_μου/δοκιμή_10kb.dat'); } public static function upload600KbRoot(Connector $s3, array $options): bool { - return static::upload($s3, $options, AbstractTest::SIX_HUNDRED_KB, 'root_600kb.dat'); + return self::upload($s3, $options, AbstractTest::SIX_HUNDRED_KB, 'root_600kb.dat'); } public static function upload10KbFolder(Connector $s3, array $options): bool { - return static::upload($s3, $options, AbstractTest::TEN_KB, 'my_folder/10kb.dat'); + return self::upload($s3, $options, AbstractTest::TEN_KB, 'my_folder/10kb.dat'); } public static function upload600KbFolder(Connector $s3, array $options): bool { - return static::upload($s3, $options, AbstractTest::SIX_HUNDRED_KB, 'my_folder/600kb.dat'); + return self::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 = static::createFile($size); + $sourceFile = self::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 (static::$downloadAfter) + if (self::$downloadAfter) { // Donwload the data. Throws exception if it fails. - $downloadedFile = tempnam(static::getTempFolder(), 'as3'); + $downloadedFile = tempnam(self::getTempFolder(), 'as3'); $s3->getObject($bucket, $uri, $downloadedFile); // Compare the file contents. - $result = static::areFilesEqual($sourceFile, $downloadedFile); + $result = self::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 (static::$deleteRemote) + if (self::$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 bdd3193b..7ef9cf5b 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\S3\Connector; +use Akeeba\Engine\Postproc\Connector\S3v4\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 { - static::$deleteRemote = false; + self::$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 e1aacafd..1b6cdca7 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\S3\Connector; +use Akeeba\Engine\Postproc\Connector\S3v4\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 { - static::$deleteRemote = false; - static::$downloadAfter = false; + self::$deleteRemote = false; + self::$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 d648d106..5cb942e7 100644 --- a/s3_storage/vendor/akeeba/s3/minitest/Test/SmallInlineFiles.php +++ b/s3_storage/vendor/akeeba/s3/minitest/Test/SmallInlineFiles.php @@ -3,14 +3,15 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\S3\Connector; -use Akeeba\S3\Input; + +use Akeeba\Engine\Postproc\Connector\S3v4\Connector; +use Akeeba\Engine\Postproc\Connector\S3v4\Input; /** * Upload, download and delete small files (under 1MB) using a string source @@ -26,7 +27,7 @@ class SmallInlineFiles extends SmallFiles $uri = substr($uri, 0, $dotPos) . '.' . md5(microtime(false)) . substr($uri, $dotPos); // Create some random data to upload - $sourceData = static::getRandomData($size); + $sourceData = self::getRandomData($size); // Upload the data. Throws exception if it fails. $bucket = $options['bucket']; @@ -38,15 +39,15 @@ class SmallInlineFiles extends SmallFiles $result = true; // Should I download the file and compare its contents with my random data? - if (static::$downloadAfter) + if (self::$downloadAfter) { $downloadedData = $s3->getObject($bucket, $uri); - $result = static::areStringsEqual($sourceData, $downloadedData); + $result = self::areStringsEqual($sourceData, $downloadedData); } // Should I delete the remotely stored file? - if (static::$deleteRemote) + if (self::$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 d7e0d73e..8ba99355 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\S3\Connector; +use Akeeba\Engine\Postproc\Connector\S3v4\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 { - static:: $deleteRemote = false; + self:: $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 890ecccd..e41bf5ec 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\S3\Connector; +use Akeeba\Engine\Postproc\Connector\S3v4\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 { - static::$deleteRemote = false; - static::$downloadAfter = false; + self::$deleteRemote = false; + self::$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 deleted file mode 100644 index 5ab54893..00000000 --- a/s3_storage/vendor/akeeba/s3/minitest/Test/SmallInlineXMLFiles.php +++ /dev/null @@ -1,131 +0,0 @@ -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 42adce42..9e57ba7a 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\S3\Acl; -use Akeeba\S3\Connector; -use Akeeba\S3\Input; -use Akeeba\S3\StorageClass; +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; class StorageClasses extends AbstractTest { @@ -23,12 +23,12 @@ class StorageClasses extends AbstractTest public static function uploadRRS(Connector $s3, array $options): bool { - return static::upload($s3, $options, static::TEN_KB, 'rrs_test_10kb.dat', StorageClass::REDUCED_REDUNDANCY); + return self::upload($s3, $options, self::TEN_KB, 'rrs_test_10kb.dat', StorageClass::REDUCED_REDUNDANCY); } public static function uploadIntelligentTiering(Connector $s3, array $options): bool { - return static::upload($s3, $options, static::TEN_KB, 'rrs_test_10kb.dat', StorageClass::INTELLIGENT_TIERING); + return self::upload($s3, $options, self::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 = static::getRandomData($size); + $sourceData = self::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 (static::$downloadAfter) + if (self::$downloadAfter) { $downloadedData = $s3->getObject($bucket, $uri); - $result = static::areStringsEqual($sourceData, $downloadedData); + $result = self::areStringsEqual($sourceData, $downloadedData); } // Should I delete the remotely stored file? - if (static::$deleteRemote) + if (self::$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 b9124065..063934fe 100644 --- a/s3_storage/vendor/akeeba/s3/minitest/config.dist.php +++ b/s3_storage/vendor/akeeba/s3/minitest/config.dist.php @@ -3,12 +3,10 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 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 @@ -25,8 +23,6 @@ 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 @@ -37,9 +33,7 @@ $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 21e9dce1..e9490321 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -use Akeeba\S3\Configuration; -use Akeeba\S3\Connector; -use Akeeba\S3\Input; +use Akeeba\Engine\Postproc\Connector\S3v4\Configuration; +use Akeeba\Engine\Postproc\Connector\S3v4\Connector; +use Akeeba\Engine\Postproc\Connector\S3v4\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' => defined('DEFAULT_ENDPOINT') ? constant('DEFAULT_ENDPOINT') : null, + 'endpoint' => null, ], $setup['configuration']); // Extract the test classes/methods to run @@ -185,21 +185,15 @@ foreach ($testConfigurations as $description => $setup) // Create the S3 configuration object $s3Configuration = new Configuration($configOptions['access'], $configOptions['secret'], $configOptions['signature'], $configOptions['region']); - $s3Configuration->setRegion($configOptions['region']); - $s3Configuration->setSignatureMethod($configOptions['signature']); + $s3Configuration->setUseDualstackUrl($configOptions['dualstack']); + $s3Configuration->setUseLegacyPathStyle($configOptions['path_access']); + $s3Configuration->setSSL($configOptions['ssl']); 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 3a58f5e8..36952cba 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3; +namespace Akeeba\Engine\Postproc\Connector\S3v4; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or die(); /** * Shortcuts to often used access control privileges */ class Acl { - public const ACL_PRIVATE = 'private'; + const ACL_PRIVATE = 'private'; - public const ACL_PUBLIC_READ = 'public-read'; + const ACL_PUBLIC_READ = 'public-read'; - public const ACL_PUBLIC_READ_WRITE = 'public-read-write'; + const ACL_PUBLIC_READ_WRITE = 'public-read-write'; - public const ACL_AUTHENTICATED_READ = 'authenticated-read'; + const ACL_AUTHENTICATED_READ = 'authenticated-read'; - public const ACL_BUCKET_OWNER_READ = 'bucket-owner-read'; + const ACL_BUCKET_OWNER_READ = 'bucket-owner-read'; - public const ACL_BUCKET_OWNER_FULL_CONTROL = 'bucket-owner-full-control'; + 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 ca5fa19e..13540dd0 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3; +namespace Akeeba\Engine\Postproc\Connector\S3v4; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or die(); /** * Holds the Amazon S3 confiugration credentials @@ -199,8 +199,6 @@ class Configuration throw new Exception\InvalidSignatureMethod; } - $this->signatureMethod = $signatureMethod; - // If you switch to v2 signatures we unset the region. if ($signatureMethod == 'v2') { @@ -216,7 +214,13 @@ 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 54fdc3cc..4bf52caa 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3; +namespace Akeeba\Engine\Postproc\Connector\S3v4; // Protection against direct access -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; +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; -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or die(); class Connector { @@ -81,10 +81,7 @@ class Connector if (($input->getSize() <= 0) || (($input->getInputType() == Input::INPUT_DATA) && (!strlen($input->getDataReference())))) { - if (substr($uri, -1) !== '/') - { - throw new CannotPutFile('Missing input parameters', 0); - } + throw new CannotPutFile('Missing input parameters', 0); } // We need to post with Content-Length and Content-Type, MD5 is optional @@ -172,7 +169,7 @@ class Connector if (!is_resource($saveTo) && is_string($saveTo)) { - $fp = @fopen($saveTo, 'w'); + $fp = @fopen($saveTo, 'wb'); if ($fp === false) { @@ -196,53 +193,6 @@ 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))) @@ -256,20 +206,19 @@ class Connector 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) - ) + 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() ); } - return $response->getHeaders(); - } + if (!is_resource($fp)) + { + return $response->body; + } + return null; + } /** * Delete an object @@ -295,13 +244,9 @@ class Connector if ($response->error->isError()) { throw new CannotDeleteFile( - sprintf( - __METHOD__ . "({%s}, {%s}): [%s] %s", - $bucket, - $uri, - $response->error->getCode(), - $response->error->getMessage() - ) + sprintf(__METHOD__ . "({$bucket}, {$uri}): [%s] %s", + $response->error->getCode(), $response->error->getMessage()), + $response->error->getCode() ); } } @@ -413,7 +358,8 @@ class Connector if ($response->error->isError()) { throw new CannotGetBucket( - sprintf(__METHOD__ . "(): [%s] %s", $response->error->getCode(), $response->error->getMessage()) + sprintf(__METHOD__ . "(): [%s] %s", $response->error->getCode(), $response->error->getMessage()), + $response->error->getCode() ); } @@ -457,47 +403,168 @@ class Connector */ public function getBucket(string $bucket, ?string $prefix = null, ?string $marker = null, ?int $maxKeys = null, string $delimiter = '/', bool $returnCommonPrefixes = false): array { - $internalResult = $this->internalGetBucket($bucket, $prefix, $marker, $maxKeys, $delimiter, $returnCommonPrefixes); + $request = new Request('GET', $bucket, '', $this->configuration); - /** - * @var array $objects - * @var ?string $nextMarker - */ - extract($internalResult); - unset($internalResult); + if (!empty($prefix)) + { + $request->setParameter('prefix', $prefix); + } - // 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)) + 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) { do { - $internalResult = $this->internalGetBucket($bucket, $prefix, $nextMarker, $maxKeys, $delimiter, $returnCommonPrefixes); + $request = new Request('GET', $bucket, '', $this->configuration); - $nextMarker = $internalResult['nextMarker']; - $objects = array_merge($objects, $internalResult['objects']); + if (!empty($prefix)) + { + $request->setParameter('prefix', $prefix); + } - unset($internalResult); + $request->setParameter('marker', $nextMarker); - // If the last call did not return a nextMarker I am done iterating. - if ($nextMarker === null) + if (!empty($delimiter)) + { + $request->setParameter('delimiter', $delimiter); + } + + try + { + $response = $request->getResponse(); + } + catch (\Exception $e) { break; } - // If we have maxKeys AND the number of objects is at least this many I am done iterating. - if ($maxKeys !== null && count($objects) >= $maxKeys) + if ($response->hasBody() && isset($response->body->Contents)) { - break; + 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; + } } - } while (true); + + 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); } - if ($maxKeys !== null) + if (!is_null($maxKeys)) { - return array_splice($objects, 0, $maxKeys); + $results = array_splice($results, 0, $maxKeys); } - return $objects; + return $results; } /** @@ -527,7 +594,8 @@ class Connector if ($response->error->isError()) { throw new CannotListBuckets( - sprintf(__METHOD__ . "(): [%s] %s", $response->error->getCode(), $response->error->getMessage()) + sprintf(__METHOD__ . "(): [%s] %s", $response->error->getCode(), $response->error->getMessage()), + $response->error->getCode() ); } @@ -623,12 +691,7 @@ 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)) ); } @@ -895,90 +958,4 @@ 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 05e3fa50..b98c566e 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3\Exception; +namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or 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 e87c0994..6047a4b4 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3\Exception; +namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or 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 5a9d8e82..b9719353 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3\Exception; +namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or 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 7a365fba..de29bcbd 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3\Exception; +namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or 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 78aa5cd2..6a206ffe 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3\Exception; +namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or 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 24f8a724..ecec4e70 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3\Exception; +namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or 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 a7a2a478..9f53c4f5 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3\Exception; +namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or 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 2699b5e7..60d64a6c 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3\Exception; +namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or 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 3db444b4..dd561686 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3\Exception; +namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or 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 57b628fd..6e1e1690 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3\Exception; +namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or 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 3c58c035..b35e56d0 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3\Exception; +namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or 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 15c546cd..084b3cd0 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3\Exception; +namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or 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 e21c1f67..fe6abc08 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3\Exception; +namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or 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 af58e5d9..2348c289 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3\Exception; +namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or 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 bd4fdedc..6145ed1c 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3\Exception; +namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or 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 3f521532..c397fee8 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3\Exception; +namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or die(); use LogicException; diff --git a/s3_storage/vendor/akeeba/s3/src/Input.php b/s3_storage/vendor/akeeba/s3/src/Input.php index 5dd5743d..4420bdba 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3; +namespace Akeeba\Engine\Postproc\Connector\S3v4; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or die(); /** * Defines an input source for PUT/POST requests to Amazon S3 @@ -20,17 +20,17 @@ class Input /** * Input type: resource */ - public const INPUT_RESOURCE = 1; + const INPUT_RESOURCE = 1; /** * Input type: file */ - public const INPUT_FILE = 2; + const INPUT_FILE = 2; /** * Input type: raw data */ - public const INPUT_DATA = 3; + const INPUT_DATA = 3; /** * File pointer, in case we have a resource @@ -177,13 +177,7 @@ class Input { if (is_resource($this->fp)) { - try - { - @fclose($this->fp); - } - catch (\Throwable $e) - { - } + @fclose($this->fp); } } @@ -264,16 +258,10 @@ class Input if (is_resource($this->fp)) { - try - { - @fclose($this->fp); - } - catch (\Throwable $e) - { - } + @fclose($this->fp); } - $this->fp = @fopen($file, 'r'); + $this->fp = @fopen($file, 'rb'); if ($this->fp === false) { @@ -307,13 +295,7 @@ class Input if (is_resource($this->fp)) { - try - { - @fclose($this->fp); - } - catch (\Throwable $e) - { - } + @fclose($this->fp); } $this->file = null; @@ -347,13 +329,7 @@ class Input if (is_resource($this->fp)) { - try - { - @fclose($this->fp); - } - catch (\Throwable $e) - { - } + @fclose($this->fp); } $this->file = null; @@ -474,7 +450,7 @@ class Input */ public function setSha256(?string $sha256): void { - $this->sha256 = is_null($sha256) ? null : strtolower($sha256); + $this->sha256 = strtolower($sha256); } /** @@ -556,7 +532,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: @@ -659,7 +635,7 @@ class Input $ext = strtolower(pathInfo($file, PATHINFO_EXTENSION)); - return $exts[$ext] ?? 'application/octet-stream'; + return isset($exts[$ext]) ? $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 4237b862..172113fc 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3; +namespace Akeeba\Engine\Postproc\Connector\S3v4; -use Akeeba\S3\Response\Error; +use Akeeba\Engine\Postproc\Connector\S3v4\Response\Error; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or die(); class Request @@ -142,12 +142,6 @@ 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(); @@ -373,7 +367,7 @@ class Request * * @return Response */ - public function getResponse(bool $rawResponse = false): Response + public function getResponse(): Response { $this->processParametersIntoResource(); @@ -423,10 +417,8 @@ 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; @@ -437,27 +429,6 @@ 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); @@ -511,7 +482,7 @@ class Request $data = $this->input->getDataReference(); - if (strlen($data ?? '')) + if (strlen($data)) { curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } @@ -567,18 +538,12 @@ class Request @curl_close($curl); // Set the body data - $this->response->finaliseBody($rawResponse); + $this->response->finaliseBody(); // Clean up file resources if (!is_null($this->fp) && is_resource($this->fp)) { - try - { - @fclose($this->fp); - } - catch (\Throwable $e) - { - } + fclose($this->fp); } return $this->response; @@ -595,7 +560,7 @@ class Request */ protected function __responseWriteCallback($curl, string $data): int { - if (in_array($this->response->code, [0, 200, 206]) && !is_null($this->fp) && is_resource($this->fp)) + if (in_array($this->response->code, [200, 206]) && !is_null($this->fp) && is_resource($this->fp)) { return fwrite($this->fp, $data); } @@ -608,7 +573,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 @@ -627,15 +592,7 @@ class Request return $strlen; } - // Ignore malformed headers without a value. - if (strpos($data, ':') === false) - { - return $strlen; - } - - [$header, $value] = explode(':', trim($data), 2); - $header = trim($header ?? ''); - $value = trim($value ?? ''); + [$header, $value] = explode(': ', trim($data), 2); switch (strtolower($header)) { @@ -652,12 +609,10 @@ class Request break; case 'etag': - $this->response->setHeader('hash', trim($value, '"')); + $this->response->setHeader('hash', $value[0] == '"' ? substr($value, 1, -1) : $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); @@ -697,12 +652,13 @@ 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; @@ -764,8 +720,6 @@ 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 * @@ -774,27 +728,25 @@ class Request * * v4 signing does NOT support non-Amazon endpoints. */ - if (in_array($endpoint, ['s3.amazonaws.com', 'amazonaws.com.cn'])) + + // Most endpoints: s3-REGION.amazonaws.com + $regionalEndpoint = $region . '.amazonaws.com'; + + // Exception: China + if (substr($region, 0, 3) == 'cn-') { - // Most endpoints: s3-REGION.amazonaws.com - $regionalEndpoint = $region . '.amazonaws.com'; + // Chinese endpoint, e.g.: s3.cn-north-1.amazonaws.com.cn + $regionalEndpoint = $regionalEndpoint . '.cn'; + } - // 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; - } + // 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 01810941..a8078b29 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3; +namespace Akeeba\Engine\Postproc\Connector\S3v4; -use Akeeba\S3\Exception\PropertyNotFound; -use Akeeba\S3\Response\Error; +use Akeeba\Engine\Postproc\Connector\S3v4\Exception\PropertyNotFound; +use Akeeba\Engine\Postproc\Connector\S3v4\Response\Error; use SimpleXMLElement; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or die(); /** * Amazon S3 API response object @@ -124,7 +124,7 @@ class Response * * @param string|SimpleXMLElement|null $body */ - public function setBody($body, bool $rawResponse = false): void + public function setBody($body): void { $this->body = null; @@ -135,7 +135,7 @@ class Response $this->body = $body; - $this->finaliseBody($rawResponse); + $this->finaliseBody(); } public function resetBody(): void @@ -153,7 +153,7 @@ class Response $this->body .= $data; } - public function finaliseBody(bool $rawResponse = false): void + public function finaliseBody(): void { if (!$this->hasBody()) { @@ -165,14 +165,8 @@ class Response $this->headers['type'] = 'text/plain'; } - if ( - !$rawResponse - && 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); @@ -338,8 +332,8 @@ class Response ) { $this->error = new Error( - 500, - (string) $this->body->Code . ':' . (string) $this->body->Message + $this->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 69710bdf..ca40985d 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3\Response; +namespace Akeeba\Engine\Postproc\Connector\S3v4\Response; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or 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 93d8f0f6..c841ebe1 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3; +namespace Akeeba\Engine\Postproc\Connector\S3v4; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or 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 = __NAMESPACE__ . '\\Signature\\' . ucfirst($method); + $className = '\\Akeeba\\Engine\\Postproc\\Connector\\S3v4\\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 6864846f..86d9be75 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3\Signature; +namespace Akeeba\Engine\Postproc\Connector\S3v4\Signature; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or die(); -use Akeeba\S3\Signature; +use Akeeba\Engine\Postproc\Connector\S3v4\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 (count($amz) > 0) + if (sizeof($amz) > 0) { sort($amz); $amzString = "\n" . implode("\n", $amz); @@ -150,8 +150,8 @@ class V2 extends Signature } $stringToSign = $verb . "\n" . - ($headers['Content-MD5'] ?? '') . "\n" . - ($headers['Content-Type'] ?? '') . "\n" . + (isset($headers['Content-MD5']) ? $headers['Content-MD5'] : '') . "\n" . + (isset($headers['Content-Type']) ? $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 b39f81f4..e2bb908e 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3\Signature; +namespace Akeeba\Engine\Postproc\Connector\S3v4\Signature; // Protection against direct access -defined('AKEEBAENGINE') || die(); +defined('AKEEBAENGINE') or die(); -use Akeeba\S3\Signature; +use Akeeba\Engine\Postproc\Connector\S3v4\Signature; use DateTime; /** @@ -77,20 +77,14 @@ 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'; @@ -99,11 +93,6 @@ 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; @@ -140,8 +129,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 @@ -219,14 +208,12 @@ 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; } @@ -287,11 +274,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); @@ -303,40 +290,17 @@ 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" . - $dateToSignFor . "\n" . - $credentialScope . "\n" . - $hashedCanonicalRequest; + $headers['Date'] . "\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 ========== @@ -349,9 +313,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. @@ -402,14 +366,7 @@ class V4 extends Signature */ private function getPresignedHostnameForRegion(string $region): string { - $config = $this->request->getConfiguration(); - $endpoint = $config->getEndpoint(); - - if (empty($endpoint)) - { - $endpoint = 's3.' . $region . '.amazonaws.com'; - } - + $endpoint = 's3.' . $region . '.amazonaws.com'; $dualstackEnabled = $this->request->getConfiguration()->getDualstackUrl(); // If dual-stack URLs are enabled then prepend the endpoint @@ -425,83 +382,4 @@ 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 0c213af2..53ea310f 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-2023 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\S3; +namespace Akeeba\Engine\Postproc\Connector\S3v4; /** * Amazon S3 Storage Classes @@ -28,39 +28,39 @@ class StorageClass /** * Amazon S3 Standard (S3 Standard) */ - public const STANDARD = 'STANDARD'; + const STANDARD = 'STANDARD'; /** * Reduced redundancy storage * * Not recommended anymore. Use INTELLIGENT_TIERING instead. */ - public const REDUCED_REDUNDANCY = 'REDUCED_REDUNDANCY'; + const REDUCED_REDUNDANCY = 'REDUCED_REDUNDANCY'; /** * Amazon S3 Intelligent-Tiering (S3 Intelligent-Tiering) */ - public const INTELLIGENT_TIERING = 'INTELLIGENT_TIERING'; + const INTELLIGENT_TIERING = 'INTELLIGENT_TIERING'; /** * Amazon S3 Standard-Infrequent Access (S3 Standard-IA) */ - public const STANDARD_IA = 'STANDARD_IA'; + const STANDARD_IA = 'STANDARD_IA'; /** * Amazon S3 One Zone-Infrequent Access (S3 One Zone-IA) */ - public const ONEZONE_IA = 'ONEZONE_IA'; + const ONEZONE_IA = 'ONEZONE_IA'; /** * Amazon S3 Glacier (S3 Glacier) */ - public const GLACIER = 'GLACIER'; + const GLACIER = 'GLACIER'; /** * Amazon S3 Glacier Deep Archive (S3 Glacier Deep Archive) */ - public const DEEP_ARCHIVE = 'DEEP_ARCHIVE'; + 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 deleted file mode 100644 index 4b408ac3..00000000 --- a/s3_storage/vendor/akeeba/s3/src/aliasing.php +++ /dev/null @@ -1,35 +0,0 @@ - $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', + 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Acl' => $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', ); diff --git a/s3_storage/vendor/composer/autoload_files.php b/s3_storage/vendor/composer/autoload_files.php deleted file mode 100644 index cc01550f..00000000 --- a/s3_storage/vendor/composer/autoload_files.php +++ /dev/null @@ -1,10 +0,0 @@ - $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 400320bf..b1215e7f 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\\S3\\' => array($vendorDir . '/akeeba/s3/src'), + 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\' => array($vendorDir . '/akeeba/s3/src'), ); diff --git a/s3_storage/vendor/composer/autoload_real.php b/s3_storage/vendor/composer/autoload_real.php index 9df2057b..a5d4ee9a 100644 --- a/s3_storage/vendor/composer/autoload_real.php +++ b/s3_storage/vendor/composer/autoload_real.php @@ -50,24 +50,6 @@ 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 929f8194..09179f94 100644 --- a/s3_storage/vendor/composer/autoload_static.php +++ b/s3_storage/vendor/composer/autoload_static.php @@ -6,52 +6,48 @@ namespace Composer\Autoload; class ComposerStaticInitS3StorageAddon { - public static $files = array ( - '714ccd4b330431237faf946f71c4c9a4' => __DIR__ . '/..' . '/akeeba/s3/src/aliasing.php', - ); - public static $prefixLengthsPsr4 = array ( 'A' => array ( - 'Akeeba\\S3\\' => 10, + 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\' => 38, ), ); public static $prefixDirsPsr4 = array ( - 'Akeeba\\S3\\' => + 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\' => array ( 0 => __DIR__ . '/..' . '/akeeba/s3/src', ), ); public static $classMap = array ( - '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', + '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', ); public static function getInitializer(ClassLoader $loader) diff --git a/s3_storage/vendor/composer/installed.json b/s3_storage/vendor/composer/installed.json index 70c17e11..f122e1ba 100644 --- a/s3_storage/vendor/composer/installed.json +++ b/s3_storage/vendor/composer/installed.json @@ -1,38 +1,35 @@ [ { "name": "akeeba/s3", - "version": "2.3.1", - "version_normalized": "2.3.1.0", + "version": "2.0.0", + "version_normalized": "2.0.0.0", "source": { "type": "git", "url": "https://github.com/akeeba/s3.git", - "reference": "7f5b3e929c93eb02ba24472560c0cbbef735aed9" + "reference": "01520dae1f736555e08efda0ddc1044701bd340a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/akeeba/s3/zipball/7f5b3e929c93eb02ba24472560c0cbbef735aed9", - "reference": "7f5b3e929c93eb02ba24472560c0cbbef735aed9", + "url": "https://api.github.com/repos/akeeba/s3/zipball/01520dae1f736555e08efda0ddc1044701bd340a", + "reference": "01520dae1f736555e08efda0ddc1044701bd340a", "shasum": "" }, "require": { "ext-curl": "*", "ext-simplexml": "*", - "php": ">=7.1.0 <8.4" + "php": ">=7.1.0 <8.1" }, - "time": "2023-09-26T11:40:10+00:00", + "time": "2020-11-30T14:03:55+00:00", "type": "library", "installation-source": "dist", "autoload": { - "files": [ - "src/aliasing.php" - ], "psr-4": { - "Akeeba\\S3\\": "src" + "Akeeba\\Engine\\Postproc\\Connector\\S3v4\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "GPL-3.0-or-later" + "GPL-3.0+" ], "authors": [ { diff --git a/saml/saml.php b/saml/saml.php index 56dd0f5d..050ac00f 100755 --- a/saml/saml.php +++ b/saml/saml.php @@ -6,6 +6,7 @@ * Author: Ryan */ +use Friendica\App; use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; use Friendica\Core\Logger; @@ -13,6 +14,7 @@ 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'); @@ -82,7 +84,7 @@ function saml_head(string &$body) function saml_footer(string &$body) { - $fragment = addslashes(BBCode::convertForUriId(User::getSystemUriId(), DI::config()->get('saml', 'settings_statement'))); + $fragment = addslashes(BBCode::convert(DI::config()->get('saml', 'settings_statement'))); $body .= << var target=$("#settings-nickname-desc"); @@ -161,7 +163,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']) { diff --git a/securemail/SecureTestEmail.php b/securemail/SecureTestEmail.php index c614104f..2832adba 100644 --- a/securemail/SecureTestEmail.php +++ b/securemail/SecureTestEmail.php @@ -38,7 +38,7 @@ class SecureTestEmail extends Email { $sitename = $config->get('config', 'sitename'); - $hostname = $baseUrl->getHost(); + $hostname = $baseUrl->getHostname(); if (strpos($hostname, ':')) { $hostname = substr($hostname, 0, strpos($hostname, ':')); } diff --git a/securemail/composer.json b/securemail/composer.json index 4c7cb54b..98a91a6c 100644 --- a/securemail/composer.json +++ b/securemail/composer.json @@ -1,26 +1,23 @@ { - "name": "friendica-addons/securemail", - "description": "Send notification mail encrypted with user-defined public GPG key.", - "type": "friendica-addon", - "authors": [ - { - "name": "Fabio Comuni", - "homepage": "https://kirgroup.com/profile/fabrixxm", - "role": "Developer" + "name": "friendica-addons/securemail", + "description": "Send notification mail encrypted with user-defined public GPG key.", + "type": "friendica-addon", + "authors": [ + { + "name": "Fabio Comuni", + "homepage": "https://kirgroup.com/profile/fabrixxm", + "role": "Developer" + } + ], + "require": { + "singpolyma/openpgp-php": "0.6.0" + }, + "license": "AGPL-3.0+", + "minimum-stability": "stable", + "config": { + "autoloader-suffix": "SecuremailAddon", + "platform": { + "php": "7.3" + } } - ], - "require": { - "singpolyma/openpgp-php": "0.6.0" - }, - "replace": { - "paragonie/random_compat": "9.99.99" - }, - "license": "AGPL-3.0+", - "minimum-stability": "stable", - "config": { - "autoloader-suffix": "SecuremailAddon", - "platform": { - "php": "7.3" - } - } } diff --git a/securemail/composer.lock b/securemail/composer.lock index 7934eebc..8bbbbaa4 100644 --- a/securemail/composer.lock +++ b/securemail/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e7230dc266b072700d7e108251b5ea8f", + "content-hash": "e0f467bdac029de5c8176dbb7e955f94", "packages": [ { "name": "paragonie/constant_time_encoding", @@ -66,20 +66,75 @@ "hex2bin", "rfc4648" ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/constant_time_encoding/issues", + "source": "https://github.com/paragonie/constant_time_encoding" + }, "time": "2022-06-14T06:56:20+00:00" }, { - "name": "phpseclib/phpseclib", - "version": "3.0.19", + "name": "paragonie/random_compat", + "version": "v9.99.100", "source": { "type": "git", - "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "cc181005cf548bfd8a4896383bb825d859259f95" + "url": "https://github.com/paragonie/random_compat.git", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/cc181005cf548bfd8a4896383bb825d859259f95", - "reference": "cc181005cf548bfd8a4896383bb825d859259f95", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a", + "shasum": "" + }, + "require": { + "php": ">= 7" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/random_compat/issues", + "source": "https://github.com/paragonie/random_compat" + }, + "time": "2020-10-15T08:29:30+00:00" + }, + { + "name": "phpseclib/phpseclib", + "version": "3.0.17", + "source": { + "type": "git", + "url": "https://github.com/phpseclib/phpseclib.git", + "reference": "dbc2307d5c69aeb22db136c52e91130d7f2ca761" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/dbc2307d5c69aeb22db136c52e91130d7f2ca761", + "reference": "dbc2307d5c69aeb22db136c52e91130d7f2ca761", "shasum": "" }, "require": { @@ -158,6 +213,10 @@ "x.509", "x509" ], + "support": { + "issues": "https://github.com/phpseclib/phpseclib/issues", + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.17" + }, "funding": [ { "url": "https://github.com/terrafrost", @@ -172,7 +231,7 @@ "type": "tidelift" } ], - "time": "2023-03-05T17:13:09+00:00" + "time": "2022-10-24T10:51:50+00:00" }, { "name": "singpolyma/openpgp-php", @@ -220,6 +279,10 @@ } ], "description": "Pure-PHP implementation of the OpenPGP Message Format (RFC 4880)", + "support": { + "issues": "https://github.com/singpolyma/openpgp-php/issues", + "source": "https://github.com/singpolyma/openpgp-php/tree/0.6.0" + }, "funding": [ { "url": "https://github.com/singpolyma", @@ -248,5 +311,5 @@ "platform-overrides": { "php": "7.3" }, - "plugin-api-version": "1.1.0" + "plugin-api-version": "2.0.0" } diff --git a/securemail/lang/fr/messages.po b/securemail/lang/fr/messages.po index 828d507b..bb15513d 100644 --- a/securemail/lang/fr/messages.po +++ b/securemail/lang/fr/messages.po @@ -5,7 +5,6 @@ # # Translators: # Hypolite Petovan , 2022 -# Florent C., 2023 # #, fuzzy msgid "" @@ -14,8 +13,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: Florent C., 2023\n" -"Language-Team: French (https://app.transifex.com/Friendica/teams/12172/fr/)\n" +"Last-Translator: Hypolite Petovan , 2022\n" +"Language-Team: French (https://www.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" @@ -48,8 +47,8 @@ msgstr "Enregistrer et envoyer un message de test" #: securemail.php:93 msgid "Test email sent" -msgstr "Courriel de test envoyé avec succès" +msgstr "Message 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 courriel de test" +msgstr "Une erreur est survenue pendant l'envoi du message de test" diff --git a/securemail/lang/fr/strings.php b/securemail/lang/fr/strings.php index 9d40a8e2..91b8f1f2 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'] = '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'; +$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'; diff --git a/securemail/lang/it/messages.po b/securemail/lang/it/messages.po index ae0156d0..208bbc92 100644 --- a/securemail/lang/it/messages.po +++ b/securemail/lang/it/messages.po @@ -3,52 +3,53 @@ # This file is distributed under the same license as the Friendica securemail addon package. # # -# Translators: -# fabrixxm , 2018 -# #, fuzzy msgid "" msgstr "" "Project-Id-Version: \n" "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" +"POT-Creation-Date: 2017-04-11 21:14+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: fabrixxm , 2018\n" -"Language-Team: Italian (https://app.transifex.com/Friendica/teams/12172/it/)\n" +"Language-Team: Italian (https://www.transifex.com/Friendica/teams/12172/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: securemail.php:50 -msgid "Enable Secure Mail" -msgstr "Abilita Secure Mail" - -#: securemail.php:51 -msgid "Public key" -msgstr "Chiave pubblica" - -#: securemail.php:51 -msgid "Your public PGP key, ascii armored format" -msgstr "La tua chiave pubblica PGP, in formato ascii armored" - -#: securemail.php:56 +#: securemail.php:53 msgid "\"Secure Mail\" Settings" msgstr "Impostazioni Secure Mail" -#: securemail.php:59 +#: securemail.php:54 msgid "Save Settings" msgstr "Salva Impostazioni" -#: securemail.php:60 +#: securemail.php:55 securemail.php:76 msgid "Save and send test" msgstr "Salva e invia mail di prova" -#: securemail.php:93 +#: securemail.php:56 +msgid "Enable Secure Mail" +msgstr "Abilita Secure Mail" + +#: securemail.php:57 +msgid "Public key" +msgstr "Chiave pubblica" + +#: securemail.php:57 +msgid "Your public PGP key, ascii armored format" +msgstr "La tua chiave pubblica PGP, in formato ascii armored" + +#: securemail.php:74 +msgid "Secure Mail Settings saved." +msgstr "Impostazioni Secure Mail salvate." + +#: securemail.php:111 msgid "Test email sent" msgstr "Email di prova invata" -#: securemail.php:95 +#: securemail.php:113 msgid "There was an error sending the test email" msgstr "Si è verificato un errore durante l'invio dell'email di prova" diff --git a/securemail/lang/it/strings.php b/securemail/lang/it/strings.php index 899c8f81..04b3c7fe 100644 --- a/securemail/lang/it/strings.php +++ b/securemail/lang/it/strings.php @@ -3,13 +3,14 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} -$a->strings['Enable Secure Mail'] = 'Abilita Secure Mail'; -$a->strings['Public key'] = 'Chiave pubblica'; -$a->strings['Your public PGP key, ascii armored format'] = 'La tua chiave pubblica PGP, in formato ascii armored'; $a->strings['"Secure Mail" Settings'] = 'Impostazioni Secure Mail'; $a->strings['Save Settings'] = 'Salva Impostazioni'; $a->strings['Save and send test'] = 'Salva e invia mail di prova'; +$a->strings['Enable Secure Mail'] = 'Abilita Secure Mail'; +$a->strings['Public key'] = 'Chiave pubblica'; +$a->strings['Your public PGP key, ascii armored format'] = 'La tua chiave pubblica PGP, in formato ascii armored'; +$a->strings['Secure Mail Settings saved.'] = 'Impostazioni Secure Mail salvate.'; $a->strings['Test email sent'] = 'Email di prova invata'; $a->strings['There was an error sending the test email'] = 'Si è verificato un errore durante l\'invio dell\'email di prova'; diff --git a/securemail/vendor/composer/ClassLoader.php b/securemail/vendor/composer/ClassLoader.php index 03b9bb9c..1a58957d 100644 --- a/securemail/vendor/composer/ClassLoader.php +++ b/securemail/vendor/composer/ClassLoader.php @@ -37,8 +37,8 @@ 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 { diff --git a/securemail/vendor/composer/InstalledVersions.php b/securemail/vendor/composer/InstalledVersions.php new file mode 100644 index 00000000..6e4c3a77 --- /dev/null +++ b/securemail/vendor/composer/InstalledVersions.php @@ -0,0 +1,245 @@ + + array ( + 'pretty_version' => '1.0.0+no-version-set', + 'version' => '1.0.0.0', + 'aliases' => + array ( + ), + 'reference' => NULL, + 'name' => 'friendica-addons/securemail', + ), + 'versions' => + array ( + 'friendica-addons/securemail' => + array ( + 'pretty_version' => '1.0.0+no-version-set', + 'version' => '1.0.0.0', + 'aliases' => + array ( + ), + 'reference' => NULL, + ), + 'paragonie/constant_time_encoding' => + array ( + 'pretty_version' => 'v2.6.3', + 'version' => '2.6.3.0', + 'aliases' => + array ( + ), + 'reference' => '58c3f47f650c94ec05a151692652a868995d2938', + ), + 'paragonie/random_compat' => + array ( + 'pretty_version' => 'v9.99.100', + 'version' => '9.99.100.0', + 'aliases' => + array ( + ), + 'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a', + ), + 'phpseclib/phpseclib' => + array ( + 'pretty_version' => '3.0.17', + 'version' => '3.0.17.0', + 'aliases' => + array ( + ), + 'reference' => 'dbc2307d5c69aeb22db136c52e91130d7f2ca761', + ), + 'singpolyma/openpgp-php' => + array ( + 'pretty_version' => '0.6.0', + 'version' => '0.6.0.0', + 'aliases' => + array ( + ), + 'reference' => '1c3bdcd2d9c6113c2d6b768e208e7432a48d3a1e', + ), + ), +); + + + + + + + +public static function getInstalledPackages() +{ +return array_keys(self::$installed['versions']); +} + + + + + + + + + +public static function isInstalled($packageName) +{ +return isset(self::$installed['versions'][$packageName]); +} + + + + + + + + + + + + + + +public static function satisfies(VersionParser $parser, $packageName, $constraint) +{ +$constraint = $parser->parseConstraints($constraint); +$provided = $parser->parseConstraints(self::getVersionRanges($packageName)); + +return $provided->matches($constraint); +} + + + + + + + + + + +public static function getVersionRanges($packageName) +{ +if (!isset(self::$installed['versions'][$packageName])) { +throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); +} + +$ranges = array(); +if (isset(self::$installed['versions'][$packageName]['pretty_version'])) { +$ranges[] = self::$installed['versions'][$packageName]['pretty_version']; +} +if (array_key_exists('aliases', self::$installed['versions'][$packageName])) { +$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['aliases']); +} +if (array_key_exists('replaced', self::$installed['versions'][$packageName])) { +$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['replaced']); +} +if (array_key_exists('provided', self::$installed['versions'][$packageName])) { +$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['provided']); +} + +return implode(' || ', $ranges); +} + + + + + +public static function getVersion($packageName) +{ +if (!isset(self::$installed['versions'][$packageName])) { +throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); +} + +if (!isset(self::$installed['versions'][$packageName]['version'])) { +return null; +} + +return self::$installed['versions'][$packageName]['version']; +} + + + + + +public static function getPrettyVersion($packageName) +{ +if (!isset(self::$installed['versions'][$packageName])) { +throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); +} + +if (!isset(self::$installed['versions'][$packageName]['pretty_version'])) { +return null; +} + +return self::$installed['versions'][$packageName]['pretty_version']; +} + + + + + +public static function getReference($packageName) +{ +if (!isset(self::$installed['versions'][$packageName])) { +throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); +} + +if (!isset(self::$installed['versions'][$packageName]['reference'])) { +return null; +} + +return self::$installed['versions'][$packageName]['reference']; +} + + + + + +public static function getRootPackage() +{ +return self::$installed['root']; +} + + + + + + + +public static function getRawData() +{ +return self::$installed; +} + + + + + + + + + + + + + + + + + + + +public static function reload($data) +{ +self::$installed = $data; +} +} diff --git a/securemail/vendor/composer/autoload_classmap.php b/securemail/vendor/composer/autoload_classmap.php index 77479334..f832f412 100644 --- a/securemail/vendor/composer/autoload_classmap.php +++ b/securemail/vendor/composer/autoload_classmap.php @@ -6,6 +6,7 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( + 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', 'MCryptWrapper' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp_mcrypt_wrapper.php', 'OpenPGP' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php', 'OpenPGP_AsymmetricSessionKeyPacket' => $vendorDir . '/singpolyma/openpgp-php/lib/openpgp.php', diff --git a/securemail/vendor/composer/autoload_psr4.php b/securemail/vendor/composer/autoload_psr4.php index c12a8d7f..b265c64a 100644 --- a/securemail/vendor/composer/autoload_psr4.php +++ b/securemail/vendor/composer/autoload_psr4.php @@ -6,6 +6,4 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( - 'phpseclib3\\' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'), - 'ParagonIE\\ConstantTime\\' => array($vendorDir . '/paragonie/constant_time_encoding/src'), ); diff --git a/securemail/vendor/composer/autoload_real.php b/securemail/vendor/composer/autoload_real.php index 00bd40ef..2db90803 100644 --- a/securemail/vendor/composer/autoload_real.php +++ b/securemail/vendor/composer/autoload_real.php @@ -22,13 +22,15 @@ class ComposerAutoloaderInitSecuremailAddon return self::$loader; } + require __DIR__ . '/platform_check.php'; + spl_autoload_register(array('ComposerAutoloaderInitSecuremailAddon', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); spl_autoload_unregister(array('ComposerAutoloaderInitSecuremailAddon', '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'; + require __DIR__ . '/autoload_static.php'; call_user_func(\Composer\Autoload\ComposerStaticInitSecuremailAddon::getInitializer($loader)); } else { diff --git a/securemail/vendor/composer/autoload_static.php b/securemail/vendor/composer/autoload_static.php index d7427cb6..734f6b14 100644 --- a/securemail/vendor/composer/autoload_static.php +++ b/securemail/vendor/composer/autoload_static.php @@ -11,28 +11,13 @@ class ComposerStaticInitSecuremailAddon ); public static $prefixLengthsPsr4 = array ( - 'p' => - array ( - 'phpseclib3\\' => 11, - ), - 'P' => - array ( - 'ParagonIE\\ConstantTime\\' => 23, - ), ); public static $prefixDirsPsr4 = array ( - 'phpseclib3\\' => - array ( - 0 => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib', - ), - 'ParagonIE\\ConstantTime\\' => - array ( - 0 => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src', - ), ); public static $classMap = array ( + 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 'MCryptWrapper' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp_mcrypt_wrapper.php', 'OpenPGP' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php', 'OpenPGP_AsymmetricSessionKeyPacket' => __DIR__ . '/..' . '/singpolyma/openpgp-php/lib/openpgp.php', diff --git a/securemail/vendor/composer/installed.json b/securemail/vendor/composer/installed.json index 25c1aae4..3df6272c 100644 --- a/securemail/vendor/composer/installed.json +++ b/securemail/vendor/composer/installed.json @@ -1,238 +1,311 @@ -[ - { - "name": "paragonie/constant_time_encoding", - "version": "v2.6.3", - "version_normalized": "2.6.3.0", - "source": { - "type": "git", - "url": "https://github.com/paragonie/constant_time_encoding.git", - "reference": "58c3f47f650c94ec05a151692652a868995d2938" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/58c3f47f650c94ec05a151692652a868995d2938", - "reference": "58c3f47f650c94ec05a151692652a868995d2938", - "shasum": "" - }, - "require": { - "php": "^7|^8" - }, - "require-dev": { - "phpunit/phpunit": "^6|^7|^8|^9", - "vimeo/psalm": "^1|^2|^3|^4" - }, - "time": "2022-06-14T06:56:20+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "ParagonIE\\ConstantTime\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com", - "role": "Maintainer" +{ + "packages": [ + { + "name": "paragonie/constant_time_encoding", + "version": "v2.6.3", + "version_normalized": "2.6.3.0", + "source": { + "type": "git", + "url": "https://github.com/paragonie/constant_time_encoding.git", + "reference": "58c3f47f650c94ec05a151692652a868995d2938" }, - { - "name": "Steve 'Sc00bz' Thomas", - "email": "steve@tobtu.com", - "homepage": "https://www.tobtu.com", - "role": "Original Developer" - } - ], - "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", - "keywords": [ - "base16", - "base32", - "base32_decode", - "base32_encode", - "base64", - "base64_decode", - "base64_encode", - "bin2hex", - "encoding", - "hex", - "hex2bin", - "rfc4648" - ] - }, - { - "name": "phpseclib/phpseclib", - "version": "3.0.19", - "version_normalized": "3.0.19.0", - "source": { - "type": "git", - "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "cc181005cf548bfd8a4896383bb825d859259f95" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/cc181005cf548bfd8a4896383bb825d859259f95", - "reference": "cc181005cf548bfd8a4896383bb825d859259f95", - "shasum": "" - }, - "require": { - "paragonie/constant_time_encoding": "^1|^2", - "paragonie/random_compat": "^1.4|^2.0|^9.99.99", - "php": ">=5.6.1" - }, - "require-dev": { - "phpunit/phpunit": "*" - }, - "suggest": { - "ext-dom": "Install the DOM extension to load XML formatted public keys.", - "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", - "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", - "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", - "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." - }, - "time": "2023-03-05T17:13:09+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "files": [ - "phpseclib/bootstrap.php" + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/58c3f47f650c94ec05a151692652a868995d2938", + "reference": "58c3f47f650c94ec05a151692652a868995d2938", + "shasum": "" + }, + "require": { + "php": "^7|^8" + }, + "require-dev": { + "phpunit/phpunit": "^6|^7|^8|^9", + "vimeo/psalm": "^1|^2|^3|^4" + }, + "time": "2022-06-14T06:56:20+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "ParagonIE\\ConstantTime\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" ], - "psr-4": { - "phpseclib3\\": "phpseclib/" - } + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com", + "role": "Maintainer" + }, + { + "name": "Steve 'Sc00bz' Thomas", + "email": "steve@tobtu.com", + "homepage": "https://www.tobtu.com", + "role": "Original Developer" + } + ], + "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", + "keywords": [ + "base16", + "base32", + "base32_decode", + "base32_encode", + "base64", + "base64_decode", + "base64_encode", + "bin2hex", + "encoding", + "hex", + "hex2bin", + "rfc4648" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/constant_time_encoding/issues", + "source": "https://github.com/paragonie/constant_time_encoding" + }, + "install-path": "../paragonie/constant_time_encoding" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jim Wigginton", - "email": "terrafrost@php.net", - "role": "Lead Developer" + { + "name": "paragonie/random_compat", + "version": "v9.99.100", + "version_normalized": "9.99.100.0", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a" }, - { - "name": "Patrick Monnerat", - "email": "pm@datasphere.ch", - "role": "Developer" + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a", + "shasum": "" }, - { - "name": "Andreas Fischer", - "email": "bantu@phpbb.com", - "role": "Developer" + "require": { + "php": ">= 7" }, - { - "name": "Hans-Jürgen Petrich", - "email": "petrich@tronic-media.com", - "role": "Developer" + "require-dev": { + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" }, - { - "name": "Graham Campbell", - "email": "graham@alt-three.com", - "role": "Developer" - } - ], - "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", - "homepage": "http://phpseclib.sourceforge.net", - "keywords": [ - "BigInteger", - "aes", - "asn.1", - "asn1", - "blowfish", - "crypto", - "cryptography", - "encryption", - "rsa", - "security", - "sftp", - "signature", - "signing", - "ssh", - "twofish", - "x.509", - "x509" - ], - "funding": [ - { - "url": "https://github.com/terrafrost", - "type": "github" + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." }, - { - "url": "https://www.patreon.com/phpseclib", - "type": "patreon" + "time": "2020-10-15T08:29:30+00:00", + "type": "library", + "installation-source": "dist", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/random_compat/issues", + "source": "https://github.com/paragonie/random_compat" }, - { - "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib", - "type": "tidelift" - } - ] - }, - { - "name": "singpolyma/openpgp-php", - "version": "0.6.0", - "version_normalized": "0.6.0.0", - "source": { - "type": "git", - "url": "https://github.com/singpolyma/openpgp-php.git", - "reference": "1c3bdcd2d9c6113c2d6b768e208e7432a48d3a1e" + "install-path": "../paragonie/random_compat" }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/singpolyma/openpgp-php/zipball/1c3bdcd2d9c6113c2d6b768e208e7432a48d3a1e", - "reference": "1c3bdcd2d9c6113c2d6b768e208e7432a48d3a1e", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0 || ^8.0", - "phpseclib/phpseclib": "^3.0.14" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" - }, - "suggest": { - "ext-mcrypt": "required if you use encryption cast5", - "ext-openssl": "required if you use encryption cast5" - }, - "time": "2022-10-31T13:43:21+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "classmap": [ - "lib/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Unlicense" - ], - "authors": [ - { - "name": "Arto Bendiken", - "email": "arto.bendiken@gmail.com" + { + "name": "phpseclib/phpseclib", + "version": "3.0.17", + "version_normalized": "3.0.17.0", + "source": { + "type": "git", + "url": "https://github.com/phpseclib/phpseclib.git", + "reference": "dbc2307d5c69aeb22db136c52e91130d7f2ca761" }, - { - "name": "Stephen Paul Weber", - "email": "singpolyma@singpolyma.net" - } - ], - "description": "Pure-PHP implementation of the OpenPGP Message Format (RFC 4880)", - "funding": [ - { - "url": "https://github.com/singpolyma", - "type": "github" + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/dbc2307d5c69aeb22db136c52e91130d7f2ca761", + "reference": "dbc2307d5c69aeb22db136c52e91130d7f2ca761", + "shasum": "" }, - { - "url": "https://liberapay.com/singpolyma", - "type": "liberapay" + "require": { + "paragonie/constant_time_encoding": "^1|^2", + "paragonie/random_compat": "^1.4|^2.0|^9.99.99", + "php": ">=5.6.1" }, - { - "url": "https://www.patreon.com/singpolyma", - "type": "patreon" - } - ] - } -] + "require-dev": { + "phpunit/phpunit": "*" + }, + "suggest": { + "ext-dom": "Install the DOM extension to load XML formatted public keys.", + "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", + "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", + "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", + "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." + }, + "time": "2022-10-24T10:51:50+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "files": [ + "phpseclib/bootstrap.php" + ], + "psr-4": { + "phpseclib3\\": "phpseclib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jim Wigginton", + "email": "terrafrost@php.net", + "role": "Lead Developer" + }, + { + "name": "Patrick Monnerat", + "email": "pm@datasphere.ch", + "role": "Developer" + }, + { + "name": "Andreas Fischer", + "email": "bantu@phpbb.com", + "role": "Developer" + }, + { + "name": "Hans-Jürgen Petrich", + "email": "petrich@tronic-media.com", + "role": "Developer" + }, + { + "name": "Graham Campbell", + "email": "graham@alt-three.com", + "role": "Developer" + } + ], + "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", + "homepage": "http://phpseclib.sourceforge.net", + "keywords": [ + "BigInteger", + "aes", + "asn.1", + "asn1", + "blowfish", + "crypto", + "cryptography", + "encryption", + "rsa", + "security", + "sftp", + "signature", + "signing", + "ssh", + "twofish", + "x.509", + "x509" + ], + "support": { + "issues": "https://github.com/phpseclib/phpseclib/issues", + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.17" + }, + "funding": [ + { + "url": "https://github.com/terrafrost", + "type": "github" + }, + { + "url": "https://www.patreon.com/phpseclib", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib", + "type": "tidelift" + } + ], + "install-path": "../phpseclib/phpseclib" + }, + { + "name": "singpolyma/openpgp-php", + "version": "0.6.0", + "version_normalized": "0.6.0.0", + "source": { + "type": "git", + "url": "https://github.com/singpolyma/openpgp-php.git", + "reference": "1c3bdcd2d9c6113c2d6b768e208e7432a48d3a1e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/singpolyma/openpgp-php/zipball/1c3bdcd2d9c6113c2d6b768e208e7432a48d3a1e", + "reference": "1c3bdcd2d9c6113c2d6b768e208e7432a48d3a1e", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0 || ^8.0", + "phpseclib/phpseclib": "^3.0.14" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "suggest": { + "ext-mcrypt": "required if you use encryption cast5", + "ext-openssl": "required if you use encryption cast5" + }, + "time": "2022-10-31T13:43:21+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Unlicense" + ], + "authors": [ + { + "name": "Arto Bendiken", + "email": "arto.bendiken@gmail.com" + }, + { + "name": "Stephen Paul Weber", + "email": "singpolyma@singpolyma.net" + } + ], + "description": "Pure-PHP implementation of the OpenPGP Message Format (RFC 4880)", + "support": { + "issues": "https://github.com/singpolyma/openpgp-php/issues", + "source": "https://github.com/singpolyma/openpgp-php/tree/0.6.0" + }, + "funding": [ + { + "url": "https://github.com/singpolyma", + "type": "github" + }, + { + "url": "https://liberapay.com/singpolyma", + "type": "liberapay" + }, + { + "url": "https://www.patreon.com/singpolyma", + "type": "patreon" + } + ], + "install-path": "../singpolyma/openpgp-php" + } + ], + "dev": true, + "dev-package-names": [] +} diff --git a/securemail/vendor/composer/installed.php b/securemail/vendor/composer/installed.php new file mode 100644 index 00000000..c66b1835 --- /dev/null +++ b/securemail/vendor/composer/installed.php @@ -0,0 +1,60 @@ + + array ( + 'pretty_version' => '1.0.0+no-version-set', + 'version' => '1.0.0.0', + 'aliases' => + array ( + ), + 'reference' => NULL, + 'name' => 'friendica-addons/securemail', + ), + 'versions' => + array ( + 'friendica-addons/securemail' => + array ( + 'pretty_version' => '1.0.0+no-version-set', + 'version' => '1.0.0.0', + 'aliases' => + array ( + ), + 'reference' => NULL, + ), + 'paragonie/constant_time_encoding' => + array ( + 'pretty_version' => 'v2.6.3', + 'version' => '2.6.3.0', + 'aliases' => + array ( + ), + 'reference' => '58c3f47f650c94ec05a151692652a868995d2938', + ), + 'paragonie/random_compat' => + array ( + 'pretty_version' => 'v9.99.100', + 'version' => '9.99.100.0', + 'aliases' => + array ( + ), + 'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a', + ), + 'phpseclib/phpseclib' => + array ( + 'pretty_version' => '3.0.17', + 'version' => '3.0.17.0', + 'aliases' => + array ( + ), + 'reference' => 'dbc2307d5c69aeb22db136c52e91130d7f2ca761', + ), + 'singpolyma/openpgp-php' => + array ( + 'pretty_version' => '0.6.0', + 'version' => '0.6.0.0', + 'aliases' => + array ( + ), + 'reference' => '1c3bdcd2d9c6113c2d6b768e208e7432a48d3a1e', + ), + ), +); diff --git a/securemail/vendor/composer/platform_check.php b/securemail/vendor/composer/platform_check.php new file mode 100644 index 00000000..f79e574b --- /dev/null +++ b/securemail/vendor/composer/platform_check.php @@ -0,0 +1,26 @@ += 70000)) { + $issues[] = 'Your Composer dependencies require a PHP version ">= 7.0.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/securemail/vendor/paragonie/constant_time_encoding/LICENSE.txt b/securemail/vendor/paragonie/constant_time_encoding/LICENSE.txt deleted file mode 100644 index 91acaca6..00000000 --- a/securemail/vendor/paragonie/constant_time_encoding/LICENSE.txt +++ /dev/null @@ -1,48 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 - 2022 Paragon Initiative Enterprises - -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. - ------------------------------------------------------------------------------- -This library was based on the work of Steve "Sc00bz" Thomas. ------------------------------------------------------------------------------- - -The MIT License (MIT) - -Copyright (c) 2014 Steve Thomas - -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/securemail/vendor/paragonie/constant_time_encoding/README.md b/securemail/vendor/paragonie/constant_time_encoding/README.md deleted file mode 100644 index cedddd86..00000000 --- a/securemail/vendor/paragonie/constant_time_encoding/README.md +++ /dev/null @@ -1,84 +0,0 @@ -# Constant-Time Encoding - -[![Build Status](https://github.com/paragonie/constant_time_encoding/actions/workflows/ci.yml/badge.svg)](https://github.com/paragonie/constant_time_encoding/actions) -[![Latest Stable Version](https://poser.pugx.org/paragonie/constant_time_encoding/v/stable)](https://packagist.org/packages/paragonie/constant_time_encoding) -[![Latest Unstable Version](https://poser.pugx.org/paragonie/constant_time_encoding/v/unstable)](https://packagist.org/packages/paragonie/constant_time_encoding) -[![License](https://poser.pugx.org/paragonie/constant_time_encoding/license)](https://packagist.org/packages/paragonie/constant_time_encoding) -[![Downloads](https://img.shields.io/packagist/dt/paragonie/constant_time_encoding.svg)](https://packagist.org/packages/paragonie/constant_time_encoding) - -Based on the [constant-time base64 implementation made by Steve "Sc00bz" Thomas](https://github.com/Sc00bz/ConstTimeEncoding), -this library aims to offer character encoding functions that do not leak -information about what you are encoding/decoding via processor cache -misses. Further reading on [cache-timing attacks](http://blog.ircmaxell.com/2014/11/its-all-about-time.html). - -Our fork offers the following enchancements: - -* `mbstring.func_overload` resistance -* Unit tests -* Composer- and Packagist-ready -* Base16 encoding -* Base32 encoding -* Uses `pack()` and `unpack()` instead of `chr()` and `ord()` - -## PHP Version Requirements - -Version 2 of this library should work on **PHP 7** or newer. For PHP 5 -support, see [the v1.x branch](https://github.com/paragonie/constant_time_encoding/tree/v1.x). - -If you are adding this as a dependency to a project intended to work on both PHP 5 and PHP 7, please set the required version to `^1|^2` instead of just `^1` or `^2`. - -## How to Install - -```sh -composer require paragonie/constant_time_encoding -``` - -## How to Use - -```php -use ParagonIE\ConstantTime\Encoding; - -// possibly (if applicable): -// require 'vendor/autoload.php'; - -$data = random_bytes(32); -echo Encoding::base64Encode($data), "\n"; -echo Encoding::base32EncodeUpper($data), "\n"; -echo Encoding::base32Encode($data), "\n"; -echo Encoding::hexEncode($data), "\n"; -echo Encoding::hexEncodeUpper($data), "\n"; -``` - -Example output: - -``` -1VilPkeVqirlPifk5scbzcTTbMT2clp+Zkyv9VFFasE= -2VMKKPSHSWVCVZJ6E7SONRY3ZXCNG3GE6ZZFU7TGJSX7KUKFNLAQ==== -2vmkkpshswvcvzj6e7sonry3zxcng3ge6zzfu7tgjsx7kukfnlaq==== -d558a53e4795aa2ae53e27e4e6c71bcdc4d36cc4f6725a7e664caff551456ac1 -D558A53E4795AA2AE53E27E4E6C71BDCC4D36CC4F6725A7E664CAFF551456AC1 -``` - -If you only need a particular variant, you can just reference the -required class like so: - -```php -use ParagonIE\ConstantTime\Base64; -use ParagonIE\ConstantTime\Base32; - -$data = random_bytes(32); -echo Base64::encode($data), "\n"; -echo Base32::encode($data), "\n"; -``` - -Example output: - -``` -1VilPkeVqirlPifk5scbzcTTbMT2clp+Zkyv9VFFasE= -2vmkkpshswvcvzj6e7sonry3zxcng3ge6zzfu7tgjsx7kukfnlaq==== -``` - -## Support Contracts - -If your company uses this library in their products or services, you may be -interested in [purchasing a support contract from Paragon Initiative Enterprises](https://paragonie.com/enterprise). diff --git a/securemail/vendor/paragonie/constant_time_encoding/composer.json b/securemail/vendor/paragonie/constant_time_encoding/composer.json deleted file mode 100644 index 2fe9717a..00000000 --- a/securemail/vendor/paragonie/constant_time_encoding/composer.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "name": "paragonie/constant_time_encoding", - "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", - "keywords": [ - "base64", - "encoding", - "rfc4648", - "base32", - "base16", - "hex", - "bin2hex", - "hex2bin", - "base64_encode", - "base64_decode", - "base32_encode", - "base32_decode" - ], - "license": "MIT", - "type": "library", - "authors": [ - { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com", - "role": "Maintainer" - }, - { - "name": "Steve 'Sc00bz' Thomas", - "email": "steve@tobtu.com", - "homepage": "https://www.tobtu.com", - "role": "Original Developer" - } - ], - "support": { - "issues": "https://github.com/paragonie/constant_time_encoding/issues", - "email": "info@paragonie.com", - "source": "https://github.com/paragonie/constant_time_encoding" - }, - "require": { - "php": "^7|^8" - }, - "require-dev": { - "phpunit/phpunit": "^6|^7|^8|^9", - "vimeo/psalm": "^1|^2|^3|^4" - }, - "autoload": { - "psr-4": { - "ParagonIE\\ConstantTime\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "ParagonIE\\ConstantTime\\Tests\\": "tests/" - } - } -} diff --git a/securemail/vendor/paragonie/constant_time_encoding/src/Base32.php b/securemail/vendor/paragonie/constant_time_encoding/src/Base32.php deleted file mode 100644 index 7508b3df..00000000 --- a/securemail/vendor/paragonie/constant_time_encoding/src/Base32.php +++ /dev/null @@ -1,519 +0,0 @@ - 96 && $src < 123) $ret += $src - 97 + 1; // -64 - $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 96); - - // if ($src > 0x31 && $src < 0x38) $ret += $src - 24 + 1; // -23 - $ret += (((0x31 - $src) & ($src - 0x38)) >> 8) & ($src - 23); - - return $ret; - } - - /** - * Uses bitwise operators instead of table-lookups to turn 5-bit integers - * into 8-bit integers. - * - * Uppercase variant. - * - * @param int $src - * @return int - */ - protected static function decode5BitsUpper(int $src): int - { - $ret = -1; - - // if ($src > 64 && $src < 91) $ret += $src - 65 + 1; // -64 - $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64); - - // if ($src > 0x31 && $src < 0x38) $ret += $src - 24 + 1; // -23 - $ret += (((0x31 - $src) & ($src - 0x38)) >> 8) & ($src - 23); - - return $ret; - } - - /** - * Uses bitwise operators instead of table-lookups to turn 8-bit integers - * into 5-bit integers. - * - * @param int $src - * @return string - */ - protected static function encode5Bits(int $src): string - { - $diff = 0x61; - - // if ($src > 25) $ret -= 72; - $diff -= ((25 - $src) >> 8) & 73; - - return \pack('C', $src + $diff); - } - - /** - * Uses bitwise operators instead of table-lookups to turn 8-bit integers - * into 5-bit integers. - * - * Uppercase variant. - * - * @param int $src - * @return string - */ - protected static function encode5BitsUpper(int $src): string - { - $diff = 0x41; - - // if ($src > 25) $ret -= 40; - $diff -= ((25 - $src) >> 8) & 41; - - return \pack('C', $src + $diff); - } - - /** - * @param string $encodedString - * @param bool $upper - * @return string - */ - public static function decodeNoPadding(string $encodedString, bool $upper = false): string - { - $srcLen = Binary::safeStrlen($encodedString); - if ($srcLen === 0) { - return ''; - } - if (($srcLen & 7) === 0) { - for ($j = 0; $j < 7 && $j < $srcLen; ++$j) { - if ($encodedString[$srcLen - $j - 1] === '=') { - throw new InvalidArgumentException( - "decodeNoPadding() doesn't tolerate padding" - ); - } - } - } - return static::doDecode( - $encodedString, - $upper, - true - ); - } - - /** - * Base32 decoding - * - * @param string $src - * @param bool $upper - * @param bool $strictPadding - * @return string - * - * @throws TypeError - * @psalm-suppress RedundantCondition - */ - protected static function doDecode( - string $src, - bool $upper = false, - bool $strictPadding = false - ): string { - // We do this to reduce code duplication: - $method = $upper - ? 'decode5BitsUpper' - : 'decode5Bits'; - - // Remove padding - $srcLen = Binary::safeStrlen($src); - if ($srcLen === 0) { - return ''; - } - if ($strictPadding) { - if (($srcLen & 7) === 0) { - for ($j = 0; $j < 7; ++$j) { - if ($src[$srcLen - 1] === '=') { - $srcLen--; - } else { - break; - } - } - } - if (($srcLen & 7) === 1) { - throw new RangeException( - 'Incorrect padding' - ); - } - } else { - $src = \rtrim($src, '='); - $srcLen = Binary::safeStrlen($src); - } - - $err = 0; - $dest = ''; - // Main loop (no padding): - for ($i = 0; $i + 8 <= $srcLen; $i += 8) { - /** @var array $chunk */ - $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 8)); - /** @var int $c0 */ - $c0 = static::$method($chunk[1]); - /** @var int $c1 */ - $c1 = static::$method($chunk[2]); - /** @var int $c2 */ - $c2 = static::$method($chunk[3]); - /** @var int $c3 */ - $c3 = static::$method($chunk[4]); - /** @var int $c4 */ - $c4 = static::$method($chunk[5]); - /** @var int $c5 */ - $c5 = static::$method($chunk[6]); - /** @var int $c6 */ - $c6 = static::$method($chunk[7]); - /** @var int $c7 */ - $c7 = static::$method($chunk[8]); - - $dest .= \pack( - 'CCCCC', - (($c0 << 3) | ($c1 >> 2) ) & 0xff, - (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff, - (($c3 << 4) | ($c4 >> 1) ) & 0xff, - (($c4 << 7) | ($c5 << 2) | ($c6 >> 3)) & 0xff, - (($c6 << 5) | ($c7 ) ) & 0xff - ); - $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5 | $c6 | $c7) >> 8; - } - // The last chunk, which may have padding: - if ($i < $srcLen) { - /** @var array $chunk */ - $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i)); - /** @var int $c0 */ - $c0 = static::$method($chunk[1]); - - if ($i + 6 < $srcLen) { - /** @var int $c1 */ - $c1 = static::$method($chunk[2]); - /** @var int $c2 */ - $c2 = static::$method($chunk[3]); - /** @var int $c3 */ - $c3 = static::$method($chunk[4]); - /** @var int $c4 */ - $c4 = static::$method($chunk[5]); - /** @var int $c5 */ - $c5 = static::$method($chunk[6]); - /** @var int $c6 */ - $c6 = static::$method($chunk[7]); - - $dest .= \pack( - 'CCCC', - (($c0 << 3) | ($c1 >> 2) ) & 0xff, - (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff, - (($c3 << 4) | ($c4 >> 1) ) & 0xff, - (($c4 << 7) | ($c5 << 2) | ($c6 >> 3)) & 0xff - ); - $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5 | $c6) >> 8; - if ($strictPadding) { - $err |= ($c6 << 5) & 0xff; - } - } elseif ($i + 5 < $srcLen) { - /** @var int $c1 */ - $c1 = static::$method($chunk[2]); - /** @var int $c2 */ - $c2 = static::$method($chunk[3]); - /** @var int $c3 */ - $c3 = static::$method($chunk[4]); - /** @var int $c4 */ - $c4 = static::$method($chunk[5]); - /** @var int $c5 */ - $c5 = static::$method($chunk[6]); - - $dest .= \pack( - 'CCCC', - (($c0 << 3) | ($c1 >> 2) ) & 0xff, - (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff, - (($c3 << 4) | ($c4 >> 1) ) & 0xff, - (($c4 << 7) | ($c5 << 2) ) & 0xff - ); - $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5) >> 8; - } elseif ($i + 4 < $srcLen) { - /** @var int $c1 */ - $c1 = static::$method($chunk[2]); - /** @var int $c2 */ - $c2 = static::$method($chunk[3]); - /** @var int $c3 */ - $c3 = static::$method($chunk[4]); - /** @var int $c4 */ - $c4 = static::$method($chunk[5]); - - $dest .= \pack( - 'CCC', - (($c0 << 3) | ($c1 >> 2) ) & 0xff, - (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff, - (($c3 << 4) | ($c4 >> 1) ) & 0xff - ); - $err |= ($c0 | $c1 | $c2 | $c3 | $c4) >> 8; - if ($strictPadding) { - $err |= ($c4 << 7) & 0xff; - } - } elseif ($i + 3 < $srcLen) { - /** @var int $c1 */ - $c1 = static::$method($chunk[2]); - /** @var int $c2 */ - $c2 = static::$method($chunk[3]); - /** @var int $c3 */ - $c3 = static::$method($chunk[4]); - - $dest .= \pack( - 'CC', - (($c0 << 3) | ($c1 >> 2) ) & 0xff, - (($c1 << 6) | ($c2 << 1) | ($c3 >> 4)) & 0xff - ); - $err |= ($c0 | $c1 | $c2 | $c3) >> 8; - if ($strictPadding) { - $err |= ($c3 << 4) & 0xff; - } - } elseif ($i + 2 < $srcLen) { - /** @var int $c1 */ - $c1 = static::$method($chunk[2]); - /** @var int $c2 */ - $c2 = static::$method($chunk[3]); - - $dest .= \pack( - 'CC', - (($c0 << 3) | ($c1 >> 2) ) & 0xff, - (($c1 << 6) | ($c2 << 1) ) & 0xff - ); - $err |= ($c0 | $c1 | $c2) >> 8; - if ($strictPadding) { - $err |= ($c2 << 6) & 0xff; - } - } elseif ($i + 1 < $srcLen) { - /** @var int $c1 */ - $c1 = static::$method($chunk[2]); - - $dest .= \pack( - 'C', - (($c0 << 3) | ($c1 >> 2) ) & 0xff - ); - $err |= ($c0 | $c1) >> 8; - if ($strictPadding) { - $err |= ($c1 << 6) & 0xff; - } - } else { - $dest .= \pack( - 'C', - (($c0 << 3) ) & 0xff - ); - $err |= ($c0) >> 8; - } - } - $check = ($err === 0); - if (!$check) { - throw new RangeException( - 'Base32::doDecode() only expects characters in the correct base32 alphabet' - ); - } - return $dest; - } - - /** - * Base32 Encoding - * - * @param string $src - * @param bool $upper - * @param bool $pad - * @return string - * @throws TypeError - */ - protected static function doEncode(string $src, bool $upper = false, $pad = true): string - { - // We do this to reduce code duplication: - $method = $upper - ? 'encode5BitsUpper' - : 'encode5Bits'; - - $dest = ''; - $srcLen = Binary::safeStrlen($src); - - // Main loop (no padding): - for ($i = 0; $i + 5 <= $srcLen; $i += 5) { - /** @var array $chunk */ - $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 5)); - $b0 = $chunk[1]; - $b1 = $chunk[2]; - $b2 = $chunk[3]; - $b3 = $chunk[4]; - $b4 = $chunk[5]; - $dest .= - static::$method( ($b0 >> 3) & 31) . - static::$method((($b0 << 2) | ($b1 >> 6)) & 31) . - static::$method((($b1 >> 1) ) & 31) . - static::$method((($b1 << 4) | ($b2 >> 4)) & 31) . - static::$method((($b2 << 1) | ($b3 >> 7)) & 31) . - static::$method((($b3 >> 2) ) & 31) . - static::$method((($b3 << 3) | ($b4 >> 5)) & 31) . - static::$method( $b4 & 31); - } - // The last chunk, which may have padding: - if ($i < $srcLen) { - /** @var array $chunk */ - $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i)); - $b0 = $chunk[1]; - if ($i + 3 < $srcLen) { - $b1 = $chunk[2]; - $b2 = $chunk[3]; - $b3 = $chunk[4]; - $dest .= - static::$method( ($b0 >> 3) & 31) . - static::$method((($b0 << 2) | ($b1 >> 6)) & 31) . - static::$method((($b1 >> 1) ) & 31) . - static::$method((($b1 << 4) | ($b2 >> 4)) & 31) . - static::$method((($b2 << 1) | ($b3 >> 7)) & 31) . - static::$method((($b3 >> 2) ) & 31) . - static::$method((($b3 << 3) ) & 31); - if ($pad) { - $dest .= '='; - } - } elseif ($i + 2 < $srcLen) { - $b1 = $chunk[2]; - $b2 = $chunk[3]; - $dest .= - static::$method( ($b0 >> 3) & 31) . - static::$method((($b0 << 2) | ($b1 >> 6)) & 31) . - static::$method((($b1 >> 1) ) & 31) . - static::$method((($b1 << 4) | ($b2 >> 4)) & 31) . - static::$method((($b2 << 1) ) & 31); - if ($pad) { - $dest .= '==='; - } - } elseif ($i + 1 < $srcLen) { - $b1 = $chunk[2]; - $dest .= - static::$method( ($b0 >> 3) & 31) . - static::$method((($b0 << 2) | ($b1 >> 6)) & 31) . - static::$method((($b1 >> 1) ) & 31) . - static::$method((($b1 << 4) ) & 31); - if ($pad) { - $dest .= '===='; - } - } else { - $dest .= - static::$method( ($b0 >> 3) & 31) . - static::$method( ($b0 << 2) & 31); - if ($pad) { - $dest .= '======'; - } - } - } - return $dest; - } -} diff --git a/securemail/vendor/paragonie/constant_time_encoding/src/Base32Hex.php b/securemail/vendor/paragonie/constant_time_encoding/src/Base32Hex.php deleted file mode 100644 index b868dd04..00000000 --- a/securemail/vendor/paragonie/constant_time_encoding/src/Base32Hex.php +++ /dev/null @@ -1,111 +0,0 @@ - 0x30 && $src < 0x3a) ret += $src - 0x2e + 1; // -47 - $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src - 47); - - // if ($src > 0x60 && $src < 0x77) ret += $src - 0x61 + 10 + 1; // -86 - $ret += (((0x60 - $src) & ($src - 0x77)) >> 8) & ($src - 86); - - return $ret; - } - - /** - * Uses bitwise operators instead of table-lookups to turn 5-bit integers - * into 8-bit integers. - * - * @param int $src - * @return int - */ - protected static function decode5BitsUpper(int $src): int - { - $ret = -1; - - // if ($src > 0x30 && $src < 0x3a) ret += $src - 0x2e + 1; // -47 - $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src - 47); - - // if ($src > 0x40 && $src < 0x57) ret += $src - 0x41 + 10 + 1; // -54 - $ret += (((0x40 - $src) & ($src - 0x57)) >> 8) & ($src - 54); - - return $ret; - } - - /** - * Uses bitwise operators instead of table-lookups to turn 8-bit integers - * into 5-bit integers. - * - * @param int $src - * @return string - */ - protected static function encode5Bits(int $src): string - { - $src += 0x30; - - // if ($src > 0x39) $src += 0x61 - 0x3a; // 39 - $src += ((0x39 - $src) >> 8) & 39; - - return \pack('C', $src); - } - - /** - * Uses bitwise operators instead of table-lookups to turn 8-bit integers - * into 5-bit integers. - * - * Uppercase variant. - * - * @param int $src - * @return string - */ - protected static function encode5BitsUpper(int $src): string - { - $src += 0x30; - - // if ($src > 0x39) $src += 0x41 - 0x3a; // 7 - $src += ((0x39 - $src) >> 8) & 7; - - return \pack('C', $src); - } -} \ No newline at end of file diff --git a/securemail/vendor/paragonie/constant_time_encoding/src/Base64.php b/securemail/vendor/paragonie/constant_time_encoding/src/Base64.php deleted file mode 100644 index f5716179..00000000 --- a/securemail/vendor/paragonie/constant_time_encoding/src/Base64.php +++ /dev/null @@ -1,314 +0,0 @@ - $chunk */ - $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 3)); - $b0 = $chunk[1]; - $b1 = $chunk[2]; - $b2 = $chunk[3]; - - $dest .= - static::encode6Bits( $b0 >> 2 ) . - static::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) . - static::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) . - static::encode6Bits( $b2 & 63); - } - // The last chunk, which may have padding: - if ($i < $srcLen) { - /** @var array $chunk */ - $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i)); - $b0 = $chunk[1]; - if ($i + 1 < $srcLen) { - $b1 = $chunk[2]; - $dest .= - static::encode6Bits($b0 >> 2) . - static::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) . - static::encode6Bits(($b1 << 2) & 63); - if ($pad) { - $dest .= '='; - } - } else { - $dest .= - static::encode6Bits( $b0 >> 2) . - static::encode6Bits(($b0 << 4) & 63); - if ($pad) { - $dest .= '=='; - } - } - } - return $dest; - } - - /** - * decode from base64 into binary - * - * Base64 character set "./[A-Z][a-z][0-9]" - * - * @param string $encodedString - * @param bool $strictPadding - * @return string - * - * @throws RangeException - * @throws TypeError - * @psalm-suppress RedundantCondition - */ - public static function decode(string $encodedString, bool $strictPadding = false): string - { - // Remove padding - $srcLen = Binary::safeStrlen($encodedString); - if ($srcLen === 0) { - return ''; - } - - if ($strictPadding) { - if (($srcLen & 3) === 0) { - if ($encodedString[$srcLen - 1] === '=') { - $srcLen--; - if ($encodedString[$srcLen - 1] === '=') { - $srcLen--; - } - } - } - if (($srcLen & 3) === 1) { - throw new RangeException( - 'Incorrect padding' - ); - } - if ($encodedString[$srcLen - 1] === '=') { - throw new RangeException( - 'Incorrect padding' - ); - } - } else { - $encodedString = \rtrim($encodedString, '='); - $srcLen = Binary::safeStrlen($encodedString); - } - - $err = 0; - $dest = ''; - // Main loop (no padding): - for ($i = 0; $i + 4 <= $srcLen; $i += 4) { - /** @var array $chunk */ - $chunk = \unpack('C*', Binary::safeSubstr($encodedString, $i, 4)); - $c0 = static::decode6Bits($chunk[1]); - $c1 = static::decode6Bits($chunk[2]); - $c2 = static::decode6Bits($chunk[3]); - $c3 = static::decode6Bits($chunk[4]); - - $dest .= \pack( - 'CCC', - ((($c0 << 2) | ($c1 >> 4)) & 0xff), - ((($c1 << 4) | ($c2 >> 2)) & 0xff), - ((($c2 << 6) | $c3 ) & 0xff) - ); - $err |= ($c0 | $c1 | $c2 | $c3) >> 8; - } - // The last chunk, which may have padding: - if ($i < $srcLen) { - /** @var array $chunk */ - $chunk = \unpack('C*', Binary::safeSubstr($encodedString, $i, $srcLen - $i)); - $c0 = static::decode6Bits($chunk[1]); - - if ($i + 2 < $srcLen) { - $c1 = static::decode6Bits($chunk[2]); - $c2 = static::decode6Bits($chunk[3]); - $dest .= \pack( - 'CC', - ((($c0 << 2) | ($c1 >> 4)) & 0xff), - ((($c1 << 4) | ($c2 >> 2)) & 0xff) - ); - $err |= ($c0 | $c1 | $c2) >> 8; - if ($strictPadding) { - $err |= ($c2 << 6) & 0xff; - } - } elseif ($i + 1 < $srcLen) { - $c1 = static::decode6Bits($chunk[2]); - $dest .= \pack( - 'C', - ((($c0 << 2) | ($c1 >> 4)) & 0xff) - ); - $err |= ($c0 | $c1) >> 8; - if ($strictPadding) { - $err |= ($c1 << 4) & 0xff; - } - } elseif ($strictPadding) { - $err |= 1; - } - } - $check = ($err === 0); - if (!$check) { - throw new RangeException( - 'Base64::decode() only expects characters in the correct base64 alphabet' - ); - } - return $dest; - } - - /** - * @param string $encodedString - * @return string - */ - public static function decodeNoPadding(string $encodedString): string - { - $srcLen = Binary::safeStrlen($encodedString); - if ($srcLen === 0) { - return ''; - } - if (($srcLen & 3) === 0) { - if ($encodedString[$srcLen - 1] === '=') { - throw new InvalidArgumentException( - "decodeNoPadding() doesn't tolerate padding" - ); - } - if (($srcLen & 3) > 1) { - if ($encodedString[$srcLen - 2] === '=') { - throw new InvalidArgumentException( - "decodeNoPadding() doesn't tolerate padding" - ); - } - } - } - return static::decode( - $encodedString, - true - ); - } - - /** - * Uses bitwise operators instead of table-lookups to turn 6-bit integers - * into 8-bit integers. - * - * Base64 character set: - * [A-Z] [a-z] [0-9] + / - * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f - * - * @param int $src - * @return int - */ - protected static function decode6Bits(int $src): int - { - $ret = -1; - - // if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64 - $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64); - - // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70 - $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70); - - // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5 - $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5); - - // if ($src == 0x2b) $ret += 62 + 1; - $ret += (((0x2a - $src) & ($src - 0x2c)) >> 8) & 63; - - // if ($src == 0x2f) ret += 63 + 1; - $ret += (((0x2e - $src) & ($src - 0x30)) >> 8) & 64; - - return $ret; - } - - /** - * Uses bitwise operators instead of table-lookups to turn 8-bit integers - * into 6-bit integers. - * - * @param int $src - * @return string - */ - protected static function encode6Bits(int $src): string - { - $diff = 0x41; - - // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6 - $diff += ((25 - $src) >> 8) & 6; - - // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75 - $diff -= ((51 - $src) >> 8) & 75; - - // if ($src > 61) $diff += 0x2b - 0x30 - 10; // -15 - $diff -= ((61 - $src) >> 8) & 15; - - // if ($src > 62) $diff += 0x2f - 0x2b - 1; // 3 - $diff += ((62 - $src) >> 8) & 3; - - return \pack('C', $src + $diff); - } -} diff --git a/securemail/vendor/paragonie/constant_time_encoding/src/Base64DotSlash.php b/securemail/vendor/paragonie/constant_time_encoding/src/Base64DotSlash.php deleted file mode 100644 index 5e98a8f7..00000000 --- a/securemail/vendor/paragonie/constant_time_encoding/src/Base64DotSlash.php +++ /dev/null @@ -1,88 +0,0 @@ - 0x2d && $src < 0x30) ret += $src - 0x2e + 1; // -45 - $ret += (((0x2d - $src) & ($src - 0x30)) >> 8) & ($src - 45); - - // if ($src > 0x40 && $src < 0x5b) ret += $src - 0x41 + 2 + 1; // -62 - $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 62); - - // if ($src > 0x60 && $src < 0x7b) ret += $src - 0x61 + 28 + 1; // -68 - $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 68); - - // if ($src > 0x2f && $src < 0x3a) ret += $src - 0x30 + 54 + 1; // 7 - $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 7); - - return $ret; - } - - /** - * Uses bitwise operators instead of table-lookups to turn 8-bit integers - * into 6-bit integers. - * - * @param int $src - * @return string - */ - protected static function encode6Bits(int $src): string - { - $src += 0x2e; - - // if ($src > 0x2f) $src += 0x41 - 0x30; // 17 - $src += ((0x2f - $src) >> 8) & 17; - - // if ($src > 0x5a) $src += 0x61 - 0x5b; // 6 - $src += ((0x5a - $src) >> 8) & 6; - - // if ($src > 0x7a) $src += 0x30 - 0x7b; // -75 - $src -= ((0x7a - $src) >> 8) & 75; - - return \pack('C', $src); - } -} diff --git a/securemail/vendor/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php b/securemail/vendor/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php deleted file mode 100644 index 9780b14b..00000000 --- a/securemail/vendor/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php +++ /dev/null @@ -1,82 +0,0 @@ - 0x2d && $src < 0x3a) ret += $src - 0x2e + 1; // -45 - $ret += (((0x2d - $src) & ($src - 0x3a)) >> 8) & ($src - 45); - - // if ($src > 0x40 && $src < 0x5b) ret += $src - 0x41 + 12 + 1; // -52 - $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 52); - - // if ($src > 0x60 && $src < 0x7b) ret += $src - 0x61 + 38 + 1; // -58 - $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 58); - - return $ret; - } - - /** - * Uses bitwise operators instead of table-lookups to turn 8-bit integers - * into 6-bit integers. - * - * @param int $src - * @return string - */ - protected static function encode6Bits(int $src): string - { - $src += 0x2e; - - // if ($src > 0x39) $src += 0x41 - 0x3a; // 7 - $src += ((0x39 - $src) >> 8) & 7; - - // if ($src > 0x5a) $src += 0x61 - 0x5b; // 6 - $src += ((0x5a - $src) >> 8) & 6; - - return \pack('C', $src); - } -} diff --git a/securemail/vendor/paragonie/constant_time_encoding/src/Base64UrlSafe.php b/securemail/vendor/paragonie/constant_time_encoding/src/Base64UrlSafe.php deleted file mode 100644 index 8192c63d..00000000 --- a/securemail/vendor/paragonie/constant_time_encoding/src/Base64UrlSafe.php +++ /dev/null @@ -1,95 +0,0 @@ - 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64 - $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64); - - // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70 - $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70); - - // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5 - $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5); - - // if ($src == 0x2c) $ret += 62 + 1; - $ret += (((0x2c - $src) & ($src - 0x2e)) >> 8) & 63; - - // if ($src == 0x5f) ret += 63 + 1; - $ret += (((0x5e - $src) & ($src - 0x60)) >> 8) & 64; - - return $ret; - } - - /** - * Uses bitwise operators instead of table-lookups to turn 8-bit integers - * into 6-bit integers. - * - * @param int $src - * @return string - */ - protected static function encode6Bits(int $src): string - { - $diff = 0x41; - - // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6 - $diff += ((25 - $src) >> 8) & 6; - - // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75 - $diff -= ((51 - $src) >> 8) & 75; - - // if ($src > 61) $diff += 0x2d - 0x30 - 10; // -13 - $diff -= ((61 - $src) >> 8) & 13; - - // if ($src > 62) $diff += 0x5f - 0x2b - 1; // 3 - $diff += ((62 - $src) >> 8) & 49; - - return \pack('C', $src + $diff); - } -} diff --git a/securemail/vendor/paragonie/constant_time_encoding/src/Binary.php b/securemail/vendor/paragonie/constant_time_encoding/src/Binary.php deleted file mode 100644 index 828f3e0f..00000000 --- a/securemail/vendor/paragonie/constant_time_encoding/src/Binary.php +++ /dev/null @@ -1,90 +0,0 @@ - $chunk */ - $chunk = \unpack('C', $binString[$i]); - $c = $chunk[1] & 0xf; - $b = $chunk[1] >> 4; - - $hex .= \pack( - 'CC', - (87 + $b + ((($b - 10) >> 8) & ~38)), - (87 + $c + ((($c - 10) >> 8) & ~38)) - ); - } - return $hex; - } - - /** - * Convert a binary string into a hexadecimal string without cache-timing - * leaks, returning uppercase letters (as per RFC 4648) - * - * @param string $binString (raw binary) - * @return string - * @throws TypeError - */ - public static function encodeUpper(string $binString): string - { - $hex = ''; - $len = Binary::safeStrlen($binString); - - for ($i = 0; $i < $len; ++$i) { - /** @var array $chunk */ - $chunk = \unpack('C', $binString[$i]); - $c = $chunk[1] & 0xf; - $b = $chunk[1] >> 4; - - $hex .= \pack( - 'CC', - (55 + $b + ((($b - 10) >> 8) & ~6)), - (55 + $c + ((($c - 10) >> 8) & ~6)) - ); - } - return $hex; - } - - /** - * Convert a hexadecimal string into a binary string without cache-timing - * leaks - * - * @param string $encodedString - * @param bool $strictPadding - * @return string (raw binary) - * @throws RangeException - */ - public static function decode( - string $encodedString, - bool $strictPadding = false - ): string { - $hex_pos = 0; - $bin = ''; - $c_acc = 0; - $hex_len = Binary::safeStrlen($encodedString); - $state = 0; - if (($hex_len & 1) !== 0) { - if ($strictPadding) { - throw new RangeException( - 'Expected an even number of hexadecimal characters' - ); - } else { - $encodedString = '0' . $encodedString; - ++$hex_len; - } - } - - /** @var array $chunk */ - $chunk = \unpack('C*', $encodedString); - while ($hex_pos < $hex_len) { - ++$hex_pos; - $c = $chunk[$hex_pos]; - $c_num = $c ^ 48; - $c_num0 = ($c_num - 10) >> 8; - $c_alpha = ($c & ~32) - 55; - $c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8; - - if (($c_num0 | $c_alpha0) === 0) { - throw new RangeException( - 'Expected hexadecimal character' - ); - } - $c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0); - if ($state === 0) { - $c_acc = $c_val * 16; - } else { - $bin .= \pack('C', $c_acc | $c_val); - } - $state ^= 1; - } - return $bin; - } -} diff --git a/securemail/vendor/paragonie/constant_time_encoding/src/RFC4648.php b/securemail/vendor/paragonie/constant_time_encoding/src/RFC4648.php deleted file mode 100644 index f124d65b..00000000 --- a/securemail/vendor/paragonie/constant_time_encoding/src/RFC4648.php +++ /dev/null @@ -1,186 +0,0 @@ - "Zm9v" - * - * @param string $str - * @return string - * - * @throws TypeError - */ - public static function base64Encode(string $str): string - { - return Base64::encode($str); - } - - /** - * RFC 4648 Base64 decoding - * - * "Zm9v" -> "foo" - * - * @param string $str - * @return string - * - * @throws TypeError - */ - public static function base64Decode(string $str): string - { - return Base64::decode($str, true); - } - - /** - * RFC 4648 Base64 (URL Safe) encoding - * - * "foo" -> "Zm9v" - * - * @param string $str - * @return string - * - * @throws TypeError - */ - public static function base64UrlSafeEncode(string $str): string - { - return Base64UrlSafe::encode($str); - } - - /** - * RFC 4648 Base64 (URL Safe) decoding - * - * "Zm9v" -> "foo" - * - * @param string $str - * @return string - * - * @throws TypeError - */ - public static function base64UrlSafeDecode(string $str): string - { - return Base64UrlSafe::decode($str, true); - } - - /** - * RFC 4648 Base32 encoding - * - * "foo" -> "MZXW6===" - * - * @param string $str - * @return string - * - * @throws TypeError - */ - public static function base32Encode(string $str): string - { - return Base32::encodeUpper($str); - } - - /** - * RFC 4648 Base32 encoding - * - * "MZXW6===" -> "foo" - * - * @param string $str - * @return string - * - * @throws TypeError - */ - public static function base32Decode(string $str): string - { - return Base32::decodeUpper($str, true); - } - - /** - * RFC 4648 Base32-Hex encoding - * - * "foo" -> "CPNMU===" - * - * @param string $str - * @return string - * - * @throws TypeError - */ - public static function base32HexEncode(string $str): string - { - return Base32::encodeUpper($str); - } - - /** - * RFC 4648 Base32-Hex decoding - * - * "CPNMU===" -> "foo" - * - * @param string $str - * @return string - * - * @throws TypeError - */ - public static function base32HexDecode(string $str): string - { - return Base32::decodeUpper($str, true); - } - - /** - * RFC 4648 Base16 decoding - * - * "foo" -> "666F6F" - * - * @param string $str - * @return string - * - * @throws TypeError - */ - public static function base16Encode(string $str): string - { - return Hex::encodeUpper($str); - } - - /** - * RFC 4648 Base16 decoding - * - * "666F6F" -> "foo" - * - * @param string $str - * @return string - */ - public static function base16Decode(string $str): string - { - return Hex::decode($str, true); - } -} \ No newline at end of file diff --git a/securemail/vendor/phpseclib/phpseclib/AUTHORS b/securemail/vendor/phpseclib/phpseclib/AUTHORS deleted file mode 100644 index 9f10d267..00000000 --- a/securemail/vendor/phpseclib/phpseclib/AUTHORS +++ /dev/null @@ -1,7 +0,0 @@ -phpseclib Lead Developer: TerraFrost (Jim Wigginton) - -phpseclib Developers: monnerat (Patrick Monnerat) - bantu (Andreas Fischer) - petrich (Hans-Jürgen Petrich) - GrahamCampbell (Graham Campbell) - hc-jworman \ No newline at end of file diff --git a/securemail/vendor/phpseclib/phpseclib/BACKERS.md b/securemail/vendor/phpseclib/phpseclib/BACKERS.md deleted file mode 100644 index 5e5c6d99..00000000 --- a/securemail/vendor/phpseclib/phpseclib/BACKERS.md +++ /dev/null @@ -1,15 +0,0 @@ -# Backers - -phpseclib ongoing development is made possible by [Tidelift](https://tidelift.com/subscription/pkg/packagist-phpseclib-phpseclib?utm_source=packagist-phpseclib-phpseclib&utm_medium=referral&utm_campaign=readme) and by contributions by users like you. Thank you. - -## Backers - -- Allan Simon -- [ChargeOver](https://chargeover.com/) -- Raghu Veer Dendukuri -- Zane Hooper -- [Setasign](https://www.setasign.com/) -- [Charles Severance](https://github.com/csev) -- [Rachel Fish](https://github.com/itsrachelfish) -- Tharyrok -- [cjhaas](https://github.com/cjhaas) \ No newline at end of file diff --git a/securemail/vendor/phpseclib/phpseclib/LICENSE b/securemail/vendor/phpseclib/phpseclib/LICENSE deleted file mode 100644 index e7214ebb..00000000 --- a/securemail/vendor/phpseclib/phpseclib/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2011-2019 TerraFrost and other contributors - -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/securemail/vendor/phpseclib/phpseclib/README.md b/securemail/vendor/phpseclib/phpseclib/README.md deleted file mode 100644 index 64c06ba2..00000000 --- a/securemail/vendor/phpseclib/phpseclib/README.md +++ /dev/null @@ -1,98 +0,0 @@ -# phpseclib - PHP Secure Communications Library - -[![CI Status](https://github.com/phpseclib/phpseclib/actions/workflows/ci.yml/badge.svg?branch=3.0&event=push "CI Status")](https://github.com/phpseclib/phpseclib) - -## Supporting phpseclib - -- [Become a backer or sponsor on Patreon](https://www.patreon.com/phpseclib) -- [One-time donation via PayPal or crypto-currencies](http://sourceforge.net/donate/index.php?group_id=198487) -- [Subscribe to Tidelift](https://tidelift.com/subscription/pkg/packagist-phpseclib-phpseclib?utm_source=packagist-phpseclib-phpseclib&utm_medium=referral&utm_campaign=readme) - -## Introduction - -MIT-licensed pure-PHP implementations of the following: - -SSH-2, SFTP, X.509, an arbitrary-precision integer arithmetic library, Ed25519 / Ed449 / Curve25519 / Curve449, ECDSA / ECDH (with support for 66 curves), RSA (PKCS#1 v2.2 compliant), DSA / DH, DES / 3DES / RC4 / Rijndael / AES / Blowfish / Twofish / Salsa20 / ChaCha20, GCM / Poly1305 - -* [Browse Git](https://github.com/phpseclib/phpseclib) - -## Documentation - -* [Documentation / Manual](https://phpseclib.com/) -* [API Documentation](https://api.phpseclib.com/3.0/) (generated by Doctum) - -## Branches - -### master - -* Development Branch -* Unstable API -* Do not use in production - -### 3.0 - -* Long term support (LTS) release -* Major expansion of cryptographic primitives -* Minimum PHP version: 5.6.1 -* PSR-4 autoloading with namespace rooted at `\phpseclib3` -* Install via Composer: `composer require phpseclib/phpseclib:~3.0` - -### 2.0 - -* Long term support (LTS) release -* Modernized version of 1.0 -* Minimum PHP version: 5.3.3 -* PSR-4 autoloading with namespace rooted at `\phpseclib` -* Install via Composer: `composer require phpseclib/phpseclib:~2.0` - -### 1.0 - -* Long term support (LTS) release -* PHP4 compatible -* Composer compatible (PSR-0 autoloading) -* Install using Composer: `composer require phpseclib/phpseclib:~1.0` -* Install using PEAR: See [phpseclib PEAR Channel Documentation](http://phpseclib.sourceforge.net/pear.htm) -* [Download 1.0.20 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.20.zip/download) - -## Security contact information - -To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure. - -## Support - -Need Support? - -* [Checkout Questions and Answers on Stack Overflow](http://stackoverflow.com/questions/tagged/phpseclib) -* [Create a Support Ticket on GitHub](https://github.com/phpseclib/phpseclib/issues/new) -* [Browse the Support Forum](http://www.frostjedi.com/phpbb/viewforum.php?f=46) (no longer in use) - -## Special Thanks - -Special Thanks to our $50+ sponsors!: - -- Allan Simon -- [ChargeOver](https://chargeover.com/) - -## Contributing - -1. Fork the Project - -2. Ensure you have Composer installed (see [Composer Download Instructions](https://getcomposer.org/download/)) - -3. Install Development Dependencies - ```sh - composer install - ``` - -4. Create a Feature Branch - -5. Run continuous integration checks: - ```sh - composer global require php:^8.1 squizlabs/php_codesniffer friendsofphp/php-cs-fixer vimeo/psalm - phpcs --standard=build/php_codesniffer.xml - php-cs-fixer fix --config=build/php-cs-fixer.php --diff --dry-run --using-cache=no - psalm --config=build/psalm.xml --no-cache --long-progress --report-show-info=false --output-format=text - vendor/bin/phpunit --verbose --configuration tests/phpunit.xml - ``` - -6. Send us a Pull Request diff --git a/securemail/vendor/phpseclib/phpseclib/composer.json b/securemail/vendor/phpseclib/phpseclib/composer.json deleted file mode 100644 index 5052d5fb..00000000 --- a/securemail/vendor/phpseclib/phpseclib/composer.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "name": "phpseclib/phpseclib", - "type": "library", - "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", - "keywords": [ - "security", - "crypto", - "cryptography", - "encryption", - "signature", - "signing", - "rsa", - "aes", - "blowfish", - "twofish", - "ssh", - "sftp", - "x509", - "x.509", - "asn1", - "asn.1", - "BigInteger" - ], - "homepage": "http://phpseclib.sourceforge.net", - "license": "MIT", - "authors": [ - { - "name": "Jim Wigginton", - "email": "terrafrost@php.net", - "role": "Lead Developer" - }, - { - "name": "Patrick Monnerat", - "email": "pm@datasphere.ch", - "role": "Developer" - }, - { - "name": "Andreas Fischer", - "email": "bantu@phpbb.com", - "role": "Developer" - }, - { - "name": "Hans-Jürgen Petrich", - "email": "petrich@tronic-media.com", - "role": "Developer" - }, - { - "name": "Graham Campbell", - "email": "graham@alt-three.com", - "role": "Developer" - } - ], - "require": { - "php": ">=5.6.1", - "paragonie/constant_time_encoding": "^1|^2", - "paragonie/random_compat": "^1.4|^2.0|^9.99.99" - }, - "require-dev": { - "phpunit/phpunit": "*" - }, - "suggest": { - "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", - "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations.", - "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", - "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", - "ext-dom": "Install the DOM extension to load XML formatted public keys." - }, - "autoload": { - "files": [ - "phpseclib/bootstrap.php" - ], - "psr-4": { - "phpseclib3\\": "phpseclib/" - } - }, - "autoload-dev": { - "psr-4": { - "phpseclib3\\Tests\\": "tests/" - } - }, - "config": { - "sort-packages": true - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Common/Functions/Strings.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Common/Functions/Strings.php deleted file mode 100644 index eac793a6..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Common/Functions/Strings.php +++ /dev/null @@ -1,505 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Common\Functions; - -use ParagonIE\ConstantTime\Base64; -use ParagonIE\ConstantTime\Base64UrlSafe; -use ParagonIE\ConstantTime\Hex; -use phpseclib3\Math\BigInteger; -use phpseclib3\Math\Common\FiniteField; - -/** - * Common String Functions - * - * @author Jim Wigginton - */ -abstract class Strings -{ - /** - * String Shift - * - * Inspired by array_shift - * - * @param string $string - * @param int $index - * @return string - */ - public static function shift(&$string, $index = 1) - { - $substr = substr($string, 0, $index); - $string = substr($string, $index); - return $substr; - } - - /** - * String Pop - * - * Inspired by array_pop - * - * @param string $string - * @param int $index - * @return string - */ - public static function pop(&$string, $index = 1) - { - $substr = substr($string, -$index); - $string = substr($string, 0, -$index); - return $substr; - } - - /** - * Parse SSH2-style string - * - * Returns either an array or a boolean if $data is malformed. - * - * Valid characters for $format are as follows: - * - * C = byte - * b = boolean (true/false) - * N = uint32 - * Q = uint64 - * s = string - * i = mpint - * L = name-list - * - * uint64 is not supported. - * - * @param string $format - * @param string $data - * @return mixed - */ - public static function unpackSSH2($format, &$data) - { - $format = self::formatPack($format); - $result = []; - for ($i = 0; $i < strlen($format); $i++) { - switch ($format[$i]) { - case 'C': - case 'b': - if (!strlen($data)) { - throw new \LengthException('At least one byte needs to be present for successful C / b decodes'); - } - break; - case 'N': - case 'i': - case 's': - case 'L': - if (strlen($data) < 4) { - throw new \LengthException('At least four byte needs to be present for successful N / i / s / L decodes'); - } - break; - case 'Q': - if (strlen($data) < 8) { - throw new \LengthException('At least eight byte needs to be present for successful N / i / s / L decodes'); - } - break; - - default: - throw new \InvalidArgumentException('$format contains an invalid character'); - } - switch ($format[$i]) { - case 'C': - $result[] = ord(self::shift($data)); - continue 2; - case 'b': - $result[] = ord(self::shift($data)) != 0; - continue 2; - case 'N': - list(, $temp) = unpack('N', self::shift($data, 4)); - $result[] = $temp; - continue 2; - case 'Q': - // pack() added support for Q in PHP 5.6.3 and PHP 5.6 is phpseclib 3's minimum version - // so in theory we could support this BUT, "64-bit format codes are not available for - // 32-bit versions" and phpseclib works on 32-bit installs. on 32-bit installs - // 64-bit floats can be used to get larger numbers then 32-bit signed ints would allow - // for. sure, you're not gonna get the full precision of 64-bit numbers but just because - // you need > 32-bit precision doesn't mean you need the full 64-bit precision - extract(unpack('Nupper/Nlower', self::shift($data, 8))); - $temp = $upper ? 4294967296 * $upper : 0; - $temp += $lower < 0 ? ($lower & 0x7FFFFFFFF) + 0x80000000 : $lower; - // $temp = hexdec(bin2hex(self::shift($data, 8))); - $result[] = $temp; - continue 2; - } - list(, $length) = unpack('N', self::shift($data, 4)); - if (strlen($data) < $length) { - throw new \LengthException("$length bytes needed; " . strlen($data) . ' bytes available'); - } - $temp = self::shift($data, $length); - switch ($format[$i]) { - case 'i': - $result[] = new BigInteger($temp, -256); - break; - case 's': - $result[] = $temp; - break; - case 'L': - $result[] = explode(',', $temp); - } - } - - return $result; - } - - /** - * Create SSH2-style string - * - * @param string $format - * @param string|int|float|array|bool ...$elements - * @return string - */ - public static function packSSH2($format, ...$elements) - { - $format = self::formatPack($format); - if (strlen($format) != count($elements)) { - throw new \InvalidArgumentException('There must be as many arguments as there are characters in the $format string'); - } - $result = ''; - for ($i = 0; $i < strlen($format); $i++) { - $element = $elements[$i]; - switch ($format[$i]) { - case 'C': - if (!is_int($element)) { - throw new \InvalidArgumentException('Bytes must be represented as an integer between 0 and 255, inclusive.'); - } - $result .= pack('C', $element); - break; - case 'b': - if (!is_bool($element)) { - throw new \InvalidArgumentException('A boolean parameter was expected.'); - } - $result .= $element ? "\1" : "\0"; - break; - case 'Q': - if (!is_int($element) && !is_float($element)) { - throw new \InvalidArgumentException('An integer was expected.'); - } - // 4294967296 == 1 << 32 - $result .= pack('NN', $element / 4294967296, $element); - break; - case 'N': - if (is_float($element)) { - $element = (int) $element; - } - if (!is_int($element)) { - throw new \InvalidArgumentException('An integer was expected.'); - } - $result .= pack('N', $element); - break; - case 's': - if (!self::is_stringable($element)) { - throw new \InvalidArgumentException('A string was expected.'); - } - $result .= pack('Na*', strlen($element), $element); - break; - case 'i': - if (!$element instanceof BigInteger && !$element instanceof FiniteField\Integer) { - throw new \InvalidArgumentException('A phpseclib3\Math\BigInteger or phpseclib3\Math\Common\FiniteField\Integer object was expected.'); - } - $element = $element->toBytes(true); - $result .= pack('Na*', strlen($element), $element); - break; - case 'L': - if (!is_array($element)) { - throw new \InvalidArgumentException('An array was expected.'); - } - $element = implode(',', $element); - $result .= pack('Na*', strlen($element), $element); - break; - default: - throw new \InvalidArgumentException('$format contains an invalid character'); - } - } - return $result; - } - - /** - * Expand a pack string - * - * Converts C5 to CCCCC, for example. - * - * @param string $format - * @return string - */ - private static function formatPack($format) - { - $parts = preg_split('#(\d+)#', $format, -1, PREG_SPLIT_DELIM_CAPTURE); - $format = ''; - for ($i = 1; $i < count($parts); $i += 2) { - $format .= substr($parts[$i - 1], 0, -1) . str_repeat(substr($parts[$i - 1], -1), $parts[$i]); - } - $format .= $parts[$i - 1]; - - return $format; - } - - /** - * Convert binary data into bits - * - * bin2hex / hex2bin refer to base-256 encoded data as binary, whilst - * decbin / bindec refer to base-2 encoded data as binary. For the purposes - * of this function, bin refers to base-256 encoded data whilst bits refers - * to base-2 encoded data - * - * @param string $x - * @return string - */ - public static function bits2bin($x) - { - /* - // the pure-PHP approach is faster than the GMP approach - if (function_exists('gmp_export')) { - return strlen($x) ? gmp_export(gmp_init($x, 2)) : gmp_init(0); - } - */ - - if (preg_match('#[^01]#', $x)) { - throw new \RuntimeException('The only valid characters are 0 and 1'); - } - - if (!defined('PHP_INT_MIN')) { - define('PHP_INT_MIN', ~PHP_INT_MAX); - } - - $length = strlen($x); - if (!$length) { - return ''; - } - $block_size = PHP_INT_SIZE << 3; - $pad = $block_size - ($length % $block_size); - if ($pad != $block_size) { - $x = str_repeat('0', $pad) . $x; - } - - $parts = str_split($x, $block_size); - $str = ''; - foreach ($parts as $part) { - $xor = $part[0] == '1' ? PHP_INT_MIN : 0; - $part[0] = '0'; - $str .= pack( - PHP_INT_SIZE == 4 ? 'N' : 'J', - $xor ^ eval('return 0b' . $part . ';') - ); - } - return ltrim($str, "\0"); - } - - /** - * Convert bits to binary data - * - * @param string $x - * @return string - */ - public static function bin2bits($x, $trim = true) - { - /* - // the pure-PHP approach is slower than the GMP approach BUT - // i want to the pure-PHP version to be easily unit tested as well - if (function_exists('gmp_import')) { - return gmp_strval(gmp_import($x), 2); - } - */ - - $len = strlen($x); - $mod = $len % PHP_INT_SIZE; - if ($mod) { - $x = str_pad($x, $len + PHP_INT_SIZE - $mod, "\0", STR_PAD_LEFT); - } - - $bits = ''; - if (PHP_INT_SIZE == 4) { - $digits = unpack('N*', $x); - foreach ($digits as $digit) { - $bits .= sprintf('%032b', $digit); - } - } else { - $digits = unpack('J*', $x); - foreach ($digits as $digit) { - $bits .= sprintf('%064b', $digit); - } - } - - return $trim ? ltrim($bits, '0') : $bits; - } - - /** - * Switch Endianness Bit Order - * - * @param string $x - * @return string - */ - public static function switchEndianness($x) - { - $r = ''; - for ($i = strlen($x) - 1; $i >= 0; $i--) { - $b = ord($x[$i]); - if (PHP_INT_SIZE === 8) { - // 3 operations - // from http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith64BitsDiv - $r .= chr((($b * 0x0202020202) & 0x010884422010) % 1023); - } else { - // 7 operations - // from http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits - $p1 = ($b * 0x0802) & 0x22110; - $p2 = ($b * 0x8020) & 0x88440; - $r .= chr( - (($p1 | $p2) * 0x10101) >> 16 - ); - } - } - return $r; - } - - /** - * Increment the current string - * - * @param string $var - * @return string - */ - public static function increment_str(&$var) - { - if (function_exists('sodium_increment')) { - $var = strrev($var); - sodium_increment($var); - $var = strrev($var); - return $var; - } - - for ($i = 4; $i <= strlen($var); $i += 4) { - $temp = substr($var, -$i, 4); - switch ($temp) { - case "\xFF\xFF\xFF\xFF": - $var = substr_replace($var, "\x00\x00\x00\x00", -$i, 4); - break; - case "\x7F\xFF\xFF\xFF": - $var = substr_replace($var, "\x80\x00\x00\x00", -$i, 4); - return $var; - default: - $temp = unpack('Nnum', $temp); - $var = substr_replace($var, pack('N', $temp['num'] + 1), -$i, 4); - return $var; - } - } - - $remainder = strlen($var) % 4; - - if ($remainder == 0) { - return $var; - } - - $temp = unpack('Nnum', str_pad(substr($var, 0, $remainder), 4, "\0", STR_PAD_LEFT)); - $temp = substr(pack('N', $temp['num'] + 1), -$remainder); - $var = substr_replace($var, $temp, 0, $remainder); - - return $var; - } - - /** - * Find whether the type of a variable is string (or could be converted to one) - * - * @param mixed $var - * @return bool - * @psalm-assert-if-true string|\Stringable $var - */ - public static function is_stringable($var) - { - return is_string($var) || (is_object($var) && method_exists($var, '__toString')); - } - - /** - * Constant Time Base64-decoding - * - * ParagoneIE\ConstantTime doesn't use libsodium if it's available so we'll do so - * ourselves. see https://github.com/paragonie/constant_time_encoding/issues/39 - * - * @param string $data - * @return string - */ - public static function base64_decode($data) - { - return function_exists('sodium_base642bin') ? - sodium_base642bin($data, SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING, '=') : - Base64::decode($data); - } - - /** - * Constant Time Base64-decoding (URL safe) - * - * @param string $data - * @return string - */ - public static function base64url_decode($data) - { - // return self::base64_decode(str_replace(['-', '_'], ['+', '/'], $data)); - - return function_exists('sodium_base642bin') ? - sodium_base642bin($data, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING, '=') : - Base64UrlSafe::decode($data); - } - - /** - * Constant Time Base64-encoding - * - * @param string $data - * @return string - */ - public static function base64_encode($data) - { - return function_exists('sodium_bin2base64') ? - sodium_bin2base64($data, SODIUM_BASE64_VARIANT_ORIGINAL) : - Base64::encode($data); - } - - /** - * Constant Time Base64-encoding (URL safe) - * - * @param string $data - * @return string - */ - public static function base64url_encode($data) - { - // return str_replace(['+', '/'], ['-', '_'], self::base64_encode($data)); - - return function_exists('sodium_bin2base64') ? - sodium_bin2base64($data, SODIUM_BASE64_VARIANT_URLSAFE) : - Base64UrlSafe::encode($data); - } - - /** - * Constant Time Hex Decoder - * - * @param string $data - * @return string - */ - public static function hex2bin($data) - { - return function_exists('sodium_hex2bin') ? - sodium_hex2bin($data) : - Hex::decode($data); - } - - /** - * Constant Time Hex Encoder - * - * @param string $data - * @return string - */ - public static function bin2hex($data) - { - return function_exists('sodium_bin2hex') ? - sodium_bin2hex($data) : - Hex::encode($data); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/AES.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/AES.php deleted file mode 100644 index 40387162..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/AES.php +++ /dev/null @@ -1,116 +0,0 @@ - - * setKey('abcdefghijklmnop'); - * - * $size = 10 * 1024; - * $plaintext = ''; - * for ($i = 0; $i < $size; $i++) { - * $plaintext.= 'a'; - * } - * - * echo $aes->decrypt($aes->encrypt($plaintext)); - * ?> - * - * - * @author Jim Wigginton - * @copyright 2008 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt; - -/** - * Pure-PHP implementation of AES. - * - * @author Jim Wigginton - */ -class AES extends Rijndael -{ - /** - * Dummy function - * - * Since \phpseclib3\Crypt\AES extends \phpseclib3\Crypt\Rijndael, this function is, technically, available, but it doesn't do anything. - * - * @see \phpseclib3\Crypt\Rijndael::setBlockLength() - * @param int $length - * @throws \BadMethodCallException anytime it's called - */ - public function setBlockLength($length) - { - throw new \BadMethodCallException('The block length cannot be set for AES.'); - } - - /** - * Sets the key length - * - * Valid key lengths are 128, 192, and 256. Set the link to bool(false) to disable a fixed key length - * - * @see \phpseclib3\Crypt\Rijndael:setKeyLength() - * @param int $length - * @throws \LengthException if the key length isn't supported - */ - public function setKeyLength($length) - { - switch ($length) { - case 128: - case 192: - case 256: - break; - default: - throw new \LengthException('Key of size ' . $length . ' not supported by this algorithm. Only keys of sizes 128, 192 or 256 supported'); - } - parent::setKeyLength($length); - } - - /** - * Sets the key. - * - * Rijndael supports five different key lengths, AES only supports three. - * - * @see \phpseclib3\Crypt\Rijndael:setKey() - * @see setKeyLength() - * @param string $key - * @throws \LengthException if the key length isn't supported - */ - public function setKey($key) - { - switch (strlen($key)) { - case 16: - case 24: - case 32: - break; - default: - throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported'); - } - - parent::setKey($key); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php deleted file mode 100644 index 12250708..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php +++ /dev/null @@ -1,918 +0,0 @@ - unpack('N*', $x), $blocks); it jumps up by an additional - * ~90MB, yielding a 106x increase in memory usage. Consequently, it bcrypt calls a different - * _encryptBlock() then the regular Blowfish does. That said, the Blowfish _encryptBlock() is - * basically just a thin wrapper around the bcrypt _encryptBlock(), so there's that. - * - * This explains 3 of the 4 _encryptBlock() implementations. the last _encryptBlock() - * implementation can best be understood by doing Ctrl + F and searching for where - * self::$use_reg_intval is defined. - * - * # phpseclib's three different _setupKey() implementations - * - * Every bcrypt round is the equivalent of encrypting 512KB of data. Since OpenSSH uses 16 - * rounds by default that's ~8MB of data that's essentially being encrypted whenever - * you use bcrypt. That's a lot of data, however, bcrypt operates within tighter constraints - * than regular Blowfish, so we can use that to our advantage. In particular, whereas Blowfish - * supports variable length keys, in bcrypt, the initial "key" is the sha512 hash of the - * password. sha512 hashes are 512 bits or 64 bytes long and thus the bcrypt keys are of a - * fixed length whereas Blowfish keys are not of a fixed length. - * - * bcrypt actually has two different key expansion steps. The first one (expandstate) is - * constantly XOR'ing every _encryptBlock() parameter against the salt prior _encryptBlock()'s - * being called. The second one (expand0state) is more similar to Blowfish's _setupKey() - * but it can still use the fixed length key optimization discussed above and can do away with - * the pack() / unpack() calls. - * - * I suppose _setupKey() could be made to be a thin wrapper around expandstate() but idk it's - * just a lot of work for very marginal benefits as _setupKey() is only called once for - * regular Blowfish vs the 128 times it's called --per round-- with bcrypt. - * - * # blowfish + bcrypt in the same class - * - * Altho there's a lot of Blowfish code that bcrypt doesn't re-use, bcrypt does re-use the - * initial S-boxes, the initial P-array and the int-only _encryptBlock() implementation. - * - * # Credit - * - * phpseclib's bcrypt implementation is based losely off of OpenSSH's implementation: - * - * https://github.com/openssh/openssh-portable/blob/master/openbsd-compat/bcrypt_pbkdf.c - * - * Here's a short example of how to use this library: - * - * setKey('12345678901234567890123456789012'); - * - * $plaintext = str_repeat('a', 1024); - * - * echo $blowfish->decrypt($blowfish->encrypt($plaintext)); - * ?> - * - * - * @author Jim Wigginton - * @author Hans-Juergen Petrich - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt; - -use phpseclib3\Crypt\Common\BlockCipher; - -/** - * Pure-PHP implementation of Blowfish. - * - * @author Jim Wigginton - * @author Hans-Juergen Petrich - */ -class Blowfish extends BlockCipher -{ - /** - * Block Length of the cipher - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::block_size - * @var int - */ - protected $block_size = 8; - - /** - * The mcrypt specific name of the cipher - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt - * @var string - */ - protected $cipher_name_mcrypt = 'blowfish'; - - /** - * Optimizing value while CFB-encrypting - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len - * @var int - */ - protected $cfb_init_len = 500; - - /** - * The fixed subkeys boxes ($sbox0 - $sbox3) with 256 entries each - * - * S-Box 0 - * - * @var array - */ - private static $sbox0 = [ - 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, - 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, - 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, - 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, - 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, - 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, - 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, - 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, - 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, - 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, - 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, - 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, - 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, - 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, - 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, - 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, - 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, - 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, - 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, - 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, - 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, - 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, - 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, - 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, - 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, - 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, - 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, - 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, - 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, - 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, - 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, - 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a - ]; - - /** - * S-Box 1 - * - * @var array - */ - private static $sbox1 = [ - 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, - 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, - 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, - 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, - 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, - 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, - 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, - 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, - 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, - 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, - 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, - 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, - 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, - 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, - 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, - 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, - 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, - 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, - 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, - 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, - 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, - 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, - 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, - 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, - 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, - 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, - 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, - 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, - 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, - 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, - 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, - 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 - ]; - - /** - * S-Box 2 - * - * @var array - */ - private static $sbox2 = [ - 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, - 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, - 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, - 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, - 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, - 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, - 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, - 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, - 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, - 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, - 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, - 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, - 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, - 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, - 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, - 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, - 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, - 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, - 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, - 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, - 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, - 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, - 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, - 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, - 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, - 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, - 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, - 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, - 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, - 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, - 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, - 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 - ]; - - /** - * S-Box 3 - * - * @var array - */ - private static $sbox3 = [ - 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, - 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, - 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, - 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, - 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, - 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, - 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, - 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, - 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, - 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, - 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, - 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, - 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, - 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, - 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, - 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, - 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, - 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, - 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, - 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, - 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, - 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, - 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, - 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, - 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, - 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, - 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, - 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, - 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, - 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, - 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, - 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 - ]; - - /** - * P-Array consists of 18 32-bit subkeys - * - * @var array - */ - private static $parray = [ - 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, - 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, - 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b - ]; - - /** - * The BCTX-working Array - * - * Holds the expanded key [p] and the key-depended s-boxes [sb] - * - * @var array - */ - private $bctx; - - /** - * Holds the last used key - * - * @var array - */ - private $kl; - - /** - * The Key Length (in bytes) - * {@internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk - * because the encryption / decryption / key schedule creation requires this number and not $key_length. We could - * derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu - * of that, we'll just precompute it once.} - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::setKeyLength() - * @var int - */ - protected $key_length = 16; - - /** - * Default Constructor. - * - * @param string $mode - * @throws \InvalidArgumentException if an invalid / unsupported mode is provided - */ - public function __construct($mode) - { - parent::__construct($mode); - - if ($this->mode == self::MODE_STREAM) { - throw new \InvalidArgumentException('Block ciphers cannot be ran in stream mode'); - } - } - - /** - * Sets the key length. - * - * Key lengths can be between 32 and 448 bits. - * - * @param int $length - */ - public function setKeyLength($length) - { - if ($length < 32 || $length > 448) { - throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes between 32 and 448 bits are supported'); - } - - $this->key_length = $length >> 3; - - parent::setKeyLength($length); - } - - /** - * Test for engine validity - * - * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine() - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine() - * @param int $engine - * @return bool - */ - protected function isValidEngineHelper($engine) - { - if ($engine == self::ENGINE_OPENSSL) { - if ($this->key_length < 16) { - return false; - } - // quoting https://www.openssl.org/news/openssl-3.0-notes.html, OpenSSL 3.0.1 - // "Moved all variations of the EVP ciphers CAST5, BF, IDEA, SEED, RC2, RC4, RC5, and DES to the legacy provider" - // in theory openssl_get_cipher_methods() should catch this but, on GitHub Actions, at least, it does not - if (defined('OPENSSL_VERSION_TEXT') && version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) { - return false; - } - $this->cipher_name_openssl_ecb = 'bf-ecb'; - $this->cipher_name_openssl = 'bf-' . $this->openssl_translate_mode(); - } - - return parent::isValidEngineHelper($engine); - } - - /** - * Setup the key (expansion) - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupKey() - */ - protected function setupKey() - { - if (isset($this->kl['key']) && $this->key === $this->kl['key']) { - // already expanded - return; - } - $this->kl = ['key' => $this->key]; - - /* key-expanding p[] and S-Box building sb[] */ - $this->bctx = [ - 'p' => [], - 'sb' => [ - self::$sbox0, - self::$sbox1, - self::$sbox2, - self::$sbox3 - ] - ]; - - // unpack binary string in unsigned chars - $key = array_values(unpack('C*', $this->key)); - $keyl = count($key); - // with bcrypt $keyl will always be 16 (because the key is the sha512 of the key you provide) - for ($j = 0, $i = 0; $i < 18; ++$i) { - // xor P1 with the first 32-bits of the key, xor P2 with the second 32-bits ... - for ($data = 0, $k = 0; $k < 4; ++$k) { - $data = ($data << 8) | $key[$j]; - if (++$j >= $keyl) { - $j = 0; - } - } - $this->bctx['p'][] = self::$parray[$i] ^ intval($data); - } - - // encrypt the zero-string, replace P1 and P2 with the encrypted data, - // encrypt P3 and P4 with the new P1 and P2, do it with all P-array and subkeys - $data = "\0\0\0\0\0\0\0\0"; - for ($i = 0; $i < 18; $i += 2) { - list($l, $r) = array_values(unpack('N*', $data = $this->encryptBlock($data))); - $this->bctx['p'][$i ] = $l; - $this->bctx['p'][$i + 1] = $r; - } - for ($i = 0; $i < 4; ++$i) { - for ($j = 0; $j < 256; $j += 2) { - list($l, $r) = array_values(unpack('N*', $data = $this->encryptBlock($data))); - $this->bctx['sb'][$i][$j ] = $l; - $this->bctx['sb'][$i][$j + 1] = $r; - } - } - } - - /** - * Initialize Static Variables - */ - protected static function initialize_static_variables() - { - if (is_float(self::$sbox2[0])) { - self::$sbox0 = array_map('intval', self::$sbox0); - self::$sbox1 = array_map('intval', self::$sbox1); - self::$sbox2 = array_map('intval', self::$sbox2); - self::$sbox3 = array_map('intval', self::$sbox3); - self::$parray = array_map('intval', self::$parray); - } - - parent::initialize_static_variables(); - } - - /** - * bcrypt - * - * @param string $sha2pass - * @param string $sha2salt - * @access private - * @return string - */ - private static function bcrypt_hash($sha2pass, $sha2salt) - { - $p = self::$parray; - $sbox0 = self::$sbox0; - $sbox1 = self::$sbox1; - $sbox2 = self::$sbox2; - $sbox3 = self::$sbox3; - - $cdata = array_values(unpack('N*', 'OxychromaticBlowfishSwatDynamite')); - $sha2pass = array_values(unpack('N*', $sha2pass)); - $sha2salt = array_values(unpack('N*', $sha2salt)); - - self::expandstate($sha2salt, $sha2pass, $sbox0, $sbox1, $sbox2, $sbox3, $p); - for ($i = 0; $i < 64; $i++) { - self::expand0state($sha2salt, $sbox0, $sbox1, $sbox2, $sbox3, $p); - self::expand0state($sha2pass, $sbox0, $sbox1, $sbox2, $sbox3, $p); - } - - for ($i = 0; $i < 64; $i++) { - for ($j = 0; $j < 8; $j += 2) { // count($cdata) == 8 - list($cdata[$j], $cdata[$j + 1]) = self::encryptBlockHelperFast($cdata[$j], $cdata[$j + 1], $sbox0, $sbox1, $sbox2, $sbox3, $p); - } - } - - return pack('L*', ...$cdata); - } - - /** - * Performs OpenSSH-style bcrypt - * - * @param string $pass - * @param string $salt - * @param int $keylen - * @param int $rounds - * @access public - * @return string - */ - public static function bcrypt_pbkdf($pass, $salt, $keylen, $rounds) - { - self::initialize_static_variables(); - - if (PHP_INT_SIZE == 4) { - throw new \RuntimeException('bcrypt is far too slow to be practical on 32-bit versions of PHP'); - } - - $sha2pass = hash('sha512', $pass, true); - $results = []; - $count = 1; - while (32 * count($results) < $keylen) { - $countsalt = $salt . pack('N', $count++); - $sha2salt = hash('sha512', $countsalt, true); - $out = $tmpout = self::bcrypt_hash($sha2pass, $sha2salt); - for ($i = 1; $i < $rounds; $i++) { - $sha2salt = hash('sha512', $tmpout, true); - $tmpout = self::bcrypt_hash($sha2pass, $sha2salt); - $out ^= $tmpout; - } - $results[] = $out; - } - $output = ''; - for ($i = 0; $i < 32; $i++) { - foreach ($results as $result) { - $output .= $result[$i]; - } - } - return substr($output, 0, $keylen); - } - - /** - * Key expansion without salt - * - * @access private - * @param int[] $key - * @param int[] $sbox0 - * @param int[] $sbox1 - * @param int[] $sbox2 - * @param int[] $sbox3 - * @param int[] $p - * @see self::_bcrypt_hash() - */ - private static function expand0state(array $key, array &$sbox0, array &$sbox1, array &$sbox2, array &$sbox3, array &$p) - { - // expand0state is basically the same thing as this: - //return self::expandstate(array_fill(0, 16, 0), $key); - // but this separate function eliminates a bunch of XORs and array lookups - - $p = [ - $p[0] ^ $key[0], - $p[1] ^ $key[1], - $p[2] ^ $key[2], - $p[3] ^ $key[3], - $p[4] ^ $key[4], - $p[5] ^ $key[5], - $p[6] ^ $key[6], - $p[7] ^ $key[7], - $p[8] ^ $key[8], - $p[9] ^ $key[9], - $p[10] ^ $key[10], - $p[11] ^ $key[11], - $p[12] ^ $key[12], - $p[13] ^ $key[13], - $p[14] ^ $key[14], - $p[15] ^ $key[15], - $p[16] ^ $key[0], - $p[17] ^ $key[1] - ]; - - // @codingStandardsIgnoreStart - list( $p[0], $p[1]) = self::encryptBlockHelperFast( 0, 0, $sbox0, $sbox1, $sbox2, $sbox3, $p); - list( $p[2], $p[3]) = self::encryptBlockHelperFast($p[ 0], $p[ 1], $sbox0, $sbox1, $sbox2, $sbox3, $p); - list( $p[4], $p[5]) = self::encryptBlockHelperFast($p[ 2], $p[ 3], $sbox0, $sbox1, $sbox2, $sbox3, $p); - list( $p[6], $p[7]) = self::encryptBlockHelperFast($p[ 4], $p[ 5], $sbox0, $sbox1, $sbox2, $sbox3, $p); - list( $p[8], $p[9]) = self::encryptBlockHelperFast($p[ 6], $p[ 7], $sbox0, $sbox1, $sbox2, $sbox3, $p); - list($p[10], $p[11]) = self::encryptBlockHelperFast($p[ 8], $p[ 9], $sbox0, $sbox1, $sbox2, $sbox3, $p); - list($p[12], $p[13]) = self::encryptBlockHelperFast($p[10], $p[11], $sbox0, $sbox1, $sbox2, $sbox3, $p); - list($p[14], $p[15]) = self::encryptBlockHelperFast($p[12], $p[13], $sbox0, $sbox1, $sbox2, $sbox3, $p); - list($p[16], $p[17]) = self::encryptBlockHelperFast($p[14], $p[15], $sbox0, $sbox1, $sbox2, $sbox3, $p); - // @codingStandardsIgnoreEnd - - list($sbox0[0], $sbox0[1]) = self::encryptBlockHelperFast($p[16], $p[17], $sbox0, $sbox1, $sbox2, $sbox3, $p); - for ($i = 2; $i < 256; $i += 2) { - list($sbox0[$i], $sbox0[$i + 1]) = self::encryptBlockHelperFast($sbox0[$i - 2], $sbox0[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p); - } - - list($sbox1[0], $sbox1[1]) = self::encryptBlockHelperFast($sbox0[254], $sbox0[255], $sbox0, $sbox1, $sbox2, $sbox3, $p); - for ($i = 2; $i < 256; $i += 2) { - list($sbox1[$i], $sbox1[$i + 1]) = self::encryptBlockHelperFast($sbox1[$i - 2], $sbox1[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p); - } - - list($sbox2[0], $sbox2[1]) = self::encryptBlockHelperFast($sbox1[254], $sbox1[255], $sbox0, $sbox1, $sbox2, $sbox3, $p); - for ($i = 2; $i < 256; $i += 2) { - list($sbox2[$i], $sbox2[$i + 1]) = self::encryptBlockHelperFast($sbox2[$i - 2], $sbox2[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p); - } - - list($sbox3[0], $sbox3[1]) = self::encryptBlockHelperFast($sbox2[254], $sbox2[255], $sbox0, $sbox1, $sbox2, $sbox3, $p); - for ($i = 2; $i < 256; $i += 2) { - list($sbox3[$i], $sbox3[$i + 1]) = self::encryptBlockHelperFast($sbox3[$i - 2], $sbox3[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p); - } - } - - /** - * Key expansion with salt - * - * @access private - * @param int[] $data - * @param int[] $key - * @param int[] $sbox0 - * @param int[] $sbox1 - * @param int[] $sbox2 - * @param int[] $sbox3 - * @param int[] $p - * @see self::_bcrypt_hash() - */ - private static function expandstate(array $data, array $key, array &$sbox0, array &$sbox1, array &$sbox2, array &$sbox3, array &$p) - { - $p = [ - $p[0] ^ $key[0], - $p[1] ^ $key[1], - $p[2] ^ $key[2], - $p[3] ^ $key[3], - $p[4] ^ $key[4], - $p[5] ^ $key[5], - $p[6] ^ $key[6], - $p[7] ^ $key[7], - $p[8] ^ $key[8], - $p[9] ^ $key[9], - $p[10] ^ $key[10], - $p[11] ^ $key[11], - $p[12] ^ $key[12], - $p[13] ^ $key[13], - $p[14] ^ $key[14], - $p[15] ^ $key[15], - $p[16] ^ $key[0], - $p[17] ^ $key[1] - ]; - - // @codingStandardsIgnoreStart - list( $p[0], $p[1]) = self::encryptBlockHelperFast($data[ 0] , $data[ 1] , $sbox0, $sbox1, $sbox2, $sbox3, $p); - list( $p[2], $p[3]) = self::encryptBlockHelperFast($data[ 2] ^ $p[ 0], $data[ 3] ^ $p[ 1], $sbox0, $sbox1, $sbox2, $sbox3, $p); - list( $p[4], $p[5]) = self::encryptBlockHelperFast($data[ 4] ^ $p[ 2], $data[ 5] ^ $p[ 3], $sbox0, $sbox1, $sbox2, $sbox3, $p); - list( $p[6], $p[7]) = self::encryptBlockHelperFast($data[ 6] ^ $p[ 4], $data[ 7] ^ $p[ 5], $sbox0, $sbox1, $sbox2, $sbox3, $p); - list( $p[8], $p[9]) = self::encryptBlockHelperFast($data[ 8] ^ $p[ 6], $data[ 9] ^ $p[ 7], $sbox0, $sbox1, $sbox2, $sbox3, $p); - list($p[10], $p[11]) = self::encryptBlockHelperFast($data[10] ^ $p[ 8], $data[11] ^ $p[ 9], $sbox0, $sbox1, $sbox2, $sbox3, $p); - list($p[12], $p[13]) = self::encryptBlockHelperFast($data[12] ^ $p[10], $data[13] ^ $p[11], $sbox0, $sbox1, $sbox2, $sbox3, $p); - list($p[14], $p[15]) = self::encryptBlockHelperFast($data[14] ^ $p[12], $data[15] ^ $p[13], $sbox0, $sbox1, $sbox2, $sbox3, $p); - list($p[16], $p[17]) = self::encryptBlockHelperFast($data[ 0] ^ $p[14], $data[ 1] ^ $p[15], $sbox0, $sbox1, $sbox2, $sbox3, $p); - // @codingStandardsIgnoreEnd - - list($sbox0[0], $sbox0[1]) = self::encryptBlockHelperFast($data[2] ^ $p[16], $data[3] ^ $p[17], $sbox0, $sbox1, $sbox2, $sbox3, $p); - for ($i = 2, $j = 4; $i < 256; $i += 2, $j = ($j + 2) % 16) { // instead of 16 maybe count($data) would be better? - list($sbox0[$i], $sbox0[$i + 1]) = self::encryptBlockHelperFast($data[$j] ^ $sbox0[$i - 2], $data[$j + 1] ^ $sbox0[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p); - } - - list($sbox1[0], $sbox1[1]) = self::encryptBlockHelperFast($data[2] ^ $sbox0[254], $data[3] ^ $sbox0[255], $sbox0, $sbox1, $sbox2, $sbox3, $p); - for ($i = 2, $j = 4; $i < 256; $i += 2, $j = ($j + 2) % 16) { - list($sbox1[$i], $sbox1[$i + 1]) = self::encryptBlockHelperFast($data[$j] ^ $sbox1[$i - 2], $data[$j + 1] ^ $sbox1[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p); - } - - list($sbox2[0], $sbox2[1]) = self::encryptBlockHelperFast($data[2] ^ $sbox1[254], $data[3] ^ $sbox1[255], $sbox0, $sbox1, $sbox2, $sbox3, $p); - for ($i = 2, $j = 4; $i < 256; $i += 2, $j = ($j + 2) % 16) { - list($sbox2[$i], $sbox2[$i + 1]) = self::encryptBlockHelperFast($data[$j] ^ $sbox2[$i - 2], $data[$j + 1] ^ $sbox2[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p); - } - - list($sbox3[0], $sbox3[1]) = self::encryptBlockHelperFast($data[2] ^ $sbox2[254], $data[3] ^ $sbox2[255], $sbox0, $sbox1, $sbox2, $sbox3, $p); - for ($i = 2, $j = 4; $i < 256; $i += 2, $j = ($j + 2) % 16) { - list($sbox3[$i], $sbox3[$i + 1]) = self::encryptBlockHelperFast($data[$j] ^ $sbox3[$i - 2], $data[$j + 1] ^ $sbox3[$i - 1], $sbox0, $sbox1, $sbox2, $sbox3, $p); - } - } - - /** - * Encrypts a block - * - * @param string $in - * @return string - */ - protected function encryptBlock($in) - { - $p = $this->bctx['p']; - // extract($this->bctx['sb'], EXTR_PREFIX_ALL, 'sb'); // slower - $sb_0 = $this->bctx['sb'][0]; - $sb_1 = $this->bctx['sb'][1]; - $sb_2 = $this->bctx['sb'][2]; - $sb_3 = $this->bctx['sb'][3]; - - $in = unpack('N*', $in); - $l = $in[1]; - $r = $in[2]; - - list($r, $l) = PHP_INT_SIZE == 4 ? - self::encryptBlockHelperSlow($l, $r, $sb_0, $sb_1, $sb_2, $sb_3, $p) : - self::encryptBlockHelperFast($l, $r, $sb_0, $sb_1, $sb_2, $sb_3, $p); - - return pack("N*", $r, $l); - } - - /** - * Fast helper function for block encryption - * - * @access private - * @param int $x0 - * @param int $x1 - * @param int[] $sbox0 - * @param int[] $sbox1 - * @param int[] $sbox2 - * @param int[] $sbox3 - * @param int[] $p - * @return int[] - */ - private static function encryptBlockHelperFast($x0, $x1, array $sbox0, array $sbox1, array $sbox2, array $sbox3, array $p) - { - $x0 ^= $p[0]; - $x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[1]; - $x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[2]; - $x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[3]; - $x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[4]; - $x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[5]; - $x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[6]; - $x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[7]; - $x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[8]; - $x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[9]; - $x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[10]; - $x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[11]; - $x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[12]; - $x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[13]; - $x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[14]; - $x1 ^= ((($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[15]; - $x0 ^= ((($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[16]; - - return [$x1 & 0xFFFFFFFF ^ $p[17], $x0 & 0xFFFFFFFF]; - } - - /** - * Slow helper function for block encryption - * - * @access private - * @param int $x0 - * @param int $x1 - * @param int[] $sbox0 - * @param int[] $sbox1 - * @param int[] $sbox2 - * @param int[] $sbox3 - * @param int[] $p - * @return int[] - */ - private static function encryptBlockHelperSlow($x0, $x1, array $sbox0, array $sbox1, array $sbox2, array $sbox3, array $p) - { - // -16777216 == intval(0xFF000000) on 32-bit PHP installs - $x0 ^= $p[0]; - $x1 ^= self::safe_intval((self::safe_intval($sbox0[(($x0 & -16777216) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[1]; - $x0 ^= self::safe_intval((self::safe_intval($sbox0[(($x1 & -16777216) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[2]; - $x1 ^= self::safe_intval((self::safe_intval($sbox0[(($x0 & -16777216) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[3]; - $x0 ^= self::safe_intval((self::safe_intval($sbox0[(($x1 & -16777216) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[4]; - $x1 ^= self::safe_intval((self::safe_intval($sbox0[(($x0 & -16777216) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[5]; - $x0 ^= self::safe_intval((self::safe_intval($sbox0[(($x1 & -16777216) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[6]; - $x1 ^= self::safe_intval((self::safe_intval($sbox0[(($x0 & -16777216) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[7]; - $x0 ^= self::safe_intval((self::safe_intval($sbox0[(($x1 & -16777216) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[8]; - $x1 ^= self::safe_intval((self::safe_intval($sbox0[(($x0 & -16777216) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[9]; - $x0 ^= self::safe_intval((self::safe_intval($sbox0[(($x1 & -16777216) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[10]; - $x1 ^= self::safe_intval((self::safe_intval($sbox0[(($x0 & -16777216) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[11]; - $x0 ^= self::safe_intval((self::safe_intval($sbox0[(($x1 & -16777216) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[12]; - $x1 ^= self::safe_intval((self::safe_intval($sbox0[(($x0 & -16777216) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[13]; - $x0 ^= self::safe_intval((self::safe_intval($sbox0[(($x1 & -16777216) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[14]; - $x1 ^= self::safe_intval((self::safe_intval($sbox0[(($x0 & -16777216) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[15]; - $x0 ^= self::safe_intval((self::safe_intval($sbox0[(($x1 & -16777216) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[16]; - - return [$x1 ^ $p[17], $x0]; - } - - /** - * Decrypts a block - * - * @param string $in - * @return string - */ - protected function decryptBlock($in) - { - $p = $this->bctx['p']; - $sb_0 = $this->bctx['sb'][0]; - $sb_1 = $this->bctx['sb'][1]; - $sb_2 = $this->bctx['sb'][2]; - $sb_3 = $this->bctx['sb'][3]; - - $in = unpack('N*', $in); - $l = $in[1]; - $r = $in[2]; - - for ($i = 17; $i > 2; $i -= 2) { - $l ^= $p[$i]; - $r ^= self::safe_intval((self::safe_intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^ - $sb_2[$l >> 8 & 0xff]) + - $sb_3[$l & 0xff]); - - $r ^= $p[$i - 1]; - $l ^= self::safe_intval((self::safe_intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^ - $sb_2[$r >> 8 & 0xff]) + - $sb_3[$r & 0xff]); - } - return pack('N*', $r ^ $p[0], $l ^ $p[1]); - } - - /** - * Setup the performance-optimized function for de/encrypt() - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupInlineCrypt() - */ - protected function setupInlineCrypt() - { - $p = $this->bctx['p']; - $init_crypt = ' - static $sb_0, $sb_1, $sb_2, $sb_3; - if (!$sb_0) { - $sb_0 = $this->bctx["sb"][0]; - $sb_1 = $this->bctx["sb"][1]; - $sb_2 = $this->bctx["sb"][2]; - $sb_3 = $this->bctx["sb"][3]; - } - '; - - $safeint = self::safe_intval_inline(); - - // Generating encrypt code: - $encrypt_block = ' - $in = unpack("N*", $in); - $l = $in[1]; - $r = $in[2]; - '; - for ($i = 0; $i < 16; $i += 2) { - $encrypt_block .= ' - $l^= ' . $p[$i] . '; - $r^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]') . ' ^ - $sb_2[$l >> 8 & 0xff]) + - $sb_3[$l & 0xff]') . '; - - $r^= ' . $p[$i + 1] . '; - $l^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]') . ' ^ - $sb_2[$r >> 8 & 0xff]) + - $sb_3[$r & 0xff]') . '; - '; - } - $encrypt_block .= ' - $in = pack("N*", - $r ^ ' . $p[17] . ', - $l ^ ' . $p[16] . ' - ); - '; - // Generating decrypt code: - $decrypt_block = ' - $in = unpack("N*", $in); - $l = $in[1]; - $r = $in[2]; - '; - - for ($i = 17; $i > 2; $i -= 2) { - $decrypt_block .= ' - $l^= ' . $p[$i] . '; - $r^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]') . ' ^ - $sb_2[$l >> 8 & 0xff]) + - $sb_3[$l & 0xff]') . '; - - $r^= ' . $p[$i - 1] . '; - $l^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]') . ' ^ - $sb_2[$r >> 8 & 0xff]) + - $sb_3[$r & 0xff]') . '; - '; - } - - $decrypt_block .= ' - $in = pack("N*", - $r ^ ' . $p[0] . ', - $l ^ ' . $p[1] . ' - ); - '; - - $this->inline_crypt = $this->createInlineCryptFunction( - [ - 'init_crypt' => $init_crypt, - 'init_encrypt' => '', - 'init_decrypt' => '', - 'encrypt_block' => $encrypt_block, - 'decrypt_block' => $decrypt_block - ] - ); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/ChaCha20.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/ChaCha20.php deleted file mode 100644 index b2691b5d..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/ChaCha20.php +++ /dev/null @@ -1,799 +0,0 @@ - - * @copyright 2019 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt; - -use phpseclib3\Exception\BadDecryptionException; -use phpseclib3\Exception\InsufficientSetupException; - -/** - * Pure-PHP implementation of ChaCha20. - * - * @author Jim Wigginton - */ -class ChaCha20 extends Salsa20 -{ - /** - * The OpenSSL specific name of the cipher - * - * @var string - */ - protected $cipher_name_openssl = 'chacha20'; - - /** - * Test for engine validity - * - * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine() - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() - * @param int $engine - * @return bool - */ - protected function isValidEngineHelper($engine) - { - switch ($engine) { - case self::ENGINE_LIBSODIUM: - // PHP 7.2.0 (30 Nov 2017) added support for libsodium - - // we could probably make it so that if $this->counter == 0 then the first block would be done with either OpenSSL - // or PHP and then subsequent blocks would then be done with libsodium but idk - it's not a high priority atm - - // we could also make it so that if $this->counter == 0 and $this->continuousBuffer then do the first string - // with libsodium and subsequent strings with openssl or pure-PHP but again not a high priority - return function_exists('sodium_crypto_aead_chacha20poly1305_ietf_encrypt') && - $this->key_length == 32 && - (($this->usePoly1305 && !isset($this->poly1305Key) && $this->counter == 0) || $this->counter == 1) && - !$this->continuousBuffer; - case self::ENGINE_OPENSSL: - // OpenSSL 1.1.0 (released 25 Aug 2016) added support for chacha20. - // PHP didn't support OpenSSL 1.1.0 until 7.0.19 (11 May 2017) - - // if you attempt to provide openssl with a 128 bit key (as opposed to a 256 bit key) openssl will null - // pad the key to 256 bits and still use the expansion constant for 256-bit keys. the fact that - // openssl treats the IV as both the counter and nonce, however, let's us use openssl in continuous mode - // whereas libsodium does not - if ($this->key_length != 32) { - return false; - } - } - - return parent::isValidEngineHelper($engine); - } - - /** - * Encrypts a message. - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() - * @see self::crypt() - * @param string $plaintext - * @return string $ciphertext - */ - public function encrypt($plaintext) - { - $this->setup(); - - if ($this->engine == self::ENGINE_LIBSODIUM) { - return $this->encrypt_with_libsodium($plaintext); - } - - return parent::encrypt($plaintext); - } - - /** - * Decrypts a message. - * - * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)). - * At least if the continuous buffer is disabled. - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @see self::crypt() - * @param string $ciphertext - * @return string $plaintext - */ - public function decrypt($ciphertext) - { - $this->setup(); - - if ($this->engine == self::ENGINE_LIBSODIUM) { - return $this->decrypt_with_libsodium($ciphertext); - } - - return parent::decrypt($ciphertext); - } - - /** - * Encrypts a message with libsodium - * - * @see self::encrypt() - * @param string $plaintext - * @return string $text - */ - private function encrypt_with_libsodium($plaintext) - { - $params = [$plaintext, $this->aad, $this->nonce, $this->key]; - $ciphertext = strlen($this->nonce) == 8 ? - sodium_crypto_aead_chacha20poly1305_encrypt(...$params) : - sodium_crypto_aead_chacha20poly1305_ietf_encrypt(...$params); - if (!$this->usePoly1305) { - return substr($ciphertext, 0, strlen($plaintext)); - } - - $newciphertext = substr($ciphertext, 0, strlen($plaintext)); - - $this->newtag = $this->usingGeneratedPoly1305Key && strlen($this->nonce) == 12 ? - substr($ciphertext, strlen($plaintext)) : - $this->poly1305($newciphertext); - - return $newciphertext; - } - - /** - * Decrypts a message with libsodium - * - * @see self::decrypt() - * @param string $ciphertext - * @return string $text - */ - private function decrypt_with_libsodium($ciphertext) - { - $params = [$ciphertext, $this->aad, $this->nonce, $this->key]; - - if (isset($this->poly1305Key)) { - if ($this->oldtag === false) { - throw new InsufficientSetupException('Authentication Tag has not been set'); - } - if ($this->usingGeneratedPoly1305Key && strlen($this->nonce) == 12) { - $plaintext = sodium_crypto_aead_chacha20poly1305_ietf_decrypt(...$params); - $this->oldtag = false; - if ($plaintext === false) { - throw new BadDecryptionException('Derived authentication tag and supplied authentication tag do not match'); - } - return $plaintext; - } - $newtag = $this->poly1305($ciphertext); - if ($this->oldtag != substr($newtag, 0, strlen($this->oldtag))) { - $this->oldtag = false; - throw new BadDecryptionException('Derived authentication tag and supplied authentication tag do not match'); - } - $this->oldtag = false; - } - - $plaintext = strlen($this->nonce) == 8 ? - sodium_crypto_aead_chacha20poly1305_encrypt(...$params) : - sodium_crypto_aead_chacha20poly1305_ietf_encrypt(...$params); - - return substr($plaintext, 0, strlen($ciphertext)); - } - - /** - * Sets the nonce. - * - * @param string $nonce - */ - public function setNonce($nonce) - { - if (!is_string($nonce)) { - throw new \UnexpectedValueException('The nonce should be a string'); - } - - /* - from https://tools.ietf.org/html/rfc7539#page-7 - - "Note also that the original ChaCha had a 64-bit nonce and 64-bit - block count. We have modified this here to be more consistent with - recommendations in Section 3.2 of [RFC5116]." - */ - switch (strlen($nonce)) { - case 8: // 64 bits - case 12: // 96 bits - break; - default: - throw new \LengthException('Nonce of size ' . strlen($nonce) . ' not supported by this algorithm. Only 64-bit nonces or 96-bit nonces are supported'); - } - - $this->nonce = $nonce; - $this->changed = true; - $this->setEngine(); - } - - /** - * Setup the self::ENGINE_INTERNAL $engine - * - * (re)init, if necessary, the internal cipher $engine - * - * _setup() will be called each time if $changed === true - * typically this happens when using one or more of following public methods: - * - * - setKey() - * - * - setNonce() - * - * - First run of encrypt() / decrypt() with no init-settings - * - * @see self::setKey() - * @see self::setNonce() - * @see self::disableContinuousBuffer() - */ - protected function setup() - { - if (!$this->changed) { - return; - } - - $this->enbuffer = $this->debuffer = ['ciphertext' => '', 'counter' => $this->counter]; - - $this->changed = $this->nonIVChanged = false; - - if ($this->nonce === false) { - throw new InsufficientSetupException('No nonce has been defined'); - } - - if ($this->key === false) { - throw new InsufficientSetupException('No key has been defined'); - } - - if ($this->usePoly1305 && !isset($this->poly1305Key)) { - $this->usingGeneratedPoly1305Key = true; - if ($this->engine == self::ENGINE_LIBSODIUM) { - return; - } - $this->createPoly1305Key(); - } - - $key = $this->key; - if (strlen($key) == 16) { - $constant = 'expand 16-byte k'; - $key .= $key; - } else { - $constant = 'expand 32-byte k'; - } - - $this->p1 = $constant . $key; - $this->p2 = $this->nonce; - if (strlen($this->nonce) == 8) { - $this->p2 = "\0\0\0\0" . $this->p2; - } - } - - /** - * The quarterround function - * - * @param int $a - * @param int $b - * @param int $c - * @param int $d - */ - protected static function quarterRound(&$a, &$b, &$c, &$d) - { - // in https://datatracker.ietf.org/doc/html/rfc7539#section-2.1 the addition, - // xor'ing and rotation are all on the same line so i'm keeping it on the same - // line here as well - // @codingStandardsIgnoreStart - $a+= $b; $d = self::leftRotate(intval($d) ^ intval($a), 16); - $c+= $d; $b = self::leftRotate(intval($b) ^ intval($c), 12); - $a+= $b; $d = self::leftRotate(intval($d) ^ intval($a), 8); - $c+= $d; $b = self::leftRotate(intval($b) ^ intval($c), 7); - // @codingStandardsIgnoreEnd - } - - /** - * The doubleround function - * - * @param int $x0 (by reference) - * @param int $x1 (by reference) - * @param int $x2 (by reference) - * @param int $x3 (by reference) - * @param int $x4 (by reference) - * @param int $x5 (by reference) - * @param int $x6 (by reference) - * @param int $x7 (by reference) - * @param int $x8 (by reference) - * @param int $x9 (by reference) - * @param int $x10 (by reference) - * @param int $x11 (by reference) - * @param int $x12 (by reference) - * @param int $x13 (by reference) - * @param int $x14 (by reference) - * @param int $x15 (by reference) - */ - protected static function doubleRound(&$x0, &$x1, &$x2, &$x3, &$x4, &$x5, &$x6, &$x7, &$x8, &$x9, &$x10, &$x11, &$x12, &$x13, &$x14, &$x15) - { - // columnRound - static::quarterRound($x0, $x4, $x8, $x12); - static::quarterRound($x1, $x5, $x9, $x13); - static::quarterRound($x2, $x6, $x10, $x14); - static::quarterRound($x3, $x7, $x11, $x15); - // rowRound - static::quarterRound($x0, $x5, $x10, $x15); - static::quarterRound($x1, $x6, $x11, $x12); - static::quarterRound($x2, $x7, $x8, $x13); - static::quarterRound($x3, $x4, $x9, $x14); - } - - /** - * The Salsa20 hash function function - * - * On my laptop this loop unrolled / function dereferenced version of parent::salsa20 encrypts 1mb of text in - * 0.65s vs the 0.85s that it takes with the parent method. - * - * If we were free to assume that the host OS would always be 64-bits then the if condition in leftRotate could - * be eliminated and we could knock this done to 0.60s. - * - * For comparison purposes, RC4 takes 0.16s and AES in CTR mode with the Eval engine takes 0.48s. - * AES in CTR mode with the PHP engine takes 1.19s. Salsa20 / ChaCha20 do not benefit as much from the Eval - * approach due to the fact that there are a lot less variables to de-reference, fewer loops to unroll, etc - * - * @param string $x - */ - protected static function salsa20($x) - { - list(, $x0, $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15) = unpack('V*', $x); - $z0 = $x0; - $z1 = $x1; - $z2 = $x2; - $z3 = $x3; - $z4 = $x4; - $z5 = $x5; - $z6 = $x6; - $z7 = $x7; - $z8 = $x8; - $z9 = $x9; - $z10 = $x10; - $z11 = $x11; - $z12 = $x12; - $z13 = $x13; - $z14 = $x14; - $z15 = $x15; - - // @codingStandardsIgnoreStart - // columnRound - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12); - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7); - - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7); - - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7); - - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7); - - // rowRound - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12); - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7); - - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7); - - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7); - - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7); - - // columnRound - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12); - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7); - - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7); - - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7); - - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7); - - // rowRound - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12); - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7); - - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7); - - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7); - - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7); - - // columnRound - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12); - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7); - - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7); - - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7); - - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7); - - // rowRound - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12); - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7); - - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7); - - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7); - - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7); - - // columnRound - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12); - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7); - - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7); - - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7); - - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7); - - // rowRound - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12); - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7); - - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7); - - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7); - - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7); - - // columnRound - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12); - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7); - - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7); - - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7); - - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7); - - // rowRound - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12); - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7); - - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7); - - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7); - - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7); - - // columnRound - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12); - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7); - - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7); - - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7); - - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7); - - // rowRound - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12); - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7); - - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7); - - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7); - - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7); - - // columnRound - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12); - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7); - - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7); - - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7); - - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7); - - // rowRound - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12); - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7); - - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7); - - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7); - - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7); - - // columnRound - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12); - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7); - - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7); - - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7); - - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7); - - // rowRound - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12); - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7); - - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7); - - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7); - - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7); - - // columnRound - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12); - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7); - - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7); - - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7); - - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7); - - // rowRound - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12); - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7); - - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7); - - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7); - - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7); - - // columnRound - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12); - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7); - - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7); - - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7); - - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7); - - // rowRound - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12); - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7); - - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7); - - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7); - - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7); - // @codingStandardsIgnoreEnd - - $x0 += $z0; - $x1 += $z1; - $x2 += $z2; - $x3 += $z3; - $x4 += $z4; - $x5 += $z5; - $x6 += $z6; - $x7 += $z7; - $x8 += $z8; - $x9 += $z9; - $x10 += $z10; - $x11 += $z11; - $x12 += $z12; - $x13 += $z13; - $x14 += $z14; - $x15 += $z15; - - return pack('V*', $x0, $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/AsymmetricKey.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/AsymmetricKey.php deleted file mode 100644 index 407f0369..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/AsymmetricKey.php +++ /dev/null @@ -1,581 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\Common; - -use phpseclib3\Crypt\DSA; -use phpseclib3\Crypt\Hash; -use phpseclib3\Crypt\RSA; -use phpseclib3\Exception\NoKeyLoadedException; -use phpseclib3\Exception\UnsupportedFormatException; -use phpseclib3\Math\BigInteger; - -/** - * Base Class for all asymmetric cipher classes - * - * @author Jim Wigginton - */ -abstract class AsymmetricKey -{ - /** - * Precomputed Zero - * - * @var \phpseclib3\Math\BigInteger - */ - protected static $zero; - - /** - * Precomputed One - * - * @var \phpseclib3\Math\BigInteger - */ - protected static $one; - - /** - * Format of the loaded key - * - * @var string - */ - protected $format; - - /** - * Hash function - * - * @var \phpseclib3\Crypt\Hash - */ - protected $hash; - - /** - * HMAC function - * - * @var \phpseclib3\Crypt\Hash - */ - private $hmac; - - /** - * Supported plugins (lower case) - * - * @see self::initialize_static_variables() - * @var array - */ - private static $plugins = []; - - /** - * Invisible plugins - * - * @see self::initialize_static_variables() - * @var array - */ - private static $invisiblePlugins = []; - - /** - * Available Engines - * - * @var boolean[] - */ - protected static $engines = []; - - /** - * Key Comment - * - * @var null|string - */ - private $comment; - - /** - * @param string $type - * @return string - */ - abstract public function toString($type, array $options = []); - - /** - * The constructor - */ - protected function __construct() - { - self::initialize_static_variables(); - - $this->hash = new Hash('sha256'); - $this->hmac = new Hash('sha256'); - } - - /** - * Initialize static variables - */ - protected static function initialize_static_variables() - { - if (!isset(self::$zero)) { - self::$zero = new BigInteger(0); - self::$one = new BigInteger(1); - } - - self::loadPlugins('Keys'); - if (static::ALGORITHM != 'RSA' && static::ALGORITHM != 'DH') { - self::loadPlugins('Signature'); - } - } - - /** - * Load the key - * - * @param string $key - * @param string $password optional - * @return AsymmetricKey - */ - public static function load($key, $password = false) - { - self::initialize_static_variables(); - - $class = new \ReflectionClass(static::class); - if ($class->isFinal()) { - throw new \RuntimeException('load() should not be called from final classes (' . static::class . ')'); - } - - $components = false; - foreach (self::$plugins[static::ALGORITHM]['Keys'] as $format) { - if (isset(self::$invisiblePlugins[static::ALGORITHM]) && in_array($format, self::$invisiblePlugins[static::ALGORITHM])) { - continue; - } - try { - $components = $format::load($key, $password); - } catch (\Exception $e) { - $components = false; - } - if ($components !== false) { - break; - } - } - - if ($components === false) { - throw new NoKeyLoadedException('Unable to read key'); - } - - $components['format'] = $format; - $components['secret'] = isset($components['secret']) ? $components['secret'] : ''; - $comment = isset($components['comment']) ? $components['comment'] : null; - $new = static::onLoad($components); - $new->format = $format; - $new->comment = $comment; - return $new instanceof PrivateKey ? - $new->withPassword($password) : - $new; - } - - /** - * Loads a private key - * - * @return PrivateKey - * @param string|array $key - * @param string $password optional - */ - public static function loadPrivateKey($key, $password = '') - { - $key = self::load($key, $password); - if (!$key instanceof PrivateKey) { - throw new NoKeyLoadedException('The key that was loaded was not a private key'); - } - return $key; - } - - /** - * Loads a public key - * - * @return PublicKey - * @param string|array $key - */ - public static function loadPublicKey($key) - { - $key = self::load($key); - if (!$key instanceof PublicKey) { - throw new NoKeyLoadedException('The key that was loaded was not a public key'); - } - return $key; - } - - /** - * Loads parameters - * - * @return AsymmetricKey - * @param string|array $key - */ - public static function loadParameters($key) - { - $key = self::load($key); - if (!$key instanceof PrivateKey && !$key instanceof PublicKey) { - throw new NoKeyLoadedException('The key that was loaded was not a parameter'); - } - return $key; - } - - /** - * Load the key, assuming a specific format - * - * @param string $type - * @param string $key - * @param string $password optional - * @return static - */ - public static function loadFormat($type, $key, $password = false) - { - self::initialize_static_variables(); - - $components = false; - $format = strtolower($type); - if (isset(self::$plugins[static::ALGORITHM]['Keys'][$format])) { - $format = self::$plugins[static::ALGORITHM]['Keys'][$format]; - $components = $format::load($key, $password); - } - - if ($components === false) { - throw new NoKeyLoadedException('Unable to read key'); - } - - $components['format'] = $format; - $components['secret'] = isset($components['secret']) ? $components['secret'] : ''; - - $new = static::onLoad($components); - $new->format = $format; - return $new instanceof PrivateKey ? - $new->withPassword($password) : - $new; - } - - /** - * Loads a private key - * - * @return PrivateKey - * @param string $type - * @param string $key - * @param string $password optional - */ - public static function loadPrivateKeyFormat($type, $key, $password = false) - { - $key = self::loadFormat($type, $key, $password); - if (!$key instanceof PrivateKey) { - throw new NoKeyLoadedException('The key that was loaded was not a private key'); - } - return $key; - } - - /** - * Loads a public key - * - * @return PublicKey - * @param string $type - * @param string $key - */ - public static function loadPublicKeyFormat($type, $key) - { - $key = self::loadFormat($type, $key); - if (!$key instanceof PublicKey) { - throw new NoKeyLoadedException('The key that was loaded was not a public key'); - } - return $key; - } - - /** - * Loads parameters - * - * @return AsymmetricKey - * @param string $type - * @param string|array $key - */ - public static function loadParametersFormat($type, $key) - { - $key = self::loadFormat($type, $key); - if (!$key instanceof PrivateKey && !$key instanceof PublicKey) { - throw new NoKeyLoadedException('The key that was loaded was not a parameter'); - } - return $key; - } - - /** - * Validate Plugin - * - * @param string $format - * @param string $type - * @param string $method optional - * @return mixed - */ - protected static function validatePlugin($format, $type, $method = null) - { - $type = strtolower($type); - if (!isset(self::$plugins[static::ALGORITHM][$format][$type])) { - throw new UnsupportedFormatException("$type is not a supported format"); - } - $type = self::$plugins[static::ALGORITHM][$format][$type]; - if (isset($method) && !method_exists($type, $method)) { - throw new UnsupportedFormatException("$type does not implement $method"); - } - - return $type; - } - - /** - * Load Plugins - * - * @param string $format - */ - private static function loadPlugins($format) - { - if (!isset(self::$plugins[static::ALGORITHM][$format])) { - self::$plugins[static::ALGORITHM][$format] = []; - foreach (new \DirectoryIterator(__DIR__ . '/../' . static::ALGORITHM . '/Formats/' . $format . '/') as $file) { - if ($file->getExtension() != 'php') { - continue; - } - $name = $file->getBasename('.php'); - if ($name[0] == '.') { - continue; - } - $type = 'phpseclib3\Crypt\\' . static::ALGORITHM . '\\Formats\\' . $format . '\\' . $name; - $reflect = new \ReflectionClass($type); - if ($reflect->isTrait()) { - continue; - } - self::$plugins[static::ALGORITHM][$format][strtolower($name)] = $type; - if ($reflect->hasConstant('IS_INVISIBLE')) { - self::$invisiblePlugins[static::ALGORITHM][] = $type; - } - } - } - } - - /** - * Returns a list of supported formats. - * - * @return array - */ - public static function getSupportedKeyFormats() - { - self::initialize_static_variables(); - - return self::$plugins[static::ALGORITHM]['Keys']; - } - - /** - * Add a fileformat plugin - * - * The plugin needs to either already be loaded or be auto-loadable. - * Loading a plugin whose shortname overwrite an existing shortname will overwrite the old plugin. - * - * @see self::load() - * @param string $fullname - * @return bool - */ - public static function addFileFormat($fullname) - { - self::initialize_static_variables(); - - if (class_exists($fullname)) { - $meta = new \ReflectionClass($fullname); - $shortname = $meta->getShortName(); - self::$plugins[static::ALGORITHM]['Keys'][strtolower($shortname)] = $fullname; - if ($meta->hasConstant('IS_INVISIBLE')) { - self::$invisiblePlugins[static::ALGORITHM] = strtolower($name); - } - } - } - - /** - * Returns the format of the loaded key. - * - * If the key that was loaded wasn't in a valid or if the key was auto-generated - * with RSA::createKey() then this will throw an exception. - * - * @see self::load() - * @return mixed - */ - public function getLoadedFormat() - { - if (empty($this->format)) { - throw new NoKeyLoadedException('This key was created with createKey - it was not loaded with load. Therefore there is no "loaded format"'); - } - - $meta = new \ReflectionClass($this->format); - return $meta->getShortName(); - } - - /** - * Returns the key's comment - * - * Not all key formats support comments. If you want to set a comment use toString() - * - * @return null|string - */ - public function getComment() - { - return $this->comment; - } - - /** - * Tests engine validity - * - */ - public static function useBestEngine() - { - static::$engines = [ - 'PHP' => true, - 'OpenSSL' => extension_loaded('openssl'), - // this test can be satisfied by either of the following: - // http://php.net/manual/en/book.sodium.php - // https://github.com/paragonie/sodium_compat - 'libsodium' => function_exists('sodium_crypto_sign_keypair') - ]; - - return static::$engines; - } - - /** - * Flag to use internal engine only (useful for unit testing) - * - */ - public static function useInternalEngine() - { - static::$engines = [ - 'PHP' => true, - 'OpenSSL' => false, - 'libsodium' => false - ]; - } - - /** - * __toString() magic method - * - * @return string - */ - public function __toString() - { - return $this->toString('PKCS8'); - } - - /** - * Determines which hashing function should be used - * - * @param string $hash - */ - public function withHash($hash) - { - $new = clone $this; - - $new->hash = new Hash($hash); - $new->hmac = new Hash($hash); - - return $new; - } - - /** - * Returns the hash algorithm currently being used - * - */ - public function getHash() - { - return clone $this->hash; - } - - /** - * Compute the pseudorandom k for signature generation, - * using the process specified for deterministic DSA. - * - * @param string $h1 - * @return string - */ - protected function computek($h1) - { - $v = str_repeat("\1", strlen($h1)); - - $k = str_repeat("\0", strlen($h1)); - - $x = $this->int2octets($this->x); - $h1 = $this->bits2octets($h1); - - $this->hmac->setKey($k); - $k = $this->hmac->hash($v . "\0" . $x . $h1); - $this->hmac->setKey($k); - $v = $this->hmac->hash($v); - $k = $this->hmac->hash($v . "\1" . $x . $h1); - $this->hmac->setKey($k); - $v = $this->hmac->hash($v); - - $qlen = $this->q->getLengthInBytes(); - - while (true) { - $t = ''; - while (strlen($t) < $qlen) { - $v = $this->hmac->hash($v); - $t = $t . $v; - } - $k = $this->bits2int($t); - - if (!$k->equals(self::$zero) && $k->compare($this->q) < 0) { - break; - } - $k = $this->hmac->hash($v . "\0"); - $this->hmac->setKey($k); - $v = $this->hmac->hash($v); - } - - return $k; - } - - /** - * Integer to Octet String - * - * @param \phpseclib3\Math\BigInteger $v - * @return string - */ - private function int2octets($v) - { - $out = $v->toBytes(); - $rolen = $this->q->getLengthInBytes(); - if (strlen($out) < $rolen) { - return str_pad($out, $rolen, "\0", STR_PAD_LEFT); - } elseif (strlen($out) > $rolen) { - return substr($out, -$rolen); - } else { - return $out; - } - } - - /** - * Bit String to Integer - * - * @param string $in - * @return \phpseclib3\Math\BigInteger - */ - protected function bits2int($in) - { - $v = new BigInteger($in, 256); - $vlen = strlen($in) << 3; - $qlen = $this->q->getLength(); - if ($vlen > $qlen) { - return $v->bitwise_rightShift($vlen - $qlen); - } - return $v; - } - - /** - * Bit String to Octet String - * - * @param string $in - * @return string - */ - private function bits2octets($in) - { - $z1 = $this->bits2int($in); - $z2 = $z1->subtract($this->q); - return $z2->compare(self::$zero) < 0 ? - $this->int2octets($z1) : - $this->int2octets($z2); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/BlockCipher.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/BlockCipher.php deleted file mode 100644 index b2642be1..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/BlockCipher.php +++ /dev/null @@ -1,24 +0,0 @@ - - * @author Hans-Juergen Petrich - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\Common; - -/** - * Base Class for all block cipher classes - * - * @author Jim Wigginton - */ -abstract class BlockCipher extends SymmetricKey -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/JWK.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/JWK.php deleted file mode 100644 index 4c761b83..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/JWK.php +++ /dev/null @@ -1,69 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\Common\Formats\Keys; - -use phpseclib3\Common\Functions\Strings; - -/** - * JSON Web Key Formatted Key Handler - * - * @author Jim Wigginton - */ -abstract class JWK -{ - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password - * @return array - */ - public static function load($key, $password = '') - { - if (!Strings::is_stringable($key)) { - throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key)); - } - - $key = preg_replace('#\s#', '', $key); // remove whitespace - - if (PHP_VERSION_ID >= 73000) { - $key = json_decode($key, null, 512, JSON_THROW_ON_ERROR); - } else { - $key = json_decode($key); - if (!$key) { - throw new \RuntimeException('Unable to decode JSON'); - } - } - - if (isset($key->kty)) { - return $key; - } - - if (count($key->keys) != 1) { - throw new \RuntimeException('Although the JWK key format supports multiple keys phpseclib does not'); - } - - return $key->keys[0]; - } - - /** - * Wrap a key appropriately - * - * @return string - */ - protected static function wrapKey(array $key, array $options) - { - return json_encode(['keys' => [$key + $options]]); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/OpenSSH.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/OpenSSH.php deleted file mode 100644 index fe3d85bd..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/OpenSSH.php +++ /dev/null @@ -1,220 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\Common\Formats\Keys; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\AES; -use phpseclib3\Crypt\Random; - -/** - * OpenSSH Formatted RSA Key Handler - * - * @author Jim Wigginton - */ -abstract class OpenSSH -{ - /** - * Default comment - * - * @var string - */ - protected static $comment = 'phpseclib-generated-key'; - - /** - * Binary key flag - * - * @var bool - */ - protected static $binary = false; - - /** - * Sets the default comment - * - * @param string $comment - */ - public static function setComment($comment) - { - self::$comment = str_replace(["\r", "\n"], '', $comment); - } - - /** - * Break a public or private key down into its constituent components - * - * $type can be either ssh-dss or ssh-rsa - * - * @param string $key - * @param string $password - * @return array - */ - public static function load($key, $password = '') - { - if (!Strings::is_stringable($key)) { - throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key)); - } - - // key format is described here: - // https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.key?annotate=HEAD - - if (strpos($key, 'BEGIN OPENSSH PRIVATE KEY') !== false) { - $key = preg_replace('#(?:^-.*?-[\r\n]*$)|\s#ms', '', $key); - $key = Strings::base64_decode($key); - $magic = Strings::shift($key, 15); - if ($magic != "openssh-key-v1\0") { - throw new \RuntimeException('Expected openssh-key-v1'); - } - list($ciphername, $kdfname, $kdfoptions, $numKeys) = Strings::unpackSSH2('sssN', $key); - if ($numKeys != 1) { - // if we wanted to support multiple keys we could update PublicKeyLoader to preview what the # of keys - // would be; it'd then call Common\Keys\OpenSSH.php::load() and get the paddedKey. it'd then pass - // that to the appropriate key loading parser $numKey times or something - throw new \RuntimeException('Although the OpenSSH private key format supports multiple keys phpseclib does not'); - } - switch ($ciphername) { - case 'none': - break; - case 'aes256-ctr': - if ($kdfname != 'bcrypt') { - throw new \RuntimeException('Only the bcrypt kdf is supported (' . $kdfname . ' encountered)'); - } - list($salt, $rounds) = Strings::unpackSSH2('sN', $kdfoptions); - $crypto = new AES('ctr'); - //$crypto->setKeyLength(256); - //$crypto->disablePadding(); - $crypto->setPassword($password, 'bcrypt', $salt, $rounds, 32); - break; - default: - throw new \RuntimeException('The only supported cipherse are: none, aes256-ctr (' . $ciphername . ' is being used)'); - } - - list($publicKey, $paddedKey) = Strings::unpackSSH2('ss', $key); - list($type) = Strings::unpackSSH2('s', $publicKey); - if (isset($crypto)) { - $paddedKey = $crypto->decrypt($paddedKey); - } - list($checkint1, $checkint2) = Strings::unpackSSH2('NN', $paddedKey); - // any leftover bytes in $paddedKey are for padding? but they should be sequential bytes. eg. 1, 2, 3, etc. - if ($checkint1 != $checkint2) { - throw new \RuntimeException('The two checkints do not match'); - } - self::checkType($type); - - return compact('type', 'publicKey', 'paddedKey'); - } - - $parts = explode(' ', $key, 3); - - if (!isset($parts[1])) { - $key = base64_decode($parts[0]); - $comment = false; - } else { - $asciiType = $parts[0]; - self::checkType($parts[0]); - $key = base64_decode($parts[1]); - $comment = isset($parts[2]) ? $parts[2] : false; - } - if ($key === false) { - throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key)); - } - - list($type) = Strings::unpackSSH2('s', $key); - self::checkType($type); - if (isset($asciiType) && $asciiType != $type) { - throw new \RuntimeException('Two different types of keys are claimed: ' . $asciiType . ' and ' . $type); - } - if (strlen($key) <= 4) { - throw new \UnexpectedValueException('Key appears to be malformed'); - } - - $publicKey = $key; - - return compact('type', 'publicKey', 'comment'); - } - - /** - * Toggle between binary and printable keys - * - * Printable keys are what are generated by default. These are the ones that go in - * $HOME/.ssh/authorized_key. - * - * @param bool $enabled - */ - public static function setBinaryOutput($enabled) - { - self::$binary = $enabled; - } - - /** - * Checks to see if the type is valid - * - * @param string $candidate - */ - private static function checkType($candidate) - { - if (!in_array($candidate, static::$types)) { - throw new \RuntimeException("The key type ($candidate) is not equal to: " . implode(',', static::$types)); - } - } - - /** - * Wrap a private key appropriately - * - * @param string $publicKey - * @param string $privateKey - * @param string $password - * @param array $options - * @return string - */ - protected static function wrapPrivateKey($publicKey, $privateKey, $password, $options) - { - list(, $checkint) = unpack('N', Random::string(4)); - - $comment = isset($options['comment']) ? $options['comment'] : self::$comment; - $paddedKey = Strings::packSSH2('NN', $checkint, $checkint) . - $privateKey . - Strings::packSSH2('s', $comment); - - $usesEncryption = !empty($password) && is_string($password); - - /* - from http://tools.ietf.org/html/rfc4253#section-6 : - - Note that the length of the concatenation of 'packet_length', - 'padding_length', 'payload', and 'random padding' MUST be a multiple - of the cipher block size or 8, whichever is larger. - */ - $blockSize = $usesEncryption ? 16 : 8; - $paddingLength = (($blockSize - 1) * strlen($paddedKey)) % $blockSize; - for ($i = 1; $i <= $paddingLength; $i++) { - $paddedKey .= chr($i); - } - if (!$usesEncryption) { - $key = Strings::packSSH2('sssNss', 'none', 'none', '', 1, $publicKey, $paddedKey); - } else { - $rounds = isset($options['rounds']) ? $options['rounds'] : 16; - $salt = Random::string(16); - $kdfoptions = Strings::packSSH2('sN', $salt, $rounds); - $crypto = new AES('ctr'); - $crypto->setPassword($password, 'bcrypt', $salt, $rounds, 32); - $paddedKey = $crypto->encrypt($paddedKey); - $key = Strings::packSSH2('sssNss', 'aes256-ctr', 'bcrypt', $kdfoptions, 1, $publicKey, $paddedKey); - } - $key = "openssh-key-v1\0$key"; - - return "-----BEGIN OPENSSH PRIVATE KEY-----\n" . - chunk_split(Strings::base64_encode($key), 70, "\n") . - "-----END OPENSSH PRIVATE KEY-----\n"; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS.php deleted file mode 100644 index 0219400b..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS.php +++ /dev/null @@ -1,72 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\Common\Formats\Keys; - -/** - * PKCS1 Formatted Key Handler - * - * @author Jim Wigginton - */ -abstract class PKCS -{ - /** - * Auto-detect the format - */ - const MODE_ANY = 0; - /** - * Require base64-encoded PEM's be supplied - */ - const MODE_PEM = 1; - /** - * Require raw DER's be supplied - */ - const MODE_DER = 2; - /**#@-*/ - - /** - * Is the key a base-64 encoded PEM, DER or should it be auto-detected? - * - * @var int - */ - protected static $format = self::MODE_ANY; - - /** - * Require base64-encoded PEM's be supplied - * - */ - public static function requirePEM() - { - self::$format = self::MODE_PEM; - } - - /** - * Require raw DER's be supplied - * - */ - public static function requireDER() - { - self::$format = self::MODE_DER; - } - - /** - * Accept any format and auto detect the format - * - * This is the default setting - * - */ - public static function requireAny() - { - self::$format = self::MODE_ANY; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS1.php deleted file mode 100644 index 4c639c05..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS1.php +++ /dev/null @@ -1,209 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\Common\Formats\Keys; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\AES; -use phpseclib3\Crypt\DES; -use phpseclib3\Crypt\Random; -use phpseclib3\Crypt\TripleDES; -use phpseclib3\Exception\UnsupportedAlgorithmException; -use phpseclib3\File\ASN1; - -/** - * PKCS1 Formatted Key Handler - * - * @author Jim Wigginton - */ -abstract class PKCS1 extends PKCS -{ - /** - * Default encryption algorithm - * - * @var string - */ - private static $defaultEncryptionAlgorithm = 'AES-128-CBC'; - - /** - * Sets the default encryption algorithm - * - * @param string $algo - */ - public static function setEncryptionAlgorithm($algo) - { - self::$defaultEncryptionAlgorithm = $algo; - } - - /** - * Returns the mode constant corresponding to the mode string - * - * @param string $mode - * @return int - * @throws \UnexpectedValueException if the block cipher mode is unsupported - */ - private static function getEncryptionMode($mode) - { - switch ($mode) { - case 'CBC': - case 'ECB': - case 'CFB': - case 'OFB': - case 'CTR': - return $mode; - } - throw new \UnexpectedValueException('Unsupported block cipher mode of operation'); - } - - /** - * Returns a cipher object corresponding to a string - * - * @param string $algo - * @return string - * @throws \UnexpectedValueException if the encryption algorithm is unsupported - */ - private static function getEncryptionObject($algo) - { - $modes = '(CBC|ECB|CFB|OFB|CTR)'; - switch (true) { - case preg_match("#^AES-(128|192|256)-$modes$#", $algo, $matches): - $cipher = new AES(self::getEncryptionMode($matches[2])); - $cipher->setKeyLength($matches[1]); - return $cipher; - case preg_match("#^DES-EDE3-$modes$#", $algo, $matches): - return new TripleDES(self::getEncryptionMode($matches[1])); - case preg_match("#^DES-$modes$#", $algo, $matches): - return new DES(self::getEncryptionMode($matches[1])); - default: - throw new UnsupportedAlgorithmException($algo . ' is not a supported algorithm'); - } - } - - /** - * Generate a symmetric key for PKCS#1 keys - * - * @param string $password - * @param string $iv - * @param int $length - * @return string - */ - private static function generateSymmetricKey($password, $iv, $length) - { - $symkey = ''; - $iv = substr($iv, 0, 8); - while (strlen($symkey) < $length) { - $symkey .= md5($symkey . $password . $iv, true); - } - return substr($symkey, 0, $length); - } - - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - protected static function load($key, $password) - { - if (!Strings::is_stringable($key)) { - throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key)); - } - - /* Although PKCS#1 proposes a format that public and private keys can use, encrypting them is - "outside the scope" of PKCS#1. PKCS#1 then refers you to PKCS#12 and PKCS#15 if you're wanting to - protect private keys, however, that's not what OpenSSL* does. OpenSSL protects private keys by adding - two new "fields" to the key - DEK-Info and Proc-Type. These fields are discussed here: - - http://tools.ietf.org/html/rfc1421#section-4.6.1.1 - http://tools.ietf.org/html/rfc1421#section-4.6.1.3 - - DES-EDE3-CBC as an algorithm, however, is not discussed anywhere, near as I can tell. - DES-CBC and DES-EDE are discussed in RFC1423, however, DES-EDE3-CBC isn't, nor is its key derivation - function. As is, the definitive authority on this encoding scheme isn't the IETF but rather OpenSSL's - own implementation. ie. the implementation *is* the standard and any bugs that may exist in that - implementation are part of the standard, as well. - - * OpenSSL is the de facto standard. It's utilized by OpenSSH and other projects */ - if (preg_match('#DEK-Info: (.+),(.+)#', $key, $matches)) { - $iv = Strings::hex2bin(trim($matches[2])); - // remove the Proc-Type / DEK-Info sections as they're no longer needed - $key = preg_replace('#^(?:Proc-Type|DEK-Info): .*#m', '', $key); - $ciphertext = ASN1::extractBER($key); - if ($ciphertext === false) { - $ciphertext = $key; - } - $crypto = self::getEncryptionObject($matches[1]); - $crypto->setKey(self::generateSymmetricKey($password, $iv, $crypto->getKeyLength() >> 3)); - $crypto->setIV($iv); - $key = $crypto->decrypt($ciphertext); - } else { - if (self::$format != self::MODE_DER) { - $decoded = ASN1::extractBER($key); - if ($decoded !== false) { - $key = $decoded; - } elseif (self::$format == self::MODE_PEM) { - throw new \UnexpectedValueException('Expected base64-encoded PEM format but was unable to decode base64 text'); - } - } - } - - return $key; - } - - /** - * Wrap a private key appropriately - * - * @param string $key - * @param string $type - * @param string $password - * @param array $options optional - * @return string - */ - protected static function wrapPrivateKey($key, $type, $password, array $options = []) - { - if (empty($password) || !is_string($password)) { - return "-----BEGIN $type PRIVATE KEY-----\r\n" . - chunk_split(Strings::base64_encode($key), 64) . - "-----END $type PRIVATE KEY-----"; - } - - $encryptionAlgorithm = isset($options['encryptionAlgorithm']) ? $options['encryptionAlgorithm'] : self::$defaultEncryptionAlgorithm; - - $cipher = self::getEncryptionObject($encryptionAlgorithm); - $iv = Random::string($cipher->getBlockLength() >> 3); - $cipher->setKey(self::generateSymmetricKey($password, $iv, $cipher->getKeyLength() >> 3)); - $cipher->setIV($iv); - $iv = strtoupper(Strings::bin2hex($iv)); - return "-----BEGIN $type PRIVATE KEY-----\r\n" . - "Proc-Type: 4,ENCRYPTED\r\n" . - "DEK-Info: " . $encryptionAlgorithm . ",$iv\r\n" . - "\r\n" . - chunk_split(Strings::base64_encode($cipher->encrypt($key)), 64) . - "-----END $type PRIVATE KEY-----"; - } - - /** - * Wrap a public key appropriately - * - * @param string $key - * @param string $type - * @return string - */ - protected static function wrapPublicKey($key, $type) - { - return "-----BEGIN $type PUBLIC KEY-----\r\n" . - chunk_split(Strings::base64_encode($key), 64) . - "-----END $type PUBLIC KEY-----"; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS8.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS8.php deleted file mode 100644 index 4638a539..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS8.php +++ /dev/null @@ -1,724 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\Common\Formats\Keys; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\AES; -use phpseclib3\Crypt\DES; -use phpseclib3\Crypt\Random; -use phpseclib3\Crypt\RC2; -use phpseclib3\Crypt\RC4; -use phpseclib3\Crypt\TripleDES; -use phpseclib3\Exception\InsufficientSetupException; -use phpseclib3\Exception\UnsupportedAlgorithmException; -use phpseclib3\File\ASN1; -use phpseclib3\File\ASN1\Maps; - -/** - * PKCS#8 Formatted Key Handler - * - * @author Jim Wigginton - */ -abstract class PKCS8 extends PKCS -{ - /** - * Default encryption algorithm - * - * @var string - */ - private static $defaultEncryptionAlgorithm = 'id-PBES2'; - - /** - * Default encryption scheme - * - * Only used when defaultEncryptionAlgorithm is id-PBES2 - * - * @var string - */ - private static $defaultEncryptionScheme = 'aes128-CBC-PAD'; - - /** - * Default PRF - * - * Only used when defaultEncryptionAlgorithm is id-PBES2 - * - * @var string - */ - private static $defaultPRF = 'id-hmacWithSHA256'; - - /** - * Default Iteration Count - * - * @var int - */ - private static $defaultIterationCount = 2048; - - /** - * OIDs loaded - * - * @var bool - */ - private static $oidsLoaded = false; - - /** - * Sets the default encryption algorithm - * - * @param string $algo - */ - public static function setEncryptionAlgorithm($algo) - { - self::$defaultEncryptionAlgorithm = $algo; - } - - /** - * Sets the default encryption algorithm for PBES2 - * - * @param string $algo - */ - public static function setEncryptionScheme($algo) - { - self::$defaultEncryptionScheme = $algo; - } - - /** - * Sets the iteration count - * - * @param int $count - */ - public static function setIterationCount($count) - { - self::$defaultIterationCount = $count; - } - - /** - * Sets the PRF for PBES2 - * - * @param string $algo - */ - public static function setPRF($algo) - { - self::$defaultPRF = $algo; - } - - /** - * Returns a SymmetricKey object based on a PBES1 $algo - * - * @return \phpseclib3\Crypt\Common\SymmetricKey - * @param string $algo - */ - private static function getPBES1EncryptionObject($algo) - { - $algo = preg_match('#^pbeWith(?:MD2|MD5|SHA1|SHA)And(.*?)-CBC$#', $algo, $matches) ? - $matches[1] : - substr($algo, 13); // strlen('pbeWithSHAAnd') == 13 - - switch ($algo) { - case 'DES': - $cipher = new DES('cbc'); - break; - case 'RC2': - $cipher = new RC2('cbc'); - break; - case '3-KeyTripleDES': - $cipher = new TripleDES('cbc'); - break; - case '2-KeyTripleDES': - $cipher = new TripleDES('cbc'); - $cipher->setKeyLength(128); - break; - case '128BitRC2': - $cipher = new RC2('cbc'); - $cipher->setKeyLength(128); - break; - case '40BitRC2': - $cipher = new RC2('cbc'); - $cipher->setKeyLength(40); - break; - case '128BitRC4': - $cipher = new RC4(); - $cipher->setKeyLength(128); - break; - case '40BitRC4': - $cipher = new RC4(); - $cipher->setKeyLength(40); - break; - default: - throw new UnsupportedAlgorithmException("$algo is not a supported algorithm"); - } - - return $cipher; - } - - /** - * Returns a hash based on a PBES1 $algo - * - * @return string - * @param string $algo - */ - private static function getPBES1Hash($algo) - { - if (preg_match('#^pbeWith(MD2|MD5|SHA1|SHA)And.*?-CBC$#', $algo, $matches)) { - return $matches[1] == 'SHA' ? 'sha1' : $matches[1]; - } - - return 'sha1'; - } - - /** - * Returns a KDF baesd on a PBES1 $algo - * - * @return string - * @param string $algo - */ - private static function getPBES1KDF($algo) - { - switch ($algo) { - case 'pbeWithMD2AndDES-CBC': - case 'pbeWithMD2AndRC2-CBC': - case 'pbeWithMD5AndDES-CBC': - case 'pbeWithMD5AndRC2-CBC': - case 'pbeWithSHA1AndDES-CBC': - case 'pbeWithSHA1AndRC2-CBC': - return 'pbkdf1'; - } - - return 'pkcs12'; - } - - /** - * Returns a SymmetricKey object baesd on a PBES2 $algo - * - * @return SymmetricKey - * @param string $algo - */ - private static function getPBES2EncryptionObject($algo) - { - switch ($algo) { - case 'desCBC': - $cipher = new TripleDES('cbc'); - break; - case 'des-EDE3-CBC': - $cipher = new TripleDES('cbc'); - break; - case 'rc2CBC': - $cipher = new RC2('cbc'); - // in theory this can be changed - $cipher->setKeyLength(128); - break; - case 'rc5-CBC-PAD': - throw new UnsupportedAlgorithmException('rc5-CBC-PAD is not supported for PBES2 PKCS#8 keys'); - case 'aes128-CBC-PAD': - case 'aes192-CBC-PAD': - case 'aes256-CBC-PAD': - $cipher = new AES('cbc'); - $cipher->setKeyLength(substr($algo, 3, 3)); - break; - default: - throw new UnsupportedAlgorithmException("$algo is not supported"); - } - - return $cipher; - } - - /** - * Initialize static variables - * - */ - private static function initialize_static_variables() - { - if (!isset(static::$childOIDsLoaded)) { - throw new InsufficientSetupException('This class should not be called directly'); - } - - if (!static::$childOIDsLoaded) { - ASN1::loadOIDs(is_array(static::OID_NAME) ? - array_combine(static::OID_NAME, static::OID_VALUE) : - [static::OID_NAME => static::OID_VALUE]); - static::$childOIDsLoaded = true; - } - if (!self::$oidsLoaded) { - // from https://tools.ietf.org/html/rfc2898 - ASN1::loadOIDs([ - // PBES1 encryption schemes - 'pbeWithMD2AndDES-CBC' => '1.2.840.113549.1.5.1', - 'pbeWithMD2AndRC2-CBC' => '1.2.840.113549.1.5.4', - 'pbeWithMD5AndDES-CBC' => '1.2.840.113549.1.5.3', - 'pbeWithMD5AndRC2-CBC' => '1.2.840.113549.1.5.6', - 'pbeWithSHA1AndDES-CBC' => '1.2.840.113549.1.5.10', - 'pbeWithSHA1AndRC2-CBC' => '1.2.840.113549.1.5.11', - - // from PKCS#12: - // https://tools.ietf.org/html/rfc7292 - 'pbeWithSHAAnd128BitRC4' => '1.2.840.113549.1.12.1.1', - 'pbeWithSHAAnd40BitRC4' => '1.2.840.113549.1.12.1.2', - 'pbeWithSHAAnd3-KeyTripleDES-CBC' => '1.2.840.113549.1.12.1.3', - 'pbeWithSHAAnd2-KeyTripleDES-CBC' => '1.2.840.113549.1.12.1.4', - 'pbeWithSHAAnd128BitRC2-CBC' => '1.2.840.113549.1.12.1.5', - 'pbeWithSHAAnd40BitRC2-CBC' => '1.2.840.113549.1.12.1.6', - - 'id-PBKDF2' => '1.2.840.113549.1.5.12', - 'id-PBES2' => '1.2.840.113549.1.5.13', - 'id-PBMAC1' => '1.2.840.113549.1.5.14', - - // from PKCS#5 v2.1: - // http://www.rsa.com/rsalabs/pkcs/files/h11302-wp-pkcs5v2-1-password-based-cryptography-standard.pdf - 'id-hmacWithSHA1' => '1.2.840.113549.2.7', - 'id-hmacWithSHA224' => '1.2.840.113549.2.8', - 'id-hmacWithSHA256' => '1.2.840.113549.2.9', - 'id-hmacWithSHA384' => '1.2.840.113549.2.10', - 'id-hmacWithSHA512' => '1.2.840.113549.2.11', - 'id-hmacWithSHA512-224' => '1.2.840.113549.2.12', - 'id-hmacWithSHA512-256' => '1.2.840.113549.2.13', - - 'desCBC' => '1.3.14.3.2.7', - 'des-EDE3-CBC' => '1.2.840.113549.3.7', - 'rc2CBC' => '1.2.840.113549.3.2', - 'rc5-CBC-PAD' => '1.2.840.113549.3.9', - - 'aes128-CBC-PAD' => '2.16.840.1.101.3.4.1.2', - 'aes192-CBC-PAD' => '2.16.840.1.101.3.4.1.22', - 'aes256-CBC-PAD' => '2.16.840.1.101.3.4.1.42' - ]); - self::$oidsLoaded = true; - } - } - - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - protected static function load($key, $password = '') - { - if (!Strings::is_stringable($key)) { - throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key)); - } - - $isPublic = strpos($key, 'PUBLIC') !== false; - $isPrivate = strpos($key, 'PRIVATE') !== false; - - $decoded = self::preParse($key); - - $meta = []; - - $decrypted = ASN1::asn1map($decoded[0], Maps\EncryptedPrivateKeyInfo::MAP); - if (strlen($password) && is_array($decrypted)) { - $algorithm = $decrypted['encryptionAlgorithm']['algorithm']; - switch ($algorithm) { - // PBES1 - case 'pbeWithMD2AndDES-CBC': - case 'pbeWithMD2AndRC2-CBC': - case 'pbeWithMD5AndDES-CBC': - case 'pbeWithMD5AndRC2-CBC': - case 'pbeWithSHA1AndDES-CBC': - case 'pbeWithSHA1AndRC2-CBC': - case 'pbeWithSHAAnd3-KeyTripleDES-CBC': - case 'pbeWithSHAAnd2-KeyTripleDES-CBC': - case 'pbeWithSHAAnd128BitRC2-CBC': - case 'pbeWithSHAAnd40BitRC2-CBC': - case 'pbeWithSHAAnd128BitRC4': - case 'pbeWithSHAAnd40BitRC4': - $cipher = self::getPBES1EncryptionObject($algorithm); - $hash = self::getPBES1Hash($algorithm); - $kdf = self::getPBES1KDF($algorithm); - - $meta['meta']['algorithm'] = $algorithm; - - $temp = ASN1::decodeBER($decrypted['encryptionAlgorithm']['parameters']); - if (!$temp) { - throw new \RuntimeException('Unable to decode BER'); - } - extract(ASN1::asn1map($temp[0], Maps\PBEParameter::MAP)); - $iterationCount = (int) $iterationCount->toString(); - $cipher->setPassword($password, $kdf, $hash, $salt, $iterationCount); - $key = $cipher->decrypt($decrypted['encryptedData']); - $decoded = ASN1::decodeBER($key); - if (!$decoded) { - throw new \RuntimeException('Unable to decode BER 2'); - } - - break; - case 'id-PBES2': - $meta['meta']['algorithm'] = $algorithm; - - $temp = ASN1::decodeBER($decrypted['encryptionAlgorithm']['parameters']); - if (!$temp) { - throw new \RuntimeException('Unable to decode BER'); - } - $temp = ASN1::asn1map($temp[0], Maps\PBES2params::MAP); - extract($temp); - - $cipher = self::getPBES2EncryptionObject($encryptionScheme['algorithm']); - $meta['meta']['cipher'] = $encryptionScheme['algorithm']; - - $temp = ASN1::decodeBER($decrypted['encryptionAlgorithm']['parameters']); - if (!$temp) { - throw new \RuntimeException('Unable to decode BER'); - } - $temp = ASN1::asn1map($temp[0], Maps\PBES2params::MAP); - extract($temp); - - if (!$cipher instanceof RC2) { - $cipher->setIV($encryptionScheme['parameters']['octetString']); - } else { - $temp = ASN1::decodeBER($encryptionScheme['parameters']); - if (!$temp) { - throw new \RuntimeException('Unable to decode BER'); - } - extract(ASN1::asn1map($temp[0], Maps\RC2CBCParameter::MAP)); - $effectiveKeyLength = (int) $rc2ParametersVersion->toString(); - switch ($effectiveKeyLength) { - case 160: - $effectiveKeyLength = 40; - break; - case 120: - $effectiveKeyLength = 64; - break; - case 58: - $effectiveKeyLength = 128; - break; - //default: // should be >= 256 - } - $cipher->setIV($iv); - $cipher->setKeyLength($effectiveKeyLength); - } - - $meta['meta']['keyDerivationFunc'] = $keyDerivationFunc['algorithm']; - switch ($keyDerivationFunc['algorithm']) { - case 'id-PBKDF2': - $temp = ASN1::decodeBER($keyDerivationFunc['parameters']); - if (!$temp) { - throw new \RuntimeException('Unable to decode BER'); - } - $prf = ['algorithm' => 'id-hmacWithSHA1']; - $params = ASN1::asn1map($temp[0], Maps\PBKDF2params::MAP); - extract($params); - $meta['meta']['prf'] = $prf['algorithm']; - $hash = str_replace('-', '/', substr($prf['algorithm'], 11)); - $params = [ - $password, - 'pbkdf2', - $hash, - $salt, - (int) $iterationCount->toString() - ]; - if (isset($keyLength)) { - $params[] = (int) $keyLength->toString(); - } - $cipher->setPassword(...$params); - $key = $cipher->decrypt($decrypted['encryptedData']); - $decoded = ASN1::decodeBER($key); - if (!$decoded) { - throw new \RuntimeException('Unable to decode BER 3'); - } - break; - default: - throw new UnsupportedAlgorithmException('Only PBKDF2 is supported for PBES2 PKCS#8 keys'); - } - break; - case 'id-PBMAC1': - //$temp = ASN1::decodeBER($decrypted['encryptionAlgorithm']['parameters']); - //$value = ASN1::asn1map($temp[0], Maps\PBMAC1params::MAP); - // since i can't find any implementation that does PBMAC1 it is unsupported - throw new UnsupportedAlgorithmException('Only PBES1 and PBES2 PKCS#8 keys are supported.'); - // at this point we'll assume that the key conforms to PublicKeyInfo - } - } - - $private = ASN1::asn1map($decoded[0], Maps\OneAsymmetricKey::MAP); - if (is_array($private)) { - if ($isPublic) { - throw new \UnexpectedValueException('Human readable string claims public key but DER encoded string claims private key'); - } - - if (isset($private['privateKeyAlgorithm']['parameters']) && !$private['privateKeyAlgorithm']['parameters'] instanceof ASN1\Element && isset($decoded[0]['content'][1]['content'][1])) { - $temp = $decoded[0]['content'][1]['content'][1]; - $private['privateKeyAlgorithm']['parameters'] = new ASN1\Element(substr($key, $temp['start'], $temp['length'])); - } - if (is_array(static::OID_NAME)) { - if (!in_array($private['privateKeyAlgorithm']['algorithm'], static::OID_NAME)) { - throw new UnsupportedAlgorithmException($private['privateKeyAlgorithm']['algorithm'] . ' is not a supported key type'); - } - } else { - if ($private['privateKeyAlgorithm']['algorithm'] != static::OID_NAME) { - throw new UnsupportedAlgorithmException('Only ' . static::OID_NAME . ' keys are supported; this is a ' . $private['privateKeyAlgorithm']['algorithm'] . ' key'); - } - } - if (isset($private['publicKey'])) { - if ($private['publicKey'][0] != "\0") { - throw new \UnexpectedValueException('The first byte of the public key should be null - not ' . bin2hex($private['publicKey'][0])); - } - $private['publicKey'] = substr($private['publicKey'], 1); - } - return $private + $meta; - } - - // EncryptedPrivateKeyInfo and PublicKeyInfo have largely identical "signatures". the only difference - // is that the former has an octet string and the later has a bit string. the first byte of a bit - // string represents the number of bits in the last byte that are to be ignored but, currently, - // bit strings wanting a non-zero amount of bits trimmed are not supported - $public = ASN1::asn1map($decoded[0], Maps\PublicKeyInfo::MAP); - - if (is_array($public)) { - if ($isPrivate) { - throw new \UnexpectedValueException('Human readable string claims private key but DER encoded string claims public key'); - } - - if ($public['publicKey'][0] != "\0") { - throw new \UnexpectedValueException('The first byte of the public key should be null - not ' . bin2hex($public['publicKey'][0])); - } - if (is_array(static::OID_NAME)) { - if (!in_array($public['publicKeyAlgorithm']['algorithm'], static::OID_NAME)) { - throw new UnsupportedAlgorithmException($public['publicKeyAlgorithm']['algorithm'] . ' is not a supported key type'); - } - } else { - if ($public['publicKeyAlgorithm']['algorithm'] != static::OID_NAME) { - throw new UnsupportedAlgorithmException('Only ' . static::OID_NAME . ' keys are supported; this is a ' . $public['publicKeyAlgorithm']['algorithm'] . ' key'); - } - } - if (isset($public['publicKeyAlgorithm']['parameters']) && !$public['publicKeyAlgorithm']['parameters'] instanceof ASN1\Element && isset($decoded[0]['content'][0]['content'][1])) { - $temp = $decoded[0]['content'][0]['content'][1]; - $public['publicKeyAlgorithm']['parameters'] = new ASN1\Element(substr($key, $temp['start'], $temp['length'])); - } - $public['publicKey'] = substr($public['publicKey'], 1); - return $public; - } - - throw new \RuntimeException('Unable to parse using either OneAsymmetricKey or PublicKeyInfo ASN1 maps'); - } - - /** - * Wrap a private key appropriately - * - * @param string $key - * @param string $attr - * @param mixed $params - * @param string $password - * @param string $oid optional - * @param string $publicKey optional - * @param array $options optional - * @return string - */ - protected static function wrapPrivateKey($key, $attr, $params, $password, $oid = null, $publicKey = '', array $options = []) - { - self::initialize_static_variables(); - - $key = [ - 'version' => 'v1', - 'privateKeyAlgorithm' => [ - 'algorithm' => is_string(static::OID_NAME) ? static::OID_NAME : $oid - ], - 'privateKey' => $key - ]; - if ($oid != 'id-Ed25519' && $oid != 'id-Ed448') { - $key['privateKeyAlgorithm']['parameters'] = $params; - } - if (!empty($attr)) { - $key['attributes'] = $attr; - } - if (!empty($publicKey)) { - $key['version'] = 'v2'; - $key['publicKey'] = $publicKey; - } - $key = ASN1::encodeDER($key, Maps\OneAsymmetricKey::MAP); - if (!empty($password) && is_string($password)) { - $salt = Random::string(8); - - $iterationCount = isset($options['iterationCount']) ? $options['iterationCount'] : self::$defaultIterationCount; - $encryptionAlgorithm = isset($options['encryptionAlgorithm']) ? $options['encryptionAlgorithm'] : self::$defaultEncryptionAlgorithm; - $encryptionScheme = isset($options['encryptionScheme']) ? $options['encryptionScheme'] : self::$defaultEncryptionScheme; - $prf = isset($options['PRF']) ? $options['PRF'] : self::$defaultPRF; - - if ($encryptionAlgorithm == 'id-PBES2') { - $crypto = self::getPBES2EncryptionObject($encryptionScheme); - $hash = str_replace('-', '/', substr($prf, 11)); - $kdf = 'pbkdf2'; - $iv = Random::string($crypto->getBlockLength() >> 3); - - $PBKDF2params = [ - 'salt' => $salt, - 'iterationCount' => $iterationCount, - 'prf' => ['algorithm' => $prf, 'parameters' => null] - ]; - $PBKDF2params = ASN1::encodeDER($PBKDF2params, Maps\PBKDF2params::MAP); - - if (!$crypto instanceof RC2) { - $params = ['octetString' => $iv]; - } else { - $params = [ - 'rc2ParametersVersion' => 58, - 'iv' => $iv - ]; - $params = ASN1::encodeDER($params, Maps\RC2CBCParameter::MAP); - $params = new ASN1\Element($params); - } - - $params = [ - 'keyDerivationFunc' => [ - 'algorithm' => 'id-PBKDF2', - 'parameters' => new ASN1\Element($PBKDF2params) - ], - 'encryptionScheme' => [ - 'algorithm' => $encryptionScheme, - 'parameters' => $params - ] - ]; - $params = ASN1::encodeDER($params, Maps\PBES2params::MAP); - - $crypto->setIV($iv); - } else { - $crypto = self::getPBES1EncryptionObject($encryptionAlgorithm); - $hash = self::getPBES1Hash($encryptionAlgorithm); - $kdf = self::getPBES1KDF($encryptionAlgorithm); - - $params = [ - 'salt' => $salt, - 'iterationCount' => $iterationCount - ]; - $params = ASN1::encodeDER($params, Maps\PBEParameter::MAP); - } - $crypto->setPassword($password, $kdf, $hash, $salt, $iterationCount); - $key = $crypto->encrypt($key); - - $key = [ - 'encryptionAlgorithm' => [ - 'algorithm' => $encryptionAlgorithm, - 'parameters' => new ASN1\Element($params) - ], - 'encryptedData' => $key - ]; - - $key = ASN1::encodeDER($key, Maps\EncryptedPrivateKeyInfo::MAP); - - return "-----BEGIN ENCRYPTED PRIVATE KEY-----\r\n" . - chunk_split(Strings::base64_encode($key), 64) . - "-----END ENCRYPTED PRIVATE KEY-----"; - } - - return "-----BEGIN PRIVATE KEY-----\r\n" . - chunk_split(Strings::base64_encode($key), 64) . - "-----END PRIVATE KEY-----"; - } - - /** - * Wrap a public key appropriately - * - * @param string $key - * @param mixed $params - * @param string $oid - * @return string - */ - protected static function wrapPublicKey($key, $params, $oid = null) - { - self::initialize_static_variables(); - - $key = [ - 'publicKeyAlgorithm' => [ - 'algorithm' => is_string(static::OID_NAME) ? static::OID_NAME : $oid - ], - 'publicKey' => "\0" . $key - ]; - - if ($oid != 'id-Ed25519' && $oid != 'id-Ed448') { - $key['publicKeyAlgorithm']['parameters'] = $params; - } - - $key = ASN1::encodeDER($key, Maps\PublicKeyInfo::MAP); - - return "-----BEGIN PUBLIC KEY-----\r\n" . - chunk_split(Strings::base64_encode($key), 64) . - "-----END PUBLIC KEY-----"; - } - - /** - * Perform some preliminary parsing of the key - * - * @param string $key - * @return array - */ - private static function preParse(&$key) - { - self::initialize_static_variables(); - - if (self::$format != self::MODE_DER) { - $decoded = ASN1::extractBER($key); - if ($decoded !== false) { - $key = $decoded; - } elseif (self::$format == self::MODE_PEM) { - throw new \UnexpectedValueException('Expected base64-encoded PEM format but was unable to decode base64 text'); - } - } - - $decoded = ASN1::decodeBER($key); - if (!$decoded) { - throw new \RuntimeException('Unable to decode BER'); - } - - return $decoded; - } - - /** - * Returns the encryption parameters used by the key - * - * @param string $key - * @return array - */ - public static function extractEncryptionAlgorithm($key) - { - if (!Strings::is_stringable($key)) { - throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key)); - } - - $decoded = self::preParse($key); - - $r = ASN1::asn1map($decoded[0], ASN1\Maps\EncryptedPrivateKeyInfo::MAP); - if (!is_array($r)) { - throw new \RuntimeException('Unable to parse using EncryptedPrivateKeyInfo map'); - } - - if ($r['encryptionAlgorithm']['algorithm'] == 'id-PBES2') { - $decoded = ASN1::decodeBER($r['encryptionAlgorithm']['parameters']->element); - if (!$decoded) { - throw new \RuntimeException('Unable to decode BER'); - } - $r['encryptionAlgorithm']['parameters'] = ASN1::asn1map($decoded[0], ASN1\Maps\PBES2params::MAP); - - $kdf = &$r['encryptionAlgorithm']['parameters']['keyDerivationFunc']; - switch ($kdf['algorithm']) { - case 'id-PBKDF2': - $decoded = ASN1::decodeBER($kdf['parameters']->element); - if (!$decoded) { - throw new \RuntimeException('Unable to decode BER'); - } - $kdf['parameters'] = ASN1::asn1map($decoded[0], Maps\PBKDF2params::MAP); - } - } - - return $r['encryptionAlgorithm']; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PuTTY.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PuTTY.php deleted file mode 100644 index 85da83a7..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PuTTY.php +++ /dev/null @@ -1,374 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\Common\Formats\Keys; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\AES; -use phpseclib3\Crypt\Hash; -use phpseclib3\Crypt\Random; -use phpseclib3\Exception\UnsupportedAlgorithmException; - -/** - * PuTTY Formatted Key Handler - * - * @author Jim Wigginton - */ -abstract class PuTTY -{ - /** - * Default comment - * - * @var string - */ - private static $comment = 'phpseclib-generated-key'; - - /** - * Default version - * - * @var int - */ - private static $version = 2; - - /** - * Sets the default comment - * - * @param string $comment - */ - public static function setComment($comment) - { - self::$comment = str_replace(["\r", "\n"], '', $comment); - } - - /** - * Sets the default version - * - * @param int $version - */ - public static function setVersion($version) - { - if ($version != 2 && $version != 3) { - throw new \RuntimeException('Only supported versions are 2 and 3'); - } - self::$version = $version; - } - - /** - * Generate a symmetric key for PuTTY v2 keys - * - * @param string $password - * @param int $length - * @return string - */ - private static function generateV2Key($password, $length) - { - $symkey = ''; - $sequence = 0; - while (strlen($symkey) < $length) { - $temp = pack('Na*', $sequence++, $password); - $symkey .= Strings::hex2bin(sha1($temp)); - } - return substr($symkey, 0, $length); - } - - /** - * Generate a symmetric key for PuTTY v3 keys - * - * @param string $password - * @param string $flavour - * @param int $memory - * @param int $passes - * @param string $salt - * @return array - */ - private static function generateV3Key($password, $flavour, $memory, $passes, $salt) - { - if (!function_exists('sodium_crypto_pwhash')) { - throw new \RuntimeException('sodium_crypto_pwhash needs to exist for Argon2 password hasing'); - } - - switch ($flavour) { - case 'Argon2i': - $flavour = SODIUM_CRYPTO_PWHASH_ALG_ARGON2I13; - break; - case 'Argon2id': - $flavour = SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13; - break; - default: - throw new UnsupportedAlgorithmException('Only Argon2i and Argon2id are supported'); - } - - $length = 80; // keylen + ivlen + mac_keylen - $temp = sodium_crypto_pwhash($length, $password, $salt, $passes, $memory << 10, $flavour); - - $symkey = substr($temp, 0, 32); - $symiv = substr($temp, 32, 16); - $hashkey = substr($temp, -32); - - return compact('symkey', 'symiv', 'hashkey'); - } - - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password - * @return array - */ - public static function load($key, $password) - { - if (!Strings::is_stringable($key)) { - throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key)); - } - - if (strpos($key, 'BEGIN SSH2 PUBLIC KEY') !== false) { - $lines = preg_split('#[\r\n]+#', $key); - switch (true) { - case $lines[0] != '---- BEGIN SSH2 PUBLIC KEY ----': - throw new \UnexpectedValueException('Key doesn\'t start with ---- BEGIN SSH2 PUBLIC KEY ----'); - case $lines[count($lines) - 1] != '---- END SSH2 PUBLIC KEY ----': - throw new \UnexpectedValueException('Key doesn\'t end with ---- END SSH2 PUBLIC KEY ----'); - } - $lines = array_splice($lines, 1, -1); - $lines = array_map(function ($line) { - return rtrim($line, "\r\n"); - }, $lines); - $data = $current = ''; - $values = []; - $in_value = false; - foreach ($lines as $line) { - switch (true) { - case preg_match('#^(.*?): (.*)#', $line, $match): - $in_value = $line[strlen($line) - 1] == '\\'; - $current = strtolower($match[1]); - $values[$current] = $in_value ? substr($match[2], 0, -1) : $match[2]; - break; - case $in_value: - $in_value = $line[strlen($line) - 1] == '\\'; - $values[$current] .= $in_value ? substr($line, 0, -1) : $line; - break; - default: - $data .= $line; - } - } - - $components = call_user_func([static::PUBLIC_HANDLER, 'load'], $data); - if ($components === false) { - throw new \UnexpectedValueException('Unable to decode public key'); - } - $components += $values; - $components['comment'] = str_replace(['\\\\', '\"'], ['\\', '"'], $values['comment']); - - return $components; - } - - $components = []; - - $key = preg_split('#\r\n|\r|\n#', trim($key)); - if (Strings::shift($key[0], strlen('PuTTY-User-Key-File-')) != 'PuTTY-User-Key-File-') { - return false; - } - $version = (int) Strings::shift($key[0], 3); // should be either "2: " or "3: 0" prior to int casting - if ($version != 2 && $version != 3) { - throw new \RuntimeException('Only v2 and v3 PuTTY private keys are supported'); - } - $components['type'] = $type = rtrim($key[0]); - if (!in_array($type, static::$types)) { - $error = count(static::$types) == 1 ? - 'Only ' . static::$types[0] . ' keys are supported. ' : - ''; - throw new UnsupportedAlgorithmException($error . 'This is an unsupported ' . $type . ' key'); - } - $encryption = trim(preg_replace('#Encryption: (.+)#', '$1', $key[1])); - $components['comment'] = trim(preg_replace('#Comment: (.+)#', '$1', $key[2])); - - $publicLength = trim(preg_replace('#Public-Lines: (\d+)#', '$1', $key[3])); - $public = Strings::base64_decode(implode('', array_map('trim', array_slice($key, 4, $publicLength)))); - - $source = Strings::packSSH2('ssss', $type, $encryption, $components['comment'], $public); - - extract(unpack('Nlength', Strings::shift($public, 4))); - $newtype = Strings::shift($public, $length); - if ($newtype != $type) { - throw new \RuntimeException('The binary type does not match the human readable type field'); - } - - $components['public'] = $public; - - switch ($version) { - case 3: - $hashkey = ''; - break; - case 2: - $hashkey = 'putty-private-key-file-mac-key'; - } - - $offset = $publicLength + 4; - switch ($encryption) { - case 'aes256-cbc': - $crypto = new AES('cbc'); - switch ($version) { - case 3: - $flavour = trim(preg_replace('#Key-Derivation: (.*)#', '$1', $key[$offset++])); - $memory = trim(preg_replace('#Argon2-Memory: (\d+)#', '$1', $key[$offset++])); - $passes = trim(preg_replace('#Argon2-Passes: (\d+)#', '$1', $key[$offset++])); - $parallelism = trim(preg_replace('#Argon2-Parallelism: (\d+)#', '$1', $key[$offset++])); - $salt = Strings::hex2bin(trim(preg_replace('#Argon2-Salt: ([0-9a-f]+)#', '$1', $key[$offset++]))); - - extract(self::generateV3Key($password, $flavour, $memory, $passes, $salt)); - - break; - case 2: - $symkey = self::generateV2Key($password, 32); - $symiv = str_repeat("\0", $crypto->getBlockLength() >> 3); - $hashkey .= $password; - } - } - - switch ($version) { - case 3: - $hash = new Hash('sha256'); - $hash->setKey($hashkey); - break; - case 2: - $hash = new Hash('sha1'); - $hash->setKey(sha1($hashkey, true)); - } - - $privateLength = trim(preg_replace('#Private-Lines: (\d+)#', '$1', $key[$offset++])); - $private = Strings::base64_decode(implode('', array_map('trim', array_slice($key, $offset, $privateLength)))); - - if ($encryption != 'none') { - $crypto->setKey($symkey); - $crypto->setIV($symiv); - $crypto->disablePadding(); - $private = $crypto->decrypt($private); - } - - $source .= Strings::packSSH2('s', $private); - - $hmac = trim(preg_replace('#Private-MAC: (.+)#', '$1', $key[$offset + $privateLength])); - $hmac = Strings::hex2bin($hmac); - - if (!hash_equals($hash->hash($source), $hmac)) { - throw new \UnexpectedValueException('MAC validation error'); - } - - $components['private'] = $private; - - return $components; - } - - /** - * Wrap a private key appropriately - * - * @param string $public - * @param string $private - * @param string $type - * @param string $password - * @param array $options optional - * @return string - */ - protected static function wrapPrivateKey($public, $private, $type, $password, array $options = []) - { - $encryption = (!empty($password) || is_string($password)) ? 'aes256-cbc' : 'none'; - $comment = isset($options['comment']) ? $options['comment'] : self::$comment; - $version = isset($options['version']) ? $options['version'] : self::$version; - - $key = "PuTTY-User-Key-File-$version: $type\r\n"; - $key .= "Encryption: $encryption\r\n"; - $key .= "Comment: $comment\r\n"; - - $public = Strings::packSSH2('s', $type) . $public; - - $source = Strings::packSSH2('ssss', $type, $encryption, $comment, $public); - - $public = Strings::base64_encode($public); - $key .= "Public-Lines: " . ((strlen($public) + 63) >> 6) . "\r\n"; - $key .= chunk_split($public, 64); - - if (empty($password) && !is_string($password)) { - $source .= Strings::packSSH2('s', $private); - switch ($version) { - case 3: - $hash = new Hash('sha256'); - $hash->setKey(''); - break; - case 2: - $hash = new Hash('sha1'); - $hash->setKey(sha1('putty-private-key-file-mac-key', true)); - } - } else { - $private .= Random::string(16 - (strlen($private) & 15)); - $source .= Strings::packSSH2('s', $private); - $crypto = new AES('cbc'); - - switch ($version) { - case 3: - $salt = Random::string(16); - $key .= "Key-Derivation: Argon2id\r\n"; - $key .= "Argon2-Memory: 8192\r\n"; - $key .= "Argon2-Passes: 13\r\n"; - $key .= "Argon2-Parallelism: 1\r\n"; - $key .= "Argon2-Salt: " . Strings::bin2hex($salt) . "\r\n"; - extract(self::generateV3Key($password, 'Argon2id', 8192, 13, $salt)); - - $hash = new Hash('sha256'); - $hash->setKey($hashkey); - - break; - case 2: - $symkey = self::generateV2Key($password, 32); - $symiv = str_repeat("\0", $crypto->getBlockLength() >> 3); - $hashkey = 'putty-private-key-file-mac-key' . $password; - - $hash = new Hash('sha1'); - $hash->setKey(sha1($hashkey, true)); - } - - $crypto->setKey($symkey); - $crypto->setIV($symiv); - $crypto->disablePadding(); - $private = $crypto->encrypt($private); - $mac = $hash->hash($source); - } - - $private = Strings::base64_encode($private); - $key .= 'Private-Lines: ' . ((strlen($private) + 63) >> 6) . "\r\n"; - $key .= chunk_split($private, 64); - $key .= 'Private-MAC: ' . Strings::bin2hex($hash->hash($source)) . "\r\n"; - - return $key; - } - - /** - * Wrap a public key appropriately - * - * This is basically the format described in RFC 4716 (https://tools.ietf.org/html/rfc4716) - * - * @param string $key - * @param string $type - * @return string - */ - protected static function wrapPublicKey($key, $type) - { - $key = pack('Na*a*', strlen($type), $type, $key); - $key = "---- BEGIN SSH2 PUBLIC KEY ----\r\n" . - 'Comment: "' . str_replace(['\\', '"'], ['\\\\', '\"'], self::$comment) . "\"\r\n" . - chunk_split(Strings::base64_encode($key), 64) . - '---- END SSH2 PUBLIC KEY ----'; - return $key; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Signature/Raw.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Signature/Raw.php deleted file mode 100644 index ab8e7e46..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Signature/Raw.php +++ /dev/null @@ -1,60 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\Common\Formats\Signature; - -use phpseclib3\Math\BigInteger; - -/** - * Raw Signature Handler - * - * @author Jim Wigginton - */ -abstract class Raw -{ - /** - * Loads a signature - * - * @param array $sig - * @return array|bool - */ - public static function load($sig) - { - switch (true) { - case !is_array($sig): - case !isset($sig['r']) || !isset($sig['s']): - case !$sig['r'] instanceof BigInteger: - case !$sig['s'] instanceof BigInteger: - return false; - } - - return [ - 'r' => $sig['r'], - 's' => $sig['s'] - ]; - } - - /** - * Returns a signature in the appropriate format - * - * @param \phpseclib3\Math\BigInteger $r - * @param \phpseclib3\Math\BigInteger $s - * @return string - */ - public static function save(BigInteger $r, BigInteger $s) - { - return compact('r', 's'); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/PrivateKey.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/PrivateKey.php deleted file mode 100644 index a6e1eb0b..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/PrivateKey.php +++ /dev/null @@ -1,31 +0,0 @@ - - * @copyright 2009 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\Common; - -/** - * PrivateKey interface - * - * @author Jim Wigginton - */ -interface PrivateKey -{ - public function sign($message); - //public function decrypt($ciphertext); - public function getPublicKey(); - public function toString($type, array $options = []); - - /** - * @param string|false $password - * @return mixed - */ - public function withPassword($password = false); -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/PublicKey.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/PublicKey.php deleted file mode 100644 index 48a5875b..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/PublicKey.php +++ /dev/null @@ -1,25 +0,0 @@ - - * @copyright 2009 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\Common; - -/** - * PublicKey interface - * - * @author Jim Wigginton - */ -interface PublicKey -{ - public function verify($message, $signature); - //public function encrypt($plaintext); - public function toString($type, array $options = []); - public function getFingerprint($algorithm); -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/StreamCipher.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/StreamCipher.php deleted file mode 100644 index 0e2d6f0c..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/StreamCipher.php +++ /dev/null @@ -1,54 +0,0 @@ - - * @author Hans-Juergen Petrich - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\Common; - -/** - * Base Class for all stream cipher classes - * - * @author Jim Wigginton - */ -abstract class StreamCipher extends SymmetricKey -{ - /** - * Block Length of the cipher - * - * Stream ciphers do not have a block size - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::block_size - * @var int - */ - protected $block_size = 0; - - /** - * Default Constructor. - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() - * @return \phpseclib3\Crypt\Common\StreamCipher - */ - public function __construct() - { - parent::__construct('stream'); - } - - /** - * Stream ciphers not use an IV - * - * @return bool - */ - public function usesIV() - { - return false; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/SymmetricKey.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/SymmetricKey.php deleted file mode 100644 index 2a376f11..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/SymmetricKey.php +++ /dev/null @@ -1,3396 +0,0 @@ - - * @author Hans-Juergen Petrich - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\Common; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\Blowfish; -use phpseclib3\Crypt\Hash; -use phpseclib3\Exception\BadDecryptionException; -use phpseclib3\Exception\BadModeException; -use phpseclib3\Exception\InconsistentSetupException; -use phpseclib3\Exception\InsufficientSetupException; -use phpseclib3\Exception\UnsupportedAlgorithmException; -use phpseclib3\Math\BigInteger; -use phpseclib3\Math\BinaryField; -use phpseclib3\Math\PrimeField; - -/** - * Base Class for all \phpseclib3\Crypt\* cipher classes - * - * @author Jim Wigginton - * @author Hans-Juergen Petrich - */ -abstract class SymmetricKey -{ - /** - * Encrypt / decrypt using the Counter mode. - * - * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode. - * - * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29 - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() - */ - const MODE_CTR = -1; - /** - * Encrypt / decrypt using the Electronic Code Book mode. - * - * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29 - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() - */ - const MODE_ECB = 1; - /** - * Encrypt / decrypt using the Code Book Chaining mode. - * - * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29 - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() - */ - const MODE_CBC = 2; - /** - * Encrypt / decrypt using the Cipher Feedback mode. - * - * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29 - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() - */ - const MODE_CFB = 3; - /** - * Encrypt / decrypt using the Cipher Feedback mode (8bit) - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() - */ - const MODE_CFB8 = 7; - /** - * Encrypt / decrypt using the Output Feedback mode (8bit) - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() - */ - const MODE_OFB8 = 8; - /** - * Encrypt / decrypt using the Output Feedback mode. - * - * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29 - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() - */ - const MODE_OFB = 4; - /** - * Encrypt / decrypt using Galois/Counter mode. - * - * @link https://en.wikipedia.org/wiki/Galois/Counter_Mode - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() - */ - const MODE_GCM = 5; - /** - * Encrypt / decrypt using streaming mode. - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() - */ - const MODE_STREAM = 6; - - /** - * Mode Map - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() - */ - const MODE_MAP = [ - 'ctr' => self::MODE_CTR, - 'ecb' => self::MODE_ECB, - 'cbc' => self::MODE_CBC, - 'cfb' => self::MODE_CFB, - 'cfb8' => self::MODE_CFB8, - 'ofb' => self::MODE_OFB, - 'ofb8' => self::MODE_OFB8, - 'gcm' => self::MODE_GCM, - 'stream' => self::MODE_STREAM - ]; - - /** - * Base value for the internal implementation $engine switch - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() - */ - const ENGINE_INTERNAL = 1; - /** - * Base value for the eval() implementation $engine switch - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() - */ - const ENGINE_EVAL = 2; - /** - * Base value for the mcrypt implementation $engine switch - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() - */ - const ENGINE_MCRYPT = 3; - /** - * Base value for the openssl implementation $engine switch - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() - */ - const ENGINE_OPENSSL = 4; - /** - * Base value for the libsodium implementation $engine switch - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() - */ - const ENGINE_LIBSODIUM = 5; - /** - * Base value for the openssl / gcm implementation $engine switch - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() - */ - const ENGINE_OPENSSL_GCM = 6; - - /** - * Engine Reverse Map - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::getEngine() - */ - const ENGINE_MAP = [ - self::ENGINE_INTERNAL => 'PHP', - self::ENGINE_EVAL => 'Eval', - self::ENGINE_MCRYPT => 'mcrypt', - self::ENGINE_OPENSSL => 'OpenSSL', - self::ENGINE_LIBSODIUM => 'libsodium', - self::ENGINE_OPENSSL_GCM => 'OpenSSL (GCM)' - ]; - - /** - * The Encryption Mode - * - * @see self::__construct() - * @var int - */ - protected $mode; - - /** - * The Block Length of the block cipher - * - * @var int - */ - protected $block_size = 16; - - /** - * The Key - * - * @see self::setKey() - * @var string - */ - protected $key = false; - - /** - * HMAC Key - * - * @see self::setupGCM() - * @var ?string - */ - protected $hKey = false; - - /** - * The Initialization Vector - * - * @see self::setIV() - * @var string - */ - protected $iv = false; - - /** - * A "sliding" Initialization Vector - * - * @see self::enableContinuousBuffer() - * @see self::clearBuffers() - * @var string - */ - protected $encryptIV; - - /** - * A "sliding" Initialization Vector - * - * @see self::enableContinuousBuffer() - * @see self::clearBuffers() - * @var string - */ - protected $decryptIV; - - /** - * Continuous Buffer status - * - * @see self::enableContinuousBuffer() - * @var bool - */ - protected $continuousBuffer = false; - - /** - * Encryption buffer for CTR, OFB and CFB modes - * - * @see self::encrypt() - * @see self::clearBuffers() - * @var array - */ - protected $enbuffer; - - /** - * Decryption buffer for CTR, OFB and CFB modes - * - * @see self::decrypt() - * @see self::clearBuffers() - * @var array - */ - protected $debuffer; - - /** - * mcrypt resource for encryption - * - * The mcrypt resource can be recreated every time something needs to be created or it can be created just once. - * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode. - * - * @see self::encrypt() - * @var resource - */ - private $enmcrypt; - - /** - * mcrypt resource for decryption - * - * The mcrypt resource can be recreated every time something needs to be created or it can be created just once. - * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode. - * - * @see self::decrypt() - * @var resource - */ - private $demcrypt; - - /** - * Does the enmcrypt resource need to be (re)initialized? - * - * @see \phpseclib3\Crypt\Twofish::setKey() - * @see \phpseclib3\Crypt\Twofish::setIV() - * @var bool - */ - private $enchanged = true; - - /** - * Does the demcrypt resource need to be (re)initialized? - * - * @see \phpseclib3\Crypt\Twofish::setKey() - * @see \phpseclib3\Crypt\Twofish::setIV() - * @var bool - */ - private $dechanged = true; - - /** - * mcrypt resource for CFB mode - * - * mcrypt's CFB mode, in (and only in) buffered context, - * is broken, so phpseclib implements the CFB mode by it self, - * even when the mcrypt php extension is available. - * - * In order to do the CFB-mode work (fast) phpseclib - * use a separate ECB-mode mcrypt resource. - * - * @link http://phpseclib.sourceforge.net/cfb-demo.phps - * @see self::encrypt() - * @see self::decrypt() - * @see self::setupMcrypt() - * @var resource - */ - private $ecb; - - /** - * Optimizing value while CFB-encrypting - * - * Only relevant if $continuousBuffer enabled - * and $engine == self::ENGINE_MCRYPT - * - * It's faster to re-init $enmcrypt if - * $buffer bytes > $cfb_init_len than - * using the $ecb resource furthermore. - * - * This value depends of the chosen cipher - * and the time it would be needed for it's - * initialization [by mcrypt_generic_init()] - * which, typically, depends on the complexity - * on its internaly Key-expanding algorithm. - * - * @see self::encrypt() - * @var int - */ - protected $cfb_init_len = 600; - - /** - * Does internal cipher state need to be (re)initialized? - * - * @see self::setKey() - * @see self::setIV() - * @see self::disableContinuousBuffer() - * @var bool - */ - protected $changed = true; - - /** - * Does Eval engie need to be (re)initialized? - * - * @see self::setup() - * @var bool - */ - protected $nonIVChanged = true; - - /** - * Padding status - * - * @see self::enablePadding() - * @var bool - */ - private $padding = true; - - /** - * Is the mode one that is paddable? - * - * @see self::__construct() - * @var bool - */ - private $paddable = false; - - /** - * Holds which crypt engine internaly should be use, - * which will be determined automatically on __construct() - * - * Currently available $engines are: - * - self::ENGINE_LIBSODIUM (very fast, php-extension: libsodium, extension_loaded('libsodium') required) - * - self::ENGINE_OPENSSL_GCM (very fast, php-extension: openssl, extension_loaded('openssl') required) - * - self::ENGINE_OPENSSL (very fast, php-extension: openssl, extension_loaded('openssl') required) - * - self::ENGINE_MCRYPT (fast, php-extension: mcrypt, extension_loaded('mcrypt') required) - * - self::ENGINE_EVAL (medium, pure php-engine, no php-extension required) - * - self::ENGINE_INTERNAL (slower, pure php-engine, no php-extension required) - * - * @see self::setEngine() - * @see self::encrypt() - * @see self::decrypt() - * @var int - */ - protected $engine; - - /** - * Holds the preferred crypt engine - * - * @see self::setEngine() - * @see self::setPreferredEngine() - * @var int - */ - private $preferredEngine; - - /** - * The mcrypt specific name of the cipher - * - * Only used if $engine == self::ENGINE_MCRYPT - * - * @link http://www.php.net/mcrypt_module_open - * @link http://www.php.net/mcrypt_list_algorithms - * @see self::setupMcrypt() - * @var string - */ - protected $cipher_name_mcrypt; - - /** - * The openssl specific name of the cipher - * - * Only used if $engine == self::ENGINE_OPENSSL - * - * @link http://www.php.net/openssl-get-cipher-methods - * @var string - */ - protected $cipher_name_openssl; - - /** - * The openssl specific name of the cipher in ECB mode - * - * If OpenSSL does not support the mode we're trying to use (CTR) - * it can still be emulated with ECB mode. - * - * @link http://www.php.net/openssl-get-cipher-methods - * @var string - */ - protected $cipher_name_openssl_ecb; - - /** - * The default salt used by setPassword() - * - * @see self::setPassword() - * @var string - */ - private $password_default_salt = 'phpseclib/salt'; - - /** - * The name of the performance-optimized callback function - * - * Used by encrypt() / decrypt() - * only if $engine == self::ENGINE_INTERNAL - * - * @see self::encrypt() - * @see self::decrypt() - * @see self::setupInlineCrypt() - * @var Callback - */ - protected $inline_crypt; - - /** - * If OpenSSL can be used in ECB but not in CTR we can emulate CTR - * - * @see self::openssl_ctr_process() - * @var bool - */ - private $openssl_emulate_ctr = false; - - /** - * Don't truncate / null pad key - * - * @see self::clearBuffers() - * @var bool - */ - private $skip_key_adjustment = false; - - /** - * Has the key length explicitly been set or should it be derived from the key, itself? - * - * @see self::setKeyLength() - * @var bool - */ - protected $explicit_key_length = false; - - /** - * Hash subkey for GHASH - * - * @see self::setupGCM() - * @see self::ghash() - * @var BinaryField\Integer - */ - private $h; - - /** - * Additional authenticated data - * - * @var string - */ - protected $aad = ''; - - /** - * Authentication Tag produced after a round of encryption - * - * @var string - */ - protected $newtag = false; - - /** - * Authentication Tag to be verified during decryption - * - * @var string - */ - protected $oldtag = false; - - /** - * GCM Binary Field - * - * @see self::__construct() - * @see self::ghash() - * @var BinaryField - */ - private static $gcmField; - - /** - * Poly1305 Prime Field - * - * @see self::enablePoly1305() - * @see self::poly1305() - * @var PrimeField - */ - private static $poly1305Field; - - /** - * Flag for using regular vs "safe" intval - * - * @see self::initialize_static_variables() - * @var boolean - */ - protected static $use_reg_intval; - - /** - * Poly1305 Key - * - * @see self::setPoly1305Key() - * @see self::poly1305() - * @var string - */ - protected $poly1305Key; - - /** - * Poly1305 Flag - * - * @see self::setPoly1305Key() - * @see self::enablePoly1305() - * @var boolean - */ - protected $usePoly1305 = false; - - /** - * The Original Initialization Vector - * - * GCM uses the nonce to build the IV but we want to be able to distinguish between nonce-derived - * IV's and user-set IV's - * - * @see self::setIV() - * @var string - */ - private $origIV = false; - - /** - * Nonce - * - * Only used with GCM. We could re-use setIV() but nonce's can be of a different length and - * toggling between GCM and other modes could be more complicated if we re-used setIV() - * - * @see self::setNonce() - * @var string - */ - protected $nonce = false; - - /** - * Default Constructor. - * - * $mode could be: - * - * - ecb - * - * - cbc - * - * - ctr - * - * - cfb - * - * - cfb8 - * - * - ofb - * - * - ofb8 - * - * - gcm - * - * @param string $mode - * @throws BadModeException if an invalid / unsupported mode is provided - */ - public function __construct($mode) - { - $mode = strtolower($mode); - // necessary because of 5.6 compatibility; we can't do isset(self::MODE_MAP[$mode]) in 5.6 - $map = self::MODE_MAP; - if (!isset($map[$mode])) { - throw new BadModeException('No valid mode has been specified'); - } - - $mode = self::MODE_MAP[$mode]; - - // $mode dependent settings - switch ($mode) { - case self::MODE_ECB: - case self::MODE_CBC: - $this->paddable = true; - break; - case self::MODE_CTR: - case self::MODE_CFB: - case self::MODE_CFB8: - case self::MODE_OFB: - case self::MODE_OFB8: - case self::MODE_STREAM: - $this->paddable = false; - break; - case self::MODE_GCM: - if ($this->block_size != 16) { - throw new BadModeException('GCM is only valid for block ciphers with a block size of 128 bits'); - } - if (!isset(self::$gcmField)) { - self::$gcmField = new BinaryField(128, 7, 2, 1, 0); - } - $this->paddable = false; - break; - default: - throw new BadModeException('No valid mode has been specified'); - } - - $this->mode = $mode; - - static::initialize_static_variables(); - } - - /** - * Initialize static variables - */ - protected static function initialize_static_variables() - { - if (!isset(self::$use_reg_intval)) { - switch (true) { - // PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster - case (PHP_OS & "\xDF\xDF\xDF") === 'WIN': - case (php_uname('m') & "\xDF\xDF\xDF") != 'ARM': - case defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8: - self::$use_reg_intval = true; - break; - case (php_uname('m') & "\xDF\xDF\xDF") == 'ARM': - switch (true) { - /* PHP 7.0.0 introduced a bug that affected 32-bit ARM processors: - - https://github.com/php/php-src/commit/716da71446ebbd40fa6cf2cea8a4b70f504cc3cd - - altho the changelogs make no mention of it, this bug was fixed with this commit: - - https://github.com/php/php-src/commit/c1729272b17a1fe893d1a54e423d3b71470f3ee8 - - affected versions of PHP are: 7.0.x, 7.1.0 - 7.1.23 and 7.2.0 - 7.2.11 */ - case PHP_VERSION_ID >= 70000 && PHP_VERSION_ID <= 70123: - case PHP_VERSION_ID >= 70200 && PHP_VERSION_ID <= 70211: - self::$use_reg_intval = false; - break; - default: - self::$use_reg_intval = true; - } - } - } - } - - /** - * Sets the initialization vector. - * - * setIV() is not required when ecb or gcm modes are being used. - * - * {@internal Can be overwritten by a sub class, but does not have to be} - * - * @param string $iv - * @throws \LengthException if the IV length isn't equal to the block size - * @throws \BadMethodCallException if an IV is provided when one shouldn't be - */ - public function setIV($iv) - { - if ($this->mode == self::MODE_ECB) { - throw new \BadMethodCallException('This mode does not require an IV.'); - } - - if ($this->mode == self::MODE_GCM) { - throw new \BadMethodCallException('Use setNonce instead'); - } - - if (!$this->usesIV()) { - throw new \BadMethodCallException('This algorithm does not use an IV.'); - } - - if (strlen($iv) != $this->block_size) { - throw new \LengthException('Received initialization vector of size ' . strlen($iv) . ', but size ' . $this->block_size . ' is required'); - } - - $this->iv = $this->origIV = $iv; - $this->changed = true; - } - - /** - * Enables Poly1305 mode. - * - * Once enabled Poly1305 cannot be disabled. - * - * @throws \BadMethodCallException if Poly1305 is enabled whilst in GCM mode - */ - public function enablePoly1305() - { - if ($this->mode == self::MODE_GCM) { - throw new \BadMethodCallException('Poly1305 cannot be used in GCM mode'); - } - - $this->usePoly1305 = true; - } - - /** - * Enables Poly1305 mode. - * - * Once enabled Poly1305 cannot be disabled. If $key is not passed then an attempt to call createPoly1305Key - * will be made. - * - * @param string $key optional - * @throws \LengthException if the key isn't long enough - * @throws \BadMethodCallException if Poly1305 is enabled whilst in GCM mode - */ - public function setPoly1305Key($key = null) - { - if ($this->mode == self::MODE_GCM) { - throw new \BadMethodCallException('Poly1305 cannot be used in GCM mode'); - } - - if (!is_string($key) || strlen($key) != 32) { - throw new \LengthException('The Poly1305 key must be 32 bytes long (256 bits)'); - } - - if (!isset(self::$poly1305Field)) { - // 2^130-5 - self::$poly1305Field = new PrimeField(new BigInteger('3fffffffffffffffffffffffffffffffb', 16)); - } - - $this->poly1305Key = $key; - $this->usePoly1305 = true; - } - - /** - * Sets the nonce. - * - * setNonce() is only required when gcm is used - * - * @param string $nonce - * @throws \BadMethodCallException if an nonce is provided when one shouldn't be - */ - public function setNonce($nonce) - { - if ($this->mode != self::MODE_GCM) { - throw new \BadMethodCallException('Nonces are only used in GCM mode.'); - } - - $this->nonce = $nonce; - $this->setEngine(); - } - - /** - * Sets additional authenticated data - * - * setAAD() is only used by gcm or in poly1305 mode - * - * @param string $aad - * @throws \BadMethodCallException if mode isn't GCM or if poly1305 isn't being utilized - */ - public function setAAD($aad) - { - if ($this->mode != self::MODE_GCM && !$this->usePoly1305) { - throw new \BadMethodCallException('Additional authenticated data is only utilized in GCM mode or with Poly1305'); - } - - $this->aad = $aad; - } - - /** - * Returns whether or not the algorithm uses an IV - * - * @return bool - */ - public function usesIV() - { - return $this->mode != self::MODE_GCM && $this->mode != self::MODE_ECB; - } - - /** - * Returns whether or not the algorithm uses a nonce - * - * @return bool - */ - public function usesNonce() - { - return $this->mode == self::MODE_GCM; - } - - /** - * Returns the current key length in bits - * - * @return int - */ - public function getKeyLength() - { - return $this->key_length << 3; - } - - /** - * Returns the current block length in bits - * - * @return int - */ - public function getBlockLength() - { - return $this->block_size << 3; - } - - /** - * Returns the current block length in bytes - * - * @return int - */ - public function getBlockLengthInBytes() - { - return $this->block_size; - } - - /** - * Sets the key length. - * - * Keys with explicitly set lengths need to be treated accordingly - * - * @param int $length - */ - public function setKeyLength($length) - { - $this->explicit_key_length = $length >> 3; - - if (is_string($this->key) && strlen($this->key) != $this->explicit_key_length) { - $this->key = false; - throw new InconsistentSetupException('Key has already been set and is not ' . $this->explicit_key_length . ' bytes long'); - } - } - - /** - * Sets the key. - * - * The min/max length(s) of the key depends on the cipher which is used. - * If the key not fits the length(s) of the cipher it will paded with null bytes - * up to the closest valid key length. If the key is more than max length, - * we trim the excess bits. - * - * If the key is not explicitly set, it'll be assumed to be all null bytes. - * - * {@internal Could, but not must, extend by the child Crypt_* class} - * - * @param string $key - */ - public function setKey($key) - { - if ($this->explicit_key_length !== false && strlen($key) != $this->explicit_key_length) { - throw new InconsistentSetupException('Key length has already been set to ' . $this->explicit_key_length . ' bytes and this key is ' . strlen($key) . ' bytes'); - } - - $this->key = $key; - $this->key_length = strlen($key); - $this->setEngine(); - } - - /** - * Sets the password. - * - * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows: - * {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2} or pbkdf1: - * $hash, $salt, $count, $dkLen - * - * Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php - * {@link https://en.wikipedia.org/wiki/Bcrypt bcypt}: - * $salt, $rounds, $keylen - * - * This is a modified version of bcrypt used by OpenSSH. - * - * {@internal Could, but not must, extend by the child Crypt_* class} - * - * @see Crypt/Hash.php - * @param string $password - * @param string $method - * @param string[] ...$func_args - * @throws \LengthException if pbkdf1 is being used and the derived key length exceeds the hash length - * @throws \RuntimeException if bcrypt is being used and a salt isn't provided - * @return bool - */ - public function setPassword($password, $method = 'pbkdf2', ...$func_args) - { - $key = ''; - - $method = strtolower($method); - switch ($method) { - case 'bcrypt': - if (!isset($func_args[2])) { - throw new \RuntimeException('A salt must be provided for bcrypt to work'); - } - - $salt = $func_args[0]; - - $rounds = isset($func_args[1]) ? $func_args[1] : 16; - $keylen = isset($func_args[2]) ? $func_args[2] : $this->key_length; - - $key = Blowfish::bcrypt_pbkdf($password, $salt, $keylen + $this->block_size, $rounds); - - $this->setKey(substr($key, 0, $keylen)); - $this->setIV(substr($key, $keylen)); - - return true; - case 'pkcs12': // from https://tools.ietf.org/html/rfc7292#appendix-B.2 - case 'pbkdf1': - case 'pbkdf2': - // Hash function - $hash = isset($func_args[0]) ? strtolower($func_args[0]) : 'sha1'; - $hashObj = new Hash(); - $hashObj->setHash($hash); - - // WPA and WPA2 use the SSID as the salt - $salt = isset($func_args[1]) ? $func_args[1] : $this->password_default_salt; - - // RFC2898#section-4.2 uses 1,000 iterations by default - // WPA and WPA2 use 4,096. - $count = isset($func_args[2]) ? $func_args[2] : 1000; - - // Keylength - if (isset($func_args[3])) { - if ($func_args[3] <= 0) { - throw new \LengthException('Derived key length cannot be longer 0 or less'); - } - $dkLen = $func_args[3]; - } else { - $key_length = $this->explicit_key_length !== false ? $this->explicit_key_length : $this->key_length; - $dkLen = $method == 'pbkdf1' ? 2 * $key_length : $key_length; - } - - switch (true) { - case $method == 'pkcs12': - /* - In this specification, however, all passwords are created from - BMPStrings with a NULL terminator. This means that each character in - the original BMPString is encoded in 2 bytes in big-endian format - (most-significant byte first). There are no Unicode byte order - marks. The 2 bytes produced from the last character in the BMPString - are followed by 2 additional bytes with the value 0x00. - - -- https://tools.ietf.org/html/rfc7292#appendix-B.1 - */ - $password = "\0" . chunk_split($password, 1, "\0") . "\0"; - - /* - This standard specifies 3 different values for the ID byte mentioned - above: - - 1. If ID=1, then the pseudorandom bits being produced are to be used - as key material for performing encryption or decryption. - - 2. If ID=2, then the pseudorandom bits being produced are to be used - as an IV (Initial Value) for encryption or decryption. - - 3. If ID=3, then the pseudorandom bits being produced are to be used - as an integrity key for MACing. - */ - // Construct a string, D (the "diversifier"), by concatenating v/8 - // copies of ID. - $blockLength = $hashObj->getBlockLengthInBytes(); - $d1 = str_repeat(chr(1), $blockLength); - $d2 = str_repeat(chr(2), $blockLength); - $s = ''; - if (strlen($salt)) { - while (strlen($s) < $blockLength) { - $s .= $salt; - } - } - $s = substr($s, 0, $blockLength); - - $p = ''; - if (strlen($password)) { - while (strlen($p) < $blockLength) { - $p .= $password; - } - } - $p = substr($p, 0, $blockLength); - - $i = $s . $p; - - $this->setKey(self::pkcs12helper($dkLen, $hashObj, $i, $d1, $count)); - if ($this->usesIV()) { - $this->setIV(self::pkcs12helper($this->block_size, $hashObj, $i, $d2, $count)); - } - - return true; - case $method == 'pbkdf1': - if ($dkLen > $hashObj->getLengthInBytes()) { - throw new \LengthException('Derived key length cannot be longer than the hash length'); - } - $t = $password . $salt; - for ($i = 0; $i < $count; ++$i) { - $t = $hashObj->hash($t); - } - $key = substr($t, 0, $dkLen); - - $this->setKey(substr($key, 0, $dkLen >> 1)); - if ($this->usesIV()) { - $this->setIV(substr($key, $dkLen >> 1)); - } - - return true; - case !in_array($hash, hash_algos()): - $i = 1; - $hashObj->setKey($password); - while (strlen($key) < $dkLen) { - $f = $u = $hashObj->hash($salt . pack('N', $i++)); - for ($j = 2; $j <= $count; ++$j) { - $u = $hashObj->hash($u); - $f ^= $u; - } - $key .= $f; - } - $key = substr($key, 0, $dkLen); - break; - default: - $key = hash_pbkdf2($hash, $password, $salt, $count, $dkLen, true); - } - break; - default: - throw new UnsupportedAlgorithmException($method . ' is not a supported password hashing method'); - } - - $this->setKey($key); - - return true; - } - - /** - * PKCS#12 KDF Helper Function - * - * As discussed here: - * - * {@link https://tools.ietf.org/html/rfc7292#appendix-B} - * - * @see self::setPassword() - * @param int $n - * @param \phpseclib3\Crypt\Hash $hashObj - * @param string $i - * @param string $d - * @param int $count - * @return string $a - */ - private static function pkcs12helper($n, $hashObj, $i, $d, $count) - { - static $one; - if (!isset($one)) { - $one = new BigInteger(1); - } - - $blockLength = $hashObj->getBlockLength() >> 3; - - $c = ceil($n / $hashObj->getLengthInBytes()); - $a = ''; - for ($j = 1; $j <= $c; $j++) { - $ai = $d . $i; - for ($k = 0; $k < $count; $k++) { - $ai = $hashObj->hash($ai); - } - $b = ''; - while (strlen($b) < $blockLength) { - $b .= $ai; - } - $b = substr($b, 0, $blockLength); - $b = new BigInteger($b, 256); - $newi = ''; - for ($k = 0; $k < strlen($i); $k += $blockLength) { - $temp = substr($i, $k, $blockLength); - $temp = new BigInteger($temp, 256); - $temp->setPrecision($blockLength << 3); - $temp = $temp->add($b); - $temp = $temp->add($one); - $newi .= $temp->toBytes(false); - } - $i = $newi; - $a .= $ai; - } - - return substr($a, 0, $n); - } - - /** - * Encrypts a message. - * - * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other cipher - * implementations may or may not pad in the same manner. Other common approaches to padding and the reasons why it's - * necessary are discussed in the following - * URL: - * - * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html} - * - * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does. - * strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that - * length. - * - * {@internal Could, but not must, extend by the child Crypt_* class} - * - * @see self::decrypt() - * @param string $plaintext - * @return string $ciphertext - */ - public function encrypt($plaintext) - { - if ($this->paddable) { - $plaintext = $this->pad($plaintext); - } - - $this->setup(); - - if ($this->mode == self::MODE_GCM) { - $oldIV = $this->iv; - Strings::increment_str($this->iv); - $cipher = new static('ctr'); - $cipher->setKey($this->key); - $cipher->setIV($this->iv); - $ciphertext = $cipher->encrypt($plaintext); - - $s = $this->ghash( - self::nullPad128($this->aad) . - self::nullPad128($ciphertext) . - self::len64($this->aad) . - self::len64($ciphertext) - ); - $cipher->encryptIV = $this->iv = $this->encryptIV = $this->decryptIV = $oldIV; - $this->newtag = $cipher->encrypt($s); - return $ciphertext; - } - - if (isset($this->poly1305Key)) { - $cipher = clone $this; - unset($cipher->poly1305Key); - $this->usePoly1305 = false; - $ciphertext = $cipher->encrypt($plaintext); - $this->newtag = $this->poly1305($ciphertext); - return $ciphertext; - } - - if ($this->engine === self::ENGINE_OPENSSL) { - switch ($this->mode) { - case self::MODE_STREAM: - return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); - case self::MODE_ECB: - return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); - case self::MODE_CBC: - $result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->encryptIV); - if ($this->continuousBuffer) { - $this->encryptIV = substr($result, -$this->block_size); - } - return $result; - case self::MODE_CTR: - return $this->openssl_ctr_process($plaintext, $this->encryptIV, $this->enbuffer); - case self::MODE_CFB: - // cfb loosely routines inspired by openssl's: - // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1} - $ciphertext = ''; - if ($this->continuousBuffer) { - $iv = &$this->encryptIV; - $pos = &$this->enbuffer['pos']; - } else { - $iv = $this->encryptIV; - $pos = 0; - } - $len = strlen($plaintext); - $i = 0; - if ($pos) { - $orig_pos = $pos; - $max = $this->block_size - $pos; - if ($len >= $max) { - $i = $max; - $len -= $max; - $pos = 0; - } else { - $i = $len; - $pos += $len; - $len = 0; - } - // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize - $ciphertext = substr($iv, $orig_pos) ^ $plaintext; - $iv = substr_replace($iv, $ciphertext, $orig_pos, $i); - $plaintext = substr($plaintext, $i); - } - - $overflow = $len % $this->block_size; - - if ($overflow) { - $ciphertext .= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv); - $iv = Strings::pop($ciphertext, $this->block_size); - - $size = $len - $overflow; - $block = $iv ^ substr($plaintext, -$overflow); - $iv = substr_replace($iv, $block, 0, $overflow); - $ciphertext .= $block; - $pos = $overflow; - } elseif ($len) { - $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv); - $iv = substr($ciphertext, -$this->block_size); - } - - return $ciphertext; - case self::MODE_CFB8: - $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->encryptIV); - if ($this->continuousBuffer) { - if (($len = strlen($ciphertext)) >= $this->block_size) { - $this->encryptIV = substr($ciphertext, -$this->block_size); - } else { - $this->encryptIV = substr($this->encryptIV, $len - $this->block_size) . substr($ciphertext, -$len); - } - } - return $ciphertext; - case self::MODE_OFB8: - $ciphertext = ''; - $len = strlen($plaintext); - $iv = $this->encryptIV; - - for ($i = 0; $i < $len; ++$i) { - $xor = openssl_encrypt($iv, $this->cipher_name_openssl_ecb, $this->key, $this->openssl_options, $this->decryptIV); - $ciphertext .= $plaintext[$i] ^ $xor; - $iv = substr($iv, 1) . $xor[0]; - } - - if ($this->continuousBuffer) { - $this->encryptIV = $iv; - } - break; - case self::MODE_OFB: - return $this->openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer); - } - } - - if ($this->engine === self::ENGINE_MCRYPT) { - set_error_handler(function () { - }); - if ($this->enchanged) { - mcrypt_generic_init($this->enmcrypt, $this->key, $this->getIV($this->encryptIV)); - $this->enchanged = false; - } - - // re: {@link http://phpseclib.sourceforge.net/cfb-demo.phps} - // using mcrypt's default handing of CFB the above would output two different things. using phpseclib's - // rewritten CFB implementation the above outputs the same thing twice. - if ($this->mode == self::MODE_CFB && $this->continuousBuffer) { - $block_size = $this->block_size; - $iv = &$this->encryptIV; - $pos = &$this->enbuffer['pos']; - $len = strlen($plaintext); - $ciphertext = ''; - $i = 0; - if ($pos) { - $orig_pos = $pos; - $max = $block_size - $pos; - if ($len >= $max) { - $i = $max; - $len -= $max; - $pos = 0; - } else { - $i = $len; - $pos += $len; - $len = 0; - } - $ciphertext = substr($iv, $orig_pos) ^ $plaintext; - $iv = substr_replace($iv, $ciphertext, $orig_pos, $i); - $this->enbuffer['enmcrypt_init'] = true; - } - if ($len >= $block_size) { - if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) { - if ($this->enbuffer['enmcrypt_init'] === true) { - mcrypt_generic_init($this->enmcrypt, $this->key, $iv); - $this->enbuffer['enmcrypt_init'] = false; - } - $ciphertext .= mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size)); - $iv = substr($ciphertext, -$block_size); - $len %= $block_size; - } else { - while ($len >= $block_size) { - $iv = mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size); - $ciphertext .= $iv; - $len -= $block_size; - $i += $block_size; - } - } - } - - if ($len) { - $iv = mcrypt_generic($this->ecb, $iv); - $block = $iv ^ substr($plaintext, -$len); - $iv = substr_replace($iv, $block, 0, $len); - $ciphertext .= $block; - $pos = $len; - } - - restore_error_handler(); - - return $ciphertext; - } - - $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext); - - if (!$this->continuousBuffer) { - mcrypt_generic_init($this->enmcrypt, $this->key, $this->getIV($this->encryptIV)); - } - - restore_error_handler(); - - return $ciphertext; - } - - if ($this->engine === self::ENGINE_EVAL) { - $inline = $this->inline_crypt; - return $inline('encrypt', $plaintext); - } - - $buffer = &$this->enbuffer; - $block_size = $this->block_size; - $ciphertext = ''; - switch ($this->mode) { - case self::MODE_ECB: - for ($i = 0; $i < strlen($plaintext); $i += $block_size) { - $ciphertext .= $this->encryptBlock(substr($plaintext, $i, $block_size)); - } - break; - case self::MODE_CBC: - $xor = $this->encryptIV; - for ($i = 0; $i < strlen($plaintext); $i += $block_size) { - $block = substr($plaintext, $i, $block_size); - $block = $this->encryptBlock($block ^ $xor); - $xor = $block; - $ciphertext .= $block; - } - if ($this->continuousBuffer) { - $this->encryptIV = $xor; - } - break; - case self::MODE_CTR: - $xor = $this->encryptIV; - if (strlen($buffer['ciphertext'])) { - for ($i = 0; $i < strlen($plaintext); $i += $block_size) { - $block = substr($plaintext, $i, $block_size); - if (strlen($block) > strlen($buffer['ciphertext'])) { - $buffer['ciphertext'] .= $this->encryptBlock($xor); - Strings::increment_str($xor); - } - $key = Strings::shift($buffer['ciphertext'], $block_size); - $ciphertext .= $block ^ $key; - } - } else { - for ($i = 0; $i < strlen($plaintext); $i += $block_size) { - $block = substr($plaintext, $i, $block_size); - $key = $this->encryptBlock($xor); - Strings::increment_str($xor); - $ciphertext .= $block ^ $key; - } - } - if ($this->continuousBuffer) { - $this->encryptIV = $xor; - if ($start = strlen($plaintext) % $block_size) { - $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext']; - } - } - break; - case self::MODE_CFB: - // cfb loosely routines inspired by openssl's: - // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1} - if ($this->continuousBuffer) { - $iv = &$this->encryptIV; - $pos = &$buffer['pos']; - } else { - $iv = $this->encryptIV; - $pos = 0; - } - $len = strlen($plaintext); - $i = 0; - if ($pos) { - $orig_pos = $pos; - $max = $block_size - $pos; - if ($len >= $max) { - $i = $max; - $len -= $max; - $pos = 0; - } else { - $i = $len; - $pos += $len; - $len = 0; - } - // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize - $ciphertext = substr($iv, $orig_pos) ^ $plaintext; - $iv = substr_replace($iv, $ciphertext, $orig_pos, $i); - } - while ($len >= $block_size) { - $iv = $this->encryptBlock($iv) ^ substr($plaintext, $i, $block_size); - $ciphertext .= $iv; - $len -= $block_size; - $i += $block_size; - } - if ($len) { - $iv = $this->encryptBlock($iv); - $block = $iv ^ substr($plaintext, $i); - $iv = substr_replace($iv, $block, 0, $len); - $ciphertext .= $block; - $pos = $len; - } - break; - case self::MODE_CFB8: - $ciphertext = ''; - $len = strlen($plaintext); - $iv = $this->encryptIV; - - for ($i = 0; $i < $len; ++$i) { - $ciphertext .= ($c = $plaintext[$i] ^ $this->encryptBlock($iv)); - $iv = substr($iv, 1) . $c; - } - - if ($this->continuousBuffer) { - if ($len >= $block_size) { - $this->encryptIV = substr($ciphertext, -$block_size); - } else { - $this->encryptIV = substr($this->encryptIV, $len - $block_size) . substr($ciphertext, -$len); - } - } - break; - case self::MODE_OFB8: - $ciphertext = ''; - $len = strlen($plaintext); - $iv = $this->encryptIV; - - for ($i = 0; $i < $len; ++$i) { - $xor = $this->encryptBlock($iv); - $ciphertext .= $plaintext[$i] ^ $xor; - $iv = substr($iv, 1) . $xor[0]; - } - - if ($this->continuousBuffer) { - $this->encryptIV = $iv; - } - break; - case self::MODE_OFB: - $xor = $this->encryptIV; - if (strlen($buffer['xor'])) { - for ($i = 0; $i < strlen($plaintext); $i += $block_size) { - $block = substr($plaintext, $i, $block_size); - if (strlen($block) > strlen($buffer['xor'])) { - $xor = $this->encryptBlock($xor); - $buffer['xor'] .= $xor; - } - $key = Strings::shift($buffer['xor'], $block_size); - $ciphertext .= $block ^ $key; - } - } else { - for ($i = 0; $i < strlen($plaintext); $i += $block_size) { - $xor = $this->encryptBlock($xor); - $ciphertext .= substr($plaintext, $i, $block_size) ^ $xor; - } - $key = $xor; - } - if ($this->continuousBuffer) { - $this->encryptIV = $xor; - if ($start = strlen($plaintext) % $block_size) { - $buffer['xor'] = substr($key, $start) . $buffer['xor']; - } - } - break; - case self::MODE_STREAM: - $ciphertext = $this->encryptBlock($plaintext); - break; - } - - return $ciphertext; - } - - /** - * Decrypts a message. - * - * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until - * it is. - * - * {@internal Could, but not must, extend by the child Crypt_* class} - * - * @see self::encrypt() - * @param string $ciphertext - * @return string $plaintext - * @throws \LengthException if we're inside a block cipher and the ciphertext length is not a multiple of the block size - */ - public function decrypt($ciphertext) - { - if ($this->paddable && strlen($ciphertext) % $this->block_size) { - throw new \LengthException('The ciphertext length (' . strlen($ciphertext) . ') needs to be a multiple of the block size (' . $this->block_size . ')'); - } - $this->setup(); - - if ($this->mode == self::MODE_GCM || isset($this->poly1305Key)) { - if ($this->oldtag === false) { - throw new InsufficientSetupException('Authentication Tag has not been set'); - } - - if (isset($this->poly1305Key)) { - $newtag = $this->poly1305($ciphertext); - } else { - $oldIV = $this->iv; - Strings::increment_str($this->iv); - $cipher = new static('ctr'); - $cipher->setKey($this->key); - $cipher->setIV($this->iv); - $plaintext = $cipher->decrypt($ciphertext); - - $s = $this->ghash( - self::nullPad128($this->aad) . - self::nullPad128($ciphertext) . - self::len64($this->aad) . - self::len64($ciphertext) - ); - $cipher->encryptIV = $this->iv = $this->encryptIV = $this->decryptIV = $oldIV; - $newtag = $cipher->encrypt($s); - } - if ($this->oldtag != substr($newtag, 0, strlen($newtag))) { - $cipher = clone $this; - unset($cipher->poly1305Key); - $this->usePoly1305 = false; - $plaintext = $cipher->decrypt($ciphertext); - $this->oldtag = false; - throw new BadDecryptionException('Derived authentication tag and supplied authentication tag do not match'); - } - $this->oldtag = false; - return $plaintext; - } - - if ($this->engine === self::ENGINE_OPENSSL) { - switch ($this->mode) { - case self::MODE_STREAM: - $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); - break; - case self::MODE_ECB: - $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); - break; - case self::MODE_CBC: - $offset = $this->block_size; - $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->decryptIV); - if ($this->continuousBuffer) { - $this->decryptIV = substr($ciphertext, -$offset, $this->block_size); - } - break; - case self::MODE_CTR: - $plaintext = $this->openssl_ctr_process($ciphertext, $this->decryptIV, $this->debuffer); - break; - case self::MODE_CFB: - // cfb loosely routines inspired by openssl's: - // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1} - $plaintext = ''; - if ($this->continuousBuffer) { - $iv = &$this->decryptIV; - $pos = &$this->debuffer['pos']; - } else { - $iv = $this->decryptIV; - $pos = 0; - } - $len = strlen($ciphertext); - $i = 0; - if ($pos) { - $orig_pos = $pos; - $max = $this->block_size - $pos; - if ($len >= $max) { - $i = $max; - $len -= $max; - $pos = 0; - } else { - $i = $len; - $pos += $len; - $len = 0; - } - // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $this->blocksize - $plaintext = substr($iv, $orig_pos) ^ $ciphertext; - $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i); - $ciphertext = substr($ciphertext, $i); - } - $overflow = $len % $this->block_size; - if ($overflow) { - $plaintext .= openssl_decrypt(substr($ciphertext, 0, -$overflow), $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv); - if ($len - $overflow) { - $iv = substr($ciphertext, -$overflow - $this->block_size, -$overflow); - } - $iv = openssl_encrypt(str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv); - $plaintext .= $iv ^ substr($ciphertext, -$overflow); - $iv = substr_replace($iv, substr($ciphertext, -$overflow), 0, $overflow); - $pos = $overflow; - } elseif ($len) { - $plaintext .= openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv); - $iv = substr($ciphertext, -$this->block_size); - } - break; - case self::MODE_CFB8: - $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->decryptIV); - if ($this->continuousBuffer) { - if (($len = strlen($ciphertext)) >= $this->block_size) { - $this->decryptIV = substr($ciphertext, -$this->block_size); - } else { - $this->decryptIV = substr($this->decryptIV, $len - $this->block_size) . substr($ciphertext, -$len); - } - } - break; - case self::MODE_OFB8: - $plaintext = ''; - $len = strlen($ciphertext); - $iv = $this->decryptIV; - - for ($i = 0; $i < $len; ++$i) { - $xor = openssl_encrypt($iv, $this->cipher_name_openssl_ecb, $this->key, $this->openssl_options, $this->decryptIV); - $plaintext .= $ciphertext[$i] ^ $xor; - $iv = substr($iv, 1) . $xor[0]; - } - - if ($this->continuousBuffer) { - $this->decryptIV = $iv; - } - break; - case self::MODE_OFB: - $plaintext = $this->openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer); - } - - return $this->paddable ? $this->unpad($plaintext) : $plaintext; - } - - if ($this->engine === self::ENGINE_MCRYPT) { - set_error_handler(function () { - }); - $block_size = $this->block_size; - if ($this->dechanged) { - mcrypt_generic_init($this->demcrypt, $this->key, $this->getIV($this->decryptIV)); - $this->dechanged = false; - } - - if ($this->mode == self::MODE_CFB && $this->continuousBuffer) { - $iv = &$this->decryptIV; - $pos = &$this->debuffer['pos']; - $len = strlen($ciphertext); - $plaintext = ''; - $i = 0; - if ($pos) { - $orig_pos = $pos; - $max = $block_size - $pos; - if ($len >= $max) { - $i = $max; - $len -= $max; - $pos = 0; - } else { - $i = $len; - $pos += $len; - $len = 0; - } - // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize - $plaintext = substr($iv, $orig_pos) ^ $ciphertext; - $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i); - } - if ($len >= $block_size) { - $cb = substr($ciphertext, $i, $len - $len % $block_size); - $plaintext .= mcrypt_generic($this->ecb, $iv . $cb) ^ $cb; - $iv = substr($cb, -$block_size); - $len %= $block_size; - } - if ($len) { - $iv = mcrypt_generic($this->ecb, $iv); - $plaintext .= $iv ^ substr($ciphertext, -$len); - $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len); - $pos = $len; - } - - restore_error_handler(); - - return $plaintext; - } - - $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext); - - if (!$this->continuousBuffer) { - mcrypt_generic_init($this->demcrypt, $this->key, $this->getIV($this->decryptIV)); - } - - restore_error_handler(); - - return $this->paddable ? $this->unpad($plaintext) : $plaintext; - } - - if ($this->engine === self::ENGINE_EVAL) { - $inline = $this->inline_crypt; - return $inline('decrypt', $ciphertext); - } - - $block_size = $this->block_size; - - $buffer = &$this->debuffer; - $plaintext = ''; - switch ($this->mode) { - case self::MODE_ECB: - for ($i = 0; $i < strlen($ciphertext); $i += $block_size) { - $plaintext .= $this->decryptBlock(substr($ciphertext, $i, $block_size)); - } - break; - case self::MODE_CBC: - $xor = $this->decryptIV; - for ($i = 0; $i < strlen($ciphertext); $i += $block_size) { - $block = substr($ciphertext, $i, $block_size); - $plaintext .= $this->decryptBlock($block) ^ $xor; - $xor = $block; - } - if ($this->continuousBuffer) { - $this->decryptIV = $xor; - } - break; - case self::MODE_CTR: - $xor = $this->decryptIV; - if (strlen($buffer['ciphertext'])) { - for ($i = 0; $i < strlen($ciphertext); $i += $block_size) { - $block = substr($ciphertext, $i, $block_size); - if (strlen($block) > strlen($buffer['ciphertext'])) { - $buffer['ciphertext'] .= $this->encryptBlock($xor); - Strings::increment_str($xor); - } - $key = Strings::shift($buffer['ciphertext'], $block_size); - $plaintext .= $block ^ $key; - } - } else { - for ($i = 0; $i < strlen($ciphertext); $i += $block_size) { - $block = substr($ciphertext, $i, $block_size); - $key = $this->encryptBlock($xor); - Strings::increment_str($xor); - $plaintext .= $block ^ $key; - } - } - if ($this->continuousBuffer) { - $this->decryptIV = $xor; - if ($start = strlen($ciphertext) % $block_size) { - $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext']; - } - } - break; - case self::MODE_CFB: - if ($this->continuousBuffer) { - $iv = &$this->decryptIV; - $pos = &$buffer['pos']; - } else { - $iv = $this->decryptIV; - $pos = 0; - } - $len = strlen($ciphertext); - $i = 0; - if ($pos) { - $orig_pos = $pos; - $max = $block_size - $pos; - if ($len >= $max) { - $i = $max; - $len -= $max; - $pos = 0; - } else { - $i = $len; - $pos += $len; - $len = 0; - } - // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize - $plaintext = substr($iv, $orig_pos) ^ $ciphertext; - $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i); - } - while ($len >= $block_size) { - $iv = $this->encryptBlock($iv); - $cb = substr($ciphertext, $i, $block_size); - $plaintext .= $iv ^ $cb; - $iv = $cb; - $len -= $block_size; - $i += $block_size; - } - if ($len) { - $iv = $this->encryptBlock($iv); - $plaintext .= $iv ^ substr($ciphertext, $i); - $iv = substr_replace($iv, substr($ciphertext, $i), 0, $len); - $pos = $len; - } - break; - case self::MODE_CFB8: - $plaintext = ''; - $len = strlen($ciphertext); - $iv = $this->decryptIV; - - for ($i = 0; $i < $len; ++$i) { - $plaintext .= $ciphertext[$i] ^ $this->encryptBlock($iv); - $iv = substr($iv, 1) . $ciphertext[$i]; - } - - if ($this->continuousBuffer) { - if ($len >= $block_size) { - $this->decryptIV = substr($ciphertext, -$block_size); - } else { - $this->decryptIV = substr($this->decryptIV, $len - $block_size) . substr($ciphertext, -$len); - } - } - break; - case self::MODE_OFB8: - $plaintext = ''; - $len = strlen($ciphertext); - $iv = $this->decryptIV; - - for ($i = 0; $i < $len; ++$i) { - $xor = $this->encryptBlock($iv); - $plaintext .= $ciphertext[$i] ^ $xor; - $iv = substr($iv, 1) . $xor[0]; - } - - if ($this->continuousBuffer) { - $this->decryptIV = $iv; - } - break; - case self::MODE_OFB: - $xor = $this->decryptIV; - if (strlen($buffer['xor'])) { - for ($i = 0; $i < strlen($ciphertext); $i += $block_size) { - $block = substr($ciphertext, $i, $block_size); - if (strlen($block) > strlen($buffer['xor'])) { - $xor = $this->encryptBlock($xor); - $buffer['xor'] .= $xor; - } - $key = Strings::shift($buffer['xor'], $block_size); - $plaintext .= $block ^ $key; - } - } else { - for ($i = 0; $i < strlen($ciphertext); $i += $block_size) { - $xor = $this->encryptBlock($xor); - $plaintext .= substr($ciphertext, $i, $block_size) ^ $xor; - } - $key = $xor; - } - if ($this->continuousBuffer) { - $this->decryptIV = $xor; - if ($start = strlen($ciphertext) % $block_size) { - $buffer['xor'] = substr($key, $start) . $buffer['xor']; - } - } - break; - case self::MODE_STREAM: - $plaintext = $this->decryptBlock($ciphertext); - break; - } - return $this->paddable ? $this->unpad($plaintext) : $plaintext; - } - - /** - * Get the authentication tag - * - * Only used in GCM or Poly1305 mode - * - * @see self::encrypt() - * @param int $length optional - * @return string - * @throws \LengthException if $length isn't of a sufficient length - * @throws \RuntimeException if GCM mode isn't being used - */ - public function getTag($length = 16) - { - if ($this->mode != self::MODE_GCM && !$this->usePoly1305) { - throw new \BadMethodCallException('Authentication tags are only utilized in GCM mode or with Poly1305'); - } - - if ($this->newtag === false) { - throw new \BadMethodCallException('A tag can only be returned after a round of encryption has been performed'); - } - - // the tag is 128-bits. it can't be greater than 16 bytes because that's bigger than the tag is. if it - // were 0 you might as well be doing CTR and less than 4 provides minimal security that could be trivially - // easily brute forced. - // see https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf#page=36 - // for more info - if ($length < 4 || $length > 16) { - throw new \LengthException('The authentication tag must be between 4 and 16 bytes long'); - } - - return $length == 16 ? - $this->newtag : - substr($this->newtag, 0, $length); - } - - /** - * Sets the authentication tag - * - * Only used in GCM mode - * - * @see self::decrypt() - * @param string $tag - * @throws \LengthException if $length isn't of a sufficient length - * @throws \RuntimeException if GCM mode isn't being used - */ - public function setTag($tag) - { - if ($this->usePoly1305 && !isset($this->poly1305Key) && method_exists($this, 'createPoly1305Key')) { - $this->createPoly1305Key(); - } - - if ($this->mode != self::MODE_GCM && !$this->usePoly1305) { - throw new \BadMethodCallException('Authentication tags are only utilized in GCM mode or with Poly1305'); - } - - $length = strlen($tag); - if ($length < 4 || $length > 16) { - throw new \LengthException('The authentication tag must be between 4 and 16 bytes long'); - } - $this->oldtag = $tag; - } - - /** - * Get the IV - * - * mcrypt requires an IV even if ECB is used - * - * @see self::encrypt() - * @see self::decrypt() - * @param string $iv - * @return string - */ - protected function getIV($iv) - { - return $this->mode == self::MODE_ECB ? str_repeat("\0", $this->block_size) : $iv; - } - - /** - * OpenSSL CTR Processor - * - * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream - * for CTR is the same for both encrypting and decrypting this function is re-used by both SymmetricKey::encrypt() - * and SymmetricKey::decrypt(). Also, OpenSSL doesn't implement CTR for all of it's symmetric ciphers so this - * function will emulate CTR with ECB when necessary. - * - * @see self::encrypt() - * @see self::decrypt() - * @param string $plaintext - * @param string $encryptIV - * @param array $buffer - * @return string - */ - private function openssl_ctr_process($plaintext, &$encryptIV, &$buffer) - { - $ciphertext = ''; - - $block_size = $this->block_size; - $key = $this->key; - - if ($this->openssl_emulate_ctr) { - $xor = $encryptIV; - if (strlen($buffer['ciphertext'])) { - for ($i = 0; $i < strlen($plaintext); $i += $block_size) { - $block = substr($plaintext, $i, $block_size); - if (strlen($block) > strlen($buffer['ciphertext'])) { - $buffer['ciphertext'] .= openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); - } - Strings::increment_str($xor); - $otp = Strings::shift($buffer['ciphertext'], $block_size); - $ciphertext .= $block ^ $otp; - } - } else { - for ($i = 0; $i < strlen($plaintext); $i += $block_size) { - $block = substr($plaintext, $i, $block_size); - $otp = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); - Strings::increment_str($xor); - $ciphertext .= $block ^ $otp; - } - } - if ($this->continuousBuffer) { - $encryptIV = $xor; - if ($start = strlen($plaintext) % $block_size) { - $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext']; - } - } - - return $ciphertext; - } - - if (strlen($buffer['ciphertext'])) { - $ciphertext = $plaintext ^ Strings::shift($buffer['ciphertext'], strlen($plaintext)); - $plaintext = substr($plaintext, strlen($ciphertext)); - - if (!strlen($plaintext)) { - return $ciphertext; - } - } - - $overflow = strlen($plaintext) % $block_size; - if ($overflow) { - $plaintext2 = Strings::pop($plaintext, $overflow); // ie. trim $plaintext to a multiple of $block_size and put rest of $plaintext in $plaintext2 - $encrypted = openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV); - $temp = Strings::pop($encrypted, $block_size); - $ciphertext .= $encrypted . ($plaintext2 ^ $temp); - if ($this->continuousBuffer) { - $buffer['ciphertext'] = substr($temp, $overflow); - $encryptIV = $temp; - } - } elseif (!strlen($buffer['ciphertext'])) { - $ciphertext .= openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV); - $temp = Strings::pop($ciphertext, $block_size); - if ($this->continuousBuffer) { - $encryptIV = $temp; - } - } - if ($this->continuousBuffer) { - $encryptIV = openssl_decrypt($encryptIV, $this->cipher_name_openssl_ecb, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); - if ($overflow) { - Strings::increment_str($encryptIV); - } - } - - return $ciphertext; - } - - /** - * OpenSSL OFB Processor - * - * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream - * for OFB is the same for both encrypting and decrypting this function is re-used by both SymmetricKey::encrypt() - * and SymmetricKey::decrypt(). - * - * @see self::encrypt() - * @see self::decrypt() - * @param string $plaintext - * @param string $encryptIV - * @param array $buffer - * @return string - */ - private function openssl_ofb_process($plaintext, &$encryptIV, &$buffer) - { - if (strlen($buffer['xor'])) { - $ciphertext = $plaintext ^ $buffer['xor']; - $buffer['xor'] = substr($buffer['xor'], strlen($ciphertext)); - $plaintext = substr($plaintext, strlen($ciphertext)); - } else { - $ciphertext = ''; - } - - $block_size = $this->block_size; - - $len = strlen($plaintext); - $key = $this->key; - $overflow = $len % $block_size; - - if (strlen($plaintext)) { - if ($overflow) { - $ciphertext .= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV); - $xor = Strings::pop($ciphertext, $block_size); - if ($this->continuousBuffer) { - $encryptIV = $xor; - } - $ciphertext .= Strings::shift($xor, $overflow) ^ substr($plaintext, -$overflow); - if ($this->continuousBuffer) { - $buffer['xor'] = $xor; - } - } else { - $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV); - if ($this->continuousBuffer) { - $encryptIV = substr($ciphertext, -$block_size) ^ substr($plaintext, -$block_size); - } - } - } - - return $ciphertext; - } - - /** - * phpseclib <-> OpenSSL Mode Mapper - * - * May need to be overwritten by classes extending this one in some cases - * - * @return string - */ - protected function openssl_translate_mode() - { - switch ($this->mode) { - case self::MODE_ECB: - return 'ecb'; - case self::MODE_CBC: - return 'cbc'; - case self::MODE_CTR: - case self::MODE_GCM: - return 'ctr'; - case self::MODE_CFB: - return 'cfb'; - case self::MODE_CFB8: - return 'cfb8'; - case self::MODE_OFB: - return 'ofb'; - } - } - - /** - * Pad "packets". - * - * Block ciphers working by encrypting between their specified [$this->]block_size at a time - * If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to - * pad the input so that it is of the proper length. - * - * Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH, - * where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping - * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is - * transmitted separately) - * - * @see self::disablePadding() - */ - public function enablePadding() - { - $this->padding = true; - } - - /** - * Do not pad packets. - * - * @see self::enablePadding() - */ - public function disablePadding() - { - $this->padding = false; - } - - /** - * Treat consecutive "packets" as if they are a continuous buffer. - * - * Say you have a 32-byte plaintext $plaintext. Using the default behavior, the two following code snippets - * will yield different outputs: - * - * - * echo $rijndael->encrypt(substr($plaintext, 0, 16)); - * echo $rijndael->encrypt(substr($plaintext, 16, 16)); - * - * - * echo $rijndael->encrypt($plaintext); - * - * - * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates - * another, as demonstrated with the following: - * - * - * $rijndael->encrypt(substr($plaintext, 0, 16)); - * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16))); - * - * - * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16))); - * - * - * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different - * outputs. The reason is due to the fact that the initialization vector's change after every encryption / - * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant. - * - * Put another way, when the continuous buffer is enabled, the state of the \phpseclib3\Crypt\*() object changes after each - * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that - * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them), - * however, they are also less intuitive and more likely to cause you problems. - * - * {@internal Could, but not must, extend by the child Crypt_* class} - * - * @see self::disableContinuousBuffer() - */ - public function enableContinuousBuffer() - { - if ($this->mode == self::MODE_ECB) { - return; - } - - if ($this->mode == self::MODE_GCM) { - throw new \BadMethodCallException('This mode does not run in continuous mode'); - } - - $this->continuousBuffer = true; - - $this->setEngine(); - } - - /** - * Treat consecutive packets as if they are a discontinuous buffer. - * - * The default behavior. - * - * {@internal Could, but not must, extend by the child Crypt_* class} - * - * @see self::enableContinuousBuffer() - */ - public function disableContinuousBuffer() - { - if ($this->mode == self::MODE_ECB) { - return; - } - if (!$this->continuousBuffer) { - return; - } - - $this->continuousBuffer = false; - - $this->setEngine(); - } - - /** - * Test for engine validity - * - * @see self::__construct() - * @param int $engine - * @return bool - */ - protected function isValidEngineHelper($engine) - { - switch ($engine) { - case self::ENGINE_OPENSSL: - $this->openssl_emulate_ctr = false; - $result = $this->cipher_name_openssl && - extension_loaded('openssl'); - if (!$result) { - return false; - } - - $methods = openssl_get_cipher_methods(); - if (in_array($this->cipher_name_openssl, $methods)) { - return true; - } - // not all of openssl's symmetric cipher's support ctr. for those - // that don't we'll emulate it - switch ($this->mode) { - case self::MODE_CTR: - if (in_array($this->cipher_name_openssl_ecb, $methods)) { - $this->openssl_emulate_ctr = true; - return true; - } - } - return false; - case self::ENGINE_MCRYPT: - set_error_handler(function () { - }); - $result = $this->cipher_name_mcrypt && - extension_loaded('mcrypt') && - in_array($this->cipher_name_mcrypt, mcrypt_list_algorithms()); - restore_error_handler(); - return $result; - case self::ENGINE_EVAL: - return method_exists($this, 'setupInlineCrypt'); - case self::ENGINE_INTERNAL: - return true; - } - - return false; - } - - /** - * Test for engine validity - * - * @see self::__construct() - * @param string $engine - * @return bool - */ - public function isValidEngine($engine) - { - static $reverseMap; - if (!isset($reverseMap)) { - $reverseMap = array_map('strtolower', self::ENGINE_MAP); - $reverseMap = array_flip($reverseMap); - } - $engine = strtolower($engine); - if (!isset($reverseMap[$engine])) { - return false; - } - - return $this->isValidEngineHelper($reverseMap[$engine]); - } - - /** - * Sets the preferred crypt engine - * - * Currently, $engine could be: - * - * - libsodium[very fast] - * - * - OpenSSL [very fast] - * - * - mcrypt [fast] - * - * - Eval [slow] - * - * - PHP [slowest] - * - * If the preferred crypt engine is not available the fastest available one will be used - * - * @see self::__construct() - * @param string $engine - */ - public function setPreferredEngine($engine) - { - static $reverseMap; - if (!isset($reverseMap)) { - $reverseMap = array_map('strtolower', self::ENGINE_MAP); - $reverseMap = array_flip($reverseMap); - } - $engine = is_string($engine) ? strtolower($engine) : ''; - $this->preferredEngine = isset($reverseMap[$engine]) ? $reverseMap[$engine] : self::ENGINE_LIBSODIUM; - - $this->setEngine(); - } - - /** - * Returns the engine currently being utilized - * - * @see self::setEngine() - */ - public function getEngine() - { - return self::ENGINE_MAP[$this->engine]; - } - - /** - * Sets the engine as appropriate - * - * @see self::__construct() - */ - protected function setEngine() - { - $this->engine = null; - - $candidateEngines = [ - self::ENGINE_LIBSODIUM, - self::ENGINE_OPENSSL_GCM, - self::ENGINE_OPENSSL, - self::ENGINE_MCRYPT, - self::ENGINE_EVAL - ]; - if (isset($this->preferredEngine)) { - $temp = [$this->preferredEngine]; - $candidateEngines = array_merge( - $temp, - array_diff($candidateEngines, $temp) - ); - } - foreach ($candidateEngines as $engine) { - if ($this->isValidEngineHelper($engine)) { - $this->engine = $engine; - break; - } - } - if (!$this->engine) { - $this->engine = self::ENGINE_INTERNAL; - } - - if ($this->engine != self::ENGINE_MCRYPT && $this->enmcrypt) { - set_error_handler(function () { - }); - // Closing the current mcrypt resource(s). _mcryptSetup() will, if needed, - // (re)open them with the module named in $this->cipher_name_mcrypt - mcrypt_module_close($this->enmcrypt); - mcrypt_module_close($this->demcrypt); - $this->enmcrypt = null; - $this->demcrypt = null; - - if ($this->ecb) { - mcrypt_module_close($this->ecb); - $this->ecb = null; - } - restore_error_handler(); - } - - $this->changed = $this->nonIVChanged = true; - } - - /** - * Encrypts a block - * - * Note: Must be extended by the child \phpseclib3\Crypt\* class - * - * @param string $in - * @return string - */ - abstract protected function encryptBlock($in); - - /** - * Decrypts a block - * - * Note: Must be extended by the child \phpseclib3\Crypt\* class - * - * @param string $in - * @return string - */ - abstract protected function decryptBlock($in); - - /** - * Setup the key (expansion) - * - * Only used if $engine == self::ENGINE_INTERNAL - * - * Note: Must extend by the child \phpseclib3\Crypt\* class - * - * @see self::setup() - */ - abstract protected function setupKey(); - - /** - * Setup the self::ENGINE_INTERNAL $engine - * - * (re)init, if necessary, the internal cipher $engine and flush all $buffers - * Used (only) if $engine == self::ENGINE_INTERNAL - * - * _setup() will be called each time if $changed === true - * typically this happens when using one or more of following public methods: - * - * - setKey() - * - * - setIV() - * - * - disableContinuousBuffer() - * - * - First run of encrypt() / decrypt() with no init-settings - * - * {@internal setup() is always called before en/decryption.} - * - * {@internal Could, but not must, extend by the child Crypt_* class} - * - * @see self::setKey() - * @see self::setIV() - * @see self::disableContinuousBuffer() - */ - protected function setup() - { - if (!$this->changed) { - return; - } - - $this->changed = false; - - if ($this->usePoly1305 && !isset($this->poly1305Key) && method_exists($this, 'createPoly1305Key')) { - $this->createPoly1305Key(); - } - - $this->enbuffer = $this->debuffer = ['ciphertext' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true]; - //$this->newtag = $this->oldtag = false; - - if ($this->usesNonce()) { - if ($this->nonce === false) { - throw new InsufficientSetupException('No nonce has been defined'); - } - if ($this->mode == self::MODE_GCM && !in_array($this->engine, [self::ENGINE_LIBSODIUM, self::ENGINE_OPENSSL_GCM])) { - $this->setupGCM(); - } - } else { - $this->iv = $this->origIV; - } - - if ($this->iv === false && !in_array($this->mode, [self::MODE_STREAM, self::MODE_ECB])) { - if ($this->mode != self::MODE_GCM || !in_array($this->engine, [self::ENGINE_LIBSODIUM, self::ENGINE_OPENSSL_GCM])) { - throw new InsufficientSetupException('No IV has been defined'); - } - } - - if ($this->key === false) { - throw new InsufficientSetupException('No key has been defined'); - } - - $this->encryptIV = $this->decryptIV = $this->iv; - - switch ($this->engine) { - case self::ENGINE_MCRYPT: - $this->enchanged = $this->dechanged = true; - - set_error_handler(function () { - }); - - if (!isset($this->enmcrypt)) { - static $mcrypt_modes = [ - self::MODE_CTR => 'ctr', - self::MODE_ECB => MCRYPT_MODE_ECB, - self::MODE_CBC => MCRYPT_MODE_CBC, - self::MODE_CFB => 'ncfb', - self::MODE_CFB8 => MCRYPT_MODE_CFB, - self::MODE_OFB => MCRYPT_MODE_NOFB, - self::MODE_OFB8 => MCRYPT_MODE_OFB, - self::MODE_STREAM => MCRYPT_MODE_STREAM, - ]; - - $this->demcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], ''); - $this->enmcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], ''); - - // we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer() - // to workaround mcrypt's broken ncfb implementation in buffered mode - // see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps} - if ($this->mode == self::MODE_CFB) { - $this->ecb = mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, ''); - } - } // else should mcrypt_generic_deinit be called? - - if ($this->mode == self::MODE_CFB) { - mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size)); - } - - restore_error_handler(); - - break; - case self::ENGINE_INTERNAL: - $this->setupKey(); - break; - case self::ENGINE_EVAL: - if ($this->nonIVChanged) { - $this->setupKey(); - $this->setupInlineCrypt(); - } - } - - $this->nonIVChanged = false; - } - - /** - * Pads a string - * - * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize. - * $this->block_size - (strlen($text) % $this->block_size) bytes are added, each of which is equal to - * chr($this->block_size - (strlen($text) % $this->block_size) - * - * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless - * and padding will, hence forth, be enabled. - * - * @see self::unpad() - * @param string $text - * @throws \LengthException if padding is disabled and the plaintext's length is not a multiple of the block size - * @return string - */ - protected function pad($text) - { - $length = strlen($text); - - if (!$this->padding) { - if ($length % $this->block_size == 0) { - return $text; - } else { - throw new \LengthException("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size}). Try enabling padding."); - } - } - - $pad = $this->block_size - ($length % $this->block_size); - - return str_pad($text, $length + $pad, chr($pad)); - } - - /** - * Unpads a string. - * - * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong - * and false will be returned. - * - * @see self::pad() - * @param string $text - * @throws \LengthException if the ciphertext's length is not a multiple of the block size - * @return string - */ - protected function unpad($text) - { - if (!$this->padding) { - return $text; - } - - $length = ord($text[strlen($text) - 1]); - - if (!$length || $length > $this->block_size) { - throw new BadDecryptionException("The ciphertext has an invalid padding length ($length) compared to the block size ({$this->block_size})"); - } - - return substr($text, 0, -$length); - } - - /** - * Setup the performance-optimized function for de/encrypt() - * - * Stores the created (or existing) callback function-name - * in $this->inline_crypt - * - * Internally for phpseclib developers: - * - * _setupInlineCrypt() would be called only if: - * - * - $this->engine === self::ENGINE_EVAL - * - * - each time on _setup(), after(!) _setupKey() - * - * - * This ensures that _setupInlineCrypt() has always a - * full ready2go initializated internal cipher $engine state - * where, for example, the keys already expanded, - * keys/block_size calculated and such. - * - * It is, each time if called, the responsibility of _setupInlineCrypt(): - * - * - to set $this->inline_crypt to a valid and fully working callback function - * as a (faster) replacement for encrypt() / decrypt() - * - * - NOT to create unlimited callback functions (for memory reasons!) - * no matter how often _setupInlineCrypt() would be called. At some - * point of amount they must be generic re-useable. - * - * - the code of _setupInlineCrypt() it self, - * and the generated callback code, - * must be, in following order: - * - 100% safe - * - 100% compatible to encrypt()/decrypt() - * - using only php5+ features/lang-constructs/php-extensions if - * compatibility (down to php4) or fallback is provided - * - readable/maintainable/understandable/commented and... not-cryptic-styled-code :-) - * - >= 10% faster than encrypt()/decrypt() [which is, by the way, - * the reason for the existence of _setupInlineCrypt() :-)] - * - memory-nice - * - short (as good as possible) - * - * Note: - _setupInlineCrypt() is using _createInlineCryptFunction() to create the full callback function code. - * - In case of using inline crypting, _setupInlineCrypt() must extend by the child \phpseclib3\Crypt\* class. - * - The following variable names are reserved: - * - $_* (all variable names prefixed with an underscore) - * - $self (object reference to it self. Do not use $this, but $self instead) - * - $in (the content of $in has to en/decrypt by the generated code) - * - The callback function should not use the 'return' statement, but en/decrypt'ing the content of $in only - * - * {@internal If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt()} - * - * @see self::setup() - * @see self::createInlineCryptFunction() - * @see self::encrypt() - * @see self::decrypt() - */ - //protected function setupInlineCrypt(); - - /** - * Creates the performance-optimized function for en/decrypt() - * - * Internally for phpseclib developers: - * - * _createInlineCryptFunction(): - * - * - merge the $cipher_code [setup'ed by _setupInlineCrypt()] - * with the current [$this->]mode of operation code - * - * - create the $inline function, which called by encrypt() / decrypt() - * as its replacement to speed up the en/decryption operations. - * - * - return the name of the created $inline callback function - * - * - used to speed up en/decryption - * - * - * - * The main reason why can speed up things [up to 50%] this way are: - * - * - using variables more effective then regular. - * (ie no use of expensive arrays but integers $k_0, $k_1 ... - * or even, for example, the pure $key[] values hardcoded) - * - * - avoiding 1000's of function calls of ie _encryptBlock() - * but inlining the crypt operations. - * in the mode of operation for() loop. - * - * - full loop unroll the (sometimes key-dependent) rounds - * avoiding this way ++$i counters and runtime-if's etc... - * - * The basic code architectur of the generated $inline en/decrypt() - * lambda function, in pseudo php, is: - * - * - * +----------------------------------------------------------------------------------------------+ - * | callback $inline = create_function: | - * | lambda_function_0001_crypt_ECB($action, $text) | - * | { | - * | INSERT PHP CODE OF: | - * | $cipher_code['init_crypt']; // general init code. | - * | // ie: $sbox'es declarations used for | - * | // encrypt and decrypt'ing. | - * | | - * | switch ($action) { | - * | case 'encrypt': | - * | INSERT PHP CODE OF: | - * | $cipher_code['init_encrypt']; // encrypt sepcific init code. | - * | ie: specified $key or $box | - * | declarations for encrypt'ing. | - * | | - * | foreach ($ciphertext) { | - * | $in = $block_size of $ciphertext; | - * | | - * | INSERT PHP CODE OF: | - * | $cipher_code['encrypt_block']; // encrypt's (string) $in, which is always: | - * | // strlen($in) == $this->block_size | - * | // here comes the cipher algorithm in action | - * | // for encryption. | - * | // $cipher_code['encrypt_block'] has to | - * | // encrypt the content of the $in variable | - * | | - * | $plaintext .= $in; | - * | } | - * | return $plaintext; | - * | | - * | case 'decrypt': | - * | INSERT PHP CODE OF: | - * | $cipher_code['init_decrypt']; // decrypt sepcific init code | - * | ie: specified $key or $box | - * | declarations for decrypt'ing. | - * | foreach ($plaintext) { | - * | $in = $block_size of $plaintext; | - * | | - * | INSERT PHP CODE OF: | - * | $cipher_code['decrypt_block']; // decrypt's (string) $in, which is always | - * | // strlen($in) == $this->block_size | - * | // here comes the cipher algorithm in action | - * | // for decryption. | - * | // $cipher_code['decrypt_block'] has to | - * | // decrypt the content of the $in variable | - * | $ciphertext .= $in; | - * | } | - * | return $ciphertext; | - * | } | - * | } | - * +----------------------------------------------------------------------------------------------+ - * - * - * See also the \phpseclib3\Crypt\*::_setupInlineCrypt()'s for - * productive inline $cipher_code's how they works. - * - * Structure of: - * - * $cipher_code = [ - * 'init_crypt' => (string) '', // optional - * 'init_encrypt' => (string) '', // optional - * 'init_decrypt' => (string) '', // optional - * 'encrypt_block' => (string) '', // required - * 'decrypt_block' => (string) '' // required - * ]; - * - * - * @see self::setupInlineCrypt() - * @see self::encrypt() - * @see self::decrypt() - * @param array $cipher_code - * @return string (the name of the created callback function) - */ - protected function createInlineCryptFunction($cipher_code) - { - $block_size = $this->block_size; - - // optional - $init_crypt = isset($cipher_code['init_crypt']) ? $cipher_code['init_crypt'] : ''; - $init_encrypt = isset($cipher_code['init_encrypt']) ? $cipher_code['init_encrypt'] : ''; - $init_decrypt = isset($cipher_code['init_decrypt']) ? $cipher_code['init_decrypt'] : ''; - // required - $encrypt_block = $cipher_code['encrypt_block']; - $decrypt_block = $cipher_code['decrypt_block']; - - // Generating mode of operation inline code, - // merged with the $cipher_code algorithm - // for encrypt- and decryption. - switch ($this->mode) { - case self::MODE_ECB: - $encrypt = $init_encrypt . ' - $_ciphertext = ""; - $_plaintext_len = strlen($_text); - - for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') { - $in = substr($_text, $_i, ' . $block_size . '); - ' . $encrypt_block . ' - $_ciphertext.= $in; - } - - return $_ciphertext; - '; - - $decrypt = $init_decrypt . ' - $_plaintext = ""; - $_text = str_pad($_text, strlen($_text) + (' . $block_size . ' - strlen($_text) % ' . $block_size . ') % ' . $block_size . ', chr(0)); - $_ciphertext_len = strlen($_text); - - for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') { - $in = substr($_text, $_i, ' . $block_size . '); - ' . $decrypt_block . ' - $_plaintext.= $in; - } - - return $this->unpad($_plaintext); - '; - break; - case self::MODE_CTR: - $encrypt = $init_encrypt . ' - $_ciphertext = ""; - $_plaintext_len = strlen($_text); - $_xor = $this->encryptIV; - $_buffer = &$this->enbuffer; - if (strlen($_buffer["ciphertext"])) { - for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') { - $_block = substr($_text, $_i, ' . $block_size . '); - if (strlen($_block) > strlen($_buffer["ciphertext"])) { - $in = $_xor; - ' . $encrypt_block . ' - \phpseclib3\Common\Functions\Strings::increment_str($_xor); - $_buffer["ciphertext"].= $in; - } - $_key = \phpseclib3\Common\Functions\Strings::shift($_buffer["ciphertext"], ' . $block_size . '); - $_ciphertext.= $_block ^ $_key; - } - } else { - for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') { - $_block = substr($_text, $_i, ' . $block_size . '); - $in = $_xor; - ' . $encrypt_block . ' - \phpseclib3\Common\Functions\Strings::increment_str($_xor); - $_key = $in; - $_ciphertext.= $_block ^ $_key; - } - } - if ($this->continuousBuffer) { - $this->encryptIV = $_xor; - if ($_start = $_plaintext_len % ' . $block_size . ') { - $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"]; - } - } - - return $_ciphertext; - '; - - $decrypt = $init_encrypt . ' - $_plaintext = ""; - $_ciphertext_len = strlen($_text); - $_xor = $this->decryptIV; - $_buffer = &$this->debuffer; - - if (strlen($_buffer["ciphertext"])) { - for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') { - $_block = substr($_text, $_i, ' . $block_size . '); - if (strlen($_block) > strlen($_buffer["ciphertext"])) { - $in = $_xor; - ' . $encrypt_block . ' - \phpseclib3\Common\Functions\Strings::increment_str($_xor); - $_buffer["ciphertext"].= $in; - } - $_key = \phpseclib3\Common\Functions\Strings::shift($_buffer["ciphertext"], ' . $block_size . '); - $_plaintext.= $_block ^ $_key; - } - } else { - for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') { - $_block = substr($_text, $_i, ' . $block_size . '); - $in = $_xor; - ' . $encrypt_block . ' - \phpseclib3\Common\Functions\Strings::increment_str($_xor); - $_key = $in; - $_plaintext.= $_block ^ $_key; - } - } - if ($this->continuousBuffer) { - $this->decryptIV = $_xor; - if ($_start = $_ciphertext_len % ' . $block_size . ') { - $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"]; - } - } - - return $_plaintext; - '; - break; - case self::MODE_CFB: - $encrypt = $init_encrypt . ' - $_ciphertext = ""; - $_buffer = &$this->enbuffer; - - if ($this->continuousBuffer) { - $_iv = &$this->encryptIV; - $_pos = &$_buffer["pos"]; - } else { - $_iv = $this->encryptIV; - $_pos = 0; - } - $_len = strlen($_text); - $_i = 0; - if ($_pos) { - $_orig_pos = $_pos; - $_max = ' . $block_size . ' - $_pos; - if ($_len >= $_max) { - $_i = $_max; - $_len-= $_max; - $_pos = 0; - } else { - $_i = $_len; - $_pos+= $_len; - $_len = 0; - } - $_ciphertext = substr($_iv, $_orig_pos) ^ $_text; - $_iv = substr_replace($_iv, $_ciphertext, $_orig_pos, $_i); - } - while ($_len >= ' . $block_size . ') { - $in = $_iv; - ' . $encrypt_block . '; - $_iv = $in ^ substr($_text, $_i, ' . $block_size . '); - $_ciphertext.= $_iv; - $_len-= ' . $block_size . '; - $_i+= ' . $block_size . '; - } - if ($_len) { - $in = $_iv; - ' . $encrypt_block . ' - $_iv = $in; - $_block = $_iv ^ substr($_text, $_i); - $_iv = substr_replace($_iv, $_block, 0, $_len); - $_ciphertext.= $_block; - $_pos = $_len; - } - return $_ciphertext; - '; - - $decrypt = $init_encrypt . ' - $_plaintext = ""; - $_buffer = &$this->debuffer; - - if ($this->continuousBuffer) { - $_iv = &$this->decryptIV; - $_pos = &$_buffer["pos"]; - } else { - $_iv = $this->decryptIV; - $_pos = 0; - } - $_len = strlen($_text); - $_i = 0; - if ($_pos) { - $_orig_pos = $_pos; - $_max = ' . $block_size . ' - $_pos; - if ($_len >= $_max) { - $_i = $_max; - $_len-= $_max; - $_pos = 0; - } else { - $_i = $_len; - $_pos+= $_len; - $_len = 0; - } - $_plaintext = substr($_iv, $_orig_pos) ^ $_text; - $_iv = substr_replace($_iv, substr($_text, 0, $_i), $_orig_pos, $_i); - } - while ($_len >= ' . $block_size . ') { - $in = $_iv; - ' . $encrypt_block . ' - $_iv = $in; - $cb = substr($_text, $_i, ' . $block_size . '); - $_plaintext.= $_iv ^ $cb; - $_iv = $cb; - $_len-= ' . $block_size . '; - $_i+= ' . $block_size . '; - } - if ($_len) { - $in = $_iv; - ' . $encrypt_block . ' - $_iv = $in; - $_plaintext.= $_iv ^ substr($_text, $_i); - $_iv = substr_replace($_iv, substr($_text, $_i), 0, $_len); - $_pos = $_len; - } - - return $_plaintext; - '; - break; - case self::MODE_CFB8: - $encrypt = $init_encrypt . ' - $_ciphertext = ""; - $_len = strlen($_text); - $_iv = $this->encryptIV; - - for ($_i = 0; $_i < $_len; ++$_i) { - $in = $_iv; - ' . $encrypt_block . ' - $_ciphertext .= ($_c = $_text[$_i] ^ $in); - $_iv = substr($_iv, 1) . $_c; - } - - if ($this->continuousBuffer) { - if ($_len >= ' . $block_size . ') { - $this->encryptIV = substr($_ciphertext, -' . $block_size . '); - } else { - $this->encryptIV = substr($this->encryptIV, $_len - ' . $block_size . ') . substr($_ciphertext, -$_len); - } - } - - return $_ciphertext; - '; - $decrypt = $init_encrypt . ' - $_plaintext = ""; - $_len = strlen($_text); - $_iv = $this->decryptIV; - - for ($_i = 0; $_i < $_len; ++$_i) { - $in = $_iv; - ' . $encrypt_block . ' - $_plaintext .= $_text[$_i] ^ $in; - $_iv = substr($_iv, 1) . $_text[$_i]; - } - - if ($this->continuousBuffer) { - if ($_len >= ' . $block_size . ') { - $this->decryptIV = substr($_text, -' . $block_size . '); - } else { - $this->decryptIV = substr($this->decryptIV, $_len - ' . $block_size . ') . substr($_text, -$_len); - } - } - - return $_plaintext; - '; - break; - case self::MODE_OFB8: - $encrypt = $init_encrypt . ' - $_ciphertext = ""; - $_len = strlen($_text); - $_iv = $this->encryptIV; - - for ($_i = 0; $_i < $_len; ++$_i) { - $in = $_iv; - ' . $encrypt_block . ' - $_ciphertext.= $_text[$_i] ^ $in; - $_iv = substr($_iv, 1) . $in[0]; - } - - if ($this->continuousBuffer) { - $this->encryptIV = $_iv; - } - - return $_ciphertext; - '; - $decrypt = $init_encrypt . ' - $_plaintext = ""; - $_len = strlen($_text); - $_iv = $this->decryptIV; - - for ($_i = 0; $_i < $_len; ++$_i) { - $in = $_iv; - ' . $encrypt_block . ' - $_plaintext.= $_text[$_i] ^ $in; - $_iv = substr($_iv, 1) . $in[0]; - } - - if ($this->continuousBuffer) { - $this->decryptIV = $_iv; - } - - return $_plaintext; - '; - break; - case self::MODE_OFB: - $encrypt = $init_encrypt . ' - $_ciphertext = ""; - $_plaintext_len = strlen($_text); - $_xor = $this->encryptIV; - $_buffer = &$this->enbuffer; - - if (strlen($_buffer["xor"])) { - for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') { - $_block = substr($_text, $_i, ' . $block_size . '); - if (strlen($_block) > strlen($_buffer["xor"])) { - $in = $_xor; - ' . $encrypt_block . ' - $_xor = $in; - $_buffer["xor"].= $_xor; - } - $_key = \phpseclib3\Common\Functions\Strings::shift($_buffer["xor"], ' . $block_size . '); - $_ciphertext.= $_block ^ $_key; - } - } else { - for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') { - $in = $_xor; - ' . $encrypt_block . ' - $_xor = $in; - $_ciphertext.= substr($_text, $_i, ' . $block_size . ') ^ $_xor; - } - $_key = $_xor; - } - if ($this->continuousBuffer) { - $this->encryptIV = $_xor; - if ($_start = $_plaintext_len % ' . $block_size . ') { - $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"]; - } - } - return $_ciphertext; - '; - - $decrypt = $init_encrypt . ' - $_plaintext = ""; - $_ciphertext_len = strlen($_text); - $_xor = $this->decryptIV; - $_buffer = &$this->debuffer; - - if (strlen($_buffer["xor"])) { - for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') { - $_block = substr($_text, $_i, ' . $block_size . '); - if (strlen($_block) > strlen($_buffer["xor"])) { - $in = $_xor; - ' . $encrypt_block . ' - $_xor = $in; - $_buffer["xor"].= $_xor; - } - $_key = \phpseclib3\Common\Functions\Strings::shift($_buffer["xor"], ' . $block_size . '); - $_plaintext.= $_block ^ $_key; - } - } else { - for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') { - $in = $_xor; - ' . $encrypt_block . ' - $_xor = $in; - $_plaintext.= substr($_text, $_i, ' . $block_size . ') ^ $_xor; - } - $_key = $_xor; - } - if ($this->continuousBuffer) { - $this->decryptIV = $_xor; - if ($_start = $_ciphertext_len % ' . $block_size . ') { - $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"]; - } - } - return $_plaintext; - '; - break; - case self::MODE_STREAM: - $encrypt = $init_encrypt . ' - $_ciphertext = ""; - ' . $encrypt_block . ' - return $_ciphertext; - '; - $decrypt = $init_decrypt . ' - $_plaintext = ""; - ' . $decrypt_block . ' - return $_plaintext; - '; - break; - // case self::MODE_CBC: - default: - $encrypt = $init_encrypt . ' - $_ciphertext = ""; - $_plaintext_len = strlen($_text); - - $in = $this->encryptIV; - - for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') { - $in = substr($_text, $_i, ' . $block_size . ') ^ $in; - ' . $encrypt_block . ' - $_ciphertext.= $in; - } - - if ($this->continuousBuffer) { - $this->encryptIV = $in; - } - - return $_ciphertext; - '; - - $decrypt = $init_decrypt . ' - $_plaintext = ""; - $_text = str_pad($_text, strlen($_text) + (' . $block_size . ' - strlen($_text) % ' . $block_size . ') % ' . $block_size . ', chr(0)); - $_ciphertext_len = strlen($_text); - - $_iv = $this->decryptIV; - - for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') { - $in = $_block = substr($_text, $_i, ' . $block_size . '); - ' . $decrypt_block . ' - $_plaintext.= $in ^ $_iv; - $_iv = $_block; - } - - if ($this->continuousBuffer) { - $this->decryptIV = $_iv; - } - - return $this->unpad($_plaintext); - '; - break; - } - - // Before discrediting this, please read the following: - // @see https://github.com/phpseclib/phpseclib/issues/1293 - // @see https://github.com/phpseclib/phpseclib/pull/1143 - eval('$func = function ($_action, $_text) { ' . $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }};'); - - return \Closure::bind($func, $this, static::class); - } - - /** - * Convert float to int - * - * On ARM CPUs converting floats to ints doesn't always work - * - * @param string $x - * @return int - */ - protected static function safe_intval($x) - { - if (is_int($x)) { - return $x; - } - - if (self::$use_reg_intval) { - return PHP_INT_SIZE == 4 && PHP_VERSION_ID >= 80100 ? intval($x) : $x; - } - - return (fmod($x, 0x80000000) & 0x7FFFFFFF) | - ((fmod(floor($x / 0x80000000), 2) & 1) << 31); - } - - /** - * eval()'able string for in-line float to int - * - * @return string - */ - protected static function safe_intval_inline() - { - if (self::$use_reg_intval) { - return PHP_INT_SIZE == 4 && PHP_VERSION_ID >= 80100 ? 'intval(%s)' : '%s'; - } - - $safeint = '(is_int($temp = %s) ? $temp : (fmod($temp, 0x80000000) & 0x7FFFFFFF) | '; - return $safeint . '((fmod(floor($temp / 0x80000000), 2) & 1) << 31))'; - } - - /** - * Sets up GCM parameters - * - * See steps 1-2 of https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf#page=23 - * for more info - * - */ - private function setupGCM() - { - // don't keep on re-calculating $this->h - if (!$this->h || $this->hKey != $this->key) { - $cipher = new static('ecb'); - $cipher->setKey($this->key); - $cipher->disablePadding(); - - $this->h = self::$gcmField->newInteger( - Strings::switchEndianness($cipher->encrypt("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")) - ); - $this->hKey = $this->key; - } - - if (strlen($this->nonce) == 12) { - $this->iv = $this->nonce . "\0\0\0\1"; - } else { - $this->iv = $this->ghash( - self::nullPad128($this->nonce) . str_repeat("\0", 8) . self::len64($this->nonce) - ); - } - } - - /** - * Performs GHASH operation - * - * See https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf#page=20 - * for more info - * - * @see self::decrypt() - * @see self::encrypt() - * @param string $x - * @return string - */ - private function ghash($x) - { - $h = $this->h; - $y = ["\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"]; - $x = str_split($x, 16); - $n = 0; - // the switchEndianness calls are necessary because the multiplication algorithm in BinaryField/Integer - // interprets strings as polynomials in big endian order whereas in GCM they're interpreted in little - // endian order per https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf#page=19. - // big endian order is what binary field elliptic curves use per http://www.secg.org/sec1-v2.pdf#page=18. - - // we could switchEndianness here instead of in the while loop but doing so in the while loop seems like it - // might be slightly more performant - //$x = Strings::switchEndianness($x); - foreach ($x as $xn) { - $xn = Strings::switchEndianness($xn); - $t = $y[$n] ^ $xn; - $temp = self::$gcmField->newInteger($t); - $y[++$n] = $temp->multiply($h)->toBytes(); - $y[$n] = substr($y[$n], 1); - } - $y[$n] = Strings::switchEndianness($y[$n]); - return $y[$n]; - } - - /** - * Returns the bit length of a string in a packed format - * - * @see self::decrypt() - * @see self::encrypt() - * @see self::setupGCM() - * @param string $str - * @return string - */ - private static function len64($str) - { - return "\0\0\0\0" . pack('N', 8 * strlen($str)); - } - - /** - * NULL pads a string to be a multiple of 128 - * - * @see self::decrypt() - * @see self::encrypt() - * @see self::setupGCM() - * @param string $str - * @return string - */ - protected static function nullPad128($str) - { - $len = strlen($str); - return $str . str_repeat("\0", 16 * ceil($len / 16) - $len); - } - - /** - * Calculates Poly1305 MAC - * - * On my system ChaCha20, with libsodium, takes 0.5s. With this custom Poly1305 implementation - * it takes 1.2s. - * - * @see self::decrypt() - * @see self::encrypt() - * @param string $text - * @return string - */ - protected function poly1305($text) - { - $s = $this->poly1305Key; // strlen($this->poly1305Key) == 32 - $r = Strings::shift($s, 16); - $r = strrev($r); - $r &= "\x0f\xff\xff\xfc\x0f\xff\xff\xfc\x0f\xff\xff\xfc\x0f\xff\xff\xff"; - $s = strrev($s); - - $r = self::$poly1305Field->newInteger(new BigInteger($r, 256)); - $s = self::$poly1305Field->newInteger(new BigInteger($s, 256)); - $a = self::$poly1305Field->newInteger(new BigInteger()); - - $blocks = str_split($text, 16); - foreach ($blocks as $block) { - $n = strrev($block . chr(1)); - $n = self::$poly1305Field->newInteger(new BigInteger($n, 256)); - $a = $a->add($n); - $a = $a->multiply($r); - } - $r = $a->toBigInteger()->add($s->toBigInteger()); - $mask = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"; - return strrev($r->toBytes()) & $mask; - } - - /** - * Return the mode - * - * You can do $obj instanceof AES or whatever to get the cipher but you can't do that to get the mode - * - * @return string - */ - public function getMode() - { - return array_flip(self::MODE_MAP)[$this->mode]; - } - - /** - * Is the continuous buffer enabled? - * - * @return boolean - */ - public function continuousBufferEnabled() - { - return $this->continuousBuffer; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Traits/Fingerprint.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Traits/Fingerprint.php deleted file mode 100644 index 9ca8926d..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Traits/Fingerprint.php +++ /dev/null @@ -1,57 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\Common\Traits; - -use phpseclib3\Crypt\Hash; - -/** - * Fingerprint Trait for Private Keys - * - * @author Jim Wigginton - */ -trait Fingerprint -{ - /** - * Returns the public key's fingerprint - * - * The public key's fingerprint is returned, which is equivalent to running `ssh-keygen -lf rsa.pub`. If there is - * no public key currently loaded, false is returned. - * Example output (md5): "c1:b1:30:29:d7:b8:de:6c:97:77:10:d7:46:41:63:87" (as specified by RFC 4716) - * - * @param string $algorithm The hashing algorithm to be used. Valid options are 'md5' and 'sha256'. False is returned - * for invalid values. - * @return mixed - */ - public function getFingerprint($algorithm = 'md5') - { - $type = self::validatePlugin('Keys', 'OpenSSH', 'savePublicKey'); - if ($type === false) { - return false; - } - $key = $this->toString('OpenSSH', ['binary' => true]); - if ($key === false) { - return false; - } - switch ($algorithm) { - case 'sha256': - $hash = new Hash('sha256'); - $base = base64_encode($hash->hash($key)); - return substr($base, 0, strlen($base) - 1); - case 'md5': - return substr(chunk_split(md5($key), 2, ':'), 0, -1); - default: - return false; - } - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Traits/PasswordProtected.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Traits/PasswordProtected.php deleted file mode 100644 index 0ac274e8..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Traits/PasswordProtected.php +++ /dev/null @@ -1,46 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\Common\Traits; - -/** - * Password Protected Trait for Private Keys - * - * @author Jim Wigginton - */ -trait PasswordProtected -{ - /** - * Password - * - * @var string|bool - */ - private $password = false; - - /** - * Sets the password - * - * Private keys can be encrypted with a password. To unset the password, pass in the empty string or false. - * Or rather, pass in $password such that empty($password) && !is_string($password) is true. - * - * @see self::createKey() - * @see self::load() - * @param string|bool $password - */ - public function withPassword($password = false) - { - $new = clone $this; - $new->password = $password; - return $new; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DES.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DES.php deleted file mode 100644 index 3b038300..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DES.php +++ /dev/null @@ -1,1392 +0,0 @@ - - * setKey('abcdefgh'); - * - * $size = 10 * 1024; - * $plaintext = ''; - * for ($i = 0; $i < $size; $i++) { - * $plaintext.= 'a'; - * } - * - * echo $des->decrypt($des->encrypt($plaintext)); - * ?> - * - * - * @author Jim Wigginton - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt; - -use phpseclib3\Crypt\Common\BlockCipher; -use phpseclib3\Exception\BadModeException; - -/** - * Pure-PHP implementation of DES. - * - * @author Jim Wigginton - */ -class DES extends BlockCipher -{ - /** - * Contains $keys[self::ENCRYPT] - * - * @see \phpseclib3\Crypt\DES::setupKey() - * @see \phpseclib3\Crypt\DES::processBlock() - */ - const ENCRYPT = 0; - /** - * Contains $keys[self::DECRYPT] - * - * @see \phpseclib3\Crypt\DES::setupKey() - * @see \phpseclib3\Crypt\DES::processBlock() - */ - const DECRYPT = 1; - - /** - * Block Length of the cipher - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::block_size - * @var int - */ - protected $block_size = 8; - - /** - * Key Length (in bytes) - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::setKeyLength() - * @var int - */ - protected $key_length = 8; - - /** - * The mcrypt specific name of the cipher - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt - * @var string - */ - protected $cipher_name_mcrypt = 'des'; - - /** - * The OpenSSL names of the cipher / modes - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::openssl_mode_names - * @var array - */ - protected $openssl_mode_names = [ - self::MODE_ECB => 'des-ecb', - self::MODE_CBC => 'des-cbc', - self::MODE_CFB => 'des-cfb', - self::MODE_OFB => 'des-ofb' - // self::MODE_CTR is undefined for DES - ]; - - /** - * Optimizing value while CFB-encrypting - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len - * @var int - */ - protected $cfb_init_len = 500; - - /** - * Switch for DES/3DES encryption - * - * Used only if $engine == self::ENGINE_INTERNAL - * - * @see self::setupKey() - * @see self::processBlock() - * @var int - */ - protected $des_rounds = 1; - - /** - * max possible size of $key - * - * @see self::setKey() - * @var string - */ - protected $key_length_max = 8; - - /** - * The Key Schedule - * - * @see self::setupKey() - * @var array - */ - private $keys; - - /** - * Key Cache "key" - * - * @see self::setupKey() - * @var array - */ - private $kl; - - /** - * Shuffle table. - * - * For each byte value index, the entry holds an 8-byte string - * with each byte containing all bits in the same state as the - * corresponding bit in the index value. - * - * @see self::processBlock() - * @see self::setupKey() - * @var array - */ - protected static $shuffle = [ - "\x00\x00\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00\x00\x00\x00\xFF", - "\x00\x00\x00\x00\x00\x00\xFF\x00", "\x00\x00\x00\x00\x00\x00\xFF\xFF", - "\x00\x00\x00\x00\x00\xFF\x00\x00", "\x00\x00\x00\x00\x00\xFF\x00\xFF", - "\x00\x00\x00\x00\x00\xFF\xFF\x00", "\x00\x00\x00\x00\x00\xFF\xFF\xFF", - "\x00\x00\x00\x00\xFF\x00\x00\x00", "\x00\x00\x00\x00\xFF\x00\x00\xFF", - "\x00\x00\x00\x00\xFF\x00\xFF\x00", "\x00\x00\x00\x00\xFF\x00\xFF\xFF", - "\x00\x00\x00\x00\xFF\xFF\x00\x00", "\x00\x00\x00\x00\xFF\xFF\x00\xFF", - "\x00\x00\x00\x00\xFF\xFF\xFF\x00", "\x00\x00\x00\x00\xFF\xFF\xFF\xFF", - "\x00\x00\x00\xFF\x00\x00\x00\x00", "\x00\x00\x00\xFF\x00\x00\x00\xFF", - "\x00\x00\x00\xFF\x00\x00\xFF\x00", "\x00\x00\x00\xFF\x00\x00\xFF\xFF", - "\x00\x00\x00\xFF\x00\xFF\x00\x00", "\x00\x00\x00\xFF\x00\xFF\x00\xFF", - "\x00\x00\x00\xFF\x00\xFF\xFF\x00", "\x00\x00\x00\xFF\x00\xFF\xFF\xFF", - "\x00\x00\x00\xFF\xFF\x00\x00\x00", "\x00\x00\x00\xFF\xFF\x00\x00\xFF", - "\x00\x00\x00\xFF\xFF\x00\xFF\x00", "\x00\x00\x00\xFF\xFF\x00\xFF\xFF", - "\x00\x00\x00\xFF\xFF\xFF\x00\x00", "\x00\x00\x00\xFF\xFF\xFF\x00\xFF", - "\x00\x00\x00\xFF\xFF\xFF\xFF\x00", "\x00\x00\x00\xFF\xFF\xFF\xFF\xFF", - "\x00\x00\xFF\x00\x00\x00\x00\x00", "\x00\x00\xFF\x00\x00\x00\x00\xFF", - "\x00\x00\xFF\x00\x00\x00\xFF\x00", "\x00\x00\xFF\x00\x00\x00\xFF\xFF", - "\x00\x00\xFF\x00\x00\xFF\x00\x00", "\x00\x00\xFF\x00\x00\xFF\x00\xFF", - "\x00\x00\xFF\x00\x00\xFF\xFF\x00", "\x00\x00\xFF\x00\x00\xFF\xFF\xFF", - "\x00\x00\xFF\x00\xFF\x00\x00\x00", "\x00\x00\xFF\x00\xFF\x00\x00\xFF", - "\x00\x00\xFF\x00\xFF\x00\xFF\x00", "\x00\x00\xFF\x00\xFF\x00\xFF\xFF", - "\x00\x00\xFF\x00\xFF\xFF\x00\x00", "\x00\x00\xFF\x00\xFF\xFF\x00\xFF", - "\x00\x00\xFF\x00\xFF\xFF\xFF\x00", "\x00\x00\xFF\x00\xFF\xFF\xFF\xFF", - "\x00\x00\xFF\xFF\x00\x00\x00\x00", "\x00\x00\xFF\xFF\x00\x00\x00\xFF", - "\x00\x00\xFF\xFF\x00\x00\xFF\x00", "\x00\x00\xFF\xFF\x00\x00\xFF\xFF", - "\x00\x00\xFF\xFF\x00\xFF\x00\x00", "\x00\x00\xFF\xFF\x00\xFF\x00\xFF", - "\x00\x00\xFF\xFF\x00\xFF\xFF\x00", "\x00\x00\xFF\xFF\x00\xFF\xFF\xFF", - "\x00\x00\xFF\xFF\xFF\x00\x00\x00", "\x00\x00\xFF\xFF\xFF\x00\x00\xFF", - "\x00\x00\xFF\xFF\xFF\x00\xFF\x00", "\x00\x00\xFF\xFF\xFF\x00\xFF\xFF", - "\x00\x00\xFF\xFF\xFF\xFF\x00\x00", "\x00\x00\xFF\xFF\xFF\xFF\x00\xFF", - "\x00\x00\xFF\xFF\xFF\xFF\xFF\x00", "\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF", - "\x00\xFF\x00\x00\x00\x00\x00\x00", "\x00\xFF\x00\x00\x00\x00\x00\xFF", - "\x00\xFF\x00\x00\x00\x00\xFF\x00", "\x00\xFF\x00\x00\x00\x00\xFF\xFF", - "\x00\xFF\x00\x00\x00\xFF\x00\x00", "\x00\xFF\x00\x00\x00\xFF\x00\xFF", - "\x00\xFF\x00\x00\x00\xFF\xFF\x00", "\x00\xFF\x00\x00\x00\xFF\xFF\xFF", - "\x00\xFF\x00\x00\xFF\x00\x00\x00", "\x00\xFF\x00\x00\xFF\x00\x00\xFF", - "\x00\xFF\x00\x00\xFF\x00\xFF\x00", "\x00\xFF\x00\x00\xFF\x00\xFF\xFF", - "\x00\xFF\x00\x00\xFF\xFF\x00\x00", "\x00\xFF\x00\x00\xFF\xFF\x00\xFF", - "\x00\xFF\x00\x00\xFF\xFF\xFF\x00", "\x00\xFF\x00\x00\xFF\xFF\xFF\xFF", - "\x00\xFF\x00\xFF\x00\x00\x00\x00", "\x00\xFF\x00\xFF\x00\x00\x00\xFF", - "\x00\xFF\x00\xFF\x00\x00\xFF\x00", "\x00\xFF\x00\xFF\x00\x00\xFF\xFF", - "\x00\xFF\x00\xFF\x00\xFF\x00\x00", "\x00\xFF\x00\xFF\x00\xFF\x00\xFF", - "\x00\xFF\x00\xFF\x00\xFF\xFF\x00", "\x00\xFF\x00\xFF\x00\xFF\xFF\xFF", - "\x00\xFF\x00\xFF\xFF\x00\x00\x00", "\x00\xFF\x00\xFF\xFF\x00\x00\xFF", - "\x00\xFF\x00\xFF\xFF\x00\xFF\x00", "\x00\xFF\x00\xFF\xFF\x00\xFF\xFF", - "\x00\xFF\x00\xFF\xFF\xFF\x00\x00", "\x00\xFF\x00\xFF\xFF\xFF\x00\xFF", - "\x00\xFF\x00\xFF\xFF\xFF\xFF\x00", "\x00\xFF\x00\xFF\xFF\xFF\xFF\xFF", - "\x00\xFF\xFF\x00\x00\x00\x00\x00", "\x00\xFF\xFF\x00\x00\x00\x00\xFF", - "\x00\xFF\xFF\x00\x00\x00\xFF\x00", "\x00\xFF\xFF\x00\x00\x00\xFF\xFF", - "\x00\xFF\xFF\x00\x00\xFF\x00\x00", "\x00\xFF\xFF\x00\x00\xFF\x00\xFF", - "\x00\xFF\xFF\x00\x00\xFF\xFF\x00", "\x00\xFF\xFF\x00\x00\xFF\xFF\xFF", - "\x00\xFF\xFF\x00\xFF\x00\x00\x00", "\x00\xFF\xFF\x00\xFF\x00\x00\xFF", - "\x00\xFF\xFF\x00\xFF\x00\xFF\x00", "\x00\xFF\xFF\x00\xFF\x00\xFF\xFF", - "\x00\xFF\xFF\x00\xFF\xFF\x00\x00", "\x00\xFF\xFF\x00\xFF\xFF\x00\xFF", - "\x00\xFF\xFF\x00\xFF\xFF\xFF\x00", "\x00\xFF\xFF\x00\xFF\xFF\xFF\xFF", - "\x00\xFF\xFF\xFF\x00\x00\x00\x00", "\x00\xFF\xFF\xFF\x00\x00\x00\xFF", - "\x00\xFF\xFF\xFF\x00\x00\xFF\x00", "\x00\xFF\xFF\xFF\x00\x00\xFF\xFF", - "\x00\xFF\xFF\xFF\x00\xFF\x00\x00", "\x00\xFF\xFF\xFF\x00\xFF\x00\xFF", - "\x00\xFF\xFF\xFF\x00\xFF\xFF\x00", "\x00\xFF\xFF\xFF\x00\xFF\xFF\xFF", - "\x00\xFF\xFF\xFF\xFF\x00\x00\x00", "\x00\xFF\xFF\xFF\xFF\x00\x00\xFF", - "\x00\xFF\xFF\xFF\xFF\x00\xFF\x00", "\x00\xFF\xFF\xFF\xFF\x00\xFF\xFF", - "\x00\xFF\xFF\xFF\xFF\xFF\x00\x00", "\x00\xFF\xFF\xFF\xFF\xFF\x00\xFF", - "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00", "\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF", - "\xFF\x00\x00\x00\x00\x00\x00\x00", "\xFF\x00\x00\x00\x00\x00\x00\xFF", - "\xFF\x00\x00\x00\x00\x00\xFF\x00", "\xFF\x00\x00\x00\x00\x00\xFF\xFF", - "\xFF\x00\x00\x00\x00\xFF\x00\x00", "\xFF\x00\x00\x00\x00\xFF\x00\xFF", - "\xFF\x00\x00\x00\x00\xFF\xFF\x00", "\xFF\x00\x00\x00\x00\xFF\xFF\xFF", - "\xFF\x00\x00\x00\xFF\x00\x00\x00", "\xFF\x00\x00\x00\xFF\x00\x00\xFF", - "\xFF\x00\x00\x00\xFF\x00\xFF\x00", "\xFF\x00\x00\x00\xFF\x00\xFF\xFF", - "\xFF\x00\x00\x00\xFF\xFF\x00\x00", "\xFF\x00\x00\x00\xFF\xFF\x00\xFF", - "\xFF\x00\x00\x00\xFF\xFF\xFF\x00", "\xFF\x00\x00\x00\xFF\xFF\xFF\xFF", - "\xFF\x00\x00\xFF\x00\x00\x00\x00", "\xFF\x00\x00\xFF\x00\x00\x00\xFF", - "\xFF\x00\x00\xFF\x00\x00\xFF\x00", "\xFF\x00\x00\xFF\x00\x00\xFF\xFF", - "\xFF\x00\x00\xFF\x00\xFF\x00\x00", "\xFF\x00\x00\xFF\x00\xFF\x00\xFF", - "\xFF\x00\x00\xFF\x00\xFF\xFF\x00", "\xFF\x00\x00\xFF\x00\xFF\xFF\xFF", - "\xFF\x00\x00\xFF\xFF\x00\x00\x00", "\xFF\x00\x00\xFF\xFF\x00\x00\xFF", - "\xFF\x00\x00\xFF\xFF\x00\xFF\x00", "\xFF\x00\x00\xFF\xFF\x00\xFF\xFF", - "\xFF\x00\x00\xFF\xFF\xFF\x00\x00", "\xFF\x00\x00\xFF\xFF\xFF\x00\xFF", - "\xFF\x00\x00\xFF\xFF\xFF\xFF\x00", "\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF", - "\xFF\x00\xFF\x00\x00\x00\x00\x00", "\xFF\x00\xFF\x00\x00\x00\x00\xFF", - "\xFF\x00\xFF\x00\x00\x00\xFF\x00", "\xFF\x00\xFF\x00\x00\x00\xFF\xFF", - "\xFF\x00\xFF\x00\x00\xFF\x00\x00", "\xFF\x00\xFF\x00\x00\xFF\x00\xFF", - "\xFF\x00\xFF\x00\x00\xFF\xFF\x00", "\xFF\x00\xFF\x00\x00\xFF\xFF\xFF", - "\xFF\x00\xFF\x00\xFF\x00\x00\x00", "\xFF\x00\xFF\x00\xFF\x00\x00\xFF", - "\xFF\x00\xFF\x00\xFF\x00\xFF\x00", "\xFF\x00\xFF\x00\xFF\x00\xFF\xFF", - "\xFF\x00\xFF\x00\xFF\xFF\x00\x00", "\xFF\x00\xFF\x00\xFF\xFF\x00\xFF", - "\xFF\x00\xFF\x00\xFF\xFF\xFF\x00", "\xFF\x00\xFF\x00\xFF\xFF\xFF\xFF", - "\xFF\x00\xFF\xFF\x00\x00\x00\x00", "\xFF\x00\xFF\xFF\x00\x00\x00\xFF", - "\xFF\x00\xFF\xFF\x00\x00\xFF\x00", "\xFF\x00\xFF\xFF\x00\x00\xFF\xFF", - "\xFF\x00\xFF\xFF\x00\xFF\x00\x00", "\xFF\x00\xFF\xFF\x00\xFF\x00\xFF", - "\xFF\x00\xFF\xFF\x00\xFF\xFF\x00", "\xFF\x00\xFF\xFF\x00\xFF\xFF\xFF", - "\xFF\x00\xFF\xFF\xFF\x00\x00\x00", "\xFF\x00\xFF\xFF\xFF\x00\x00\xFF", - "\xFF\x00\xFF\xFF\xFF\x00\xFF\x00", "\xFF\x00\xFF\xFF\xFF\x00\xFF\xFF", - "\xFF\x00\xFF\xFF\xFF\xFF\x00\x00", "\xFF\x00\xFF\xFF\xFF\xFF\x00\xFF", - "\xFF\x00\xFF\xFF\xFF\xFF\xFF\x00", "\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF", - "\xFF\xFF\x00\x00\x00\x00\x00\x00", "\xFF\xFF\x00\x00\x00\x00\x00\xFF", - "\xFF\xFF\x00\x00\x00\x00\xFF\x00", "\xFF\xFF\x00\x00\x00\x00\xFF\xFF", - "\xFF\xFF\x00\x00\x00\xFF\x00\x00", "\xFF\xFF\x00\x00\x00\xFF\x00\xFF", - "\xFF\xFF\x00\x00\x00\xFF\xFF\x00", "\xFF\xFF\x00\x00\x00\xFF\xFF\xFF", - "\xFF\xFF\x00\x00\xFF\x00\x00\x00", "\xFF\xFF\x00\x00\xFF\x00\x00\xFF", - "\xFF\xFF\x00\x00\xFF\x00\xFF\x00", "\xFF\xFF\x00\x00\xFF\x00\xFF\xFF", - "\xFF\xFF\x00\x00\xFF\xFF\x00\x00", "\xFF\xFF\x00\x00\xFF\xFF\x00\xFF", - "\xFF\xFF\x00\x00\xFF\xFF\xFF\x00", "\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF", - "\xFF\xFF\x00\xFF\x00\x00\x00\x00", "\xFF\xFF\x00\xFF\x00\x00\x00\xFF", - "\xFF\xFF\x00\xFF\x00\x00\xFF\x00", "\xFF\xFF\x00\xFF\x00\x00\xFF\xFF", - "\xFF\xFF\x00\xFF\x00\xFF\x00\x00", "\xFF\xFF\x00\xFF\x00\xFF\x00\xFF", - "\xFF\xFF\x00\xFF\x00\xFF\xFF\x00", "\xFF\xFF\x00\xFF\x00\xFF\xFF\xFF", - "\xFF\xFF\x00\xFF\xFF\x00\x00\x00", "\xFF\xFF\x00\xFF\xFF\x00\x00\xFF", - "\xFF\xFF\x00\xFF\xFF\x00\xFF\x00", "\xFF\xFF\x00\xFF\xFF\x00\xFF\xFF", - "\xFF\xFF\x00\xFF\xFF\xFF\x00\x00", "\xFF\xFF\x00\xFF\xFF\xFF\x00\xFF", - "\xFF\xFF\x00\xFF\xFF\xFF\xFF\x00", "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF", - "\xFF\xFF\xFF\x00\x00\x00\x00\x00", "\xFF\xFF\xFF\x00\x00\x00\x00\xFF", - "\xFF\xFF\xFF\x00\x00\x00\xFF\x00", "\xFF\xFF\xFF\x00\x00\x00\xFF\xFF", - "\xFF\xFF\xFF\x00\x00\xFF\x00\x00", "\xFF\xFF\xFF\x00\x00\xFF\x00\xFF", - "\xFF\xFF\xFF\x00\x00\xFF\xFF\x00", "\xFF\xFF\xFF\x00\x00\xFF\xFF\xFF", - "\xFF\xFF\xFF\x00\xFF\x00\x00\x00", "\xFF\xFF\xFF\x00\xFF\x00\x00\xFF", - "\xFF\xFF\xFF\x00\xFF\x00\xFF\x00", "\xFF\xFF\xFF\x00\xFF\x00\xFF\xFF", - "\xFF\xFF\xFF\x00\xFF\xFF\x00\x00", "\xFF\xFF\xFF\x00\xFF\xFF\x00\xFF", - "\xFF\xFF\xFF\x00\xFF\xFF\xFF\x00", "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF", - "\xFF\xFF\xFF\xFF\x00\x00\x00\x00", "\xFF\xFF\xFF\xFF\x00\x00\x00\xFF", - "\xFF\xFF\xFF\xFF\x00\x00\xFF\x00", "\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF", - "\xFF\xFF\xFF\xFF\x00\xFF\x00\x00", "\xFF\xFF\xFF\xFF\x00\xFF\x00\xFF", - "\xFF\xFF\xFF\xFF\x00\xFF\xFF\x00", "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF", - "\xFF\xFF\xFF\xFF\xFF\x00\x00\x00", "\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF", - "\xFF\xFF\xFF\xFF\xFF\x00\xFF\x00", "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF", - "\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00", "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF", - "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00", "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" - ]; - - /** - * IP mapping helper table. - * - * Indexing this table with each source byte performs the initial bit permutation. - * - * @var array - */ - protected static $ipmap = [ - 0x00, 0x10, 0x01, 0x11, 0x20, 0x30, 0x21, 0x31, - 0x02, 0x12, 0x03, 0x13, 0x22, 0x32, 0x23, 0x33, - 0x40, 0x50, 0x41, 0x51, 0x60, 0x70, 0x61, 0x71, - 0x42, 0x52, 0x43, 0x53, 0x62, 0x72, 0x63, 0x73, - 0x04, 0x14, 0x05, 0x15, 0x24, 0x34, 0x25, 0x35, - 0x06, 0x16, 0x07, 0x17, 0x26, 0x36, 0x27, 0x37, - 0x44, 0x54, 0x45, 0x55, 0x64, 0x74, 0x65, 0x75, - 0x46, 0x56, 0x47, 0x57, 0x66, 0x76, 0x67, 0x77, - 0x80, 0x90, 0x81, 0x91, 0xA0, 0xB0, 0xA1, 0xB1, - 0x82, 0x92, 0x83, 0x93, 0xA2, 0xB2, 0xA3, 0xB3, - 0xC0, 0xD0, 0xC1, 0xD1, 0xE0, 0xF0, 0xE1, 0xF1, - 0xC2, 0xD2, 0xC3, 0xD3, 0xE2, 0xF2, 0xE3, 0xF3, - 0x84, 0x94, 0x85, 0x95, 0xA4, 0xB4, 0xA5, 0xB5, - 0x86, 0x96, 0x87, 0x97, 0xA6, 0xB6, 0xA7, 0xB7, - 0xC4, 0xD4, 0xC5, 0xD5, 0xE4, 0xF4, 0xE5, 0xF5, - 0xC6, 0xD6, 0xC7, 0xD7, 0xE6, 0xF6, 0xE7, 0xF7, - 0x08, 0x18, 0x09, 0x19, 0x28, 0x38, 0x29, 0x39, - 0x0A, 0x1A, 0x0B, 0x1B, 0x2A, 0x3A, 0x2B, 0x3B, - 0x48, 0x58, 0x49, 0x59, 0x68, 0x78, 0x69, 0x79, - 0x4A, 0x5A, 0x4B, 0x5B, 0x6A, 0x7A, 0x6B, 0x7B, - 0x0C, 0x1C, 0x0D, 0x1D, 0x2C, 0x3C, 0x2D, 0x3D, - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4C, 0x5C, 0x4D, 0x5D, 0x6C, 0x7C, 0x6D, 0x7D, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x88, 0x98, 0x89, 0x99, 0xA8, 0xB8, 0xA9, 0xB9, - 0x8A, 0x9A, 0x8B, 0x9B, 0xAA, 0xBA, 0xAB, 0xBB, - 0xC8, 0xD8, 0xC9, 0xD9, 0xE8, 0xF8, 0xE9, 0xF9, - 0xCA, 0xDA, 0xCB, 0xDB, 0xEA, 0xFA, 0xEB, 0xFB, - 0x8C, 0x9C, 0x8D, 0x9D, 0xAC, 0xBC, 0xAD, 0xBD, - 0x8E, 0x9E, 0x8F, 0x9F, 0xAE, 0xBE, 0xAF, 0xBF, - 0xCC, 0xDC, 0xCD, 0xDD, 0xEC, 0xFC, 0xED, 0xFD, - 0xCE, 0xDE, 0xCF, 0xDF, 0xEE, 0xFE, 0xEF, 0xFF - ]; - - /** - * Inverse IP mapping helper table. - * Indexing this table with a byte value reverses the bit order. - * - * @var array - */ - protected static $invipmap = [ - 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, - 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, - 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, - 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, - 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, - 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, - 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, - 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, - 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, - 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, - 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, - 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, - 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, - 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, - 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, - 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, - 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, - 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, - 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, - 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, - 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, - 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, - 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, - 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, - 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, - 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, - 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, - 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, - 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, - 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, - 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, - 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF - ]; - - /** - * Pre-permuted S-box1 - * - * Each box ($sbox1-$sbox8) has been vectorized, then each value pre-permuted using the - * P table: concatenation can then be replaced by exclusive ORs. - * - * @var array - */ - protected static $sbox1 = [ - 0x00808200, 0x00000000, 0x00008000, 0x00808202, - 0x00808002, 0x00008202, 0x00000002, 0x00008000, - 0x00000200, 0x00808200, 0x00808202, 0x00000200, - 0x00800202, 0x00808002, 0x00800000, 0x00000002, - 0x00000202, 0x00800200, 0x00800200, 0x00008200, - 0x00008200, 0x00808000, 0x00808000, 0x00800202, - 0x00008002, 0x00800002, 0x00800002, 0x00008002, - 0x00000000, 0x00000202, 0x00008202, 0x00800000, - 0x00008000, 0x00808202, 0x00000002, 0x00808000, - 0x00808200, 0x00800000, 0x00800000, 0x00000200, - 0x00808002, 0x00008000, 0x00008200, 0x00800002, - 0x00000200, 0x00000002, 0x00800202, 0x00008202, - 0x00808202, 0x00008002, 0x00808000, 0x00800202, - 0x00800002, 0x00000202, 0x00008202, 0x00808200, - 0x00000202, 0x00800200, 0x00800200, 0x00000000, - 0x00008002, 0x00008200, 0x00000000, 0x00808002 - ]; - - /** - * Pre-permuted S-box2 - * - * @var array - */ - protected static $sbox2 = [ - 0x40084010, 0x40004000, 0x00004000, 0x00084010, - 0x00080000, 0x00000010, 0x40080010, 0x40004010, - 0x40000010, 0x40084010, 0x40084000, 0x40000000, - 0x40004000, 0x00080000, 0x00000010, 0x40080010, - 0x00084000, 0x00080010, 0x40004010, 0x00000000, - 0x40000000, 0x00004000, 0x00084010, 0x40080000, - 0x00080010, 0x40000010, 0x00000000, 0x00084000, - 0x00004010, 0x40084000, 0x40080000, 0x00004010, - 0x00000000, 0x00084010, 0x40080010, 0x00080000, - 0x40004010, 0x40080000, 0x40084000, 0x00004000, - 0x40080000, 0x40004000, 0x00000010, 0x40084010, - 0x00084010, 0x00000010, 0x00004000, 0x40000000, - 0x00004010, 0x40084000, 0x00080000, 0x40000010, - 0x00080010, 0x40004010, 0x40000010, 0x00080010, - 0x00084000, 0x00000000, 0x40004000, 0x00004010, - 0x40000000, 0x40080010, 0x40084010, 0x00084000 - ]; - - /** - * Pre-permuted S-box3 - * - * @var array - */ - protected static $sbox3 = [ - 0x00000104, 0x04010100, 0x00000000, 0x04010004, - 0x04000100, 0x00000000, 0x00010104, 0x04000100, - 0x00010004, 0x04000004, 0x04000004, 0x00010000, - 0x04010104, 0x00010004, 0x04010000, 0x00000104, - 0x04000000, 0x00000004, 0x04010100, 0x00000100, - 0x00010100, 0x04010000, 0x04010004, 0x00010104, - 0x04000104, 0x00010100, 0x00010000, 0x04000104, - 0x00000004, 0x04010104, 0x00000100, 0x04000000, - 0x04010100, 0x04000000, 0x00010004, 0x00000104, - 0x00010000, 0x04010100, 0x04000100, 0x00000000, - 0x00000100, 0x00010004, 0x04010104, 0x04000100, - 0x04000004, 0x00000100, 0x00000000, 0x04010004, - 0x04000104, 0x00010000, 0x04000000, 0x04010104, - 0x00000004, 0x00010104, 0x00010100, 0x04000004, - 0x04010000, 0x04000104, 0x00000104, 0x04010000, - 0x00010104, 0x00000004, 0x04010004, 0x00010100 - ]; - - /** - * Pre-permuted S-box4 - * - * @var array - */ - protected static $sbox4 = [ - 0x80401000, 0x80001040, 0x80001040, 0x00000040, - 0x00401040, 0x80400040, 0x80400000, 0x80001000, - 0x00000000, 0x00401000, 0x00401000, 0x80401040, - 0x80000040, 0x00000000, 0x00400040, 0x80400000, - 0x80000000, 0x00001000, 0x00400000, 0x80401000, - 0x00000040, 0x00400000, 0x80001000, 0x00001040, - 0x80400040, 0x80000000, 0x00001040, 0x00400040, - 0x00001000, 0x00401040, 0x80401040, 0x80000040, - 0x00400040, 0x80400000, 0x00401000, 0x80401040, - 0x80000040, 0x00000000, 0x00000000, 0x00401000, - 0x00001040, 0x00400040, 0x80400040, 0x80000000, - 0x80401000, 0x80001040, 0x80001040, 0x00000040, - 0x80401040, 0x80000040, 0x80000000, 0x00001000, - 0x80400000, 0x80001000, 0x00401040, 0x80400040, - 0x80001000, 0x00001040, 0x00400000, 0x80401000, - 0x00000040, 0x00400000, 0x00001000, 0x00401040 - ]; - - /** - * Pre-permuted S-box5 - * - * @var array - */ - protected static $sbox5 = [ - 0x00000080, 0x01040080, 0x01040000, 0x21000080, - 0x00040000, 0x00000080, 0x20000000, 0x01040000, - 0x20040080, 0x00040000, 0x01000080, 0x20040080, - 0x21000080, 0x21040000, 0x00040080, 0x20000000, - 0x01000000, 0x20040000, 0x20040000, 0x00000000, - 0x20000080, 0x21040080, 0x21040080, 0x01000080, - 0x21040000, 0x20000080, 0x00000000, 0x21000000, - 0x01040080, 0x01000000, 0x21000000, 0x00040080, - 0x00040000, 0x21000080, 0x00000080, 0x01000000, - 0x20000000, 0x01040000, 0x21000080, 0x20040080, - 0x01000080, 0x20000000, 0x21040000, 0x01040080, - 0x20040080, 0x00000080, 0x01000000, 0x21040000, - 0x21040080, 0x00040080, 0x21000000, 0x21040080, - 0x01040000, 0x00000000, 0x20040000, 0x21000000, - 0x00040080, 0x01000080, 0x20000080, 0x00040000, - 0x00000000, 0x20040000, 0x01040080, 0x20000080 - ]; - - /** - * Pre-permuted S-box6 - * - * @var array - */ - protected static $sbox6 = [ - 0x10000008, 0x10200000, 0x00002000, 0x10202008, - 0x10200000, 0x00000008, 0x10202008, 0x00200000, - 0x10002000, 0x00202008, 0x00200000, 0x10000008, - 0x00200008, 0x10002000, 0x10000000, 0x00002008, - 0x00000000, 0x00200008, 0x10002008, 0x00002000, - 0x00202000, 0x10002008, 0x00000008, 0x10200008, - 0x10200008, 0x00000000, 0x00202008, 0x10202000, - 0x00002008, 0x00202000, 0x10202000, 0x10000000, - 0x10002000, 0x00000008, 0x10200008, 0x00202000, - 0x10202008, 0x00200000, 0x00002008, 0x10000008, - 0x00200000, 0x10002000, 0x10000000, 0x00002008, - 0x10000008, 0x10202008, 0x00202000, 0x10200000, - 0x00202008, 0x10202000, 0x00000000, 0x10200008, - 0x00000008, 0x00002000, 0x10200000, 0x00202008, - 0x00002000, 0x00200008, 0x10002008, 0x00000000, - 0x10202000, 0x10000000, 0x00200008, 0x10002008 - ]; - - /** - * Pre-permuted S-box7 - * - * @var array - */ - protected static $sbox7 = [ - 0x00100000, 0x02100001, 0x02000401, 0x00000000, - 0x00000400, 0x02000401, 0x00100401, 0x02100400, - 0x02100401, 0x00100000, 0x00000000, 0x02000001, - 0x00000001, 0x02000000, 0x02100001, 0x00000401, - 0x02000400, 0x00100401, 0x00100001, 0x02000400, - 0x02000001, 0x02100000, 0x02100400, 0x00100001, - 0x02100000, 0x00000400, 0x00000401, 0x02100401, - 0x00100400, 0x00000001, 0x02000000, 0x00100400, - 0x02000000, 0x00100400, 0x00100000, 0x02000401, - 0x02000401, 0x02100001, 0x02100001, 0x00000001, - 0x00100001, 0x02000000, 0x02000400, 0x00100000, - 0x02100400, 0x00000401, 0x00100401, 0x02100400, - 0x00000401, 0x02000001, 0x02100401, 0x02100000, - 0x00100400, 0x00000000, 0x00000001, 0x02100401, - 0x00000000, 0x00100401, 0x02100000, 0x00000400, - 0x02000001, 0x02000400, 0x00000400, 0x00100001 - ]; - - /** - * Pre-permuted S-box8 - * - * @var array - */ - protected static $sbox8 = [ - 0x08000820, 0x00000800, 0x00020000, 0x08020820, - 0x08000000, 0x08000820, 0x00000020, 0x08000000, - 0x00020020, 0x08020000, 0x08020820, 0x00020800, - 0x08020800, 0x00020820, 0x00000800, 0x00000020, - 0x08020000, 0x08000020, 0x08000800, 0x00000820, - 0x00020800, 0x00020020, 0x08020020, 0x08020800, - 0x00000820, 0x00000000, 0x00000000, 0x08020020, - 0x08000020, 0x08000800, 0x00020820, 0x00020000, - 0x00020820, 0x00020000, 0x08020800, 0x00000800, - 0x00000020, 0x08020020, 0x00000800, 0x00020820, - 0x08000800, 0x00000020, 0x08000020, 0x08020000, - 0x08020020, 0x08000000, 0x00020000, 0x08000820, - 0x00000000, 0x08020820, 0x00020020, 0x08000020, - 0x08020000, 0x08000800, 0x08000820, 0x00000000, - 0x08020820, 0x00020800, 0x00020800, 0x00000820, - 0x00000820, 0x00020020, 0x08000000, 0x08020800 - ]; - - /** - * Default Constructor. - * - * @param string $mode - * @throws BadModeException if an invalid / unsupported mode is provided - */ - public function __construct($mode) - { - parent::__construct($mode); - - if ($this->mode == self::MODE_STREAM) { - throw new BadModeException('Block ciphers cannot be ran in stream mode'); - } - } - - /** - * Test for engine validity - * - * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine() - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine() - * @param int $engine - * @return bool - */ - protected function isValidEngineHelper($engine) - { - if ($this->key_length_max == 8) { - if ($engine == self::ENGINE_OPENSSL) { - // quoting https://www.openssl.org/news/openssl-3.0-notes.html, OpenSSL 3.0.1 - // "Moved all variations of the EVP ciphers CAST5, BF, IDEA, SEED, RC2, RC4, RC5, and DES to the legacy provider" - // in theory openssl_get_cipher_methods() should catch this but, on GitHub Actions, at least, it does not - if (defined('OPENSSL_VERSION_TEXT') && version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) { - return false; - } - $this->cipher_name_openssl_ecb = 'des-ecb'; - $this->cipher_name_openssl = 'des-' . $this->openssl_translate_mode(); - } - } - - return parent::isValidEngineHelper($engine); - } - - /** - * Sets the key. - * - * Keys must be 64-bits long or 8 bytes long. - * - * DES also requires that every eighth bit be a parity bit, however, we'll ignore that. - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::setKey() - * @param string $key - */ - public function setKey($key) - { - if (!($this instanceof TripleDES) && strlen($key) != 8) { - throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of size 8 are supported'); - } - - // Sets the key - parent::setKey($key); - } - - /** - * Encrypts a block - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::encryptBlock() - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @see self::encrypt() - * @param string $in - * @return string - */ - protected function encryptBlock($in) - { - return $this->processBlock($in, self::ENCRYPT); - } - - /** - * Decrypts a block - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::decryptBlock() - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() - * @see self::decrypt() - * @param string $in - * @return string - */ - protected function decryptBlock($in) - { - return $this->processBlock($in, self::DECRYPT); - } - - /** - * Encrypts or decrypts a 64-bit block - * - * $mode should be either self::ENCRYPT or self::DECRYPT. See - * {@link http://en.wikipedia.org/wiki/Image:Feistel.png Feistel.png} to get a general - * idea of what this function does. - * - * @see self::encryptBlock() - * @see self::decryptBlock() - * @param string $block - * @param int $mode - * @return string - */ - private function processBlock($block, $mode) - { - static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip; - if (!$sbox1) { - $sbox1 = array_map('intval', self::$sbox1); - $sbox2 = array_map('intval', self::$sbox2); - $sbox3 = array_map('intval', self::$sbox3); - $sbox4 = array_map('intval', self::$sbox4); - $sbox5 = array_map('intval', self::$sbox5); - $sbox6 = array_map('intval', self::$sbox6); - $sbox7 = array_map('intval', self::$sbox7); - $sbox8 = array_map('intval', self::$sbox8); - /* Merge $shuffle with $[inv]ipmap */ - for ($i = 0; $i < 256; ++$i) { - $shuffleip[] = self::$shuffle[self::$ipmap[$i]]; - $shuffleinvip[] = self::$shuffle[self::$invipmap[$i]]; - } - } - - $keys = $this->keys[$mode]; - $ki = -1; - - // Do the initial IP permutation. - $t = unpack('Nl/Nr', $block); - list($l, $r) = [$t['l'], $t['r']]; - $block = ($shuffleip[ $r & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") | - ($shuffleip[($r >> 8) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") | - ($shuffleip[($r >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") | - ($shuffleip[($r >> 24) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") | - ($shuffleip[ $l & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") | - ($shuffleip[($l >> 8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") | - ($shuffleip[($l >> 16) & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") | - ($shuffleip[($l >> 24) & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01"); - - // Extract L0 and R0. - $t = unpack('Nl/Nr', $block); - list($l, $r) = [$t['l'], $t['r']]; - - for ($des_round = 0; $des_round < $this->des_rounds; ++$des_round) { - // Perform the 16 steps. - for ($i = 0; $i < 16; $i++) { - // start of "the Feistel (F) function" - see the following URL: - // http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png - // Merge key schedule. - $b1 = (($r >> 3) & 0x1FFFFFFF) ^ ($r << 29) ^ $keys[++$ki]; - $b2 = (($r >> 31) & 0x00000001) ^ ($r << 1) ^ $keys[++$ki]; - - // S-box indexing. - $t = $sbox1[($b1 >> 24) & 0x3F] ^ $sbox2[($b2 >> 24) & 0x3F] ^ - $sbox3[($b1 >> 16) & 0x3F] ^ $sbox4[($b2 >> 16) & 0x3F] ^ - $sbox5[($b1 >> 8) & 0x3F] ^ $sbox6[($b2 >> 8) & 0x3F] ^ - $sbox7[ $b1 & 0x3F] ^ $sbox8[ $b2 & 0x3F] ^ $l; - // end of "the Feistel (F) function" - - $l = $r; - $r = $t; - } - - // Last step should not permute L & R. - $t = $l; - $l = $r; - $r = $t; - } - - // Perform the inverse IP permutation. - return ($shuffleinvip[($r >> 24) & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") | - ($shuffleinvip[($l >> 24) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") | - ($shuffleinvip[($r >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") | - ($shuffleinvip[($l >> 16) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") | - ($shuffleinvip[($r >> 8) & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") | - ($shuffleinvip[($l >> 8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") | - ($shuffleinvip[ $r & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") | - ($shuffleinvip[ $l & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01"); - } - - /** - * Creates the key schedule - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::setupKey() - */ - protected function setupKey() - { - if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->des_rounds === $this->kl['des_rounds']) { - // already expanded - return; - } - $this->kl = ['key' => $this->key, 'des_rounds' => $this->des_rounds]; - - static $shifts = [ // number of key bits shifted per round - 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 - ]; - - static $pc1map = [ - 0x00, 0x00, 0x08, 0x08, 0x04, 0x04, 0x0C, 0x0C, - 0x02, 0x02, 0x0A, 0x0A, 0x06, 0x06, 0x0E, 0x0E, - 0x10, 0x10, 0x18, 0x18, 0x14, 0x14, 0x1C, 0x1C, - 0x12, 0x12, 0x1A, 0x1A, 0x16, 0x16, 0x1E, 0x1E, - 0x20, 0x20, 0x28, 0x28, 0x24, 0x24, 0x2C, 0x2C, - 0x22, 0x22, 0x2A, 0x2A, 0x26, 0x26, 0x2E, 0x2E, - 0x30, 0x30, 0x38, 0x38, 0x34, 0x34, 0x3C, 0x3C, - 0x32, 0x32, 0x3A, 0x3A, 0x36, 0x36, 0x3E, 0x3E, - 0x40, 0x40, 0x48, 0x48, 0x44, 0x44, 0x4C, 0x4C, - 0x42, 0x42, 0x4A, 0x4A, 0x46, 0x46, 0x4E, 0x4E, - 0x50, 0x50, 0x58, 0x58, 0x54, 0x54, 0x5C, 0x5C, - 0x52, 0x52, 0x5A, 0x5A, 0x56, 0x56, 0x5E, 0x5E, - 0x60, 0x60, 0x68, 0x68, 0x64, 0x64, 0x6C, 0x6C, - 0x62, 0x62, 0x6A, 0x6A, 0x66, 0x66, 0x6E, 0x6E, - 0x70, 0x70, 0x78, 0x78, 0x74, 0x74, 0x7C, 0x7C, - 0x72, 0x72, 0x7A, 0x7A, 0x76, 0x76, 0x7E, 0x7E, - 0x80, 0x80, 0x88, 0x88, 0x84, 0x84, 0x8C, 0x8C, - 0x82, 0x82, 0x8A, 0x8A, 0x86, 0x86, 0x8E, 0x8E, - 0x90, 0x90, 0x98, 0x98, 0x94, 0x94, 0x9C, 0x9C, - 0x92, 0x92, 0x9A, 0x9A, 0x96, 0x96, 0x9E, 0x9E, - 0xA0, 0xA0, 0xA8, 0xA8, 0xA4, 0xA4, 0xAC, 0xAC, - 0xA2, 0xA2, 0xAA, 0xAA, 0xA6, 0xA6, 0xAE, 0xAE, - 0xB0, 0xB0, 0xB8, 0xB8, 0xB4, 0xB4, 0xBC, 0xBC, - 0xB2, 0xB2, 0xBA, 0xBA, 0xB6, 0xB6, 0xBE, 0xBE, - 0xC0, 0xC0, 0xC8, 0xC8, 0xC4, 0xC4, 0xCC, 0xCC, - 0xC2, 0xC2, 0xCA, 0xCA, 0xC6, 0xC6, 0xCE, 0xCE, - 0xD0, 0xD0, 0xD8, 0xD8, 0xD4, 0xD4, 0xDC, 0xDC, - 0xD2, 0xD2, 0xDA, 0xDA, 0xD6, 0xD6, 0xDE, 0xDE, - 0xE0, 0xE0, 0xE8, 0xE8, 0xE4, 0xE4, 0xEC, 0xEC, - 0xE2, 0xE2, 0xEA, 0xEA, 0xE6, 0xE6, 0xEE, 0xEE, - 0xF0, 0xF0, 0xF8, 0xF8, 0xF4, 0xF4, 0xFC, 0xFC, - 0xF2, 0xF2, 0xFA, 0xFA, 0xF6, 0xF6, 0xFE, 0xFE - ]; - - // Mapping tables for the PC-2 transformation. - static $pc2mapc1 = [ - 0x00000000, 0x00000400, 0x00200000, 0x00200400, - 0x00000001, 0x00000401, 0x00200001, 0x00200401, - 0x02000000, 0x02000400, 0x02200000, 0x02200400, - 0x02000001, 0x02000401, 0x02200001, 0x02200401 - ]; - static $pc2mapc2 = [ - 0x00000000, 0x00000800, 0x08000000, 0x08000800, - 0x00010000, 0x00010800, 0x08010000, 0x08010800, - 0x00000000, 0x00000800, 0x08000000, 0x08000800, - 0x00010000, 0x00010800, 0x08010000, 0x08010800, - 0x00000100, 0x00000900, 0x08000100, 0x08000900, - 0x00010100, 0x00010900, 0x08010100, 0x08010900, - 0x00000100, 0x00000900, 0x08000100, 0x08000900, - 0x00010100, 0x00010900, 0x08010100, 0x08010900, - 0x00000010, 0x00000810, 0x08000010, 0x08000810, - 0x00010010, 0x00010810, 0x08010010, 0x08010810, - 0x00000010, 0x00000810, 0x08000010, 0x08000810, - 0x00010010, 0x00010810, 0x08010010, 0x08010810, - 0x00000110, 0x00000910, 0x08000110, 0x08000910, - 0x00010110, 0x00010910, 0x08010110, 0x08010910, - 0x00000110, 0x00000910, 0x08000110, 0x08000910, - 0x00010110, 0x00010910, 0x08010110, 0x08010910, - 0x00040000, 0x00040800, 0x08040000, 0x08040800, - 0x00050000, 0x00050800, 0x08050000, 0x08050800, - 0x00040000, 0x00040800, 0x08040000, 0x08040800, - 0x00050000, 0x00050800, 0x08050000, 0x08050800, - 0x00040100, 0x00040900, 0x08040100, 0x08040900, - 0x00050100, 0x00050900, 0x08050100, 0x08050900, - 0x00040100, 0x00040900, 0x08040100, 0x08040900, - 0x00050100, 0x00050900, 0x08050100, 0x08050900, - 0x00040010, 0x00040810, 0x08040010, 0x08040810, - 0x00050010, 0x00050810, 0x08050010, 0x08050810, - 0x00040010, 0x00040810, 0x08040010, 0x08040810, - 0x00050010, 0x00050810, 0x08050010, 0x08050810, - 0x00040110, 0x00040910, 0x08040110, 0x08040910, - 0x00050110, 0x00050910, 0x08050110, 0x08050910, - 0x00040110, 0x00040910, 0x08040110, 0x08040910, - 0x00050110, 0x00050910, 0x08050110, 0x08050910, - 0x01000000, 0x01000800, 0x09000000, 0x09000800, - 0x01010000, 0x01010800, 0x09010000, 0x09010800, - 0x01000000, 0x01000800, 0x09000000, 0x09000800, - 0x01010000, 0x01010800, 0x09010000, 0x09010800, - 0x01000100, 0x01000900, 0x09000100, 0x09000900, - 0x01010100, 0x01010900, 0x09010100, 0x09010900, - 0x01000100, 0x01000900, 0x09000100, 0x09000900, - 0x01010100, 0x01010900, 0x09010100, 0x09010900, - 0x01000010, 0x01000810, 0x09000010, 0x09000810, - 0x01010010, 0x01010810, 0x09010010, 0x09010810, - 0x01000010, 0x01000810, 0x09000010, 0x09000810, - 0x01010010, 0x01010810, 0x09010010, 0x09010810, - 0x01000110, 0x01000910, 0x09000110, 0x09000910, - 0x01010110, 0x01010910, 0x09010110, 0x09010910, - 0x01000110, 0x01000910, 0x09000110, 0x09000910, - 0x01010110, 0x01010910, 0x09010110, 0x09010910, - 0x01040000, 0x01040800, 0x09040000, 0x09040800, - 0x01050000, 0x01050800, 0x09050000, 0x09050800, - 0x01040000, 0x01040800, 0x09040000, 0x09040800, - 0x01050000, 0x01050800, 0x09050000, 0x09050800, - 0x01040100, 0x01040900, 0x09040100, 0x09040900, - 0x01050100, 0x01050900, 0x09050100, 0x09050900, - 0x01040100, 0x01040900, 0x09040100, 0x09040900, - 0x01050100, 0x01050900, 0x09050100, 0x09050900, - 0x01040010, 0x01040810, 0x09040010, 0x09040810, - 0x01050010, 0x01050810, 0x09050010, 0x09050810, - 0x01040010, 0x01040810, 0x09040010, 0x09040810, - 0x01050010, 0x01050810, 0x09050010, 0x09050810, - 0x01040110, 0x01040910, 0x09040110, 0x09040910, - 0x01050110, 0x01050910, 0x09050110, 0x09050910, - 0x01040110, 0x01040910, 0x09040110, 0x09040910, - 0x01050110, 0x01050910, 0x09050110, 0x09050910 - ]; - static $pc2mapc3 = [ - 0x00000000, 0x00000004, 0x00001000, 0x00001004, - 0x00000000, 0x00000004, 0x00001000, 0x00001004, - 0x10000000, 0x10000004, 0x10001000, 0x10001004, - 0x10000000, 0x10000004, 0x10001000, 0x10001004, - 0x00000020, 0x00000024, 0x00001020, 0x00001024, - 0x00000020, 0x00000024, 0x00001020, 0x00001024, - 0x10000020, 0x10000024, 0x10001020, 0x10001024, - 0x10000020, 0x10000024, 0x10001020, 0x10001024, - 0x00080000, 0x00080004, 0x00081000, 0x00081004, - 0x00080000, 0x00080004, 0x00081000, 0x00081004, - 0x10080000, 0x10080004, 0x10081000, 0x10081004, - 0x10080000, 0x10080004, 0x10081000, 0x10081004, - 0x00080020, 0x00080024, 0x00081020, 0x00081024, - 0x00080020, 0x00080024, 0x00081020, 0x00081024, - 0x10080020, 0x10080024, 0x10081020, 0x10081024, - 0x10080020, 0x10080024, 0x10081020, 0x10081024, - 0x20000000, 0x20000004, 0x20001000, 0x20001004, - 0x20000000, 0x20000004, 0x20001000, 0x20001004, - 0x30000000, 0x30000004, 0x30001000, 0x30001004, - 0x30000000, 0x30000004, 0x30001000, 0x30001004, - 0x20000020, 0x20000024, 0x20001020, 0x20001024, - 0x20000020, 0x20000024, 0x20001020, 0x20001024, - 0x30000020, 0x30000024, 0x30001020, 0x30001024, - 0x30000020, 0x30000024, 0x30001020, 0x30001024, - 0x20080000, 0x20080004, 0x20081000, 0x20081004, - 0x20080000, 0x20080004, 0x20081000, 0x20081004, - 0x30080000, 0x30080004, 0x30081000, 0x30081004, - 0x30080000, 0x30080004, 0x30081000, 0x30081004, - 0x20080020, 0x20080024, 0x20081020, 0x20081024, - 0x20080020, 0x20080024, 0x20081020, 0x20081024, - 0x30080020, 0x30080024, 0x30081020, 0x30081024, - 0x30080020, 0x30080024, 0x30081020, 0x30081024, - 0x00000002, 0x00000006, 0x00001002, 0x00001006, - 0x00000002, 0x00000006, 0x00001002, 0x00001006, - 0x10000002, 0x10000006, 0x10001002, 0x10001006, - 0x10000002, 0x10000006, 0x10001002, 0x10001006, - 0x00000022, 0x00000026, 0x00001022, 0x00001026, - 0x00000022, 0x00000026, 0x00001022, 0x00001026, - 0x10000022, 0x10000026, 0x10001022, 0x10001026, - 0x10000022, 0x10000026, 0x10001022, 0x10001026, - 0x00080002, 0x00080006, 0x00081002, 0x00081006, - 0x00080002, 0x00080006, 0x00081002, 0x00081006, - 0x10080002, 0x10080006, 0x10081002, 0x10081006, - 0x10080002, 0x10080006, 0x10081002, 0x10081006, - 0x00080022, 0x00080026, 0x00081022, 0x00081026, - 0x00080022, 0x00080026, 0x00081022, 0x00081026, - 0x10080022, 0x10080026, 0x10081022, 0x10081026, - 0x10080022, 0x10080026, 0x10081022, 0x10081026, - 0x20000002, 0x20000006, 0x20001002, 0x20001006, - 0x20000002, 0x20000006, 0x20001002, 0x20001006, - 0x30000002, 0x30000006, 0x30001002, 0x30001006, - 0x30000002, 0x30000006, 0x30001002, 0x30001006, - 0x20000022, 0x20000026, 0x20001022, 0x20001026, - 0x20000022, 0x20000026, 0x20001022, 0x20001026, - 0x30000022, 0x30000026, 0x30001022, 0x30001026, - 0x30000022, 0x30000026, 0x30001022, 0x30001026, - 0x20080002, 0x20080006, 0x20081002, 0x20081006, - 0x20080002, 0x20080006, 0x20081002, 0x20081006, - 0x30080002, 0x30080006, 0x30081002, 0x30081006, - 0x30080002, 0x30080006, 0x30081002, 0x30081006, - 0x20080022, 0x20080026, 0x20081022, 0x20081026, - 0x20080022, 0x20080026, 0x20081022, 0x20081026, - 0x30080022, 0x30080026, 0x30081022, 0x30081026, - 0x30080022, 0x30080026, 0x30081022, 0x30081026 - ]; - static $pc2mapc4 = [ - 0x00000000, 0x00100000, 0x00000008, 0x00100008, - 0x00000200, 0x00100200, 0x00000208, 0x00100208, - 0x00000000, 0x00100000, 0x00000008, 0x00100008, - 0x00000200, 0x00100200, 0x00000208, 0x00100208, - 0x04000000, 0x04100000, 0x04000008, 0x04100008, - 0x04000200, 0x04100200, 0x04000208, 0x04100208, - 0x04000000, 0x04100000, 0x04000008, 0x04100008, - 0x04000200, 0x04100200, 0x04000208, 0x04100208, - 0x00002000, 0x00102000, 0x00002008, 0x00102008, - 0x00002200, 0x00102200, 0x00002208, 0x00102208, - 0x00002000, 0x00102000, 0x00002008, 0x00102008, - 0x00002200, 0x00102200, 0x00002208, 0x00102208, - 0x04002000, 0x04102000, 0x04002008, 0x04102008, - 0x04002200, 0x04102200, 0x04002208, 0x04102208, - 0x04002000, 0x04102000, 0x04002008, 0x04102008, - 0x04002200, 0x04102200, 0x04002208, 0x04102208, - 0x00000000, 0x00100000, 0x00000008, 0x00100008, - 0x00000200, 0x00100200, 0x00000208, 0x00100208, - 0x00000000, 0x00100000, 0x00000008, 0x00100008, - 0x00000200, 0x00100200, 0x00000208, 0x00100208, - 0x04000000, 0x04100000, 0x04000008, 0x04100008, - 0x04000200, 0x04100200, 0x04000208, 0x04100208, - 0x04000000, 0x04100000, 0x04000008, 0x04100008, - 0x04000200, 0x04100200, 0x04000208, 0x04100208, - 0x00002000, 0x00102000, 0x00002008, 0x00102008, - 0x00002200, 0x00102200, 0x00002208, 0x00102208, - 0x00002000, 0x00102000, 0x00002008, 0x00102008, - 0x00002200, 0x00102200, 0x00002208, 0x00102208, - 0x04002000, 0x04102000, 0x04002008, 0x04102008, - 0x04002200, 0x04102200, 0x04002208, 0x04102208, - 0x04002000, 0x04102000, 0x04002008, 0x04102008, - 0x04002200, 0x04102200, 0x04002208, 0x04102208, - 0x00020000, 0x00120000, 0x00020008, 0x00120008, - 0x00020200, 0x00120200, 0x00020208, 0x00120208, - 0x00020000, 0x00120000, 0x00020008, 0x00120008, - 0x00020200, 0x00120200, 0x00020208, 0x00120208, - 0x04020000, 0x04120000, 0x04020008, 0x04120008, - 0x04020200, 0x04120200, 0x04020208, 0x04120208, - 0x04020000, 0x04120000, 0x04020008, 0x04120008, - 0x04020200, 0x04120200, 0x04020208, 0x04120208, - 0x00022000, 0x00122000, 0x00022008, 0x00122008, - 0x00022200, 0x00122200, 0x00022208, 0x00122208, - 0x00022000, 0x00122000, 0x00022008, 0x00122008, - 0x00022200, 0x00122200, 0x00022208, 0x00122208, - 0x04022000, 0x04122000, 0x04022008, 0x04122008, - 0x04022200, 0x04122200, 0x04022208, 0x04122208, - 0x04022000, 0x04122000, 0x04022008, 0x04122008, - 0x04022200, 0x04122200, 0x04022208, 0x04122208, - 0x00020000, 0x00120000, 0x00020008, 0x00120008, - 0x00020200, 0x00120200, 0x00020208, 0x00120208, - 0x00020000, 0x00120000, 0x00020008, 0x00120008, - 0x00020200, 0x00120200, 0x00020208, 0x00120208, - 0x04020000, 0x04120000, 0x04020008, 0x04120008, - 0x04020200, 0x04120200, 0x04020208, 0x04120208, - 0x04020000, 0x04120000, 0x04020008, 0x04120008, - 0x04020200, 0x04120200, 0x04020208, 0x04120208, - 0x00022000, 0x00122000, 0x00022008, 0x00122008, - 0x00022200, 0x00122200, 0x00022208, 0x00122208, - 0x00022000, 0x00122000, 0x00022008, 0x00122008, - 0x00022200, 0x00122200, 0x00022208, 0x00122208, - 0x04022000, 0x04122000, 0x04022008, 0x04122008, - 0x04022200, 0x04122200, 0x04022208, 0x04122208, - 0x04022000, 0x04122000, 0x04022008, 0x04122008, - 0x04022200, 0x04122200, 0x04022208, 0x04122208 - ]; - static $pc2mapd1 = [ - 0x00000000, 0x00000001, 0x08000000, 0x08000001, - 0x00200000, 0x00200001, 0x08200000, 0x08200001, - 0x00000002, 0x00000003, 0x08000002, 0x08000003, - 0x00200002, 0x00200003, 0x08200002, 0x08200003 - ]; - static $pc2mapd2 = [ - 0x00000000, 0x00100000, 0x00000800, 0x00100800, - 0x00000000, 0x00100000, 0x00000800, 0x00100800, - 0x04000000, 0x04100000, 0x04000800, 0x04100800, - 0x04000000, 0x04100000, 0x04000800, 0x04100800, - 0x00000004, 0x00100004, 0x00000804, 0x00100804, - 0x00000004, 0x00100004, 0x00000804, 0x00100804, - 0x04000004, 0x04100004, 0x04000804, 0x04100804, - 0x04000004, 0x04100004, 0x04000804, 0x04100804, - 0x00000000, 0x00100000, 0x00000800, 0x00100800, - 0x00000000, 0x00100000, 0x00000800, 0x00100800, - 0x04000000, 0x04100000, 0x04000800, 0x04100800, - 0x04000000, 0x04100000, 0x04000800, 0x04100800, - 0x00000004, 0x00100004, 0x00000804, 0x00100804, - 0x00000004, 0x00100004, 0x00000804, 0x00100804, - 0x04000004, 0x04100004, 0x04000804, 0x04100804, - 0x04000004, 0x04100004, 0x04000804, 0x04100804, - 0x00000200, 0x00100200, 0x00000A00, 0x00100A00, - 0x00000200, 0x00100200, 0x00000A00, 0x00100A00, - 0x04000200, 0x04100200, 0x04000A00, 0x04100A00, - 0x04000200, 0x04100200, 0x04000A00, 0x04100A00, - 0x00000204, 0x00100204, 0x00000A04, 0x00100A04, - 0x00000204, 0x00100204, 0x00000A04, 0x00100A04, - 0x04000204, 0x04100204, 0x04000A04, 0x04100A04, - 0x04000204, 0x04100204, 0x04000A04, 0x04100A04, - 0x00000200, 0x00100200, 0x00000A00, 0x00100A00, - 0x00000200, 0x00100200, 0x00000A00, 0x00100A00, - 0x04000200, 0x04100200, 0x04000A00, 0x04100A00, - 0x04000200, 0x04100200, 0x04000A00, 0x04100A00, - 0x00000204, 0x00100204, 0x00000A04, 0x00100A04, - 0x00000204, 0x00100204, 0x00000A04, 0x00100A04, - 0x04000204, 0x04100204, 0x04000A04, 0x04100A04, - 0x04000204, 0x04100204, 0x04000A04, 0x04100A04, - 0x00020000, 0x00120000, 0x00020800, 0x00120800, - 0x00020000, 0x00120000, 0x00020800, 0x00120800, - 0x04020000, 0x04120000, 0x04020800, 0x04120800, - 0x04020000, 0x04120000, 0x04020800, 0x04120800, - 0x00020004, 0x00120004, 0x00020804, 0x00120804, - 0x00020004, 0x00120004, 0x00020804, 0x00120804, - 0x04020004, 0x04120004, 0x04020804, 0x04120804, - 0x04020004, 0x04120004, 0x04020804, 0x04120804, - 0x00020000, 0x00120000, 0x00020800, 0x00120800, - 0x00020000, 0x00120000, 0x00020800, 0x00120800, - 0x04020000, 0x04120000, 0x04020800, 0x04120800, - 0x04020000, 0x04120000, 0x04020800, 0x04120800, - 0x00020004, 0x00120004, 0x00020804, 0x00120804, - 0x00020004, 0x00120004, 0x00020804, 0x00120804, - 0x04020004, 0x04120004, 0x04020804, 0x04120804, - 0x04020004, 0x04120004, 0x04020804, 0x04120804, - 0x00020200, 0x00120200, 0x00020A00, 0x00120A00, - 0x00020200, 0x00120200, 0x00020A00, 0x00120A00, - 0x04020200, 0x04120200, 0x04020A00, 0x04120A00, - 0x04020200, 0x04120200, 0x04020A00, 0x04120A00, - 0x00020204, 0x00120204, 0x00020A04, 0x00120A04, - 0x00020204, 0x00120204, 0x00020A04, 0x00120A04, - 0x04020204, 0x04120204, 0x04020A04, 0x04120A04, - 0x04020204, 0x04120204, 0x04020A04, 0x04120A04, - 0x00020200, 0x00120200, 0x00020A00, 0x00120A00, - 0x00020200, 0x00120200, 0x00020A00, 0x00120A00, - 0x04020200, 0x04120200, 0x04020A00, 0x04120A00, - 0x04020200, 0x04120200, 0x04020A00, 0x04120A00, - 0x00020204, 0x00120204, 0x00020A04, 0x00120A04, - 0x00020204, 0x00120204, 0x00020A04, 0x00120A04, - 0x04020204, 0x04120204, 0x04020A04, 0x04120A04, - 0x04020204, 0x04120204, 0x04020A04, 0x04120A04 - ]; - static $pc2mapd3 = [ - 0x00000000, 0x00010000, 0x02000000, 0x02010000, - 0x00000020, 0x00010020, 0x02000020, 0x02010020, - 0x00040000, 0x00050000, 0x02040000, 0x02050000, - 0x00040020, 0x00050020, 0x02040020, 0x02050020, - 0x00002000, 0x00012000, 0x02002000, 0x02012000, - 0x00002020, 0x00012020, 0x02002020, 0x02012020, - 0x00042000, 0x00052000, 0x02042000, 0x02052000, - 0x00042020, 0x00052020, 0x02042020, 0x02052020, - 0x00000000, 0x00010000, 0x02000000, 0x02010000, - 0x00000020, 0x00010020, 0x02000020, 0x02010020, - 0x00040000, 0x00050000, 0x02040000, 0x02050000, - 0x00040020, 0x00050020, 0x02040020, 0x02050020, - 0x00002000, 0x00012000, 0x02002000, 0x02012000, - 0x00002020, 0x00012020, 0x02002020, 0x02012020, - 0x00042000, 0x00052000, 0x02042000, 0x02052000, - 0x00042020, 0x00052020, 0x02042020, 0x02052020, - 0x00000010, 0x00010010, 0x02000010, 0x02010010, - 0x00000030, 0x00010030, 0x02000030, 0x02010030, - 0x00040010, 0x00050010, 0x02040010, 0x02050010, - 0x00040030, 0x00050030, 0x02040030, 0x02050030, - 0x00002010, 0x00012010, 0x02002010, 0x02012010, - 0x00002030, 0x00012030, 0x02002030, 0x02012030, - 0x00042010, 0x00052010, 0x02042010, 0x02052010, - 0x00042030, 0x00052030, 0x02042030, 0x02052030, - 0x00000010, 0x00010010, 0x02000010, 0x02010010, - 0x00000030, 0x00010030, 0x02000030, 0x02010030, - 0x00040010, 0x00050010, 0x02040010, 0x02050010, - 0x00040030, 0x00050030, 0x02040030, 0x02050030, - 0x00002010, 0x00012010, 0x02002010, 0x02012010, - 0x00002030, 0x00012030, 0x02002030, 0x02012030, - 0x00042010, 0x00052010, 0x02042010, 0x02052010, - 0x00042030, 0x00052030, 0x02042030, 0x02052030, - 0x20000000, 0x20010000, 0x22000000, 0x22010000, - 0x20000020, 0x20010020, 0x22000020, 0x22010020, - 0x20040000, 0x20050000, 0x22040000, 0x22050000, - 0x20040020, 0x20050020, 0x22040020, 0x22050020, - 0x20002000, 0x20012000, 0x22002000, 0x22012000, - 0x20002020, 0x20012020, 0x22002020, 0x22012020, - 0x20042000, 0x20052000, 0x22042000, 0x22052000, - 0x20042020, 0x20052020, 0x22042020, 0x22052020, - 0x20000000, 0x20010000, 0x22000000, 0x22010000, - 0x20000020, 0x20010020, 0x22000020, 0x22010020, - 0x20040000, 0x20050000, 0x22040000, 0x22050000, - 0x20040020, 0x20050020, 0x22040020, 0x22050020, - 0x20002000, 0x20012000, 0x22002000, 0x22012000, - 0x20002020, 0x20012020, 0x22002020, 0x22012020, - 0x20042000, 0x20052000, 0x22042000, 0x22052000, - 0x20042020, 0x20052020, 0x22042020, 0x22052020, - 0x20000010, 0x20010010, 0x22000010, 0x22010010, - 0x20000030, 0x20010030, 0x22000030, 0x22010030, - 0x20040010, 0x20050010, 0x22040010, 0x22050010, - 0x20040030, 0x20050030, 0x22040030, 0x22050030, - 0x20002010, 0x20012010, 0x22002010, 0x22012010, - 0x20002030, 0x20012030, 0x22002030, 0x22012030, - 0x20042010, 0x20052010, 0x22042010, 0x22052010, - 0x20042030, 0x20052030, 0x22042030, 0x22052030, - 0x20000010, 0x20010010, 0x22000010, 0x22010010, - 0x20000030, 0x20010030, 0x22000030, 0x22010030, - 0x20040010, 0x20050010, 0x22040010, 0x22050010, - 0x20040030, 0x20050030, 0x22040030, 0x22050030, - 0x20002010, 0x20012010, 0x22002010, 0x22012010, - 0x20002030, 0x20012030, 0x22002030, 0x22012030, - 0x20042010, 0x20052010, 0x22042010, 0x22052010, - 0x20042030, 0x20052030, 0x22042030, 0x22052030 - ]; - static $pc2mapd4 = [ - 0x00000000, 0x00000400, 0x01000000, 0x01000400, - 0x00000000, 0x00000400, 0x01000000, 0x01000400, - 0x00000100, 0x00000500, 0x01000100, 0x01000500, - 0x00000100, 0x00000500, 0x01000100, 0x01000500, - 0x10000000, 0x10000400, 0x11000000, 0x11000400, - 0x10000000, 0x10000400, 0x11000000, 0x11000400, - 0x10000100, 0x10000500, 0x11000100, 0x11000500, - 0x10000100, 0x10000500, 0x11000100, 0x11000500, - 0x00080000, 0x00080400, 0x01080000, 0x01080400, - 0x00080000, 0x00080400, 0x01080000, 0x01080400, - 0x00080100, 0x00080500, 0x01080100, 0x01080500, - 0x00080100, 0x00080500, 0x01080100, 0x01080500, - 0x10080000, 0x10080400, 0x11080000, 0x11080400, - 0x10080000, 0x10080400, 0x11080000, 0x11080400, - 0x10080100, 0x10080500, 0x11080100, 0x11080500, - 0x10080100, 0x10080500, 0x11080100, 0x11080500, - 0x00000008, 0x00000408, 0x01000008, 0x01000408, - 0x00000008, 0x00000408, 0x01000008, 0x01000408, - 0x00000108, 0x00000508, 0x01000108, 0x01000508, - 0x00000108, 0x00000508, 0x01000108, 0x01000508, - 0x10000008, 0x10000408, 0x11000008, 0x11000408, - 0x10000008, 0x10000408, 0x11000008, 0x11000408, - 0x10000108, 0x10000508, 0x11000108, 0x11000508, - 0x10000108, 0x10000508, 0x11000108, 0x11000508, - 0x00080008, 0x00080408, 0x01080008, 0x01080408, - 0x00080008, 0x00080408, 0x01080008, 0x01080408, - 0x00080108, 0x00080508, 0x01080108, 0x01080508, - 0x00080108, 0x00080508, 0x01080108, 0x01080508, - 0x10080008, 0x10080408, 0x11080008, 0x11080408, - 0x10080008, 0x10080408, 0x11080008, 0x11080408, - 0x10080108, 0x10080508, 0x11080108, 0x11080508, - 0x10080108, 0x10080508, 0x11080108, 0x11080508, - 0x00001000, 0x00001400, 0x01001000, 0x01001400, - 0x00001000, 0x00001400, 0x01001000, 0x01001400, - 0x00001100, 0x00001500, 0x01001100, 0x01001500, - 0x00001100, 0x00001500, 0x01001100, 0x01001500, - 0x10001000, 0x10001400, 0x11001000, 0x11001400, - 0x10001000, 0x10001400, 0x11001000, 0x11001400, - 0x10001100, 0x10001500, 0x11001100, 0x11001500, - 0x10001100, 0x10001500, 0x11001100, 0x11001500, - 0x00081000, 0x00081400, 0x01081000, 0x01081400, - 0x00081000, 0x00081400, 0x01081000, 0x01081400, - 0x00081100, 0x00081500, 0x01081100, 0x01081500, - 0x00081100, 0x00081500, 0x01081100, 0x01081500, - 0x10081000, 0x10081400, 0x11081000, 0x11081400, - 0x10081000, 0x10081400, 0x11081000, 0x11081400, - 0x10081100, 0x10081500, 0x11081100, 0x11081500, - 0x10081100, 0x10081500, 0x11081100, 0x11081500, - 0x00001008, 0x00001408, 0x01001008, 0x01001408, - 0x00001008, 0x00001408, 0x01001008, 0x01001408, - 0x00001108, 0x00001508, 0x01001108, 0x01001508, - 0x00001108, 0x00001508, 0x01001108, 0x01001508, - 0x10001008, 0x10001408, 0x11001008, 0x11001408, - 0x10001008, 0x10001408, 0x11001008, 0x11001408, - 0x10001108, 0x10001508, 0x11001108, 0x11001508, - 0x10001108, 0x10001508, 0x11001108, 0x11001508, - 0x00081008, 0x00081408, 0x01081008, 0x01081408, - 0x00081008, 0x00081408, 0x01081008, 0x01081408, - 0x00081108, 0x00081508, 0x01081108, 0x01081508, - 0x00081108, 0x00081508, 0x01081108, 0x01081508, - 0x10081008, 0x10081408, 0x11081008, 0x11081408, - 0x10081008, 0x10081408, 0x11081008, 0x11081408, - 0x10081108, 0x10081508, 0x11081108, 0x11081508, - 0x10081108, 0x10081508, 0x11081108, 0x11081508 - ]; - - $keys = []; - for ($des_round = 0; $des_round < $this->des_rounds; ++$des_round) { - // pad the key and remove extra characters as appropriate. - $key = str_pad(substr($this->key, $des_round * 8, 8), 8, "\0"); - - // Perform the PC/1 transformation and compute C and D. - $t = unpack('Nl/Nr', $key); - list($l, $r) = [$t['l'], $t['r']]; - $key = (self::$shuffle[$pc1map[ $r & 0xFF]] & "\x80\x80\x80\x80\x80\x80\x80\x00") | - (self::$shuffle[$pc1map[($r >> 8) & 0xFF]] & "\x40\x40\x40\x40\x40\x40\x40\x00") | - (self::$shuffle[$pc1map[($r >> 16) & 0xFF]] & "\x20\x20\x20\x20\x20\x20\x20\x00") | - (self::$shuffle[$pc1map[($r >> 24) & 0xFF]] & "\x10\x10\x10\x10\x10\x10\x10\x00") | - (self::$shuffle[$pc1map[ $l & 0xFF]] & "\x08\x08\x08\x08\x08\x08\x08\x00") | - (self::$shuffle[$pc1map[($l >> 8) & 0xFF]] & "\x04\x04\x04\x04\x04\x04\x04\x00") | - (self::$shuffle[$pc1map[($l >> 16) & 0xFF]] & "\x02\x02\x02\x02\x02\x02\x02\x00") | - (self::$shuffle[$pc1map[($l >> 24) & 0xFF]] & "\x01\x01\x01\x01\x01\x01\x01\x00"); - $key = unpack('Nc/Nd', $key); - $c = ( $key['c'] >> 4) & 0x0FFFFFFF; - $d = (($key['d'] >> 4) & 0x0FFFFFF0) | ($key['c'] & 0x0F); - - $keys[$des_round] = [ - self::ENCRYPT => [], - self::DECRYPT => array_fill(0, 32, 0) - ]; - for ($i = 0, $ki = 31; $i < 16; ++$i, $ki -= 2) { - $c <<= $shifts[$i]; - $c = ($c | ($c >> 28)) & 0x0FFFFFFF; - $d <<= $shifts[$i]; - $d = ($d | ($d >> 28)) & 0x0FFFFFFF; - - // Perform the PC-2 transformation. - $cp = $pc2mapc1[ $c >> 24 ] | $pc2mapc2[($c >> 16) & 0xFF] | - $pc2mapc3[($c >> 8) & 0xFF] | $pc2mapc4[ $c & 0xFF]; - $dp = $pc2mapd1[ $d >> 24 ] | $pc2mapd2[($d >> 16) & 0xFF] | - $pc2mapd3[($d >> 8) & 0xFF] | $pc2mapd4[ $d & 0xFF]; - - // Reorder: odd bytes/even bytes. Push the result in key schedule. - $val1 = ( $cp & intval(0xFF000000)) | (($cp << 8) & 0x00FF0000) | - (($dp >> 16) & 0x0000FF00) | (($dp >> 8) & 0x000000FF); - $val2 = (($cp << 8) & intval(0xFF000000)) | (($cp << 16) & 0x00FF0000) | - (($dp >> 8) & 0x0000FF00) | ( $dp & 0x000000FF); - $keys[$des_round][self::ENCRYPT][ ] = $val1; - $keys[$des_round][self::DECRYPT][$ki - 1] = $val1; - $keys[$des_round][self::ENCRYPT][ ] = $val2; - $keys[$des_round][self::DECRYPT][$ki ] = $val2; - } - } - - switch ($this->des_rounds) { - case 3: // 3DES keys - $this->keys = [ - self::ENCRYPT => array_merge( - $keys[0][self::ENCRYPT], - $keys[1][self::DECRYPT], - $keys[2][self::ENCRYPT] - ), - self::DECRYPT => array_merge( - $keys[2][self::DECRYPT], - $keys[1][self::ENCRYPT], - $keys[0][self::DECRYPT] - ) - ]; - break; - // case 1: // DES keys - default: - $this->keys = [ - self::ENCRYPT => $keys[0][self::ENCRYPT], - self::DECRYPT => $keys[0][self::DECRYPT] - ]; - } - } - - /** - * Setup the performance-optimized function for de/encrypt() - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::setupInlineCrypt() - */ - protected function setupInlineCrypt() - { - // Engine configuration for: - // - DES ($des_rounds == 1) or - // - 3DES ($des_rounds == 3) - $des_rounds = $this->des_rounds; - - $init_crypt = 'static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip; - if (!$sbox1) { - $sbox1 = array_map("intval", self::$sbox1); - $sbox2 = array_map("intval", self::$sbox2); - $sbox3 = array_map("intval", self::$sbox3); - $sbox4 = array_map("intval", self::$sbox4); - $sbox5 = array_map("intval", self::$sbox5); - $sbox6 = array_map("intval", self::$sbox6); - $sbox7 = array_map("intval", self::$sbox7); - $sbox8 = array_map("intval", self::$sbox8);' - /* Merge $shuffle with $[inv]ipmap */ . ' - for ($i = 0; $i < 256; ++$i) { - $shuffleip[] = self::$shuffle[self::$ipmap[$i]]; - $shuffleinvip[] = self::$shuffle[self::$invipmap[$i]]; - } - } - '; - - $k = [ - self::ENCRYPT => $this->keys[self::ENCRYPT], - self::DECRYPT => $this->keys[self::DECRYPT] - ]; - $init_encrypt = ''; - $init_decrypt = ''; - - // Creating code for en- and decryption. - $crypt_block = []; - foreach ([self::ENCRYPT, self::DECRYPT] as $c) { - /* Do the initial IP permutation. */ - $crypt_block[$c] = ' - $in = unpack("N*", $in); - $l = $in[1]; - $r = $in[2]; - $in = unpack("N*", - ($shuffleip[ $r & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") | - ($shuffleip[($r >> 8) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") | - ($shuffleip[($r >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") | - ($shuffleip[($r >> 24) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") | - ($shuffleip[ $l & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") | - ($shuffleip[($l >> 8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") | - ($shuffleip[($l >> 16) & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") | - ($shuffleip[($l >> 24) & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01") - ); - ' . /* Extract L0 and R0 */ ' - $l = $in[1]; - $r = $in[2]; - '; - - $l = '$l'; - $r = '$r'; - - // Perform DES or 3DES. - for ($ki = -1, $des_round = 0; $des_round < $des_rounds; ++$des_round) { - // Perform the 16 steps. - for ($i = 0; $i < 16; ++$i) { - // start of "the Feistel (F) function" - see the following URL: - // http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png - // Merge key schedule. - $crypt_block[$c] .= ' - $b1 = ((' . $r . ' >> 3) & 0x1FFFFFFF) ^ (' . $r . ' << 29) ^ ' . $k[$c][++$ki] . '; - $b2 = ((' . $r . ' >> 31) & 0x00000001) ^ (' . $r . ' << 1) ^ ' . $k[$c][++$ki] . ';' . - /* S-box indexing. */ - $l . ' = $sbox1[($b1 >> 24) & 0x3F] ^ $sbox2[($b2 >> 24) & 0x3F] ^ - $sbox3[($b1 >> 16) & 0x3F] ^ $sbox4[($b2 >> 16) & 0x3F] ^ - $sbox5[($b1 >> 8) & 0x3F] ^ $sbox6[($b2 >> 8) & 0x3F] ^ - $sbox7[ $b1 & 0x3F] ^ $sbox8[ $b2 & 0x3F] ^ ' . $l . '; - '; - // end of "the Feistel (F) function" - - // swap L & R - list($l, $r) = [$r, $l]; - } - list($l, $r) = [$r, $l]; - } - - // Perform the inverse IP permutation. - $crypt_block[$c] .= '$in = - ($shuffleinvip[($l >> 24) & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") | - ($shuffleinvip[($r >> 24) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") | - ($shuffleinvip[($l >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") | - ($shuffleinvip[($r >> 16) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") | - ($shuffleinvip[($l >> 8) & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") | - ($shuffleinvip[($r >> 8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") | - ($shuffleinvip[ $l & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") | - ($shuffleinvip[ $r & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01"); - '; - } - - // Creates the inline-crypt function - $this->inline_crypt = $this->createInlineCryptFunction( - [ - 'init_crypt' => $init_crypt, - 'init_encrypt' => $init_encrypt, - 'init_decrypt' => $init_decrypt, - 'encrypt_block' => $crypt_block[self::ENCRYPT], - 'decrypt_block' => $crypt_block[self::DECRYPT] - ] - ); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH.php deleted file mode 100644 index e1deaf08..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH.php +++ /dev/null @@ -1,405 +0,0 @@ - - * - * - * - * @author Jim Wigginton - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt; - -use phpseclib3\Crypt\Common\AsymmetricKey; -use phpseclib3\Crypt\DH\Parameters; -use phpseclib3\Crypt\DH\PrivateKey; -use phpseclib3\Crypt\DH\PublicKey; -use phpseclib3\Exception\NoKeyLoadedException; -use phpseclib3\Exception\UnsupportedOperationException; -use phpseclib3\Math\BigInteger; - -/** - * Pure-PHP (EC)DH implementation - * - * @author Jim Wigginton - */ -abstract class DH extends AsymmetricKey -{ - /** - * Algorithm Name - * - * @var string - */ - const ALGORITHM = 'DH'; - - /** - * DH prime - * - * @var \phpseclib3\Math\BigInteger - */ - protected $prime; - - /** - * DH Base - * - * Prime divisor of p-1 - * - * @var \phpseclib3\Math\BigInteger - */ - protected $base; - - /** - * Public Key - * - * @var \phpseclib3\Math\BigInteger - */ - protected $publicKey; - - /** - * Create DH parameters - * - * This method is a bit polymorphic. It can take any of the following: - * - two BigInteger's (prime and base) - * - an integer representing the size of the prime in bits (the base is assumed to be 2) - * - a string (eg. diffie-hellman-group14-sha1) - * - * @return Parameters - */ - public static function createParameters(...$args) - { - $class = new \ReflectionClass(static::class); - if ($class->isFinal()) { - throw new \RuntimeException('createParameters() should not be called from final classes (' . static::class . ')'); - } - - $params = new Parameters(); - if (count($args) == 2 && $args[0] instanceof BigInteger && $args[1] instanceof BigInteger) { - //if (!$args[0]->isPrime()) { - // throw new \InvalidArgumentException('The first parameter should be a prime number'); - //} - $params->prime = $args[0]; - $params->base = $args[1]; - return $params; - } elseif (count($args) == 1 && is_numeric($args[0])) { - $params->prime = BigInteger::randomPrime($args[0]); - $params->base = new BigInteger(2); - return $params; - } elseif (count($args) != 1 || !is_string($args[0])) { - throw new \InvalidArgumentException('Valid parameters are either: two BigInteger\'s (prime and base), a single integer (the length of the prime; base is assumed to be 2) or a string'); - } - switch ($args[0]) { - // see http://tools.ietf.org/html/rfc2409#section-6.2 and - // http://tools.ietf.org/html/rfc2412, appendex E - case 'diffie-hellman-group1-sha1': - $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . - '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . - '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . - 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF'; - break; - // see http://tools.ietf.org/html/rfc3526#section-3 - case 'diffie-hellman-group14-sha1': // 2048-bit MODP Group - case 'diffie-hellman-group14-sha256': - $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . - '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . - '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . - 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' . - '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' . - '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' . - 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' . - '3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF'; - break; - // see https://tools.ietf.org/html/rfc3526#section-4 - case 'diffie-hellman-group15-sha512': // 3072-bit MODP Group - $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . - '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . - '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . - 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' . - '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' . - '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' . - 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' . - '3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33' . - 'A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7' . - 'ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864' . - 'D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E2' . - '08E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF'; - break; - // see https://tools.ietf.org/html/rfc3526#section-5 - case 'diffie-hellman-group16-sha512': // 4096-bit MODP Group - $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . - '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . - '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . - 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' . - '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' . - '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' . - 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' . - '3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33' . - 'A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7' . - 'ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864' . - 'D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E2' . - '08E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7' . - '88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8' . - 'DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2' . - '233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9' . - '93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF'; - break; - // see https://tools.ietf.org/html/rfc3526#section-6 - case 'diffie-hellman-group17-sha512': // 6144-bit MODP Group - $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . - '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . - '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . - 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' . - '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' . - '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' . - 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' . - '3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33' . - 'A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7' . - 'ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864' . - 'D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E2' . - '08E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7' . - '88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8' . - 'DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2' . - '233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9' . - '93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026' . - 'C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AE' . - 'B06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B' . - 'DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92EC' . - 'F032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E' . - '59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA' . - 'CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76' . - 'F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468' . - '043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF'; - break; - // see https://tools.ietf.org/html/rfc3526#section-7 - case 'diffie-hellman-group18-sha512': // 8192-bit MODP Group - $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . - '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . - '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . - 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' . - '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' . - '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' . - 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' . - '3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33' . - 'A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7' . - 'ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864' . - 'D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E2' . - '08E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7' . - '88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8' . - 'DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2' . - '233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9' . - '93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026' . - 'C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AE' . - 'B06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B' . - 'DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92EC' . - 'F032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E' . - '59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA' . - 'CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76' . - 'F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468' . - '043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4' . - '38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED' . - '2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652D' . - 'E3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B' . - '4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A6' . - '6D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851D' . - 'F9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92' . - '4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA' . - '9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF'; - break; - default: - throw new \InvalidArgumentException('Invalid named prime provided'); - } - - $params->prime = new BigInteger($prime, 16); - $params->base = new BigInteger(2); - - return $params; - } - - /** - * Create public / private key pair. - * - * The rationale for the second parameter is described in http://tools.ietf.org/html/rfc4419#section-6.2 : - * - * "To increase the speed of the key exchange, both client and server may - * reduce the size of their private exponents. It should be at least - * twice as long as the key material that is generated from the shared - * secret. For more details, see the paper by van Oorschot and Wiener - * [VAN-OORSCHOT]." - * - * $length is in bits - * - * @param Parameters $params - * @param int $length optional - * @return DH\PrivateKey - */ - public static function createKey(Parameters $params, $length = 0) - { - $class = new \ReflectionClass(static::class); - if ($class->isFinal()) { - throw new \RuntimeException('createKey() should not be called from final classes (' . static::class . ')'); - } - - $one = new BigInteger(1); - if ($length) { - $max = $one->bitwise_leftShift($length); - $max = $max->subtract($one); - } else { - $max = $params->prime->subtract($one); - } - - $key = new PrivateKey(); - $key->prime = $params->prime; - $key->base = $params->base; - $key->privateKey = BigInteger::randomRange($one, $max); - $key->publicKey = $key->base->powMod($key->privateKey, $key->prime); - return $key; - } - - /** - * Compute Shared Secret - * - * @param PrivateKey|EC $private - * @param PublicKey|BigInteger|string $public - * @return mixed - */ - public static function computeSecret($private, $public) - { - if ($private instanceof PrivateKey) { // DH\PrivateKey - switch (true) { - case $public instanceof PublicKey: - if (!$private->prime->equals($public->prime) || !$private->base->equals($public->base)) { - throw new \InvalidArgumentException('The public and private key do not share the same prime and / or base numbers'); - } - return $public->publicKey->powMod($private->privateKey, $private->prime)->toBytes(true); - case is_string($public): - $public = new BigInteger($public, -256); - // fall-through - case $public instanceof BigInteger: - return $public->powMod($private->privateKey, $private->prime)->toBytes(true); - default: - throw new \InvalidArgumentException('$public needs to be an instance of DH\PublicKey, a BigInteger or a string'); - } - } - - if ($private instanceof EC\PrivateKey) { - switch (true) { - case $public instanceof EC\PublicKey: - $public = $public->getEncodedCoordinates(); - // fall-through - case is_string($public): - $point = $private->multiply($public); - switch ($private->getCurve()) { - case 'Curve25519': - case 'Curve448': - $secret = $point; - break; - default: - // according to https://www.secg.org/sec1-v2.pdf#page=33 only X is returned - $secret = substr($point, 1, (strlen($point) - 1) >> 1); - } - /* - if (($secret[0] & "\x80") === "\x80") { - $secret = "\0$secret"; - } - */ - return $secret; - default: - throw new \InvalidArgumentException('$public needs to be an instance of EC\PublicKey or a string (an encoded coordinate)'); - } - } - } - - /** - * Load the key - * - * @param string $key - * @param string $password optional - * @return AsymmetricKey - */ - public static function load($key, $password = false) - { - try { - return EC::load($key, $password); - } catch (NoKeyLoadedException $e) { - } - - return parent::load($key, $password); - } - - /** - * OnLoad Handler - * - * @return bool - */ - protected static function onLoad(array $components) - { - if (!isset($components['privateKey']) && !isset($components['publicKey'])) { - $new = new Parameters(); - } else { - $new = isset($components['privateKey']) ? - new PrivateKey() : - new PublicKey(); - } - - $new->prime = $components['prime']; - $new->base = $components['base']; - - if (isset($components['privateKey'])) { - $new->privateKey = $components['privateKey']; - } - if (isset($components['publicKey'])) { - $new->publicKey = $components['publicKey']; - } - - return $new; - } - - /** - * Determines which hashing function should be used - * - * @param string $hash - */ - public function withHash($hash) - { - throw new UnsupportedOperationException('DH does not use a hash algorithm'); - } - - /** - * Returns the hash algorithm currently being used - * - */ - public function getHash() - { - throw new UnsupportedOperationException('DH does not use a hash algorithm'); - } - - /** - * Returns the parameters - * - * A public / private key is only returned if the currently loaded "key" contains an x or y - * value. - * - * @see self::getPublicKey() - * @return mixed - */ - public function getParameters() - { - $type = DH::validatePlugin('Keys', 'PKCS1', 'saveParameters'); - - $key = $type::saveParameters($this->prime, $this->base); - return DH::load($key, 'PKCS1'); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH/Formats/Keys/PKCS1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH/Formats/Keys/PKCS1.php deleted file mode 100644 index 65a0a5db..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH/Formats/Keys/PKCS1.php +++ /dev/null @@ -1,77 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\DH\Formats\Keys; - -use phpseclib3\Crypt\Common\Formats\Keys\PKCS1 as Progenitor; -use phpseclib3\File\ASN1; -use phpseclib3\File\ASN1\Maps; -use phpseclib3\Math\BigInteger; - -/** - * "PKCS1" Formatted DH Key Handler - * - * @author Jim Wigginton - */ -abstract class PKCS1 extends Progenitor -{ - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - $key = parent::load($key, $password); - - $decoded = ASN1::decodeBER($key); - if (!$decoded) { - throw new \RuntimeException('Unable to decode BER'); - } - - $components = ASN1::asn1map($decoded[0], Maps\DHParameter::MAP); - if (!is_array($components)) { - throw new \RuntimeException('Unable to perform ASN1 mapping on parameters'); - } - - return $components; - } - - /** - * Convert EC parameters to the appropriate format - * - * @return string - */ - public static function saveParameters(BigInteger $prime, BigInteger $base, array $options = []) - { - $params = [ - 'prime' => $prime, - 'base' => $base - ]; - $params = ASN1::encodeDER($params, Maps\DHParameter::MAP); - - return "-----BEGIN DH PARAMETERS-----\r\n" . - chunk_split(base64_encode($params), 64) . - "-----END DH PARAMETERS-----\r\n"; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH/Formats/Keys/PKCS8.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH/Formats/Keys/PKCS8.php deleted file mode 100644 index c330a3c7..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH/Formats/Keys/PKCS8.php +++ /dev/null @@ -1,132 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\DH\Formats\Keys; - -use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor; -use phpseclib3\File\ASN1; -use phpseclib3\File\ASN1\Maps; -use phpseclib3\Math\BigInteger; - -/** - * PKCS#8 Formatted DH Key Handler - * - * @author Jim Wigginton - */ -abstract class PKCS8 extends Progenitor -{ - /** - * OID Name - * - * @var string - */ - const OID_NAME = 'dhKeyAgreement'; - - /** - * OID Value - * - * @var string - */ - const OID_VALUE = '1.2.840.113549.1.3.1'; - - /** - * Child OIDs loaded - * - * @var bool - */ - protected static $childOIDsLoaded = false; - - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - $key = parent::load($key, $password); - - $type = isset($key['privateKey']) ? 'privateKey' : 'publicKey'; - - $decoded = ASN1::decodeBER($key[$type . 'Algorithm']['parameters']->element); - if (empty($decoded)) { - throw new \RuntimeException('Unable to decode BER of parameters'); - } - $components = ASN1::asn1map($decoded[0], Maps\DHParameter::MAP); - if (!is_array($components)) { - throw new \RuntimeException('Unable to perform ASN1 mapping on parameters'); - } - - $decoded = ASN1::decodeBER($key[$type]); - switch (true) { - case !isset($decoded): - case !isset($decoded[0]['content']): - case !$decoded[0]['content'] instanceof BigInteger: - throw new \RuntimeException('Unable to decode BER of parameters'); - } - $components[$type] = $decoded[0]['content']; - - return $components; - } - - /** - * Convert a private key to the appropriate format. - * - * @param \phpseclib3\Math\BigInteger $prime - * @param \phpseclib3\Math\BigInteger $base - * @param \phpseclib3\Math\BigInteger $privateKey - * @param \phpseclib3\Math\BigInteger $publicKey - * @param string $password optional - * @param array $options optional - * @return string - */ - public static function savePrivateKey(BigInteger $prime, BigInteger $base, BigInteger $privateKey, BigInteger $publicKey, $password = '', array $options = []) - { - $params = [ - 'prime' => $prime, - 'base' => $base - ]; - $params = ASN1::encodeDER($params, Maps\DHParameter::MAP); - $params = new ASN1\Element($params); - $key = ASN1::encodeDER($privateKey, ['type' => ASN1::TYPE_INTEGER]); - return self::wrapPrivateKey($key, [], $params, $password, null, '', $options); - } - - /** - * Convert a public key to the appropriate format - * - * @param \phpseclib3\Math\BigInteger $prime - * @param \phpseclib3\Math\BigInteger $base - * @param \phpseclib3\Math\BigInteger $publicKey - * @param array $options optional - * @return string - */ - public static function savePublicKey(BigInteger $prime, BigInteger $base, BigInteger $publicKey, array $options = []) - { - $params = [ - 'prime' => $prime, - 'base' => $base - ]; - $params = ASN1::encodeDER($params, Maps\DHParameter::MAP); - $params = new ASN1\Element($params); - $key = ASN1::encodeDER($publicKey, ['type' => ASN1::TYPE_INTEGER]); - return self::wrapPublicKey($key, $params); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH/Parameters.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH/Parameters.php deleted file mode 100644 index c0ded84c..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH/Parameters.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\DH; - -use phpseclib3\Crypt\DH; - -/** - * DH Parameters - * - * @author Jim Wigginton - */ -final class Parameters extends DH -{ - /** - * Returns the parameters - * - * @param string $type - * @param array $options optional - * @return string - */ - public function toString($type = 'PKCS1', array $options = []) - { - $type = self::validatePlugin('Keys', 'PKCS1', 'saveParameters'); - - return $type::saveParameters($this->prime, $this->base, $options); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH/PrivateKey.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH/PrivateKey.php deleted file mode 100644 index 737781f8..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH/PrivateKey.php +++ /dev/null @@ -1,75 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\DH; - -use phpseclib3\Crypt\Common; -use phpseclib3\Crypt\DH; - -/** - * DH Private Key - * - * @author Jim Wigginton - */ -final class PrivateKey extends DH -{ - use Common\Traits\PasswordProtected; - - /** - * Private Key - * - * @var \phpseclib3\Math\BigInteger - */ - protected $privateKey; - - /** - * Public Key - * - * @var \phpseclib3\Math\BigInteger - */ - protected $publicKey; - - /** - * Returns the public key - * - * @return DH\PublicKey - */ - public function getPublicKey() - { - $type = self::validatePlugin('Keys', 'PKCS8', 'savePublicKey'); - - if (!isset($this->publicKey)) { - $this->publicKey = $this->base->powMod($this->privateKey, $this->prime); - } - - $key = $type::savePublicKey($this->prime, $this->base, $this->publicKey); - - return DH::loadFormat('PKCS8', $key); - } - - /** - * Returns the private key - * - * @param string $type - * @param array $options optional - * @return string - */ - public function toString($type, array $options = []) - { - $type = self::validatePlugin('Keys', $type, 'savePrivateKey'); - - if (!isset($this->publicKey)) { - $this->publicKey = $this->base->powMod($this->privateKey, $this->prime); - } - - return $type::savePrivateKey($this->prime, $this->base, $this->privateKey, $this->publicKey, $this->password, $options); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH/PublicKey.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH/PublicKey.php deleted file mode 100644 index 87726a5a..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH/PublicKey.php +++ /dev/null @@ -1,49 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\DH; - -use phpseclib3\Crypt\Common; -use phpseclib3\Crypt\DH; - -/** - * DH Public Key - * - * @author Jim Wigginton - */ -final class PublicKey extends DH -{ - use Common\Traits\Fingerprint; - - /** - * Returns the public key - * - * @param string $type - * @param array $options optional - * @return string - */ - public function toString($type, array $options = []) - { - $type = self::validatePlugin('Keys', $type, 'savePublicKey'); - - return $type::savePublicKey($this->prime, $this->base, $this->publicKey, $options); - } - - /** - * Returns the public key as a BigInteger - * - * @return \phpseclib3\Math\BigInteger - */ - public function toBigInteger() - { - return $this->publicKey; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA.php deleted file mode 100644 index 0123c66c..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA.php +++ /dev/null @@ -1,337 +0,0 @@ - - * getPublicKey(); - * - * $plaintext = 'terrafrost'; - * - * $signature = $private->sign($plaintext); - * - * echo $public->verify($plaintext, $signature) ? 'verified' : 'unverified'; - * ?> - * - * - * @author Jim Wigginton - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt; - -use phpseclib3\Crypt\Common\AsymmetricKey; -use phpseclib3\Crypt\DSA\Parameters; -use phpseclib3\Crypt\DSA\PrivateKey; -use phpseclib3\Crypt\DSA\PublicKey; -use phpseclib3\Exception\InsufficientSetupException; -use phpseclib3\Math\BigInteger; - -/** - * Pure-PHP FIPS 186-4 compliant implementation of DSA. - * - * @author Jim Wigginton - */ -abstract class DSA extends AsymmetricKey -{ - /** - * Algorithm Name - * - * @var string - */ - const ALGORITHM = 'DSA'; - - /** - * DSA Prime P - * - * @var \phpseclib3\Math\BigInteger - */ - protected $p; - - /** - * DSA Group Order q - * - * Prime divisor of p-1 - * - * @var \phpseclib3\Math\BigInteger - */ - protected $q; - - /** - * DSA Group Generator G - * - * @var \phpseclib3\Math\BigInteger - */ - protected $g; - - /** - * DSA public key value y - * - * @var \phpseclib3\Math\BigInteger - */ - protected $y; - - /** - * Signature Format - * - * @var string - */ - protected $sigFormat; - - /** - * Signature Format (Short) - * - * @var string - */ - protected $shortFormat; - - /** - * Create DSA parameters - * - * @param int $L - * @param int $N - * @return \phpseclib3\Crypt\DSA|bool - */ - public static function createParameters($L = 2048, $N = 224) - { - self::initialize_static_variables(); - - $class = new \ReflectionClass(static::class); - if ($class->isFinal()) { - throw new \RuntimeException('createParameters() should not be called from final classes (' . static::class . ')'); - } - - if (!isset(self::$engines['PHP'])) { - self::useBestEngine(); - } - - switch (true) { - case $N == 160: - /* - in FIPS 186-1 and 186-2 N was fixed at 160 whereas K had an upper bound of 1024. - RFC 4253 (SSH Transport Layer Protocol) references FIPS 186-2 and as such most - SSH DSA implementations only support keys with an N of 160. - puttygen let's you set the size of L (but not the size of N) and uses 2048 as the - default L value. that's not really compliant with any of the FIPS standards, however, - for the purposes of maintaining compatibility with puttygen, we'll support it - */ - //case ($L >= 512 || $L <= 1024) && (($L & 0x3F) == 0) && $N == 160: - // FIPS 186-3 changed this as follows: - //case $L == 1024 && $N == 160: - case $L == 2048 && $N == 224: - case $L == 2048 && $N == 256: - case $L == 3072 && $N == 256: - break; - default: - throw new \InvalidArgumentException('Invalid values for N and L'); - } - - $two = new BigInteger(2); - - $q = BigInteger::randomPrime($N); - $divisor = $q->multiply($two); - - do { - $x = BigInteger::random($L); - list(, $c) = $x->divide($divisor); - $p = $x->subtract($c->subtract(self::$one)); - } while ($p->getLength() != $L || !$p->isPrime()); - - $p_1 = $p->subtract(self::$one); - list($e) = $p_1->divide($q); - - // quoting http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf#page=50 , - // "h could be obtained from a random number generator or from a counter that - // changes after each use". PuTTY (sshdssg.c) starts h off at 1 and increments - // it on each loop. wikipedia says "commonly h = 2 is used" so we'll just do that - $h = clone $two; - while (true) { - $g = $h->powMod($e, $p); - if (!$g->equals(self::$one)) { - break; - } - $h = $h->add(self::$one); - } - - $dsa = new Parameters(); - $dsa->p = $p; - $dsa->q = $q; - $dsa->g = $g; - - return $dsa; - } - - /** - * Create public / private key pair. - * - * This method is a bit polymorphic. It can take a DSA/Parameters object, L / N as two distinct parameters or - * no parameters (at which point L and N will be generated with this method) - * - * Returns the private key, from which the publickey can be extracted - * - * @param int[] ...$args - * @return DSA\PrivateKey - */ - public static function createKey(...$args) - { - self::initialize_static_variables(); - - $class = new \ReflectionClass(static::class); - if ($class->isFinal()) { - throw new \RuntimeException('createKey() should not be called from final classes (' . static::class . ')'); - } - - if (!isset(self::$engines['PHP'])) { - self::useBestEngine(); - } - - if (count($args) == 2 && is_int($args[0]) && is_int($args[1])) { - $params = self::createParameters($args[0], $args[1]); - } elseif (count($args) == 1 && $args[0] instanceof Parameters) { - $params = $args[0]; - } elseif (!count($args)) { - $params = self::createParameters(); - } else { - throw new InsufficientSetupException('Valid parameters are either two integers (L and N), a single DSA object or no parameters at all.'); - } - - $private = new PrivateKey(); - $private->p = $params->p; - $private->q = $params->q; - $private->g = $params->g; - - $private->x = BigInteger::randomRange(self::$one, $private->q->subtract(self::$one)); - $private->y = $private->g->powMod($private->x, $private->p); - - //$public = clone $private; - //unset($public->x); - - return $private - ->withHash($params->hash->getHash()) - ->withSignatureFormat($params->shortFormat); - } - - /** - * OnLoad Handler - * - * @return bool - */ - protected static function onLoad(array $components) - { - if (!isset(self::$engines['PHP'])) { - self::useBestEngine(); - } - - if (!isset($components['x']) && !isset($components['y'])) { - $new = new Parameters(); - } elseif (isset($components['x'])) { - $new = new PrivateKey(); - $new->x = $components['x']; - } else { - $new = new PublicKey(); - } - - $new->p = $components['p']; - $new->q = $components['q']; - $new->g = $components['g']; - - if (isset($components['y'])) { - $new->y = $components['y']; - } - - return $new; - } - - /** - * Constructor - * - * PublicKey and PrivateKey objects can only be created from abstract RSA class - */ - protected function __construct() - { - $this->sigFormat = self::validatePlugin('Signature', 'ASN1'); - $this->shortFormat = 'ASN1'; - - parent::__construct(); - } - - /** - * Returns the key size - * - * More specifically, this L (the length of DSA Prime P) and N (the length of DSA Group Order q) - * - * @return array - */ - public function getLength() - { - return ['L' => $this->p->getLength(), 'N' => $this->q->getLength()]; - } - - /** - * Returns the current engine being used - * - * @see self::useInternalEngine() - * @see self::useBestEngine() - * @return string - */ - public function getEngine() - { - if (!isset(self::$engines['PHP'])) { - self::useBestEngine(); - } - return self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods()) ? - 'OpenSSL' : 'PHP'; - } - - /** - * Returns the parameters - * - * A public / private key is only returned if the currently loaded "key" contains an x or y - * value. - * - * @see self::getPublicKey() - * @return mixed - */ - public function getParameters() - { - $type = self::validatePlugin('Keys', 'PKCS1', 'saveParameters'); - - $key = $type::saveParameters($this->p, $this->q, $this->g); - return DSA::load($key, 'PKCS1') - ->withHash($this->hash->getHash()) - ->withSignatureFormat($this->shortFormat); - } - - /** - * Determines the signature padding mode - * - * Valid values are: ASN1, SSH2, Raw - * - * @param string $format - */ - public function withSignatureFormat($format) - { - $new = clone $this; - $new->shortFormat = $format; - $new->sigFormat = self::validatePlugin('Signature', $format); - return $new; - } - - /** - * Returns the signature format currently being used - * - */ - public function getSignatureFormat() - { - return $this->shortFormat; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/OpenSSH.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/OpenSSH.php deleted file mode 100644 index cc204fa9..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/OpenSSH.php +++ /dev/null @@ -1,118 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\DSA\Formats\Keys; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\Common\Formats\Keys\OpenSSH as Progenitor; -use phpseclib3\Math\BigInteger; - -/** - * OpenSSH Formatted DSA Key Handler - * - * @author Jim Wigginton - */ -abstract class OpenSSH extends Progenitor -{ - /** - * Supported Key Types - * - * @var array - */ - protected static $types = ['ssh-dss']; - - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - $parsed = parent::load($key, $password); - - if (isset($parsed['paddedKey'])) { - list($type) = Strings::unpackSSH2('s', $parsed['paddedKey']); - if ($type != $parsed['type']) { - throw new \RuntimeException("The public and private keys are not of the same type ($type vs $parsed[type])"); - } - - list($p, $q, $g, $y, $x, $comment) = Strings::unpackSSH2('i5s', $parsed['paddedKey']); - - return compact('p', 'q', 'g', 'y', 'x', 'comment'); - } - - list($p, $q, $g, $y) = Strings::unpackSSH2('iiii', $parsed['publicKey']); - - $comment = $parsed['comment']; - - return compact('p', 'q', 'g', 'y', 'comment'); - } - - /** - * Convert a public key to the appropriate format - * - * @param \phpseclib3\Math\BigInteger $p - * @param \phpseclib3\Math\BigInteger $q - * @param \phpseclib3\Math\BigInteger $g - * @param \phpseclib3\Math\BigInteger $y - * @param array $options optional - * @return string - */ - public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, array $options = []) - { - if ($q->getLength() != 160) { - throw new \InvalidArgumentException('SSH only supports keys with an N (length of Group Order q) of 160'); - } - - // from : - // string "ssh-dss" - // mpint p - // mpint q - // mpint g - // mpint y - $DSAPublicKey = Strings::packSSH2('siiii', 'ssh-dss', $p, $q, $g, $y); - - if (isset($options['binary']) ? $options['binary'] : self::$binary) { - return $DSAPublicKey; - } - - $comment = isset($options['comment']) ? $options['comment'] : self::$comment; - $DSAPublicKey = 'ssh-dss ' . base64_encode($DSAPublicKey) . ' ' . $comment; - - return $DSAPublicKey; - } - - /** - * Convert a private key to the appropriate format. - * - * @param \phpseclib3\Math\BigInteger $p - * @param \phpseclib3\Math\BigInteger $q - * @param \phpseclib3\Math\BigInteger $g - * @param \phpseclib3\Math\BigInteger $y - * @param \phpseclib3\Math\BigInteger $x - * @param string $password optional - * @param array $options optional - * @return string - */ - public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = '', array $options = []) - { - $publicKey = self::savePublicKey($p, $q, $g, $y, ['binary' => true]); - $privateKey = Strings::packSSH2('si5', 'ssh-dss', $p, $q, $g, $y, $x); - - return self::wrapPrivateKey($publicKey, $privateKey, $password, $options); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PKCS1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PKCS1.php deleted file mode 100644 index 52a04992..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PKCS1.php +++ /dev/null @@ -1,143 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\DSA\Formats\Keys; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\Common\Formats\Keys\PKCS1 as Progenitor; -use phpseclib3\File\ASN1; -use phpseclib3\File\ASN1\Maps; -use phpseclib3\Math\BigInteger; - -/** - * PKCS#1 Formatted DSA Key Handler - * - * @author Jim Wigginton - */ -abstract class PKCS1 extends Progenitor -{ - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - $key = parent::load($key, $password); - - $decoded = ASN1::decodeBER($key); - if (!$decoded) { - throw new \RuntimeException('Unable to decode BER'); - } - - $key = ASN1::asn1map($decoded[0], Maps\DSAParams::MAP); - if (is_array($key)) { - return $key; - } - - $key = ASN1::asn1map($decoded[0], Maps\DSAPrivateKey::MAP); - if (is_array($key)) { - return $key; - } - - $key = ASN1::asn1map($decoded[0], Maps\DSAPublicKey::MAP); - if (is_array($key)) { - return $key; - } - - throw new \RuntimeException('Unable to perform ASN1 mapping'); - } - - /** - * Convert DSA parameters to the appropriate format - * - * @param \phpseclib3\Math\BigInteger $p - * @param \phpseclib3\Math\BigInteger $q - * @param \phpseclib3\Math\BigInteger $g - * @return string - */ - public static function saveParameters(BigInteger $p, BigInteger $q, BigInteger $g) - { - $key = [ - 'p' => $p, - 'q' => $q, - 'g' => $g - ]; - - $key = ASN1::encodeDER($key, Maps\DSAParams::MAP); - - return "-----BEGIN DSA PARAMETERS-----\r\n" . - chunk_split(Strings::base64_encode($key), 64) . - "-----END DSA PARAMETERS-----\r\n"; - } - - /** - * Convert a private key to the appropriate format. - * - * @param \phpseclib3\Math\BigInteger $p - * @param \phpseclib3\Math\BigInteger $q - * @param \phpseclib3\Math\BigInteger $g - * @param \phpseclib3\Math\BigInteger $y - * @param \phpseclib3\Math\BigInteger $x - * @param string $password optional - * @param array $options optional - * @return string - */ - public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = '', array $options = []) - { - $key = [ - 'version' => 0, - 'p' => $p, - 'q' => $q, - 'g' => $g, - 'y' => $y, - 'x' => $x - ]; - - $key = ASN1::encodeDER($key, Maps\DSAPrivateKey::MAP); - - return self::wrapPrivateKey($key, 'DSA', $password, $options); - } - - /** - * Convert a public key to the appropriate format - * - * @param \phpseclib3\Math\BigInteger $p - * @param \phpseclib3\Math\BigInteger $q - * @param \phpseclib3\Math\BigInteger $g - * @param \phpseclib3\Math\BigInteger $y - * @return string - */ - public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y) - { - $key = ASN1::encodeDER($y, Maps\DSAPublicKey::MAP); - - return self::wrapPublicKey($key, 'DSA'); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PKCS8.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PKCS8.php deleted file mode 100644 index 004881e8..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PKCS8.php +++ /dev/null @@ -1,146 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\DSA\Formats\Keys; - -use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor; -use phpseclib3\File\ASN1; -use phpseclib3\File\ASN1\Maps; -use phpseclib3\Math\BigInteger; - -/** - * PKCS#8 Formatted DSA Key Handler - * - * @author Jim Wigginton - */ -abstract class PKCS8 extends Progenitor -{ - /** - * OID Name - * - * @var string - */ - const OID_NAME = 'id-dsa'; - - /** - * OID Value - * - * @var string - */ - const OID_VALUE = '1.2.840.10040.4.1'; - - /** - * Child OIDs loaded - * - * @var bool - */ - protected static $childOIDsLoaded = false; - - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - $key = parent::load($key, $password); - - $type = isset($key['privateKey']) ? 'privateKey' : 'publicKey'; - - $decoded = ASN1::decodeBER($key[$type . 'Algorithm']['parameters']->element); - if (!$decoded) { - throw new \RuntimeException('Unable to decode BER of parameters'); - } - $components = ASN1::asn1map($decoded[0], Maps\DSAParams::MAP); - if (!is_array($components)) { - throw new \RuntimeException('Unable to perform ASN1 mapping on parameters'); - } - - $decoded = ASN1::decodeBER($key[$type]); - if (empty($decoded)) { - throw new \RuntimeException('Unable to decode BER'); - } - - $var = $type == 'privateKey' ? 'x' : 'y'; - $components[$var] = ASN1::asn1map($decoded[0], Maps\DSAPublicKey::MAP); - if (!$components[$var] instanceof BigInteger) { - throw new \RuntimeException('Unable to perform ASN1 mapping'); - } - - if (isset($key['meta'])) { - $components['meta'] = $key['meta']; - } - - return $components; - } - - /** - * Convert a private key to the appropriate format. - * - * @param \phpseclib3\Math\BigInteger $p - * @param \phpseclib3\Math\BigInteger $q - * @param \phpseclib3\Math\BigInteger $g - * @param \phpseclib3\Math\BigInteger $y - * @param \phpseclib3\Math\BigInteger $x - * @param string $password optional - * @param array $options optional - * @return string - */ - public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = '', array $options = []) - { - $params = [ - 'p' => $p, - 'q' => $q, - 'g' => $g - ]; - $params = ASN1::encodeDER($params, Maps\DSAParams::MAP); - $params = new ASN1\Element($params); - $key = ASN1::encodeDER($x, Maps\DSAPublicKey::MAP); - return self::wrapPrivateKey($key, [], $params, $password, null, '', $options); - } - - /** - * Convert a public key to the appropriate format - * - * @param \phpseclib3\Math\BigInteger $p - * @param \phpseclib3\Math\BigInteger $q - * @param \phpseclib3\Math\BigInteger $g - * @param \phpseclib3\Math\BigInteger $y - * @param array $options optional - * @return string - */ - public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, array $options = []) - { - $params = [ - 'p' => $p, - 'q' => $q, - 'g' => $g - ]; - $params = ASN1::encodeDER($params, Maps\DSAParams::MAP); - $params = new ASN1\Element($params); - $key = ASN1::encodeDER($y, Maps\DSAPublicKey::MAP); - return self::wrapPublicKey($key, $params); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PuTTY.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PuTTY.php deleted file mode 100644 index 177bfdd4..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PuTTY.php +++ /dev/null @@ -1,109 +0,0 @@ - 160 kinda useless, hence this handlers not supporting such keys. - * - * PHP version 5 - * - * @author Jim Wigginton - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\DSA\Formats\Keys; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\Common\Formats\Keys\PuTTY as Progenitor; -use phpseclib3\Math\BigInteger; - -/** - * PuTTY Formatted DSA Key Handler - * - * @author Jim Wigginton - */ -abstract class PuTTY extends Progenitor -{ - /** - * Public Handler - * - * @var string - */ - const PUBLIC_HANDLER = 'phpseclib3\Crypt\DSA\Formats\Keys\OpenSSH'; - - /** - * Algorithm Identifier - * - * @var array - */ - protected static $types = ['ssh-dss']; - - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - $components = parent::load($key, $password); - if (!isset($components['private'])) { - return $components; - } - extract($components); - unset($components['public'], $components['private']); - - list($p, $q, $g, $y) = Strings::unpackSSH2('iiii', $public); - list($x) = Strings::unpackSSH2('i', $private); - - return compact('p', 'q', 'g', 'y', 'x', 'comment'); - } - - /** - * Convert a private key to the appropriate format. - * - * @param \phpseclib3\Math\BigInteger $p - * @param \phpseclib3\Math\BigInteger $q - * @param \phpseclib3\Math\BigInteger $g - * @param \phpseclib3\Math\BigInteger $y - * @param \phpseclib3\Math\BigInteger $x - * @param string $password optional - * @param array $options optional - * @return string - */ - public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = false, array $options = []) - { - if ($q->getLength() != 160) { - throw new \InvalidArgumentException('SSH only supports keys with an N (length of Group Order q) of 160'); - } - - $public = Strings::packSSH2('iiii', $p, $q, $g, $y); - $private = Strings::packSSH2('i', $x); - - return self::wrapPrivateKey($public, $private, 'ssh-dss', $password, $options); - } - - /** - * Convert a public key to the appropriate format - * - * @param \phpseclib3\Math\BigInteger $p - * @param \phpseclib3\Math\BigInteger $q - * @param \phpseclib3\Math\BigInteger $g - * @param \phpseclib3\Math\BigInteger $y - * @return string - */ - public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y) - { - if ($q->getLength() != 160) { - throw new \InvalidArgumentException('SSH only supports keys with an N (length of Group Order q) of 160'); - } - - return self::wrapPublicKey(Strings::packSSH2('iiii', $p, $q, $g, $y), 'ssh-dss'); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/Raw.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/Raw.php deleted file mode 100644 index 201aa6f9..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/Raw.php +++ /dev/null @@ -1,85 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\DSA\Formats\Keys; - -use phpseclib3\Math\BigInteger; - -/** - * Raw DSA Key Handler - * - * @author Jim Wigginton - */ -abstract class Raw -{ - /** - * Break a public or private key down into its constituent components - * - * @param array $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - if (!is_array($key)) { - throw new \UnexpectedValueException('Key should be a array - not a ' . gettype($key)); - } - - switch (true) { - case !isset($key['p']) || !isset($key['q']) || !isset($key['g']): - case !$key['p'] instanceof BigInteger: - case !$key['q'] instanceof BigInteger: - case !$key['g'] instanceof BigInteger: - case !isset($key['x']) && !isset($key['y']): - case isset($key['x']) && !$key['x'] instanceof BigInteger: - case isset($key['y']) && !$key['y'] instanceof BigInteger: - throw new \UnexpectedValueException('Key appears to be malformed'); - } - - $options = ['p' => 1, 'q' => 1, 'g' => 1, 'x' => 1, 'y' => 1]; - - return array_intersect_key($key, $options); - } - - /** - * Convert a private key to the appropriate format. - * - * @param \phpseclib3\Math\BigInteger $p - * @param \phpseclib3\Math\BigInteger $q - * @param \phpseclib3\Math\BigInteger $g - * @param \phpseclib3\Math\BigInteger $y - * @param \phpseclib3\Math\BigInteger $x - * @param string $password optional - * @return string - */ - public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = '') - { - return compact('p', 'q', 'g', 'y', 'x'); - } - - /** - * Convert a public key to the appropriate format - * - * @param \phpseclib3\Math\BigInteger $p - * @param \phpseclib3\Math\BigInteger $q - * @param \phpseclib3\Math\BigInteger $g - * @param \phpseclib3\Math\BigInteger $y - * @return string - */ - public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y) - { - return compact('p', 'q', 'g', 'y'); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/XML.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/XML.php deleted file mode 100644 index fc363677..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/XML.php +++ /dev/null @@ -1,132 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\DSA\Formats\Keys; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Exception\BadConfigurationException; -use phpseclib3\Math\BigInteger; - -/** - * XML Formatted DSA Key Handler - * - * @author Jim Wigginton - */ -abstract class XML -{ - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - if (!Strings::is_stringable($key)) { - throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key)); - } - - if (!class_exists('DOMDocument')) { - throw new BadConfigurationException('The dom extension is not setup correctly on this system'); - } - - $use_errors = libxml_use_internal_errors(true); - - $dom = new \DOMDocument(); - if (substr($key, 0, 5) != '' . $key . ''; - } - if (!$dom->loadXML($key)) { - libxml_use_internal_errors($use_errors); - throw new \UnexpectedValueException('Key does not appear to contain XML'); - } - $xpath = new \DOMXPath($dom); - $keys = ['p', 'q', 'g', 'y', 'j', 'seed', 'pgencounter']; - foreach ($keys as $key) { - // $dom->getElementsByTagName($key) is case-sensitive - $temp = $xpath->query("//*[translate(local-name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='$key']"); - if (!$temp->length) { - continue; - } - $value = new BigInteger(Strings::base64_decode($temp->item(0)->nodeValue), 256); - switch ($key) { - case 'p': // a prime modulus meeting the [DSS] requirements - // Parameters P, Q, and G can be public and common to a group of users. They might be known - // from application context. As such, they are optional but P and Q must either both appear - // or both be absent - $components['p'] = $value; - break; - case 'q': // an integer in the range 2**159 < Q < 2**160 which is a prime divisor of P-1 - $components['q'] = $value; - break; - case 'g': // an integer with certain properties with respect to P and Q - $components['g'] = $value; - break; - case 'y': // G**X mod P (where X is part of the private key and not made public) - $components['y'] = $value; - // the remaining options do not do anything - case 'j': // (P - 1) / Q - // Parameter J is available for inclusion solely for efficiency as it is calculatable from - // P and Q - case 'seed': // a DSA prime generation seed - // Parameters seed and pgenCounter are used in the DSA prime number generation algorithm - // specified in [DSS]. As such, they are optional but must either both be present or both - // be absent - case 'pgencounter': // a DSA prime generation counter - } - } - - libxml_use_internal_errors($use_errors); - - if (!isset($components['y'])) { - throw new \UnexpectedValueException('Key is missing y component'); - } - - switch (true) { - case !isset($components['p']): - case !isset($components['q']): - case !isset($components['g']): - return ['y' => $components['y']]; - } - - return $components; - } - - /** - * Convert a public key to the appropriate format - * - * See https://www.w3.org/TR/xmldsig-core/#sec-DSAKeyValue - * - * @param \phpseclib3\Math\BigInteger $p - * @param \phpseclib3\Math\BigInteger $q - * @param \phpseclib3\Math\BigInteger $g - * @param \phpseclib3\Math\BigInteger $y - * @return string - */ - public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y) - { - return "\r\n" . - '

' . Strings::base64_encode($p->toBytes()) . "

\r\n" . - ' ' . Strings::base64_encode($q->toBytes()) . "\r\n" . - ' ' . Strings::base64_encode($g->toBytes()) . "\r\n" . - ' ' . Strings::base64_encode($y->toBytes()) . "\r\n" . - '
'; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Signature/ASN1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Signature/ASN1.php deleted file mode 100644 index df52beed..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Signature/ASN1.php +++ /dev/null @@ -1,62 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\DSA\Formats\Signature; - -use phpseclib3\File\ASN1 as Encoder; -use phpseclib3\File\ASN1\Maps; -use phpseclib3\Math\BigInteger; - -/** - * ASN1 Signature Handler - * - * @author Jim Wigginton - */ -abstract class ASN1 -{ - /** - * Loads a signature - * - * @param string $sig - * @return array|bool - */ - public static function load($sig) - { - if (!is_string($sig)) { - return false; - } - - $decoded = Encoder::decodeBER($sig); - if (empty($decoded)) { - return false; - } - $components = Encoder::asn1map($decoded[0], Maps\DssSigValue::MAP); - - return $components; - } - - /** - * Returns a signature in the appropriate format - * - * @param \phpseclib3\Math\BigInteger $r - * @param \phpseclib3\Math\BigInteger $s - * @return string - */ - public static function save(BigInteger $r, BigInteger $s) - { - return Encoder::encodeDER(compact('r', 's'), Maps\DssSigValue::MAP); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Signature/Raw.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Signature/Raw.php deleted file mode 100644 index 2657a2a8..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Signature/Raw.php +++ /dev/null @@ -1,25 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\DSA\Formats\Signature; - -use phpseclib3\Crypt\Common\Formats\Signature\Raw as Progenitor; - -/** - * Raw DSA Signature Handler - * - * @author Jim Wigginton - */ -abstract class Raw extends Progenitor -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Signature/SSH2.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Signature/SSH2.php deleted file mode 100644 index dbfceabb..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Signature/SSH2.php +++ /dev/null @@ -1,74 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\DSA\Formats\Signature; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Math\BigInteger; - -/** - * SSH2 Signature Handler - * - * @author Jim Wigginton - */ -abstract class SSH2 -{ - /** - * Loads a signature - * - * @param string $sig - * @return mixed - */ - public static function load($sig) - { - if (!is_string($sig)) { - return false; - } - - $result = Strings::unpackSSH2('ss', $sig); - if ($result === false) { - return false; - } - list($type, $blob) = $result; - if ($type != 'ssh-dss' || strlen($blob) != 40) { - return false; - } - - return [ - 'r' => new BigInteger(substr($blob, 0, 20), 256), - 's' => new BigInteger(substr($blob, 20), 256) - ]; - } - - /** - * Returns a signature in the appropriate format - * - * @param \phpseclib3\Math\BigInteger $r - * @param \phpseclib3\Math\BigInteger $s - * @return string - */ - public static function save(BigInteger $r, BigInteger $s) - { - if ($r->getLength() > 160 || $s->getLength() > 160) { - return false; - } - return Strings::packSSH2( - 'ss', - 'ssh-dss', - str_pad($r->toBytes(), 20, "\0", STR_PAD_LEFT) . - str_pad($s->toBytes(), 20, "\0", STR_PAD_LEFT) - ); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Parameters.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Parameters.php deleted file mode 100644 index 84d16ba6..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Parameters.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\DSA; - -use phpseclib3\Crypt\DSA; - -/** - * DSA Parameters - * - * @author Jim Wigginton - */ -final class Parameters extends DSA -{ - /** - * Returns the parameters - * - * @param string $type - * @param array $options optional - * @return string - */ - public function toString($type = 'PKCS1', array $options = []) - { - $type = self::validatePlugin('Keys', 'PKCS1', 'saveParameters'); - - return $type::saveParameters($this->p, $this->q, $this->g, $options); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/PrivateKey.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/PrivateKey.php deleted file mode 100644 index 74d3e69e..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/PrivateKey.php +++ /dev/null @@ -1,152 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\DSA; - -use phpseclib3\Crypt\Common; -use phpseclib3\Crypt\DSA; -use phpseclib3\Crypt\DSA\Formats\Signature\ASN1 as ASN1Signature; -use phpseclib3\Math\BigInteger; - -/** - * DSA Private Key - * - * @author Jim Wigginton - */ -final class PrivateKey extends DSA implements Common\PrivateKey -{ - use Common\Traits\PasswordProtected; - - /** - * DSA secret exponent x - * - * @var \phpseclib3\Math\BigInteger - */ - protected $x; - - /** - * Returns the public key - * - * If you do "openssl rsa -in private.rsa -pubout -outform PEM" you get a PKCS8 formatted key - * that contains a publicKeyAlgorithm AlgorithmIdentifier and a publicKey BIT STRING. - * An AlgorithmIdentifier contains an OID and a parameters field. With RSA public keys this - * parameters field is NULL. With DSA PKCS8 public keys it is not - it contains the p, q and g - * variables. The publicKey BIT STRING contains, simply, the y variable. This can be verified - * by getting a DSA PKCS8 public key: - * - * "openssl dsa -in private.dsa -pubout -outform PEM" - * - * ie. just swap out rsa with dsa in the rsa command above. - * - * A PKCS1 public key corresponds to the publicKey portion of the PKCS8 key. In the case of RSA - * the publicKey portion /is/ the key. In the case of DSA it is not. You cannot verify a signature - * without the parameters and the PKCS1 DSA public key format does not include the parameters. - * - * @see self::getPrivateKey() - * @return mixed - */ - public function getPublicKey() - { - $type = self::validatePlugin('Keys', 'PKCS8', 'savePublicKey'); - - if (!isset($this->y)) { - $this->y = $this->g->powMod($this->x, $this->p); - } - - $key = $type::savePublicKey($this->p, $this->q, $this->g, $this->y); - - return DSA::loadFormat('PKCS8', $key) - ->withHash($this->hash->getHash()) - ->withSignatureFormat($this->shortFormat); - } - - /** - * Create a signature - * - * @see self::verify() - * @param string $message - * @return mixed - */ - public function sign($message) - { - $format = $this->sigFormat; - - if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) { - $signature = ''; - $result = openssl_sign($message, $signature, $this->toString('PKCS8'), $this->hash->getHash()); - - if ($result) { - if ($this->shortFormat == 'ASN1') { - return $signature; - } - - extract(ASN1Signature::load($signature)); - - return $format::save($r, $s); - } - } - - $h = $this->hash->hash($message); - $h = $this->bits2int($h); - - while (true) { - $k = BigInteger::randomRange(self::$one, $this->q->subtract(self::$one)); - $r = $this->g->powMod($k, $this->p); - list(, $r) = $r->divide($this->q); - if ($r->equals(self::$zero)) { - continue; - } - $kinv = $k->modInverse($this->q); - $temp = $h->add($this->x->multiply($r)); - $temp = $kinv->multiply($temp); - list(, $s) = $temp->divide($this->q); - if (!$s->equals(self::$zero)) { - break; - } - } - - // the following is an RFC6979 compliant implementation of deterministic DSA - // it's unused because it's mainly intended for use when a good CSPRNG isn't - // available. if phpseclib's CSPRNG isn't good then even key generation is - // suspect - /* - $h1 = $this->hash->hash($message); - $k = $this->computek($h1); - $r = $this->g->powMod($k, $this->p); - list(, $r) = $r->divide($this->q); - $kinv = $k->modInverse($this->q); - $h1 = $this->bits2int($h1); - $temp = $h1->add($this->x->multiply($r)); - $temp = $kinv->multiply($temp); - list(, $s) = $temp->divide($this->q); - */ - - return $format::save($r, $s); - } - - /** - * Returns the private key - * - * @param string $type - * @param array $options optional - * @return string - */ - public function toString($type, array $options = []) - { - $type = self::validatePlugin('Keys', $type, 'savePrivateKey'); - - if (!isset($this->y)) { - $this->y = $this->g->powMod($this->x, $this->p); - } - - return $type::savePrivateKey($this->p, $this->q, $this->g, $this->y, $this->x, $this->password, $options); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/PublicKey.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/PublicKey.php deleted file mode 100644 index c14ffbdf..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/PublicKey.php +++ /dev/null @@ -1,86 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\DSA; - -use phpseclib3\Crypt\Common; -use phpseclib3\Crypt\DSA; -use phpseclib3\Crypt\DSA\Formats\Signature\ASN1 as ASN1Signature; - -/** - * DSA Public Key - * - * @author Jim Wigginton - */ -final class PublicKey extends DSA implements Common\PublicKey -{ - use Common\Traits\Fingerprint; - - /** - * Verify a signature - * - * @see self::verify() - * @param string $message - * @param string $signature - * @return mixed - */ - public function verify($message, $signature) - { - $format = $this->sigFormat; - - $params = $format::load($signature); - if ($params === false || count($params) != 2) { - return false; - } - extract($params); - - if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) { - $sig = $format != 'ASN1' ? ASN1Signature::save($r, $s) : $signature; - - $result = openssl_verify($message, $sig, $this->toString('PKCS8'), $this->hash->getHash()); - - if ($result != -1) { - return (bool) $result; - } - } - - $q_1 = $this->q->subtract(self::$one); - if (!$r->between(self::$one, $q_1) || !$s->between(self::$one, $q_1)) { - return false; - } - - $w = $s->modInverse($this->q); - $h = $this->hash->hash($message); - $h = $this->bits2int($h); - list(, $u1) = $h->multiply($w)->divide($this->q); - list(, $u2) = $r->multiply($w)->divide($this->q); - $v1 = $this->g->powMod($u1, $this->p); - $v2 = $this->y->powMod($u2, $this->p); - list(, $v) = $v1->multiply($v2)->divide($this->p); - list(, $v) = $v->divide($this->q); - - return $v->equals($r); - } - - /** - * Returns the public key - * - * @param string $type - * @param array $options optional - * @return string - */ - public function toString($type, array $options = []) - { - $type = self::validatePlugin('Keys', $type, 'savePublicKey'); - - return $type::savePublicKey($this->p, $this->q, $this->g, $this->y, $options); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC.php deleted file mode 100644 index 10b38254..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC.php +++ /dev/null @@ -1,480 +0,0 @@ - - * getPublicKey(); - * - * $plaintext = 'terrafrost'; - * - * $signature = $private->sign($plaintext); - * - * echo $public->verify($plaintext, $signature) ? 'verified' : 'unverified'; - * ?> - * - * - * @author Jim Wigginton - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt; - -use phpseclib3\Crypt\Common\AsymmetricKey; -use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve; -use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve; -use phpseclib3\Crypt\EC\Curves\Curve25519; -use phpseclib3\Crypt\EC\Curves\Ed25519; -use phpseclib3\Crypt\EC\Curves\Ed448; -use phpseclib3\Crypt\EC\Formats\Keys\PKCS1; -use phpseclib3\Crypt\EC\Parameters; -use phpseclib3\Crypt\EC\PrivateKey; -use phpseclib3\Crypt\EC\PublicKey; -use phpseclib3\Exception\UnsupportedAlgorithmException; -use phpseclib3\Exception\UnsupportedCurveException; -use phpseclib3\Exception\UnsupportedOperationException; -use phpseclib3\File\ASN1; -use phpseclib3\File\ASN1\Maps\ECParameters; -use phpseclib3\Math\BigInteger; - -/** - * Pure-PHP implementation of EC. - * - * @author Jim Wigginton - */ -abstract class EC extends AsymmetricKey -{ - /** - * Algorithm Name - * - * @var string - */ - const ALGORITHM = 'EC'; - - /** - * Public Key QA - * - * @var object[] - */ - protected $QA; - - /** - * Curve - * - * @var \phpseclib3\Crypt\EC\BaseCurves\Base - */ - protected $curve; - - /** - * Signature Format - * - * @var string - */ - protected $format; - - /** - * Signature Format (Short) - * - * @var string - */ - protected $shortFormat; - - /** - * Curve Name - * - * @var string - */ - private $curveName; - - /** - * Curve Order - * - * Used for deterministic ECDSA - * - * @var \phpseclib3\Math\BigInteger - */ - protected $q; - - /** - * Alias for the private key - * - * Used for deterministic ECDSA. AsymmetricKey expects $x. I don't like x because - * with x you have x * the base point yielding an (x, y)-coordinate that is the - * public key. But the x is different depending on which side of the equal sign - * you're on. It's less ambiguous if you do dA * base point = (x, y)-coordinate. - * - * @var \phpseclib3\Math\BigInteger - */ - protected $x; - - /** - * Context - * - * @var string - */ - protected $context; - - /** - * Signature Format - * - * @var string - */ - protected $sigFormat; - - /** - * Create public / private key pair. - * - * @param string $curve - * @return \phpseclib3\Crypt\EC\PrivateKey - */ - public static function createKey($curve) - { - self::initialize_static_variables(); - - $class = new \ReflectionClass(static::class); - if ($class->isFinal()) { - throw new \RuntimeException('createKey() should not be called from final classes (' . static::class . ')'); - } - - if (!isset(self::$engines['PHP'])) { - self::useBestEngine(); - } - - $curve = strtolower($curve); - if (self::$engines['libsodium'] && $curve == 'ed25519' && function_exists('sodium_crypto_sign_keypair')) { - $kp = sodium_crypto_sign_keypair(); - - $privatekey = EC::loadFormat('libsodium', sodium_crypto_sign_secretkey($kp)); - //$publickey = EC::loadFormat('libsodium', sodium_crypto_sign_publickey($kp)); - - $privatekey->curveName = 'Ed25519'; - //$publickey->curveName = $curve; - - return $privatekey; - } - - $privatekey = new PrivateKey(); - - $curveName = $curve; - if (preg_match('#(?:^curve|^ed)\d+$#', $curveName)) { - $curveName = ucfirst($curveName); - } elseif (substr($curveName, 0, 10) == 'brainpoolp') { - $curveName = 'brainpoolP' . substr($curveName, 10); - } - $curve = '\phpseclib3\Crypt\EC\Curves\\' . $curveName; - - if (!class_exists($curve)) { - throw new UnsupportedCurveException('Named Curve of ' . $curveName . ' is not supported'); - } - - $reflect = new \ReflectionClass($curve); - $curveName = $reflect->isFinal() ? - $reflect->getParentClass()->getShortName() : - $reflect->getShortName(); - - $curve = new $curve(); - if ($curve instanceof TwistedEdwardsCurve) { - $arr = $curve->extractSecret(Random::string($curve instanceof Ed448 ? 57 : 32)); - $privatekey->dA = $dA = $arr['dA']; - $privatekey->secret = $arr['secret']; - } else { - $privatekey->dA = $dA = $curve->createRandomMultiplier(); - } - if ($curve instanceof Curve25519 && self::$engines['libsodium']) { - //$r = pack('H*', '0900000000000000000000000000000000000000000000000000000000000000'); - //$QA = sodium_crypto_scalarmult($dA->toBytes(), $r); - $QA = sodium_crypto_box_publickey_from_secretkey($dA->toBytes()); - $privatekey->QA = [$curve->convertInteger(new BigInteger(strrev($QA), 256))]; - } else { - $privatekey->QA = $curve->multiplyPoint($curve->getBasePoint(), $dA); - } - $privatekey->curve = $curve; - - //$publickey = clone $privatekey; - //unset($publickey->dA); - //unset($publickey->x); - - $privatekey->curveName = $curveName; - //$publickey->curveName = $curveName; - - if ($privatekey->curve instanceof TwistedEdwardsCurve) { - return $privatekey->withHash($curve::HASH); - } - - return $privatekey; - } - - /** - * OnLoad Handler - * - * @return bool - */ - protected static function onLoad(array $components) - { - if (!isset(self::$engines['PHP'])) { - self::useBestEngine(); - } - - if (!isset($components['dA']) && !isset($components['QA'])) { - $new = new Parameters(); - $new->curve = $components['curve']; - return $new; - } - - $new = isset($components['dA']) ? - new PrivateKey() : - new PublicKey(); - $new->curve = $components['curve']; - $new->QA = $components['QA']; - - if (isset($components['dA'])) { - $new->dA = $components['dA']; - $new->secret = $components['secret']; - } - - if ($new->curve instanceof TwistedEdwardsCurve) { - return $new->withHash($components['curve']::HASH); - } - - return $new; - } - - /** - * Constructor - * - * PublicKey and PrivateKey objects can only be created from abstract RSA class - */ - protected function __construct() - { - $this->sigFormat = self::validatePlugin('Signature', 'ASN1'); - $this->shortFormat = 'ASN1'; - - parent::__construct(); - } - - /** - * Returns the curve - * - * Returns a string if it's a named curve, an array if not - * - * @return string|array - */ - public function getCurve() - { - if ($this->curveName) { - return $this->curveName; - } - - if ($this->curve instanceof MontgomeryCurve) { - $this->curveName = $this->curve instanceof Curve25519 ? 'Curve25519' : 'Curve448'; - return $this->curveName; - } - - if ($this->curve instanceof TwistedEdwardsCurve) { - $this->curveName = $this->curve instanceof Ed25519 ? 'Ed25519' : 'Ed448'; - return $this->curveName; - } - - $params = $this->getParameters()->toString('PKCS8', ['namedCurve' => true]); - $decoded = ASN1::extractBER($params); - $decoded = ASN1::decodeBER($decoded); - $decoded = ASN1::asn1map($decoded[0], ECParameters::MAP); - if (isset($decoded['namedCurve'])) { - $this->curveName = $decoded['namedCurve']; - return $decoded['namedCurve']; - } - - if (!$namedCurves) { - PKCS1::useSpecifiedCurve(); - } - - return $decoded; - } - - /** - * Returns the key size - * - * Quoting https://tools.ietf.org/html/rfc5656#section-2, - * - * "The size of a set of elliptic curve domain parameters on a prime - * curve is defined as the number of bits in the binary representation - * of the field order, commonly denoted by p. Size on a - * characteristic-2 curve is defined as the number of bits in the binary - * representation of the field, commonly denoted by m. A set of - * elliptic curve domain parameters defines a group of order n generated - * by a base point P" - * - * @return int - */ - public function getLength() - { - return $this->curve->getLength(); - } - - /** - * Returns the current engine being used - * - * @see self::useInternalEngine() - * @see self::useBestEngine() - * @return string - */ - public function getEngine() - { - if (!isset(self::$engines['PHP'])) { - self::useBestEngine(); - } - if ($this->curve instanceof TwistedEdwardsCurve) { - return $this->curve instanceof Ed25519 && self::$engines['libsodium'] && !isset($this->context) ? - 'libsodium' : 'PHP'; - } - - return self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods()) ? - 'OpenSSL' : 'PHP'; - } - - /** - * Returns the public key coordinates as a string - * - * Used by ECDH - * - * @return string - */ - public function getEncodedCoordinates() - { - if ($this->curve instanceof MontgomeryCurve) { - return strrev($this->QA[0]->toBytes(true)); - } - if ($this->curve instanceof TwistedEdwardsCurve) { - return $this->curve->encodePoint($this->QA); - } - return "\4" . $this->QA[0]->toBytes(true) . $this->QA[1]->toBytes(true); - } - - /** - * Returns the parameters - * - * @see self::getPublicKey() - * @param string $type optional - * @return mixed - */ - public function getParameters($type = 'PKCS1') - { - $type = self::validatePlugin('Keys', $type, 'saveParameters'); - - $key = $type::saveParameters($this->curve); - - return EC::load($key, 'PKCS1') - ->withHash($this->hash->getHash()) - ->withSignatureFormat($this->shortFormat); - } - - /** - * Determines the signature padding mode - * - * Valid values are: ASN1, SSH2, Raw - * - * @param string $format - */ - public function withSignatureFormat($format) - { - if ($this->curve instanceof MontgomeryCurve) { - throw new UnsupportedOperationException('Montgomery Curves cannot be used to create signatures'); - } - - $new = clone $this; - $new->shortFormat = $format; - $new->sigFormat = self::validatePlugin('Signature', $format); - return $new; - } - - /** - * Returns the signature format currently being used - * - */ - public function getSignatureFormat() - { - return $this->shortFormat; - } - - /** - * Sets the context - * - * Used by Ed25519 / Ed448. - * - * @see self::sign() - * @see self::verify() - * @param string $context optional - */ - public function withContext($context = null) - { - if (!$this->curve instanceof TwistedEdwardsCurve) { - throw new UnsupportedCurveException('Only Ed25519 and Ed448 support contexts'); - } - - $new = clone $this; - if (!isset($context)) { - $new->context = null; - return $new; - } - if (!is_string($context)) { - throw new \InvalidArgumentException('setContext expects a string'); - } - if (strlen($context) > 255) { - throw new \LengthException('The context is supposed to be, at most, 255 bytes long'); - } - $new->context = $context; - return $new; - } - - /** - * Returns the signature format currently being used - * - */ - public function getContext() - { - return $this->context; - } - - /** - * Determines which hashing function should be used - * - * @param string $hash - */ - public function withHash($hash) - { - if ($this->curve instanceof MontgomeryCurve) { - throw new UnsupportedOperationException('Montgomery Curves cannot be used to create signatures'); - } - if ($this->curve instanceof Ed25519 && $hash != 'sha512') { - throw new UnsupportedAlgorithmException('Ed25519 only supports sha512 as a hash'); - } - if ($this->curve instanceof Ed448 && $hash != 'shake256-912') { - throw new UnsupportedAlgorithmException('Ed448 only supports shake256 with a length of 114 bytes'); - } - - return parent::withHash($hash); - } - - /** - * __toString() magic method - * - * @return string - */ - public function __toString() - { - if ($this->curve instanceof MontgomeryCurve) { - return ''; - } - - return parent::__toString(); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Base.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Base.php deleted file mode 100644 index dbc914be..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Base.php +++ /dev/null @@ -1,218 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\BaseCurves; - -use phpseclib3\Math\BigInteger; - -/** - * Base - * - * @author Jim Wigginton - */ -abstract class Base -{ - /** - * The Order - * - * @var BigInteger - */ - protected $order; - - /** - * Finite Field Integer factory - * - * @var \phpseclib3\Math\FiniteField\Integer - */ - protected $factory; - - /** - * Returns a random integer - * - * @return object - */ - public function randomInteger() - { - return $this->factory->randomInteger(); - } - - /** - * Converts a BigInteger to a \phpseclib3\Math\FiniteField\Integer integer - * - * @return object - */ - public function convertInteger(BigInteger $x) - { - return $this->factory->newInteger($x); - } - - /** - * Returns the length, in bytes, of the modulo - * - * @return integer - */ - public function getLengthInBytes() - { - return $this->factory->getLengthInBytes(); - } - - /** - * Returns the length, in bits, of the modulo - * - * @return integer - */ - public function getLength() - { - return $this->factory->getLength(); - } - - /** - * Multiply a point on the curve by a scalar - * - * Uses the montgomery ladder technique as described here: - * - * https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication#Montgomery_ladder - * https://github.com/phpecc/phpecc/issues/16#issuecomment-59176772 - * - * @return array - */ - public function multiplyPoint(array $p, BigInteger $d) - { - $alreadyInternal = isset($p[2]); - $r = $alreadyInternal ? - [[], $p] : - [[], $this->convertToInternal($p)]; - - $d = $d->toBits(); - for ($i = 0; $i < strlen($d); $i++) { - $d_i = (int) $d[$i]; - $r[1 - $d_i] = $this->addPoint($r[0], $r[1]); - $r[$d_i] = $this->doublePoint($r[$d_i]); - } - - return $alreadyInternal ? $r[0] : $this->convertToAffine($r[0]); - } - - /** - * Creates a random scalar multiplier - * - * @return BigInteger - */ - public function createRandomMultiplier() - { - static $one; - if (!isset($one)) { - $one = new BigInteger(1); - } - - return BigInteger::randomRange($one, $this->order->subtract($one)); - } - - /** - * Performs range check - */ - public function rangeCheck(BigInteger $x) - { - static $zero; - if (!isset($zero)) { - $zero = new BigInteger(); - } - - if (!isset($this->order)) { - throw new \RuntimeException('setOrder needs to be called before this method'); - } - if ($x->compare($this->order) > 0 || $x->compare($zero) <= 0) { - throw new \RangeException('x must be between 1 and the order of the curve'); - } - } - - /** - * Sets the Order - */ - public function setOrder(BigInteger $order) - { - $this->order = $order; - } - - /** - * Returns the Order - * - * @return \phpseclib3\Math\BigInteger - */ - public function getOrder() - { - return $this->order; - } - - /** - * Use a custom defined modular reduction function - * - * @return object - */ - public function setReduction(callable $func) - { - $this->factory->setReduction($func); - } - - /** - * Returns the affine point - * - * @return object[] - */ - public function convertToAffine(array $p) - { - return $p; - } - - /** - * Converts an affine point to a jacobian coordinate - * - * @return object[] - */ - public function convertToInternal(array $p) - { - return $p; - } - - /** - * Negates a point - * - * @return object[] - */ - public function negatePoint(array $p) - { - $temp = [ - $p[0], - $p[1]->negate() - ]; - if (isset($p[2])) { - $temp[] = $p[2]; - } - return $temp; - } - - /** - * Multiply and Add Points - * - * @return int[] - */ - public function multiplyAddPoints(array $points, array $scalars) - { - $p1 = $this->convertToInternal($points[0]); - $p2 = $this->convertToInternal($points[1]); - $p1 = $this->multiplyPoint($p1, $scalars[0]); - $p2 = $this->multiplyPoint($p2, $scalars[1]); - $r = $this->addPoint($p1, $p2); - return $this->convertToAffine($r); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Binary.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Binary.php deleted file mode 100644 index 4fc6c70c..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Binary.php +++ /dev/null @@ -1,373 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\BaseCurves; - -use phpseclib3\Math\BigInteger; -use phpseclib3\Math\BinaryField; -use phpseclib3\Math\BinaryField\Integer as BinaryInteger; - -/** - * Curves over y^2 + x*y = x^3 + a*x^2 + b - * - * @author Jim Wigginton - */ -class Binary extends Base -{ - /** - * Binary Field Integer factory - * - * @var \phpseclib3\Math\BinaryField - */ - protected $factory; - - /** - * Cofficient for x^1 - * - * @var object - */ - protected $a; - - /** - * Cofficient for x^0 - * - * @var object - */ - protected $b; - - /** - * Base Point - * - * @var object - */ - protected $p; - - /** - * The number one over the specified finite field - * - * @var object - */ - protected $one; - - /** - * The modulo - * - * @var BigInteger - */ - protected $modulo; - - /** - * The Order - * - * @var BigInteger - */ - protected $order; - - /** - * Sets the modulo - */ - public function setModulo(...$modulo) - { - $this->modulo = $modulo; - $this->factory = new BinaryField(...$modulo); - - $this->one = $this->factory->newInteger("\1"); - } - - /** - * Set coefficients a and b - * - * @param string $a - * @param string $b - */ - public function setCoefficients($a, $b) - { - if (!isset($this->factory)) { - throw new \RuntimeException('setModulo needs to be called before this method'); - } - $this->a = $this->factory->newInteger(pack('H*', $a)); - $this->b = $this->factory->newInteger(pack('H*', $b)); - } - - /** - * Set x and y coordinates for the base point - * - * @param string|BinaryInteger $x - * @param string|BinaryInteger $y - */ - public function setBasePoint($x, $y) - { - switch (true) { - case !is_string($x) && !$x instanceof BinaryInteger: - throw new \UnexpectedValueException('Argument 1 passed to Binary::setBasePoint() must be a string or an instance of BinaryField\Integer'); - case !is_string($y) && !$y instanceof BinaryInteger: - throw new \UnexpectedValueException('Argument 2 passed to Binary::setBasePoint() must be a string or an instance of BinaryField\Integer'); - } - if (!isset($this->factory)) { - throw new \RuntimeException('setModulo needs to be called before this method'); - } - $this->p = [ - is_string($x) ? $this->factory->newInteger(pack('H*', $x)) : $x, - is_string($y) ? $this->factory->newInteger(pack('H*', $y)) : $y - ]; - } - - /** - * Retrieve the base point as an array - * - * @return array - */ - public function getBasePoint() - { - if (!isset($this->factory)) { - throw new \RuntimeException('setModulo needs to be called before this method'); - } - /* - if (!isset($this->p)) { - throw new \RuntimeException('setBasePoint needs to be called before this method'); - } - */ - return $this->p; - } - - /** - * Adds two points on the curve - * - * @return FiniteField[] - */ - public function addPoint(array $p, array $q) - { - if (!isset($this->factory)) { - throw new \RuntimeException('setModulo needs to be called before this method'); - } - - if (!count($p) || !count($q)) { - if (count($q)) { - return $q; - } - if (count($p)) { - return $p; - } - return []; - } - - if (!isset($p[2]) || !isset($q[2])) { - throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa'); - } - - if ($p[0]->equals($q[0])) { - return !$p[1]->equals($q[1]) ? [] : $this->doublePoint($p); - } - - // formulas from http://hyperelliptic.org/EFD/g12o/auto-shortw-jacobian.html - - list($x1, $y1, $z1) = $p; - list($x2, $y2, $z2) = $q; - - $o1 = $z1->multiply($z1); - $b = $x2->multiply($o1); - - if ($z2->equals($this->one)) { - $d = $y2->multiply($o1)->multiply($z1); - $e = $x1->add($b); - $f = $y1->add($d); - $z3 = $e->multiply($z1); - $h = $f->multiply($x2)->add($z3->multiply($y2)); - $i = $f->add($z3); - $g = $z3->multiply($z3); - $p1 = $this->a->multiply($g); - $p2 = $f->multiply($i); - $p3 = $e->multiply($e)->multiply($e); - $x3 = $p1->add($p2)->add($p3); - $y3 = $i->multiply($x3)->add($g->multiply($h)); - - return [$x3, $y3, $z3]; - } - - $o2 = $z2->multiply($z2); - $a = $x1->multiply($o2); - $c = $y1->multiply($o2)->multiply($z2); - $d = $y2->multiply($o1)->multiply($z1); - $e = $a->add($b); - $f = $c->add($d); - $g = $e->multiply($z1); - $h = $f->multiply($x2)->add($g->multiply($y2)); - $z3 = $g->multiply($z2); - $i = $f->add($z3); - $p1 = $this->a->multiply($z3->multiply($z3)); - $p2 = $f->multiply($i); - $p3 = $e->multiply($e)->multiply($e); - $x3 = $p1->add($p2)->add($p3); - $y3 = $i->multiply($x3)->add($g->multiply($g)->multiply($h)); - - return [$x3, $y3, $z3]; - } - - /** - * Doubles a point on a curve - * - * @return FiniteField[] - */ - public function doublePoint(array $p) - { - if (!isset($this->factory)) { - throw new \RuntimeException('setModulo needs to be called before this method'); - } - - if (!count($p)) { - return []; - } - - if (!isset($p[2])) { - throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa'); - } - - // formulas from http://hyperelliptic.org/EFD/g12o/auto-shortw-jacobian.html - - list($x1, $y1, $z1) = $p; - - $a = $x1->multiply($x1); - $b = $a->multiply($a); - - if ($z1->equals($this->one)) { - $x3 = $b->add($this->b); - $z3 = clone $x1; - $p1 = $a->add($y1)->add($z3)->multiply($this->b); - $p2 = $a->add($y1)->multiply($b); - $y3 = $p1->add($p2); - - return [$x3, $y3, $z3]; - } - - $c = $z1->multiply($z1); - $d = $c->multiply($c); - $x3 = $b->add($this->b->multiply($d->multiply($d))); - $z3 = $x1->multiply($c); - $p1 = $b->multiply($z3); - $p2 = $a->add($y1->multiply($z1))->add($z3)->multiply($x3); - $y3 = $p1->add($p2); - - return [$x3, $y3, $z3]; - } - - /** - * Returns the X coordinate and the derived Y coordinate - * - * Not supported because it is covered by patents. - * Quoting https://www.openssl.org/docs/man1.1.0/apps/ecparam.html , - * - * "Due to patent issues the compressed option is disabled by default for binary curves - * and can be enabled by defining the preprocessor macro OPENSSL_EC_BIN_PT_COMP at - * compile time." - * - * @return array - */ - public function derivePoint($m) - { - throw new \RuntimeException('Point compression on binary finite field elliptic curves is not supported'); - } - - /** - * Tests whether or not the x / y values satisfy the equation - * - * @return boolean - */ - public function verifyPoint(array $p) - { - list($x, $y) = $p; - $lhs = $y->multiply($y); - $lhs = $lhs->add($x->multiply($y)); - $x2 = $x->multiply($x); - $x3 = $x2->multiply($x); - $rhs = $x3->add($this->a->multiply($x2))->add($this->b); - - return $lhs->equals($rhs); - } - - /** - * Returns the modulo - * - * @return \phpseclib3\Math\BigInteger - */ - public function getModulo() - { - return $this->modulo; - } - - /** - * Returns the a coefficient - * - * @return \phpseclib3\Math\PrimeField\Integer - */ - public function getA() - { - return $this->a; - } - - /** - * Returns the a coefficient - * - * @return \phpseclib3\Math\PrimeField\Integer - */ - public function getB() - { - return $this->b; - } - - /** - * Returns the affine point - * - * A Jacobian Coordinate is of the form (x, y, z). - * To convert a Jacobian Coordinate to an Affine Point - * you do (x / z^2, y / z^3) - * - * @return \phpseclib3\Math\PrimeField\Integer[] - */ - public function convertToAffine(array $p) - { - if (!isset($p[2])) { - return $p; - } - list($x, $y, $z) = $p; - $z = $this->one->divide($z); - $z2 = $z->multiply($z); - return [ - $x->multiply($z2), - $y->multiply($z2)->multiply($z) - ]; - } - - /** - * Converts an affine point to a jacobian coordinate - * - * @return \phpseclib3\Math\PrimeField\Integer[] - */ - public function convertToInternal(array $p) - { - if (isset($p[2])) { - return $p; - } - - $p[2] = clone $this->one; - $p['fresh'] = true; - return $p; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/KoblitzPrime.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/KoblitzPrime.php deleted file mode 100644 index d8492ebc..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/KoblitzPrime.php +++ /dev/null @@ -1,335 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\BaseCurves; - -use phpseclib3\Math\BigInteger; -use phpseclib3\Math\PrimeField; - -/** - * Curves over y^2 = x^3 + b - * - * @author Jim Wigginton - */ -class KoblitzPrime extends Prime -{ - /** - * Basis - * - * @var list - */ - protected $basis; - - /** - * Beta - * - * @var PrimeField\Integer - */ - protected $beta; - - // don't overwrite setCoefficients() with one that only accepts one parameter so that - // one might be able to switch between KoblitzPrime and Prime more easily (for benchmarking - // purposes). - - /** - * Multiply and Add Points - * - * Uses a efficiently computable endomorphism to achieve a slight speedup - * - * Adapted from: - * https://github.com/indutny/elliptic/blob/725bd91/lib/elliptic/curve/short.js#L219 - * - * @return int[] - */ - public function multiplyAddPoints(array $points, array $scalars) - { - static $zero, $one, $two; - if (!isset($two)) { - $two = new BigInteger(2); - $one = new BigInteger(1); - } - - if (!isset($this->beta)) { - // get roots - $inv = $this->one->divide($this->two)->negate(); - $s = $this->three->negate()->squareRoot()->multiply($inv); - $betas = [ - $inv->add($s), - $inv->subtract($s) - ]; - $this->beta = $betas[0]->compare($betas[1]) < 0 ? $betas[0] : $betas[1]; - //echo strtoupper($this->beta->toHex(true)) . "\n"; exit; - } - - if (!isset($this->basis)) { - $factory = new PrimeField($this->order); - $tempOne = $factory->newInteger($one); - $tempTwo = $factory->newInteger($two); - $tempThree = $factory->newInteger(new BigInteger(3)); - - $inv = $tempOne->divide($tempTwo)->negate(); - $s = $tempThree->negate()->squareRoot()->multiply($inv); - - $lambdas = [ - $inv->add($s), - $inv->subtract($s) - ]; - - $lhs = $this->multiplyPoint($this->p, $lambdas[0])[0]; - $rhs = $this->p[0]->multiply($this->beta); - $lambda = $lhs->equals($rhs) ? $lambdas[0] : $lambdas[1]; - - $this->basis = static::extendedGCD($lambda->toBigInteger(), $this->order); - ///* - foreach ($this->basis as $basis) { - echo strtoupper($basis['a']->toHex(true)) . "\n"; - echo strtoupper($basis['b']->toHex(true)) . "\n\n"; - } - exit; - //*/ - } - - $npoints = $nscalars = []; - for ($i = 0; $i < count($points); $i++) { - $p = $points[$i]; - $k = $scalars[$i]->toBigInteger(); - - // begin split - list($v1, $v2) = $this->basis; - - $c1 = $v2['b']->multiply($k); - list($c1, $r) = $c1->divide($this->order); - if ($this->order->compare($r->multiply($two)) <= 0) { - $c1 = $c1->add($one); - } - - $c2 = $v1['b']->negate()->multiply($k); - list($c2, $r) = $c2->divide($this->order); - if ($this->order->compare($r->multiply($two)) <= 0) { - $c2 = $c2->add($one); - } - - $p1 = $c1->multiply($v1['a']); - $p2 = $c2->multiply($v2['a']); - $q1 = $c1->multiply($v1['b']); - $q2 = $c2->multiply($v2['b']); - - $k1 = $k->subtract($p1)->subtract($p2); - $k2 = $q1->add($q2)->negate(); - // end split - - $beta = [ - $p[0]->multiply($this->beta), - $p[1], - clone $this->one - ]; - - if (isset($p['naf'])) { - $beta['naf'] = array_map(function ($p) { - return [ - $p[0]->multiply($this->beta), - $p[1], - clone $this->one - ]; - }, $p['naf']); - $beta['nafwidth'] = $p['nafwidth']; - } - - if ($k1->isNegative()) { - $k1 = $k1->negate(); - $p = $this->negatePoint($p); - } - - if ($k2->isNegative()) { - $k2 = $k2->negate(); - $beta = $this->negatePoint($beta); - } - - $pos = 2 * $i; - $npoints[$pos] = $p; - $nscalars[$pos] = $this->factory->newInteger($k1); - - $pos++; - $npoints[$pos] = $beta; - $nscalars[$pos] = $this->factory->newInteger($k2); - } - - return parent::multiplyAddPoints($npoints, $nscalars); - } - - /** - * Returns the numerator and denominator of the slope - * - * @return FiniteField[] - */ - protected function doublePointHelper(array $p) - { - $numerator = $this->three->multiply($p[0])->multiply($p[0]); - $denominator = $this->two->multiply($p[1]); - return [$numerator, $denominator]; - } - - /** - * Doubles a jacobian coordinate on the curve - * - * See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l - * - * @return FiniteField[] - */ - protected function jacobianDoublePoint(array $p) - { - list($x1, $y1, $z1) = $p; - $a = $x1->multiply($x1); - $b = $y1->multiply($y1); - $c = $b->multiply($b); - $d = $x1->add($b); - $d = $d->multiply($d)->subtract($a)->subtract($c)->multiply($this->two); - $e = $this->three->multiply($a); - $f = $e->multiply($e); - $x3 = $f->subtract($this->two->multiply($d)); - $y3 = $e->multiply($d->subtract($x3))->subtract( - $this->eight->multiply($c) - ); - $z3 = $this->two->multiply($y1)->multiply($z1); - return [$x3, $y3, $z3]; - } - - /** - * Doubles a "fresh" jacobian coordinate on the curve - * - * See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-mdbl-2007-bl - * - * @return FiniteField[] - */ - protected function jacobianDoublePointMixed(array $p) - { - list($x1, $y1) = $p; - $xx = $x1->multiply($x1); - $yy = $y1->multiply($y1); - $yyyy = $yy->multiply($yy); - $s = $x1->add($yy); - $s = $s->multiply($s)->subtract($xx)->subtract($yyyy)->multiply($this->two); - $m = $this->three->multiply($xx); - $t = $m->multiply($m)->subtract($this->two->multiply($s)); - $x3 = $t; - $y3 = $s->subtract($t); - $y3 = $m->multiply($y3)->subtract($this->eight->multiply($yyyy)); - $z3 = $this->two->multiply($y1); - return [$x3, $y3, $z3]; - } - - /** - * Tests whether or not the x / y values satisfy the equation - * - * @return boolean - */ - public function verifyPoint(array $p) - { - list($x, $y) = $p; - $lhs = $y->multiply($y); - $temp = $x->multiply($x)->multiply($x); - $rhs = $temp->add($this->b); - - return $lhs->equals($rhs); - } - - /** - * Calculates the parameters needed from the Euclidean algorithm as discussed at - * http://diamond.boisestate.edu/~liljanab/MATH308/GuideToECC.pdf#page=148 - * - * @param BigInteger $u - * @param BigInteger $v - * @return BigInteger[] - */ - protected static function extendedGCD(BigInteger $u, BigInteger $v) - { - $one = new BigInteger(1); - $zero = new BigInteger(); - - $a = clone $one; - $b = clone $zero; - $c = clone $zero; - $d = clone $one; - - $stop = $v->bitwise_rightShift($v->getLength() >> 1); - - $a1 = clone $zero; - $b1 = clone $zero; - $a2 = clone $zero; - $b2 = clone $zero; - - $postGreatestIndex = 0; - - while (!$v->equals($zero)) { - list($q) = $u->divide($v); - - $temp = $u; - $u = $v; - $v = $temp->subtract($v->multiply($q)); - - $temp = $a; - $a = $c; - $c = $temp->subtract($a->multiply($q)); - - $temp = $b; - $b = $d; - $d = $temp->subtract($b->multiply($q)); - - if ($v->compare($stop) > 0) { - $a0 = $v; - $b0 = $c; - } else { - $postGreatestIndex++; - } - - if ($postGreatestIndex == 1) { - $a1 = $v; - $b1 = $c->negate(); - } - - if ($postGreatestIndex == 2) { - $rhs = $a0->multiply($a0)->add($b0->multiply($b0)); - $lhs = $v->multiply($v)->add($b->multiply($b)); - if ($lhs->compare($rhs) <= 0) { - $a2 = $a0; - $b2 = $b0->negate(); - } else { - $a2 = $v; - $b2 = $c->negate(); - } - - break; - } - } - - return [ - ['a' => $a1, 'b' => $b1], - ['a' => $a2, 'b' => $b2] - ]; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Montgomery.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Montgomery.php deleted file mode 100644 index e3fa50b3..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Montgomery.php +++ /dev/null @@ -1,279 +0,0 @@ - - * @copyright 2019 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\BaseCurves; - -use phpseclib3\Crypt\EC\Curves\Curve25519; -use phpseclib3\Math\BigInteger; -use phpseclib3\Math\PrimeField; -use phpseclib3\Math\PrimeField\Integer as PrimeInteger; - -/** - * Curves over y^2 = x^3 + a*x + x - * - * @author Jim Wigginton - */ -class Montgomery extends Base -{ - /** - * Prime Field Integer factory - * - * @var \phpseclib3\Math\PrimeField - */ - protected $factory; - - /** - * Cofficient for x - * - * @var object - */ - protected $a; - - /** - * Constant used for point doubling - * - * @var object - */ - protected $a24; - - /** - * The Number Zero - * - * @var object - */ - protected $zero; - - /** - * The Number One - * - * @var object - */ - protected $one; - - /** - * Base Point - * - * @var object - */ - protected $p; - - /** - * The modulo - * - * @var BigInteger - */ - protected $modulo; - - /** - * The Order - * - * @var BigInteger - */ - protected $order; - - /** - * Sets the modulo - */ - public function setModulo(BigInteger $modulo) - { - $this->modulo = $modulo; - $this->factory = new PrimeField($modulo); - $this->zero = $this->factory->newInteger(new BigInteger()); - $this->one = $this->factory->newInteger(new BigInteger(1)); - } - - /** - * Set coefficients a - */ - public function setCoefficients(BigInteger $a) - { - if (!isset($this->factory)) { - throw new \RuntimeException('setModulo needs to be called before this method'); - } - $this->a = $this->factory->newInteger($a); - $two = $this->factory->newInteger(new BigInteger(2)); - $four = $this->factory->newInteger(new BigInteger(4)); - $this->a24 = $this->a->subtract($two)->divide($four); - } - - /** - * Set x and y coordinates for the base point - * - * @param BigInteger|PrimeInteger $x - * @param BigInteger|PrimeInteger $y - * @return PrimeInteger[] - */ - public function setBasePoint($x, $y) - { - switch (true) { - case !$x instanceof BigInteger && !$x instanceof PrimeInteger: - throw new \UnexpectedValueException('Argument 1 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\Integer'); - case !$y instanceof BigInteger && !$y instanceof PrimeInteger: - throw new \UnexpectedValueException('Argument 2 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\Integer'); - } - if (!isset($this->factory)) { - throw new \RuntimeException('setModulo needs to be called before this method'); - } - $this->p = [ - $x instanceof BigInteger ? $this->factory->newInteger($x) : $x, - $y instanceof BigInteger ? $this->factory->newInteger($y) : $y - ]; - } - - /** - * Retrieve the base point as an array - * - * @return array - */ - public function getBasePoint() - { - if (!isset($this->factory)) { - throw new \RuntimeException('setModulo needs to be called before this method'); - } - /* - if (!isset($this->p)) { - throw new \RuntimeException('setBasePoint needs to be called before this method'); - } - */ - return $this->p; - } - - /** - * Doubles and adds a point on a curve - * - * See https://tools.ietf.org/html/draft-ietf-tls-curve25519-01#appendix-A.1.3 - * - * @return FiniteField[][] - */ - private function doubleAndAddPoint(array $p, array $q, PrimeInteger $x1) - { - if (!isset($this->factory)) { - throw new \RuntimeException('setModulo needs to be called before this method'); - } - - if (!count($p) || !count($q)) { - return []; - } - - if (!isset($p[1])) { - throw new \RuntimeException('Affine coordinates need to be manually converted to XZ coordinates'); - } - - list($x2, $z2) = $p; - list($x3, $z3) = $q; - - $a = $x2->add($z2); - $aa = $a->multiply($a); - $b = $x2->subtract($z2); - $bb = $b->multiply($b); - $e = $aa->subtract($bb); - $c = $x3->add($z3); - $d = $x3->subtract($z3); - $da = $d->multiply($a); - $cb = $c->multiply($b); - $temp = $da->add($cb); - $x5 = $temp->multiply($temp); - $temp = $da->subtract($cb); - $z5 = $x1->multiply($temp->multiply($temp)); - $x4 = $aa->multiply($bb); - $temp = static::class == Curve25519::class ? $bb : $aa; - $z4 = $e->multiply($temp->add($this->a24->multiply($e))); - - return [ - [$x4, $z4], - [$x5, $z5] - ]; - } - - /** - * Multiply a point on the curve by a scalar - * - * Uses the montgomery ladder technique as described here: - * - * https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication#Montgomery_ladder - * https://github.com/phpecc/phpecc/issues/16#issuecomment-59176772 - * - * @return array - */ - public function multiplyPoint(array $p, BigInteger $d) - { - $p1 = [$this->one, $this->zero]; - $alreadyInternal = isset($x[1]); - $p2 = $this->convertToInternal($p); - $x = $p[0]; - - $b = $d->toBits(); - $b = str_pad($b, 256, '0', STR_PAD_LEFT); - for ($i = 0; $i < strlen($b); $i++) { - $b_i = (int) $b[$i]; - if ($b_i) { - list($p2, $p1) = $this->doubleAndAddPoint($p2, $p1, $x); - } else { - list($p1, $p2) = $this->doubleAndAddPoint($p1, $p2, $x); - } - } - - return $alreadyInternal ? $p1 : $this->convertToAffine($p1); - } - - /** - * Converts an affine point to an XZ coordinate - * - * From https://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html - * - * XZ coordinates represent x y as X Z satsfying the following equations: - * - * x=X/Z - * - * @return \phpseclib3\Math\PrimeField\Integer[] - */ - public function convertToInternal(array $p) - { - if (empty($p)) { - return [clone $this->zero, clone $this->one]; - } - - if (isset($p[1])) { - return $p; - } - - $p[1] = clone $this->one; - - return $p; - } - - /** - * Returns the affine point - * - * @return \phpseclib3\Math\PrimeField\Integer[] - */ - public function convertToAffine(array $p) - { - if (!isset($p[1])) { - return $p; - } - list($x, $z) = $p; - return [$x->divide($z)]; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Prime.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Prime.php deleted file mode 100644 index 6250dfb0..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Prime.php +++ /dev/null @@ -1,785 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\BaseCurves; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Math\BigInteger; -use phpseclib3\Math\Common\FiniteField\Integer; -use phpseclib3\Math\PrimeField; -use phpseclib3\Math\PrimeField\Integer as PrimeInteger; - -/** - * Curves over y^2 = x^3 + a*x + b - * - * @author Jim Wigginton - */ -class Prime extends Base -{ - /** - * Prime Field Integer factory - * - * @var \phpseclib3\Math\PrimeFields - */ - protected $factory; - - /** - * Cofficient for x^1 - * - * @var object - */ - protected $a; - - /** - * Cofficient for x^0 - * - * @var object - */ - protected $b; - - /** - * Base Point - * - * @var object - */ - protected $p; - - /** - * The number one over the specified finite field - * - * @var object - */ - protected $one; - - /** - * The number two over the specified finite field - * - * @var object - */ - protected $two; - - /** - * The number three over the specified finite field - * - * @var object - */ - protected $three; - - /** - * The number four over the specified finite field - * - * @var object - */ - protected $four; - - /** - * The number eight over the specified finite field - * - * @var object - */ - protected $eight; - - /** - * The modulo - * - * @var BigInteger - */ - protected $modulo; - - /** - * The Order - * - * @var BigInteger - */ - protected $order; - - /** - * Sets the modulo - */ - public function setModulo(BigInteger $modulo) - { - $this->modulo = $modulo; - $this->factory = new PrimeField($modulo); - $this->two = $this->factory->newInteger(new BigInteger(2)); - $this->three = $this->factory->newInteger(new BigInteger(3)); - // used by jacobian coordinates - $this->one = $this->factory->newInteger(new BigInteger(1)); - $this->four = $this->factory->newInteger(new BigInteger(4)); - $this->eight = $this->factory->newInteger(new BigInteger(8)); - } - - /** - * Set coefficients a and b - */ - public function setCoefficients(BigInteger $a, BigInteger $b) - { - if (!isset($this->factory)) { - throw new \RuntimeException('setModulo needs to be called before this method'); - } - $this->a = $this->factory->newInteger($a); - $this->b = $this->factory->newInteger($b); - } - - /** - * Set x and y coordinates for the base point - * - * @param BigInteger|PrimeInteger $x - * @param BigInteger|PrimeInteger $y - * @return PrimeInteger[] - */ - public function setBasePoint($x, $y) - { - switch (true) { - case !$x instanceof BigInteger && !$x instanceof PrimeInteger: - throw new \UnexpectedValueException('Argument 1 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\Integer'); - case !$y instanceof BigInteger && !$y instanceof PrimeInteger: - throw new \UnexpectedValueException('Argument 2 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\Integer'); - } - if (!isset($this->factory)) { - throw new \RuntimeException('setModulo needs to be called before this method'); - } - $this->p = [ - $x instanceof BigInteger ? $this->factory->newInteger($x) : $x, - $y instanceof BigInteger ? $this->factory->newInteger($y) : $y - ]; - } - - /** - * Retrieve the base point as an array - * - * @return array - */ - public function getBasePoint() - { - if (!isset($this->factory)) { - throw new \RuntimeException('setModulo needs to be called before this method'); - } - /* - if (!isset($this->p)) { - throw new \RuntimeException('setBasePoint needs to be called before this method'); - } - */ - return $this->p; - } - - /** - * Adds two "fresh" jacobian form on the curve - * - * @return FiniteField[] - */ - protected function jacobianAddPointMixedXY(array $p, array $q) - { - list($u1, $s1) = $p; - list($u2, $s2) = $q; - if ($u1->equals($u2)) { - if (!$s1->equals($s2)) { - return []; - } else { - return $this->doublePoint($p); - } - } - $h = $u2->subtract($u1); - $r = $s2->subtract($s1); - $h2 = $h->multiply($h); - $h3 = $h2->multiply($h); - $v = $u1->multiply($h2); - $x3 = $r->multiply($r)->subtract($h3)->subtract($v->multiply($this->two)); - $y3 = $r->multiply( - $v->subtract($x3) - )->subtract( - $s1->multiply($h3) - ); - return [$x3, $y3, $h]; - } - - /** - * Adds one "fresh" jacobian form on the curve - * - * The second parameter should be the "fresh" one - * - * @return FiniteField[] - */ - protected function jacobianAddPointMixedX(array $p, array $q) - { - list($u1, $s1, $z1) = $p; - list($x2, $y2) = $q; - - $z12 = $z1->multiply($z1); - - $u2 = $x2->multiply($z12); - $s2 = $y2->multiply($z12->multiply($z1)); - if ($u1->equals($u2)) { - if (!$s1->equals($s2)) { - return []; - } else { - return $this->doublePoint($p); - } - } - $h = $u2->subtract($u1); - $r = $s2->subtract($s1); - $h2 = $h->multiply($h); - $h3 = $h2->multiply($h); - $v = $u1->multiply($h2); - $x3 = $r->multiply($r)->subtract($h3)->subtract($v->multiply($this->two)); - $y3 = $r->multiply( - $v->subtract($x3) - )->subtract( - $s1->multiply($h3) - ); - $z3 = $h->multiply($z1); - return [$x3, $y3, $z3]; - } - - /** - * Adds two jacobian coordinates on the curve - * - * @return FiniteField[] - */ - protected function jacobianAddPoint(array $p, array $q) - { - list($x1, $y1, $z1) = $p; - list($x2, $y2, $z2) = $q; - - $z12 = $z1->multiply($z1); - $z22 = $z2->multiply($z2); - - $u1 = $x1->multiply($z22); - $u2 = $x2->multiply($z12); - $s1 = $y1->multiply($z22->multiply($z2)); - $s2 = $y2->multiply($z12->multiply($z1)); - if ($u1->equals($u2)) { - if (!$s1->equals($s2)) { - return []; - } else { - return $this->doublePoint($p); - } - } - $h = $u2->subtract($u1); - $r = $s2->subtract($s1); - $h2 = $h->multiply($h); - $h3 = $h2->multiply($h); - $v = $u1->multiply($h2); - $x3 = $r->multiply($r)->subtract($h3)->subtract($v->multiply($this->two)); - $y3 = $r->multiply( - $v->subtract($x3) - )->subtract( - $s1->multiply($h3) - ); - $z3 = $h->multiply($z1)->multiply($z2); - return [$x3, $y3, $z3]; - } - - /** - * Adds two points on the curve - * - * @return FiniteField[] - */ - public function addPoint(array $p, array $q) - { - if (!isset($this->factory)) { - throw new \RuntimeException('setModulo needs to be called before this method'); - } - - if (!count($p) || !count($q)) { - if (count($q)) { - return $q; - } - if (count($p)) { - return $p; - } - return []; - } - - // use jacobian coordinates - if (isset($p[2]) && isset($q[2])) { - if (isset($p['fresh']) && isset($q['fresh'])) { - return $this->jacobianAddPointMixedXY($p, $q); - } - if (isset($p['fresh'])) { - return $this->jacobianAddPointMixedX($q, $p); - } - if (isset($q['fresh'])) { - return $this->jacobianAddPointMixedX($p, $q); - } - return $this->jacobianAddPoint($p, $q); - } - - if (isset($p[2]) || isset($q[2])) { - throw new \RuntimeException('Affine coordinates need to be manually converted to Jacobi coordinates or vice versa'); - } - - if ($p[0]->equals($q[0])) { - if (!$p[1]->equals($q[1])) { - return []; - } else { // eg. doublePoint - list($numerator, $denominator) = $this->doublePointHelper($p); - } - } else { - $numerator = $q[1]->subtract($p[1]); - $denominator = $q[0]->subtract($p[0]); - } - $slope = $numerator->divide($denominator); - $x = $slope->multiply($slope)->subtract($p[0])->subtract($q[0]); - $y = $slope->multiply($p[0]->subtract($x))->subtract($p[1]); - - return [$x, $y]; - } - - /** - * Returns the numerator and denominator of the slope - * - * @return FiniteField[] - */ - protected function doublePointHelper(array $p) - { - $numerator = $this->three->multiply($p[0])->multiply($p[0])->add($this->a); - $denominator = $this->two->multiply($p[1]); - return [$numerator, $denominator]; - } - - /** - * Doubles a jacobian coordinate on the curve - * - * @return FiniteField[] - */ - protected function jacobianDoublePoint(array $p) - { - list($x, $y, $z) = $p; - $x2 = $x->multiply($x); - $y2 = $y->multiply($y); - $z2 = $z->multiply($z); - $s = $this->four->multiply($x)->multiply($y2); - $m1 = $this->three->multiply($x2); - $m2 = $this->a->multiply($z2->multiply($z2)); - $m = $m1->add($m2); - $x1 = $m->multiply($m)->subtract($this->two->multiply($s)); - $y1 = $m->multiply($s->subtract($x1))->subtract( - $this->eight->multiply($y2->multiply($y2)) - ); - $z1 = $this->two->multiply($y)->multiply($z); - return [$x1, $y1, $z1]; - } - - /** - * Doubles a "fresh" jacobian coordinate on the curve - * - * @return FiniteField[] - */ - protected function jacobianDoublePointMixed(array $p) - { - list($x, $y) = $p; - $x2 = $x->multiply($x); - $y2 = $y->multiply($y); - $s = $this->four->multiply($x)->multiply($y2); - $m1 = $this->three->multiply($x2); - $m = $m1->add($this->a); - $x1 = $m->multiply($m)->subtract($this->two->multiply($s)); - $y1 = $m->multiply($s->subtract($x1))->subtract( - $this->eight->multiply($y2->multiply($y2)) - ); - $z1 = $this->two->multiply($y); - return [$x1, $y1, $z1]; - } - - /** - * Doubles a point on a curve - * - * @return FiniteField[] - */ - public function doublePoint(array $p) - { - if (!isset($this->factory)) { - throw new \RuntimeException('setModulo needs to be called before this method'); - } - - if (!count($p)) { - return []; - } - - // use jacobian coordinates - if (isset($p[2])) { - if (isset($p['fresh'])) { - return $this->jacobianDoublePointMixed($p); - } - return $this->jacobianDoublePoint($p); - } - - list($numerator, $denominator) = $this->doublePointHelper($p); - - $slope = $numerator->divide($denominator); - - $x = $slope->multiply($slope)->subtract($p[0])->subtract($p[0]); - $y = $slope->multiply($p[0]->subtract($x))->subtract($p[1]); - - return [$x, $y]; - } - - /** - * Returns the X coordinate and the derived Y coordinate - * - * @return array - */ - public function derivePoint($m) - { - $y = ord(Strings::shift($m)); - $x = new BigInteger($m, 256); - $xp = $this->convertInteger($x); - switch ($y) { - case 2: - $ypn = false; - break; - case 3: - $ypn = true; - break; - default: - throw new \RuntimeException('Coordinate not in recognized format'); - } - $temp = $xp->multiply($this->a); - $temp = $xp->multiply($xp)->multiply($xp)->add($temp); - $temp = $temp->add($this->b); - $b = $temp->squareRoot(); - if (!$b) { - throw new \RuntimeException('Unable to derive Y coordinate'); - } - $bn = $b->isOdd(); - $yp = $ypn == $bn ? $b : $b->negate(); - return [$xp, $yp]; - } - - /** - * Tests whether or not the x / y values satisfy the equation - * - * @return boolean - */ - public function verifyPoint(array $p) - { - list($x, $y) = $p; - $lhs = $y->multiply($y); - $temp = $x->multiply($this->a); - $temp = $x->multiply($x)->multiply($x)->add($temp); - $rhs = $temp->add($this->b); - - return $lhs->equals($rhs); - } - - /** - * Returns the modulo - * - * @return \phpseclib3\Math\BigInteger - */ - public function getModulo() - { - return $this->modulo; - } - - /** - * Returns the a coefficient - * - * @return \phpseclib3\Math\PrimeField\Integer - */ - public function getA() - { - return $this->a; - } - - /** - * Returns the a coefficient - * - * @return \phpseclib3\Math\PrimeField\Integer - */ - public function getB() - { - return $this->b; - } - - /** - * Multiply and Add Points - * - * Adapted from: - * https://github.com/indutny/elliptic/blob/725bd91/lib/elliptic/curve/base.js#L125 - * - * @return int[] - */ - public function multiplyAddPoints(array $points, array $scalars) - { - $length = count($points); - - foreach ($points as &$point) { - $point = $this->convertToInternal($point); - } - - $wnd = [$this->getNAFPoints($points[0], 7)]; - $wndWidth = [isset($points[0]['nafwidth']) ? $points[0]['nafwidth'] : 7]; - for ($i = 1; $i < $length; $i++) { - $wnd[] = $this->getNAFPoints($points[$i], 1); - $wndWidth[] = isset($points[$i]['nafwidth']) ? $points[$i]['nafwidth'] : 1; - } - - $naf = []; - - // comb all window NAFs - - $max = 0; - for ($i = $length - 1; $i >= 1; $i -= 2) { - $a = $i - 1; - $b = $i; - if ($wndWidth[$a] != 1 || $wndWidth[$b] != 1) { - $naf[$a] = $scalars[$a]->getNAF($wndWidth[$a]); - $naf[$b] = $scalars[$b]->getNAF($wndWidth[$b]); - $max = max(count($naf[$a]), count($naf[$b]), $max); - continue; - } - - $comb = [ - $points[$a], // 1 - null, // 3 - null, // 5 - $points[$b] // 7 - ]; - - $comb[1] = $this->addPoint($points[$a], $points[$b]); - $comb[2] = $this->addPoint($points[$a], $this->negatePoint($points[$b])); - - $index = [ - -3, /* -1 -1 */ - -1, /* -1 0 */ - -5, /* -1 1 */ - -7, /* 0 -1 */ - 0, /* 0 -1 */ - 7, /* 0 1 */ - 5, /* 1 -1 */ - 1, /* 1 0 */ - 3 /* 1 1 */ - ]; - - $jsf = self::getJSFPoints($scalars[$a], $scalars[$b]); - - $max = max(count($jsf[0]), $max); - if ($max > 0) { - $naf[$a] = array_fill(0, $max, 0); - $naf[$b] = array_fill(0, $max, 0); - } else { - $naf[$a] = []; - $naf[$b] = []; - } - - for ($j = 0; $j < $max; $j++) { - $ja = isset($jsf[0][$j]) ? $jsf[0][$j] : 0; - $jb = isset($jsf[1][$j]) ? $jsf[1][$j] : 0; - - $naf[$a][$j] = $index[3 * ($ja + 1) + $jb + 1]; - $naf[$b][$j] = 0; - $wnd[$a] = $comb; - } - } - - $acc = []; - $temp = [0, 0, 0, 0]; - for ($i = $max; $i >= 0; $i--) { - $k = 0; - while ($i >= 0) { - $zero = true; - for ($j = 0; $j < $length; $j++) { - $temp[$j] = isset($naf[$j][$i]) ? $naf[$j][$i] : 0; - if ($temp[$j] != 0) { - $zero = false; - } - } - if (!$zero) { - break; - } - $k++; - $i--; - } - - if ($i >= 0) { - $k++; - } - while ($k--) { - $acc = $this->doublePoint($acc); - } - - if ($i < 0) { - break; - } - - for ($j = 0; $j < $length; $j++) { - $z = $temp[$j]; - $p = null; - if ($z == 0) { - continue; - } - $p = $z > 0 ? - $wnd[$j][($z - 1) >> 1] : - $this->negatePoint($wnd[$j][(-$z - 1) >> 1]); - $acc = $this->addPoint($acc, $p); - } - } - - return $this->convertToAffine($acc); - } - - /** - * Precomputes NAF points - * - * Adapted from: - * https://github.com/indutny/elliptic/blob/725bd91/lib/elliptic/curve/base.js#L351 - * - * @return int[] - */ - private function getNAFPoints(array $point, $wnd) - { - if (isset($point['naf'])) { - return $point['naf']; - } - - $res = [$point]; - $max = (1 << $wnd) - 1; - $dbl = $max == 1 ? null : $this->doublePoint($point); - for ($i = 1; $i < $max; $i++) { - $res[] = $this->addPoint($res[$i - 1], $dbl); - } - - $point['naf'] = $res; - - /* - $str = ''; - foreach ($res as $re) { - $re[0] = bin2hex($re[0]->toBytes()); - $re[1] = bin2hex($re[1]->toBytes()); - $str.= " ['$re[0]', '$re[1]'],\r\n"; - } - file_put_contents('temp.txt', $str); - exit; - */ - - return $res; - } - - /** - * Precomputes points in Joint Sparse Form - * - * Adapted from: - * https://github.com/indutny/elliptic/blob/725bd91/lib/elliptic/utils.js#L96 - * - * @return int[] - */ - private static function getJSFPoints(Integer $k1, Integer $k2) - { - static $three; - if (!isset($three)) { - $three = new BigInteger(3); - } - - $jsf = [[], []]; - $k1 = $k1->toBigInteger(); - $k2 = $k2->toBigInteger(); - $d1 = 0; - $d2 = 0; - - while ($k1->compare(new BigInteger(-$d1)) > 0 || $k2->compare(new BigInteger(-$d2)) > 0) { - // first phase - $m14 = $k1->testBit(0) + 2 * $k1->testBit(1); - $m14 += $d1; - $m14 &= 3; - - $m24 = $k2->testBit(0) + 2 * $k2->testBit(1); - $m24 += $d2; - $m24 &= 3; - - if ($m14 == 3) { - $m14 = -1; - } - if ($m24 == 3) { - $m24 = -1; - } - - $u1 = 0; - if ($m14 & 1) { // if $m14 is odd - $m8 = $k1->testBit(0) + 2 * $k1->testBit(1) + 4 * $k1->testBit(2); - $m8 += $d1; - $m8 &= 7; - $u1 = ($m8 == 3 || $m8 == 5) && $m24 == 2 ? -$m14 : $m14; - } - $jsf[0][] = $u1; - - $u2 = 0; - if ($m24 & 1) { // if $m24 is odd - $m8 = $k2->testBit(0) + 2 * $k2->testBit(1) + 4 * $k2->testBit(2); - $m8 += $d2; - $m8 &= 7; - $u2 = ($m8 == 3 || $m8 == 5) && $m14 == 2 ? -$m24 : $m24; - } - $jsf[1][] = $u2; - - // second phase - if (2 * $d1 == $u1 + 1) { - $d1 = 1 - $d1; - } - if (2 * $d2 == $u2 + 1) { - $d2 = 1 - $d2; - } - $k1 = $k1->bitwise_rightShift(1); - $k2 = $k2->bitwise_rightShift(1); - } - - return $jsf; - } - - /** - * Returns the affine point - * - * A Jacobian Coordinate is of the form (x, y, z). - * To convert a Jacobian Coordinate to an Affine Point - * you do (x / z^2, y / z^3) - * - * @return \phpseclib3\Math\PrimeField\Integer[] - */ - public function convertToAffine(array $p) - { - if (!isset($p[2])) { - return $p; - } - list($x, $y, $z) = $p; - $z = $this->one->divide($z); - $z2 = $z->multiply($z); - return [ - $x->multiply($z2), - $y->multiply($z2)->multiply($z) - ]; - } - - /** - * Converts an affine point to a jacobian coordinate - * - * @return \phpseclib3\Math\PrimeField\Integer[] - */ - public function convertToInternal(array $p) - { - if (isset($p[2])) { - return $p; - } - - $p[2] = clone $this->one; - $p['fresh'] = true; - return $p; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/TwistedEdwards.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/TwistedEdwards.php deleted file mode 100644 index 2521a4c0..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/TwistedEdwards.php +++ /dev/null @@ -1,215 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\BaseCurves; - -use phpseclib3\Math\BigInteger; -use phpseclib3\Math\PrimeField; -use phpseclib3\Math\PrimeField\Integer as PrimeInteger; - -/** - * Curves over a*x^2 + y^2 = 1 + d*x^2*y^2 - * - * @author Jim Wigginton - */ -class TwistedEdwards extends Base -{ - /** - * The modulo - * - * @var BigInteger - */ - protected $modulo; - - /** - * Cofficient for x^2 - * - * @var object - */ - protected $a; - - /** - * Cofficient for x^2*y^2 - * - * @var object - */ - protected $d; - - /** - * Base Point - * - * @var object[] - */ - protected $p; - - /** - * The number zero over the specified finite field - * - * @var object - */ - protected $zero; - - /** - * The number one over the specified finite field - * - * @var object - */ - protected $one; - - /** - * The number two over the specified finite field - * - * @var object - */ - protected $two; - - /** - * Sets the modulo - */ - public function setModulo(BigInteger $modulo) - { - $this->modulo = $modulo; - $this->factory = new PrimeField($modulo); - $this->zero = $this->factory->newInteger(new BigInteger(0)); - $this->one = $this->factory->newInteger(new BigInteger(1)); - $this->two = $this->factory->newInteger(new BigInteger(2)); - } - - /** - * Set coefficients a and b - */ - public function setCoefficients(BigInteger $a, BigInteger $d) - { - if (!isset($this->factory)) { - throw new \RuntimeException('setModulo needs to be called before this method'); - } - $this->a = $this->factory->newInteger($a); - $this->d = $this->factory->newInteger($d); - } - - /** - * Set x and y coordinates for the base point - */ - public function setBasePoint($x, $y) - { - switch (true) { - case !$x instanceof BigInteger && !$x instanceof PrimeInteger: - throw new \UnexpectedValueException('Argument 1 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\Integer'); - case !$y instanceof BigInteger && !$y instanceof PrimeInteger: - throw new \UnexpectedValueException('Argument 2 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\Integer'); - } - if (!isset($this->factory)) { - throw new \RuntimeException('setModulo needs to be called before this method'); - } - $this->p = [ - $x instanceof BigInteger ? $this->factory->newInteger($x) : $x, - $y instanceof BigInteger ? $this->factory->newInteger($y) : $y - ]; - } - - /** - * Returns the a coefficient - * - * @return \phpseclib3\Math\PrimeField\Integer - */ - public function getA() - { - return $this->a; - } - - /** - * Returns the a coefficient - * - * @return \phpseclib3\Math\PrimeField\Integer - */ - public function getD() - { - return $this->d; - } - - /** - * Retrieve the base point as an array - * - * @return array - */ - public function getBasePoint() - { - if (!isset($this->factory)) { - throw new \RuntimeException('setModulo needs to be called before this method'); - } - /* - if (!isset($this->p)) { - throw new \RuntimeException('setBasePoint needs to be called before this method'); - } - */ - return $this->p; - } - - /** - * Returns the affine point - * - * @return \phpseclib3\Math\PrimeField\Integer[] - */ - public function convertToAffine(array $p) - { - if (!isset($p[2])) { - return $p; - } - list($x, $y, $z) = $p; - $z = $this->one->divide($z); - return [ - $x->multiply($z), - $y->multiply($z) - ]; - } - - /** - * Returns the modulo - * - * @return \phpseclib3\Math\BigInteger - */ - public function getModulo() - { - return $this->modulo; - } - - /** - * Tests whether or not the x / y values satisfy the equation - * - * @return boolean - */ - public function verifyPoint(array $p) - { - list($x, $y) = $p; - $x2 = $x->multiply($x); - $y2 = $y->multiply($y); - - $lhs = $this->a->multiply($x2)->add($y2); - $rhs = $this->d->multiply($x2)->multiply($y2)->add($this->one); - - return $lhs->equals($rhs); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve25519.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve25519.php deleted file mode 100644 index 0f3f4d82..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve25519.php +++ /dev/null @@ -1,81 +0,0 @@ - - * @copyright 2019 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Montgomery; -use phpseclib3\Math\BigInteger; - -class Curve25519 extends Montgomery -{ - public function __construct() - { - // 2^255 - 19 - $this->setModulo(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED', 16)); - $this->a24 = $this->factory->newInteger(new BigInteger('121666')); - $this->p = [$this->factory->newInteger(new BigInteger(9))]; - // 2^252 + 0x14def9dea2f79cd65812631a5cf5d3ed - $this->setOrder(new BigInteger('1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED', 16)); - - /* - $this->setCoefficients( - new BigInteger('486662'), // a - ); - $this->setBasePoint( - new BigInteger(9), - new BigInteger('14781619447589544791020593568409986887264606134616475288964881837755586237401') - ); - */ - } - - /** - * Multiply a point on the curve by a scalar - * - * Modifies the scalar as described at https://tools.ietf.org/html/rfc7748#page-8 - * - * @return array - */ - public function multiplyPoint(array $p, BigInteger $d) - { - //$r = strrev(sodium_crypto_scalarmult($d->toBytes(), strrev($p[0]->toBytes()))); - //return [$this->factory->newInteger(new BigInteger($r, 256))]; - - $d = $d->toBytes(); - $d &= "\xF8" . str_repeat("\xFF", 30) . "\x7F"; - $d = strrev($d); - $d |= "\x40"; - $d = new BigInteger($d, -256); - - return parent::multiplyPoint($p, $d); - } - - /** - * Creates a random scalar multiplier - * - * @return BigInteger - */ - public function createRandomMultiplier() - { - return BigInteger::random(256); - } - - /** - * Performs range check - */ - public function rangeCheck(BigInteger $x) - { - if ($x->getLength() > 256 || $x->isNegative()) { - throw new \RangeException('x must be a positive integer less than 256 bytes in length'); - } - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve448.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve448.php deleted file mode 100644 index f4a44231..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve448.php +++ /dev/null @@ -1,92 +0,0 @@ - - * @copyright 2019 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Montgomery; -use phpseclib3\Math\BigInteger; - -class Curve448 extends Montgomery -{ - public function __construct() - { - // 2^448 - 2^224 - 1 - $this->setModulo(new BigInteger( - 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE' . - 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', - 16 - )); - $this->a24 = $this->factory->newInteger(new BigInteger('39081')); - $this->p = [$this->factory->newInteger(new BigInteger(5))]; - // 2^446 - 0x8335dc163bb124b65129c96fde933d8d723a70aadc873d6d54a7bb0d - $this->setOrder(new BigInteger( - '3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' . - '7CCA23E9C44EDB49AED63690216CC2728DC58F552378C292AB5844F3', - 16 - )); - - /* - $this->setCoefficients( - new BigInteger('156326'), // a - ); - $this->setBasePoint( - new BigInteger(5), - new BigInteger( - '355293926785568175264127502063783334808976399387714271831880898' . - '435169088786967410002932673765864550910142774147268105838985595290' . - '606362') - ); - */ - } - - /** - * Multiply a point on the curve by a scalar - * - * Modifies the scalar as described at https://tools.ietf.org/html/rfc7748#page-8 - * - * @return array - */ - public function multiplyPoint(array $p, BigInteger $d) - { - //$r = strrev(sodium_crypto_scalarmult($d->toBytes(), strrev($p[0]->toBytes()))); - //return [$this->factory->newInteger(new BigInteger($r, 256))]; - - $d = $d->toBytes(); - $d[0] = $d[0] & "\xFC"; - $d = strrev($d); - $d |= "\x80"; - $d = new BigInteger($d, 256); - - return parent::multiplyPoint($p, $d); - } - - /** - * Creates a random scalar multiplier - * - * @return BigInteger - */ - public function createRandomMultiplier() - { - return BigInteger::random(446); - } - - /** - * Performs range check - */ - public function rangeCheck(BigInteger $x) - { - if ($x->getLength() > 448 || $x->isNegative()) { - throw new \RangeException('x must be a positive integer less than 446 bytes in length'); - } - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Ed25519.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Ed25519.php deleted file mode 100644 index 9d3de684..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Ed25519.php +++ /dev/null @@ -1,333 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards; -use phpseclib3\Crypt\Hash; -use phpseclib3\Crypt\Random; -use phpseclib3\Math\BigInteger; - -class Ed25519 extends TwistedEdwards -{ - const HASH = 'sha512'; - /* - Per https://tools.ietf.org/html/rfc8032#page-6 EdDSA has several parameters, one of which is b: - - 2. An integer b with 2^(b-1) > p. EdDSA public keys have exactly b - bits, and EdDSA signatures have exactly 2*b bits. b is - recommended to be a multiple of 8, so public key and signature - lengths are an integral number of octets. - - SIZE corresponds to b - */ - const SIZE = 32; - - public function __construct() - { - // 2^255 - 19 - $this->setModulo(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED', 16)); - $this->setCoefficients( - // -1 - new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEC', 16), // a - // -121665/121666 - new BigInteger('52036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978A3', 16) // d - ); - $this->setBasePoint( - new BigInteger('216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A', 16), - new BigInteger('6666666666666666666666666666666666666666666666666666666666666658', 16) - ); - $this->setOrder(new BigInteger('1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED', 16)); - // algorithm 14.47 from http://cacr.uwaterloo.ca/hac/about/chap14.pdf#page=16 - /* - $this->setReduction(function($x) { - $parts = $x->bitwise_split(255); - $className = $this->className; - - if (count($parts) > 2) { - list(, $r) = $x->divide($className::$modulo); - return $r; - } - - $zero = new BigInteger(); - $c = new BigInteger(19); - - switch (count($parts)) { - case 2: - list($qi, $ri) = $parts; - break; - case 1: - $qi = $zero; - list($ri) = $parts; - break; - case 0: - return $zero; - } - $r = $ri; - - while ($qi->compare($zero) > 0) { - $temp = $qi->multiply($c)->bitwise_split(255); - if (count($temp) == 2) { - list($qi, $ri) = $temp; - } else { - $qi = $zero; - list($ri) = $temp; - } - $r = $r->add($ri); - } - - while ($r->compare($className::$modulo) > 0) { - $r = $r->subtract($className::$modulo); - } - return $r; - }); - */ - } - - /** - * Recover X from Y - * - * Implements steps 2-4 at https://tools.ietf.org/html/rfc8032#section-5.1.3 - * - * Used by EC\Keys\Common.php - * - * @param BigInteger $y - * @param boolean $sign - * @return object[] - */ - public function recoverX(BigInteger $y, $sign) - { - $y = $this->factory->newInteger($y); - - $y2 = $y->multiply($y); - $u = $y2->subtract($this->one); - $v = $this->d->multiply($y2)->add($this->one); - $x2 = $u->divide($v); - if ($x2->equals($this->zero)) { - if ($sign) { - throw new \RuntimeException('Unable to recover X coordinate (x2 = 0)'); - } - return clone $this->zero; - } - // find the square root - /* we don't do $x2->squareRoot() because, quoting from - https://tools.ietf.org/html/rfc8032#section-5.1.1: - - "For point decoding or "decompression", square roots modulo p are - needed. They can be computed using the Tonelli-Shanks algorithm or - the special case for p = 5 (mod 8). To find a square root of a, - first compute the candidate root x = a^((p+3)/8) (mod p)." - */ - $exp = $this->getModulo()->add(new BigInteger(3)); - $exp = $exp->bitwise_rightShift(3); - $x = $x2->pow($exp); - - // If v x^2 = -u (mod p), set x <-- x * 2^((p-1)/4), which is a square root. - if (!$x->multiply($x)->subtract($x2)->equals($this->zero)) { - $temp = $this->getModulo()->subtract(new BigInteger(1)); - $temp = $temp->bitwise_rightShift(2); - $temp = $this->two->pow($temp); - $x = $x->multiply($temp); - if (!$x->multiply($x)->subtract($x2)->equals($this->zero)) { - throw new \RuntimeException('Unable to recover X coordinate'); - } - } - if ($x->isOdd() != $sign) { - $x = $x->negate(); - } - - return [$x, $y]; - } - - /** - * Extract Secret Scalar - * - * Implements steps 1-3 at https://tools.ietf.org/html/rfc8032#section-5.1.5 - * - * Used by the various key handlers - * - * @param string $str - * @return array - */ - public function extractSecret($str) - { - if (strlen($str) != 32) { - throw new \LengthException('Private Key should be 32-bytes long'); - } - // 1. Hash the 32-byte private key using SHA-512, storing the digest in - // a 64-octet large buffer, denoted h. Only the lower 32 bytes are - // used for generating the public key. - $hash = new Hash('sha512'); - $h = $hash->hash($str); - $h = substr($h, 0, 32); - // 2. Prune the buffer: The lowest three bits of the first octet are - // cleared, the highest bit of the last octet is cleared, and the - // second highest bit of the last octet is set. - $h[0] = $h[0] & chr(0xF8); - $h = strrev($h); - $h[0] = ($h[0] & chr(0x3F)) | chr(0x40); - // 3. Interpret the buffer as the little-endian integer, forming a - // secret scalar s. - $dA = new BigInteger($h, 256); - - return [ - 'dA' => $dA, - 'secret' => $str - ]; - } - - /** - * Encode a point as a string - * - * @param array $point - * @return string - */ - public function encodePoint($point) - { - list($x, $y) = $point; - $y = $y->toBytes(); - $y[0] = $y[0] & chr(0x7F); - if ($x->isOdd()) { - $y[0] = $y[0] | chr(0x80); - } - $y = strrev($y); - - return $y; - } - - /** - * Creates a random scalar multiplier - * - * @return \phpseclib3\Math\PrimeField\Integer - */ - public function createRandomMultiplier() - { - return $this->extractSecret(Random::string(32))['dA']; - } - - /** - * Converts an affine point to an extended homogeneous coordinate - * - * From https://tools.ietf.org/html/rfc8032#section-5.1.4 : - * - * A point (x,y) is represented in extended homogeneous coordinates (X, Y, Z, T), - * with x = X/Z, y = Y/Z, x * y = T/Z. - * - * @return \phpseclib3\Math\PrimeField\Integer[] - */ - public function convertToInternal(array $p) - { - if (empty($p)) { - return [clone $this->zero, clone $this->one, clone $this->one, clone $this->zero]; - } - - if (isset($p[2])) { - return $p; - } - - $p[2] = clone $this->one; - $p[3] = $p[0]->multiply($p[1]); - - return $p; - } - - /** - * Doubles a point on a curve - * - * @return FiniteField[] - */ - public function doublePoint(array $p) - { - if (!isset($this->factory)) { - throw new \RuntimeException('setModulo needs to be called before this method'); - } - - if (!count($p)) { - return []; - } - - if (!isset($p[2])) { - throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa'); - } - - // from https://tools.ietf.org/html/rfc8032#page-12 - - list($x1, $y1, $z1, $t1) = $p; - - $a = $x1->multiply($x1); - $b = $y1->multiply($y1); - $c = $this->two->multiply($z1)->multiply($z1); - $h = $a->add($b); - $temp = $x1->add($y1); - $e = $h->subtract($temp->multiply($temp)); - $g = $a->subtract($b); - $f = $c->add($g); - - $x3 = $e->multiply($f); - $y3 = $g->multiply($h); - $t3 = $e->multiply($h); - $z3 = $f->multiply($g); - - return [$x3, $y3, $z3, $t3]; - } - - /** - * Adds two points on the curve - * - * @return FiniteField[] - */ - public function addPoint(array $p, array $q) - { - if (!isset($this->factory)) { - throw new \RuntimeException('setModulo needs to be called before this method'); - } - - if (!count($p) || !count($q)) { - if (count($q)) { - return $q; - } - if (count($p)) { - return $p; - } - return []; - } - - if (!isset($p[2]) || !isset($q[2])) { - throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa'); - } - - if ($p[0]->equals($q[0])) { - return !$p[1]->equals($q[1]) ? [] : $this->doublePoint($p); - } - - // from https://tools.ietf.org/html/rfc8032#page-12 - - list($x1, $y1, $z1, $t1) = $p; - list($x2, $y2, $z2, $t2) = $q; - - $a = $y1->subtract($x1)->multiply($y2->subtract($x2)); - $b = $y1->add($x1)->multiply($y2->add($x2)); - $c = $t1->multiply($this->two)->multiply($this->d)->multiply($t2); - $d = $z1->multiply($this->two)->multiply($z2); - $e = $b->subtract($a); - $f = $d->subtract($c); - $g = $d->add($c); - $h = $b->add($a); - - $x3 = $e->multiply($f); - $y3 = $g->multiply($h); - $t3 = $e->multiply($h); - $z3 = $f->multiply($g); - - return [$x3, $y3, $z3, $t3]; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Ed448.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Ed448.php deleted file mode 100644 index 5451f909..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Ed448.php +++ /dev/null @@ -1,273 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards; -use phpseclib3\Crypt\Hash; -use phpseclib3\Crypt\Random; -use phpseclib3\Math\BigInteger; - -class Ed448 extends TwistedEdwards -{ - const HASH = 'shake256-912'; - const SIZE = 57; - - public function __construct() - { - // 2^448 - 2^224 - 1 - $this->setModulo(new BigInteger( - 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE' . - 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', - 16 - )); - $this->setCoefficients( - new BigInteger(1), - // -39081 - new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE' . - 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6756', 16) - ); - $this->setBasePoint( - new BigInteger('4F1970C66BED0DED221D15A622BF36DA9E146570470F1767EA6DE324' . - 'A3D3A46412AE1AF72AB66511433B80E18B00938E2626A82BC70CC05E', 16), - new BigInteger('693F46716EB6BC248876203756C9C7624BEA73736CA3984087789C1E' . - '05A0C2D73AD3FF1CE67C39C4FDBD132C4ED7C8AD9808795BF230FA14', 16) - ); - $this->setOrder(new BigInteger( - '3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' . - '7CCA23E9C44EDB49AED63690216CC2728DC58F552378C292AB5844F3', - 16 - )); - } - - /** - * Recover X from Y - * - * Implements steps 2-4 at https://tools.ietf.org/html/rfc8032#section-5.2.3 - * - * Used by EC\Keys\Common.php - * - * @param BigInteger $y - * @param boolean $sign - * @return object[] - */ - public function recoverX(BigInteger $y, $sign) - { - $y = $this->factory->newInteger($y); - - $y2 = $y->multiply($y); - $u = $y2->subtract($this->one); - $v = $this->d->multiply($y2)->subtract($this->one); - $x2 = $u->divide($v); - if ($x2->equals($this->zero)) { - if ($sign) { - throw new \RuntimeException('Unable to recover X coordinate (x2 = 0)'); - } - return clone $this->zero; - } - // find the square root - $exp = $this->getModulo()->add(new BigInteger(1)); - $exp = $exp->bitwise_rightShift(2); - $x = $x2->pow($exp); - - if (!$x->multiply($x)->subtract($x2)->equals($this->zero)) { - throw new \RuntimeException('Unable to recover X coordinate'); - } - if ($x->isOdd() != $sign) { - $x = $x->negate(); - } - - return [$x, $y]; - } - - /** - * Extract Secret Scalar - * - * Implements steps 1-3 at https://tools.ietf.org/html/rfc8032#section-5.2.5 - * - * Used by the various key handlers - * - * @param string $str - * @return array - */ - public function extractSecret($str) - { - if (strlen($str) != 57) { - throw new \LengthException('Private Key should be 57-bytes long'); - } - // 1. Hash the 57-byte private key using SHAKE256(x, 114), storing the - // digest in a 114-octet large buffer, denoted h. Only the lower 57 - // bytes are used for generating the public key. - $hash = new Hash('shake256-912'); - $h = $hash->hash($str); - $h = substr($h, 0, 57); - // 2. Prune the buffer: The two least significant bits of the first - // octet are cleared, all eight bits the last octet are cleared, and - // the highest bit of the second to last octet is set. - $h[0] = $h[0] & chr(0xFC); - $h = strrev($h); - $h[0] = "\0"; - $h[1] = $h[1] | chr(0x80); - // 3. Interpret the buffer as the little-endian integer, forming a - // secret scalar s. - $dA = new BigInteger($h, 256); - - return [ - 'dA' => $dA, - 'secret' => $str - ]; - - $dA->secret = $str; - return $dA; - } - - /** - * Encode a point as a string - * - * @param array $point - * @return string - */ - public function encodePoint($point) - { - list($x, $y) = $point; - $y = "\0" . $y->toBytes(); - if ($x->isOdd()) { - $y[0] = $y[0] | chr(0x80); - } - $y = strrev($y); - - return $y; - } - - /** - * Creates a random scalar multiplier - * - * @return \phpseclib3\Math\PrimeField\Integer - */ - public function createRandomMultiplier() - { - return $this->extractSecret(Random::string(57))['dA']; - } - - /** - * Converts an affine point to an extended homogeneous coordinate - * - * From https://tools.ietf.org/html/rfc8032#section-5.2.4 : - * - * A point (x,y) is represented in extended homogeneous coordinates (X, Y, Z, T), - * with x = X/Z, y = Y/Z, x * y = T/Z. - * - * @return \phpseclib3\Math\PrimeField\Integer[] - */ - public function convertToInternal(array $p) - { - if (empty($p)) { - return [clone $this->zero, clone $this->one, clone $this->one]; - } - - if (isset($p[2])) { - return $p; - } - - $p[2] = clone $this->one; - - return $p; - } - - /** - * Doubles a point on a curve - * - * @return FiniteField[] - */ - public function doublePoint(array $p) - { - if (!isset($this->factory)) { - throw new \RuntimeException('setModulo needs to be called before this method'); - } - - if (!count($p)) { - return []; - } - - if (!isset($p[2])) { - throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa'); - } - - // from https://tools.ietf.org/html/rfc8032#page-18 - - list($x1, $y1, $z1) = $p; - - $b = $x1->add($y1); - $b = $b->multiply($b); - $c = $x1->multiply($x1); - $d = $y1->multiply($y1); - $e = $c->add($d); - $h = $z1->multiply($z1); - $j = $e->subtract($this->two->multiply($h)); - - $x3 = $b->subtract($e)->multiply($j); - $y3 = $c->subtract($d)->multiply($e); - $z3 = $e->multiply($j); - - return [$x3, $y3, $z3]; - } - - /** - * Adds two points on the curve - * - * @return FiniteField[] - */ - public function addPoint(array $p, array $q) - { - if (!isset($this->factory)) { - throw new \RuntimeException('setModulo needs to be called before this method'); - } - - if (!count($p) || !count($q)) { - if (count($q)) { - return $q; - } - if (count($p)) { - return $p; - } - return []; - } - - if (!isset($p[2]) || !isset($q[2])) { - throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa'); - } - - if ($p[0]->equals($q[0])) { - return !$p[1]->equals($q[1]) ? [] : $this->doublePoint($p); - } - - // from https://tools.ietf.org/html/rfc8032#page-17 - - list($x1, $y1, $z1) = $p; - list($x2, $y2, $z2) = $q; - - $a = $z1->multiply($z2); - $b = $a->multiply($a); - $c = $x1->multiply($x2); - $d = $y1->multiply($y2); - $e = $this->d->multiply($c)->multiply($d); - $f = $b->subtract($e); - $g = $b->add($e); - $h = $x1->add($y1)->multiply($x2->add($y2)); - - $x3 = $a->multiply($f)->multiply($h->subtract($c)->subtract($d)); - $y3 = $a->multiply($g)->multiply($d->subtract($c)); - $z3 = $f->multiply($g); - - return [$x3, $y3, $z3]; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP160r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP160r1.php deleted file mode 100644 index 7bc2272a..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP160r1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class brainpoolP160r1 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger('E95E4A5F737059DC60DFC7AD95B3D8139515620F', 16)); - $this->setCoefficients( - new BigInteger('340E7BE2A280EB74E2BE61BADA745D97E8F7C300', 16), - new BigInteger('1E589A8595423412134FAA2DBDEC95C8D8675E58', 16) - ); - $this->setBasePoint( - new BigInteger('BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3', 16), - new BigInteger('1667CB477A1A8EC338F94741669C976316DA6321', 16) - ); - $this->setOrder(new BigInteger('E95E4A5F737059DC60DF5991D45029409E60FC09', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP160t1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP160t1.php deleted file mode 100644 index ebfb29ae..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP160t1.php +++ /dev/null @@ -1,47 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class brainpoolP160t1 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger('E95E4A5F737059DC60DFC7AD95B3D8139515620F', 16)); - $this->setCoefficients( - new BigInteger('E95E4A5F737059DC60DFC7AD95B3D8139515620C', 16), // eg. -3 - new BigInteger('7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380', 16) - ); - $this->setBasePoint( - new BigInteger('B199B13B9B34EFC1397E64BAEB05ACC265FF2378', 16), - new BigInteger('ADD6718B7C7C1961F0991B842443772152C9E0AD', 16) - ); - $this->setOrder(new BigInteger('E95E4A5F737059DC60DF5991D45029409E60FC09', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP192r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP192r1.php deleted file mode 100644 index 6ec848bc..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP192r1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class brainpoolP192r1 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger('C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297', 16)); - $this->setCoefficients( - new BigInteger('6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF', 16), - new BigInteger('469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9', 16) - ); - $this->setBasePoint( - new BigInteger('C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6', 16), - new BigInteger('14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F', 16) - ); - $this->setOrder(new BigInteger('C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP192t1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP192t1.php deleted file mode 100644 index e6a86bbd..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP192t1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class brainpoolP192t1 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger('C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297', 16)); - $this->setCoefficients( - new BigInteger('C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86294', 16), // eg. -3 - new BigInteger('13D56FFAEC78681E68F9DEB43B35BEC2FB68542E27897B79', 16) - ); - $this->setBasePoint( - new BigInteger('3AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129', 16), - new BigInteger('097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9', 16) - ); - $this->setOrder(new BigInteger('C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP224r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP224r1.php deleted file mode 100644 index 3d7d8726..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP224r1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class brainpoolP224r1 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger('D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF', 16)); - $this->setCoefficients( - new BigInteger('68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43', 16), - new BigInteger('2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B', 16) - ); - $this->setBasePoint( - new BigInteger('0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D', 16), - new BigInteger('58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD', 16) - ); - $this->setOrder(new BigInteger('D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP224t1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP224t1.php deleted file mode 100644 index 3d4f9289..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP224t1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class brainpoolP224t1 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger('D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF', 16)); - $this->setCoefficients( - new BigInteger('D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FC', 16), // eg. -3 - new BigInteger('4B337D934104CD7BEF271BF60CED1ED20DA14C08B3BB64F18A60888D', 16) - ); - $this->setBasePoint( - new BigInteger('6AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D580', 16), - new BigInteger('0374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C', 16) - ); - $this->setOrder(new BigInteger('D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP256r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP256r1.php deleted file mode 100644 index 5780da76..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP256r1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class brainpoolP256r1 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger('A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377', 16)); - $this->setCoefficients( - new BigInteger('7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9', 16), - new BigInteger('26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6', 16) - ); - $this->setBasePoint( - new BigInteger('8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262', 16), - new BigInteger('547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997', 16) - ); - $this->setOrder(new BigInteger('A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP256t1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP256t1.php deleted file mode 100644 index 724d8b8f..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP256t1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class brainpoolP256t1 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger('A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377', 16)); - $this->setCoefficients( - new BigInteger('A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5374', 16), // eg. -3 - new BigInteger('662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04', 16) - ); - $this->setBasePoint( - new BigInteger('A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F4', 16), - new BigInteger('2D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE', 16) - ); - $this->setOrder(new BigInteger('A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP320r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP320r1.php deleted file mode 100644 index 182e6227..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP320r1.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class brainpoolP320r1 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger('D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F9' . - '2B9EC7893EC28FCD412B1F1B32E27', 16)); - $this->setCoefficients( - new BigInteger('3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F4' . - '92F375A97D860EB4', 16), - new BigInteger('520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD88453981' . - '6F5EB4AC8FB1F1A6', 16) - ); - $this->setBasePoint( - new BigInteger('43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C7' . - '10AF8D0D39E20611', 16), - new BigInteger('14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7' . - 'D35245D1692E8EE1', 16) - ); - $this->setOrder(new BigInteger('D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D4' . - '82EC7EE8658E98691555B44C59311', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP320t1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP320t1.php deleted file mode 100644 index d5a620d8..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP320t1.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class brainpoolP320t1 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger('D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F9' . - '2B9EC7893EC28FCD412B1F1B32E27', 16)); - $this->setCoefficients( - new BigInteger('D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28' . - 'FCD412B1F1B32E24', 16), // eg. -3 - new BigInteger('A7F561E038EB1ED560B3D147DB782013064C19F27ED27C6780AAF77FB8A547CE' . - 'B5B4FEF422340353', 16) - ); - $this->setBasePoint( - new BigInteger('925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF' . - '3357F624A21BED52', 16), - new BigInteger('63BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B' . - '1B9BC0455FB0D2C3', 16) - ); - $this->setOrder(new BigInteger('D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D4' . - '82EC7EE8658E98691555B44C59311', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP384r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP384r1.php deleted file mode 100644 index a20b4b44..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP384r1.php +++ /dev/null @@ -1,58 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class brainpoolP384r1 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger( - '8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A7' . - '1874700133107EC53', - 16 - )); - $this->setCoefficients( - new BigInteger( - '7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503' . - 'AD4EB04A8C7DD22CE2826', - 16 - ), - new BigInteger( - '4A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DB' . - 'C9943AB78696FA504C11', - 16 - ) - ); - $this->setBasePoint( - new BigInteger( - '1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D' . - '646AAEF87B2E247D4AF1E', - 16 - ), - new BigInteger( - '8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E464621779' . - '1811142820341263C5315', - 16 - ) - ); - $this->setOrder(new BigInteger( - '8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC31' . - '03B883202E9046565', - 16 - )); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP384t1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP384t1.php deleted file mode 100644 index 366660e6..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP384t1.php +++ /dev/null @@ -1,58 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class brainpoolP384t1 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger( - '8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A7' . - '1874700133107EC53', - 16 - )); - $this->setCoefficients( - new BigInteger( - '8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901' . - 'D1A71874700133107EC50', - 16 - ), // eg. -3 - new BigInteger( - '7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B8' . - '8805CED70355A33B471EE', - 16 - ) - ); - $this->setBasePoint( - new BigInteger( - '18DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946' . - 'A5F54D8D0AA2F418808CC', - 16 - ), - new BigInteger( - '25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC' . - '2B2912675BF5B9E582928', - 16 - ) - ); - $this->setOrder(new BigInteger( - '8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC31' . - '03B883202E9046565', - 16 - )); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP512r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP512r1.php deleted file mode 100644 index 5efe5e1a..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP512r1.php +++ /dev/null @@ -1,58 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class brainpoolP512r1 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger( - 'AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC' . - '66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3', - 16 - )); - $this->setCoefficients( - new BigInteger( - '7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA82' . - '53AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA', - 16 - ), - new BigInteger( - '3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C' . - '1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723', - 16 - ) - ); - $this->setBasePoint( - new BigInteger( - '81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D' . - '0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822', - 16 - ), - new BigInteger( - '7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5' . - 'F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892', - 16 - ) - ); - $this->setOrder(new BigInteger( - 'AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA' . - '92619418661197FAC10471DB1D381085DDADDB58796829CA90069', - 16 - )); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP512t1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP512t1.php deleted file mode 100644 index 745863a6..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP512t1.php +++ /dev/null @@ -1,58 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class brainpoolP512t1 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger( - 'AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC' . - '66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3', - 16 - )); - $this->setCoefficients( - new BigInteger( - 'AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC' . - '66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F0', - 16 - ), // eg. -3 - new BigInteger( - '7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA23049' . - '76540F6450085F2DAE145C22553B465763689180EA2571867423E', - 16 - ) - ); - $this->setBasePoint( - new BigInteger( - '640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CD' . - 'B3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA', - 16 - ), - new BigInteger( - '5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEE' . - 'F216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332', - 16 - ) - ); - $this->setOrder(new BigInteger( - 'AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA' . - '92619418661197FAC10471DB1D381085DDADDB58796829CA90069', - 16 - )); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistb233.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistb233.php deleted file mode 100644 index bae12b06..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistb233.php +++ /dev/null @@ -1,18 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -final class nistb233 extends sect233r1 -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistb409.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistb409.php deleted file mode 100644 index a46153d3..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistb409.php +++ /dev/null @@ -1,18 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -final class nistb409 extends sect409r1 -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk163.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk163.php deleted file mode 100644 index 8b263761..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk163.php +++ /dev/null @@ -1,18 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -final class nistk163 extends sect163k1 -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk233.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk233.php deleted file mode 100644 index 69e14138..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk233.php +++ /dev/null @@ -1,18 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -final class nistk233 extends sect233k1 -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk283.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk283.php deleted file mode 100644 index 9e95f10e..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk283.php +++ /dev/null @@ -1,18 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -final class nistk283 extends sect283k1 -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk409.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk409.php deleted file mode 100644 index 06bd9af7..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk409.php +++ /dev/null @@ -1,18 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -final class nistk409 extends sect409k1 -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp192.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp192.php deleted file mode 100644 index ddead3cf..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp192.php +++ /dev/null @@ -1,18 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -final class nistp192 extends secp192r1 -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp224.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp224.php deleted file mode 100644 index 746571b4..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp224.php +++ /dev/null @@ -1,18 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -final class nistp224 extends secp224r1 -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp256.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp256.php deleted file mode 100644 index a26c0f99..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp256.php +++ /dev/null @@ -1,18 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -final class nistp256 extends secp256r1 -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp384.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp384.php deleted file mode 100644 index 1f20c02d..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp384.php +++ /dev/null @@ -1,18 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -final class nistp384 extends secp384r1 -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp521.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp521.php deleted file mode 100644 index 86fa0508..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp521.php +++ /dev/null @@ -1,18 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -final class nistp521 extends secp521r1 -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistt571.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistt571.php deleted file mode 100644 index 7908b38b..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistt571.php +++ /dev/null @@ -1,18 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -final class nistt571 extends sect571k1 -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime192v1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime192v1.php deleted file mode 100644 index e9c13cd8..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime192v1.php +++ /dev/null @@ -1,18 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -final class prime192v1 extends secp192r1 -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime192v2.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime192v2.php deleted file mode 100644 index e3e341f2..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime192v2.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class prime192v2 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF', 16)); - $this->setCoefficients( - new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC', 16), - new BigInteger('CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953', 16) - ); - $this->setBasePoint( - new BigInteger('EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A', 16), - new BigInteger('6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15', 16) - ); - $this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime192v3.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime192v3.php deleted file mode 100644 index 1e97992d..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime192v3.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class prime192v3 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF', 16)); - $this->setCoefficients( - new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC', 16), - new BigInteger('22123DC2395A05CAA7423DAECCC94760A7D462256BD56916', 16) - ); - $this->setBasePoint( - new BigInteger('7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896', 16), - new BigInteger('38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0', 16) - ); - $this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime239v1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime239v1.php deleted file mode 100644 index 084be9d7..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime239v1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class prime239v1 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF', 16)); - $this->setCoefficients( - new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC', 16), - new BigInteger('6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A', 16) - ); - $this->setBasePoint( - new BigInteger('0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF', 16), - new BigInteger('7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE', 16) - ); - $this->setOrder(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime239v2.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime239v2.php deleted file mode 100644 index 21941b83..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime239v2.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class prime239v2 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF', 16)); - $this->setCoefficients( - new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC', 16), - new BigInteger('617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C', 16) - ); - $this->setBasePoint( - new BigInteger('38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7', 16), - new BigInteger('5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA', 16) - ); - $this->setOrder(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime239v3.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime239v3.php deleted file mode 100644 index 78c50f06..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime239v3.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class prime239v3 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF', 16)); - $this->setCoefficients( - new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC', 16), - new BigInteger('255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E', 16) - ); - $this->setBasePoint( - new BigInteger('6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A', 16), - new BigInteger('1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3', 16) - ); - $this->setOrder(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime256v1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime256v1.php deleted file mode 100644 index c72b22e8..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime256v1.php +++ /dev/null @@ -1,18 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -final class prime256v1 extends secp256r1 -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp112r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp112r1.php deleted file mode 100644 index d1d3194b..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp112r1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class secp112r1 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger('DB7C2ABF62E35E668076BEAD208B', 16)); - $this->setCoefficients( - new BigInteger('DB7C2ABF62E35E668076BEAD2088', 16), - new BigInteger('659EF8BA043916EEDE8911702B22', 16) - ); - $this->setBasePoint( - new BigInteger('09487239995A5EE76B55F9C2F098', 16), - new BigInteger('A89CE5AF8724C0A23E0E0FF77500', 16) - ); - $this->setOrder(new BigInteger('DB7C2ABF62E35E7628DFAC6561C5', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp112r2.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp112r2.php deleted file mode 100644 index da44e7fd..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp112r2.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class secp112r2 extends Prime -{ - public function __construct() - { - // same modulo as secp112r1 - $this->setModulo(new BigInteger('DB7C2ABF62E35E668076BEAD208B', 16)); - $this->setCoefficients( - new BigInteger('6127C24C05F38A0AAAF65C0EF02C', 16), - new BigInteger('51DEF1815DB5ED74FCC34C85D709', 16) - ); - $this->setBasePoint( - new BigInteger('4BA30AB5E892B4E1649DD0928643', 16), - new BigInteger('ADCD46F5882E3747DEF36E956E97', 16) - ); - $this->setOrder(new BigInteger('36DF0AAFD8B8D7597CA10520D04B', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp128r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp128r1.php deleted file mode 100644 index 34456bc0..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp128r1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class secp128r1 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger('FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF', 16)); - $this->setCoefficients( - new BigInteger('FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC', 16), - new BigInteger('E87579C11079F43DD824993C2CEE5ED3', 16) - ); - $this->setBasePoint( - new BigInteger('161FF7528B899B2D0C28607CA52C5B86', 16), - new BigInteger('CF5AC8395BAFEB13C02DA292DDED7A83', 16) - ); - $this->setOrder(new BigInteger('FFFFFFFE0000000075A30D1B9038A115', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp128r2.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp128r2.php deleted file mode 100644 index e102c340..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp128r2.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class secp128r2 extends Prime -{ - public function __construct() - { - // same as secp128r1 - $this->setModulo(new BigInteger('FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF', 16)); - $this->setCoefficients( - new BigInteger('D6031998D1B3BBFEBF59CC9BBFF9AEE1', 16), - new BigInteger('5EEEFCA380D02919DC2C6558BB6D8A5D', 16) - ); - $this->setBasePoint( - new BigInteger('7B6AA5D85E572983E6FB32A7CDEBC140', 16), - new BigInteger('27B6916A894D3AEE7106FE805FC34B44', 16) - ); - $this->setOrder(new BigInteger('3FFFFFFF7FFFFFFFBE0024720613B5A3', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp160k1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp160k1.php deleted file mode 100644 index c6a33344..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp160k1.php +++ /dev/null @@ -1,46 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\KoblitzPrime; -use phpseclib3\Math\BigInteger; - -class secp160k1 extends KoblitzPrime -{ - public function __construct() - { - // same as secp160r2 - $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73', 16)); - $this->setCoefficients( - new BigInteger('0000000000000000000000000000000000000000', 16), - new BigInteger('0000000000000000000000000000000000000007', 16) - ); - $this->setBasePoint( - new BigInteger('3B4C382CE37AA192A4019E763036F4F5DD4D7EBB', 16), - new BigInteger('938CF935318FDCED6BC28286531733C3F03C4FEE', 16) - ); - $this->setOrder(new BigInteger('0100000000000000000001B8FA16DFAB9ACA16B6B3', 16)); - - $this->basis = []; - $this->basis[] = [ - 'a' => new BigInteger('0096341F1138933BC2F505', -16), - 'b' => new BigInteger('FF6E9D0418C67BB8D5F562', -16) - ]; - $this->basis[] = [ - 'a' => new BigInteger('01BDCB3A09AAAABEAFF4A8', -16), - 'b' => new BigInteger('04D12329FF0EF498EA67', -16) - ]; - $this->beta = $this->factory->newInteger(new BigInteger('645B7345A143464942CC46D7CF4D5D1E1E6CBB68', -16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp160r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp160r1.php deleted file mode 100644 index af468774..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp160r1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class secp160r1 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF', 16)); - $this->setCoefficients( - new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC', 16), - new BigInteger('1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45', 16) - ); - $this->setBasePoint( - new BigInteger('4A96B5688EF573284664698968C38BB913CBFC82', 16), - new BigInteger('23A628553168947D59DCC912042351377AC5FB32', 16) - ); - $this->setOrder(new BigInteger('0100000000000000000001F4C8F927AED3CA752257', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp160r2.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp160r2.php deleted file mode 100644 index 9bd23d23..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp160r2.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class secp160r2 extends Prime -{ - public function __construct() - { - // same as secp160k1 - $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73', 16)); - $this->setCoefficients( - new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70', 16), - new BigInteger('B4E134D3FB59EB8BAB57274904664D5AF50388BA', 16) - ); - $this->setBasePoint( - new BigInteger('52DCB034293A117E1F4FF11B30F7199D3144CE6D', 16), - new BigInteger('FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E', 16) - ); - $this->setOrder(new BigInteger('0100000000000000000000351EE786A818F3A1A16B', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp192k1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp192k1.php deleted file mode 100644 index 79ff2e09..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp192k1.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\KoblitzPrime; -use phpseclib3\Math\BigInteger; - -class secp192k1 extends KoblitzPrime -{ - public function __construct() - { - $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37', 16)); - $this->setCoefficients( - new BigInteger('000000000000000000000000000000000000000000000000', 16), - new BigInteger('000000000000000000000000000000000000000000000003', 16) - ); - $this->setBasePoint( - new BigInteger('DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D', 16), - new BigInteger('9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D', 16) - ); - $this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D', 16)); - - $this->basis = []; - $this->basis[] = [ - 'a' => new BigInteger('00B3FB3400DEC5C4ADCEB8655C', -16), - 'b' => new BigInteger('8EE96418CCF4CFC7124FDA0F', -16) - ]; - $this->basis[] = [ - 'a' => new BigInteger('01D90D03E8F096B9948B20F0A9', -16), - 'b' => new BigInteger('42E49819ABBA9474E1083F6B', -16) - ]; - $this->beta = $this->factory->newInteger(new BigInteger('447A96E6C647963E2F7809FEAAB46947F34B0AA3CA0BBA74', -16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp192r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp192r1.php deleted file mode 100644 index 83ab1c70..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp192r1.php +++ /dev/null @@ -1,78 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class secp192r1 extends Prime -{ - public function __construct() - { - $modulo = new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF', 16); - $this->setModulo($modulo); - - // algorithm 2.27 from http://diamond.boisestate.edu/~liljanab/MATH308/GuideToECC.pdf#page=66 - /* in theory this should be faster than regular modular reductions save for one small issue. - to convert to / from base-2**8 with BCMath you have to call bcmul() and bcdiv() a lot. - to convert to / from base-2**8 with PHP64 you have to call base256_rshift() a lot. - in short, converting to / from base-2**8 is pretty expensive and that expense is - enough to offset whatever else might be gained by a simplified reduction algorithm. - now, if PHP supported unsigned integers things might be different. no bit-shifting - would be required for the PHP engine and it'd be a lot faster. but as is, BigInteger - uses base-2**31 or base-2**26 depending on whether or not the system is has a 32-bit - or a 64-bit OS. - */ - /* - $m_length = $this->getLengthInBytes(); - $this->setReduction(function($c) use ($m_length) { - $cBytes = $c->toBytes(); - $className = $this->className; - - if (strlen($cBytes) > 2 * $m_length) { - list(, $r) = $c->divide($className::$modulo); - return $r; - } - - $c = str_pad($cBytes, 48, "\0", STR_PAD_LEFT); - $c = array_reverse(str_split($c, 8)); - - $null = "\0\0\0\0\0\0\0\0"; - $s1 = new BigInteger($c[2] . $c[1] . $c[0], 256); - $s2 = new BigInteger($null . $c[3] . $c[3], 256); - $s3 = new BigInteger($c[4] . $c[4] . $null, 256); - $s4 = new BigInteger($c[5] . $c[5] . $c[5], 256); - - $r = $s1->add($s2)->add($s3)->add($s4); - while ($r->compare($className::$modulo) >= 0) { - $r = $r->subtract($className::$modulo); - } - - return $r; - }); - */ - - $this->setCoefficients( - new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC', 16), - new BigInteger('64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1', 16) - ); - $this->setBasePoint( - new BigInteger('188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012', 16), - new BigInteger('07192B95FFC8DA78631011ED6B24CDD573F977A11E794811', 16) - ); - $this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp224k1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp224k1.php deleted file mode 100644 index 79a5c541..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp224k1.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\KoblitzPrime; -use phpseclib3\Math\BigInteger; - -class secp224k1 extends KoblitzPrime -{ - public function __construct() - { - $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D', 16)); - $this->setCoefficients( - new BigInteger('00000000000000000000000000000000000000000000000000000000', 16), - new BigInteger('00000000000000000000000000000000000000000000000000000005', 16) - ); - $this->setBasePoint( - new BigInteger('A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C', 16), - new BigInteger('7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5', 16) - ); - $this->setOrder(new BigInteger('010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7', 16)); - - $this->basis = []; - $this->basis[] = [ - 'a' => new BigInteger('00B8ADF1378A6EB73409FA6C9C637D', -16), - 'b' => new BigInteger('94730F82B358A3776A826298FA6F', -16) - ]; - $this->basis[] = [ - 'a' => new BigInteger('01DCE8D2EC6184CAF0A972769FCC8B', -16), - 'b' => new BigInteger('4D2100BA3DC75AAB747CCF355DEC', -16) - ]; - $this->beta = $this->factory->newInteger(new BigInteger('01F178FFA4B17C89E6F73AECE2AAD57AF4C0A748B63C830947B27E04', -16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp224r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp224r1.php deleted file mode 100644 index a9e474a3..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp224r1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class secp224r1 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001', 16)); - $this->setCoefficients( - new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE', 16), - new BigInteger('B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4', 16) - ); - $this->setBasePoint( - new BigInteger('B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21', 16), - new BigInteger('BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34', 16) - ); - $this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp256k1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp256k1.php deleted file mode 100644 index 462e7a1c..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp256k1.php +++ /dev/null @@ -1,49 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -//use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Crypt\EC\BaseCurves\KoblitzPrime; -use phpseclib3\Math\BigInteger; - -//class secp256k1 extends Prime -class secp256k1 extends KoblitzPrime -{ - public function __construct() - { - $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F', 16)); - $this->setCoefficients( - new BigInteger('0000000000000000000000000000000000000000000000000000000000000000', 16), - new BigInteger('0000000000000000000000000000000000000000000000000000000000000007', 16) - ); - $this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141', 16)); - $this->setBasePoint( - new BigInteger('79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798', 16), - new BigInteger('483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8', 16) - ); - - $this->basis = []; - $this->basis[] = [ - 'a' => new BigInteger('3086D221A7D46BCDE86C90E49284EB15', -16), - 'b' => new BigInteger('FF1BBC8129FEF177D790AB8056F5401B3D', -16) - ]; - $this->basis[] = [ - 'a' => new BigInteger('114CA50F7A8E2F3F657C1108D9D44CFD8', -16), - 'b' => new BigInteger('3086D221A7D46BCDE86C90E49284EB15', -16) - ]; - $this->beta = $this->factory->newInteger(new BigInteger('7AE96A2B657C07106E64479EAC3434E99CF0497512F58995C1396C28719501EE', -16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp256r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp256r1.php deleted file mode 100644 index 9003373c..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp256r1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class secp256r1 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger('FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF', 16)); - $this->setCoefficients( - new BigInteger('FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC', 16), - new BigInteger('5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B', 16) - ); - $this->setBasePoint( - new BigInteger('6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296', 16), - new BigInteger('4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5', 16) - ); - $this->setOrder(new BigInteger('FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp384r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp384r1.php deleted file mode 100644 index 98764a34..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp384r1.php +++ /dev/null @@ -1,52 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class secp384r1 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger( - 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF', - 16 - )); - $this->setCoefficients( - new BigInteger( - 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC', - 16 - ), - new BigInteger( - 'B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF', - 16 - ) - ); - $this->setBasePoint( - new BigInteger( - 'AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7', - 16 - ), - new BigInteger( - '3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F', - 16 - ) - ); - $this->setOrder(new BigInteger( - 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973', - 16 - )); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp521r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp521r1.php deleted file mode 100644 index b89a4ea7..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp521r1.php +++ /dev/null @@ -1,46 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Prime; -use phpseclib3\Math\BigInteger; - -class secp521r1 extends Prime -{ - public function __construct() - { - $this->setModulo(new BigInteger('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' . - 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' . - 'FFFF', 16)); - $this->setCoefficients( - new BigInteger('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' . - 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' . - 'FFFC', 16), - new BigInteger('0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF1' . - '09E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B50' . - '3F00', 16) - ); - $this->setBasePoint( - new BigInteger('00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D' . - '3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5' . - 'BD66', 16), - new BigInteger('011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E' . - '662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD1' . - '6650', 16) - ); - $this->setOrder(new BigInteger('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' . - 'FFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E9138' . - '6409', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect113r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect113r1.php deleted file mode 100644 index 77ec7603..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect113r1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Binary; -use phpseclib3\Math\BigInteger; - -class sect113r1 extends Binary -{ - public function __construct() - { - $this->setModulo(113, 9, 0); - $this->setCoefficients( - '003088250CA6E7C7FE649CE85820F7', - '00E8BEE4D3E2260744188BE0E9C723' - ); - $this->setBasePoint( - '009D73616F35F4AB1407D73562C10F', - '00A52830277958EE84D1315ED31886' - ); - $this->setOrder(new BigInteger('0100000000000000D9CCEC8A39E56F', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect113r2.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect113r2.php deleted file mode 100644 index 2185d60e..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect113r2.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Binary; -use phpseclib3\Math\BigInteger; - -class sect113r2 extends Binary -{ - public function __construct() - { - $this->setModulo(113, 9, 0); - $this->setCoefficients( - '00689918DBEC7E5A0DD6DFC0AA55C7', - '0095E9A9EC9B297BD4BF36E059184F' - ); - $this->setBasePoint( - '01A57A6A7B26CA5EF52FCDB8164797', - '00B3ADC94ED1FE674C06E695BABA1D' - ); - $this->setOrder(new BigInteger('010000000000000108789B2496AF93', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect131r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect131r1.php deleted file mode 100644 index 1365cb60..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect131r1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Binary; -use phpseclib3\Math\BigInteger; - -class sect131r1 extends Binary -{ - public function __construct() - { - $this->setModulo(131, 8, 3, 2, 0); - $this->setCoefficients( - '07A11B09A76B562144418FF3FF8C2570B8', - '0217C05610884B63B9C6C7291678F9D341' - ); - $this->setBasePoint( - '0081BAF91FDF9833C40F9C181343638399', - '078C6E7EA38C001F73C8134B1B4EF9E150' - ); - $this->setOrder(new BigInteger('0400000000000000023123953A9464B54D', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect131r2.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect131r2.php deleted file mode 100644 index 93c11b2a..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect131r2.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Binary; -use phpseclib3\Math\BigInteger; - -class sect131r2 extends Binary -{ - public function __construct() - { - $this->setModulo(131, 8, 3, 2, 0); - $this->setCoefficients( - '03E5A88919D7CAFCBF415F07C2176573B2', - '04B8266A46C55657AC734CE38F018F2192' - ); - $this->setBasePoint( - '0356DCD8F2F95031AD652D23951BB366A8', - '0648F06D867940A5366D9E265DE9EB240F' - ); - $this->setOrder(new BigInteger('0400000000000000016954A233049BA98F', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect163k1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect163k1.php deleted file mode 100644 index 3c8574bb..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect163k1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Binary; -use phpseclib3\Math\BigInteger; - -class sect163k1 extends Binary -{ - public function __construct() - { - $this->setModulo(163, 7, 6, 3, 0); - $this->setCoefficients( - '000000000000000000000000000000000000000001', - '000000000000000000000000000000000000000001' - ); - $this->setBasePoint( - '02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8', - '0289070FB05D38FF58321F2E800536D538CCDAA3D9' - ); - $this->setOrder(new BigInteger('04000000000000000000020108A2E0CC0D99F8A5EF', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect163r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect163r1.php deleted file mode 100644 index 26afd87e..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect163r1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Binary; -use phpseclib3\Math\BigInteger; - -class sect163r1 extends Binary -{ - public function __construct() - { - $this->setModulo(163, 7, 6, 3, 0); - $this->setCoefficients( - '07B6882CAAEFA84F9554FF8428BD88E246D2782AE2', - '0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9' - ); - $this->setBasePoint( - '0369979697AB43897789566789567F787A7876A654', - '00435EDB42EFAFB2989D51FEFCE3C80988F41FF883' - ); - $this->setOrder(new BigInteger('03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect163r2.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect163r2.php deleted file mode 100644 index 38f94661..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect163r2.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Binary; -use phpseclib3\Math\BigInteger; - -class sect163r2 extends Binary -{ - public function __construct() - { - $this->setModulo(163, 7, 6, 3, 0); - $this->setCoefficients( - '000000000000000000000000000000000000000001', - '020A601907B8C953CA1481EB10512F78744A3205FD' - ); - $this->setBasePoint( - '03F0EBA16286A2D57EA0991168D4994637E8343E36', - '00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1' - ); - $this->setOrder(new BigInteger('040000000000000000000292FE77E70C12A4234C33', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect193r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect193r1.php deleted file mode 100644 index 951f261e..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect193r1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Binary; -use phpseclib3\Math\BigInteger; - -class sect193r1 extends Binary -{ - public function __construct() - { - $this->setModulo(193, 15, 0); - $this->setCoefficients( - '0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01', - '00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814' - ); - $this->setBasePoint( - '01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1', - '0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05' - ); - $this->setOrder(new BigInteger('01000000000000000000000000C7F34A778F443ACC920EBA49', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect193r2.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect193r2.php deleted file mode 100644 index e3ff47ac..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect193r2.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Binary; -use phpseclib3\Math\BigInteger; - -class sect193r2 extends Binary -{ - public function __construct() - { - $this->setModulo(193, 15, 0); - $this->setCoefficients( - '0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B', - '00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE' - ); - $this->setBasePoint( - '00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F', - '01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C' - ); - $this->setOrder(new BigInteger('010000000000000000000000015AAB561B005413CCD4EE99D5', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect233k1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect233k1.php deleted file mode 100644 index eea3f7ad..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect233k1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Binary; -use phpseclib3\Math\BigInteger; - -class sect233k1 extends Binary -{ - public function __construct() - { - $this->setModulo(233, 74, 0); - $this->setCoefficients( - '000000000000000000000000000000000000000000000000000000000000', - '000000000000000000000000000000000000000000000000000000000001' - ); - $this->setBasePoint( - '017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126', - '01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3' - ); - $this->setOrder(new BigInteger('8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect233r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect233r1.php deleted file mode 100644 index 68219f0e..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect233r1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Binary; -use phpseclib3\Math\BigInteger; - -class sect233r1 extends Binary -{ - public function __construct() - { - $this->setModulo(233, 74, 0); - $this->setCoefficients( - '000000000000000000000000000000000000000000000000000000000001', - '0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD' - ); - $this->setBasePoint( - '00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B', - '01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052' - ); - $this->setOrder(new BigInteger('01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect239k1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect239k1.php deleted file mode 100644 index 0e6994ba..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect239k1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Binary; -use phpseclib3\Math\BigInteger; - -class sect239k1 extends Binary -{ - public function __construct() - { - $this->setModulo(239, 158, 0); - $this->setCoefficients( - '000000000000000000000000000000000000000000000000000000000000', - '000000000000000000000000000000000000000000000000000000000001' - ); - $this->setBasePoint( - '29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC', - '76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA' - ); - $this->setOrder(new BigInteger('2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect283k1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect283k1.php deleted file mode 100644 index 279c24aa..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect283k1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Binary; -use phpseclib3\Math\BigInteger; - -class sect283k1 extends Binary -{ - public function __construct() - { - $this->setModulo(283, 12, 7, 5, 0); - $this->setCoefficients( - '000000000000000000000000000000000000000000000000000000000000000000000000', - '000000000000000000000000000000000000000000000000000000000000000000000001' - ); - $this->setBasePoint( - '0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836', - '01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259' - ); - $this->setOrder(new BigInteger('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect283r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect283r1.php deleted file mode 100644 index e44a6076..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect283r1.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Binary; -use phpseclib3\Math\BigInteger; - -class sect283r1 extends Binary -{ - public function __construct() - { - $this->setModulo(283, 12, 7, 5, 0); - $this->setCoefficients( - '000000000000000000000000000000000000000000000000000000000000000000000001', - '027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5' - ); - $this->setBasePoint( - '05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053', - '03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4' - ); - $this->setOrder(new BigInteger('03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307', 16)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect409k1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect409k1.php deleted file mode 100644 index 1fe329d8..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect409k1.php +++ /dev/null @@ -1,38 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Binary; -use phpseclib3\Math\BigInteger; - -class sect409k1 extends Binary -{ - public function __construct() - { - $this->setModulo(409, 87, 0); - $this->setCoefficients( - '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001' - ); - $this->setBasePoint( - '0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746', - '01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B' - ); - $this->setOrder(new BigInteger( - '7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F' . - '83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF', - 16 - )); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect409r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect409r1.php deleted file mode 100644 index 3e209ef8..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect409r1.php +++ /dev/null @@ -1,38 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Binary; -use phpseclib3\Math\BigInteger; - -class sect409r1 extends Binary -{ - public function __construct() - { - $this->setModulo(409, 87, 0); - $this->setCoefficients( - '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', - '0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F' - ); - $this->setBasePoint( - '015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7', - '0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706' - ); - $this->setOrder(new BigInteger( - '010000000000000000000000000000000000000000000000000001E2' . - 'AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173', - 16 - )); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect571k1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect571k1.php deleted file mode 100644 index 3c54eabd..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect571k1.php +++ /dev/null @@ -1,42 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Binary; -use phpseclib3\Math\BigInteger; - -class sect571k1 extends Binary -{ - public function __construct() - { - $this->setModulo(571, 10, 5, 2, 0); - $this->setCoefficients( - '000000000000000000000000000000000000000000000000000000000000000000000000' . - '000000000000000000000000000000000000000000000000000000000000000000000000', - '000000000000000000000000000000000000000000000000000000000000000000000000' . - '000000000000000000000000000000000000000000000000000000000000000000000001' - ); - $this->setBasePoint( - '026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA443709584' . - '93B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972', - '0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0' . - 'AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3' - ); - $this->setOrder(new BigInteger( - '020000000000000000000000000000000000000000000000000000000000000000000000' . - '131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001', - 16 - )); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect571r1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect571r1.php deleted file mode 100644 index 172c1af9..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect571r1.php +++ /dev/null @@ -1,42 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Crypt\EC\Curves; - -use phpseclib3\Crypt\EC\BaseCurves\Binary; -use phpseclib3\Math\BigInteger; - -class sect571r1 extends Binary -{ - public function __construct() - { - $this->setModulo(571, 10, 5, 2, 0); - $this->setCoefficients( - '000000000000000000000000000000000000000000000000000000000000000000000000' . - '000000000000000000000000000000000000000000000000000000000000000000000001', - '02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD' . - '8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A' - ); - $this->setBasePoint( - '0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950' . - 'F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19', - '037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43' . - 'BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B' - ); - $this->setOrder(new BigInteger( - '03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' . - 'E661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47', - 16 - )); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/Common.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/Common.php deleted file mode 100644 index 63402b4a..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/Common.php +++ /dev/null @@ -1,549 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\EC\Formats\Keys; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve; -use phpseclib3\Crypt\EC\BaseCurves\Binary as BinaryCurve; -use phpseclib3\Crypt\EC\BaseCurves\Prime as PrimeCurve; -use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve; -use phpseclib3\Exception\UnsupportedCurveException; -use phpseclib3\File\ASN1; -use phpseclib3\File\ASN1\Maps; -use phpseclib3\Math\BigInteger; - -/** - * Generic EC Key Parsing Helper functions - * - * @author Jim Wigginton - */ -trait Common -{ - /** - * Curve OIDs - * - * @var array - */ - private static $curveOIDs = []; - - /** - * Child OIDs loaded - * - * @var bool - */ - protected static $childOIDsLoaded = false; - - /** - * Use Named Curves - * - * @var bool - */ - private static $useNamedCurves = true; - - /** - * Initialize static variables - */ - private static function initialize_static_variables() - { - if (empty(self::$curveOIDs)) { - // the sec* curves are from the standards for efficient cryptography group - // sect* curves are curves over binary finite fields - // secp* curves are curves over prime finite fields - // sec*r* curves are regular curves; sec*k* curves are koblitz curves - // brainpool*r* curves are regular prime finite field curves - // brainpool*t* curves are twisted versions of the brainpool*r* curves - self::$curveOIDs = [ - 'prime192v1' => '1.2.840.10045.3.1.1', // J.5.1, example 1 (aka secp192r1) - 'prime192v2' => '1.2.840.10045.3.1.2', // J.5.1, example 2 - 'prime192v3' => '1.2.840.10045.3.1.3', // J.5.1, example 3 - 'prime239v1' => '1.2.840.10045.3.1.4', // J.5.2, example 1 - 'prime239v2' => '1.2.840.10045.3.1.5', // J.5.2, example 2 - 'prime239v3' => '1.2.840.10045.3.1.6', // J.5.2, example 3 - 'prime256v1' => '1.2.840.10045.3.1.7', // J.5.3, example 1 (aka secp256r1) - - // https://tools.ietf.org/html/rfc5656#section-10 - 'nistp256' => '1.2.840.10045.3.1.7', // aka secp256r1 - 'nistp384' => '1.3.132.0.34', // aka secp384r1 - 'nistp521' => '1.3.132.0.35', // aka secp521r1 - - 'nistk163' => '1.3.132.0.1', // aka sect163k1 - 'nistp192' => '1.2.840.10045.3.1.1', // aka secp192r1 - 'nistp224' => '1.3.132.0.33', // aka secp224r1 - 'nistk233' => '1.3.132.0.26', // aka sect233k1 - 'nistb233' => '1.3.132.0.27', // aka sect233r1 - 'nistk283' => '1.3.132.0.16', // aka sect283k1 - 'nistk409' => '1.3.132.0.36', // aka sect409k1 - 'nistb409' => '1.3.132.0.37', // aka sect409r1 - 'nistt571' => '1.3.132.0.38', // aka sect571k1 - - // from https://tools.ietf.org/html/rfc5915 - 'secp192r1' => '1.2.840.10045.3.1.1', // aka prime192v1 - 'sect163k1' => '1.3.132.0.1', - 'sect163r2' => '1.3.132.0.15', - 'secp224r1' => '1.3.132.0.33', - 'sect233k1' => '1.3.132.0.26', - 'sect233r1' => '1.3.132.0.27', - 'secp256r1' => '1.2.840.10045.3.1.7', // aka prime256v1 - 'sect283k1' => '1.3.132.0.16', - 'sect283r1' => '1.3.132.0.17', - 'secp384r1' => '1.3.132.0.34', - 'sect409k1' => '1.3.132.0.36', - 'sect409r1' => '1.3.132.0.37', - 'secp521r1' => '1.3.132.0.35', - 'sect571k1' => '1.3.132.0.38', - 'sect571r1' => '1.3.132.0.39', - // from http://www.secg.org/SEC2-Ver-1.0.pdf - 'secp112r1' => '1.3.132.0.6', - 'secp112r2' => '1.3.132.0.7', - 'secp128r1' => '1.3.132.0.28', - 'secp128r2' => '1.3.132.0.29', - 'secp160k1' => '1.3.132.0.9', - 'secp160r1' => '1.3.132.0.8', - 'secp160r2' => '1.3.132.0.30', - 'secp192k1' => '1.3.132.0.31', - 'secp224k1' => '1.3.132.0.32', - 'secp256k1' => '1.3.132.0.10', - - 'sect113r1' => '1.3.132.0.4', - 'sect113r2' => '1.3.132.0.5', - 'sect131r1' => '1.3.132.0.22', - 'sect131r2' => '1.3.132.0.23', - 'sect163r1' => '1.3.132.0.2', - 'sect193r1' => '1.3.132.0.24', - 'sect193r2' => '1.3.132.0.25', - 'sect239k1' => '1.3.132.0.3', - - // from http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.202.2977&rep=rep1&type=pdf#page=36 - /* - 'c2pnb163v1' => '1.2.840.10045.3.0.1', // J.4.1, example 1 - 'c2pnb163v2' => '1.2.840.10045.3.0.2', // J.4.1, example 2 - 'c2pnb163v3' => '1.2.840.10045.3.0.3', // J.4.1, example 3 - 'c2pnb172w1' => '1.2.840.10045.3.0.4', // J.4.2, example 1 - 'c2tnb191v1' => '1.2.840.10045.3.0.5', // J.4.3, example 1 - 'c2tnb191v2' => '1.2.840.10045.3.0.6', // J.4.3, example 2 - 'c2tnb191v3' => '1.2.840.10045.3.0.7', // J.4.3, example 3 - 'c2onb191v4' => '1.2.840.10045.3.0.8', // J.4.3, example 4 - 'c2onb191v5' => '1.2.840.10045.3.0.9', // J.4.3, example 5 - 'c2pnb208w1' => '1.2.840.10045.3.0.10', // J.4.4, example 1 - 'c2tnb239v1' => '1.2.840.10045.3.0.11', // J.4.5, example 1 - 'c2tnb239v2' => '1.2.840.10045.3.0.12', // J.4.5, example 2 - 'c2tnb239v3' => '1.2.840.10045.3.0.13', // J.4.5, example 3 - 'c2onb239v4' => '1.2.840.10045.3.0.14', // J.4.5, example 4 - 'c2onb239v5' => '1.2.840.10045.3.0.15', // J.4.5, example 5 - 'c2pnb272w1' => '1.2.840.10045.3.0.16', // J.4.6, example 1 - 'c2pnb304w1' => '1.2.840.10045.3.0.17', // J.4.7, example 1 - 'c2tnb359v1' => '1.2.840.10045.3.0.18', // J.4.8, example 1 - 'c2pnb368w1' => '1.2.840.10045.3.0.19', // J.4.9, example 1 - 'c2tnb431r1' => '1.2.840.10045.3.0.20', // J.4.10, example 1 - */ - - // http://www.ecc-brainpool.org/download/Domain-parameters.pdf - // https://tools.ietf.org/html/rfc5639 - 'brainpoolP160r1' => '1.3.36.3.3.2.8.1.1.1', - 'brainpoolP160t1' => '1.3.36.3.3.2.8.1.1.2', - 'brainpoolP192r1' => '1.3.36.3.3.2.8.1.1.3', - 'brainpoolP192t1' => '1.3.36.3.3.2.8.1.1.4', - 'brainpoolP224r1' => '1.3.36.3.3.2.8.1.1.5', - 'brainpoolP224t1' => '1.3.36.3.3.2.8.1.1.6', - 'brainpoolP256r1' => '1.3.36.3.3.2.8.1.1.7', - 'brainpoolP256t1' => '1.3.36.3.3.2.8.1.1.8', - 'brainpoolP320r1' => '1.3.36.3.3.2.8.1.1.9', - 'brainpoolP320t1' => '1.3.36.3.3.2.8.1.1.10', - 'brainpoolP384r1' => '1.3.36.3.3.2.8.1.1.11', - 'brainpoolP384t1' => '1.3.36.3.3.2.8.1.1.12', - 'brainpoolP512r1' => '1.3.36.3.3.2.8.1.1.13', - 'brainpoolP512t1' => '1.3.36.3.3.2.8.1.1.14' - ]; - ASN1::loadOIDs([ - 'prime-field' => '1.2.840.10045.1.1', - 'characteristic-two-field' => '1.2.840.10045.1.2', - 'characteristic-two-basis' => '1.2.840.10045.1.2.3', - // per http://www.secg.org/SEC1-Ver-1.0.pdf#page=84, gnBasis "not used here" - 'gnBasis' => '1.2.840.10045.1.2.3.1', // NULL - 'tpBasis' => '1.2.840.10045.1.2.3.2', // Trinomial - 'ppBasis' => '1.2.840.10045.1.2.3.3' // Pentanomial - ] + self::$curveOIDs); - } - } - - /** - * Explicitly set the curve - * - * If the key contains an implicit curve phpseclib needs the curve - * to be explicitly provided - * - * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve - */ - public static function setImplicitCurve(BaseCurve $curve) - { - self::$implicitCurve = $curve; - } - - /** - * Returns an instance of \phpseclib3\Crypt\EC\BaseCurves\Base based - * on the curve parameters - * - * @param array $params - * @return \phpseclib3\Crypt\EC\BaseCurves\Base|false - */ - protected static function loadCurveByParam(array $params) - { - if (count($params) > 1) { - throw new \RuntimeException('No parameters are present'); - } - if (isset($params['namedCurve'])) { - $curve = '\phpseclib3\Crypt\EC\Curves\\' . $params['namedCurve']; - if (!class_exists($curve)) { - throw new UnsupportedCurveException('Named Curve of ' . $params['namedCurve'] . ' is not supported'); - } - return new $curve(); - } - if (isset($params['implicitCurve'])) { - if (!isset(self::$implicitCurve)) { - throw new \RuntimeException('Implicit curves can be provided by calling setImplicitCurve'); - } - return self::$implicitCurve; - } - if (isset($params['specifiedCurve'])) { - $data = $params['specifiedCurve']; - switch ($data['fieldID']['fieldType']) { - case 'prime-field': - $curve = new PrimeCurve(); - $curve->setModulo($data['fieldID']['parameters']); - $curve->setCoefficients( - new BigInteger($data['curve']['a'], 256), - new BigInteger($data['curve']['b'], 256) - ); - $point = self::extractPoint("\0" . $data['base'], $curve); - $curve->setBasePoint(...$point); - $curve->setOrder($data['order']); - return $curve; - case 'characteristic-two-field': - $curve = new BinaryCurve(); - $params = ASN1::decodeBER($data['fieldID']['parameters']); - $params = ASN1::asn1map($params[0], Maps\Characteristic_two::MAP); - $modulo = [(int) $params['m']->toString()]; - switch ($params['basis']) { - case 'tpBasis': - $modulo[] = (int) $params['parameters']->toString(); - break; - case 'ppBasis': - $temp = ASN1::decodeBER($params['parameters']); - $temp = ASN1::asn1map($temp[0], Maps\Pentanomial::MAP); - $modulo[] = (int) $temp['k3']->toString(); - $modulo[] = (int) $temp['k2']->toString(); - $modulo[] = (int) $temp['k1']->toString(); - } - $modulo[] = 0; - $curve->setModulo(...$modulo); - $len = ceil($modulo[0] / 8); - $curve->setCoefficients( - Strings::bin2hex($data['curve']['a']), - Strings::bin2hex($data['curve']['b']) - ); - $point = self::extractPoint("\0" . $data['base'], $curve); - $curve->setBasePoint(...$point); - $curve->setOrder($data['order']); - return $curve; - default: - throw new UnsupportedCurveException('Field Type of ' . $data['fieldID']['fieldType'] . ' is not supported'); - } - } - throw new \RuntimeException('No valid parameters are present'); - } - - /** - * Extract points from a string - * - * Supports both compressed and uncompressed points - * - * @param string $str - * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve - * @return object[] - */ - public static function extractPoint($str, BaseCurve $curve) - { - if ($curve instanceof TwistedEdwardsCurve) { - // first step of point deciding as discussed at the following URL's: - // https://tools.ietf.org/html/rfc8032#section-5.1.3 - // https://tools.ietf.org/html/rfc8032#section-5.2.3 - $y = $str; - $y = strrev($y); - $sign = (bool) (ord($y[0]) & 0x80); - $y[0] = $y[0] & chr(0x7F); - $y = new BigInteger($y, 256); - if ($y->compare($curve->getModulo()) >= 0) { - throw new \RuntimeException('The Y coordinate should not be >= the modulo'); - } - $point = $curve->recoverX($y, $sign); - if (!$curve->verifyPoint($point)) { - throw new \RuntimeException('Unable to verify that point exists on curve'); - } - return $point; - } - - // the first byte of a bit string represents the number of bits in the last byte that are to be ignored but, - // currently, bit strings wanting a non-zero amount of bits trimmed are not supported - if (($val = Strings::shift($str)) != "\0") { - throw new \UnexpectedValueException('extractPoint expects the first byte to be null - not ' . Strings::bin2hex($val)); - } - if ($str == "\0") { - return []; - } - - $keylen = strlen($str); - $order = $curve->getLengthInBytes(); - // point compression is being used - if ($keylen == $order + 1) { - return $curve->derivePoint($str); - } - - // point compression is not being used - if ($keylen == 2 * $order + 1) { - preg_match("#(.)(.{{$order}})(.{{$order}})#s", $str, $matches); - list(, $w, $x, $y) = $matches; - if ($w != "\4") { - throw new \UnexpectedValueException('The first byte of an uncompressed point should be 04 - not ' . Strings::bin2hex($val)); - } - $point = [ - $curve->convertInteger(new BigInteger($x, 256)), - $curve->convertInteger(new BigInteger($y, 256)) - ]; - - if (!$curve->verifyPoint($point)) { - throw new \RuntimeException('Unable to verify that point exists on curve'); - } - - return $point; - } - - throw new \UnexpectedValueException('The string representation of the points is not of an appropriate length'); - } - - /** - * Encode Parameters - * - * @todo Maybe at some point this could be moved to __toString() for each of the curves? - * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve - * @param bool $returnArray optional - * @param array $options optional - * @return string|false - */ - private static function encodeParameters(BaseCurve $curve, $returnArray = false, array $options = []) - { - $useNamedCurves = isset($options['namedCurve']) ? $options['namedCurve'] : self::$useNamedCurves; - - $reflect = new \ReflectionClass($curve); - $name = $reflect->getShortName(); - if ($useNamedCurves) { - if (isset(self::$curveOIDs[$name])) { - if ($reflect->isFinal()) { - $reflect = $reflect->getParentClass(); - $name = $reflect->getShortName(); - } - return $returnArray ? - ['namedCurve' => $name] : - ASN1::encodeDER(['namedCurve' => $name], Maps\ECParameters::MAP); - } - foreach (new \DirectoryIterator(__DIR__ . '/../../Curves/') as $file) { - if ($file->getExtension() != 'php') { - continue; - } - $testName = $file->getBasename('.php'); - $class = 'phpseclib3\Crypt\EC\Curves\\' . $testName; - $reflect = new \ReflectionClass($class); - if ($reflect->isFinal()) { - continue; - } - $candidate = new $class(); - switch ($name) { - case 'Prime': - if (!$candidate instanceof PrimeCurve) { - break; - } - if (!$candidate->getModulo()->equals($curve->getModulo())) { - break; - } - if ($candidate->getA()->toBytes() != $curve->getA()->toBytes()) { - break; - } - if ($candidate->getB()->toBytes() != $curve->getB()->toBytes()) { - break; - } - - list($candidateX, $candidateY) = $candidate->getBasePoint(); - list($curveX, $curveY) = $curve->getBasePoint(); - if ($candidateX->toBytes() != $curveX->toBytes()) { - break; - } - if ($candidateY->toBytes() != $curveY->toBytes()) { - break; - } - - return $returnArray ? - ['namedCurve' => $testName] : - ASN1::encodeDER(['namedCurve' => $testName], Maps\ECParameters::MAP); - case 'Binary': - if (!$candidate instanceof BinaryCurve) { - break; - } - if ($candidate->getModulo() != $curve->getModulo()) { - break; - } - if ($candidate->getA()->toBytes() != $curve->getA()->toBytes()) { - break; - } - if ($candidate->getB()->toBytes() != $curve->getB()->toBytes()) { - break; - } - - list($candidateX, $candidateY) = $candidate->getBasePoint(); - list($curveX, $curveY) = $curve->getBasePoint(); - if ($candidateX->toBytes() != $curveX->toBytes()) { - break; - } - if ($candidateY->toBytes() != $curveY->toBytes()) { - break; - } - - return $returnArray ? - ['namedCurve' => $testName] : - ASN1::encodeDER(['namedCurve' => $testName], Maps\ECParameters::MAP); - } - } - } - - $order = $curve->getOrder(); - // we could try to calculate the order thusly: - // https://crypto.stackexchange.com/a/27914/4520 - // https://en.wikipedia.org/wiki/Schoof%E2%80%93Elkies%E2%80%93Atkin_algorithm - if (!$order) { - throw new \RuntimeException('Specified Curves need the order to be specified'); - } - $point = $curve->getBasePoint(); - $x = $point[0]->toBytes(); - $y = $point[1]->toBytes(); - - if ($curve instanceof PrimeCurve) { - /* - * valid versions are: - * - * ecdpVer1: - * - neither the curve or the base point are generated verifiably randomly. - * ecdpVer2: - * - curve and base point are generated verifiably at random and curve.seed is present - * ecdpVer3: - * - base point is generated verifiably at random but curve is not. curve.seed is present - */ - // other (optional) parameters can be calculated using the methods discused at - // https://crypto.stackexchange.com/q/28947/4520 - $data = [ - 'version' => 'ecdpVer1', - 'fieldID' => [ - 'fieldType' => 'prime-field', - 'parameters' => $curve->getModulo() - ], - 'curve' => [ - 'a' => $curve->getA()->toBytes(), - 'b' => $curve->getB()->toBytes() - ], - 'base' => "\4" . $x . $y, - 'order' => $order - ]; - - return $returnArray ? - ['specifiedCurve' => $data] : - ASN1::encodeDER(['specifiedCurve' => $data], Maps\ECParameters::MAP); - } - if ($curve instanceof BinaryCurve) { - $modulo = $curve->getModulo(); - $basis = count($modulo); - $m = array_shift($modulo); - array_pop($modulo); // the last parameter should always be 0 - //rsort($modulo); - switch ($basis) { - case 3: - $basis = 'tpBasis'; - $modulo = new BigInteger($modulo[0]); - break; - case 5: - $basis = 'ppBasis'; - // these should be in strictly ascending order (hence the commented out rsort above) - $modulo = [ - 'k1' => new BigInteger($modulo[2]), - 'k2' => new BigInteger($modulo[1]), - 'k3' => new BigInteger($modulo[0]) - ]; - $modulo = ASN1::encodeDER($modulo, Maps\Pentanomial::MAP); - $modulo = new ASN1\Element($modulo); - } - $params = ASN1::encodeDER([ - 'm' => new BigInteger($m), - 'basis' => $basis, - 'parameters' => $modulo - ], Maps\Characteristic_two::MAP); - $params = new ASN1\Element($params); - $a = ltrim($curve->getA()->toBytes(), "\0"); - if (!strlen($a)) { - $a = "\0"; - } - $b = ltrim($curve->getB()->toBytes(), "\0"); - if (!strlen($b)) { - $b = "\0"; - } - $data = [ - 'version' => 'ecdpVer1', - 'fieldID' => [ - 'fieldType' => 'characteristic-two-field', - 'parameters' => $params - ], - 'curve' => [ - 'a' => $a, - 'b' => $b - ], - 'base' => "\4" . $x . $y, - 'order' => $order - ]; - - return $returnArray ? - ['specifiedCurve' => $data] : - ASN1::encodeDER(['specifiedCurve' => $data], Maps\ECParameters::MAP); - } - - throw new UnsupportedCurveException('Curve cannot be serialized'); - } - - /** - * Use Specified Curve - * - * A specified curve has all the coefficients, the base points, etc, explicitely included. - * A specified curve is a more verbose way of representing a curve - */ - public static function useSpecifiedCurve() - { - self::$useNamedCurves = false; - } - - /** - * Use Named Curve - * - * A named curve does not include any parameters. It is up to the EC parameters to - * know what the coefficients, the base points, etc, are from the name of the curve. - * A named curve is a more concise way of representing a curve - */ - public static function useNamedCurve() - { - self::$useNamedCurves = true; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/JWK.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/JWK.php deleted file mode 100644 index fd18a981..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/JWK.php +++ /dev/null @@ -1,189 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\EC\Formats\Keys; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\Common\Formats\Keys\JWK as Progenitor; -use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve; -use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve; -use phpseclib3\Crypt\EC\Curves\Ed25519; -use phpseclib3\Crypt\EC\Curves\secp256k1; -use phpseclib3\Crypt\EC\Curves\secp256r1; -use phpseclib3\Crypt\EC\Curves\secp384r1; -use phpseclib3\Crypt\EC\Curves\secp521r1; -use phpseclib3\Exception\UnsupportedCurveException; -use phpseclib3\Math\BigInteger; - -/** - * JWK Formatted EC Handler - * - * @author Jim Wigginton - */ -abstract class JWK extends Progenitor -{ - use Common; - - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - $key = parent::load($key, $password); - - switch ($key->kty) { - case 'EC': - switch ($key->crv) { - case 'P-256': - case 'P-384': - case 'P-521': - case 'secp256k1': - break; - default: - throw new UnsupportedCurveException('Only P-256, P-384, P-521 and secp256k1 curves are accepted (' . $key->crv . ' provided)'); - } - break; - case 'OKP': - switch ($key->crv) { - case 'Ed25519': - case 'Ed448': - break; - default: - throw new UnsupportedCurveException('Only Ed25519 and Ed448 curves are accepted (' . $key->crv . ' provided)'); - } - break; - default: - throw new \Exception('Only EC and OKP JWK keys are supported'); - } - - $curve = '\phpseclib3\Crypt\EC\Curves\\' . str_replace('P-', 'nistp', $key->crv); - $curve = new $curve(); - - if ($curve instanceof TwistedEdwardsCurve) { - $QA = self::extractPoint(Strings::base64url_decode($key->x), $curve); - if (!isset($key->d)) { - return compact('curve', 'QA'); - } - $arr = $curve->extractSecret(Strings::base64url_decode($key->d)); - return compact('curve', 'QA') + $arr; - } - - $QA = [ - $curve->convertInteger(new BigInteger(Strings::base64url_decode($key->x), 256)), - $curve->convertInteger(new BigInteger(Strings::base64url_decode($key->y), 256)) - ]; - - if (!$curve->verifyPoint($QA)) { - throw new \RuntimeException('Unable to verify that point exists on curve'); - } - - if (!isset($key->d)) { - return compact('curve', 'QA'); - } - - $dA = new BigInteger(Strings::base64url_decode($key->d), 256); - - $curve->rangeCheck($dA); - - return compact('curve', 'dA', 'QA'); - } - - /** - * Returns the alias that corresponds to a curve - * - * @return string - */ - private static function getAlias(BaseCurve $curve) - { - switch (true) { - case $curve instanceof secp256r1: - return 'P-256'; - case $curve instanceof secp384r1: - return 'P-384'; - case $curve instanceof secp521r1: - return 'P-521'; - case $curve instanceof secp256k1: - return 'secp256k1'; - } - - $reflect = new \ReflectionClass($curve); - $curveName = $reflect->isFinal() ? - $reflect->getParentClass()->getShortName() : - $reflect->getShortName(); - throw new UnsupportedCurveException("$curveName is not a supported curve"); - } - - /** - * Return the array superstructure for an EC public key - * - * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve - * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey - * @return array - */ - private static function savePublicKeyHelper(BaseCurve $curve, array $publicKey) - { - if ($curve instanceof TwistedEdwardsCurve) { - return [ - 'kty' => 'OKP', - 'crv' => $curve instanceof Ed25519 ? 'Ed25519' : 'Ed448', - 'x' => Strings::base64url_encode($curve->encodePoint($publicKey)) - ]; - } - - return [ - 'kty' => 'EC', - 'crv' => self::getAlias($curve), - 'x' => Strings::base64url_encode($publicKey[0]->toBytes()), - 'y' => Strings::base64url_encode($publicKey[1]->toBytes()) - ]; - } - - /** - * Convert an EC public key to the appropriate format - * - * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve - * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey - * @param array $options optional - * @return string - */ - public static function savePublicKey(BaseCurve $curve, array $publicKey, array $options = []) - { - $key = self::savePublicKeyHelper($curve, $publicKey); - - return self::wrapKey($key, $options); - } - - /** - * Convert a private key to the appropriate format. - * - * @param \phpseclib3\Math\BigInteger $privateKey - * @param \phpseclib3\Crypt\EC\Curves\Ed25519 $curve - * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey - * @param string $secret optional - * @param string $password optional - * @param array $options optional - * @return string - */ - public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, $secret = null, $password = '', array $options = []) - { - $key = self::savePublicKeyHelper($curve, $publicKey); - $key['d'] = $curve instanceof TwistedEdwardsCurve ? $secret : $privateKey->toBytes(); - $key['d'] = Strings::base64url_encode($key['d']); - - return self::wrapKey($key, $options); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/MontgomeryPrivate.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/MontgomeryPrivate.php deleted file mode 100644 index 5741b05a..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/MontgomeryPrivate.php +++ /dev/null @@ -1,101 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\EC\Formats\Keys; - -use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve; -use phpseclib3\Crypt\EC\Curves\Curve25519; -use phpseclib3\Crypt\EC\Curves\Curve448; -use phpseclib3\Exception\UnsupportedFormatException; -use phpseclib3\Math\BigInteger; - -/** - * Montgomery Curve Private Key Handler - * - * @author Jim Wigginton - */ -abstract class MontgomeryPrivate -{ - /** - * Is invisible flag - * - */ - const IS_INVISIBLE = true; - - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - switch (strlen($key)) { - case 32: - $curve = new Curve25519(); - break; - case 56: - $curve = new Curve448(); - break; - default: - throw new \LengthException('The only supported lengths are 32 and 56'); - } - - $components = ['curve' => $curve]; - $components['dA'] = new BigInteger($key, 256); - $curve->rangeCheck($components['dA']); - // note that EC::getEncodedCoordinates does some additional "magic" (it does strrev on the result) - $components['QA'] = $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']); - - return $components; - } - - /** - * Convert an EC public key to the appropriate format - * - * @param \phpseclib3\Crypt\EC\BaseCurves\Montgomery $curve - * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey - * @return string - */ - public static function savePublicKey(MontgomeryCurve $curve, array $publicKey) - { - return strrev($publicKey[0]->toBytes()); - } - - /** - * Convert a private key to the appropriate format. - * - * @param \phpseclib3\Math\BigInteger $privateKey - * @param \phpseclib3\Crypt\EC\BaseCurves\Montgomery $curve - * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey - * @param string $secret optional - * @param string $password optional - * @return string - */ - public static function savePrivateKey(BigInteger $privateKey, MontgomeryCurve $curve, array $publicKey, $secret = null, $password = '') - { - if (!empty($password) && is_string($password)) { - throw new UnsupportedFormatException('MontgomeryPrivate private keys do not support encryption'); - } - - return $privateKey->toBytes(); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/MontgomeryPublic.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/MontgomeryPublic.php deleted file mode 100644 index d1ad48a5..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/MontgomeryPublic.php +++ /dev/null @@ -1,71 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\EC\Formats\Keys; - -use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve; -use phpseclib3\Crypt\EC\Curves\Curve25519; -use phpseclib3\Crypt\EC\Curves\Curve448; -use phpseclib3\Math\BigInteger; - -/** - * Montgomery Public Key Handler - * - * @author Jim Wigginton - */ -abstract class MontgomeryPublic -{ - /** - * Is invisible flag - * - */ - const IS_INVISIBLE = true; - - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - switch (strlen($key)) { - case 32: - $curve = new Curve25519(); - break; - case 56: - $curve = new Curve448(); - break; - default: - throw new \LengthException('The only supported lengths are 32 and 56'); - } - - $components = ['curve' => $curve]; - $components['QA'] = [$components['curve']->convertInteger(new BigInteger(strrev($key), 256))]; - - return $components; - } - - /** - * Convert an EC public key to the appropriate format - * - * @param \phpseclib3\Crypt\EC\BaseCurves\Montgomery $curve - * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey - * @return string - */ - public static function savePublicKey(MontgomeryCurve $curve, array $publicKey) - { - return strrev($publicKey[0]->toBytes()); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/OpenSSH.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/OpenSSH.php deleted file mode 100644 index 2cd3e19d..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/OpenSSH.php +++ /dev/null @@ -1,209 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\EC\Formats\Keys; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\Common\Formats\Keys\OpenSSH as Progenitor; -use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve; -use phpseclib3\Crypt\EC\Curves\Ed25519; -use phpseclib3\Exception\UnsupportedCurveException; -use phpseclib3\Math\BigInteger; - -/** - * OpenSSH Formatted EC Key Handler - * - * @author Jim Wigginton - */ -abstract class OpenSSH extends Progenitor -{ - use Common; - - /** - * Supported Key Types - * - * @var array - */ - protected static $types = [ - 'ecdsa-sha2-nistp256', - 'ecdsa-sha2-nistp384', - 'ecdsa-sha2-nistp521', - 'ssh-ed25519' - ]; - - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - $parsed = parent::load($key, $password); - - if (isset($parsed['paddedKey'])) { - $paddedKey = $parsed['paddedKey']; - list($type) = Strings::unpackSSH2('s', $paddedKey); - if ($type != $parsed['type']) { - throw new \RuntimeException("The public and private keys are not of the same type ($type vs $parsed[type])"); - } - if ($type == 'ssh-ed25519') { - list(, $key, $comment) = Strings::unpackSSH2('sss', $paddedKey); - $key = libsodium::load($key); - $key['comment'] = $comment; - return $key; - } - list($curveName, $publicKey, $privateKey, $comment) = Strings::unpackSSH2('ssis', $paddedKey); - $curve = self::loadCurveByParam(['namedCurve' => $curveName]); - $curve->rangeCheck($privateKey); - return [ - 'curve' => $curve, - 'dA' => $privateKey, - 'QA' => self::extractPoint("\0$publicKey", $curve), - 'comment' => $comment - ]; - } - - if ($parsed['type'] == 'ssh-ed25519') { - if (Strings::shift($parsed['publicKey'], 4) != "\0\0\0\x20") { - throw new \RuntimeException('Length of ssh-ed25519 key should be 32'); - } - - $curve = new Ed25519(); - $qa = self::extractPoint($parsed['publicKey'], $curve); - } else { - list($curveName, $publicKey) = Strings::unpackSSH2('ss', $parsed['publicKey']); - $curveName = '\phpseclib3\Crypt\EC\Curves\\' . $curveName; - $curve = new $curveName(); - - $qa = self::extractPoint("\0" . $publicKey, $curve); - } - - return [ - 'curve' => $curve, - 'QA' => $qa, - 'comment' => $parsed['comment'] - ]; - } - - /** - * Returns the alias that corresponds to a curve - * - * @return string - */ - private static function getAlias(BaseCurve $curve) - { - self::initialize_static_variables(); - - $reflect = new \ReflectionClass($curve); - $name = $reflect->getShortName(); - - $oid = self::$curveOIDs[$name]; - $aliases = array_filter(self::$curveOIDs, function ($v) use ($oid) { - return $v == $oid; - }); - $aliases = array_keys($aliases); - - for ($i = 0; $i < count($aliases); $i++) { - if (in_array('ecdsa-sha2-' . $aliases[$i], self::$types)) { - $alias = $aliases[$i]; - break; - } - } - - if (!isset($alias)) { - throw new UnsupportedCurveException($name . ' is not a curve that the OpenSSH plugin supports'); - } - - return $alias; - } - - /** - * Convert an EC public key to the appropriate format - * - * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve - * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey - * @param array $options optional - * @return string - */ - public static function savePublicKey(BaseCurve $curve, array $publicKey, array $options = []) - { - $comment = isset($options['comment']) ? $options['comment'] : self::$comment; - - if ($curve instanceof Ed25519) { - $key = Strings::packSSH2('ss', 'ssh-ed25519', $curve->encodePoint($publicKey)); - - if (isset($options['binary']) ? $options['binary'] : self::$binary) { - return $key; - } - - $key = 'ssh-ed25519 ' . base64_encode($key) . ' ' . $comment; - return $key; - } - - $alias = self::getAlias($curve); - - $points = "\4" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes(); - $key = Strings::packSSH2('sss', 'ecdsa-sha2-' . $alias, $alias, $points); - - if (isset($options['binary']) ? $options['binary'] : self::$binary) { - return $key; - } - - $key = 'ecdsa-sha2-' . $alias . ' ' . base64_encode($key) . ' ' . $comment; - - return $key; - } - - /** - * Convert a private key to the appropriate format. - * - * @param \phpseclib3\Math\BigInteger $privateKey - * @param \phpseclib3\Crypt\EC\Curves\Ed25519 $curve - * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey - * @param string $secret optional - * @param string $password optional - * @param array $options optional - * @return string - */ - public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, $secret = null, $password = '', array $options = []) - { - if ($curve instanceof Ed25519) { - if (!isset($secret)) { - throw new \RuntimeException('Private Key does not have a secret set'); - } - if (strlen($secret) != 32) { - throw new \RuntimeException('Private Key secret is not of the correct length'); - } - - $pubKey = $curve->encodePoint($publicKey); - - $publicKey = Strings::packSSH2('ss', 'ssh-ed25519', $pubKey); - $privateKey = Strings::packSSH2('sss', 'ssh-ed25519', $pubKey, $secret . $pubKey); - - return self::wrapPrivateKey($publicKey, $privateKey, $password, $options); - } - - $alias = self::getAlias($curve); - - $points = "\4" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes(); - $publicKey = self::savePublicKey($curve, $publicKey, ['binary' => true]); - - $privateKey = Strings::packSSH2('sssi', 'ecdsa-sha2-' . $alias, $alias, $points, $privateKey); - - return self::wrapPrivateKey($publicKey, $privateKey, $password, $options); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS1.php deleted file mode 100644 index 9f4b3300..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS1.php +++ /dev/null @@ -1,194 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\EC\Formats\Keys; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\Common\Formats\Keys\PKCS1 as Progenitor; -use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve; -use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve; -use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve; -use phpseclib3\Exception\UnsupportedCurveException; -use phpseclib3\File\ASN1; -use phpseclib3\File\ASN1\Maps; -use phpseclib3\Math\BigInteger; - -/** - * "PKCS1" (RFC5915) Formatted EC Key Handler - * - * @author Jim Wigginton - */ -abstract class PKCS1 extends Progenitor -{ - use Common; - - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - self::initialize_static_variables(); - - if (!Strings::is_stringable($key)) { - throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key)); - } - - if (strpos($key, 'BEGIN EC PARAMETERS') && strpos($key, 'BEGIN EC PRIVATE KEY')) { - $components = []; - - preg_match('#-*BEGIN EC PRIVATE KEY-*[^-]*-*END EC PRIVATE KEY-*#s', $key, $matches); - $decoded = parent::load($matches[0], $password); - $decoded = ASN1::decodeBER($decoded); - if (!$decoded) { - throw new \RuntimeException('Unable to decode BER'); - } - - $ecPrivate = ASN1::asn1map($decoded[0], Maps\ECPrivateKey::MAP); - if (!is_array($ecPrivate)) { - throw new \RuntimeException('Unable to perform ASN1 mapping'); - } - - if (isset($ecPrivate['parameters'])) { - $components['curve'] = self::loadCurveByParam($ecPrivate['parameters']); - } - - preg_match('#-*BEGIN EC PARAMETERS-*[^-]*-*END EC PARAMETERS-*#s', $key, $matches); - $decoded = parent::load($matches[0], ''); - $decoded = ASN1::decodeBER($decoded); - if (!$decoded) { - throw new \RuntimeException('Unable to decode BER'); - } - $ecParams = ASN1::asn1map($decoded[0], Maps\ECParameters::MAP); - if (!is_array($ecParams)) { - throw new \RuntimeException('Unable to perform ASN1 mapping'); - } - $ecParams = self::loadCurveByParam($ecParams); - - // comparing $ecParams and $components['curve'] directly won't work because they'll have different Math\Common\FiniteField classes - // even if the modulo is the same - if (isset($components['curve']) && self::encodeParameters($ecParams, false, []) != self::encodeParameters($components['curve'], false, [])) { - throw new \RuntimeException('EC PARAMETERS does not correspond to EC PRIVATE KEY'); - } - - if (!isset($components['curve'])) { - $components['curve'] = $ecParams; - } - - $components['dA'] = new BigInteger($ecPrivate['privateKey'], 256); - $components['curve']->rangeCheck($components['dA']); - $components['QA'] = isset($ecPrivate['publicKey']) ? - self::extractPoint($ecPrivate['publicKey'], $components['curve']) : - $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']); - - return $components; - } - - $key = parent::load($key, $password); - - $decoded = ASN1::decodeBER($key); - if (!$decoded) { - throw new \RuntimeException('Unable to decode BER'); - } - - $key = ASN1::asn1map($decoded[0], Maps\ECParameters::MAP); - if (is_array($key)) { - return ['curve' => self::loadCurveByParam($key)]; - } - - $key = ASN1::asn1map($decoded[0], Maps\ECPrivateKey::MAP); - if (!is_array($key)) { - throw new \RuntimeException('Unable to perform ASN1 mapping'); - } - if (!isset($key['parameters'])) { - throw new \RuntimeException('Key cannot be loaded without parameters'); - } - - $components = []; - $components['curve'] = self::loadCurveByParam($key['parameters']); - $components['dA'] = new BigInteger($key['privateKey'], 256); - $components['QA'] = isset($ecPrivate['publicKey']) ? - self::extractPoint($ecPrivate['publicKey'], $components['curve']) : - $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']); - - return $components; - } - - /** - * Convert EC parameters to the appropriate format - * - * @return string - */ - public static function saveParameters(BaseCurve $curve, array $options = []) - { - self::initialize_static_variables(); - - if ($curve instanceof TwistedEdwardsCurve || $curve instanceof MontgomeryCurve) { - throw new UnsupportedCurveException('TwistedEdwards and Montgomery Curves are not supported'); - } - - $key = self::encodeParameters($curve, false, $options); - - return "-----BEGIN EC PARAMETERS-----\r\n" . - chunk_split(Strings::base64_encode($key), 64) . - "-----END EC PARAMETERS-----\r\n"; - } - - /** - * Convert a private key to the appropriate format. - * - * @param \phpseclib3\Math\BigInteger $privateKey - * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve - * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey - * @param string $secret optional - * @param string $password optional - * @param array $options optional - * @return string - */ - public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, $secret = null, $password = '', array $options = []) - { - self::initialize_static_variables(); - - if ($curve instanceof TwistedEdwardsCurve || $curve instanceof MontgomeryCurve) { - throw new UnsupportedCurveException('TwistedEdwards Curves are not supported'); - } - - $publicKey = "\4" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes(); - - $key = [ - 'version' => 'ecPrivkeyVer1', - 'privateKey' => $privateKey->toBytes(), - 'parameters' => new ASN1\Element(self::encodeParameters($curve)), - 'publicKey' => "\0" . $publicKey - ]; - - $key = ASN1::encodeDER($key, Maps\ECPrivateKey::MAP); - - return self::wrapPrivateKey($key, 'EC', $password, $options); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS8.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS8.php deleted file mode 100644 index 0ec7742f..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS8.php +++ /dev/null @@ -1,234 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\EC\Formats\Keys; - -use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor; -use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve; -use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve; -use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve; -use phpseclib3\Crypt\EC\Curves\Ed25519; -use phpseclib3\Crypt\EC\Curves\Ed448; -use phpseclib3\Exception\UnsupportedCurveException; -use phpseclib3\File\ASN1; -use phpseclib3\File\ASN1\Maps; -use phpseclib3\Math\BigInteger; - -/** - * PKCS#8 Formatted EC Key Handler - * - * @author Jim Wigginton - */ -abstract class PKCS8 extends Progenitor -{ - use Common; - - /** - * OID Name - * - * @var array - */ - const OID_NAME = ['id-ecPublicKey', 'id-Ed25519', 'id-Ed448']; - - /** - * OID Value - * - * @var string - */ - const OID_VALUE = ['1.2.840.10045.2.1', '1.3.101.112', '1.3.101.113']; - - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - // initialize_static_variables() is defined in both the trait and the parent class - // when it's defined in two places it's the traits one that's called - // the parent one is needed, as well, but the parent one is called by other methods - // in the parent class as needed and in the context of the parent it's the parent - // one that's called - self::initialize_static_variables(); - - $key = parent::load($key, $password); - - $type = isset($key['privateKey']) ? 'privateKey' : 'publicKey'; - - switch ($key[$type . 'Algorithm']['algorithm']) { - case 'id-Ed25519': - case 'id-Ed448': - return self::loadEdDSA($key); - } - - $decoded = ASN1::decodeBER($key[$type . 'Algorithm']['parameters']->element); - if (!$decoded) { - throw new \RuntimeException('Unable to decode BER'); - } - $params = ASN1::asn1map($decoded[0], Maps\ECParameters::MAP); - if (!$params) { - throw new \RuntimeException('Unable to decode the parameters using Maps\ECParameters'); - } - - $components = []; - $components['curve'] = self::loadCurveByParam($params); - - if ($type == 'publicKey') { - $components['QA'] = self::extractPoint("\0" . $key['publicKey'], $components['curve']); - - return $components; - } - - $decoded = ASN1::decodeBER($key['privateKey']); - if (!$decoded) { - throw new \RuntimeException('Unable to decode BER'); - } - $key = ASN1::asn1map($decoded[0], Maps\ECPrivateKey::MAP); - if (isset($key['parameters']) && $params != $key['parameters']) { - throw new \RuntimeException('The PKCS8 parameter field does not match the private key parameter field'); - } - - $components['dA'] = new BigInteger($key['privateKey'], 256); - $components['curve']->rangeCheck($components['dA']); - $components['QA'] = isset($key['publicKey']) ? - self::extractPoint($key['publicKey'], $components['curve']) : - $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']); - - return $components; - } - - /** - * Break a public or private EdDSA key down into its constituent components - * - * @return array - */ - private static function loadEdDSA(array $key) - { - $components = []; - - if (isset($key['privateKey'])) { - $components['curve'] = $key['privateKeyAlgorithm']['algorithm'] == 'id-Ed25519' ? new Ed25519() : new Ed448(); - - // 0x04 == octet string - // 0x20 == length (32 bytes) - if (substr($key['privateKey'], 0, 2) != "\x04\x20") { - throw new \RuntimeException('The first two bytes of the private key field should be 0x0420'); - } - $arr = $components['curve']->extractSecret(substr($key['privateKey'], 2)); - $components['dA'] = $arr['dA']; - $components['secret'] = $arr['secret']; - } - - if (isset($key['publicKey'])) { - if (!isset($components['curve'])) { - $components['curve'] = $key['publicKeyAlgorithm']['algorithm'] == 'id-Ed25519' ? new Ed25519() : new Ed448(); - } - - $components['QA'] = self::extractPoint($key['publicKey'], $components['curve']); - } - - if (isset($key['privateKey']) && !isset($components['QA'])) { - $components['QA'] = $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']); - } - - return $components; - } - - /** - * Convert an EC public key to the appropriate format - * - * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve - * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey - * @param array $options optional - * @return string - */ - public static function savePublicKey(BaseCurve $curve, array $publicKey, array $options = []) - { - self::initialize_static_variables(); - - if ($curve instanceof MontgomeryCurve) { - throw new UnsupportedCurveException('Montgomery Curves are not supported'); - } - - if ($curve instanceof TwistedEdwardsCurve) { - return self::wrapPublicKey( - $curve->encodePoint($publicKey), - null, - $curve instanceof Ed25519 ? 'id-Ed25519' : 'id-Ed448' - ); - } - - $params = new ASN1\Element(self::encodeParameters($curve, false, $options)); - - $key = "\4" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes(); - - return self::wrapPublicKey($key, $params, 'id-ecPublicKey'); - } - - /** - * Convert a private key to the appropriate format. - * - * @param \phpseclib3\Math\BigInteger $privateKey - * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve - * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey - * @param string $secret optional - * @param string $password optional - * @param array $options optional - * @return string - */ - public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, $secret = null, $password = '', array $options = []) - { - self::initialize_static_variables(); - - if ($curve instanceof MontgomeryCurve) { - throw new UnsupportedCurveException('Montgomery Curves are not supported'); - } - - if ($curve instanceof TwistedEdwardsCurve) { - return self::wrapPrivateKey( - "\x04\x20" . $secret, - [], - null, - $password, - $curve instanceof Ed25519 ? 'id-Ed25519' : 'id-Ed448' - ); - } - - $publicKey = "\4" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes(); - - $params = new ASN1\Element(self::encodeParameters($curve, false, $options)); - - $key = [ - 'version' => 'ecPrivkeyVer1', - 'privateKey' => $privateKey->toBytes(), - //'parameters' => $params, - 'publicKey' => "\0" . $publicKey - ]; - - $key = ASN1::encodeDER($key, Maps\ECPrivateKey::MAP); - - return self::wrapPrivateKey($key, [], $params, $password, 'id-ecPublicKey', '', $options); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PuTTY.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PuTTY.php deleted file mode 100644 index 866c883f..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PuTTY.php +++ /dev/null @@ -1,138 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\EC\Formats\Keys; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\Common\Formats\Keys\PuTTY as Progenitor; -use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve; -use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve; -use phpseclib3\Math\BigInteger; - -/** - * PuTTY Formatted EC Key Handler - * - * @author Jim Wigginton - */ -abstract class PuTTY extends Progenitor -{ - use Common; - - /** - * Public Handler - * - * @var string - */ - const PUBLIC_HANDLER = 'phpseclib3\Crypt\EC\Formats\Keys\OpenSSH'; - - /** - * Supported Key Types - * - * @var array - */ - protected static $types = [ - 'ecdsa-sha2-nistp256', - 'ecdsa-sha2-nistp384', - 'ecdsa-sha2-nistp521', - 'ssh-ed25519' - ]; - - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - $components = parent::load($key, $password); - if (!isset($components['private'])) { - return $components; - } - - $private = $components['private']; - - $temp = Strings::base64_encode(Strings::packSSH2('s', $components['type']) . $components['public']); - $components = OpenSSH::load($components['type'] . ' ' . $temp . ' ' . $components['comment']); - - if ($components['curve'] instanceof TwistedEdwardsCurve) { - if (Strings::shift($private, 4) != "\0\0\0\x20") { - throw new \RuntimeException('Length of ssh-ed25519 key should be 32'); - } - $arr = $components['curve']->extractSecret($private); - $components['dA'] = $arr['dA']; - $components['secret'] = $arr['secret']; - } else { - list($components['dA']) = Strings::unpackSSH2('i', $private); - $components['curve']->rangeCheck($components['dA']); - } - - return $components; - } - - /** - * Convert a private key to the appropriate format. - * - * @param \phpseclib3\Math\BigInteger $privateKey - * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve - * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey - * @param string $secret optional - * @param string $password optional - * @param array $options optional - * @return string - */ - public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, $secret = null, $password = false, array $options = []) - { - self::initialize_static_variables(); - - $public = explode(' ', OpenSSH::savePublicKey($curve, $publicKey)); - $name = $public[0]; - $public = Strings::base64_decode($public[1]); - list(, $length) = unpack('N', Strings::shift($public, 4)); - Strings::shift($public, $length); - - // PuTTY pads private keys with a null byte per the following: - // https://github.com/github/putty/blob/a3d14d77f566a41fc61dfdc5c2e0e384c9e6ae8b/sshecc.c#L1926 - if (!$curve instanceof TwistedEdwardsCurve) { - $private = $privateKey->toBytes(); - if (!(strlen($privateKey->toBits()) & 7)) { - $private = "\0$private"; - } - } - - $private = $curve instanceof TwistedEdwardsCurve ? - Strings::packSSH2('s', $secret) : - Strings::packSSH2('s', $private); - - return self::wrapPrivateKey($public, $private, $name, $password, $options); - } - - /** - * Convert an EC public key to the appropriate format - * - * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve - * @param \phpseclib3\Math\Common\FiniteField[] $publicKey - * @return string - */ - public static function savePublicKey(BaseCurve $curve, array $publicKey) - { - $public = explode(' ', OpenSSH::savePublicKey($curve, $publicKey)); - $type = $public[0]; - $public = Strings::base64_decode($public[1]); - list(, $length) = unpack('N', Strings::shift($public, 4)); - Strings::shift($public, $length); - - return self::wrapPublicKey($public, $type); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/XML.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/XML.php deleted file mode 100644 index 27d9218f..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/XML.php +++ /dev/null @@ -1,485 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\EC\Formats\Keys; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve; -use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve; -use phpseclib3\Crypt\EC\BaseCurves\Prime as PrimeCurve; -use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve; -use phpseclib3\Exception\BadConfigurationException; -use phpseclib3\Exception\UnsupportedCurveException; -use phpseclib3\Math\BigInteger; - -/** - * XML Formatted EC Key Handler - * - * @author Jim Wigginton - */ -abstract class XML -{ - use Common; - - /** - * Default namespace - * - * @var string - */ - private static $namespace; - - /** - * Flag for using RFC4050 syntax - * - * @var bool - */ - private static $rfc4050 = false; - - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - self::initialize_static_variables(); - - if (!Strings::is_stringable($key)) { - throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key)); - } - - if (!class_exists('DOMDocument')) { - throw new BadConfigurationException('The dom extension is not setup correctly on this system'); - } - - $use_errors = libxml_use_internal_errors(true); - - $temp = self::isolateNamespace($key, 'http://www.w3.org/2009/xmldsig11#'); - if ($temp) { - $key = $temp; - } - - $temp = self::isolateNamespace($key, 'http://www.w3.org/2001/04/xmldsig-more#'); - if ($temp) { - $key = $temp; - } - - $dom = new \DOMDocument(); - if (substr($key, 0, 5) != '' . $key . ''; - } - - if (!$dom->loadXML($key)) { - libxml_use_internal_errors($use_errors); - throw new \UnexpectedValueException('Key does not appear to contain XML'); - } - $xpath = new \DOMXPath($dom); - libxml_use_internal_errors($use_errors); - $curve = self::loadCurveByParam($xpath); - - $pubkey = self::query($xpath, 'publickey', 'Public Key is not present'); - - $QA = self::query($xpath, 'ecdsakeyvalue')->length ? - self::extractPointRFC4050($xpath, $curve) : - self::extractPoint("\0" . $pubkey, $curve); - - libxml_use_internal_errors($use_errors); - - return compact('curve', 'QA'); - } - - /** - * Case-insensitive xpath query - * - * @param \DOMXPath $xpath - * @param string $name - * @param string $error optional - * @param bool $decode optional - * @return \DOMNodeList - */ - private static function query(\DOMXPath $xpath, $name, $error = null, $decode = true) - { - $query = '/'; - $names = explode('/', $name); - foreach ($names as $name) { - $query .= "/*[translate(local-name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='$name']"; - } - $result = $xpath->query($query); - if (!isset($error)) { - return $result; - } - - if (!$result->length) { - throw new \RuntimeException($error); - } - return $decode ? self::decodeValue($result->item(0)->textContent) : $result->item(0)->textContent; - } - - /** - * Finds the first element in the relevant namespace, strips the namespacing and returns the XML for that element. - * - * @param string $xml - * @param string $ns - */ - private static function isolateNamespace($xml, $ns) - { - $dom = new \DOMDocument(); - if (!$dom->loadXML($xml)) { - return false; - } - $xpath = new \DOMXPath($dom); - $nodes = $xpath->query("//*[namespace::*[.='$ns'] and not(../namespace::*[.='$ns'])]"); - if (!$nodes->length) { - return false; - } - $node = $nodes->item(0); - $ns_name = $node->lookupPrefix($ns); - if ($ns_name) { - $node->removeAttributeNS($ns, $ns_name); - } - return $dom->saveXML($node); - } - - /** - * Decodes the value - * - * @param string $value - */ - private static function decodeValue($value) - { - return Strings::base64_decode(str_replace(["\r", "\n", ' ', "\t"], '', $value)); - } - - /** - * Extract points from an XML document - * - * @param \DOMXPath $xpath - * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve - * @return object[] - */ - private static function extractPointRFC4050(\DOMXPath $xpath, BaseCurve $curve) - { - $x = self::query($xpath, 'publickey/x'); - $y = self::query($xpath, 'publickey/y'); - if (!$x->length || !$x->item(0)->hasAttribute('Value')) { - throw new \RuntimeException('Public Key / X coordinate not found'); - } - if (!$y->length || !$y->item(0)->hasAttribute('Value')) { - throw new \RuntimeException('Public Key / Y coordinate not found'); - } - $point = [ - $curve->convertInteger(new BigInteger($x->item(0)->getAttribute('Value'))), - $curve->convertInteger(new BigInteger($y->item(0)->getAttribute('Value'))) - ]; - if (!$curve->verifyPoint($point)) { - throw new \RuntimeException('Unable to verify that point exists on curve'); - } - return $point; - } - - /** - * Returns an instance of \phpseclib3\Crypt\EC\BaseCurves\Base based - * on the curve parameters - * - * @param \DomXPath $xpath - * @return \phpseclib3\Crypt\EC\BaseCurves\Base|false - */ - private static function loadCurveByParam(\DOMXPath $xpath) - { - $namedCurve = self::query($xpath, 'namedcurve'); - if ($namedCurve->length == 1) { - $oid = $namedCurve->item(0)->getAttribute('URN'); - $oid = preg_replace('#[^\d.]#', '', $oid); - $name = array_search($oid, self::$curveOIDs); - if ($name === false) { - throw new UnsupportedCurveException('Curve with OID of ' . $oid . ' is not supported'); - } - - $curve = '\phpseclib3\Crypt\EC\Curves\\' . $name; - if (!class_exists($curve)) { - throw new UnsupportedCurveException('Named Curve of ' . $name . ' is not supported'); - } - return new $curve(); - } - - $params = self::query($xpath, 'explicitparams'); - if ($params->length) { - return self::loadCurveByParamRFC4050($xpath); - } - - $params = self::query($xpath, 'ecparameters'); - if (!$params->length) { - throw new \RuntimeException('No parameters are present'); - } - - $fieldTypes = [ - 'prime-field' => ['fieldid/prime/p'], - 'gnb' => ['fieldid/gnb/m'], - 'tnb' => ['fieldid/tnb/k'], - 'pnb' => ['fieldid/pnb/k1', 'fieldid/pnb/k2', 'fieldid/pnb/k3'], - 'unknown' => [] - ]; - - foreach ($fieldTypes as $type => $queries) { - foreach ($queries as $query) { - $result = self::query($xpath, $query); - if (!$result->length) { - continue 2; - } - $param = preg_replace('#.*/#', '', $query); - $$param = self::decodeValue($result->item(0)->textContent); - } - break; - } - - $a = self::query($xpath, 'curve/a', 'A coefficient is not present'); - $b = self::query($xpath, 'curve/b', 'B coefficient is not present'); - $base = self::query($xpath, 'base', 'Base point is not present'); - $order = self::query($xpath, 'order', 'Order is not present'); - - switch ($type) { - case 'prime-field': - $curve = new PrimeCurve(); - $curve->setModulo(new BigInteger($p, 256)); - $curve->setCoefficients( - new BigInteger($a, 256), - new BigInteger($b, 256) - ); - $point = self::extractPoint("\0" . $base, $curve); - $curve->setBasePoint(...$point); - $curve->setOrder(new BigInteger($order, 256)); - return $curve; - case 'gnb': - case 'tnb': - case 'pnb': - default: - throw new UnsupportedCurveException('Field Type of ' . $type . ' is not supported'); - } - } - - /** - * Returns an instance of \phpseclib3\Crypt\EC\BaseCurves\Base based - * on the curve parameters - * - * @param \DomXPath $xpath - * @return \phpseclib3\Crypt\EC\BaseCurves\Base|false - */ - private static function loadCurveByParamRFC4050(\DOMXPath $xpath) - { - $fieldTypes = [ - 'prime-field' => ['primefieldparamstype/p'], - 'unknown' => [] - ]; - - foreach ($fieldTypes as $type => $queries) { - foreach ($queries as $query) { - $result = self::query($xpath, $query); - if (!$result->length) { - continue 2; - } - $param = preg_replace('#.*/#', '', $query); - $$param = $result->item(0)->textContent; - } - break; - } - - $a = self::query($xpath, 'curveparamstype/a', 'A coefficient is not present', false); - $b = self::query($xpath, 'curveparamstype/b', 'B coefficient is not present', false); - $x = self::query($xpath, 'basepointparams/basepoint/ecpointtype/x', 'Base Point X is not present', false); - $y = self::query($xpath, 'basepointparams/basepoint/ecpointtype/y', 'Base Point Y is not present', false); - $order = self::query($xpath, 'order', 'Order is not present', false); - - switch ($type) { - case 'prime-field': - $curve = new PrimeCurve(); - - $p = str_replace(["\r", "\n", ' ', "\t"], '', $p); - $curve->setModulo(new BigInteger($p)); - - $a = str_replace(["\r", "\n", ' ', "\t"], '', $a); - $b = str_replace(["\r", "\n", ' ', "\t"], '', $b); - $curve->setCoefficients( - new BigInteger($a), - new BigInteger($b) - ); - - $x = str_replace(["\r", "\n", ' ', "\t"], '', $x); - $y = str_replace(["\r", "\n", ' ', "\t"], '', $y); - $curve->setBasePoint( - new BigInteger($x), - new BigInteger($y) - ); - - $order = str_replace(["\r", "\n", ' ', "\t"], '', $order); - $curve->setOrder(new BigInteger($order)); - return $curve; - default: - throw new UnsupportedCurveException('Field Type of ' . $type . ' is not supported'); - } - } - - /** - * Sets the namespace. dsig11 is the most common one. - * - * Set to null to unset. Used only for creating public keys. - * - * @param string $namespace - */ - public static function setNamespace($namespace) - { - self::$namespace = $namespace; - } - - /** - * Uses the XML syntax specified in https://tools.ietf.org/html/rfc4050 - */ - public static function enableRFC4050Syntax() - { - self::$rfc4050 = true; - } - - /** - * Uses the XML syntax specified in https://www.w3.org/TR/xmldsig-core/#sec-ECParameters - */ - public static function disableRFC4050Syntax() - { - self::$rfc4050 = false; - } - - /** - * Convert a public key to the appropriate format - * - * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve - * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey - * @param array $options optional - * @return string - */ - public static function savePublicKey(BaseCurve $curve, array $publicKey, array $options = []) - { - self::initialize_static_variables(); - - if ($curve instanceof TwistedEdwardsCurve || $curve instanceof MontgomeryCurve) { - throw new UnsupportedCurveException('TwistedEdwards and Montgomery Curves are not supported'); - } - - if (empty(static::$namespace)) { - $pre = $post = ''; - } else { - $pre = static::$namespace . ':'; - $post = ':' . static::$namespace; - } - - if (self::$rfc4050) { - return '<' . $pre . 'ECDSAKeyValue xmlns' . $post . '="http://www.w3.org/2001/04/xmldsig-more#">' . "\r\n" . - self::encodeXMLParameters($curve, $pre, $options) . "\r\n" . - '<' . $pre . 'PublicKey>' . "\r\n" . - '<' . $pre . 'X Value="' . $publicKey[0] . '" />' . "\r\n" . - '<' . $pre . 'Y Value="' . $publicKey[1] . '" />' . "\r\n" . - '' . "\r\n" . - ''; - } - - $publicKey = "\4" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes(); - - return '<' . $pre . 'ECDSAKeyValue xmlns' . $post . '="http://www.w3.org/2009/xmldsig11#">' . "\r\n" . - self::encodeXMLParameters($curve, $pre, $options) . "\r\n" . - '<' . $pre . 'PublicKey>' . Strings::base64_encode($publicKey) . '' . "\r\n" . - ''; - } - - /** - * Encode Parameters - * - * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve - * @param string $pre - * @param array $options optional - * @return string|false - */ - private static function encodeXMLParameters(BaseCurve $curve, $pre, array $options = []) - { - $result = self::encodeParameters($curve, true, $options); - - if (isset($result['namedCurve'])) { - $namedCurve = '<' . $pre . 'NamedCurve URI="urn:oid:' . self::$curveOIDs[$result['namedCurve']] . '" />'; - return self::$rfc4050 ? - '' . str_replace('URI', 'URN', $namedCurve) . '' : - $namedCurve; - } - - if (self::$rfc4050) { - $xml = '<' . $pre . 'ExplicitParams>' . "\r\n" . - '<' . $pre . 'FieldParams>' . "\r\n"; - $temp = $result['specifiedCurve']; - switch ($temp['fieldID']['fieldType']) { - case 'prime-field': - $xml .= '<' . $pre . 'PrimeFieldParamsType>' . "\r\n" . - '<' . $pre . 'P>' . $temp['fieldID']['parameters'] . '' . "\r\n" . - '' . "\r\n"; - $a = $curve->getA(); - $b = $curve->getB(); - list($x, $y) = $curve->getBasePoint(); - break; - default: - throw new UnsupportedCurveException('Field Type of ' . $temp['fieldID']['fieldType'] . ' is not supported'); - } - $xml .= '' . "\r\n" . - '<' . $pre . 'CurveParamsType>' . "\r\n" . - '<' . $pre . 'A>' . $a . '' . "\r\n" . - '<' . $pre . 'B>' . $b . '' . "\r\n" . - '' . "\r\n" . - '<' . $pre . 'BasePointParams>' . "\r\n" . - '<' . $pre . 'BasePoint>' . "\r\n" . - '<' . $pre . 'ECPointType>' . "\r\n" . - '<' . $pre . 'X>' . $x . '' . "\r\n" . - '<' . $pre . 'Y>' . $y . '' . "\r\n" . - '' . "\r\n" . - '' . "\r\n" . - '<' . $pre . 'Order>' . $curve->getOrder() . '' . "\r\n" . - '' . "\r\n" . - '' . "\r\n"; - - return $xml; - } - - if (isset($result['specifiedCurve'])) { - $xml = '<' . $pre . 'ECParameters>' . "\r\n" . - '<' . $pre . 'FieldID>' . "\r\n"; - $temp = $result['specifiedCurve']; - switch ($temp['fieldID']['fieldType']) { - case 'prime-field': - $xml .= '<' . $pre . 'Prime>' . "\r\n" . - '<' . $pre . 'P>' . Strings::base64_encode($temp['fieldID']['parameters']->toBytes()) . '' . "\r\n" . - '' . "\r\n" ; - break; - default: - throw new UnsupportedCurveException('Field Type of ' . $temp['fieldID']['fieldType'] . ' is not supported'); - } - $xml .= '' . "\r\n" . - '<' . $pre . 'Curve>' . "\r\n" . - '<' . $pre . 'A>' . Strings::base64_encode($temp['curve']['a']) . '' . "\r\n" . - '<' . $pre . 'B>' . Strings::base64_encode($temp['curve']['b']) . '' . "\r\n" . - '' . "\r\n" . - '<' . $pre . 'Base>' . Strings::base64_encode($temp['base']) . '' . "\r\n" . - '<' . $pre . 'Order>' . Strings::base64_encode($temp['order']) . '' . "\r\n" . - ''; - return $xml; - } - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/libsodium.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/libsodium.php deleted file mode 100644 index 2be6ba59..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/libsodium.php +++ /dev/null @@ -1,116 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\EC\Formats\Keys; - -use phpseclib3\Crypt\EC\Curves\Ed25519; -use phpseclib3\Exception\UnsupportedFormatException; -use phpseclib3\Math\BigInteger; - -/** - * libsodium Key Handler - * - * @author Jim Wigginton - */ -abstract class libsodium -{ - use Common; - - /** - * Is invisible flag - * - */ - const IS_INVISIBLE = true; - - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - switch (strlen($key)) { - case 32: - $public = $key; - break; - case 64: - $private = substr($key, 0, 32); - $public = substr($key, -32); - break; - case 96: - $public = substr($key, -32); - if (substr($key, 32, 32) != $public) { - throw new \RuntimeException('Keys with 96 bytes should have the 2nd and 3rd set of 32 bytes match'); - } - $private = substr($key, 0, 32); - break; - default: - throw new \RuntimeException('libsodium keys need to either be 32 bytes long, 64 bytes long or 96 bytes long'); - } - - $curve = new Ed25519(); - $components = ['curve' => $curve]; - if (isset($private)) { - $arr = $curve->extractSecret($private); - $components['dA'] = $arr['dA']; - $components['secret'] = $arr['secret']; - } - $components['QA'] = isset($public) ? - self::extractPoint($public, $curve) : - $curve->multiplyPoint($curve->getBasePoint(), $components['dA']); - - return $components; - } - - /** - * Convert an EC public key to the appropriate format - * - * @param \phpseclib3\Crypt\EC\Curves\Ed25519 $curve - * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey - * @return string - */ - public static function savePublicKey(Ed25519 $curve, array $publicKey) - { - return $curve->encodePoint($publicKey); - } - - /** - * Convert a private key to the appropriate format. - * - * @param \phpseclib3\Math\BigInteger $privateKey - * @param \phpseclib3\Crypt\EC\Curves\Ed25519 $curve - * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey - * @param string $secret optional - * @param string $password optional - * @return string - */ - public static function savePrivateKey(BigInteger $privateKey, Ed25519 $curve, array $publicKey, $secret = null, $password = '') - { - if (!isset($secret)) { - throw new \RuntimeException('Private Key does not have a secret set'); - } - if (strlen($secret) != 32) { - throw new \RuntimeException('Private Key secret is not of the correct length'); - } - if (!empty($password) && is_string($password)) { - throw new UnsupportedFormatException('libsodium private keys do not support encryption'); - } - return $secret . $curve->encodePoint($publicKey); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/ASN1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/ASN1.php deleted file mode 100644 index d2a80a14..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/ASN1.php +++ /dev/null @@ -1,62 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\EC\Formats\Signature; - -use phpseclib3\File\ASN1 as Encoder; -use phpseclib3\File\ASN1\Maps\EcdsaSigValue; -use phpseclib3\Math\BigInteger; - -/** - * ASN1 Signature Handler - * - * @author Jim Wigginton - */ -abstract class ASN1 -{ - /** - * Loads a signature - * - * @param string $sig - * @return array - */ - public static function load($sig) - { - if (!is_string($sig)) { - return false; - } - - $decoded = Encoder::decodeBER($sig); - if (empty($decoded)) { - return false; - } - $components = Encoder::asn1map($decoded[0], EcdsaSigValue::MAP); - - return $components; - } - - /** - * Returns a signature in the appropriate format - * - * @param \phpseclib3\Math\BigInteger $r - * @param \phpseclib3\Math\BigInteger $s - * @return string - */ - public static function save(BigInteger $r, BigInteger $s) - { - return Encoder::encodeDER(compact('r', 's'), EcdsaSigValue::MAP); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/Raw.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/Raw.php deleted file mode 100644 index 7e4b47fe..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/Raw.php +++ /dev/null @@ -1,25 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\EC\Formats\Signature; - -use phpseclib3\Crypt\Common\Formats\Signature\Raw as Progenitor; - -/** - * Raw DSA Signature Handler - * - * @author Jim Wigginton - */ -abstract class Raw extends Progenitor -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/SSH2.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/SSH2.php deleted file mode 100644 index e0644421..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/SSH2.php +++ /dev/null @@ -1,94 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\EC\Formats\Signature; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Math\BigInteger; - -/** - * SSH2 Signature Handler - * - * @author Jim Wigginton - */ -abstract class SSH2 -{ - /** - * Loads a signature - * - * @param string $sig - * @return mixed - */ - public static function load($sig) - { - if (!is_string($sig)) { - return false; - } - - $result = Strings::unpackSSH2('ss', $sig); - if ($result === false) { - return false; - } - list($type, $blob) = $result; - switch ($type) { - // see https://tools.ietf.org/html/rfc5656#section-3.1.2 - case 'ecdsa-sha2-nistp256': - case 'ecdsa-sha2-nistp384': - case 'ecdsa-sha2-nistp521': - break; - default: - return false; - } - - $result = Strings::unpackSSH2('ii', $blob); - if ($result === false) { - return false; - } - - return [ - 'r' => $result[0], - 's' => $result[1] - ]; - } - - /** - * Returns a signature in the appropriate format - * - * @param \phpseclib3\Math\BigInteger $r - * @param \phpseclib3\Math\BigInteger $s - * @param string $curve - * @return string - */ - public static function save(BigInteger $r, BigInteger $s, $curve) - { - switch ($curve) { - case 'secp256r1': - $curve = 'nistp256'; - break; - case 'secp384r1': - $curve = 'nistp384'; - break; - case 'secp521r1': - $curve = 'nistp521'; - break; - default: - return false; - } - - $blob = Strings::packSSH2('ii', $r, $s); - - return Strings::packSSH2('ss', 'ecdsa-sha2-' . $curve, $blob); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Parameters.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Parameters.php deleted file mode 100644 index c0ed64a8..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Parameters.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\EC; - -use phpseclib3\Crypt\EC; - -/** - * EC Parameters - * - * @author Jim Wigginton - */ -final class Parameters extends EC -{ - /** - * Returns the parameters - * - * @param string $type - * @param array $options optional - * @return string - */ - public function toString($type = 'PKCS1', array $options = []) - { - $type = self::validatePlugin('Keys', 'PKCS1', 'saveParameters'); - - return $type::saveParameters($this->curve, $options); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PrivateKey.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PrivateKey.php deleted file mode 100644 index 462ea1a3..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PrivateKey.php +++ /dev/null @@ -1,256 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\EC; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\Common; -use phpseclib3\Crypt\EC; -use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve; -use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve; -use phpseclib3\Crypt\EC\Curves\Curve25519; -use phpseclib3\Crypt\EC\Curves\Ed25519; -use phpseclib3\Crypt\EC\Formats\Keys\PKCS1; -use phpseclib3\Crypt\EC\Formats\Signature\ASN1 as ASN1Signature; -use phpseclib3\Crypt\Hash; -use phpseclib3\Exception\UnsupportedOperationException; -use phpseclib3\Math\BigInteger; - -/** - * EC Private Key - * - * @author Jim Wigginton - */ -final class PrivateKey extends EC implements Common\PrivateKey -{ - use Common\Traits\PasswordProtected; - - /** - * Private Key dA - * - * sign() converts this to a BigInteger so one might wonder why this is a FiniteFieldInteger instead of - * a BigInteger. That's because a FiniteFieldInteger, when converted to a byte string, is null padded by - * a certain amount whereas a BigInteger isn't. - * - * @var object - */ - protected $dA; - - /** - * @var string - */ - protected $secret; - - /** - * Multiplies an encoded point by the private key - * - * Used by ECDH - * - * @param string $coordinates - * @return string - */ - public function multiply($coordinates) - { - if ($this->curve instanceof MontgomeryCurve) { - if ($this->curve instanceof Curve25519 && self::$engines['libsodium']) { - return sodium_crypto_scalarmult($this->dA->toBytes(), $coordinates); - } - - $point = [$this->curve->convertInteger(new BigInteger(strrev($coordinates), 256))]; - $point = $this->curve->multiplyPoint($point, $this->dA); - return strrev($point[0]->toBytes(true)); - } - if (!$this->curve instanceof TwistedEdwardsCurve) { - $coordinates = "\0$coordinates"; - } - $point = PKCS1::extractPoint($coordinates, $this->curve); - $point = $this->curve->multiplyPoint($point, $this->dA); - if ($this->curve instanceof TwistedEdwardsCurve) { - return $this->curve->encodePoint($point); - } - if (empty($point)) { - throw new \RuntimeException('The infinity point is invalid'); - } - return "\4" . $point[0]->toBytes(true) . $point[1]->toBytes(true); - } - - /** - * Create a signature - * - * @see self::verify() - * @param string $message - * @return mixed - */ - public function sign($message) - { - if ($this->curve instanceof MontgomeryCurve) { - throw new UnsupportedOperationException('Montgomery Curves cannot be used to create signatures'); - } - - $dA = $this->dA; - $order = $this->curve->getOrder(); - - $shortFormat = $this->shortFormat; - $format = $this->sigFormat; - if ($format === false) { - return false; - } - - if ($this->curve instanceof TwistedEdwardsCurve) { - if ($this->curve instanceof Ed25519 && self::$engines['libsodium'] && !isset($this->context)) { - $result = sodium_crypto_sign_detached($message, $this->withPassword()->toString('libsodium')); - return $shortFormat == 'SSH2' ? Strings::packSSH2('ss', 'ssh-' . strtolower($this->getCurve()), $result) : $result; - } - - // contexts (Ed25519ctx) are supported but prehashing (Ed25519ph) is not. - // quoting https://tools.ietf.org/html/rfc8032#section-8.5 , - // "The Ed25519ph and Ed448ph variants ... SHOULD NOT be used" - $A = $this->curve->encodePoint($this->QA); - $curve = $this->curve; - $hash = new Hash($curve::HASH); - - $secret = substr($hash->hash($this->secret), $curve::SIZE); - - if ($curve instanceof Ed25519) { - $dom = !isset($this->context) ? '' : - 'SigEd25519 no Ed25519 collisions' . "\0" . chr(strlen($this->context)) . $this->context; - } else { - $context = isset($this->context) ? $this->context : ''; - $dom = 'SigEd448' . "\0" . chr(strlen($context)) . $context; - } - // SHA-512(dom2(F, C) || prefix || PH(M)) - $r = $hash->hash($dom . $secret . $message); - $r = strrev($r); - $r = new BigInteger($r, 256); - list(, $r) = $r->divide($order); - $R = $curve->multiplyPoint($curve->getBasePoint(), $r); - $R = $curve->encodePoint($R); - $k = $hash->hash($dom . $R . $A . $message); - $k = strrev($k); - $k = new BigInteger($k, 256); - list(, $k) = $k->divide($order); - $S = $k->multiply($dA)->add($r); - list(, $S) = $S->divide($order); - $S = str_pad(strrev($S->toBytes()), $curve::SIZE, "\0"); - return $shortFormat == 'SSH2' ? Strings::packSSH2('ss', 'ssh-' . strtolower($this->getCurve()), $R . $S) : $R . $S; - } - - if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) { - $signature = ''; - // altho PHP's OpenSSL bindings only supported EC key creation in PHP 7.1 they've long - // supported signing / verification - // we use specified curves to avoid issues with OpenSSL possibly not supporting a given named curve; - // doing this may mean some curve-specific optimizations can't be used but idk if OpenSSL even - // has curve-specific optimizations - $result = openssl_sign($message, $signature, $this->toString('PKCS8', ['namedCurve' => false]), $this->hash->getHash()); - - if ($result) { - if ($shortFormat == 'ASN1') { - return $signature; - } - - extract(ASN1Signature::load($signature)); - - return $shortFormat == 'SSH2' ? $format::save($r, $s, $this->getCurve()) : $format::save($r, $s); - } - } - - $e = $this->hash->hash($message); - $e = new BigInteger($e, 256); - - $Ln = $this->hash->getLength() - $order->getLength(); - $z = $Ln > 0 ? $e->bitwise_rightShift($Ln) : $e; - - while (true) { - $k = BigInteger::randomRange(self::$one, $order->subtract(self::$one)); - list($x, $y) = $this->curve->multiplyPoint($this->curve->getBasePoint(), $k); - $x = $x->toBigInteger(); - list(, $r) = $x->divide($order); - if ($r->equals(self::$zero)) { - continue; - } - $kinv = $k->modInverse($order); - $temp = $z->add($dA->multiply($r)); - $temp = $kinv->multiply($temp); - list(, $s) = $temp->divide($order); - if (!$s->equals(self::$zero)) { - break; - } - } - - // the following is an RFC6979 compliant implementation of deterministic ECDSA - // it's unused because it's mainly intended for use when a good CSPRNG isn't - // available. if phpseclib's CSPRNG isn't good then even key generation is - // suspect - /* - // if this were actually being used it'd probably be better if this lived in load() and createKey() - $this->q = $this->curve->getOrder(); - $dA = $this->dA->toBigInteger(); - $this->x = $dA; - - $h1 = $this->hash->hash($message); - $k = $this->computek($h1); - list($x, $y) = $this->curve->multiplyPoint($this->curve->getBasePoint(), $k); - $x = $x->toBigInteger(); - list(, $r) = $x->divide($this->q); - $kinv = $k->modInverse($this->q); - $h1 = $this->bits2int($h1); - $temp = $h1->add($dA->multiply($r)); - $temp = $kinv->multiply($temp); - list(, $s) = $temp->divide($this->q); - */ - - return $shortFormat == 'SSH2' ? $format::save($r, $s, $this->getCurve()) : $format::save($r, $s); - } - - /** - * Returns the private key - * - * @param string $type - * @param array $options optional - * @return string - */ - public function toString($type, array $options = []) - { - $type = self::validatePlugin('Keys', $type, 'savePrivateKey'); - - return $type::savePrivateKey($this->dA, $this->curve, $this->QA, $this->secret, $this->password, $options); - } - - /** - * Returns the public key - * - * @see self::getPrivateKey() - * @return mixed - */ - public function getPublicKey() - { - $format = 'PKCS8'; - if ($this->curve instanceof MontgomeryCurve) { - $format = 'MontgomeryPublic'; - } - - $type = self::validatePlugin('Keys', $format, 'savePublicKey'); - - $key = $type::savePublicKey($this->curve, $this->QA); - $key = EC::loadFormat($format, $key); - if ($this->curve instanceof MontgomeryCurve) { - return $key; - } - $key = $key - ->withHash($this->hash->getHash()) - ->withSignatureFormat($this->shortFormat); - if ($this->curve instanceof TwistedEdwardsCurve) { - $key = $key->withContext($this->context); - } - return $key; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PublicKey.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PublicKey.php deleted file mode 100644 index 4558ce34..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PublicKey.php +++ /dev/null @@ -1,172 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\EC; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\Common; -use phpseclib3\Crypt\EC; -use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve; -use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve; -use phpseclib3\Crypt\EC\Curves\Ed25519; -use phpseclib3\Crypt\EC\Formats\Keys\PKCS1; -use phpseclib3\Crypt\EC\Formats\Signature\ASN1 as ASN1Signature; -use phpseclib3\Crypt\Hash; -use phpseclib3\Exception\UnsupportedOperationException; -use phpseclib3\Math\BigInteger; - -/** - * EC Public Key - * - * @author Jim Wigginton - */ -final class PublicKey extends EC implements Common\PublicKey -{ - use Common\Traits\Fingerprint; - - /** - * Verify a signature - * - * @see self::verify() - * @param string $message - * @param string $signature - * @return mixed - */ - public function verify($message, $signature) - { - if ($this->curve instanceof MontgomeryCurve) { - throw new UnsupportedOperationException('Montgomery Curves cannot be used to create signatures'); - } - - $shortFormat = $this->shortFormat; - $format = $this->sigFormat; - if ($format === false) { - return false; - } - - $order = $this->curve->getOrder(); - - if ($this->curve instanceof TwistedEdwardsCurve) { - if ($shortFormat == 'SSH2') { - list(, $signature) = Strings::unpackSSH2('ss', $signature); - } - - if ($this->curve instanceof Ed25519 && self::$engines['libsodium'] && !isset($this->context)) { - return sodium_crypto_sign_verify_detached($signature, $message, $this->toString('libsodium')); - } - - $curve = $this->curve; - if (strlen($signature) != 2 * $curve::SIZE) { - return false; - } - - $R = substr($signature, 0, $curve::SIZE); - $S = substr($signature, $curve::SIZE); - - try { - $R = PKCS1::extractPoint($R, $curve); - $R = $this->curve->convertToInternal($R); - } catch (\Exception $e) { - return false; - } - - $S = strrev($S); - $S = new BigInteger($S, 256); - - if ($S->compare($order) >= 0) { - return false; - } - - $A = $curve->encodePoint($this->QA); - - if ($curve instanceof Ed25519) { - $dom2 = !isset($this->context) ? '' : - 'SigEd25519 no Ed25519 collisions' . "\0" . chr(strlen($this->context)) . $this->context; - } else { - $context = isset($this->context) ? $this->context : ''; - $dom2 = 'SigEd448' . "\0" . chr(strlen($context)) . $context; - } - - $hash = new Hash($curve::HASH); - $k = $hash->hash($dom2 . substr($signature, 0, $curve::SIZE) . $A . $message); - $k = strrev($k); - $k = new BigInteger($k, 256); - list(, $k) = $k->divide($order); - - $qa = $curve->convertToInternal($this->QA); - - $lhs = $curve->multiplyPoint($curve->getBasePoint(), $S); - $rhs = $curve->multiplyPoint($qa, $k); - $rhs = $curve->addPoint($rhs, $R); - $rhs = $curve->convertToAffine($rhs); - - return $lhs[0]->equals($rhs[0]) && $lhs[1]->equals($rhs[1]); - } - - $params = $format::load($signature); - if ($params === false || count($params) != 2) { - return false; - } - extract($params); - - if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) { - $sig = $format != 'ASN1' ? ASN1Signature::save($r, $s) : $signature; - - $result = openssl_verify($message, $sig, $this->toString('PKCS8', ['namedCurve' => false]), $this->hash->getHash()); - - if ($result != -1) { - return (bool) $result; - } - } - - $n_1 = $order->subtract(self::$one); - if (!$r->between(self::$one, $n_1) || !$s->between(self::$one, $n_1)) { - return false; - } - - $e = $this->hash->hash($message); - $e = new BigInteger($e, 256); - - $Ln = $this->hash->getLength() - $order->getLength(); - $z = $Ln > 0 ? $e->bitwise_rightShift($Ln) : $e; - - $w = $s->modInverse($order); - list(, $u1) = $z->multiply($w)->divide($order); - list(, $u2) = $r->multiply($w)->divide($order); - - $u1 = $this->curve->convertInteger($u1); - $u2 = $this->curve->convertInteger($u2); - - list($x1, $y1) = $this->curve->multiplyAddPoints( - [$this->curve->getBasePoint(), $this->QA], - [$u1, $u2] - ); - - $x1 = $x1->toBigInteger(); - list(, $x1) = $x1->divide($order); - - return $x1->equals($r); - } - - /** - * Returns the public key - * - * @param string $type - * @param array $options optional - * @return string - */ - public function toString($type, array $options = []) - { - $type = self::validatePlugin('Keys', $type, 'savePublicKey'); - - return $type::savePublicKey($this->curve, $this->QA, $options); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Hash.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Hash.php deleted file mode 100644 index 0e02544e..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Hash.php +++ /dev/null @@ -1,1455 +0,0 @@ - - * setKey('abcdefg'); - * - * echo base64_encode($hash->hash('abcdefg')); - * ?> - * - * - * @author Jim Wigginton - * @copyright 2015 Jim Wigginton - * @author Andreas Fischer - * @copyright 2015 Andreas Fischer - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Exception\InsufficientSetupException; -use phpseclib3\Exception\UnsupportedAlgorithmException; -use phpseclib3\Math\BigInteger; -use phpseclib3\Math\PrimeField; - -/** - * @author Jim Wigginton - * @author Andreas Fischer - */ -class Hash -{ - /** - * Padding Types - * - */ - const PADDING_KECCAK = 1; - - /** - * Padding Types - * - */ - const PADDING_SHA3 = 2; - - /** - * Padding Types - * - */ - const PADDING_SHAKE = 3; - - /** - * Padding Type - * - * Only used by SHA3 - * - * @var int - */ - private $paddingType = 0; - - /** - * Hash Parameter - * - * @see self::setHash() - * @var int - */ - private $hashParam; - - /** - * Byte-length of hash output (Internal HMAC) - * - * @see self::setHash() - * @var int - */ - private $length; - - /** - * Hash Algorithm - * - * @see self::setHash() - * @var string - */ - private $algo; - - /** - * Key - * - * @see self::setKey() - * @var string - */ - private $key = false; - - /** - * Nonce - * - * @see self::setNonce() - * @var string - */ - private $nonce = false; - - /** - * Hash Parameters - * - * @var array - */ - private $parameters = []; - - /** - * Computed Key - * - * @see self::_computeKey() - * @var string - */ - private $computedKey = false; - - /** - * Outer XOR (Internal HMAC) - * - * Used only for sha512/* - * - * @see self::hash() - * @var string - */ - private $opad; - - /** - * Inner XOR (Internal HMAC) - * - * Used only for sha512/* - * - * @see self::hash() - * @var string - */ - private $ipad; - - /** - * Recompute AES Key - * - * Used only for umac - * - * @see self::hash() - * @var boolean - */ - private $recomputeAESKey; - - /** - * umac cipher object - * - * @see self::hash() - * @var \phpseclib3\Crypt\AES - */ - private $c; - - /** - * umac pad - * - * @see self::hash() - * @var string - */ - private $pad; - - /** - * Block Size - * - * @var int - */ - private $blockSize; - - /**#@+ - * UMAC variables - * - * @var PrimeField - */ - private static $factory36; - private static $factory64; - private static $factory128; - private static $offset64; - private static $offset128; - private static $marker64; - private static $marker128; - private static $maxwordrange64; - private static $maxwordrange128; - /**#@-*/ - - /** - * Default Constructor. - * - * @param string $hash - */ - public function __construct($hash = 'sha256') - { - $this->setHash($hash); - } - - /** - * Sets the key for HMACs - * - * Keys can be of any length. - * - * @param string $key - */ - public function setKey($key = false) - { - $this->key = $key; - $this->computeKey(); - $this->recomputeAESKey = true; - } - - /** - * Sets the nonce for UMACs - * - * Keys can be of any length. - * - * @param string $nonce - */ - public function setNonce($nonce = false) - { - switch (true) { - case !is_string($nonce): - case strlen($nonce) > 0 && strlen($nonce) <= 16: - $this->recomputeAESKey = true; - $this->nonce = $nonce; - return; - } - - throw new \LengthException('The nonce length must be between 1 and 16 bytes, inclusive'); - } - - /** - * Pre-compute the key used by the HMAC - * - * Quoting http://tools.ietf.org/html/rfc2104#section-2, "Applications that use keys longer than B bytes - * will first hash the key using H and then use the resultant L byte string as the actual key to HMAC." - * - * As documented in https://www.reddit.com/r/PHP/comments/9nct2l/symfonypolyfill_hash_pbkdf2_correct_fix_for/ - * when doing an HMAC multiple times it's faster to compute the hash once instead of computing it during - * every call - * - */ - private function computeKey() - { - if ($this->key === false) { - $this->computedKey = false; - return; - } - - if (strlen($this->key) <= $this->getBlockLengthInBytes()) { - $this->computedKey = $this->key; - return; - } - - $this->computedKey = is_array($this->algo) ? - call_user_func($this->algo, $this->key) : - hash($this->algo, $this->key, true); - } - - /** - * Gets the hash function. - * - * As set by the constructor or by the setHash() method. - * - * @return string - */ - public function getHash() - { - return $this->hashParam; - } - - /** - * Sets the hash function. - * - * @param string $hash - */ - public function setHash($hash) - { - $this->hashParam = $hash = strtolower($hash); - switch ($hash) { - case 'umac-32': - case 'umac-64': - case 'umac-96': - case 'umac-128': - $this->blockSize = 128; - $this->length = abs(substr($hash, -3)) >> 3; - $this->algo = 'umac'; - return; - case 'md2-96': - case 'md5-96': - case 'sha1-96': - case 'sha224-96': - case 'sha256-96': - case 'sha384-96': - case 'sha512-96': - case 'sha512/224-96': - case 'sha512/256-96': - $hash = substr($hash, 0, -3); - $this->length = 12; // 96 / 8 = 12 - break; - case 'md2': - case 'md5': - $this->length = 16; - break; - case 'sha1': - $this->length = 20; - break; - case 'sha224': - case 'sha512/224': - case 'sha3-224': - $this->length = 28; - break; - case 'keccak256': - $this->paddingType = self::PADDING_KECCAK; - // fall-through - case 'sha256': - case 'sha512/256': - case 'sha3-256': - $this->length = 32; - break; - case 'sha384': - case 'sha3-384': - $this->length = 48; - break; - case 'sha512': - case 'sha3-512': - $this->length = 64; - break; - default: - if (preg_match('#^(shake(?:128|256))-(\d+)$#', $hash, $matches)) { - $this->paddingType = self::PADDING_SHAKE; - $hash = $matches[1]; - $this->length = $matches[2] >> 3; - } else { - throw new UnsupportedAlgorithmException( - "$hash is not a supported algorithm" - ); - } - } - - switch ($hash) { - case 'md2': - case 'md2-96': - $this->blockSize = 128; - break; - case 'md5-96': - case 'sha1-96': - case 'sha224-96': - case 'sha256-96': - case 'md5': - case 'sha1': - case 'sha224': - case 'sha256': - $this->blockSize = 512; - break; - case 'sha3-224': - $this->blockSize = 1152; // 1600 - 2*224 - break; - case 'sha3-256': - case 'shake256': - case 'keccak256': - $this->blockSize = 1088; // 1600 - 2*256 - break; - case 'sha3-384': - $this->blockSize = 832; // 1600 - 2*384 - break; - case 'sha3-512': - $this->blockSize = 576; // 1600 - 2*512 - break; - case 'shake128': - $this->blockSize = 1344; // 1600 - 2*128 - break; - default: - $this->blockSize = 1024; - } - - if (in_array(substr($hash, 0, 5), ['sha3-', 'shake', 'kecca'])) { - // PHP 7.1.0 introduced support for "SHA3 fixed mode algorithms": - // http://php.net/ChangeLog-7.php#7.1.0 - if (version_compare(PHP_VERSION, '7.1.0') < 0 || substr($hash, 0, 5) != 'sha3-') { - //preg_match('#(\d+)$#', $hash, $matches); - //$this->parameters['capacity'] = 2 * $matches[1]; // 1600 - $this->blockSize - //$this->parameters['rate'] = 1600 - $this->parameters['capacity']; // == $this->blockSize - if (!$this->paddingType) { - $this->paddingType = self::PADDING_SHA3; - } - $this->parameters = [ - 'capacity' => 1600 - $this->blockSize, - 'rate' => $this->blockSize, - 'length' => $this->length, - 'padding' => $this->paddingType - ]; - $hash = ['phpseclib3\Crypt\Hash', PHP_INT_SIZE == 8 ? 'sha3_64' : 'sha3_32']; - } - } - - if ($hash == 'sha512/224' || $hash == 'sha512/256') { - // PHP 7.1.0 introduced sha512/224 and sha512/256 support: - // http://php.net/ChangeLog-7.php#7.1.0 - if (version_compare(PHP_VERSION, '7.1.0') < 0) { - // from http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf#page=24 - $initial = $hash == 'sha512/256' ? - [ - '22312194FC2BF72C', '9F555FA3C84C64C2', '2393B86B6F53B151', '963877195940EABD', - '96283EE2A88EFFE3', 'BE5E1E2553863992', '2B0199FC2C85B8AA', '0EB72DDC81C52CA2' - ] : - [ - '8C3D37C819544DA2', '73E1996689DCD4D6', '1DFAB7AE32FF9C82', '679DD514582F9FCF', - '0F6D2B697BD44DA8', '77E36F7304C48942', '3F9D85A86A1D36C8', '1112E6AD91D692A1' - ]; - for ($i = 0; $i < 8; $i++) { - $initial[$i] = new BigInteger($initial[$i], 16); - $initial[$i]->setPrecision(64); - } - - $this->parameters = compact('initial'); - - $hash = ['phpseclib3\Crypt\Hash', 'sha512']; - } - } - - if (is_array($hash)) { - $b = $this->blockSize >> 3; - $this->ipad = str_repeat(chr(0x36), $b); - $this->opad = str_repeat(chr(0x5C), $b); - } - - $this->algo = $hash; - - $this->computeKey(); - } - - /** - * KDF: Key-Derivation Function - * - * The key-derivation function generates pseudorandom bits used to key the hash functions. - * - * @param int $index a non-negative integer less than 2^64 - * @param int $numbytes a non-negative integer less than 2^64 - * @return string string of length numbytes bytes - */ - private function kdf($index, $numbytes) - { - $this->c->setIV(pack('N4', 0, $index, 0, 1)); - - return $this->c->encrypt(str_repeat("\0", $numbytes)); - } - - /** - * PDF Algorithm - * - * @return string string of length taglen bytes. - */ - private function pdf() - { - $k = $this->key; - $nonce = $this->nonce; - $taglen = $this->length; - - // - // Extract and zero low bit(s) of Nonce if needed - // - if ($taglen <= 8) { - $last = strlen($nonce) - 1; - $mask = $taglen == 4 ? "\3" : "\1"; - $index = $nonce[$last] & $mask; - $nonce[$last] = $nonce[$last] ^ $index; - } - - // - // Make Nonce BLOCKLEN bytes by appending zeroes if needed - // - $nonce = str_pad($nonce, 16, "\0"); - - // - // Generate subkey, encipher and extract indexed substring - // - $kp = $this->kdf(0, 16); - $c = new AES('ctr'); - $c->disablePadding(); - $c->setKey($kp); - $c->setIV($nonce); - $t = $c->encrypt("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); - - // we could use ord() but per https://paragonie.com/blog/2016/06/constant-time-encoding-boring-cryptography-rfc-4648-and-you - // unpack() doesn't leak timing info - return $taglen <= 8 ? - substr($t, unpack('C', $index)[1] * $taglen, $taglen) : - substr($t, 0, $taglen); - } - - /** - * UHASH Algorithm - * - * @param string $m string of length less than 2^67 bits. - * @param int $taglen the integer 4, 8, 12 or 16. - * @return string string of length taglen bytes. - */ - private function uhash($m, $taglen) - { - // - // One internal iteration per 4 bytes of output - // - $iters = $taglen >> 2; - - // - // Define total key needed for all iterations using KDF. - // L1Key reuses most key material between iterations. - // - //$L1Key = $this->kdf(1, 1024 + ($iters - 1) * 16); - $L1Key = $this->kdf(1, (1024 + ($iters - 1)) * 16); - $L2Key = $this->kdf(2, $iters * 24); - $L3Key1 = $this->kdf(3, $iters * 64); - $L3Key2 = $this->kdf(4, $iters * 4); - - // - // For each iteration, extract key and do three-layer hash. - // If bytelength(M) <= 1024, then skip L2-HASH. - // - $y = ''; - for ($i = 0; $i < $iters; $i++) { - $L1Key_i = substr($L1Key, $i * 16, 1024); - $L2Key_i = substr($L2Key, $i * 24, 24); - $L3Key1_i = substr($L3Key1, $i * 64, 64); - $L3Key2_i = substr($L3Key2, $i * 4, 4); - - $a = self::L1Hash($L1Key_i, $m); - $b = strlen($m) <= 1024 ? "\0\0\0\0\0\0\0\0$a" : self::L2Hash($L2Key_i, $a); - $c = self::L3Hash($L3Key1_i, $L3Key2_i, $b); - $y .= $c; - } - - return $y; - } - - /** - * L1-HASH Algorithm - * - * The first-layer hash breaks the message into 1024-byte chunks and - * hashes each with a function called NH. Concatenating the results - * forms a string, which is up to 128 times shorter than the original. - * - * @param string $k string of length 1024 bytes. - * @param string $m string of length less than 2^67 bits. - * @return string string of length (8 * ceil(bitlength(M)/8192)) bytes. - */ - private static function L1Hash($k, $m) - { - // - // Break M into 1024 byte chunks (final chunk may be shorter) - // - $m = str_split($m, 1024); - - // - // For each chunk, except the last: endian-adjust, NH hash - // and add bit-length. Use results to build Y. - // - $length = new BigInteger(1024 * 8); - $y = ''; - for ($i = 0; $i < count($m) - 1; $i++) { - $m[$i] = pack('N*', ...unpack('V*', $m[$i])); // ENDIAN-SWAP - $y .= static::nh($k, $m[$i], $length); - } - - // - // For the last chunk: pad to 32-byte boundary, endian-adjust, - // NH hash and add bit-length. Concatenate the result to Y. - // - $length = count($m) ? strlen($m[$i]) : 0; - $pad = 32 - ($length % 32); - $pad = max(32, $length + $pad % 32); - $m[$i] = str_pad(isset($m[$i]) ? $m[$i] : '', $pad, "\0"); // zeropad - $m[$i] = pack('N*', ...unpack('V*', $m[$i])); // ENDIAN-SWAP - - $y .= static::nh($k, $m[$i], new BigInteger($length * 8)); - - return $y; - } - - /** - * NH Algorithm - * - * @param string $k string of length 1024 bytes. - * @param string $m string with length divisible by 32 bytes. - * @return string string of length 8 bytes. - */ - private static function nh($k, $m, $length) - { - $toUInt32 = function ($x) { - $x = new BigInteger($x, 256); - $x->setPrecision(32); - return $x; - }; - - // - // Break M and K into 4-byte chunks - // - //$t = strlen($m) >> 2; - $m = str_split($m, 4); - $t = count($m); - $k = str_split($k, 4); - $k = array_pad(array_slice($k, 0, $t), $t, 0); - - $m = array_map($toUInt32, $m); - $k = array_map($toUInt32, $k); - - // - // Perform NH hash on the chunks, pairing words for multiplication - // which are 4 apart to accommodate vector-parallelism. - // - $y = new BigInteger(); - $y->setPrecision(64); - $i = 0; - while ($i < $t) { - $temp = $m[$i]->add($k[$i]); - $temp->setPrecision(64); - $temp = $temp->multiply($m[$i + 4]->add($k[$i + 4])); - $y = $y->add($temp); - - $temp = $m[$i + 1]->add($k[$i + 1]); - $temp->setPrecision(64); - $temp = $temp->multiply($m[$i + 5]->add($k[$i + 5])); - $y = $y->add($temp); - - $temp = $m[$i + 2]->add($k[$i + 2]); - $temp->setPrecision(64); - $temp = $temp->multiply($m[$i + 6]->add($k[$i + 6])); - $y = $y->add($temp); - - $temp = $m[$i + 3]->add($k[$i + 3]); - $temp->setPrecision(64); - $temp = $temp->multiply($m[$i + 7]->add($k[$i + 7])); - $y = $y->add($temp); - - $i += 8; - } - - return $y->add($length)->toBytes(); - } - - /** - * L2-HASH: Second-Layer Hash - * - * The second-layer rehashes the L1-HASH output using a polynomial hash - * called POLY. If the L1-HASH output is long, then POLY is called once - * on a prefix of the L1-HASH output and called using different settings - * on the remainder. (This two-step hashing of the L1-HASH output is - * needed only if the message length is greater than 16 megabytes.) - * Careful implementation of POLY is necessary to avoid a possible - * timing attack (see Section 6.6 for more information). - * - * @param string $k string of length 24 bytes. - * @param string $m string of length less than 2^64 bytes. - * @return string string of length 16 bytes. - */ - private static function L2Hash($k, $m) - { - // - // Extract keys and restrict to special key-sets - // - $k64 = $k & "\x01\xFF\xFF\xFF\x01\xFF\xFF\xFF"; - $k64 = new BigInteger($k64, 256); - $k128 = substr($k, 8) & "\x01\xFF\xFF\xFF\x01\xFF\xFF\xFF\x01\xFF\xFF\xFF\x01\xFF\xFF\xFF"; - $k128 = new BigInteger($k128, 256); - - // - // If M is no more than 2^17 bytes, hash under 64-bit prime, - // otherwise, hash first 2^17 bytes under 64-bit prime and - // remainder under 128-bit prime. - // - if (strlen($m) <= 0x20000) { // 2^14 64-bit words - $y = self::poly(64, self::$maxwordrange64, $k64, $m); - } else { - $m_1 = substr($m, 0, 0x20000); // 1 << 17 - $m_2 = substr($m, 0x20000) . "\x80"; - $length = strlen($m_2); - $pad = 16 - ($length % 16); - $pad %= 16; - $m_2 = str_pad($m_2, $length + $pad, "\0"); // zeropad - $y = self::poly(64, self::$maxwordrange64, $k64, $m_1); - $y = str_pad($y, 16, "\0", STR_PAD_LEFT); - $y = self::poly(128, self::$maxwordrange128, $k128, $y . $m_2); - } - - return str_pad($y, 16, "\0", STR_PAD_LEFT); - } - - /** - * POLY Algorithm - * - * @param int $wordbits the integer 64 or 128. - * @param BigInteger $maxwordrange positive integer less than 2^wordbits. - * @param BigInteger $k integer in the range 0 ... prime(wordbits) - 1. - * @param string $m string with length divisible by (wordbits / 8) bytes. - * @return integer in the range 0 ... prime(wordbits) - 1. - */ - private static function poly($wordbits, $maxwordrange, $k, $m) - { - // - // Define constants used for fixing out-of-range words - // - $wordbytes = $wordbits >> 3; - if ($wordbits == 128) { - $factory = self::$factory128; - $offset = self::$offset128; - $marker = self::$marker128; - } else { - $factory = self::$factory64; - $offset = self::$offset64; - $marker = self::$marker64; - } - - $k = $factory->newInteger($k); - - // - // Break M into chunks of length wordbytes bytes - // - $m_i = str_split($m, $wordbytes); - - // - // Each input word m is compared with maxwordrange. If not smaller - // then 'marker' and (m - offset), both in range, are hashed. - // - $y = $factory->newInteger(new BigInteger(1)); - foreach ($m_i as $m) { - $m = $factory->newInteger(new BigInteger($m, 256)); - if ($m->compare($maxwordrange) >= 0) { - $y = $k->multiply($y)->add($marker); - $y = $k->multiply($y)->add($m->subtract($offset)); - } else { - $y = $k->multiply($y)->add($m); - } - } - - return $y->toBytes(); - } - - /** - * L3-HASH: Third-Layer Hash - * - * The output from L2-HASH is 16 bytes long. This final hash function - * hashes the 16-byte string to a fixed length of 4 bytes. - * - * @param string $k1 string of length 64 bytes. - * @param string $k2 string of length 4 bytes. - * @param string $m string of length 16 bytes. - * @return string string of length 4 bytes. - */ - private static function L3Hash($k1, $k2, $m) - { - $factory = self::$factory36; - - $y = $factory->newInteger(new BigInteger()); - for ($i = 0; $i < 8; $i++) { - $m_i = $factory->newInteger(new BigInteger(substr($m, 2 * $i, 2), 256)); - $k_i = $factory->newInteger(new BigInteger(substr($k1, 8 * $i, 8), 256)); - $y = $y->add($m_i->multiply($k_i)); - } - $y = str_pad(substr($y->toBytes(), -4), 4, "\0", STR_PAD_LEFT); - $y = $y ^ $k2; - - return $y; - } - - /** - * Compute the Hash / HMAC / UMAC. - * - * @param string $text - * @return string - */ - public function hash($text) - { - $algo = $this->algo; - if ($algo == 'umac') { - if ($this->recomputeAESKey) { - if (!is_string($this->nonce)) { - throw new InsufficientSetupException('No nonce has been set'); - } - if (!is_string($this->key)) { - throw new InsufficientSetupException('No key has been set'); - } - if (strlen($this->key) != 16) { - throw new \LengthException('Key must be 16 bytes long'); - } - - if (!isset(self::$maxwordrange64)) { - $one = new BigInteger(1); - - $prime36 = new BigInteger("\x00\x00\x00\x0F\xFF\xFF\xFF\xFB", 256); - self::$factory36 = new PrimeField($prime36); - - $prime64 = new BigInteger("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xC5", 256); - self::$factory64 = new PrimeField($prime64); - - $prime128 = new BigInteger("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x61", 256); - self::$factory128 = new PrimeField($prime128); - - self::$offset64 = new BigInteger("\1\0\0\0\0\0\0\0\0", 256); - self::$offset64 = self::$factory64->newInteger(self::$offset64->subtract($prime64)); - self::$offset128 = new BigInteger("\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 256); - self::$offset128 = self::$factory128->newInteger(self::$offset128->subtract($prime128)); - - self::$marker64 = self::$factory64->newInteger($prime64->subtract($one)); - self::$marker128 = self::$factory128->newInteger($prime128->subtract($one)); - - $maxwordrange64 = $one->bitwise_leftShift(64)->subtract($one->bitwise_leftShift(32)); - self::$maxwordrange64 = self::$factory64->newInteger($maxwordrange64); - - $maxwordrange128 = $one->bitwise_leftShift(128)->subtract($one->bitwise_leftShift(96)); - self::$maxwordrange128 = self::$factory128->newInteger($maxwordrange128); - } - - $this->c = new AES('ctr'); - $this->c->disablePadding(); - $this->c->setKey($this->key); - - $this->pad = $this->pdf(); - - $this->recomputeAESKey = false; - } - - $hashedmessage = $this->uhash($text, $this->length); - return $hashedmessage ^ $this->pad; - } - - if (is_array($algo)) { - if (empty($this->key) || !is_string($this->key)) { - return substr($algo($text, ...array_values($this->parameters)), 0, $this->length); - } - - // SHA3 HMACs are discussed at https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf#page=30 - - $key = str_pad($this->computedKey, $b, chr(0)); - $temp = $this->ipad ^ $key; - $temp .= $text; - $temp = substr($algo($temp, ...array_values($this->parameters)), 0, $this->length); - $output = $this->opad ^ $key; - $output .= $temp; - $output = $algo($output, ...array_values($this->parameters)); - - return substr($output, 0, $this->length); - } - - $output = !empty($this->key) || is_string($this->key) ? - hash_hmac($algo, $text, $this->computedKey, true) : - hash($algo, $text, true); - - return strlen($output) > $this->length - ? substr($output, 0, $this->length) - : $output; - } - - /** - * Returns the hash length (in bits) - * - * @return int - */ - public function getLength() - { - return $this->length << 3; - } - - /** - * Returns the hash length (in bytes) - * - * @return int - */ - public function getLengthInBytes() - { - return $this->length; - } - - /** - * Returns the block length (in bits) - * - * @return int - */ - public function getBlockLength() - { - return $this->blockSize; - } - - /** - * Returns the block length (in bytes) - * - * @return int - */ - public function getBlockLengthInBytes() - { - return $this->blockSize >> 3; - } - - /** - * Pads SHA3 based on the mode - * - * @param int $padLength - * @param int $padType - * @return string - */ - private static function sha3_pad($padLength, $padType) - { - switch ($padType) { - case self::PADDING_KECCAK: - $temp = chr(0x01) . str_repeat("\0", $padLength - 1); - $temp[$padLength - 1] = $temp[$padLength - 1] | chr(0x80); - return $temp; - case self::PADDING_SHAKE: - $temp = chr(0x1F) . str_repeat("\0", $padLength - 1); - $temp[$padLength - 1] = $temp[$padLength - 1] | chr(0x80); - return $temp; - //case self::PADDING_SHA3: - default: - // from https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf#page=36 - return $padLength == 1 ? chr(0x86) : chr(0x06) . str_repeat("\0", $padLength - 2) . chr(0x80); - } - } - - /** - * Pure-PHP 32-bit implementation of SHA3 - * - * Whereas BigInteger.php's 32-bit engine works on PHP 64-bit this 32-bit implementation - * of SHA3 will *not* work on PHP 64-bit. This is because this implementation - * employees bitwise NOTs and bitwise left shifts. And the round constants only work - * on 32-bit PHP. eg. dechex(-2147483648) returns 80000000 on 32-bit PHP and - * FFFFFFFF80000000 on 64-bit PHP. Sure, we could do bitwise ANDs but that would slow - * things down. - * - * SHA512 requires BigInteger to simulate 64-bit unsigned integers because SHA2 employees - * addition whereas SHA3 just employees bitwise operators. PHP64 only supports signed - * 64-bit integers, which complicates addition, whereas that limitation isn't an issue - * for SHA3. - * - * In https://ws680.nist.gov/publication/get_pdf.cfm?pub_id=919061#page=16 KECCAK[C] is - * defined as "the KECCAK instance with KECCAK-f[1600] as the underlying permutation and - * capacity c". This is relevant because, altho the KECCAK standard defines a mode - * (KECCAK-f[800]) designed for 32-bit machines that mode is incompatible with SHA3 - * - * @param string $p - * @param int $c - * @param int $r - * @param int $d - * @param int $padType - */ - private static function sha3_32($p, $c, $r, $d, $padType) - { - $block_size = $r >> 3; - $padLength = $block_size - (strlen($p) % $block_size); - $num_ints = $block_size >> 2; - - $p .= static::sha3_pad($padLength, $padType); - - $n = strlen($p) / $r; // number of blocks - - $s = [ - [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]], - [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]], - [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]], - [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]], - [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]] - ]; - - $p = str_split($p, $block_size); - - foreach ($p as $pi) { - $pi = unpack('V*', $pi); - $x = $y = 0; - for ($i = 1; $i <= $num_ints; $i += 2) { - $s[$x][$y][0] ^= $pi[$i + 1]; - $s[$x][$y][1] ^= $pi[$i]; - if (++$y == 5) { - $y = 0; - $x++; - } - } - static::processSHA3Block32($s); - } - - $z = ''; - $i = $j = 0; - while (strlen($z) < $d) { - $z .= pack('V2', $s[$i][$j][1], $s[$i][$j++][0]); - if ($j == 5) { - $j = 0; - $i++; - if ($i == 5) { - $i = 0; - static::processSHA3Block32($s); - } - } - } - - return $z; - } - - /** - * 32-bit block processing method for SHA3 - * - * @param array $s - */ - private static function processSHA3Block32(&$s) - { - static $rotationOffsets = [ - [ 0, 1, 62, 28, 27], - [36, 44, 6, 55, 20], - [ 3, 10, 43, 25, 39], - [41, 45, 15, 21, 8], - [18, 2, 61, 56, 14] - ]; - - // the standards give these constants in hexadecimal notation. it's tempting to want to use - // that same notation, here, however, we can't, because 0x80000000, on PHP32, is a positive - // float - not the negative int that we need to be in PHP32. so we use -2147483648 instead - static $roundConstants = [ - [0, 1], - [0, 32898], - [-2147483648, 32906], - [-2147483648, -2147450880], - [0, 32907], - [0, -2147483647], - [-2147483648, -2147450751], - [-2147483648, 32777], - [0, 138], - [0, 136], - [0, -2147450871], - [0, -2147483638], - [0, -2147450741], - [-2147483648, 139], - [-2147483648, 32905], - [-2147483648, 32771], - [-2147483648, 32770], - [-2147483648, 128], - [0, 32778], - [-2147483648, -2147483638], - [-2147483648, -2147450751], - [-2147483648, 32896], - [0, -2147483647], - [-2147483648, -2147450872] - ]; - - for ($round = 0; $round < 24; $round++) { - // theta step - $parity = $rotated = []; - for ($i = 0; $i < 5; $i++) { - $parity[] = [ - $s[0][$i][0] ^ $s[1][$i][0] ^ $s[2][$i][0] ^ $s[3][$i][0] ^ $s[4][$i][0], - $s[0][$i][1] ^ $s[1][$i][1] ^ $s[2][$i][1] ^ $s[3][$i][1] ^ $s[4][$i][1] - ]; - $rotated[] = static::rotateLeft32($parity[$i], 1); - } - - $temp = [ - [$parity[4][0] ^ $rotated[1][0], $parity[4][1] ^ $rotated[1][1]], - [$parity[0][0] ^ $rotated[2][0], $parity[0][1] ^ $rotated[2][1]], - [$parity[1][0] ^ $rotated[3][0], $parity[1][1] ^ $rotated[3][1]], - [$parity[2][0] ^ $rotated[4][0], $parity[2][1] ^ $rotated[4][1]], - [$parity[3][0] ^ $rotated[0][0], $parity[3][1] ^ $rotated[0][1]] - ]; - for ($i = 0; $i < 5; $i++) { - for ($j = 0; $j < 5; $j++) { - $s[$i][$j][0] ^= $temp[$j][0]; - $s[$i][$j][1] ^= $temp[$j][1]; - } - } - - $st = $s; - - // rho and pi steps - for ($i = 0; $i < 5; $i++) { - for ($j = 0; $j < 5; $j++) { - $st[(2 * $i + 3 * $j) % 5][$j] = static::rotateLeft32($s[$j][$i], $rotationOffsets[$j][$i]); - } - } - - // chi step - for ($i = 0; $i < 5; $i++) { - $s[$i][0] = [ - $st[$i][0][0] ^ (~$st[$i][1][0] & $st[$i][2][0]), - $st[$i][0][1] ^ (~$st[$i][1][1] & $st[$i][2][1]) - ]; - $s[$i][1] = [ - $st[$i][1][0] ^ (~$st[$i][2][0] & $st[$i][3][0]), - $st[$i][1][1] ^ (~$st[$i][2][1] & $st[$i][3][1]) - ]; - $s[$i][2] = [ - $st[$i][2][0] ^ (~$st[$i][3][0] & $st[$i][4][0]), - $st[$i][2][1] ^ (~$st[$i][3][1] & $st[$i][4][1]) - ]; - $s[$i][3] = [ - $st[$i][3][0] ^ (~$st[$i][4][0] & $st[$i][0][0]), - $st[$i][3][1] ^ (~$st[$i][4][1] & $st[$i][0][1]) - ]; - $s[$i][4] = [ - $st[$i][4][0] ^ (~$st[$i][0][0] & $st[$i][1][0]), - $st[$i][4][1] ^ (~$st[$i][0][1] & $st[$i][1][1]) - ]; - } - - // iota step - $s[0][0][0] ^= $roundConstants[$round][0]; - $s[0][0][1] ^= $roundConstants[$round][1]; - } - } - - /** - * Rotate 32-bit int - * - * @param array $x - * @param int $shift - */ - private static function rotateLeft32($x, $shift) - { - if ($shift < 32) { - list($hi, $lo) = $x; - } else { - $shift -= 32; - list($lo, $hi) = $x; - } - - return [ - ($hi << $shift) | (($lo >> (32 - $shift)) & (1 << $shift) - 1), - ($lo << $shift) | (($hi >> (32 - $shift)) & (1 << $shift) - 1) - ]; - } - - /** - * Pure-PHP 64-bit implementation of SHA3 - * - * @param string $p - * @param int $c - * @param int $r - * @param int $d - * @param int $padType - */ - private static function sha3_64($p, $c, $r, $d, $padType) - { - $block_size = $r >> 3; - $padLength = $block_size - (strlen($p) % $block_size); - $num_ints = $block_size >> 2; - - $p .= static::sha3_pad($padLength, $padType); - - $n = strlen($p) / $r; // number of blocks - - $s = [ - [0, 0, 0, 0, 0], - [0, 0, 0, 0, 0], - [0, 0, 0, 0, 0], - [0, 0, 0, 0, 0], - [0, 0, 0, 0, 0] - ]; - - $p = str_split($p, $block_size); - - foreach ($p as $pi) { - $pi = unpack('P*', $pi); - $x = $y = 0; - foreach ($pi as $subpi) { - $s[$x][$y++] ^= $subpi; - if ($y == 5) { - $y = 0; - $x++; - } - } - static::processSHA3Block64($s); - } - - $z = ''; - $i = $j = 0; - while (strlen($z) < $d) { - $z .= pack('P', $s[$i][$j++]); - if ($j == 5) { - $j = 0; - $i++; - if ($i == 5) { - $i = 0; - static::processSHA3Block64($s); - } - } - } - - return $z; - } - - /** - * 64-bit block processing method for SHA3 - * - * @param array $s - */ - private static function processSHA3Block64(&$s) - { - static $rotationOffsets = [ - [ 0, 1, 62, 28, 27], - [36, 44, 6, 55, 20], - [ 3, 10, 43, 25, 39], - [41, 45, 15, 21, 8], - [18, 2, 61, 56, 14] - ]; - - static $roundConstants = [ - 1, - 32898, - -9223372036854742902, - -9223372034707259392, - 32907, - 2147483649, - -9223372034707259263, - -9223372036854743031, - 138, - 136, - 2147516425, - 2147483658, - 2147516555, - -9223372036854775669, - -9223372036854742903, - -9223372036854743037, - -9223372036854743038, - -9223372036854775680, - 32778, - -9223372034707292150, - -9223372034707259263, - -9223372036854742912, - 2147483649, - -9223372034707259384 - ]; - - for ($round = 0; $round < 24; $round++) { - // theta step - $parity = []; - for ($i = 0; $i < 5; $i++) { - $parity[] = $s[0][$i] ^ $s[1][$i] ^ $s[2][$i] ^ $s[3][$i] ^ $s[4][$i]; - } - $temp = [ - $parity[4] ^ static::rotateLeft64($parity[1], 1), - $parity[0] ^ static::rotateLeft64($parity[2], 1), - $parity[1] ^ static::rotateLeft64($parity[3], 1), - $parity[2] ^ static::rotateLeft64($parity[4], 1), - $parity[3] ^ static::rotateLeft64($parity[0], 1) - ]; - for ($i = 0; $i < 5; $i++) { - for ($j = 0; $j < 5; $j++) { - $s[$i][$j] ^= $temp[$j]; - } - } - - $st = $s; - - // rho and pi steps - for ($i = 0; $i < 5; $i++) { - for ($j = 0; $j < 5; $j++) { - $st[(2 * $i + 3 * $j) % 5][$j] = static::rotateLeft64($s[$j][$i], $rotationOffsets[$j][$i]); - } - } - - // chi step - for ($i = 0; $i < 5; $i++) { - $s[$i] = [ - $st[$i][0] ^ (~$st[$i][1] & $st[$i][2]), - $st[$i][1] ^ (~$st[$i][2] & $st[$i][3]), - $st[$i][2] ^ (~$st[$i][3] & $st[$i][4]), - $st[$i][3] ^ (~$st[$i][4] & $st[$i][0]), - $st[$i][4] ^ (~$st[$i][0] & $st[$i][1]) - ]; - } - - // iota step - $s[0][0] ^= $roundConstants[$round]; - } - } - - /** - * Rotate 64-bit int - * - * @param int $x - * @param int $shift - */ - private static function rotateLeft64($x, $shift) - { - return ($x << $shift) | (($x >> (64 - $shift)) & ((1 << $shift) - 1)); - } - - /** - * Pure-PHP implementation of SHA512 - * - * @param string $m - * @param array $hash - * @return string - */ - private static function sha512($m, $hash) - { - static $k; - - if (!isset($k)) { - // Initialize table of round constants - // (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409) - $k = [ - '428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc', - '3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118', - 'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2', - '72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694', - 'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65', - '2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5', - '983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4', - 'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70', - '27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df', - '650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b', - 'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30', - 'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8', - '19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8', - '391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3', - '748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec', - '90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b', - 'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178', - '06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b', - '28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c', - '4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817' - ]; - - for ($i = 0; $i < 80; $i++) { - $k[$i] = new BigInteger($k[$i], 16); - } - } - - // Pre-processing - $length = strlen($m); - // to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128 - $m .= str_repeat(chr(0), 128 - (($length + 16) & 0x7F)); - $m[$length] = chr(0x80); - // we don't support hashing strings 512MB long - $m .= pack('N4', 0, 0, 0, $length << 3); - - // Process the message in successive 1024-bit chunks - $chunks = str_split($m, 128); - foreach ($chunks as $chunk) { - $w = []; - for ($i = 0; $i < 16; $i++) { - $temp = new BigInteger(Strings::shift($chunk, 8), 256); - $temp->setPrecision(64); - $w[] = $temp; - } - - // Extend the sixteen 32-bit words into eighty 32-bit words - for ($i = 16; $i < 80; $i++) { - $temp = [ - $w[$i - 15]->bitwise_rightRotate(1), - $w[$i - 15]->bitwise_rightRotate(8), - $w[$i - 15]->bitwise_rightShift(7) - ]; - $s0 = $temp[0]->bitwise_xor($temp[1]); - $s0 = $s0->bitwise_xor($temp[2]); - $temp = [ - $w[$i - 2]->bitwise_rightRotate(19), - $w[$i - 2]->bitwise_rightRotate(61), - $w[$i - 2]->bitwise_rightShift(6) - ]; - $s1 = $temp[0]->bitwise_xor($temp[1]); - $s1 = $s1->bitwise_xor($temp[2]); - $w[$i] = clone $w[$i - 16]; - $w[$i] = $w[$i]->add($s0); - $w[$i] = $w[$i]->add($w[$i - 7]); - $w[$i] = $w[$i]->add($s1); - } - - // Initialize hash value for this chunk - $a = clone $hash[0]; - $b = clone $hash[1]; - $c = clone $hash[2]; - $d = clone $hash[3]; - $e = clone $hash[4]; - $f = clone $hash[5]; - $g = clone $hash[6]; - $h = clone $hash[7]; - - // Main loop - for ($i = 0; $i < 80; $i++) { - $temp = [ - $a->bitwise_rightRotate(28), - $a->bitwise_rightRotate(34), - $a->bitwise_rightRotate(39) - ]; - $s0 = $temp[0]->bitwise_xor($temp[1]); - $s0 = $s0->bitwise_xor($temp[2]); - $temp = [ - $a->bitwise_and($b), - $a->bitwise_and($c), - $b->bitwise_and($c) - ]; - $maj = $temp[0]->bitwise_xor($temp[1]); - $maj = $maj->bitwise_xor($temp[2]); - $t2 = $s0->add($maj); - - $temp = [ - $e->bitwise_rightRotate(14), - $e->bitwise_rightRotate(18), - $e->bitwise_rightRotate(41) - ]; - $s1 = $temp[0]->bitwise_xor($temp[1]); - $s1 = $s1->bitwise_xor($temp[2]); - $temp = [ - $e->bitwise_and($f), - $g->bitwise_and($e->bitwise_not()) - ]; - $ch = $temp[0]->bitwise_xor($temp[1]); - $t1 = $h->add($s1); - $t1 = $t1->add($ch); - $t1 = $t1->add($k[$i]); - $t1 = $t1->add($w[$i]); - - $h = clone $g; - $g = clone $f; - $f = clone $e; - $e = $d->add($t1); - $d = clone $c; - $c = clone $b; - $b = clone $a; - $a = $t1->add($t2); - } - - // Add this chunk's hash to result so far - $hash = [ - $hash[0]->add($a), - $hash[1]->add($b), - $hash[2]->add($c), - $hash[3]->add($d), - $hash[4]->add($e), - $hash[5]->add($f), - $hash[6]->add($g), - $hash[7]->add($h) - ]; - } - - // Produce the final hash value (big-endian) - // (\phpseclib3\Crypt\Hash::hash() trims the output for hashes but not for HMACs. as such, we trim the output here) - $temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() . - $hash[4]->toBytes() . $hash[5]->toBytes() . $hash[6]->toBytes() . $hash[7]->toBytes(); - - return $temp; - } - - /** - * __toString() magic method - */ - public function __toString() - { - return $this->getHash(); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/PublicKeyLoader.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/PublicKeyLoader.php deleted file mode 100644 index 61afbaeb..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/PublicKeyLoader.php +++ /dev/null @@ -1,111 +0,0 @@ - - * @copyright 2009 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt; - -use phpseclib3\Crypt\Common\AsymmetricKey; -use phpseclib3\Crypt\Common\PrivateKey; -use phpseclib3\Crypt\Common\PublicKey; -use phpseclib3\Exception\NoKeyLoadedException; -use phpseclib3\File\X509; - -/** - * PublicKeyLoader - * - * @author Jim Wigginton - */ -abstract class PublicKeyLoader -{ - /** - * Loads a public or private key - * - * @return AsymmetricKey - * @param string|array $key - * @param string $password optional - */ - public static function load($key, $password = false) - { - try { - return EC::load($key, $password); - } catch (NoKeyLoadedException $e) { - } - - try { - return RSA::load($key, $password); - } catch (NoKeyLoadedException $e) { - } - - try { - return DSA::load($key, $password); - } catch (NoKeyLoadedException $e) { - } - - try { - $x509 = new X509(); - $x509->loadX509($key); - $key = $x509->getPublicKey(); - if ($key) { - return $key; - } - } catch (\Exception $e) { - } - - throw new NoKeyLoadedException('Unable to read key'); - } - - /** - * Loads a private key - * - * @return PrivateKey - * @param string|array $key - * @param string $password optional - */ - public static function loadPrivateKey($key, $password = false) - { - $key = self::load($key, $password); - if (!$key instanceof PrivateKey) { - throw new NoKeyLoadedException('The key that was loaded was not a private key'); - } - return $key; - } - - /** - * Loads a public key - * - * @return PublicKey - * @param string|array $key - */ - public static function loadPublicKey($key) - { - $key = self::load($key); - if (!$key instanceof PublicKey) { - throw new NoKeyLoadedException('The key that was loaded was not a public key'); - } - return $key; - } - - /** - * Loads parameters - * - * @return AsymmetricKey - * @param string|array $key - */ - public static function loadParameters($key) - { - $key = self::load($key); - if (!$key instanceof PrivateKey && !$key instanceof PublicKey) { - throw new NoKeyLoadedException('The key that was loaded was not a parameter'); - } - return $key; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RC2.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RC2.php deleted file mode 100644 index 654c9064..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RC2.php +++ /dev/null @@ -1,640 +0,0 @@ - - * setKey('abcdefgh'); - * - * $plaintext = str_repeat('a', 1024); - * - * echo $rc2->decrypt($rc2->encrypt($plaintext)); - * ?> - * - * - * @author Patrick Monnerat - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt; - -use phpseclib3\Crypt\Common\BlockCipher; -use phpseclib3\Exception\BadModeException; - -/** - * Pure-PHP implementation of RC2. - * - */ -class RC2 extends BlockCipher -{ - /** - * Block Length of the cipher - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::block_size - * @var int - */ - protected $block_size = 8; - - /** - * The Key - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::key - * @see self::setKey() - * @var string - */ - protected $key; - - /** - * The Original (unpadded) Key - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::key - * @see self::setKey() - * @see self::encrypt() - * @see self::decrypt() - * @var string - */ - private $orig_key; - - /** - * Key Length (in bytes) - * - * @see \phpseclib3\Crypt\RC2::setKeyLength() - * @var int - */ - protected $key_length = 16; // = 128 bits - - /** - * The mcrypt specific name of the cipher - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt - * @var string - */ - protected $cipher_name_mcrypt = 'rc2'; - - /** - * Optimizing value while CFB-encrypting - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len - * @var int - */ - protected $cfb_init_len = 500; - - /** - * The key length in bits. - * - * {@internal Should be in range [1..1024].} - * - * {@internal Changing this value after setting the key has no effect.} - * - * @see self::setKeyLength() - * @see self::setKey() - * @var int - */ - private $default_key_length = 1024; - - /** - * The key length in bits. - * - * {@internal Should be in range [1..1024].} - * - * @see self::isValidEnine() - * @see self::setKey() - * @var int - */ - private $current_key_length; - - /** - * The Key Schedule - * - * @see self::setupKey() - * @var array - */ - private $keys; - - /** - * Key expansion randomization table. - * Twice the same 256-value sequence to save a modulus in key expansion. - * - * @see self::setKey() - * @var array - */ - private static $pitable = [ - 0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED, - 0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D, - 0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E, - 0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2, - 0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13, - 0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32, - 0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B, - 0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82, - 0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C, - 0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC, - 0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1, - 0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26, - 0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57, - 0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03, - 0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7, - 0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7, - 0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7, - 0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A, - 0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74, - 0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC, - 0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC, - 0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39, - 0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A, - 0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31, - 0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE, - 0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9, - 0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C, - 0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9, - 0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0, - 0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E, - 0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77, - 0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD, - 0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED, - 0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D, - 0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E, - 0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2, - 0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13, - 0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32, - 0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B, - 0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82, - 0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C, - 0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC, - 0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1, - 0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26, - 0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57, - 0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03, - 0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7, - 0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7, - 0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7, - 0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A, - 0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74, - 0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC, - 0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC, - 0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39, - 0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A, - 0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31, - 0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE, - 0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9, - 0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C, - 0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9, - 0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0, - 0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E, - 0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77, - 0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD - ]; - - /** - * Inverse key expansion randomization table. - * - * @see self::setKey() - * @var array - */ - private static $invpitable = [ - 0xD1, 0xDA, 0xB9, 0x6F, 0x9C, 0xC8, 0x78, 0x66, - 0x80, 0x2C, 0xF8, 0x37, 0xEA, 0xE0, 0x62, 0xA4, - 0xCB, 0x71, 0x50, 0x27, 0x4B, 0x95, 0xD9, 0x20, - 0x9D, 0x04, 0x91, 0xE3, 0x47, 0x6A, 0x7E, 0x53, - 0xFA, 0x3A, 0x3B, 0xB4, 0xA8, 0xBC, 0x5F, 0x68, - 0x08, 0xCA, 0x8F, 0x14, 0xD7, 0xC0, 0xEF, 0x7B, - 0x5B, 0xBF, 0x2F, 0xE5, 0xE2, 0x8C, 0xBA, 0x12, - 0xE1, 0xAF, 0xB2, 0x54, 0x5D, 0x59, 0x76, 0xDB, - 0x32, 0xA2, 0x58, 0x6E, 0x1C, 0x29, 0x64, 0xF3, - 0xE9, 0x96, 0x0C, 0x98, 0x19, 0x8D, 0x3E, 0x26, - 0xAB, 0xA5, 0x85, 0x16, 0x40, 0xBD, 0x49, 0x67, - 0xDC, 0x22, 0x94, 0xBB, 0x3C, 0xC1, 0x9B, 0xEB, - 0x45, 0x28, 0x18, 0xD8, 0x1A, 0x42, 0x7D, 0xCC, - 0xFB, 0x65, 0x8E, 0x3D, 0xCD, 0x2A, 0xA3, 0x60, - 0xAE, 0x93, 0x8A, 0x48, 0x97, 0x51, 0x15, 0xF7, - 0x01, 0x0B, 0xB7, 0x36, 0xB1, 0x2E, 0x11, 0xFD, - 0x84, 0x2D, 0x3F, 0x13, 0x88, 0xB3, 0x34, 0x24, - 0x1B, 0xDE, 0xC5, 0x1D, 0x4D, 0x2B, 0x17, 0x31, - 0x74, 0xA9, 0xC6, 0x43, 0x6D, 0x39, 0x90, 0xBE, - 0xC3, 0xB0, 0x21, 0x6B, 0xF6, 0x0F, 0xD5, 0x99, - 0x0D, 0xAC, 0x1F, 0x5C, 0x9E, 0xF5, 0xF9, 0x4C, - 0xD6, 0xDF, 0x89, 0xE4, 0x8B, 0xFF, 0xC7, 0xAA, - 0xE7, 0xED, 0x46, 0x25, 0xB6, 0x06, 0x5E, 0x35, - 0xB5, 0xEC, 0xCE, 0xE8, 0x6C, 0x30, 0x55, 0x61, - 0x4A, 0xFE, 0xA0, 0x79, 0x03, 0xF0, 0x10, 0x72, - 0x7C, 0xCF, 0x52, 0xA6, 0xA7, 0xEE, 0x44, 0xD3, - 0x9A, 0x57, 0x92, 0xD0, 0x5A, 0x7A, 0x41, 0x7F, - 0x0E, 0x00, 0x63, 0xF2, 0x4F, 0x05, 0x83, 0xC9, - 0xA1, 0xD4, 0xDD, 0xC4, 0x56, 0xF4, 0xD2, 0x77, - 0x81, 0x09, 0x82, 0x33, 0x9F, 0x07, 0x86, 0x75, - 0x38, 0x4E, 0x69, 0xF1, 0xAD, 0x23, 0x73, 0x87, - 0x70, 0x02, 0xC2, 0x1E, 0xB8, 0x0A, 0xFC, 0xE6 - ]; - - /** - * Default Constructor. - * - * @param string $mode - * @throws \InvalidArgumentException if an invalid / unsupported mode is provided - */ - public function __construct($mode) - { - parent::__construct($mode); - - if ($this->mode == self::MODE_STREAM) { - throw new BadModeException('Block ciphers cannot be ran in stream mode'); - } - } - - /** - * Test for engine validity - * - * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine() - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() - * @param int $engine - * @return bool - */ - protected function isValidEngineHelper($engine) - { - switch ($engine) { - case self::ENGINE_OPENSSL: - if ($this->current_key_length != 128 || strlen($this->orig_key) < 16) { - return false; - } - // quoting https://www.openssl.org/news/openssl-3.0-notes.html, OpenSSL 3.0.1 - // "Moved all variations of the EVP ciphers CAST5, BF, IDEA, SEED, RC2, RC4, RC5, and DES to the legacy provider" - // in theory openssl_get_cipher_methods() should catch this but, on GitHub Actions, at least, it does not - if (defined('OPENSSL_VERSION_TEXT') && version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) { - return false; - } - $this->cipher_name_openssl_ecb = 'rc2-ecb'; - $this->cipher_name_openssl = 'rc2-' . $this->openssl_translate_mode(); - } - - return parent::isValidEngineHelper($engine); - } - - /** - * Sets the key length. - * - * Valid key lengths are 8 to 1024. - * Calling this function after setting the key has no effect until the next - * \phpseclib3\Crypt\RC2::setKey() call. - * - * @param int $length in bits - * @throws \LengthException if the key length isn't supported - */ - public function setKeyLength($length) - { - if ($length < 8 || $length > 1024) { - throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys between 1 and 1024 bits, inclusive, are supported'); - } - - $this->default_key_length = $this->current_key_length = $length; - $this->explicit_key_length = $length >> 3; - } - - /** - * Returns the current key length - * - * @return int - */ - public function getKeyLength() - { - return $this->current_key_length; - } - - /** - * Sets the key. - * - * Keys can be of any length. RC2, itself, uses 8 to 1024 bit keys (eg. - * strlen($key) <= 128), however, we only use the first 128 bytes if $key - * has more then 128 bytes in it, and set $key to a single null byte if - * it is empty. - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::setKey() - * @param string $key - * @param int|boolean $t1 optional Effective key length in bits. - * @throws \LengthException if the key length isn't supported - */ - public function setKey($key, $t1 = false) - { - $this->orig_key = $key; - - if ($t1 === false) { - $t1 = $this->default_key_length; - } - - if ($t1 < 1 || $t1 > 1024) { - throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys between 1 and 1024 bits, inclusive, are supported'); - } - - $this->current_key_length = $t1; - if (strlen($key) < 1 || strlen($key) > 128) { - throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes between 8 and 1024 bits, inclusive, are supported'); - } - - $t = strlen($key); - - // The mcrypt RC2 implementation only supports effective key length - // of 1024 bits. It is however possible to handle effective key - // lengths in range 1..1024 by expanding the key and applying - // inverse pitable mapping to the first byte before submitting it - // to mcrypt. - - // Key expansion. - $l = array_values(unpack('C*', $key)); - $t8 = ($t1 + 7) >> 3; - $tm = 0xFF >> (8 * $t8 - $t1); - - // Expand key. - $pitable = self::$pitable; - for ($i = $t; $i < 128; $i++) { - $l[$i] = $pitable[$l[$i - 1] + $l[$i - $t]]; - } - $i = 128 - $t8; - $l[$i] = $pitable[$l[$i] & $tm]; - while ($i--) { - $l[$i] = $pitable[$l[$i + 1] ^ $l[$i + $t8]]; - } - - // Prepare the key for mcrypt. - $l[0] = self::$invpitable[$l[0]]; - array_unshift($l, 'C*'); - - $this->key = pack(...$l); - $this->key_length = strlen($this->key); - $this->changed = $this->nonIVChanged = true; - $this->setEngine(); - } - - /** - * Encrypts a message. - * - * Mostly a wrapper for \phpseclib3\Crypt\Common\SymmetricKey::encrypt, with some additional OpenSSL handling code - * - * @see self::decrypt() - * @param string $plaintext - * @return string $ciphertext - */ - public function encrypt($plaintext) - { - if ($this->engine == self::ENGINE_OPENSSL) { - $temp = $this->key; - $this->key = $this->orig_key; - $result = parent::encrypt($plaintext); - $this->key = $temp; - return $result; - } - - return parent::encrypt($plaintext); - } - - /** - * Decrypts a message. - * - * Mostly a wrapper for \phpseclib3\Crypt\Common\SymmetricKey::decrypt, with some additional OpenSSL handling code - * - * @see self::encrypt() - * @param string $ciphertext - * @return string $plaintext - */ - public function decrypt($ciphertext) - { - if ($this->engine == self::ENGINE_OPENSSL) { - $temp = $this->key; - $this->key = $this->orig_key; - $result = parent::decrypt($ciphertext); - $this->key = $temp; - return $result; - } - - return parent::decrypt($ciphertext); - } - - /** - * Encrypts a block - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::encryptBlock() - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @param string $in - * @return string - */ - protected function encryptBlock($in) - { - list($r0, $r1, $r2, $r3) = array_values(unpack('v*', $in)); - $keys = $this->keys; - $limit = 20; - $actions = [$limit => 44, 44 => 64]; - $j = 0; - - for (;;) { - // Mixing round. - $r0 = (($r0 + $keys[$j++] + ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF) << 1; - $r0 |= $r0 >> 16; - $r1 = (($r1 + $keys[$j++] + ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF) << 2; - $r1 |= $r1 >> 16; - $r2 = (($r2 + $keys[$j++] + ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF) << 3; - $r2 |= $r2 >> 16; - $r3 = (($r3 + $keys[$j++] + ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5; - $r3 |= $r3 >> 16; - - if ($j === $limit) { - if ($limit === 64) { - break; - } - - // Mashing round. - $r0 += $keys[$r3 & 0x3F]; - $r1 += $keys[$r0 & 0x3F]; - $r2 += $keys[$r1 & 0x3F]; - $r3 += $keys[$r2 & 0x3F]; - $limit = $actions[$limit]; - } - } - - return pack('vvvv', $r0, $r1, $r2, $r3); - } - - /** - * Decrypts a block - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::decryptBlock() - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() - * @param string $in - * @return string - */ - protected function decryptBlock($in) - { - list($r0, $r1, $r2, $r3) = array_values(unpack('v*', $in)); - $keys = $this->keys; - $limit = 44; - $actions = [$limit => 20, 20 => 0]; - $j = 64; - - for (;;) { - // R-mixing round. - $r3 = ($r3 | ($r3 << 16)) >> 5; - $r3 = ($r3 - $keys[--$j] - ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF; - $r2 = ($r2 | ($r2 << 16)) >> 3; - $r2 = ($r2 - $keys[--$j] - ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF; - $r1 = ($r1 | ($r1 << 16)) >> 2; - $r1 = ($r1 - $keys[--$j] - ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF; - $r0 = ($r0 | ($r0 << 16)) >> 1; - $r0 = ($r0 - $keys[--$j] - ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF; - - if ($j === $limit) { - if ($limit === 0) { - break; - } - - // R-mashing round. - $r3 = ($r3 - $keys[$r2 & 0x3F]) & 0xFFFF; - $r2 = ($r2 - $keys[$r1 & 0x3F]) & 0xFFFF; - $r1 = ($r1 - $keys[$r0 & 0x3F]) & 0xFFFF; - $r0 = ($r0 - $keys[$r3 & 0x3F]) & 0xFFFF; - $limit = $actions[$limit]; - } - } - - return pack('vvvv', $r0, $r1, $r2, $r3); - } - - /** - * Creates the key schedule - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::setupKey() - */ - protected function setupKey() - { - if (!isset($this->key)) { - $this->setKey(''); - } - - // Key has already been expanded in \phpseclib3\Crypt\RC2::setKey(): - // Only the first value must be altered. - $l = unpack('Ca/Cb/v*', $this->key); - array_unshift($l, self::$pitable[$l['a']] | ($l['b'] << 8)); - unset($l['a']); - unset($l['b']); - $this->keys = $l; - } - - /** - * Setup the performance-optimized function for de/encrypt() - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::setupInlineCrypt() - */ - protected function setupInlineCrypt() - { - // Init code for both, encrypt and decrypt. - $init_crypt = '$keys = $this->keys;'; - - $keys = $this->keys; - - // $in is the current 8 bytes block which has to be en/decrypt - $encrypt_block = $decrypt_block = ' - $in = unpack("v4", $in); - $r0 = $in[1]; - $r1 = $in[2]; - $r2 = $in[3]; - $r3 = $in[4]; - '; - - // Create code for encryption. - $limit = 20; - $actions = [$limit => 44, 44 => 64]; - $j = 0; - - for (;;) { - // Mixing round. - $encrypt_block .= ' - $r0 = (($r0 + ' . $keys[$j++] . ' + - ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF) << 1; - $r0 |= $r0 >> 16; - $r1 = (($r1 + ' . $keys[$j++] . ' + - ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF) << 2; - $r1 |= $r1 >> 16; - $r2 = (($r2 + ' . $keys[$j++] . ' + - ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF) << 3; - $r2 |= $r2 >> 16; - $r3 = (($r3 + ' . $keys[$j++] . ' + - ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5; - $r3 |= $r3 >> 16;'; - - if ($j === $limit) { - if ($limit === 64) { - break; - } - - // Mashing round. - $encrypt_block .= ' - $r0 += $keys[$r3 & 0x3F]; - $r1 += $keys[$r0 & 0x3F]; - $r2 += $keys[$r1 & 0x3F]; - $r3 += $keys[$r2 & 0x3F];'; - $limit = $actions[$limit]; - } - } - - $encrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);'; - - // Create code for decryption. - $limit = 44; - $actions = [$limit => 20, 20 => 0]; - $j = 64; - - for (;;) { - // R-mixing round. - $decrypt_block .= ' - $r3 = ($r3 | ($r3 << 16)) >> 5; - $r3 = ($r3 - ' . $keys[--$j] . ' - - ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF; - $r2 = ($r2 | ($r2 << 16)) >> 3; - $r2 = ($r2 - ' . $keys[--$j] . ' - - ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF; - $r1 = ($r1 | ($r1 << 16)) >> 2; - $r1 = ($r1 - ' . $keys[--$j] . ' - - ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF; - $r0 = ($r0 | ($r0 << 16)) >> 1; - $r0 = ($r0 - ' . $keys[--$j] . ' - - ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF;'; - - if ($j === $limit) { - if ($limit === 0) { - break; - } - - // R-mashing round. - $decrypt_block .= ' - $r3 = ($r3 - $keys[$r2 & 0x3F]) & 0xFFFF; - $r2 = ($r2 - $keys[$r1 & 0x3F]) & 0xFFFF; - $r1 = ($r1 - $keys[$r0 & 0x3F]) & 0xFFFF; - $r0 = ($r0 - $keys[$r3 & 0x3F]) & 0xFFFF;'; - $limit = $actions[$limit]; - } - } - - $decrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);'; - - // Creates the inline-crypt function - $this->inline_crypt = $this->createInlineCryptFunction( - [ - 'init_crypt' => $init_crypt, - 'encrypt_block' => $encrypt_block, - 'decrypt_block' => $decrypt_block - ] - ); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RC4.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RC4.php deleted file mode 100644 index 5f3bff2c..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RC4.php +++ /dev/null @@ -1,280 +0,0 @@ - - * setKey('abcdefgh'); - * - * $size = 10 * 1024; - * $plaintext = ''; - * for ($i = 0; $i < $size; $i++) { - * $plaintext.= 'a'; - * } - * - * echo $rc4->decrypt($rc4->encrypt($plaintext)); - * ?> - * - * - * @author Jim Wigginton - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt; - -use phpseclib3\Crypt\Common\StreamCipher; - -/** - * Pure-PHP implementation of RC4. - * - * @author Jim Wigginton - */ -class RC4 extends StreamCipher -{ - /** - * @see \phpseclib3\Crypt\RC4::_crypt() - */ - const ENCRYPT = 0; - - /** - * @see \phpseclib3\Crypt\RC4::_crypt() - */ - const DECRYPT = 1; - - /** - * Key Length (in bytes) - * - * @see \phpseclib3\Crypt\RC4::setKeyLength() - * @var int - */ - protected $key_length = 128; // = 1024 bits - - /** - * The mcrypt specific name of the cipher - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt - * @var string - */ - protected $cipher_name_mcrypt = 'arcfour'; - - /** - * The Key - * - * @see self::setKey() - * @var string - */ - protected $key; - - /** - * The Key Stream for decryption and encryption - * - * @see self::setKey() - * @var array - */ - private $stream; - - /** - * Test for engine validity - * - * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine() - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() - * @param int $engine - * @return bool - */ - protected function isValidEngineHelper($engine) - { - if ($engine == self::ENGINE_OPENSSL) { - if ($this->continuousBuffer) { - return false; - } - // quoting https://www.openssl.org/news/openssl-3.0-notes.html, OpenSSL 3.0.1 - // "Moved all variations of the EVP ciphers CAST5, BF, IDEA, SEED, RC2, RC4, RC5, and DES to the legacy provider" - // in theory openssl_get_cipher_methods() should catch this but, on GitHub Actions, at least, it does not - if (defined('OPENSSL_VERSION_TEXT') && version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) { - return false; - } - $this->cipher_name_openssl = 'rc4-40'; - } - - return parent::isValidEngineHelper($engine); - } - - /** - * Sets the key length - * - * Keys can be between 1 and 256 bytes long. - * - * @param int $length - * @throws \LengthException if the key length is invalid - */ - public function setKeyLength($length) - { - if ($length < 8 || $length > 2048) { - throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys between 1 and 256 bytes are supported'); - } - - $this->key_length = $length >> 3; - - parent::setKeyLength($length); - } - - /** - * Sets the key length - * - * Keys can be between 1 and 256 bytes long. - * - * @param string $key - */ - public function setKey($key) - { - $length = strlen($key); - if ($length < 1 || $length > 256) { - throw new \LengthException('Key size of ' . $length . ' bytes is not supported by RC4. Keys must be between 1 and 256 bytes long'); - } - - parent::setKey($key); - } - - /** - * Encrypts a message. - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() - * @see self::crypt() - * @param string $plaintext - * @return string $ciphertext - */ - public function encrypt($plaintext) - { - if ($this->engine != self::ENGINE_INTERNAL) { - return parent::encrypt($plaintext); - } - return $this->crypt($plaintext, self::ENCRYPT); - } - - /** - * Decrypts a message. - * - * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)). - * At least if the continuous buffer is disabled. - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @see self::crypt() - * @param string $ciphertext - * @return string $plaintext - */ - public function decrypt($ciphertext) - { - if ($this->engine != self::ENGINE_INTERNAL) { - return parent::decrypt($ciphertext); - } - return $this->crypt($ciphertext, self::DECRYPT); - } - - /** - * Encrypts a block - * - * @param string $in - */ - protected function encryptBlock($in) - { - // RC4 does not utilize this method - } - - /** - * Decrypts a block - * - * @param string $in - */ - protected function decryptBlock($in) - { - // RC4 does not utilize this method - } - - /** - * Setup the key (expansion) - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupKey() - */ - protected function setupKey() - { - $key = $this->key; - $keyLength = strlen($key); - $keyStream = range(0, 255); - $j = 0; - for ($i = 0; $i < 256; $i++) { - $j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255; - $temp = $keyStream[$i]; - $keyStream[$i] = $keyStream[$j]; - $keyStream[$j] = $temp; - } - - $this->stream = []; - $this->stream[self::DECRYPT] = $this->stream[self::ENCRYPT] = [ - 0, // index $i - 0, // index $j - $keyStream - ]; - } - - /** - * Encrypts or decrypts a message. - * - * @see self::encrypt() - * @see self::decrypt() - * @param string $text - * @param int $mode - * @return string $text - */ - private function crypt($text, $mode) - { - if ($this->changed) { - $this->setup(); - } - - $stream = &$this->stream[$mode]; - if ($this->continuousBuffer) { - $i = &$stream[0]; - $j = &$stream[1]; - $keyStream = &$stream[2]; - } else { - $i = $stream[0]; - $j = $stream[1]; - $keyStream = $stream[2]; - } - - $len = strlen($text); - for ($k = 0; $k < $len; ++$k) { - $i = ($i + 1) & 255; - $ksi = $keyStream[$i]; - $j = ($j + $ksi) & 255; - $ksj = $keyStream[$j]; - - $keyStream[$i] = $ksj; - $keyStream[$j] = $ksi; - $text[$k] = $text[$k] ^ chr($keyStream[($ksj + $ksi) & 255]); - } - - return $text; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php deleted file mode 100644 index 7b935cc2..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php +++ /dev/null @@ -1,929 +0,0 @@ - - * getPublicKey(); - * - * $plaintext = 'terrafrost'; - * - * $ciphertext = $public->encrypt($plaintext); - * - * echo $private->decrypt($ciphertext); - * ?> - * - * - * Here's an example of how to create signatures and verify signatures with this library: - * - * getPublicKey(); - * - * $plaintext = 'terrafrost'; - * - * $signature = $private->sign($plaintext); - * - * echo $public->verify($plaintext, $signature) ? 'verified' : 'unverified'; - * ?> - * - * - * One thing to consider when using this: so phpseclib uses PSS mode by default. - * Technically, id-RSASSA-PSS has a different key format than rsaEncryption. So - * should phpseclib save to the id-RSASSA-PSS format by default or the - * rsaEncryption format? For stand-alone keys I figure rsaEncryption is better - * because SSH doesn't use PSS and idk how many SSH servers would be able to - * decode an id-RSASSA-PSS key. For X.509 certificates the id-RSASSA-PSS - * format is used by default (unless you change it up to use PKCS1 instead) - * - * @author Jim Wigginton - * @copyright 2009 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt; - -use phpseclib3\Crypt\Common\AsymmetricKey; -use phpseclib3\Crypt\RSA\Formats\Keys\PSS; -use phpseclib3\Crypt\RSA\PrivateKey; -use phpseclib3\Crypt\RSA\PublicKey; -use phpseclib3\Exception\InconsistentSetupException; -use phpseclib3\Exception\UnsupportedAlgorithmException; -use phpseclib3\Math\BigInteger; - -/** - * Pure-PHP PKCS#1 compliant implementation of RSA. - * - * @author Jim Wigginton - */ -abstract class RSA extends AsymmetricKey -{ - /** - * Algorithm Name - * - * @var string - */ - const ALGORITHM = 'RSA'; - - /** - * Use {@link http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding Optimal Asymmetric Encryption Padding} - * (OAEP) for encryption / decryption. - * - * Uses sha256 by default - * - * @see self::setHash() - * @see self::setMGFHash() - * @see self::encrypt() - * @see self::decrypt() - */ - const ENCRYPTION_OAEP = 1; - - /** - * Use PKCS#1 padding. - * - * Although self::PADDING_OAEP / self::PADDING_PSS offers more security, including PKCS#1 padding is necessary for purposes of backwards - * compatibility with protocols (like SSH-1) written before OAEP's introduction. - * - * @see self::encrypt() - * @see self::decrypt() - */ - const ENCRYPTION_PKCS1 = 2; - - /** - * Do not use any padding - * - * Although this method is not recommended it can none-the-less sometimes be useful if you're trying to decrypt some legacy - * stuff, if you're trying to diagnose why an encrypted message isn't decrypting, etc. - * - * @see self::encrypt() - * @see self::decrypt() - */ - const ENCRYPTION_NONE = 4; - - /** - * Use the Probabilistic Signature Scheme for signing - * - * Uses sha256 and 0 as the salt length - * - * @see self::setSaltLength() - * @see self::setMGFHash() - * @see self::setHash() - * @see self::sign() - * @see self::verify() - * @see self::setHash() - */ - const SIGNATURE_PSS = 16; - - /** - * Use a relaxed version of PKCS#1 padding for signature verification - * - * @see self::sign() - * @see self::verify() - * @see self::setHash() - */ - const SIGNATURE_RELAXED_PKCS1 = 32; - - /** - * Use PKCS#1 padding for signature verification - * - * @see self::sign() - * @see self::verify() - * @see self::setHash() - */ - const SIGNATURE_PKCS1 = 64; - - /** - * Encryption padding mode - * - * @var int - */ - protected $encryptionPadding = self::ENCRYPTION_OAEP; - - /** - * Signature padding mode - * - * @var int - */ - protected $signaturePadding = self::SIGNATURE_PSS; - - /** - * Length of hash function output - * - * @var int - */ - protected $hLen; - - /** - * Length of salt - * - * @var int - */ - protected $sLen; - - /** - * Label - * - * @var string - */ - protected $label = ''; - - /** - * Hash function for the Mask Generation Function - * - * @var \phpseclib3\Crypt\Hash - */ - protected $mgfHash; - - /** - * Length of MGF hash function output - * - * @var int - */ - protected $mgfHLen; - - /** - * Modulus (ie. n) - * - * @var \phpseclib3\Math\BigInteger - */ - protected $modulus; - - /** - * Modulus length - * - * @var \phpseclib3\Math\BigInteger - */ - protected $k; - - /** - * Exponent (ie. e or d) - * - * @var \phpseclib3\Math\BigInteger - */ - protected $exponent; - - /** - * Default public exponent - * - * @var int - * @link http://en.wikipedia.org/wiki/65537_%28number%29 - */ - private static $defaultExponent = 65537; - - /** - * Enable Blinding? - * - * @var bool - */ - protected static $enableBlinding = true; - - /** - * OpenSSL configuration file name. - * - * @see self::createKey() - * @var ?string - */ - protected static $configFile; - - /** - * Smallest Prime - * - * Per , this number ought not result in primes smaller - * than 256 bits. As a consequence if the key you're trying to create is 1024 bits and you've set smallestPrime - * to 384 bits then you're going to get a 384 bit prime and a 640 bit prime (384 + 1024 % 384). At least if - * engine is set to self::ENGINE_INTERNAL. If Engine is set to self::ENGINE_OPENSSL then smallest Prime is - * ignored (ie. multi-prime RSA support is more intended as a way to speed up RSA key generation when there's - * a chance neither gmp nor OpenSSL are installed) - * - * @var int - */ - private static $smallestPrime = 4096; - - /** - * Public Exponent - * - * @var \phpseclib3\Math\BigInteger - */ - protected $publicExponent; - - /** - * Sets the public exponent for key generation - * - * This will be 65537 unless changed. - * - * @param int $val - */ - public static function setExponent($val) - { - self::$defaultExponent = $val; - } - - /** - * Sets the smallest prime number in bits. Used for key generation - * - * This will be 4096 unless changed. - * - * @param int $val - */ - public static function setSmallestPrime($val) - { - self::$smallestPrime = $val; - } - - /** - * Sets the OpenSSL config file path - * - * Set to the empty string to use the default config file - * - * @param string $val - */ - public static function setOpenSSLConfigPath($val) - { - self::$configFile = $val; - } - - /** - * Create a private key - * - * The public key can be extracted from the private key - * - * @return RSA\PrivateKey - * @param int $bits - */ - public static function createKey($bits = 2048) - { - self::initialize_static_variables(); - - $class = new \ReflectionClass(static::class); - if ($class->isFinal()) { - throw new \RuntimeException('createKey() should not be called from final classes (' . static::class . ')'); - } - - $regSize = $bits >> 1; // divide by two to see how many bits P and Q would be - if ($regSize > self::$smallestPrime) { - $num_primes = floor($bits / self::$smallestPrime); - $regSize = self::$smallestPrime; - } else { - $num_primes = 2; - } - - if ($num_primes == 2 && $bits >= 384 && self::$defaultExponent == 65537) { - if (!isset(self::$engines['PHP'])) { - self::useBestEngine(); - } - - // OpenSSL uses 65537 as the exponent and requires RSA keys be 384 bits minimum - if (self::$engines['OpenSSL']) { - $config = []; - if (self::$configFile) { - $config['config'] = self::$configFile; - } - $rsa = openssl_pkey_new(['private_key_bits' => $bits] + $config); - openssl_pkey_export($rsa, $privatekeystr, null, $config); - - // clear the buffer of error strings stemming from a minimalistic openssl.cnf - while (openssl_error_string() !== false) { - } - - return RSA::load($privatekeystr); - } - } - - static $e; - if (!isset($e)) { - $e = new BigInteger(self::$defaultExponent); - } - - $n = clone self::$one; - $exponents = $coefficients = $primes = []; - $lcm = [ - 'top' => clone self::$one, - 'bottom' => false - ]; - - do { - for ($i = 1; $i <= $num_primes; $i++) { - if ($i != $num_primes) { - $primes[$i] = BigInteger::randomPrime($regSize); - } else { - extract(BigInteger::minMaxBits($bits)); - /** @var BigInteger $min - * @var BigInteger $max - */ - list($min) = $min->divide($n); - $min = $min->add(self::$one); - list($max) = $max->divide($n); - $primes[$i] = BigInteger::randomRangePrime($min, $max); - } - - // the first coefficient is calculated differently from the rest - // ie. instead of being $primes[1]->modInverse($primes[2]), it's $primes[2]->modInverse($primes[1]) - if ($i > 2) { - $coefficients[$i] = $n->modInverse($primes[$i]); - } - - $n = $n->multiply($primes[$i]); - - $temp = $primes[$i]->subtract(self::$one); - - // textbook RSA implementations use Euler's totient function instead of the least common multiple. - // see http://en.wikipedia.org/wiki/Euler%27s_totient_function - $lcm['top'] = $lcm['top']->multiply($temp); - $lcm['bottom'] = $lcm['bottom'] === false ? $temp : $lcm['bottom']->gcd($temp); - } - - list($temp) = $lcm['top']->divide($lcm['bottom']); - $gcd = $temp->gcd($e); - $i0 = 1; - } while (!$gcd->equals(self::$one)); - - $coefficients[2] = $primes[2]->modInverse($primes[1]); - - $d = $e->modInverse($temp); - - foreach ($primes as $i => $prime) { - $temp = $prime->subtract(self::$one); - $exponents[$i] = $e->modInverse($temp); - } - - // from : - // RSAPrivateKey ::= SEQUENCE { - // version Version, - // modulus INTEGER, -- n - // publicExponent INTEGER, -- e - // privateExponent INTEGER, -- d - // prime1 INTEGER, -- p - // prime2 INTEGER, -- q - // exponent1 INTEGER, -- d mod (p-1) - // exponent2 INTEGER, -- d mod (q-1) - // coefficient INTEGER, -- (inverse of q) mod p - // otherPrimeInfos OtherPrimeInfos OPTIONAL - // } - $privatekey = new PrivateKey(); - $privatekey->modulus = $n; - $privatekey->k = $bits >> 3; - $privatekey->publicExponent = $e; - $privatekey->exponent = $d; - $privatekey->primes = $primes; - $privatekey->exponents = $exponents; - $privatekey->coefficients = $coefficients; - - /* - $publickey = new PublicKey; - $publickey->modulus = $n; - $publickey->k = $bits >> 3; - $publickey->exponent = $e; - $publickey->publicExponent = $e; - $publickey->isPublic = true; - */ - - return $privatekey; - } - - /** - * OnLoad Handler - * - * @return bool - */ - protected static function onLoad(array $components) - { - $key = $components['isPublicKey'] ? - new PublicKey() : - new PrivateKey(); - - $key->modulus = $components['modulus']; - $key->publicExponent = $components['publicExponent']; - $key->k = $key->modulus->getLengthInBytes(); - - if ($components['isPublicKey'] || !isset($components['privateExponent'])) { - $key->exponent = $key->publicExponent; - } else { - $key->privateExponent = $components['privateExponent']; - $key->exponent = $key->privateExponent; - $key->primes = $components['primes']; - $key->exponents = $components['exponents']; - $key->coefficients = $components['coefficients']; - } - - if ($components['format'] == PSS::class) { - // in the X509 world RSA keys are assumed to use PKCS1 padding by default. only if the key is - // explicitly a PSS key is the use of PSS assumed. phpseclib does not work like this. phpseclib - // uses PSS padding by default. it assumes the more secure method by default and altho it provides - // for the less secure PKCS1 method you have to go out of your way to use it. this is consistent - // with the latest trends in crypto. libsodium (NaCl) is actually a little more extreme in that - // not only does it defaults to the most secure methods - it doesn't even let you choose less - // secure methods - //$key = $key->withPadding(self::SIGNATURE_PSS); - if (isset($components['hash'])) { - $key = $key->withHash($components['hash']); - } - if (isset($components['MGFHash'])) { - $key = $key->withMGFHash($components['MGFHash']); - } - if (isset($components['saltLength'])) { - $key = $key->withSaltLength($components['saltLength']); - } - } - - return $key; - } - - /** - * Initialize static variables - */ - protected static function initialize_static_variables() - { - if (!isset(self::$configFile)) { - self::$configFile = dirname(__FILE__) . '/../openssl.cnf'; - } - - parent::initialize_static_variables(); - } - - /** - * Constructor - * - * PublicKey and PrivateKey objects can only be created from abstract RSA class - */ - protected function __construct() - { - parent::__construct(); - - $this->hLen = $this->hash->getLengthInBytes(); - $this->mgfHash = new Hash('sha256'); - $this->mgfHLen = $this->mgfHash->getLengthInBytes(); - } - - /** - * Integer-to-Octet-String primitive - * - * See {@link http://tools.ietf.org/html/rfc3447#section-4.1 RFC3447#section-4.1}. - * - * @param bool|\phpseclib3\Math\BigInteger $x - * @param int $xLen - * @return bool|string - */ - protected function i2osp($x, $xLen) - { - if ($x === false) { - return false; - } - $x = $x->toBytes(); - if (strlen($x) > $xLen) { - throw new \OutOfRangeException('Resultant string length out of range'); - } - return str_pad($x, $xLen, chr(0), STR_PAD_LEFT); - } - - /** - * Octet-String-to-Integer primitive - * - * See {@link http://tools.ietf.org/html/rfc3447#section-4.2 RFC3447#section-4.2}. - * - * @param string $x - * @return \phpseclib3\Math\BigInteger - */ - protected function os2ip($x) - { - return new BigInteger($x, 256); - } - - /** - * EMSA-PKCS1-V1_5-ENCODE - * - * See {@link http://tools.ietf.org/html/rfc3447#section-9.2 RFC3447#section-9.2}. - * - * @param string $m - * @param int $emLen - * @throws \LengthException if the intended encoded message length is too short - * @return string - */ - protected function emsa_pkcs1_v1_5_encode($m, $emLen) - { - $h = $this->hash->hash($m); - - // see http://tools.ietf.org/html/rfc3447#page-43 - switch ($this->hash->getHash()) { - case 'md2': - $t = "\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x02\x05\x00\x04\x10"; - break; - case 'md5': - $t = "\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05\x05\x00\x04\x10"; - break; - case 'sha1': - $t = "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14"; - break; - case 'sha256': - $t = "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20"; - break; - case 'sha384': - $t = "\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x05\x00\x04\x30"; - break; - case 'sha512': - $t = "\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x05\x00\x04\x40"; - break; - // from https://www.emc.com/collateral/white-papers/h11300-pkcs-1v2-2-rsa-cryptography-standard-wp.pdf#page=40 - case 'sha224': - $t = "\x30\x2d\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04\x05\x00\x04\x1c"; - break; - case 'sha512/224': - $t = "\x30\x2d\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x05\x05\x00\x04\x1c"; - break; - case 'sha512/256': - $t = "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x06\x05\x00\x04\x20"; - } - $t .= $h; - $tLen = strlen($t); - - if ($emLen < $tLen + 11) { - throw new \LengthException('Intended encoded message length too short'); - } - - $ps = str_repeat(chr(0xFF), $emLen - $tLen - 3); - - $em = "\0\1$ps\0$t"; - - return $em; - } - - /** - * EMSA-PKCS1-V1_5-ENCODE (without NULL) - * - * Quoting https://tools.ietf.org/html/rfc8017#page-65, - * - * "The parameters field associated with id-sha1, id-sha224, id-sha256, - * id-sha384, id-sha512, id-sha512/224, and id-sha512/256 should - * generally be omitted, but if present, it shall have a value of type - * NULL" - * - * @param string $m - * @param int $emLen - * @return string - */ - protected function emsa_pkcs1_v1_5_encode_without_null($m, $emLen) - { - $h = $this->hash->hash($m); - - // see http://tools.ietf.org/html/rfc3447#page-43 - switch ($this->hash->getHash()) { - case 'sha1': - $t = "\x30\x1f\x30\x07\x06\x05\x2b\x0e\x03\x02\x1a\x04\x14"; - break; - case 'sha256': - $t = "\x30\x2f\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x04\x20"; - break; - case 'sha384': - $t = "\x30\x3f\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x04\x30"; - break; - case 'sha512': - $t = "\x30\x4f\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x04\x40"; - break; - // from https://www.emc.com/collateral/white-papers/h11300-pkcs-1v2-2-rsa-cryptography-standard-wp.pdf#page=40 - case 'sha224': - $t = "\x30\x2b\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04\x04\x1c"; - break; - case 'sha512/224': - $t = "\x30\x2b\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x05\x04\x1c"; - break; - case 'sha512/256': - $t = "\x30\x2f\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x06\x04\x20"; - break; - default: - throw new UnsupportedAlgorithmException('md2 and md5 require NULLs'); - } - $t .= $h; - $tLen = strlen($t); - - if ($emLen < $tLen + 11) { - throw new \LengthException('Intended encoded message length too short'); - } - - $ps = str_repeat(chr(0xFF), $emLen - $tLen - 3); - - $em = "\0\1$ps\0$t"; - - return $em; - } - - /** - * MGF1 - * - * See {@link http://tools.ietf.org/html/rfc3447#appendix-B.2.1 RFC3447#appendix-B.2.1}. - * - * @param string $mgfSeed - * @param int $maskLen - * @return string - */ - protected function mgf1($mgfSeed, $maskLen) - { - // if $maskLen would yield strings larger than 4GB, PKCS#1 suggests a "Mask too long" error be output. - - $t = ''; - $count = ceil($maskLen / $this->mgfHLen); - for ($i = 0; $i < $count; $i++) { - $c = pack('N', $i); - $t .= $this->mgfHash->hash($mgfSeed . $c); - } - - return substr($t, 0, $maskLen); - } - - /** - * Returns the key size - * - * More specifically, this returns the size of the modulo in bits. - * - * @return int - */ - public function getLength() - { - return !isset($this->modulus) ? 0 : $this->modulus->getLength(); - } - - /** - * Determines which hashing function should be used - * - * Used with signature production / verification and (if the encryption mode is self::PADDING_OAEP) encryption and - * decryption. - * - * @param string $hash - */ - public function withHash($hash) - { - $new = clone $this; - - // \phpseclib3\Crypt\Hash supports algorithms that PKCS#1 doesn't support. md5-96 and sha1-96, for example. - switch (strtolower($hash)) { - case 'md2': - case 'md5': - case 'sha1': - case 'sha256': - case 'sha384': - case 'sha512': - case 'sha224': - case 'sha512/224': - case 'sha512/256': - $new->hash = new Hash($hash); - break; - default: - throw new UnsupportedAlgorithmException( - 'The only supported hash algorithms are: md2, md5, sha1, sha256, sha384, sha512, sha224, sha512/224, sha512/256' - ); - } - $new->hLen = $new->hash->getLengthInBytes(); - - return $new; - } - - /** - * Determines which hashing function should be used for the mask generation function - * - * The mask generation function is used by self::PADDING_OAEP and self::PADDING_PSS and although it's - * best if Hash and MGFHash are set to the same thing this is not a requirement. - * - * @param string $hash - */ - public function withMGFHash($hash) - { - $new = clone $this; - - // \phpseclib3\Crypt\Hash supports algorithms that PKCS#1 doesn't support. md5-96 and sha1-96, for example. - switch (strtolower($hash)) { - case 'md2': - case 'md5': - case 'sha1': - case 'sha256': - case 'sha384': - case 'sha512': - case 'sha224': - case 'sha512/224': - case 'sha512/256': - $new->mgfHash = new Hash($hash); - break; - default: - throw new UnsupportedAlgorithmException( - 'The only supported hash algorithms are: md2, md5, sha1, sha256, sha384, sha512, sha224, sha512/224, sha512/256' - ); - } - $new->mgfHLen = $new->mgfHash->getLengthInBytes(); - - return $new; - } - - /** - * Returns the MGF hash algorithm currently being used - * - */ - public function getMGFHash() - { - return clone $this->mgfHash; - } - - /** - * Determines the salt length - * - * Used by RSA::PADDING_PSS - * - * To quote from {@link http://tools.ietf.org/html/rfc3447#page-38 RFC3447#page-38}: - * - * Typical salt lengths in octets are hLen (the length of the output - * of the hash function Hash) and 0. - * - * @param int $sLen - */ - public function withSaltLength($sLen) - { - $new = clone $this; - $new->sLen = $sLen; - return $new; - } - - /** - * Returns the salt length currently being used - * - */ - public function getSaltLength() - { - return $this->sLen !== null ? $this->sLen : $this->hLen; - } - - /** - * Determines the label - * - * Used by RSA::PADDING_OAEP - * - * To quote from {@link http://tools.ietf.org/html/rfc3447#page-17 RFC3447#page-17}: - * - * Both the encryption and the decryption operations of RSAES-OAEP take - * the value of a label L as input. In this version of PKCS #1, L is - * the empty string; other uses of the label are outside the scope of - * this document. - * - * @param string $label - */ - public function withLabel($label) - { - $new = clone $this; - $new->label = $label; - return $new; - } - - /** - * Returns the label currently being used - * - */ - public function getLabel() - { - return $this->label; - } - - /** - * Determines the padding modes - * - * Example: $key->withPadding(RSA::ENCRYPTION_PKCS1 | RSA::SIGNATURE_PKCS1); - * - * @param int $padding - */ - public function withPadding($padding) - { - $masks = [ - self::ENCRYPTION_OAEP, - self::ENCRYPTION_PKCS1, - self::ENCRYPTION_NONE - ]; - $numSelected = 0; - $selected = 0; - foreach ($masks as $mask) { - if ($padding & $mask) { - $selected = $mask; - $numSelected++; - } - } - if ($numSelected > 1) { - throw new InconsistentSetupException('Multiple encryption padding modes have been selected; at most only one should be selected'); - } - $encryptionPadding = $selected; - - $masks = [ - self::SIGNATURE_PSS, - self::SIGNATURE_RELAXED_PKCS1, - self::SIGNATURE_PKCS1 - ]; - $numSelected = 0; - $selected = 0; - foreach ($masks as $mask) { - if ($padding & $mask) { - $selected = $mask; - $numSelected++; - } - } - if ($numSelected > 1) { - throw new InconsistentSetupException('Multiple signature padding modes have been selected; at most only one should be selected'); - } - $signaturePadding = $selected; - - $new = clone $this; - $new->encryptionPadding = $encryptionPadding; - $new->signaturePadding = $signaturePadding; - return $new; - } - - /** - * Returns the padding currently being used - * - */ - public function getPadding() - { - return $this->signaturePadding | $this->encryptionPadding; - } - - /** - * Returns the current engine being used - * - * OpenSSL is only used in this class (and it's subclasses) for key generation - * Even then it depends on the parameters you're using. It's not used for - * multi-prime RSA nor is it used if the key length is outside of the range - * supported by OpenSSL - * - * @see self::useInternalEngine() - * @see self::useBestEngine() - * @return string - */ - public function getEngine() - { - if (!isset(self::$engines['PHP'])) { - self::useBestEngine(); - } - return self::$engines['OpenSSL'] && self::$defaultExponent == 65537 ? - 'OpenSSL' : - 'PHP'; - } - - /** - * Enable RSA Blinding - * - */ - public static function enableBlinding() - { - static::$enableBlinding = true; - } - - /** - * Disable RSA Blinding - * - */ - public static function disableBlinding() - { - static::$enableBlinding = false; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/JWK.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/JWK.php deleted file mode 100644 index 87f543de..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/JWK.php +++ /dev/null @@ -1,142 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\RSA\Formats\Keys; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\Common\Formats\Keys\JWK as Progenitor; -use phpseclib3\Math\BigInteger; - -/** - * JWK Formatted RSA Handler - * - * @author Jim Wigginton - */ -abstract class JWK extends Progenitor -{ - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - $key = parent::load($key, $password); - - if ($key->kty != 'RSA') { - throw new \RuntimeException('Only RSA JWK keys are supported'); - } - - $count = $publicCount = 0; - $vars = ['n', 'e', 'd', 'p', 'q', 'dp', 'dq', 'qi']; - foreach ($vars as $var) { - if (!isset($key->$var) || !is_string($key->$var)) { - continue; - } - $count++; - $value = new BigInteger(Strings::base64url_decode($key->$var), 256); - switch ($var) { - case 'n': - $publicCount++; - $components['modulus'] = $value; - break; - case 'e': - $publicCount++; - $components['publicExponent'] = $value; - break; - case 'd': - $components['privateExponent'] = $value; - break; - case 'p': - $components['primes'][1] = $value; - break; - case 'q': - $components['primes'][2] = $value; - break; - case 'dp': - $components['exponents'][1] = $value; - break; - case 'dq': - $components['exponents'][2] = $value; - break; - case 'qi': - $components['coefficients'][2] = $value; - } - } - - if ($count == count($vars)) { - return $components + ['isPublicKey' => false]; - } - - if ($count == 2 && $publicCount == 2) { - return $components + ['isPublicKey' => true]; - } - - throw new \UnexpectedValueException('Key does not have an appropriate number of RSA parameters'); - } - - /** - * Convert a private key to the appropriate format. - * - * @param \phpseclib3\Math\BigInteger $n - * @param \phpseclib3\Math\BigInteger $e - * @param \phpseclib3\Math\BigInteger $d - * @param array $primes - * @param array $exponents - * @param array $coefficients - * @param string $password optional - * @param array $options optional - * @return string - */ - public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '', array $options = []) - { - if (count($primes) != 2) { - throw new \InvalidArgumentException('JWK does not support multi-prime RSA keys'); - } - - $key = [ - 'kty' => 'RSA', - 'n' => Strings::base64url_encode($n->toBytes()), - 'e' => Strings::base64url_encode($e->toBytes()), - 'd' => Strings::base64url_encode($d->toBytes()), - 'p' => Strings::base64url_encode($primes[1]->toBytes()), - 'q' => Strings::base64url_encode($primes[2]->toBytes()), - 'dp' => Strings::base64url_encode($exponents[1]->toBytes()), - 'dq' => Strings::base64url_encode($exponents[2]->toBytes()), - 'qi' => Strings::base64url_encode($coefficients[2]->toBytes()) - ]; - - return self::wrapKey($key, $options); - } - - /** - * Convert a public key to the appropriate format - * - * @param \phpseclib3\Math\BigInteger $n - * @param \phpseclib3\Math\BigInteger $e - * @param array $options optional - * @return string - */ - public static function savePublicKey(BigInteger $n, BigInteger $e, array $options = []) - { - $key = [ - 'kty' => 'RSA', - 'n' => Strings::base64url_encode($n->toBytes()), - 'e' => Strings::base64url_encode($e->toBytes()) - ]; - - return self::wrapKey($key, $options); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/MSBLOB.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/MSBLOB.php deleted file mode 100644 index e9a0c4f3..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/MSBLOB.php +++ /dev/null @@ -1,228 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\RSA\Formats\Keys; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Exception\UnsupportedFormatException; -use phpseclib3\Math\BigInteger; - -/** - * Microsoft BLOB Formatted RSA Key Handler - * - * @author Jim Wigginton - */ -abstract class MSBLOB -{ - /** - * Public/Private Key Pair - * - */ - const PRIVATEKEYBLOB = 0x7; - /** - * Public Key - * - */ - const PUBLICKEYBLOB = 0x6; - /** - * Public Key - * - */ - const PUBLICKEYBLOBEX = 0xA; - /** - * RSA public key exchange algorithm - * - */ - const CALG_RSA_KEYX = 0x0000A400; - /** - * RSA public key exchange algorithm - * - */ - const CALG_RSA_SIGN = 0x00002400; - /** - * Public Key - * - */ - const RSA1 = 0x31415352; - /** - * Private Key - * - */ - const RSA2 = 0x32415352; - - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - if (!Strings::is_stringable($key)) { - throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key)); - } - - $key = Strings::base64_decode($key); - - if (!is_string($key)) { - throw new \UnexpectedValueException('Base64 decoding produced an error'); - } - if (strlen($key) < 20) { - throw new \UnexpectedValueException('Key appears to be malformed'); - } - - // PUBLICKEYSTRUC publickeystruc - // https://msdn.microsoft.com/en-us/library/windows/desktop/aa387453(v=vs.85).aspx - extract(unpack('atype/aversion/vreserved/Valgo', Strings::shift($key, 8))); - /** - * @var string $type - * @var string $version - * @var integer $reserved - * @var integer $algo - */ - switch (ord($type)) { - case self::PUBLICKEYBLOB: - case self::PUBLICKEYBLOBEX: - $publickey = true; - break; - case self::PRIVATEKEYBLOB: - $publickey = false; - break; - default: - throw new \UnexpectedValueException('Key appears to be malformed'); - } - - $components = ['isPublicKey' => $publickey]; - - // https://msdn.microsoft.com/en-us/library/windows/desktop/aa375549(v=vs.85).aspx - switch ($algo) { - case self::CALG_RSA_KEYX: - case self::CALG_RSA_SIGN: - break; - default: - throw new \UnexpectedValueException('Key appears to be malformed'); - } - - // RSAPUBKEY rsapubkey - // https://msdn.microsoft.com/en-us/library/windows/desktop/aa387685(v=vs.85).aspx - // could do V for pubexp but that's unsigned 32-bit whereas some PHP installs only do signed 32-bit - extract(unpack('Vmagic/Vbitlen/a4pubexp', Strings::shift($key, 12))); - /** - * @var integer $magic - * @var integer $bitlen - * @var string $pubexp - */ - switch ($magic) { - case self::RSA2: - $components['isPublicKey'] = false; - // fall-through - case self::RSA1: - break; - default: - throw new \UnexpectedValueException('Key appears to be malformed'); - } - - $baseLength = $bitlen / 16; - if (strlen($key) != 2 * $baseLength && strlen($key) != 9 * $baseLength) { - throw new \UnexpectedValueException('Key appears to be malformed'); - } - - $components[$components['isPublicKey'] ? 'publicExponent' : 'privateExponent'] = new BigInteger(strrev($pubexp), 256); - // BYTE modulus[rsapubkey.bitlen/8] - $components['modulus'] = new BigInteger(strrev(Strings::shift($key, $bitlen / 8)), 256); - - if ($publickey) { - return $components; - } - - $components['isPublicKey'] = false; - - // BYTE prime1[rsapubkey.bitlen/16] - $components['primes'] = [1 => new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256)]; - // BYTE prime2[rsapubkey.bitlen/16] - $components['primes'][] = new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256); - // BYTE exponent1[rsapubkey.bitlen/16] - $components['exponents'] = [1 => new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256)]; - // BYTE exponent2[rsapubkey.bitlen/16] - $components['exponents'][] = new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256); - // BYTE coefficient[rsapubkey.bitlen/16] - $components['coefficients'] = [2 => new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256)]; - if (isset($components['privateExponent'])) { - $components['publicExponent'] = $components['privateExponent']; - } - // BYTE privateExponent[rsapubkey.bitlen/8] - $components['privateExponent'] = new BigInteger(strrev(Strings::shift($key, $bitlen / 8)), 256); - - return $components; - } - - /** - * Convert a private key to the appropriate format. - * - * @param \phpseclib3\Math\BigInteger $n - * @param \phpseclib3\Math\BigInteger $e - * @param \phpseclib3\Math\BigInteger $d - * @param array $primes - * @param array $exponents - * @param array $coefficients - * @param string $password optional - * @return string - */ - public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '') - { - if (count($primes) != 2) { - throw new \InvalidArgumentException('MSBLOB does not support multi-prime RSA keys'); - } - - if (!empty($password) && is_string($password)) { - throw new UnsupportedFormatException('MSBLOB private keys do not support encryption'); - } - - $n = strrev($n->toBytes()); - $e = str_pad(strrev($e->toBytes()), 4, "\0"); - $key = pack('aavV', chr(self::PRIVATEKEYBLOB), chr(2), 0, self::CALG_RSA_KEYX); - $key .= pack('VVa*', self::RSA2, 8 * strlen($n), $e); - $key .= $n; - $key .= strrev($primes[1]->toBytes()); - $key .= strrev($primes[2]->toBytes()); - $key .= strrev($exponents[1]->toBytes()); - $key .= strrev($exponents[2]->toBytes()); - $key .= strrev($coefficients[2]->toBytes()); - $key .= strrev($d->toBytes()); - - return Strings::base64_encode($key); - } - - /** - * Convert a public key to the appropriate format - * - * @param \phpseclib3\Math\BigInteger $n - * @param \phpseclib3\Math\BigInteger $e - * @return string - */ - public static function savePublicKey(BigInteger $n, BigInteger $e) - { - $n = strrev($n->toBytes()); - $e = str_pad(strrev($e->toBytes()), 4, "\0"); - $key = pack('aavV', chr(self::PUBLICKEYBLOB), chr(2), 0, self::CALG_RSA_KEYX); - $key .= pack('VVa*', self::RSA1, 8 * strlen($n), $e); - $key .= $n; - - return Strings::base64_encode($key); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/OpenSSH.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/OpenSSH.php deleted file mode 100644 index 2367810a..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/OpenSSH.php +++ /dev/null @@ -1,132 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\RSA\Formats\Keys; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\Common\Formats\Keys\OpenSSH as Progenitor; -use phpseclib3\Math\BigInteger; - -/** - * OpenSSH Formatted RSA Key Handler - * - * @author Jim Wigginton - */ -abstract class OpenSSH extends Progenitor -{ - /** - * Supported Key Types - * - * @var array - */ - protected static $types = ['ssh-rsa']; - - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - static $one; - if (!isset($one)) { - $one = new BigInteger(1); - } - - $parsed = parent::load($key, $password); - - if (isset($parsed['paddedKey'])) { - list($type) = Strings::unpackSSH2('s', $parsed['paddedKey']); - if ($type != $parsed['type']) { - throw new \RuntimeException("The public and private keys are not of the same type ($type vs $parsed[type])"); - } - - $primes = $coefficients = []; - - list( - $modulus, - $publicExponent, - $privateExponent, - $coefficients[2], - $primes[1], - $primes[2], - $comment, - ) = Strings::unpackSSH2('i6s', $parsed['paddedKey']); - - $temp = $primes[1]->subtract($one); - $exponents = [1 => $publicExponent->modInverse($temp)]; - $temp = $primes[2]->subtract($one); - $exponents[] = $publicExponent->modInverse($temp); - - $isPublicKey = false; - - return compact('publicExponent', 'modulus', 'privateExponent', 'primes', 'coefficients', 'exponents', 'comment', 'isPublicKey'); - } - - list($publicExponent, $modulus) = Strings::unpackSSH2('ii', $parsed['publicKey']); - - return [ - 'isPublicKey' => true, - 'modulus' => $modulus, - 'publicExponent' => $publicExponent, - 'comment' => $parsed['comment'] - ]; - } - - /** - * Convert a public key to the appropriate format - * - * @param \phpseclib3\Math\BigInteger $n - * @param \phpseclib3\Math\BigInteger $e - * @param array $options optional - * @return string - */ - public static function savePublicKey(BigInteger $n, BigInteger $e, array $options = []) - { - $RSAPublicKey = Strings::packSSH2('sii', 'ssh-rsa', $e, $n); - - if (isset($options['binary']) ? $options['binary'] : self::$binary) { - return $RSAPublicKey; - } - - $comment = isset($options['comment']) ? $options['comment'] : self::$comment; - $RSAPublicKey = 'ssh-rsa ' . base64_encode($RSAPublicKey) . ' ' . $comment; - - return $RSAPublicKey; - } - - /** - * Convert a private key to the appropriate format. - * - * @param \phpseclib3\Math\BigInteger $n - * @param \phpseclib3\Math\BigInteger $e - * @param \phpseclib3\Math\BigInteger $d - * @param array $primes - * @param array $exponents - * @param array $coefficients - * @param string $password optional - * @param array $options optional - * @return string - */ - public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '', array $options = []) - { - $publicKey = self::savePublicKey($n, $e, ['binary' => true]); - $privateKey = Strings::packSSH2('si6', 'ssh-rsa', $n, $e, $d, $coefficients[2], $primes[1], $primes[2]); - - return self::wrapPrivateKey($publicKey, $privateKey, $password, $options); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PKCS1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PKCS1.php deleted file mode 100644 index 276c6024..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PKCS1.php +++ /dev/null @@ -1,160 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\RSA\Formats\Keys; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\Common\Formats\Keys\PKCS1 as Progenitor; -use phpseclib3\File\ASN1; -use phpseclib3\File\ASN1\Maps; -use phpseclib3\Math\BigInteger; - -/** - * PKCS#1 Formatted RSA Key Handler - * - * @author Jim Wigginton - */ -abstract class PKCS1 extends Progenitor -{ - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - if (!Strings::is_stringable($key)) { - throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key)); - } - - if (strpos($key, 'PUBLIC') !== false) { - $components = ['isPublicKey' => true]; - } elseif (strpos($key, 'PRIVATE') !== false) { - $components = ['isPublicKey' => false]; - } else { - $components = []; - } - - $key = parent::load($key, $password); - - $decoded = ASN1::decodeBER($key); - if (!$decoded) { - throw new \RuntimeException('Unable to decode BER'); - } - - $key = ASN1::asn1map($decoded[0], Maps\RSAPrivateKey::MAP); - if (is_array($key)) { - $components += [ - 'modulus' => $key['modulus'], - 'publicExponent' => $key['publicExponent'], - 'privateExponent' => $key['privateExponent'], - 'primes' => [1 => $key['prime1'], $key['prime2']], - 'exponents' => [1 => $key['exponent1'], $key['exponent2']], - 'coefficients' => [2 => $key['coefficient']] - ]; - if ($key['version'] == 'multi') { - foreach ($key['otherPrimeInfos'] as $primeInfo) { - $components['primes'][] = $primeInfo['prime']; - $components['exponents'][] = $primeInfo['exponent']; - $components['coefficients'][] = $primeInfo['coefficient']; - } - } - if (!isset($components['isPublicKey'])) { - $components['isPublicKey'] = false; - } - return $components; - } - - $key = ASN1::asn1map($decoded[0], Maps\RSAPublicKey::MAP); - - if (!is_array($key)) { - throw new \RuntimeException('Unable to perform ASN1 mapping'); - } - - if (!isset($components['isPublicKey'])) { - $components['isPublicKey'] = true; - } - - return $components + $key; - } - - /** - * Convert a private key to the appropriate format. - * - * @param \phpseclib3\Math\BigInteger $n - * @param \phpseclib3\Math\BigInteger $e - * @param \phpseclib3\Math\BigInteger $d - * @param array $primes - * @param array $exponents - * @param array $coefficients - * @param string $password optional - * @param array $options optional - * @return string - */ - public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '', array $options = []) - { - $num_primes = count($primes); - $key = [ - 'version' => $num_primes == 2 ? 'two-prime' : 'multi', - 'modulus' => $n, - 'publicExponent' => $e, - 'privateExponent' => $d, - 'prime1' => $primes[1], - 'prime2' => $primes[2], - 'exponent1' => $exponents[1], - 'exponent2' => $exponents[2], - 'coefficient' => $coefficients[2] - ]; - for ($i = 3; $i <= $num_primes; $i++) { - $key['otherPrimeInfos'][] = [ - 'prime' => $primes[$i], - 'exponent' => $exponents[$i], - 'coefficient' => $coefficients[$i] - ]; - } - - $key = ASN1::encodeDER($key, Maps\RSAPrivateKey::MAP); - - return self::wrapPrivateKey($key, 'RSA', $password, $options); - } - - /** - * Convert a public key to the appropriate format - * - * @param \phpseclib3\Math\BigInteger $n - * @param \phpseclib3\Math\BigInteger $e - * @return string - */ - public static function savePublicKey(BigInteger $n, BigInteger $e) - { - $key = [ - 'modulus' => $n, - 'publicExponent' => $e - ]; - - $key = ASN1::encodeDER($key, Maps\RSAPublicKey::MAP); - - return self::wrapPublicKey($key, 'RSA'); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PKCS8.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PKCS8.php deleted file mode 100644 index 1eaac6ef..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PKCS8.php +++ /dev/null @@ -1,122 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\RSA\Formats\Keys; - -use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor; -use phpseclib3\File\ASN1; -use phpseclib3\Math\BigInteger; - -/** - * PKCS#8 Formatted RSA Key Handler - * - * @author Jim Wigginton - */ -abstract class PKCS8 extends Progenitor -{ - /** - * OID Name - * - * @var string - */ - const OID_NAME = 'rsaEncryption'; - - /** - * OID Value - * - * @var string - */ - const OID_VALUE = '1.2.840.113549.1.1.1'; - - /** - * Child OIDs loaded - * - * @var bool - */ - protected static $childOIDsLoaded = false; - - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - $key = parent::load($key, $password); - - if (isset($key['privateKey'])) { - $components['isPublicKey'] = false; - $type = 'private'; - } else { - $components['isPublicKey'] = true; - $type = 'public'; - } - - $result = $components + PKCS1::load($key[$type . 'Key']); - - if (isset($key['meta'])) { - $result['meta'] = $key['meta']; - } - - return $result; - } - - /** - * Convert a private key to the appropriate format. - * - * @param \phpseclib3\Math\BigInteger $n - * @param \phpseclib3\Math\BigInteger $e - * @param \phpseclib3\Math\BigInteger $d - * @param array $primes - * @param array $exponents - * @param array $coefficients - * @param string $password optional - * @param array $options optional - * @return string - */ - public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '', array $options = []) - { - $key = PKCS1::savePrivateKey($n, $e, $d, $primes, $exponents, $coefficients); - $key = ASN1::extractBER($key); - return self::wrapPrivateKey($key, [], null, $password, null, '', $options); - } - - /** - * Convert a public key to the appropriate format - * - * @param \phpseclib3\Math\BigInteger $n - * @param \phpseclib3\Math\BigInteger $e - * @param array $options optional - * @return string - */ - public static function savePublicKey(BigInteger $n, BigInteger $e, array $options = []) - { - $key = PKCS1::savePublicKey($n, $e); - $key = ASN1::extractBER($key); - return self::wrapPublicKey($key, null); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PSS.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PSS.php deleted file mode 100644 index ed75b9b7..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PSS.php +++ /dev/null @@ -1,238 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\RSA\Formats\Keys; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor; -use phpseclib3\File\ASN1; -use phpseclib3\File\ASN1\Maps; -use phpseclib3\Math\BigInteger; - -/** - * PKCS#8 Formatted RSA-PSS Key Handler - * - * @author Jim Wigginton - */ -abstract class PSS extends Progenitor -{ - /** - * OID Name - * - * @var string - */ - const OID_NAME = 'id-RSASSA-PSS'; - - /** - * OID Value - * - * @var string - */ - const OID_VALUE = '1.2.840.113549.1.1.10'; - - /** - * OIDs loaded - * - * @var bool - */ - private static $oidsLoaded = false; - - /** - * Child OIDs loaded - * - * @var bool - */ - protected static $childOIDsLoaded = false; - - /** - * Initialize static variables - */ - private static function initialize_static_variables() - { - if (!self::$oidsLoaded) { - ASN1::loadOIDs([ - 'md2' => '1.2.840.113549.2.2', - 'md4' => '1.2.840.113549.2.4', - 'md5' => '1.2.840.113549.2.5', - 'id-sha1' => '1.3.14.3.2.26', - 'id-sha256' => '2.16.840.1.101.3.4.2.1', - 'id-sha384' => '2.16.840.1.101.3.4.2.2', - 'id-sha512' => '2.16.840.1.101.3.4.2.3', - 'id-sha224' => '2.16.840.1.101.3.4.2.4', - 'id-sha512/224' => '2.16.840.1.101.3.4.2.5', - 'id-sha512/256' => '2.16.840.1.101.3.4.2.6', - - 'id-mgf1' => '1.2.840.113549.1.1.8' - ]); - self::$oidsLoaded = true; - } - } - - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - self::initialize_static_variables(); - - if (!Strings::is_stringable($key)) { - throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key)); - } - - $components = ['isPublicKey' => strpos($key, 'PUBLIC') !== false]; - - $key = parent::load($key, $password); - - $type = isset($key['privateKey']) ? 'private' : 'public'; - - $result = $components + PKCS1::load($key[$type . 'Key']); - - if (isset($key[$type . 'KeyAlgorithm']['parameters'])) { - $decoded = ASN1::decodeBER($key[$type . 'KeyAlgorithm']['parameters']); - if ($decoded === false) { - throw new \UnexpectedValueException('Unable to decode parameters'); - } - $params = ASN1::asn1map($decoded[0], Maps\RSASSA_PSS_params::MAP); - } else { - $params = []; - } - - if (isset($params['maskGenAlgorithm']['parameters'])) { - $decoded = ASN1::decodeBER($params['maskGenAlgorithm']['parameters']); - if ($decoded === false) { - throw new \UnexpectedValueException('Unable to decode parameters'); - } - $params['maskGenAlgorithm']['parameters'] = ASN1::asn1map($decoded[0], Maps\HashAlgorithm::MAP); - } else { - $params['maskGenAlgorithm'] = [ - 'algorithm' => 'id-mgf1', - 'parameters' => ['algorithm' => 'id-sha1'] - ]; - } - - if (!isset($params['hashAlgorithm']['algorithm'])) { - $params['hashAlgorithm']['algorithm'] = 'id-sha1'; - } - - $result['hash'] = str_replace('id-', '', $params['hashAlgorithm']['algorithm']); - $result['MGFHash'] = str_replace('id-', '', $params['maskGenAlgorithm']['parameters']['algorithm']); - if (isset($params['saltLength'])) { - $result['saltLength'] = (int) $params['saltLength']->toString(); - } - - if (isset($key['meta'])) { - $result['meta'] = $key['meta']; - } - - return $result; - } - - /** - * Convert a private key to the appropriate format. - * - * @param \phpseclib3\Math\BigInteger $n - * @param \phpseclib3\Math\BigInteger $e - * @param \phpseclib3\Math\BigInteger $d - * @param array $primes - * @param array $exponents - * @param array $coefficients - * @param string $password optional - * @param array $options optional - * @return string - */ - public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '', array $options = []) - { - self::initialize_static_variables(); - - $key = PKCS1::savePrivateKey($n, $e, $d, $primes, $exponents, $coefficients); - $key = ASN1::extractBER($key); - $params = self::savePSSParams($options); - return self::wrapPrivateKey($key, [], $params, $password, null, '', $options); - } - - /** - * Convert a public key to the appropriate format - * - * @param \phpseclib3\Math\BigInteger $n - * @param \phpseclib3\Math\BigInteger $e - * @param array $options optional - * @return string - */ - public static function savePublicKey(BigInteger $n, BigInteger $e, array $options = []) - { - self::initialize_static_variables(); - - $key = PKCS1::savePublicKey($n, $e); - $key = ASN1::extractBER($key); - $params = self::savePSSParams($options); - return self::wrapPublicKey($key, $params); - } - - /** - * Encodes PSS parameters - * - * @param array $options - * @return string - */ - public static function savePSSParams(array $options) - { - /* - The trailerField field is an integer. It provides - compatibility with IEEE Std 1363a-2004 [P1363A]. The value - MUST be 1, which represents the trailer field with hexadecimal - value 0xBC. Other trailer fields, including the trailer field - composed of HashID concatenated with 0xCC that is specified in - IEEE Std 1363a, are not supported. Implementations that - perform signature generation MUST omit the trailerField field, - indicating that the default trailer field value was used. - Implementations that perform signature validation MUST - recognize both a present trailerField field with value 1 and an - absent trailerField field. - - source: https://tools.ietf.org/html/rfc4055#page-9 - */ - $params = [ - 'trailerField' => new BigInteger(1) - ]; - if (isset($options['hash'])) { - $params['hashAlgorithm']['algorithm'] = 'id-' . $options['hash']; - } - if (isset($options['MGFHash'])) { - $temp = ['algorithm' => 'id-' . $options['MGFHash']]; - $temp = ASN1::encodeDER($temp, Maps\HashAlgorithm::MAP); - $params['maskGenAlgorithm'] = [ - 'algorithm' => 'id-mgf1', - 'parameters' => new ASN1\Element($temp) - ]; - } - if (isset($options['saltLength'])) { - $params['saltLength'] = new BigInteger($options['saltLength']); - } - - return new ASN1\Element(ASN1::encodeDER($params, Maps\RSASSA_PSS_params::MAP)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PuTTY.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PuTTY.php deleted file mode 100644 index fe35717b..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PuTTY.php +++ /dev/null @@ -1,121 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\RSA\Formats\Keys; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\Common\Formats\Keys\PuTTY as Progenitor; -use phpseclib3\Math\BigInteger; - -/** - * PuTTY Formatted RSA Key Handler - * - * @author Jim Wigginton - */ -abstract class PuTTY extends Progenitor -{ - /** - * Public Handler - * - * @var string - */ - const PUBLIC_HANDLER = 'phpseclib3\Crypt\RSA\Formats\Keys\OpenSSH'; - - /** - * Algorithm Identifier - * - * @var array - */ - protected static $types = ['ssh-rsa']; - - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - static $one; - if (!isset($one)) { - $one = new BigInteger(1); - } - - $components = parent::load($key, $password); - if (!isset($components['private'])) { - return $components; - } - extract($components); - unset($components['public'], $components['private']); - - $isPublicKey = false; - - $result = Strings::unpackSSH2('ii', $public); - if ($result === false) { - throw new \UnexpectedValueException('Key appears to be malformed'); - } - list($publicExponent, $modulus) = $result; - - $result = Strings::unpackSSH2('iiii', $private); - if ($result === false) { - throw new \UnexpectedValueException('Key appears to be malformed'); - } - $primes = $coefficients = []; - list($privateExponent, $primes[1], $primes[2], $coefficients[2]) = $result; - - $temp = $primes[1]->subtract($one); - $exponents = [1 => $publicExponent->modInverse($temp)]; - $temp = $primes[2]->subtract($one); - $exponents[] = $publicExponent->modInverse($temp); - - return compact('publicExponent', 'modulus', 'privateExponent', 'primes', 'coefficients', 'exponents', 'comment', 'isPublicKey'); - } - - /** - * Convert a private key to the appropriate format. - * - * @param \phpseclib3\Math\BigInteger $n - * @param \phpseclib3\Math\BigInteger $e - * @param \phpseclib3\Math\BigInteger $d - * @param array $primes - * @param array $exponents - * @param array $coefficients - * @param string $password optional - * @param array $options optional - * @return string - */ - public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '', array $options = []) - { - if (count($primes) != 2) { - throw new \InvalidArgumentException('PuTTY does not support multi-prime RSA keys'); - } - - $public = Strings::packSSH2('ii', $e, $n); - $private = Strings::packSSH2('iiii', $d, $primes[1], $primes[2], $coefficients[2]); - - return self::wrapPrivateKey($public, $private, 'ssh-rsa', $password, $options); - } - - /** - * Convert a public key to the appropriate format - * - * @param \phpseclib3\Math\BigInteger $n - * @param \phpseclib3\Math\BigInteger $e - * @return string - */ - public static function savePublicKey(BigInteger $n, BigInteger $e) - { - return self::wrapPublicKey(Strings::packSSH2('ii', $e, $n), 'ssh-rsa'); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/Raw.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/Raw.php deleted file mode 100644 index db728784..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/Raw.php +++ /dev/null @@ -1,184 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\RSA\Formats\Keys; - -use phpseclib3\Math\BigInteger; - -/** - * Raw RSA Key Handler - * - * @author Jim Wigginton - */ -abstract class Raw -{ - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - if (!is_array($key)) { - throw new \UnexpectedValueException('Key should be a array - not a ' . gettype($key)); - } - - $key = array_change_key_case($key, CASE_LOWER); - - $components = ['isPublicKey' => false]; - - foreach (['e', 'exponent', 'publicexponent', 0, 'privateexponent', 'd'] as $index) { - if (isset($key[$index])) { - $components['publicExponent'] = $key[$index]; - break; - } - } - - foreach (['n', 'modulo', 'modulus', 1] as $index) { - if (isset($key[$index])) { - $components['modulus'] = $key[$index]; - break; - } - } - - if (!isset($components['publicExponent']) || !isset($components['modulus'])) { - throw new \UnexpectedValueException('Modulus / exponent not present'); - } - - if (isset($key['primes'])) { - $components['primes'] = $key['primes']; - } elseif (isset($key['p']) && isset($key['q'])) { - $indices = [ - ['p', 'q'], - ['prime1', 'prime2'] - ]; - foreach ($indices as $index) { - list($i0, $i1) = $index; - if (isset($key[$i0]) && isset($key[$i1])) { - $components['primes'] = [1 => $key[$i0], $key[$i1]]; - } - } - } - - if (isset($key['exponents'])) { - $components['exponents'] = $key['exponents']; - } else { - $indices = [ - ['dp', 'dq'], - ['exponent1', 'exponent2'] - ]; - foreach ($indices as $index) { - list($i0, $i1) = $index; - if (isset($key[$i0]) && isset($key[$i1])) { - $components['exponents'] = [1 => $key[$i0], $key[$i1]]; - } - } - } - - if (isset($key['coefficients'])) { - $components['coefficients'] = $key['coefficients']; - } else { - foreach (['inverseq', 'q\'', 'coefficient'] as $index) { - if (isset($key[$index])) { - $components['coefficients'] = [2 => $key[$index]]; - } - } - } - - if (!isset($components['primes'])) { - $components['isPublicKey'] = true; - return $components; - } - - if (!isset($components['exponents'])) { - $one = new BigInteger(1); - $temp = $components['primes'][1]->subtract($one); - $exponents = [1 => $components['publicExponent']->modInverse($temp)]; - $temp = $components['primes'][2]->subtract($one); - $exponents[] = $components['publicExponent']->modInverse($temp); - $components['exponents'] = $exponents; - } - - if (!isset($components['coefficients'])) { - $components['coefficients'] = [2 => $components['primes'][2]->modInverse($components['primes'][1])]; - } - - foreach (['privateexponent', 'd'] as $index) { - if (isset($key[$index])) { - $components['privateExponent'] = $key[$index]; - break; - } - } - - return $components; - } - - /** - * Convert a private key to the appropriate format. - * - * @param \phpseclib3\Math\BigInteger $n - * @param \phpseclib3\Math\BigInteger $e - * @param \phpseclib3\Math\BigInteger $d - * @param array $primes - * @param array $exponents - * @param array $coefficients - * @param string $password optional - * @param array $options optional - * @return array - */ - public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '', array $options = []) - { - if (!empty($password) && is_string($password)) { - throw new UnsupportedFormatException('Raw private keys do not support encryption'); - } - - return [ - 'e' => clone $e, - 'n' => clone $n, - 'd' => clone $d, - 'primes' => array_map(function ($var) { - return clone $var; - }, $primes), - 'exponents' => array_map(function ($var) { - return clone $var; - }, $exponents), - 'coefficients' => array_map(function ($var) { - return clone $var; - }, $coefficients) - ]; - } - - /** - * Convert a public key to the appropriate format - * - * @param \phpseclib3\Math\BigInteger $n - * @param \phpseclib3\Math\BigInteger $e - * @return array - */ - public static function savePublicKey(BigInteger $n, BigInteger $e) - { - return ['e' => clone $e, 'n' => clone $n]; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/XML.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/XML.php deleted file mode 100644 index 280048cc..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/XML.php +++ /dev/null @@ -1,171 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\RSA\Formats\Keys; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Exception\BadConfigurationException; -use phpseclib3\Exception\UnsupportedFormatException; -use phpseclib3\Math\BigInteger; - -/** - * XML Formatted RSA Key Handler - * - * @author Jim Wigginton - */ -abstract class XML -{ - /** - * Break a public or private key down into its constituent components - * - * @param string $key - * @param string $password optional - * @return array - */ - public static function load($key, $password = '') - { - if (!Strings::is_stringable($key)) { - throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key)); - } - - if (!class_exists('DOMDocument')) { - throw new BadConfigurationException('The dom extension is not setup correctly on this system'); - } - - $components = [ - 'isPublicKey' => false, - 'primes' => [], - 'exponents' => [], - 'coefficients' => [] - ]; - - $use_errors = libxml_use_internal_errors(true); - - $dom = new \DOMDocument(); - if (substr($key, 0, 5) != '' . $key . ''; - } - if (!$dom->loadXML($key)) { - libxml_use_internal_errors($use_errors); - throw new \UnexpectedValueException('Key does not appear to contain XML'); - } - $xpath = new \DOMXPath($dom); - $keys = ['modulus', 'exponent', 'p', 'q', 'dp', 'dq', 'inverseq', 'd']; - foreach ($keys as $key) { - // $dom->getElementsByTagName($key) is case-sensitive - $temp = $xpath->query("//*[translate(local-name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='$key']"); - if (!$temp->length) { - continue; - } - $value = new BigInteger(Strings::base64_decode($temp->item(0)->nodeValue), 256); - switch ($key) { - case 'modulus': - $components['modulus'] = $value; - break; - case 'exponent': - $components['publicExponent'] = $value; - break; - case 'p': - $components['primes'][1] = $value; - break; - case 'q': - $components['primes'][2] = $value; - break; - case 'dp': - $components['exponents'][1] = $value; - break; - case 'dq': - $components['exponents'][2] = $value; - break; - case 'inverseq': - $components['coefficients'][2] = $value; - break; - case 'd': - $components['privateExponent'] = $value; - } - } - - libxml_use_internal_errors($use_errors); - - foreach ($components as $key => $value) { - if (is_array($value) && !count($value)) { - unset($components[$key]); - } - } - - if (isset($components['modulus']) && isset($components['publicExponent'])) { - if (count($components) == 3) { - $components['isPublicKey'] = true; - } - return $components; - } - - throw new \UnexpectedValueException('Modulus / exponent not present'); - } - - /** - * Convert a private key to the appropriate format. - * - * @param \phpseclib3\Math\BigInteger $n - * @param \phpseclib3\Math\BigInteger $e - * @param \phpseclib3\Math\BigInteger $d - * @param array $primes - * @param array $exponents - * @param array $coefficients - * @param string $password optional - * @return string - */ - public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '') - { - if (count($primes) != 2) { - throw new \InvalidArgumentException('XML does not support multi-prime RSA keys'); - } - - if (!empty($password) && is_string($password)) { - throw new UnsupportedFormatException('XML private keys do not support encryption'); - } - - return "\r\n" . - ' ' . Strings::base64_encode($n->toBytes()) . "\r\n" . - ' ' . Strings::base64_encode($e->toBytes()) . "\r\n" . - '

' . Strings::base64_encode($primes[1]->toBytes()) . "

\r\n" . - ' ' . Strings::base64_encode($primes[2]->toBytes()) . "\r\n" . - ' ' . Strings::base64_encode($exponents[1]->toBytes()) . "\r\n" . - ' ' . Strings::base64_encode($exponents[2]->toBytes()) . "\r\n" . - ' ' . Strings::base64_encode($coefficients[2]->toBytes()) . "\r\n" . - ' ' . Strings::base64_encode($d->toBytes()) . "\r\n" . - '
'; - } - - /** - * Convert a public key to the appropriate format - * - * @param \phpseclib3\Math\BigInteger $n - * @param \phpseclib3\Math\BigInteger $e - * @return string - */ - public static function savePublicKey(BigInteger $n, BigInteger $e) - { - return "\r\n" . - ' ' . Strings::base64_encode($n->toBytes()) . "\r\n" . - ' ' . Strings::base64_encode($e->toBytes()) . "\r\n" . - ''; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PrivateKey.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PrivateKey.php deleted file mode 100644 index 37dd09a4..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PrivateKey.php +++ /dev/null @@ -1,530 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\RSA; - -use phpseclib3\Crypt\Common; -use phpseclib3\Crypt\Random; -use phpseclib3\Crypt\RSA; -use phpseclib3\Crypt\RSA\Formats\Keys\PSS; -use phpseclib3\Exception\UnsupportedFormatException; -use phpseclib3\Math\BigInteger; - -/** - * Raw RSA Key Handler - * - * @author Jim Wigginton - */ -final class PrivateKey extends RSA implements Common\PrivateKey -{ - use Common\Traits\PasswordProtected; - - /** - * Primes for Chinese Remainder Theorem (ie. p and q) - * - * @var array - */ - protected $primes; - - /** - * Exponents for Chinese Remainder Theorem (ie. dP and dQ) - * - * @var array - */ - protected $exponents; - - /** - * Coefficients for Chinese Remainder Theorem (ie. qInv) - * - * @var array - */ - protected $coefficients; - - /** - * Private Exponent - * - * @var \phpseclib3\Math\BigInteger - */ - protected $privateExponent; - - /** - * RSADP - * - * See {@link http://tools.ietf.org/html/rfc3447#section-5.1.2 RFC3447#section-5.1.2}. - * - * @return bool|\phpseclib3\Math\BigInteger - */ - private function rsadp(BigInteger $c) - { - if ($c->compare(self::$zero) < 0 || $c->compare($this->modulus) > 0) { - throw new \OutOfRangeException('Ciphertext representative out of range'); - } - return $this->exponentiate($c); - } - - /** - * RSASP1 - * - * See {@link http://tools.ietf.org/html/rfc3447#section-5.2.1 RFC3447#section-5.2.1}. - * - * @return bool|\phpseclib3\Math\BigInteger - */ - private function rsasp1(BigInteger $m) - { - if ($m->compare(self::$zero) < 0 || $m->compare($this->modulus) > 0) { - throw new \OutOfRangeException('Signature representative out of range'); - } - return $this->exponentiate($m); - } - - /** - * Exponentiate - * - * @param \phpseclib3\Math\BigInteger $x - * @return \phpseclib3\Math\BigInteger - */ - protected function exponentiate(BigInteger $x) - { - switch (true) { - case empty($this->primes): - case $this->primes[1]->equals(self::$zero): - case empty($this->coefficients): - case $this->coefficients[2]->equals(self::$zero): - case empty($this->exponents): - case $this->exponents[1]->equals(self::$zero): - return $x->modPow($this->exponent, $this->modulus); - } - - $num_primes = count($this->primes); - - if (!static::$enableBlinding) { - $m_i = [ - 1 => $x->modPow($this->exponents[1], $this->primes[1]), - 2 => $x->modPow($this->exponents[2], $this->primes[2]) - ]; - $h = $m_i[1]->subtract($m_i[2]); - $h = $h->multiply($this->coefficients[2]); - list(, $h) = $h->divide($this->primes[1]); - $m = $m_i[2]->add($h->multiply($this->primes[2])); - - $r = $this->primes[1]; - for ($i = 3; $i <= $num_primes; $i++) { - $m_i = $x->modPow($this->exponents[$i], $this->primes[$i]); - - $r = $r->multiply($this->primes[$i - 1]); - - $h = $m_i->subtract($m); - $h = $h->multiply($this->coefficients[$i]); - list(, $h) = $h->divide($this->primes[$i]); - - $m = $m->add($r->multiply($h)); - } - } else { - $smallest = $this->primes[1]; - for ($i = 2; $i <= $num_primes; $i++) { - if ($smallest->compare($this->primes[$i]) > 0) { - $smallest = $this->primes[$i]; - } - } - - $r = BigInteger::randomRange(self::$one, $smallest->subtract(self::$one)); - - $m_i = [ - 1 => $this->blind($x, $r, 1), - 2 => $this->blind($x, $r, 2) - ]; - $h = $m_i[1]->subtract($m_i[2]); - $h = $h->multiply($this->coefficients[2]); - list(, $h) = $h->divide($this->primes[1]); - $m = $m_i[2]->add($h->multiply($this->primes[2])); - - $r = $this->primes[1]; - for ($i = 3; $i <= $num_primes; $i++) { - $m_i = $this->blind($x, $r, $i); - - $r = $r->multiply($this->primes[$i - 1]); - - $h = $m_i->subtract($m); - $h = $h->multiply($this->coefficients[$i]); - list(, $h) = $h->divide($this->primes[$i]); - - $m = $m->add($r->multiply($h)); - } - } - - return $m; - } - - /** - * Performs RSA Blinding - * - * Protects against timing attacks by employing RSA Blinding. - * Returns $x->modPow($this->exponents[$i], $this->primes[$i]) - * - * @param \phpseclib3\Math\BigInteger $x - * @param \phpseclib3\Math\BigInteger $r - * @param int $i - * @return \phpseclib3\Math\BigInteger - */ - private function blind(BigInteger $x, BigInteger $r, $i) - { - $x = $x->multiply($r->modPow($this->publicExponent, $this->primes[$i])); - $x = $x->modPow($this->exponents[$i], $this->primes[$i]); - - $r = $r->modInverse($this->primes[$i]); - $x = $x->multiply($r); - list(, $x) = $x->divide($this->primes[$i]); - - return $x; - } - - /** - * EMSA-PSS-ENCODE - * - * See {@link http://tools.ietf.org/html/rfc3447#section-9.1.1 RFC3447#section-9.1.1}. - * - * @return string - * @param string $m - * @throws \RuntimeException on encoding error - * @param int $emBits - */ - private function emsa_pss_encode($m, $emBits) - { - // if $m is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error - // be output. - - $emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8) - $sLen = $this->sLen !== null ? $this->sLen : $this->hLen; - - $mHash = $this->hash->hash($m); - if ($emLen < $this->hLen + $sLen + 2) { - throw new \LengthException('RSA modulus too short'); - } - - $salt = Random::string($sLen); - $m2 = "\0\0\0\0\0\0\0\0" . $mHash . $salt; - $h = $this->hash->hash($m2); - $ps = str_repeat(chr(0), $emLen - $sLen - $this->hLen - 2); - $db = $ps . chr(1) . $salt; - $dbMask = $this->mgf1($h, $emLen - $this->hLen - 1); // ie. stlren($db) - $maskedDB = $db ^ $dbMask; - $maskedDB[0] = ~chr(0xFF << ($emBits & 7)) & $maskedDB[0]; - $em = $maskedDB . $h . chr(0xBC); - - return $em; - } - - /** - * RSASSA-PSS-SIGN - * - * See {@link http://tools.ietf.org/html/rfc3447#section-8.1.1 RFC3447#section-8.1.1}. - * - * @param string $m - * @return bool|string - */ - private function rsassa_pss_sign($m) - { - // EMSA-PSS encoding - - $em = $this->emsa_pss_encode($m, 8 * $this->k - 1); - - // RSA signature - - $m = $this->os2ip($em); - $s = $this->rsasp1($m); - $s = $this->i2osp($s, $this->k); - - // Output the signature S - - return $s; - } - - /** - * RSASSA-PKCS1-V1_5-SIGN - * - * See {@link http://tools.ietf.org/html/rfc3447#section-8.2.1 RFC3447#section-8.2.1}. - * - * @param string $m - * @throws \LengthException if the RSA modulus is too short - * @return bool|string - */ - private function rsassa_pkcs1_v1_5_sign($m) - { - // EMSA-PKCS1-v1_5 encoding - - // If the encoding operation outputs "intended encoded message length too short," output "RSA modulus - // too short" and stop. - try { - $em = $this->emsa_pkcs1_v1_5_encode($m, $this->k); - } catch (\LengthException $e) { - throw new \LengthException('RSA modulus too short'); - } - - // RSA signature - - $m = $this->os2ip($em); - $s = $this->rsasp1($m); - $s = $this->i2osp($s, $this->k); - - // Output the signature S - - return $s; - } - - /** - * Create a signature - * - * @see self::verify() - * @param string $message - * @return string - */ - public function sign($message) - { - switch ($this->signaturePadding) { - case self::SIGNATURE_PKCS1: - case self::SIGNATURE_RELAXED_PKCS1: - return $this->rsassa_pkcs1_v1_5_sign($message); - //case self::SIGNATURE_PSS: - default: - return $this->rsassa_pss_sign($message); - } - } - - /** - * RSAES-PKCS1-V1_5-DECRYPT - * - * See {@link http://tools.ietf.org/html/rfc3447#section-7.2.2 RFC3447#section-7.2.2}. - * - * @param string $c - * @return bool|string - */ - private function rsaes_pkcs1_v1_5_decrypt($c) - { - // Length checking - - if (strlen($c) != $this->k) { // or if k < 11 - throw new \LengthException('Ciphertext representative too long'); - } - - // RSA decryption - - $c = $this->os2ip($c); - $m = $this->rsadp($c); - $em = $this->i2osp($m, $this->k); - - // EME-PKCS1-v1_5 decoding - - if (ord($em[0]) != 0 || ord($em[1]) > 2) { - throw new \RuntimeException('Decryption error'); - } - - $ps = substr($em, 2, strpos($em, chr(0), 2) - 2); - $m = substr($em, strlen($ps) + 3); - - if (strlen($ps) < 8) { - throw new \RuntimeException('Decryption error'); - } - - // Output M - - return $m; - } - - /** - * RSAES-OAEP-DECRYPT - * - * See {@link http://tools.ietf.org/html/rfc3447#section-7.1.2 RFC3447#section-7.1.2}. The fact that the error - * messages aren't distinguishable from one another hinders debugging, but, to quote from RFC3447#section-7.1.2: - * - * Note. Care must be taken to ensure that an opponent cannot - * distinguish the different error conditions in Step 3.g, whether by - * error message or timing, or, more generally, learn partial - * information about the encoded message EM. Otherwise an opponent may - * be able to obtain useful information about the decryption of the - * ciphertext C, leading to a chosen-ciphertext attack such as the one - * observed by Manger [36]. - * - * @param string $c - * @return bool|string - */ - private function rsaes_oaep_decrypt($c) - { - // Length checking - - // if $l is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error - // be output. - - if (strlen($c) != $this->k || $this->k < 2 * $this->hLen + 2) { - throw new \LengthException('Ciphertext representative too long'); - } - - // RSA decryption - - $c = $this->os2ip($c); - $m = $this->rsadp($c); - $em = $this->i2osp($m, $this->k); - - // EME-OAEP decoding - - $lHash = $this->hash->hash($this->label); - $y = ord($em[0]); - $maskedSeed = substr($em, 1, $this->hLen); - $maskedDB = substr($em, $this->hLen + 1); - $seedMask = $this->mgf1($maskedDB, $this->hLen); - $seed = $maskedSeed ^ $seedMask; - $dbMask = $this->mgf1($seed, $this->k - $this->hLen - 1); - $db = $maskedDB ^ $dbMask; - $lHash2 = substr($db, 0, $this->hLen); - $m = substr($db, $this->hLen); - $hashesMatch = hash_equals($lHash, $lHash2); - $leadingZeros = 1; - $patternMatch = 0; - $offset = 0; - for ($i = 0; $i < strlen($m); $i++) { - $patternMatch |= $leadingZeros & ($m[$i] === "\1"); - $leadingZeros &= $m[$i] === "\0"; - $offset += $patternMatch ? 0 : 1; - } - - // we do | instead of || to avoid https://en.wikipedia.org/wiki/Short-circuit_evaluation - // to protect against timing attacks - if (!$hashesMatch | !$patternMatch) { - throw new \RuntimeException('Decryption error'); - } - - // Output the message M - - return substr($m, $offset + 1); - } - - /** - * Raw Encryption / Decryption - * - * Doesn't use padding and is not recommended. - * - * @param string $m - * @return bool|string - * @throws \LengthException if strlen($m) > $this->k - */ - private function raw_encrypt($m) - { - if (strlen($m) > $this->k) { - throw new \LengthException('Ciphertext representative too long'); - } - - $temp = $this->os2ip($m); - $temp = $this->rsadp($temp); - return $this->i2osp($temp, $this->k); - } - - /** - * Decryption - * - * @see self::encrypt() - * @param string $ciphertext - * @return bool|string - */ - public function decrypt($ciphertext) - { - switch ($this->encryptionPadding) { - case self::ENCRYPTION_NONE: - return $this->raw_encrypt($ciphertext); - case self::ENCRYPTION_PKCS1: - return $this->rsaes_pkcs1_v1_5_decrypt($ciphertext); - //case self::ENCRYPTION_OAEP: - default: - return $this->rsaes_oaep_decrypt($ciphertext); - } - } - - /** - * Returns the public key - * - * @return mixed - */ - public function getPublicKey() - { - $type = self::validatePlugin('Keys', 'PKCS8', 'savePublicKey'); - if (empty($this->modulus) || empty($this->publicExponent)) { - throw new \RuntimeException('Public key components not found'); - } - - $key = $type::savePublicKey($this->modulus, $this->publicExponent); - return RSA::loadFormat('PKCS8', $key) - ->withHash($this->hash->getHash()) - ->withMGFHash($this->mgfHash->getHash()) - ->withSaltLength($this->sLen) - ->withLabel($this->label) - ->withPadding($this->signaturePadding | $this->encryptionPadding); - } - - /** - * Returns the private key - * - * @param string $type - * @param array $options optional - * @return string - */ - public function toString($type, array $options = []) - { - $type = self::validatePlugin( - 'Keys', - $type, - empty($this->primes) ? 'savePublicKey' : 'savePrivateKey' - ); - - if ($type == PSS::class) { - if ($this->signaturePadding == self::SIGNATURE_PSS) { - $options += [ - 'hash' => $this->hash->getHash(), - 'MGFHash' => $this->mgfHash->getHash(), - 'saltLength' => $this->getSaltLength() - ]; - } else { - throw new UnsupportedFormatException('The PSS format can only be used when the signature method has been explicitly set to PSS'); - } - } - - if (empty($this->primes)) { - return $type::savePublicKey($this->modulus, $this->exponent, $options); - } - - return $type::savePrivateKey($this->modulus, $this->publicExponent, $this->exponent, $this->primes, $this->exponents, $this->coefficients, $this->password, $options); - - /* - $key = $type::savePrivateKey($this->modulus, $this->publicExponent, $this->exponent, $this->primes, $this->exponents, $this->coefficients, $this->password, $options); - if ($key !== false || count($this->primes) == 2) { - return $key; - } - - $nSize = $this->getSize() >> 1; - - $primes = [1 => clone self::$one, clone self::$one]; - $i = 1; - foreach ($this->primes as $prime) { - $primes[$i] = $primes[$i]->multiply($prime); - if ($primes[$i]->getLength() >= $nSize) { - $i++; - } - } - - $exponents = []; - $coefficients = [2 => $primes[2]->modInverse($primes[1])]; - - foreach ($primes as $i => $prime) { - $temp = $prime->subtract(self::$one); - $exponents[$i] = $this->modulus->modInverse($temp); - } - - return $type::savePrivateKey($this->modulus, $this->publicExponent, $this->exponent, $primes, $exponents, $coefficients, $this->password, $options); - */ - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PublicKey.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PublicKey.php deleted file mode 100644 index 58939a9f..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PublicKey.php +++ /dev/null @@ -1,513 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt\RSA; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\Common; -use phpseclib3\Crypt\Hash; -use phpseclib3\Crypt\Random; -use phpseclib3\Crypt\RSA; -use phpseclib3\Crypt\RSA\Formats\Keys\PSS; -use phpseclib3\Exception\UnsupportedAlgorithmException; -use phpseclib3\Exception\UnsupportedFormatException; -use phpseclib3\File\ASN1; -use phpseclib3\File\ASN1\Maps\DigestInfo; -use phpseclib3\Math\BigInteger; - -/** - * Raw RSA Key Handler - * - * @author Jim Wigginton - */ -final class PublicKey extends RSA implements Common\PublicKey -{ - use Common\Traits\Fingerprint; - - /** - * Exponentiate - * - * @param \phpseclib3\Math\BigInteger $x - * @return \phpseclib3\Math\BigInteger - */ - private function exponentiate(BigInteger $x) - { - return $x->modPow($this->exponent, $this->modulus); - } - - /** - * RSAVP1 - * - * See {@link http://tools.ietf.org/html/rfc3447#section-5.2.2 RFC3447#section-5.2.2}. - * - * @param \phpseclib3\Math\BigInteger $s - * @return bool|\phpseclib3\Math\BigInteger - */ - private function rsavp1($s) - { - if ($s->compare(self::$zero) < 0 || $s->compare($this->modulus) > 0) { - return false; - } - return $this->exponentiate($s); - } - - /** - * RSASSA-PKCS1-V1_5-VERIFY - * - * See {@link http://tools.ietf.org/html/rfc3447#section-8.2.2 RFC3447#section-8.2.2}. - * - * @param string $m - * @param string $s - * @throws \LengthException if the RSA modulus is too short - * @return bool - */ - private function rsassa_pkcs1_v1_5_verify($m, $s) - { - // Length checking - - if (strlen($s) != $this->k) { - return false; - } - - // RSA verification - - $s = $this->os2ip($s); - $m2 = $this->rsavp1($s); - if ($m2 === false) { - return false; - } - $em = $this->i2osp($m2, $this->k); - if ($em === false) { - return false; - } - - // EMSA-PKCS1-v1_5 encoding - - $exception = false; - - // If the encoding operation outputs "intended encoded message length too short," output "RSA modulus - // too short" and stop. - try { - $em2 = $this->emsa_pkcs1_v1_5_encode($m, $this->k); - $r1 = hash_equals($em, $em2); - } catch (\LengthException $e) { - $exception = true; - } - - try { - $em3 = $this->emsa_pkcs1_v1_5_encode_without_null($m, $this->k); - $r2 = hash_equals($em, $em3); - } catch (\LengthException $e) { - $exception = true; - } catch (UnsupportedAlgorithmException $e) { - $r2 = false; - } - - if ($exception) { - throw new \LengthException('RSA modulus too short'); - } - - // Compare - return $r1 || $r2; - } - - /** - * RSASSA-PKCS1-V1_5-VERIFY (relaxed matching) - * - * Per {@link http://tools.ietf.org/html/rfc3447#page-43 RFC3447#page-43} PKCS1 v1.5 - * specified the use BER encoding rather than DER encoding that PKCS1 v2.0 specified. - * This means that under rare conditions you can have a perfectly valid v1.5 signature - * that fails to validate with _rsassa_pkcs1_v1_5_verify(). PKCS1 v2.1 also recommends - * that if you're going to validate these types of signatures you "should indicate - * whether the underlying BER encoding is a DER encoding and hence whether the signature - * is valid with respect to the specification given in [PKCS1 v2.0+]". so if you do - * $rsa->getLastPadding() and get RSA::PADDING_RELAXED_PKCS1 back instead of - * RSA::PADDING_PKCS1... that means BER encoding was used. - * - * @param string $m - * @param string $s - * @return bool - */ - private function rsassa_pkcs1_v1_5_relaxed_verify($m, $s) - { - // Length checking - - if (strlen($s) != $this->k) { - return false; - } - - // RSA verification - - $s = $this->os2ip($s); - $m2 = $this->rsavp1($s); - if ($m2 === false) { - return false; - } - $em = $this->i2osp($m2, $this->k); - if ($em === false) { - return false; - } - - if (Strings::shift($em, 2) != "\0\1") { - return false; - } - - $em = ltrim($em, "\xFF"); - if (Strings::shift($em) != "\0") { - return false; - } - - $decoded = ASN1::decodeBER($em); - if (!is_array($decoded) || empty($decoded[0]) || strlen($em) > $decoded[0]['length']) { - return false; - } - - static $oids; - if (!isset($oids)) { - $oids = [ - 'md2' => '1.2.840.113549.2.2', - 'md4' => '1.2.840.113549.2.4', // from PKCS1 v1.5 - 'md5' => '1.2.840.113549.2.5', - 'id-sha1' => '1.3.14.3.2.26', - 'id-sha256' => '2.16.840.1.101.3.4.2.1', - 'id-sha384' => '2.16.840.1.101.3.4.2.2', - 'id-sha512' => '2.16.840.1.101.3.4.2.3', - // from PKCS1 v2.2 - 'id-sha224' => '2.16.840.1.101.3.4.2.4', - 'id-sha512/224' => '2.16.840.1.101.3.4.2.5', - 'id-sha512/256' => '2.16.840.1.101.3.4.2.6', - ]; - ASN1::loadOIDs($oids); - } - - $decoded = ASN1::asn1map($decoded[0], DigestInfo::MAP); - if (!isset($decoded) || $decoded === false) { - return false; - } - - if (!isset($oids[$decoded['digestAlgorithm']['algorithm']])) { - return false; - } - - if (isset($decoded['digestAlgorithm']['parameters']) && $decoded['digestAlgorithm']['parameters'] !== ['null' => '']) { - return false; - } - - $hash = $decoded['digestAlgorithm']['algorithm']; - $hash = substr($hash, 0, 3) == 'id-' ? - substr($hash, 3) : - $hash; - $hash = new Hash($hash); - $em = $hash->hash($m); - $em2 = $decoded['digest']; - - return hash_equals($em, $em2); - } - - /** - * EMSA-PSS-VERIFY - * - * See {@link http://tools.ietf.org/html/rfc3447#section-9.1.2 RFC3447#section-9.1.2}. - * - * @param string $m - * @param string $em - * @param int $emBits - * @return string - */ - private function emsa_pss_verify($m, $em, $emBits) - { - // if $m is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error - // be output. - - $emLen = ($emBits + 7) >> 3; // ie. ceil($emBits / 8); - $sLen = $this->sLen !== null ? $this->sLen : $this->hLen; - - $mHash = $this->hash->hash($m); - if ($emLen < $this->hLen + $sLen + 2) { - return false; - } - - if ($em[strlen($em) - 1] != chr(0xBC)) { - return false; - } - - $maskedDB = substr($em, 0, -$this->hLen - 1); - $h = substr($em, -$this->hLen - 1, $this->hLen); - $temp = chr(0xFF << ($emBits & 7)); - if ((~$maskedDB[0] & $temp) != $temp) { - return false; - } - $dbMask = $this->mgf1($h, $emLen - $this->hLen - 1); - $db = $maskedDB ^ $dbMask; - $db[0] = ~chr(0xFF << ($emBits & 7)) & $db[0]; - $temp = $emLen - $this->hLen - $sLen - 2; - if (substr($db, 0, $temp) != str_repeat(chr(0), $temp) || ord($db[$temp]) != 1) { - return false; - } - $salt = substr($db, $temp + 1); // should be $sLen long - $m2 = "\0\0\0\0\0\0\0\0" . $mHash . $salt; - $h2 = $this->hash->hash($m2); - return hash_equals($h, $h2); - } - - /** - * RSASSA-PSS-VERIFY - * - * See {@link http://tools.ietf.org/html/rfc3447#section-8.1.2 RFC3447#section-8.1.2}. - * - * @param string $m - * @param string $s - * @return bool|string - */ - private function rsassa_pss_verify($m, $s) - { - // Length checking - - if (strlen($s) != $this->k) { - return false; - } - - // RSA verification - - $modBits = strlen($this->modulus->toBits()); - - $s2 = $this->os2ip($s); - $m2 = $this->rsavp1($s2); - $em = $this->i2osp($m2, $this->k); - if ($em === false) { - return false; - } - - // EMSA-PSS verification - - return $this->emsa_pss_verify($m, $em, $modBits - 1); - } - - /** - * Verifies a signature - * - * @see self::sign() - * @param string $message - * @param string $signature - * @return bool - */ - public function verify($message, $signature) - { - switch ($this->signaturePadding) { - case self::SIGNATURE_RELAXED_PKCS1: - return $this->rsassa_pkcs1_v1_5_relaxed_verify($message, $signature); - case self::SIGNATURE_PKCS1: - return $this->rsassa_pkcs1_v1_5_verify($message, $signature); - //case self::SIGNATURE_PSS: - default: - return $this->rsassa_pss_verify($message, $signature); - } - } - - /** - * RSAES-PKCS1-V1_5-ENCRYPT - * - * See {@link http://tools.ietf.org/html/rfc3447#section-7.2.1 RFC3447#section-7.2.1}. - * - * @param string $m - * @param bool $pkcs15_compat optional - * @throws \LengthException if strlen($m) > $this->k - 11 - * @return bool|string - */ - private function rsaes_pkcs1_v1_5_encrypt($m, $pkcs15_compat = false) - { - $mLen = strlen($m); - - // Length checking - - if ($mLen > $this->k - 11) { - throw new \LengthException('Message too long'); - } - - // EME-PKCS1-v1_5 encoding - - $psLen = $this->k - $mLen - 3; - $ps = ''; - while (strlen($ps) != $psLen) { - $temp = Random::string($psLen - strlen($ps)); - $temp = str_replace("\x00", '', $temp); - $ps .= $temp; - } - $type = 2; - $em = chr(0) . chr($type) . $ps . chr(0) . $m; - - // RSA encryption - $m = $this->os2ip($em); - $c = $this->rsaep($m); - $c = $this->i2osp($c, $this->k); - - // Output the ciphertext C - - return $c; - } - - /** - * RSAES-OAEP-ENCRYPT - * - * See {@link http://tools.ietf.org/html/rfc3447#section-7.1.1 RFC3447#section-7.1.1} and - * {http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding OAES}. - * - * @param string $m - * @throws \LengthException if strlen($m) > $this->k - 2 * $this->hLen - 2 - * @return string - */ - private function rsaes_oaep_encrypt($m) - { - $mLen = strlen($m); - - // Length checking - - // if $l is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error - // be output. - - if ($mLen > $this->k - 2 * $this->hLen - 2) { - throw new \LengthException('Message too long'); - } - - // EME-OAEP encoding - - $lHash = $this->hash->hash($this->label); - $ps = str_repeat(chr(0), $this->k - $mLen - 2 * $this->hLen - 2); - $db = $lHash . $ps . chr(1) . $m; - $seed = Random::string($this->hLen); - $dbMask = $this->mgf1($seed, $this->k - $this->hLen - 1); - $maskedDB = $db ^ $dbMask; - $seedMask = $this->mgf1($maskedDB, $this->hLen); - $maskedSeed = $seed ^ $seedMask; - $em = chr(0) . $maskedSeed . $maskedDB; - - // RSA encryption - - $m = $this->os2ip($em); - $c = $this->rsaep($m); - $c = $this->i2osp($c, $this->k); - - // Output the ciphertext C - - return $c; - } - - /** - * RSAEP - * - * See {@link http://tools.ietf.org/html/rfc3447#section-5.1.1 RFC3447#section-5.1.1}. - * - * @param \phpseclib3\Math\BigInteger $m - * @return bool|\phpseclib3\Math\BigInteger - */ - private function rsaep($m) - { - if ($m->compare(self::$zero) < 0 || $m->compare($this->modulus) > 0) { - throw new \OutOfRangeException('Message representative out of range'); - } - return $this->exponentiate($m); - } - - /** - * Raw Encryption / Decryption - * - * Doesn't use padding and is not recommended. - * - * @param string $m - * @return bool|string - * @throws \LengthException if strlen($m) > $this->k - */ - private function raw_encrypt($m) - { - if (strlen($m) > $this->k) { - throw new \LengthException('Message too long'); - } - - $temp = $this->os2ip($m); - $temp = $this->rsaep($temp); - return $this->i2osp($temp, $this->k); - } - - /** - * Encryption - * - * Both self::PADDING_OAEP and self::PADDING_PKCS1 both place limits on how long $plaintext can be. - * If $plaintext exceeds those limits it will be broken up so that it does and the resultant ciphertext's will - * be concatenated together. - * - * @see self::decrypt() - * @param string $plaintext - * @return bool|string - * @throws \LengthException if the RSA modulus is too short - */ - public function encrypt($plaintext) - { - switch ($this->encryptionPadding) { - case self::ENCRYPTION_NONE: - return $this->raw_encrypt($plaintext); - case self::ENCRYPTION_PKCS1: - return $this->rsaes_pkcs1_v1_5_encrypt($plaintext); - //case self::ENCRYPTION_OAEP: - default: - return $this->rsaes_oaep_encrypt($plaintext); - } - } - - /** - * Returns the public key - * - * The public key is only returned under two circumstances - if the private key had the public key embedded within it - * or if the public key was set via setPublicKey(). If the currently loaded key is supposed to be the public key this - * function won't return it since this library, for the most part, doesn't distinguish between public and private keys. - * - * @param string $type - * @param array $options optional - * @return mixed - */ - public function toString($type, array $options = []) - { - $type = self::validatePlugin('Keys', $type, 'savePublicKey'); - - if ($type == PSS::class) { - if ($this->signaturePadding == self::SIGNATURE_PSS) { - $options += [ - 'hash' => $this->hash->getHash(), - 'MGFHash' => $this->mgfHash->getHash(), - 'saltLength' => $this->getSaltLength() - ]; - } else { - throw new UnsupportedFormatException('The PSS format can only be used when the signature method has been explicitly set to PSS'); - } - } - - return $type::savePublicKey($this->modulus, $this->publicExponent, $options); - } - - /** - * Converts a public key to a private key - * - * @return RSA - */ - public function asPrivateKey() - { - $new = new PrivateKey(); - $new->exponent = $this->exponent; - $new->modulus = $this->modulus; - $new->k = $this->k; - $new->format = $this->format; - return $new - ->withHash($this->hash->getHash()) - ->withMGFHash($this->mgfHash->getHash()) - ->withSaltLength($this->sLen) - ->withLabel($this->label) - ->withPadding($this->signaturePadding | $this->encryptionPadding); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Random.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Random.php deleted file mode 100644 index f813a2ea..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Random.php +++ /dev/null @@ -1,222 +0,0 @@ - - * - * - * - * @author Jim Wigginton - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt; - -/** - * Pure-PHP Random Number Generator - * - * @author Jim Wigginton - */ -abstract class Random -{ - /** - * Generate a random string. - * - * Although microoptimizations are generally discouraged as they impair readability this function is ripe with - * microoptimizations because this function has the potential of being called a huge number of times. - * eg. for RSA key generation. - * - * @param int $length - * @throws \RuntimeException if a symmetric cipher is needed but not loaded - * @return string - */ - public static function string($length) - { - if (!$length) { - return ''; - } - - try { - return random_bytes($length); - } catch (\Exception $e) { - // random_compat will throw an Exception, which in PHP 5 does not implement Throwable - } catch (\Throwable $e) { - // If a sufficient source of randomness is unavailable, random_bytes() will throw an - // object that implements the Throwable interface (Exception, TypeError, Error). - // We don't actually need to do anything here. The string() method should just continue - // as normal. Note, however, that if we don't have a sufficient source of randomness for - // random_bytes(), most of the other calls here will fail too, so we'll end up using - // the PHP implementation. - } - // at this point we have no choice but to use a pure-PHP CSPRNG - - // cascade entropy across multiple PHP instances by fixing the session and collecting all - // environmental variables, including the previous session data and the current session - // data. - // - // mt_rand seeds itself by looking at the PID and the time, both of which are (relatively) - // easy to guess at. linux uses mouse clicks, keyboard timings, etc, as entropy sources, but - // PHP isn't low level to be able to use those as sources and on a web server there's not likely - // going to be a ton of keyboard or mouse action. web servers do have one thing that we can use - // however, a ton of people visiting the website. obviously you don't want to base your seeding - // solely on parameters a potential attacker sends but (1) not everything in $_SERVER is controlled - // by the user and (2) this isn't just looking at the data sent by the current user - it's based - // on the data sent by all users. one user requests the page and a hash of their info is saved. - // another user visits the page and the serialization of their data is utilized along with the - // server environment stuff and a hash of the previous http request data (which itself utilizes - // a hash of the session data before that). certainly an attacker should be assumed to have - // full control over his own http requests. he, however, is not going to have control over - // everyone's http requests. - static $crypto = false, $v; - if ($crypto === false) { - // save old session data - $old_session_id = session_id(); - $old_use_cookies = ini_get('session.use_cookies'); - $old_session_cache_limiter = session_cache_limiter(); - $_OLD_SESSION = isset($_SESSION) ? $_SESSION : false; - if ($old_session_id != '') { - session_write_close(); - } - - session_id(1); - ini_set('session.use_cookies', 0); - session_cache_limiter(''); - session_start(); - - $v = (isset($_SERVER) ? self::safe_serialize($_SERVER) : '') . - (isset($_POST) ? self::safe_serialize($_POST) : '') . - (isset($_GET) ? self::safe_serialize($_GET) : '') . - (isset($_COOKIE) ? self::safe_serialize($_COOKIE) : '') . - // as of PHP 8.1 $GLOBALS can't be accessed by reference, which eliminates - // the need for phpseclib_safe_serialize. see https://wiki.php.net/rfc/restrict_globals_usage - // for more info - (version_compare(PHP_VERSION, '8.1.0', '>=') ? serialize($GLOBALS) : self::safe_serialize($GLOBALS)) . - self::safe_serialize($_SESSION) . - self::safe_serialize($_OLD_SESSION); - $v = $seed = $_SESSION['seed'] = sha1($v, true); - if (!isset($_SESSION['count'])) { - $_SESSION['count'] = 0; - } - $_SESSION['count']++; - - session_write_close(); - - // restore old session data - if ($old_session_id != '') { - session_id($old_session_id); - session_start(); - ini_set('session.use_cookies', $old_use_cookies); - session_cache_limiter($old_session_cache_limiter); - } else { - if ($_OLD_SESSION !== false) { - $_SESSION = $_OLD_SESSION; - unset($_OLD_SESSION); - } else { - unset($_SESSION); - } - } - - // in SSH2 a shared secret and an exchange hash are generated through the key exchange process. - // the IV client to server is the hash of that "nonce" with the letter A and for the encryption key it's the letter C. - // if the hash doesn't produce enough a key or an IV that's long enough concat successive hashes of the - // original hash and the current hash. we'll be emulating that. for more info see the following URL: - // - // http://tools.ietf.org/html/rfc4253#section-7.2 - // - // see the is_string($crypto) part for an example of how to expand the keys - $key = sha1($seed . 'A', true); - $iv = sha1($seed . 'C', true); - - // ciphers are used as per the nist.gov link below. also, see this link: - // - // http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives - switch (true) { - case class_exists('\phpseclib3\Crypt\AES'): - $crypto = new AES('ctr'); - break; - case class_exists('\phpseclib3\Crypt\Twofish'): - $crypto = new Twofish('ctr'); - break; - case class_exists('\phpseclib3\Crypt\Blowfish'): - $crypto = new Blowfish('ctr'); - break; - case class_exists('\phpseclib3\Crypt\TripleDES'): - $crypto = new TripleDES('ctr'); - break; - case class_exists('\phpseclib3\Crypt\DES'): - $crypto = new DES('ctr'); - break; - case class_exists('\phpseclib3\Crypt\RC4'): - $crypto = new RC4(); - break; - default: - throw new \RuntimeException(__CLASS__ . ' requires at least one symmetric cipher be loaded'); - } - - $crypto->setKey(substr($key, 0, $crypto->getKeyLength() >> 3)); - $crypto->setIV(substr($iv, 0, $crypto->getBlockLength() >> 3)); - $crypto->enableContinuousBuffer(); - } - - //return $crypto->encrypt(str_repeat("\0", $length)); - - // the following is based off of ANSI X9.31: - // - // http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf - // - // OpenSSL uses that same standard for it's random numbers: - // - // http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c - // (do a search for "ANS X9.31 A.2.4") - $result = ''; - while (strlen($result) < $length) { - $i = $crypto->encrypt(microtime()); // strlen(microtime()) == 21 - $r = $crypto->encrypt($i ^ $v); // strlen($v) == 20 - $v = $crypto->encrypt($r ^ $i); // strlen($r) == 20 - $result .= $r; - } - - return substr($result, 0, $length); - } - - /** - * Safely serialize variables - * - * If a class has a private __sleep() it'll emit a warning - * @return mixed - * @param mixed $arr - */ - private static function safe_serialize(&$arr) - { - if (is_object($arr)) { - return ''; - } - if (!is_array($arr)) { - return serialize($arr); - } - // prevent circular array recursion - if (isset($arr['__phpseclib_marker'])) { - return ''; - } - $safearr = []; - $arr['__phpseclib_marker'] = true; - foreach (array_keys($arr) as $key) { - // do not recurse on the '__phpseclib_marker' key itself, for smaller memory usage - if ($key !== '__phpseclib_marker') { - $safearr[$key] = self::safe_serialize($arr[$key]); - } - } - unset($arr['__phpseclib_marker']); - return serialize($safearr); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php deleted file mode 100644 index cd8b7627..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php +++ /dev/null @@ -1,1038 +0,0 @@ - - * setKey('abcdefghijklmnop'); - * - * $size = 10 * 1024; - * $plaintext = ''; - * for ($i = 0; $i < $size; $i++) { - * $plaintext.= 'a'; - * } - * - * echo $rijndael->decrypt($rijndael->encrypt($plaintext)); - * ?> - * - * - * @author Jim Wigginton - * @copyright 2008 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\Common\BlockCipher; -use phpseclib3\Exception\BadDecryptionException; -use phpseclib3\Exception\BadModeException; -use phpseclib3\Exception\InconsistentSetupException; -use phpseclib3\Exception\InsufficientSetupException; - -/** - * Pure-PHP implementation of Rijndael. - * - * @author Jim Wigginton - */ -class Rijndael extends BlockCipher -{ - /** - * The mcrypt specific name of the cipher - * - * Mcrypt is useable for 128/192/256-bit $block_size/$key_length. For 160/224 not. - * \phpseclib3\Crypt\Rijndael determines automatically whether mcrypt is useable - * or not for the current $block_size/$key_length. - * In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly. - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt - * @see \phpseclib3\Crypt\Common\SymmetricKey::engine - * @see self::isValidEngine() - * @var string - */ - protected $cipher_name_mcrypt = 'rijndael-128'; - - /** - * The Key Schedule - * - * @see self::setup() - * @var array - */ - private $w; - - /** - * The Inverse Key Schedule - * - * @see self::setup() - * @var array - */ - private $dw; - - /** - * The Block Length divided by 32 - * - * {@internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4. Exists in conjunction with $block_size - * because the encryption / decryption / key schedule creation requires this number and not $block_size. We could - * derive this from $block_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu - * of that, we'll just precompute it once.} - * - * @see self::setBlockLength() - * @var int - */ - private $Nb = 4; - - /** - * The Key Length (in bytes) - * - * {@internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk - * because the encryption / decryption / key schedule creation requires this number and not $key_length. We could - * derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu - * of that, we'll just precompute it once.} - * - * @see self::setKeyLength() - * @var int - */ - protected $key_length = 16; - - /** - * The Key Length divided by 32 - * - * @see self::setKeyLength() - * @var int - * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4 - */ - private $Nk = 4; - - /** - * The Number of Rounds - * - * {@internal The max value is 14, the min value is 10.} - * - * @var int - */ - private $Nr; - - /** - * Shift offsets - * - * @var array - */ - private $c; - - /** - * Holds the last used key- and block_size information - * - * @var array - */ - private $kl; - - /** - * Default Constructor. - * - * @param string $mode - * @throws \InvalidArgumentException if an invalid / unsupported mode is provided - */ - public function __construct($mode) - { - parent::__construct($mode); - - if ($this->mode == self::MODE_STREAM) { - throw new BadModeException('Block ciphers cannot be ran in stream mode'); - } - } - - /** - * Sets the key length. - * - * Valid key lengths are 128, 160, 192, 224, and 256. - * - * Note: phpseclib extends Rijndael (and AES) for using 160- and 224-bit keys but they are officially not defined - * and the most (if not all) implementations are not able using 160/224-bit keys but round/pad them up to - * 192/256 bits as, for example, mcrypt will do. - * - * That said, if you want be compatible with other Rijndael and AES implementations, - * you should not setKeyLength(160) or setKeyLength(224). - * - * Additional: In case of 160- and 224-bit keys, phpseclib will/can, for that reason, not use - * the mcrypt php extension, even if available. - * This results then in slower encryption. - * - * @throws \LengthException if the key length is invalid - * @param int $length - */ - public function setKeyLength($length) - { - switch ($length) { - case 128: - case 160: - case 192: - case 224: - case 256: - $this->key_length = $length >> 3; - break; - default: - throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes 128, 160, 192, 224 or 256 bits are supported'); - } - - parent::setKeyLength($length); - } - - /** - * Sets the key. - * - * Rijndael supports five different key lengths - * - * @see setKeyLength() - * @param string $key - * @throws \LengthException if the key length isn't supported - */ - public function setKey($key) - { - switch (strlen($key)) { - case 16: - case 20: - case 24: - case 28: - case 32: - break; - default: - throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 20, 24, 28 or 32 are supported'); - } - - parent::setKey($key); - } - - /** - * Sets the block length - * - * Valid block lengths are 128, 160, 192, 224, and 256. - * - * @param int $length - */ - public function setBlockLength($length) - { - switch ($length) { - case 128: - case 160: - case 192: - case 224: - case 256: - break; - default: - throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes 128, 160, 192, 224 or 256 bits are supported'); - } - - $this->Nb = $length >> 5; - $this->block_size = $length >> 3; - $this->changed = $this->nonIVChanged = true; - $this->setEngine(); - } - - /** - * Test for engine validity - * - * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine() - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() - * @param int $engine - * @return bool - */ - protected function isValidEngineHelper($engine) - { - switch ($engine) { - case self::ENGINE_LIBSODIUM: - return function_exists('sodium_crypto_aead_aes256gcm_is_available') && - sodium_crypto_aead_aes256gcm_is_available() && - $this->mode == self::MODE_GCM && - $this->key_length == 32 && - $this->nonce && strlen($this->nonce) == 12 && - $this->block_size == 16; - case self::ENGINE_OPENSSL_GCM: - if (!extension_loaded('openssl')) { - return false; - } - $methods = openssl_get_cipher_methods(); - return $this->mode == self::MODE_GCM && - version_compare(PHP_VERSION, '7.1.0', '>=') && - in_array('aes-' . $this->getKeyLength() . '-gcm', $methods) && - $this->block_size == 16; - case self::ENGINE_OPENSSL: - if ($this->block_size != 16) { - return false; - } - $this->cipher_name_openssl_ecb = 'aes-' . ($this->key_length << 3) . '-ecb'; - $this->cipher_name_openssl = 'aes-' . ($this->key_length << 3) . '-' . $this->openssl_translate_mode(); - break; - case self::ENGINE_MCRYPT: - $this->cipher_name_mcrypt = 'rijndael-' . ($this->block_size << 3); - if ($this->key_length % 8) { // is it a 160/224-bit key? - // mcrypt is not usable for them, only for 128/192/256-bit keys - return false; - } - } - - return parent::isValidEngineHelper($engine); - } - - /** - * Encrypts a block - * - * @param string $in - * @return string - */ - protected function encryptBlock($in) - { - static $tables; - if (empty($tables)) { - $tables = &$this->getTables(); - } - $t0 = $tables[0]; - $t1 = $tables[1]; - $t2 = $tables[2]; - $t3 = $tables[3]; - $sbox = $tables[4]; - - $state = []; - $words = unpack('N*', $in); - - $c = $this->c; - $w = $this->w; - $Nb = $this->Nb; - $Nr = $this->Nr; - - // addRoundKey - $wc = $Nb - 1; - foreach ($words as $word) { - $state[] = $word ^ $w[++$wc]; - } - - // fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components - - // subBytes, shiftRows, mixColumns, and addRoundKey. fips-197.pdf#page=30, "Implementation Suggestions Regarding - // Various Platforms" suggests that performs enhanced implementations are described in Rijndael-ammended.pdf. - // Rijndael-ammended.pdf#page=20, "Implementation aspects / 32-bit processor", discusses such an optimization. - // Unfortunately, the description given there is not quite correct. Per aes.spec.v316.pdf#page=19 [1], - // equation (7.4.7) is supposed to use addition instead of subtraction, so we'll do that here, as well. - - // [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf - $temp = []; - for ($round = 1; $round < $Nr; ++$round) { - $i = 0; // $c[0] == 0 - $j = $c[1]; - $k = $c[2]; - $l = $c[3]; - - while ($i < $Nb) { - $temp[$i] = $t0[$state[$i] >> 24 & 0x000000FF] ^ - $t1[$state[$j] >> 16 & 0x000000FF] ^ - $t2[$state[$k] >> 8 & 0x000000FF] ^ - $t3[$state[$l] & 0x000000FF] ^ - $w[++$wc]; - ++$i; - $j = ($j + 1) % $Nb; - $k = ($k + 1) % $Nb; - $l = ($l + 1) % $Nb; - } - $state = $temp; - } - - // subWord - for ($i = 0; $i < $Nb; ++$i) { - $state[$i] = $sbox[$state[$i] & 0x000000FF] | - ($sbox[$state[$i] >> 8 & 0x000000FF] << 8) | - ($sbox[$state[$i] >> 16 & 0x000000FF] << 16) | - ($sbox[$state[$i] >> 24 & 0x000000FF] << 24); - } - - // shiftRows + addRoundKey - $i = 0; // $c[0] == 0 - $j = $c[1]; - $k = $c[2]; - $l = $c[3]; - while ($i < $Nb) { - $temp[$i] = ($state[$i] & intval(0xFF000000)) ^ - ($state[$j] & 0x00FF0000) ^ - ($state[$k] & 0x0000FF00) ^ - ($state[$l] & 0x000000FF) ^ - $w[$i]; - ++$i; - $j = ($j + 1) % $Nb; - $k = ($k + 1) % $Nb; - $l = ($l + 1) % $Nb; - } - - return pack('N*', ...$temp); - } - - /** - * Decrypts a block - * - * @param string $in - * @return string - */ - protected function decryptBlock($in) - { - static $invtables; - if (empty($invtables)) { - $invtables = &$this->getInvTables(); - } - $dt0 = $invtables[0]; - $dt1 = $invtables[1]; - $dt2 = $invtables[2]; - $dt3 = $invtables[3]; - $isbox = $invtables[4]; - - $state = []; - $words = unpack('N*', $in); - - $c = $this->c; - $dw = $this->dw; - $Nb = $this->Nb; - $Nr = $this->Nr; - - // addRoundKey - $wc = $Nb - 1; - foreach ($words as $word) { - $state[] = $word ^ $dw[++$wc]; - } - - $temp = []; - for ($round = $Nr - 1; $round > 0; --$round) { - $i = 0; // $c[0] == 0 - $j = $Nb - $c[1]; - $k = $Nb - $c[2]; - $l = $Nb - $c[3]; - - while ($i < $Nb) { - $temp[$i] = $dt0[$state[$i] >> 24 & 0x000000FF] ^ - $dt1[$state[$j] >> 16 & 0x000000FF] ^ - $dt2[$state[$k] >> 8 & 0x000000FF] ^ - $dt3[$state[$l] & 0x000000FF] ^ - $dw[++$wc]; - ++$i; - $j = ($j + 1) % $Nb; - $k = ($k + 1) % $Nb; - $l = ($l + 1) % $Nb; - } - $state = $temp; - } - - // invShiftRows + invSubWord + addRoundKey - $i = 0; // $c[0] == 0 - $j = $Nb - $c[1]; - $k = $Nb - $c[2]; - $l = $Nb - $c[3]; - - while ($i < $Nb) { - $word = ($state[$i] & intval(0xFF000000)) | - ($state[$j] & 0x00FF0000) | - ($state[$k] & 0x0000FF00) | - ($state[$l] & 0x000000FF); - - $temp[$i] = $dw[$i] ^ ($isbox[$word & 0x000000FF] | - ($isbox[$word >> 8 & 0x000000FF] << 8) | - ($isbox[$word >> 16 & 0x000000FF] << 16) | - ($isbox[$word >> 24 & 0x000000FF] << 24)); - ++$i; - $j = ($j + 1) % $Nb; - $k = ($k + 1) % $Nb; - $l = ($l + 1) % $Nb; - } - - return pack('N*', ...$temp); - } - - /** - * Setup the self::ENGINE_INTERNAL $engine - * - * (re)init, if necessary, the internal cipher $engine and flush all $buffers - * Used (only) if $engine == self::ENGINE_INTERNAL - * - * _setup() will be called each time if $changed === true - * typically this happens when using one or more of following public methods: - * - * - setKey() - * - * - setIV() - * - * - disableContinuousBuffer() - * - * - First run of encrypt() / decrypt() with no init-settings - * - * {@internal setup() is always called before en/decryption.} - * - * {@internal Could, but not must, extend by the child Crypt_* class} - * - * @see self::setKey() - * @see self::setIV() - * @see self::disableContinuousBuffer() - */ - protected function setup() - { - if (!$this->changed) { - return; - } - - parent::setup(); - - if (is_string($this->iv) && strlen($this->iv) != $this->block_size) { - throw new InconsistentSetupException('The IV length (' . strlen($this->iv) . ') does not match the block size (' . $this->block_size . ')'); - } - } - - /** - * Setup the key (expansion) - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::setupKey() - */ - protected function setupKey() - { - // Each number in $rcon is equal to the previous number multiplied by two in Rijndael's finite field. - // See http://en.wikipedia.org/wiki/Finite_field_arithmetic#Multiplicative_inverse - static $rcon; - - if (!isset($rcon)) { - $rcon = [0, - 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, - 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, - 0x6C000000, 0xD8000000, 0xAB000000, 0x4D000000, 0x9A000000, - 0x2F000000, 0x5E000000, 0xBC000000, 0x63000000, 0xC6000000, - 0x97000000, 0x35000000, 0x6A000000, 0xD4000000, 0xB3000000, - 0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000 - ]; - $rcon = array_map('intval', $rcon); - } - - if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_length === $this->kl['key_length'] && $this->block_size === $this->kl['block_size']) { - // already expanded - return; - } - $this->kl = ['key' => $this->key, 'key_length' => $this->key_length, 'block_size' => $this->block_size]; - - $this->Nk = $this->key_length >> 2; - // see Rijndael-ammended.pdf#page=44 - $this->Nr = max($this->Nk, $this->Nb) + 6; - - // shift offsets for Nb = 5, 7 are defined in Rijndael-ammended.pdf#page=44, - // "Table 8: Shift offsets in Shiftrow for the alternative block lengths" - // shift offsets for Nb = 4, 6, 8 are defined in Rijndael-ammended.pdf#page=14, - // "Table 2: Shift offsets for different block lengths" - switch ($this->Nb) { - case 4: - case 5: - case 6: - $this->c = [0, 1, 2, 3]; - break; - case 7: - $this->c = [0, 1, 2, 4]; - break; - case 8: - $this->c = [0, 1, 3, 4]; - } - - $w = array_values(unpack('N*words', $this->key)); - - $length = $this->Nb * ($this->Nr + 1); - for ($i = $this->Nk; $i < $length; $i++) { - $temp = $w[$i - 1]; - if ($i % $this->Nk == 0) { - // according to , "the size of an integer is platform-dependent". - // on a 32-bit machine, it's 32-bits, and on a 64-bit machine, it's 64-bits. on a 32-bit machine, - // 0xFFFFFFFF << 8 == 0xFFFFFF00, but on a 64-bit machine, it equals 0xFFFFFFFF00. as such, doing 'and' - // with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is. - $temp = (($temp << 8) & intval(0xFFFFFF00)) | (($temp >> 24) & 0x000000FF); // rotWord - $temp = $this->subWord($temp) ^ $rcon[$i / $this->Nk]; - } elseif ($this->Nk > 6 && $i % $this->Nk == 4) { - $temp = $this->subWord($temp); - } - $w[$i] = $w[$i - $this->Nk] ^ $temp; - } - - // convert the key schedule from a vector of $Nb * ($Nr + 1) length to a matrix with $Nr + 1 rows and $Nb columns - // and generate the inverse key schedule. more specifically, - // according to (section 5.3.3), - // "The key expansion for the Inverse Cipher is defined as follows: - // 1. Apply the Key Expansion. - // 2. Apply InvMixColumn to all Round Keys except the first and the last one." - // also, see fips-197.pdf#page=27, "5.3.5 Equivalent Inverse Cipher" - list($dt0, $dt1, $dt2, $dt3) = $this->getInvTables(); - $temp = $this->w = $this->dw = []; - for ($i = $row = $col = 0; $i < $length; $i++, $col++) { - if ($col == $this->Nb) { - if ($row == 0) { - $this->dw[0] = $this->w[0]; - } else { - // subWord + invMixColumn + invSubWord = invMixColumn - $j = 0; - while ($j < $this->Nb) { - $dw = $this->subWord($this->w[$row][$j]); - $temp[$j] = $dt0[$dw >> 24 & 0x000000FF] ^ - $dt1[$dw >> 16 & 0x000000FF] ^ - $dt2[$dw >> 8 & 0x000000FF] ^ - $dt3[$dw & 0x000000FF]; - $j++; - } - $this->dw[$row] = $temp; - } - - $col = 0; - $row++; - } - $this->w[$row][$col] = $w[$i]; - } - - $this->dw[$row] = $this->w[$row]; - - // Converting to 1-dim key arrays (both ascending) - $this->dw = array_reverse($this->dw); - $w = array_pop($this->w); - $dw = array_pop($this->dw); - foreach ($this->w as $r => $wr) { - foreach ($wr as $c => $wc) { - $w[] = $wc; - $dw[] = $this->dw[$r][$c]; - } - } - $this->w = $w; - $this->dw = $dw; - } - - /** - * Performs S-Box substitutions - * - * @return array - * @param int $word - */ - private function subWord($word) - { - static $sbox; - if (empty($sbox)) { - list(, , , , $sbox) = self::getTables(); - } - - return $sbox[$word & 0x000000FF] | - ($sbox[$word >> 8 & 0x000000FF] << 8) | - ($sbox[$word >> 16 & 0x000000FF] << 16) | - ($sbox[$word >> 24 & 0x000000FF] << 24); - } - - /** - * Provides the mixColumns and sboxes tables - * - * @see self::encryptBlock() - * @see self::setupInlineCrypt() - * @see self::subWord() - * @return array &$tables - */ - protected function &getTables() - { - static $tables; - if (empty($tables)) { - // according to (section 5.2.1), - // precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so - // those are the names we'll use. - $t3 = array_map('intval', [ - // with array_map('intval', ...) we ensure we have only int's and not - // some slower floats converted by php automatically on high values - 0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491, - 0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC, - 0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB, - 0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B, - 0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83, - 0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A, - 0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F, - 0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA, - 0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B, - 0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713, - 0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6, - 0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85, - 0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411, - 0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B, - 0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1, - 0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF, - 0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E, - 0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6, - 0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B, - 0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD, - 0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8, - 0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2, - 0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049, - 0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810, - 0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197, - 0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F, - 0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C, - 0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927, - 0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733, - 0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5, - 0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0, - 0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C - ]); - - foreach ($t3 as $t3i) { - $t0[] = (($t3i << 24) & intval(0xFF000000)) | (($t3i >> 8) & 0x00FFFFFF); - $t1[] = (($t3i << 16) & intval(0xFFFF0000)) | (($t3i >> 16) & 0x0000FFFF); - $t2[] = (($t3i << 8) & intval(0xFFFFFF00)) | (($t3i >> 24) & 0x000000FF); - } - - $tables = [ - // The Precomputed mixColumns tables t0 - t3 - $t0, - $t1, - $t2, - $t3, - // The SubByte S-Box - [ - 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, - 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, - 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, - 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, - 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, - 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, - 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, - 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, - 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, - 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, - 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, - 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, - 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, - 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, - 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, - 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 - ] - ]; - } - return $tables; - } - - /** - * Provides the inverse mixColumns and inverse sboxes tables - * - * @see self::decryptBlock() - * @see self::setupInlineCrypt() - * @see self::setupKey() - * @return array &$tables - */ - protected function &getInvTables() - { - static $tables; - if (empty($tables)) { - $dt3 = array_map('intval', [ - 0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B, - 0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5, - 0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B, - 0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358, 0xE0692949, 0xC9C8448E, - 0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D, - 0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9, - 0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272, 0x1F8F57E3, 0x55AB2A66, - 0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED, - 0xCF1C2B8A, 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4, - 0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD, - 0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60, - 0x98FB2419, 0xBDE997D6, 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79, - 0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C, - 0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24, - 0x0A67B10C, 0x57E70F93, 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C, - 0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814, - 0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B, - 0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084, - 0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC, 0x8652EC0D, 0xC1E3D077, - 0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22, - 0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F, - 0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, 0xC3AFF582, - 0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB, - 0x267809CD, 0x5918F46E, 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF, - 0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035, - 0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17, - 0x4DD68D76, 0xEFB04D43, 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46, - 0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D, - 0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A, - 0xD2DF599C, 0xF2733F55, 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678, - 0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC, 0x3C498B28, 0x0D9541FF, - 0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0 - ]); - - foreach ($dt3 as $dt3i) { - $dt0[] = (($dt3i << 24) & intval(0xFF000000)) | (($dt3i >> 8) & 0x00FFFFFF); - $dt1[] = (($dt3i << 16) & intval(0xFFFF0000)) | (($dt3i >> 16) & 0x0000FFFF); - $dt2[] = (($dt3i << 8) & intval(0xFFFFFF00)) | (($dt3i >> 24) & 0x000000FF); - }; - - $tables = [ - // The Precomputed inverse mixColumns tables dt0 - dt3 - $dt0, - $dt1, - $dt2, - $dt3, - // The inverse SubByte S-Box - [ - 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, - 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, - 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, - 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, - 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, - 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, - 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, - 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, - 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, - 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, - 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, - 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, - 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, - 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, - 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D - ] - ]; - } - return $tables; - } - - /** - * Setup the performance-optimized function for de/encrypt() - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::setupInlineCrypt() - */ - protected function setupInlineCrypt() - { - $w = $this->w; - $dw = $this->dw; - $init_encrypt = ''; - $init_decrypt = ''; - - $Nr = $this->Nr; - $Nb = $this->Nb; - $c = $this->c; - - // Generating encrypt code: - $init_encrypt .= ' - static $tables; - if (empty($tables)) { - $tables = &$this->getTables(); - } - $t0 = $tables[0]; - $t1 = $tables[1]; - $t2 = $tables[2]; - $t3 = $tables[3]; - $sbox = $tables[4]; - '; - - $s = 'e'; - $e = 's'; - $wc = $Nb - 1; - - // Preround: addRoundKey - $encrypt_block = '$in = unpack("N*", $in);' . "\n"; - for ($i = 0; $i < $Nb; ++$i) { - $encrypt_block .= '$s' . $i . ' = $in[' . ($i + 1) . '] ^ ' . $w[++$wc] . ";\n"; - } - - // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey - for ($round = 1; $round < $Nr; ++$round) { - list($s, $e) = [$e, $s]; - for ($i = 0; $i < $Nb; ++$i) { - $encrypt_block .= - '$' . $e . $i . ' = - $t0[($' . $s . $i . ' >> 24) & 0xff] ^ - $t1[($' . $s . (($i + $c[1]) % $Nb) . ' >> 16) & 0xff] ^ - $t2[($' . $s . (($i + $c[2]) % $Nb) . ' >> 8) & 0xff] ^ - $t3[ $' . $s . (($i + $c[3]) % $Nb) . ' & 0xff] ^ - ' . $w[++$wc] . ";\n"; - } - } - - // Finalround: subWord + shiftRows + addRoundKey - for ($i = 0; $i < $Nb; ++$i) { - $encrypt_block .= - '$' . $e . $i . ' = - $sbox[ $' . $e . $i . ' & 0xff] | - ($sbox[($' . $e . $i . ' >> 8) & 0xff] << 8) | - ($sbox[($' . $e . $i . ' >> 16) & 0xff] << 16) | - ($sbox[($' . $e . $i . ' >> 24) & 0xff] << 24);' . "\n"; - } - $encrypt_block .= '$in = pack("N*"' . "\n"; - for ($i = 0; $i < $Nb; ++$i) { - $encrypt_block .= ', - ($' . $e . $i . ' & ' . ((int)0xFF000000) . ') ^ - ($' . $e . (($i + $c[1]) % $Nb) . ' & 0x00FF0000 ) ^ - ($' . $e . (($i + $c[2]) % $Nb) . ' & 0x0000FF00 ) ^ - ($' . $e . (($i + $c[3]) % $Nb) . ' & 0x000000FF ) ^ - ' . $w[$i] . "\n"; - } - $encrypt_block .= ');'; - - // Generating decrypt code: - $init_decrypt .= ' - static $invtables; - if (empty($invtables)) { - $invtables = &$this->getInvTables(); - } - $dt0 = $invtables[0]; - $dt1 = $invtables[1]; - $dt2 = $invtables[2]; - $dt3 = $invtables[3]; - $isbox = $invtables[4]; - '; - - $s = 'e'; - $e = 's'; - $wc = $Nb - 1; - - // Preround: addRoundKey - $decrypt_block = '$in = unpack("N*", $in);' . "\n"; - for ($i = 0; $i < $Nb; ++$i) { - $decrypt_block .= '$s' . $i . ' = $in[' . ($i + 1) . '] ^ ' . $dw[++$wc] . ';' . "\n"; - } - - // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey - for ($round = 1; $round < $Nr; ++$round) { - list($s, $e) = [$e, $s]; - for ($i = 0; $i < $Nb; ++$i) { - $decrypt_block .= - '$' . $e . $i . ' = - $dt0[($' . $s . $i . ' >> 24) & 0xff] ^ - $dt1[($' . $s . (($Nb + $i - $c[1]) % $Nb) . ' >> 16) & 0xff] ^ - $dt2[($' . $s . (($Nb + $i - $c[2]) % $Nb) . ' >> 8) & 0xff] ^ - $dt3[ $' . $s . (($Nb + $i - $c[3]) % $Nb) . ' & 0xff] ^ - ' . $dw[++$wc] . ";\n"; - } - } - - // Finalround: subWord + shiftRows + addRoundKey - for ($i = 0; $i < $Nb; ++$i) { - $decrypt_block .= - '$' . $e . $i . ' = - $isbox[ $' . $e . $i . ' & 0xff] | - ($isbox[($' . $e . $i . ' >> 8) & 0xff] << 8) | - ($isbox[($' . $e . $i . ' >> 16) & 0xff] << 16) | - ($isbox[($' . $e . $i . ' >> 24) & 0xff] << 24);' . "\n"; - } - $decrypt_block .= '$in = pack("N*"' . "\n"; - for ($i = 0; $i < $Nb; ++$i) { - $decrypt_block .= ', - ($' . $e . $i . ' & ' . ((int)0xFF000000) . ') ^ - ($' . $e . (($Nb + $i - $c[1]) % $Nb) . ' & 0x00FF0000 ) ^ - ($' . $e . (($Nb + $i - $c[2]) % $Nb) . ' & 0x0000FF00 ) ^ - ($' . $e . (($Nb + $i - $c[3]) % $Nb) . ' & 0x000000FF ) ^ - ' . $dw[$i] . "\n"; - } - $decrypt_block .= ');'; - - $this->inline_crypt = $this->createInlineCryptFunction( - [ - 'init_crypt' => '', - 'init_encrypt' => $init_encrypt, - 'init_decrypt' => $init_decrypt, - 'encrypt_block' => $encrypt_block, - 'decrypt_block' => $decrypt_block - ] - ); - } - - /** - * Encrypts a message. - * - * @see self::decrypt() - * @see parent::encrypt() - * @param string $plaintext - * @return string - */ - public function encrypt($plaintext) - { - $this->setup(); - - switch ($this->engine) { - case self::ENGINE_LIBSODIUM: - $this->newtag = sodium_crypto_aead_aes256gcm_encrypt($plaintext, $this->aad, $this->nonce, $this->key); - return Strings::shift($this->newtag, strlen($plaintext)); - case self::ENGINE_OPENSSL_GCM: - return openssl_encrypt( - $plaintext, - 'aes-' . $this->getKeyLength() . '-gcm', - $this->key, - OPENSSL_RAW_DATA, - $this->nonce, - $this->newtag, - $this->aad - ); - } - - return parent::encrypt($plaintext); - } - - /** - * Decrypts a message. - * - * @see self::encrypt() - * @see parent::decrypt() - * @param string $ciphertext - * @return string - */ - public function decrypt($ciphertext) - { - $this->setup(); - - switch ($this->engine) { - case self::ENGINE_LIBSODIUM: - if ($this->oldtag === false) { - throw new InsufficientSetupException('Authentication Tag has not been set'); - } - if (strlen($this->oldtag) != 16) { - break; - } - $plaintext = sodium_crypto_aead_aes256gcm_decrypt($ciphertext . $this->oldtag, $this->aad, $this->nonce, $this->key); - if ($plaintext === false) { - $this->oldtag = false; - throw new BadDecryptionException('Error decrypting ciphertext with libsodium'); - } - return $plaintext; - case self::ENGINE_OPENSSL_GCM: - if ($this->oldtag === false) { - throw new InsufficientSetupException('Authentication Tag has not been set'); - } - $plaintext = openssl_decrypt( - $ciphertext, - 'aes-' . $this->getKeyLength() . '-gcm', - $this->key, - OPENSSL_RAW_DATA, - $this->nonce, - $this->oldtag, - $this->aad - ); - if ($plaintext === false) { - $this->oldtag = false; - throw new BadDecryptionException('Error decrypting ciphertext with OpenSSL'); - } - return $plaintext; - } - - return parent::decrypt($ciphertext); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Salsa20.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Salsa20.php deleted file mode 100644 index 0a35f478..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Salsa20.php +++ /dev/null @@ -1,526 +0,0 @@ - - * @copyright 2019 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\Common\StreamCipher; -use phpseclib3\Exception\BadDecryptionException; -use phpseclib3\Exception\InsufficientSetupException; - -/** - * Pure-PHP implementation of Salsa20. - * - * @author Jim Wigginton - */ -class Salsa20 extends StreamCipher -{ - /** - * Part 1 of the state - * - * @var string|false - */ - protected $p1 = false; - - /** - * Part 2 of the state - * - * @var string|false - */ - protected $p2 = false; - - /** - * Key Length (in bytes) - * - * @var int - */ - protected $key_length = 32; // = 256 bits - - /** - * @see \phpseclib3\Crypt\Salsa20::crypt() - */ - const ENCRYPT = 0; - - /** - * @see \phpseclib3\Crypt\Salsa20::crypt() - */ - const DECRYPT = 1; - - /** - * Encryption buffer for continuous mode - * - * @var array - */ - protected $enbuffer; - - /** - * Decryption buffer for continuous mode - * - * @var array - */ - protected $debuffer; - - /** - * Counter - * - * @var int - */ - protected $counter = 0; - - /** - * Using Generated Poly1305 Key - * - * @var boolean - */ - protected $usingGeneratedPoly1305Key = false; - - /** - * Salsa20 uses a nonce - * - * @return bool - */ - public function usesNonce() - { - return true; - } - - /** - * Sets the key. - * - * @param string $key - * @throws \LengthException if the key length isn't supported - */ - public function setKey($key) - { - switch (strlen($key)) { - case 16: - case 32: - break; - default: - throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16 or 32 are supported'); - } - - parent::setKey($key); - } - - /** - * Sets the nonce. - * - * @param string $nonce - */ - public function setNonce($nonce) - { - if (strlen($nonce) != 8) { - throw new \LengthException('Nonce of size ' . strlen($key) . ' not supported by this algorithm. Only an 64-bit nonce is supported'); - } - - $this->nonce = $nonce; - $this->changed = true; - $this->setEngine(); - } - - /** - * Sets the counter. - * - * @param int $counter - */ - public function setCounter($counter) - { - $this->counter = $counter; - $this->setEngine(); - } - - /** - * Creates a Poly1305 key using the method discussed in RFC8439 - * - * See https://tools.ietf.org/html/rfc8439#section-2.6.1 - */ - protected function createPoly1305Key() - { - if ($this->nonce === false) { - throw new InsufficientSetupException('No nonce has been defined'); - } - - if ($this->key === false) { - throw new InsufficientSetupException('No key has been defined'); - } - - $c = clone $this; - $c->setCounter(0); - $c->usePoly1305 = false; - $block = $c->encrypt(str_repeat("\0", 256)); - $this->setPoly1305Key(substr($block, 0, 32)); - - if ($this->counter == 0) { - $this->counter++; - } - } - - /** - * Setup the self::ENGINE_INTERNAL $engine - * - * (re)init, if necessary, the internal cipher $engine - * - * _setup() will be called each time if $changed === true - * typically this happens when using one or more of following public methods: - * - * - setKey() - * - * - setNonce() - * - * - First run of encrypt() / decrypt() with no init-settings - * - * @see self::setKey() - * @see self::setNonce() - * @see self::disableContinuousBuffer() - */ - protected function setup() - { - if (!$this->changed) { - return; - } - - $this->enbuffer = $this->debuffer = ['ciphertext' => '', 'counter' => $this->counter]; - - $this->changed = $this->nonIVChanged = false; - - if ($this->nonce === false) { - throw new InsufficientSetupException('No nonce has been defined'); - } - - if ($this->key === false) { - throw new InsufficientSetupException('No key has been defined'); - } - - if ($this->usePoly1305 && !isset($this->poly1305Key)) { - $this->usingGeneratedPoly1305Key = true; - $this->createPoly1305Key(); - } - - $key = $this->key; - if (strlen($key) == 16) { - $constant = 'expand 16-byte k'; - $key .= $key; - } else { - $constant = 'expand 32-byte k'; - } - - $this->p1 = substr($constant, 0, 4) . - substr($key, 0, 16) . - substr($constant, 4, 4) . - $this->nonce . - "\0\0\0\0"; - $this->p2 = substr($constant, 8, 4) . - substr($key, 16, 16) . - substr($constant, 12, 4); - } - - /** - * Setup the key (expansion) - */ - protected function setupKey() - { - // Salsa20 does not utilize this method - } - - /** - * Encrypts a message. - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() - * @see self::crypt() - * @param string $plaintext - * @return string $ciphertext - */ - public function encrypt($plaintext) - { - $ciphertext = $this->crypt($plaintext, self::ENCRYPT); - if (isset($this->poly1305Key)) { - $this->newtag = $this->poly1305($ciphertext); - } - return $ciphertext; - } - - /** - * Decrypts a message. - * - * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)). - * At least if the continuous buffer is disabled. - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @see self::crypt() - * @param string $ciphertext - * @return string $plaintext - */ - public function decrypt($ciphertext) - { - if (isset($this->poly1305Key)) { - if ($this->oldtag === false) { - throw new InsufficientSetupException('Authentication Tag has not been set'); - } - $newtag = $this->poly1305($ciphertext); - if ($this->oldtag != substr($newtag, 0, strlen($this->oldtag))) { - $this->oldtag = false; - throw new BadDecryptionException('Derived authentication tag and supplied authentication tag do not match'); - } - $this->oldtag = false; - } - - return $this->crypt($ciphertext, self::DECRYPT); - } - - /** - * Encrypts a block - * - * @param string $in - */ - protected function encryptBlock($in) - { - // Salsa20 does not utilize this method - } - - /** - * Decrypts a block - * - * @param string $in - */ - protected function decryptBlock($in) - { - // Salsa20 does not utilize this method - } - - /** - * Encrypts or decrypts a message. - * - * @see self::encrypt() - * @see self::decrypt() - * @param string $text - * @param int $mode - * @return string $text - */ - private function crypt($text, $mode) - { - $this->setup(); - if (!$this->continuousBuffer) { - if ($this->engine == self::ENGINE_OPENSSL) { - $iv = pack('V', $this->counter) . $this->p2; - return openssl_encrypt( - $text, - $this->cipher_name_openssl, - $this->key, - OPENSSL_RAW_DATA, - $iv - ); - } - $i = $this->counter; - $blocks = str_split($text, 64); - foreach ($blocks as &$block) { - $block ^= static::salsa20($this->p1 . pack('V', $i++) . $this->p2); - } - - return implode('', $blocks); - } - - if ($mode == self::ENCRYPT) { - $buffer = &$this->enbuffer; - } else { - $buffer = &$this->debuffer; - } - if (!strlen($buffer['ciphertext'])) { - $ciphertext = ''; - } else { - $ciphertext = $text ^ Strings::shift($buffer['ciphertext'], strlen($text)); - $text = substr($text, strlen($ciphertext)); - if (!strlen($text)) { - return $ciphertext; - } - } - - $overflow = strlen($text) % 64; // & 0x3F - if ($overflow) { - $text2 = Strings::pop($text, $overflow); - if ($this->engine == self::ENGINE_OPENSSL) { - $iv = pack('V', $buffer['counter']) . $this->p2; - // at this point $text should be a multiple of 64 - $buffer['counter'] += (strlen($text) >> 6) + 1; // ie. divide by 64 - $encrypted = openssl_encrypt( - $text . str_repeat("\0", 64), - $this->cipher_name_openssl, - $this->key, - OPENSSL_RAW_DATA, - $iv - ); - $temp = Strings::pop($encrypted, 64); - } else { - $blocks = str_split($text, 64); - if (strlen($text)) { - foreach ($blocks as &$block) { - $block ^= static::salsa20($this->p1 . pack('V', $buffer['counter']++) . $this->p2); - } - } - $encrypted = implode('', $blocks); - $temp = static::salsa20($this->p1 . pack('V', $buffer['counter']++) . $this->p2); - } - $ciphertext .= $encrypted . ($text2 ^ $temp); - $buffer['ciphertext'] = substr($temp, $overflow); - } elseif (!strlen($buffer['ciphertext'])) { - if ($this->engine == self::ENGINE_OPENSSL) { - $iv = pack('V', $buffer['counter']) . $this->p2; - $buffer['counter'] += (strlen($text) >> 6); - $ciphertext .= openssl_encrypt( - $text, - $this->cipher_name_openssl, - $this->key, - OPENSSL_RAW_DATA, - $iv - ); - } else { - $blocks = str_split($text, 64); - foreach ($blocks as &$block) { - $block ^= static::salsa20($this->p1 . pack('V', $buffer['counter']++) . $this->p2); - } - $ciphertext .= implode('', $blocks); - } - } - - return $ciphertext; - } - - /** - * Left Rotate - * - * @param int $x - * @param int $n - * @return int - */ - protected static function leftRotate($x, $n) - { - if (PHP_INT_SIZE == 8) { - $r1 = $x << $n; - $r1 &= 0xFFFFFFFF; - $r2 = ($x & 0xFFFFFFFF) >> (32 - $n); - } else { - $x = (int) $x; - $r1 = $x << $n; - $r2 = $x >> (32 - $n); - $r2 &= (1 << $n) - 1; - } - return $r1 | $r2; - } - - /** - * The quarterround function - * - * @param int $a - * @param int $b - * @param int $c - * @param int $d - */ - protected static function quarterRound(&$a, &$b, &$c, &$d) - { - $b ^= self::leftRotate($a + $d, 7); - $c ^= self::leftRotate($b + $a, 9); - $d ^= self::leftRotate($c + $b, 13); - $a ^= self::leftRotate($d + $c, 18); - } - - /** - * The doubleround function - * - * @param int $x0 (by reference) - * @param int $x1 (by reference) - * @param int $x2 (by reference) - * @param int $x3 (by reference) - * @param int $x4 (by reference) - * @param int $x5 (by reference) - * @param int $x6 (by reference) - * @param int $x7 (by reference) - * @param int $x8 (by reference) - * @param int $x9 (by reference) - * @param int $x10 (by reference) - * @param int $x11 (by reference) - * @param int $x12 (by reference) - * @param int $x13 (by reference) - * @param int $x14 (by reference) - * @param int $x15 (by reference) - */ - protected static function doubleRound(&$x0, &$x1, &$x2, &$x3, &$x4, &$x5, &$x6, &$x7, &$x8, &$x9, &$x10, &$x11, &$x12, &$x13, &$x14, &$x15) - { - // columnRound - static::quarterRound($x0, $x4, $x8, $x12); - static::quarterRound($x5, $x9, $x13, $x1); - static::quarterRound($x10, $x14, $x2, $x6); - static::quarterRound($x15, $x3, $x7, $x11); - // rowRound - static::quarterRound($x0, $x1, $x2, $x3); - static::quarterRound($x5, $x6, $x7, $x4); - static::quarterRound($x10, $x11, $x8, $x9); - static::quarterRound($x15, $x12, $x13, $x14); - } - - /** - * The Salsa20 hash function function - * - * @param string $x - */ - protected static function salsa20($x) - { - $z = $x = unpack('V*', $x); - for ($i = 0; $i < 10; $i++) { - static::doubleRound($z[1], $z[2], $z[3], $z[4], $z[5], $z[6], $z[7], $z[8], $z[9], $z[10], $z[11], $z[12], $z[13], $z[14], $z[15], $z[16]); - } - - for ($i = 1; $i <= 16; $i++) { - $x[$i] += $z[$i]; - } - - return pack('V*', ...$x); - } - - /** - * Calculates Poly1305 MAC - * - * @see self::decrypt() - * @see self::encrypt() - * @param string $ciphertext - * @return string - */ - protected function poly1305($ciphertext) - { - if (!$this->usingGeneratedPoly1305Key) { - return parent::poly1305($this->aad . $ciphertext); - } else { - /* - sodium_crypto_aead_chacha20poly1305_encrypt does not calculate the poly1305 tag - the same way sodium_crypto_aead_chacha20poly1305_ietf_encrypt does. you can see - how the latter encrypts it in Salsa20::encrypt(). here's how the former encrypts - it: - - $this->newtag = $this->poly1305( - $this->aad . - pack('V', strlen($this->aad)) . "\0\0\0\0" . - $ciphertext . - pack('V', strlen($ciphertext)) . "\0\0\0\0" - ); - - phpseclib opts to use the IETF construction, even when the nonce is 64-bits - instead of 96-bits - */ - return parent::poly1305( - self::nullPad128($this->aad) . - self::nullPad128($ciphertext) . - pack('V', strlen($this->aad)) . "\0\0\0\0" . - pack('V', strlen($ciphertext)) . "\0\0\0\0" - ); - } - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php deleted file mode 100644 index 1ff5ed02..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php +++ /dev/null @@ -1,436 +0,0 @@ - - * setKey('abcdefghijklmnopqrstuvwx'); - * - * $size = 10 * 1024; - * $plaintext = ''; - * for ($i = 0; $i < $size; $i++) { - * $plaintext.= 'a'; - * } - * - * echo $des->decrypt($des->encrypt($plaintext)); - * ?> - * - * - * @author Jim Wigginton - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt; - -/** - * Pure-PHP implementation of Triple DES. - * - * @author Jim Wigginton - */ -class TripleDES extends DES -{ - /** - * Encrypt / decrypt using inner chaining - * - * Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (self::MODE_CBC3). - */ - const MODE_3CBC = -2; - - /** - * Encrypt / decrypt using outer chaining - * - * Outer chaining is used by SSH-2 and when the mode is set to \phpseclib3\Crypt\Common\BlockCipher::MODE_CBC. - */ - const MODE_CBC3 = self::MODE_CBC; - - /** - * Key Length (in bytes) - * - * @see \phpseclib3\Crypt\TripleDES::setKeyLength() - * @var int - */ - protected $key_length = 24; - - /** - * The mcrypt specific name of the cipher - * - * @see \phpseclib3\Crypt\DES::cipher_name_mcrypt - * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt - * @var string - */ - protected $cipher_name_mcrypt = 'tripledes'; - - /** - * Optimizing value while CFB-encrypting - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len - * @var int - */ - protected $cfb_init_len = 750; - - /** - * max possible size of $key - * - * @see self::setKey() - * @see \phpseclib3\Crypt\DES::setKey() - * @var string - */ - protected $key_length_max = 24; - - /** - * Internal flag whether using self::MODE_3CBC or not - * - * @var bool - */ - private $mode_3cbc; - - /** - * The \phpseclib3\Crypt\DES objects - * - * Used only if $mode_3cbc === true - * - * @var array - */ - private $des; - - /** - * Default Constructor. - * - * Determines whether or not the mcrypt or OpenSSL extensions should be used. - * - * $mode could be: - * - * - ecb - * - * - cbc - * - * - ctr - * - * - cfb - * - * - ofb - * - * - 3cbc - * - * - cbc3 (same as cbc) - * - * @see \phpseclib3\Crypt\DES::__construct() - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() - * @param string $mode - */ - public function __construct($mode) - { - switch (strtolower($mode)) { - // In case of self::MODE_3CBC, we init as CRYPT_DES_MODE_CBC - // and additional flag us internally as 3CBC - case '3cbc': - parent::__construct('cbc'); - $this->mode_3cbc = true; - - // This three $des'es will do the 3CBC work (if $key > 64bits) - $this->des = [ - new DES('cbc'), - new DES('cbc'), - new DES('cbc'), - ]; - - // we're going to be doing the padding, ourselves, so disable it in the \phpseclib3\Crypt\DES objects - $this->des[0]->disablePadding(); - $this->des[1]->disablePadding(); - $this->des[2]->disablePadding(); - break; - case 'cbc3': - $mode = 'cbc'; - // fall-through - // If not 3CBC, we init as usual - default: - parent::__construct($mode); - - if ($this->mode == self::MODE_STREAM) { - throw new BadModeException('Block ciphers cannot be ran in stream mode'); - } - } - } - - /** - * Test for engine validity - * - * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine() - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() - * @param int $engine - * @return bool - */ - protected function isValidEngineHelper($engine) - { - if ($engine == self::ENGINE_OPENSSL) { - $this->cipher_name_openssl_ecb = 'des-ede3'; - $mode = $this->openssl_translate_mode(); - $this->cipher_name_openssl = $mode == 'ecb' ? 'des-ede3' : 'des-ede3-' . $mode; - } - - return parent::isValidEngineHelper($engine); - } - - /** - * Sets the initialization vector. - * - * SetIV is not required when \phpseclib3\Crypt\Common\SymmetricKey::MODE_ECB is being used. - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::setIV() - * @param string $iv - */ - public function setIV($iv) - { - parent::setIV($iv); - if ($this->mode_3cbc) { - $this->des[0]->setIV($iv); - $this->des[1]->setIV($iv); - $this->des[2]->setIV($iv); - } - } - - /** - * Sets the key length. - * - * Valid key lengths are 128 and 192 bits. - * - * If you want to use a 64-bit key use DES.php - * - * @see \phpseclib3\Crypt\Common\SymmetricKey:setKeyLength() - * @throws \LengthException if the key length is invalid - * @param int $length - */ - public function setKeyLength($length) - { - switch ($length) { - case 128: - case 192: - break; - default: - throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes 128 or 192 bits are supported'); - } - - parent::setKeyLength($length); - } - - /** - * Sets the key. - * - * Triple DES can use 128-bit (eg. strlen($key) == 16) or 192-bit (eg. strlen($key) == 24) keys. - * - * DES also requires that every eighth bit be a parity bit, however, we'll ignore that. - * - * @see \phpseclib3\Crypt\DES::setKey() - * @see \phpseclib3\Crypt\Common\SymmetricKey::setKey() - * @throws \LengthException if the key length is invalid - * @param string $key - */ - public function setKey($key) - { - if ($this->explicit_key_length !== false && strlen($key) != $this->explicit_key_length) { - throw new \LengthException('Key length has already been set to ' . $this->explicit_key_length . ' bytes and this key is ' . strlen($key) . ' bytes'); - } - - switch (strlen($key)) { - case 16: - $key .= substr($key, 0, 8); - break; - case 24: - break; - default: - throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16 or 24 are supported'); - } - - // copied from self::setKey() - $this->key = $key; - $this->key_length = strlen($key); - $this->changed = $this->nonIVChanged = true; - $this->setEngine(); - - if ($this->mode_3cbc) { - $this->des[0]->setKey(substr($key, 0, 8)); - $this->des[1]->setKey(substr($key, 8, 8)); - $this->des[2]->setKey(substr($key, 16, 8)); - } - } - - /** - * Encrypts a message. - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @param string $plaintext - * @return string $cipertext - */ - public function encrypt($plaintext) - { - // parent::en/decrypt() is able to do all the work for all modes and keylengths, - // except for: self::MODE_3CBC (inner chaining CBC) with a key > 64bits - - // if the key is smaller then 8, do what we'd normally do - if ($this->mode_3cbc && strlen($this->key) > 8) { - return $this->des[2]->encrypt( - $this->des[1]->decrypt( - $this->des[0]->encrypt( - $this->pad($plaintext) - ) - ) - ); - } - - return parent::encrypt($plaintext); - } - - /** - * Decrypts a message. - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() - * @param string $ciphertext - * @return string $plaintext - */ - public function decrypt($ciphertext) - { - if ($this->mode_3cbc && strlen($this->key) > 8) { - return $this->unpad( - $this->des[0]->decrypt( - $this->des[1]->encrypt( - $this->des[2]->decrypt( - str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, "\0") - ) - ) - ) - ); - } - - return parent::decrypt($ciphertext); - } - - /** - * Treat consecutive "packets" as if they are a continuous buffer. - * - * Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets - * will yield different outputs: - * - * - * echo $des->encrypt(substr($plaintext, 0, 8)); - * echo $des->encrypt(substr($plaintext, 8, 8)); - * - * - * echo $des->encrypt($plaintext); - * - * - * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates - * another, as demonstrated with the following: - * - * - * $des->encrypt(substr($plaintext, 0, 8)); - * echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8))); - * - * - * echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8))); - * - * - * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different - * outputs. The reason is due to the fact that the initialization vector's change after every encryption / - * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant. - * - * Put another way, when the continuous buffer is enabled, the state of the \phpseclib3\Crypt\DES() object changes after each - * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that - * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them), - * however, they are also less intuitive and more likely to cause you problems. - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::enableContinuousBuffer() - * @see self::disableContinuousBuffer() - */ - public function enableContinuousBuffer() - { - parent::enableContinuousBuffer(); - if ($this->mode_3cbc) { - $this->des[0]->enableContinuousBuffer(); - $this->des[1]->enableContinuousBuffer(); - $this->des[2]->enableContinuousBuffer(); - } - } - - /** - * Treat consecutive packets as if they are a discontinuous buffer. - * - * The default behavior. - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::disableContinuousBuffer() - * @see self::enableContinuousBuffer() - */ - public function disableContinuousBuffer() - { - parent::disableContinuousBuffer(); - if ($this->mode_3cbc) { - $this->des[0]->disableContinuousBuffer(); - $this->des[1]->disableContinuousBuffer(); - $this->des[2]->disableContinuousBuffer(); - } - } - - /** - * Creates the key schedule - * - * @see \phpseclib3\Crypt\DES::setupKey() - * @see \phpseclib3\Crypt\Common\SymmetricKey::setupKey() - */ - protected function setupKey() - { - switch (true) { - // if $key <= 64bits we configure our internal pure-php cipher engine - // to act as regular [1]DES, not as 3DES. mcrypt.so::tripledes does the same. - case strlen($this->key) <= 8: - $this->des_rounds = 1; - break; - - // otherwise, if $key > 64bits, we configure our engine to work as 3DES. - default: - $this->des_rounds = 3; - - // (only) if 3CBC is used we have, of course, to setup the $des[0-2] keys also separately. - if ($this->mode_3cbc) { - $this->des[0]->setupKey(); - $this->des[1]->setupKey(); - $this->des[2]->setupKey(); - - // because $des[0-2] will, now, do all the work we can return here - // not need unnecessary stress parent::setupKey() with our, now unused, $key. - return; - } - } - // setup our key - parent::setupKey(); - } - - /** - * Sets the internal crypt engine - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() - * @see \phpseclib3\Crypt\Common\SymmetricKey::setPreferredEngine() - * @param int $engine - */ - public function setPreferredEngine($engine) - { - if ($this->mode_3cbc) { - $this->des[0]->setPreferredEngine($engine); - $this->des[1]->setPreferredEngine($engine); - $this->des[2]->setPreferredEngine($engine); - } - - parent::setPreferredEngine($engine); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php deleted file mode 100644 index bf765632..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php +++ /dev/null @@ -1,816 +0,0 @@ - - * setKey('12345678901234567890123456789012'); - * - * $plaintext = str_repeat('a', 1024); - * - * echo $twofish->decrypt($twofish->encrypt($plaintext)); - * ?> - * - * - * @author Jim Wigginton - * @author Hans-Juergen Petrich - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Crypt; - -use phpseclib3\Crypt\Common\BlockCipher; -use phpseclib3\Exception\BadModeException; - -/** - * Pure-PHP implementation of Twofish. - * - * @author Jim Wigginton - * @author Hans-Juergen Petrich - */ -class Twofish extends BlockCipher -{ - /** - * The mcrypt specific name of the cipher - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt - * @var string - */ - protected $cipher_name_mcrypt = 'twofish'; - - /** - * Optimizing value while CFB-encrypting - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len - * @var int - */ - protected $cfb_init_len = 800; - - /** - * Q-Table - * - * @var array - */ - private static $q0 = [ - 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, - 0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38, - 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, - 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, - 0xF2, 0xD0, 0x8B, 0x30, 0x84, 0x54, 0xDF, 0x23, - 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82, - 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, - 0xA6, 0xEB, 0xA5, 0xBE, 0x16, 0x0C, 0xE3, 0x61, - 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, - 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, - 0xE1, 0xE6, 0xBD, 0x45, 0xE2, 0xF4, 0xB6, 0x66, - 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7, - 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, - 0xEA, 0x77, 0x39, 0xAF, 0x33, 0xC9, 0x62, 0x71, - 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, - 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, - 0xA1, 0x1D, 0xAA, 0xED, 0x06, 0x70, 0xB2, 0xD2, - 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90, - 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, - 0x9E, 0x9C, 0x52, 0x1B, 0x5F, 0x93, 0x0A, 0xEF, - 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, - 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, - 0x2A, 0xCE, 0xCB, 0x2F, 0xFC, 0x97, 0x05, 0x7A, - 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A, - 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, - 0xB8, 0xDA, 0xB0, 0x17, 0x55, 0x1F, 0x8A, 0x7D, - 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, - 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, - 0x6E, 0x50, 0xDE, 0x68, 0x65, 0xBC, 0xDB, 0xF8, - 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, - 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, - 0x6F, 0x9D, 0x36, 0x42, 0x4A, 0x5E, 0xC1, 0xE0 - ]; - - /** - * Q-Table - * - * @var array - */ - private static $q1 = [ - 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, - 0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B, - 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, - 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, - 0x5E, 0xBA, 0xAE, 0x5B, 0x8A, 0x00, 0xBC, 0x9D, - 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5, - 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, - 0xB2, 0x73, 0x4C, 0x54, 0x92, 0x74, 0x36, 0x51, - 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, - 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, - 0x13, 0x95, 0x9C, 0xC7, 0x24, 0x46, 0x3B, 0x70, - 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8, - 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, - 0x03, 0x6F, 0x08, 0xBF, 0x40, 0xE7, 0x2B, 0xE2, - 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, - 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, - 0x66, 0x94, 0xA1, 0x1D, 0x3D, 0xF0, 0xDE, 0xB3, - 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E, - 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, - 0x81, 0x88, 0xEE, 0x21, 0xC4, 0x1A, 0xEB, 0xD9, - 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, - 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, - 0x4F, 0xF2, 0x65, 0x8E, 0x78, 0x5C, 0x58, 0x19, - 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64, - 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, - 0xCE, 0xE9, 0x68, 0x44, 0xE0, 0x4D, 0x43, 0x69, - 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, - 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, - 0x22, 0xC9, 0xC0, 0x9B, 0x89, 0xD4, 0xED, 0xAB, - 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9, - 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, - 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xBE, 0x91 - ]; - - /** - * M-Table - * - * @var array - */ - private static $m0 = [ - 0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, 0xE2E22BFB, 0x9E9EFAC8, - 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B, - 0x3C3C57D6, 0x93938A32, 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1, - 0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, 0xB0B0B306, 0x7575DE3F, - 0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D, - 0xAEAE2C6D, 0x7F7FABC1, 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5, - 0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, 0x3131272C, 0x808065A3, - 0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51, - 0x2A2A3638, 0xC4C49CB0, 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796, - 0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, 0x6767C027, 0xE9E9AF8C, - 0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70, - 0x29294CCA, 0xF0F035E3, 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8, - 0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, 0xC8C81DC3, 0x9999FFCC, - 0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2, - 0xB5B53D79, 0x09090F0C, 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9, - 0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, 0xEDEDD07A, 0x4343FC17, - 0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3, - 0x5656E70B, 0xE3E3DA72, 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E, - 0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, 0x8181942A, 0x91910149, - 0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9, - 0x7878AEC5, 0xC5C56D39, 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01, - 0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, 0x55559DF9, 0x7E7E5A48, - 0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519, - 0x0606F48D, 0x404086E5, 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64, - 0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, 0x2D2D333C, 0x3030D6A5, - 0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969, - 0xD9D97929, 0x8686912E, 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E, - 0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, 0xC1C112CF, 0x8585EBDC, - 0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB, - 0xABABA212, 0x6F6F3EA2, 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9, - 0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, 0x04047FF6, 0x272746C2, - 0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91 - ]; - - /** - * M-Table - * - * @var array - */ - private static $m1 = [ - 0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, 0xA3658080, 0x76DFE4E4, - 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A, - 0x0D54E6E6, 0xC6432020, 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141, - 0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, 0x94B1FBFB, 0x485A7E7E, - 0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060, - 0x1945FDFD, 0x5BA33A3A, 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757, - 0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, 0x9B53AAAA, 0x7C635D5D, - 0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7, - 0xC0F09090, 0x8CAFE9E9, 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656, - 0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, 0xB499C3C3, 0xF1975B5B, - 0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8, - 0xCCFF9999, 0x95EA1414, 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3, - 0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, 0xBF7E9595, 0xBA207D7D, - 0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB, - 0x81FB0F0F, 0x793DB5B5, 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282, - 0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, 0x86135050, 0xE730F7F7, - 0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B, - 0x410B9F9F, 0x7B8B0202, 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC, - 0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, 0xB1C72B2B, 0xAB6F8E8E, - 0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9, - 0x91EF1313, 0x85FE0808, 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272, - 0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, 0x6929A9A9, 0x647D4F4F, - 0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED, - 0xAC87D1D1, 0x7F8E0505, 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5, - 0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, 0x4C5F7979, 0x02B6B7B7, - 0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2, - 0x57AC3333, 0xC718CFCF, 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3, - 0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, 0x99E51D1D, 0x34392323, - 0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA, - 0xC8FA9E9E, 0xA882D6D6, 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF, - 0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, 0x0FE25151, 0x00000000, - 0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8 - ]; - - /** - * M-Table - * - * @var array - */ - private static $m2 = [ - 0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, 0xE2FBE22B, 0x9EC89EFA, - 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7, - 0x3CD63C57, 0x9332938A, 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783, - 0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, 0xB006B0B3, 0x753F75DE, - 0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0, - 0xAE6DAE2C, 0x7FC17FAB, 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA, - 0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, 0x312C3127, 0x80A38065, - 0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F, - 0x2A382A36, 0xC4B0C49C, 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07, - 0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, 0x672767C0, 0xE98CE9AF, - 0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C, - 0x29CA294C, 0xF0E3F035, 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96, - 0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, 0xC8C3C81D, 0x99CC99FF, - 0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E, - 0xB579B53D, 0x090C090F, 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD, - 0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, 0xED7AEDD0, 0x431743FC, - 0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71, - 0x560B56E7, 0xE372E3DA, 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85, - 0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, 0x812A8194, 0x91499101, - 0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5, - 0x78C578AE, 0xC539C56D, 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B, - 0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, 0x55F9559D, 0x7E487E5A, - 0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45, - 0x068D06F4, 0x40E54086, 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D, - 0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, 0x2D3C2D33, 0x30A530D6, - 0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929, - 0xD929D979, 0x862E8691, 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D, - 0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, 0xC1CFC112, 0x85DC85EB, - 0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F, - 0xAB12ABA2, 0x6FA26F3E, 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9, - 0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, 0x04F6047F, 0x27C22746, - 0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF - ]; - - /** - * M-Table - * - * @var array - */ - private static $m3 = [ - 0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, 0x6580A365, 0xDFE476DF, - 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836, - 0x54E60D54, 0x4320C643, 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77, - 0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, 0xB1FB94B1, 0x5A7E485A, - 0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5, - 0x45FD1945, 0xA33A5BA3, 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216, - 0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, 0x53AA9B53, 0x635D7C63, - 0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123, - 0xF090C0F0, 0xAFE98CAF, 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7, - 0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, 0x99C3B499, 0x975BF197, - 0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB, - 0xFF99CCFF, 0xEA1495EA, 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C, - 0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, 0x7E95BF7E, 0x207DBA20, - 0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137, - 0xFB0F81FB, 0x3DB5793D, 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE, - 0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, 0x13508613, 0x30F7E730, - 0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252, - 0x0B9F410B, 0x8B027B8B, 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4, - 0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, 0xC72BB1C7, 0x6F8EAB6F, - 0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A, - 0xEF1391EF, 0xFE0885FE, 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB, - 0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, 0x29A96929, 0x7D4F647D, - 0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0, - 0x87D1AC87, 0x8E057F8E, 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8, - 0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, 0x5F794C5F, 0xB6B702B6, - 0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38, - 0xAC3357AC, 0x18CFC718, 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA, - 0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, 0xE51D99E5, 0x39233439, - 0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6, - 0xFA9EC8FA, 0x82D6A882, 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D, - 0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, 0xE2510FE2, 0x00000000, - 0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8 - ]; - - /** - * The Key Schedule Array - * - * @var array - */ - private $K = []; - - /** - * The Key depended S-Table 0 - * - * @var array - */ - private $S0 = []; - - /** - * The Key depended S-Table 1 - * - * @var array - */ - private $S1 = []; - - /** - * The Key depended S-Table 2 - * - * @var array - */ - private $S2 = []; - - /** - * The Key depended S-Table 3 - * - * @var array - */ - private $S3 = []; - - /** - * Holds the last used key - * - * @var array - */ - private $kl; - - /** - * The Key Length (in bytes) - * - * @see Crypt_Twofish::setKeyLength() - * @var int - */ - protected $key_length = 16; - - /** - * Default Constructor. - * - * @param string $mode - * @throws BadModeException if an invalid / unsupported mode is provided - */ - public function __construct($mode) - { - parent::__construct($mode); - - if ($this->mode == self::MODE_STREAM) { - throw new BadModeException('Block ciphers cannot be ran in stream mode'); - } - } - - /** - * Initialize Static Variables - */ - protected static function initialize_static_variables() - { - if (is_float(self::$m3[0])) { - self::$m0 = array_map('intval', self::$m0); - self::$m1 = array_map('intval', self::$m1); - self::$m2 = array_map('intval', self::$m2); - self::$m3 = array_map('intval', self::$m3); - self::$q0 = array_map('intval', self::$q0); - self::$q1 = array_map('intval', self::$q1); - } - - parent::initialize_static_variables(); - } - - /** - * Sets the key length. - * - * Valid key lengths are 128, 192 or 256 bits - * - * @param int $length - */ - public function setKeyLength($length) - { - switch ($length) { - case 128: - case 192: - case 256: - break; - default: - throw new \LengthException('Key of size ' . $length . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported'); - } - - parent::setKeyLength($length); - } - - /** - * Sets the key. - * - * Rijndael supports five different key lengths - * - * @see setKeyLength() - * @param string $key - * @throws \LengthException if the key length isn't supported - */ - public function setKey($key) - { - switch (strlen($key)) { - case 16: - case 24: - case 32: - break; - default: - throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported'); - } - - parent::setKey($key); - } - - /** - * Setup the key (expansion) - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupKey() - */ - protected function setupKey() - { - if (isset($this->kl['key']) && $this->key === $this->kl['key']) { - // already expanded - return; - } - $this->kl = ['key' => $this->key]; - - /* Key expanding and generating the key-depended s-boxes */ - $le_longs = unpack('V*', $this->key); - $key = unpack('C*', $this->key); - $m0 = self::$m0; - $m1 = self::$m1; - $m2 = self::$m2; - $m3 = self::$m3; - $q0 = self::$q0; - $q1 = self::$q1; - - $K = $S0 = $S1 = $S2 = $S3 = []; - - switch (strlen($this->key)) { - case 16: - list($s7, $s6, $s5, $s4) = $this->mdsrem($le_longs[1], $le_longs[2]); - list($s3, $s2, $s1, $s0) = $this->mdsrem($le_longs[3], $le_longs[4]); - for ($i = 0, $j = 1; $i < 40; $i += 2, $j += 2) { - $A = $m0[$q0[$q0[$i] ^ $key[ 9]] ^ $key[1]] ^ - $m1[$q0[$q1[$i] ^ $key[10]] ^ $key[2]] ^ - $m2[$q1[$q0[$i] ^ $key[11]] ^ $key[3]] ^ - $m3[$q1[$q1[$i] ^ $key[12]] ^ $key[4]]; - $B = $m0[$q0[$q0[$j] ^ $key[13]] ^ $key[5]] ^ - $m1[$q0[$q1[$j] ^ $key[14]] ^ $key[6]] ^ - $m2[$q1[$q0[$j] ^ $key[15]] ^ $key[7]] ^ - $m3[$q1[$q1[$j] ^ $key[16]] ^ $key[8]]; - $B = ($B << 8) | ($B >> 24 & 0xff); - $A = self::safe_intval($A + $B); - $K[] = $A; - $A = self::safe_intval($A + $B); - $K[] = ($A << 9 | $A >> 23 & 0x1ff); - } - for ($i = 0; $i < 256; ++$i) { - $S0[$i] = $m0[$q0[$q0[$i] ^ $s4] ^ $s0]; - $S1[$i] = $m1[$q0[$q1[$i] ^ $s5] ^ $s1]; - $S2[$i] = $m2[$q1[$q0[$i] ^ $s6] ^ $s2]; - $S3[$i] = $m3[$q1[$q1[$i] ^ $s7] ^ $s3]; - } - break; - case 24: - list($sb, $sa, $s9, $s8) = $this->mdsrem($le_longs[1], $le_longs[2]); - list($s7, $s6, $s5, $s4) = $this->mdsrem($le_longs[3], $le_longs[4]); - list($s3, $s2, $s1, $s0) = $this->mdsrem($le_longs[5], $le_longs[6]); - for ($i = 0, $j = 1; $i < 40; $i += 2, $j += 2) { - $A = $m0[$q0[$q0[$q1[$i] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^ - $m1[$q0[$q1[$q1[$i] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^ - $m2[$q1[$q0[$q0[$i] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^ - $m3[$q1[$q1[$q0[$i] ^ $key[20]] ^ $key[12]] ^ $key[4]]; - $B = $m0[$q0[$q0[$q1[$j] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^ - $m1[$q0[$q1[$q1[$j] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^ - $m2[$q1[$q0[$q0[$j] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^ - $m3[$q1[$q1[$q0[$j] ^ $key[24]] ^ $key[16]] ^ $key[8]]; - $B = ($B << 8) | ($B >> 24 & 0xff); - $A = self::safe_intval($A + $B); - $K[] = $A; - $A = self::safe_intval($A + $B); - $K[] = ($A << 9 | $A >> 23 & 0x1ff); - } - for ($i = 0; $i < 256; ++$i) { - $S0[$i] = $m0[$q0[$q0[$q1[$i] ^ $s8] ^ $s4] ^ $s0]; - $S1[$i] = $m1[$q0[$q1[$q1[$i] ^ $s9] ^ $s5] ^ $s1]; - $S2[$i] = $m2[$q1[$q0[$q0[$i] ^ $sa] ^ $s6] ^ $s2]; - $S3[$i] = $m3[$q1[$q1[$q0[$i] ^ $sb] ^ $s7] ^ $s3]; - } - break; - default: // 32 - list($sf, $se, $sd, $sc) = $this->mdsrem($le_longs[1], $le_longs[2]); - list($sb, $sa, $s9, $s8) = $this->mdsrem($le_longs[3], $le_longs[4]); - list($s7, $s6, $s5, $s4) = $this->mdsrem($le_longs[5], $le_longs[6]); - list($s3, $s2, $s1, $s0) = $this->mdsrem($le_longs[7], $le_longs[8]); - for ($i = 0, $j = 1; $i < 40; $i += 2, $j += 2) { - $A = $m0[$q0[$q0[$q1[$q1[$i] ^ $key[25]] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^ - $m1[$q0[$q1[$q1[$q0[$i] ^ $key[26]] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^ - $m2[$q1[$q0[$q0[$q0[$i] ^ $key[27]] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^ - $m3[$q1[$q1[$q0[$q1[$i] ^ $key[28]] ^ $key[20]] ^ $key[12]] ^ $key[4]]; - $B = $m0[$q0[$q0[$q1[$q1[$j] ^ $key[29]] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^ - $m1[$q0[$q1[$q1[$q0[$j] ^ $key[30]] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^ - $m2[$q1[$q0[$q0[$q0[$j] ^ $key[31]] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^ - $m3[$q1[$q1[$q0[$q1[$j] ^ $key[32]] ^ $key[24]] ^ $key[16]] ^ $key[8]]; - $B = ($B << 8) | ($B >> 24 & 0xff); - $A = self::safe_intval($A + $B); - $K[] = $A; - $A = self::safe_intval($A + $B); - $K[] = ($A << 9 | $A >> 23 & 0x1ff); - } - for ($i = 0; $i < 256; ++$i) { - $S0[$i] = $m0[$q0[$q0[$q1[$q1[$i] ^ $sc] ^ $s8] ^ $s4] ^ $s0]; - $S1[$i] = $m1[$q0[$q1[$q1[$q0[$i] ^ $sd] ^ $s9] ^ $s5] ^ $s1]; - $S2[$i] = $m2[$q1[$q0[$q0[$q0[$i] ^ $se] ^ $sa] ^ $s6] ^ $s2]; - $S3[$i] = $m3[$q1[$q1[$q0[$q1[$i] ^ $sf] ^ $sb] ^ $s7] ^ $s3]; - } - } - - $this->K = $K; - $this->S0 = $S0; - $this->S1 = $S1; - $this->S2 = $S2; - $this->S3 = $S3; - } - - /** - * _mdsrem function using by the twofish cipher algorithm - * - * @param string $A - * @param string $B - * @return array - */ - private function mdsrem($A, $B) - { - // No gain by unrolling this loop. - for ($i = 0; $i < 8; ++$i) { - // Get most significant coefficient. - $t = 0xff & ($B >> 24); - - // Shift the others up. - $B = ($B << 8) | (0xff & ($A >> 24)); - $A <<= 8; - - $u = $t << 1; - - // Subtract the modular polynomial on overflow. - if ($t & 0x80) { - $u ^= 0x14d; - } - - // Remove t * (a * x^2 + 1). - $B ^= $t ^ ($u << 16); - - // Form u = a*t + t/a = t*(a + 1/a). - $u ^= 0x7fffffff & ($t >> 1); - - // Add the modular polynomial on underflow. - if ($t & 0x01) { - $u ^= 0xa6 ; - } - - // Remove t * (a + 1/a) * (x^3 + x). - $B ^= ($u << 24) | ($u << 8); - } - - return [ - 0xff & $B >> 24, - 0xff & $B >> 16, - 0xff & $B >> 8, - 0xff & $B]; - } - - /** - * Encrypts a block - * - * @param string $in - * @return string - */ - protected function encryptBlock($in) - { - $S0 = $this->S0; - $S1 = $this->S1; - $S2 = $this->S2; - $S3 = $this->S3; - $K = $this->K; - - $in = unpack("V4", $in); - $R0 = $K[0] ^ $in[1]; - $R1 = $K[1] ^ $in[2]; - $R2 = $K[2] ^ $in[3]; - $R3 = $K[3] ^ $in[4]; - - $ki = 7; - while ($ki < 39) { - $t0 = $S0[ $R0 & 0xff] ^ - $S1[($R0 >> 8) & 0xff] ^ - $S2[($R0 >> 16) & 0xff] ^ - $S3[($R0 >> 24) & 0xff]; - $t1 = $S0[($R1 >> 24) & 0xff] ^ - $S1[ $R1 & 0xff] ^ - $S2[($R1 >> 8) & 0xff] ^ - $S3[($R1 >> 16) & 0xff]; - $R2 ^= self::safe_intval($t0 + $t1 + $K[++$ki]); - $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31); - $R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ self::safe_intval($t0 + ($t1 << 1) + $K[++$ki]); - - $t0 = $S0[ $R2 & 0xff] ^ - $S1[($R2 >> 8) & 0xff] ^ - $S2[($R2 >> 16) & 0xff] ^ - $S3[($R2 >> 24) & 0xff]; - $t1 = $S0[($R3 >> 24) & 0xff] ^ - $S1[ $R3 & 0xff] ^ - $S2[($R3 >> 8) & 0xff] ^ - $S3[($R3 >> 16) & 0xff]; - $R0 ^= self::safe_intval($t0 + $t1 + $K[++$ki]); - $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31); - $R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ self::safe_intval($t0 + ($t1 << 1) + $K[++$ki]); - } - - // @codingStandardsIgnoreStart - return pack("V4", $K[4] ^ $R2, - $K[5] ^ $R3, - $K[6] ^ $R0, - $K[7] ^ $R1); - // @codingStandardsIgnoreEnd - } - - /** - * Decrypts a block - * - * @param string $in - * @return string - */ - protected function decryptBlock($in) - { - $S0 = $this->S0; - $S1 = $this->S1; - $S2 = $this->S2; - $S3 = $this->S3; - $K = $this->K; - - $in = unpack("V4", $in); - $R0 = $K[4] ^ $in[1]; - $R1 = $K[5] ^ $in[2]; - $R2 = $K[6] ^ $in[3]; - $R3 = $K[7] ^ $in[4]; - - $ki = 40; - while ($ki > 8) { - $t0 = $S0[$R0 & 0xff] ^ - $S1[$R0 >> 8 & 0xff] ^ - $S2[$R0 >> 16 & 0xff] ^ - $S3[$R0 >> 24 & 0xff]; - $t1 = $S0[$R1 >> 24 & 0xff] ^ - $S1[$R1 & 0xff] ^ - $S2[$R1 >> 8 & 0xff] ^ - $S3[$R1 >> 16 & 0xff]; - $R3 ^= self::safe_intval($t0 + ($t1 << 1) + $K[--$ki]); - $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31; - $R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ self::safe_intval($t0 + $t1 + $K[--$ki]); - - $t0 = $S0[$R2 & 0xff] ^ - $S1[$R2 >> 8 & 0xff] ^ - $S2[$R2 >> 16 & 0xff] ^ - $S3[$R2 >> 24 & 0xff]; - $t1 = $S0[$R3 >> 24 & 0xff] ^ - $S1[$R3 & 0xff] ^ - $S2[$R3 >> 8 & 0xff] ^ - $S3[$R3 >> 16 & 0xff]; - $R1 ^= self::safe_intval($t0 + ($t1 << 1) + $K[--$ki]); - $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31; - $R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ self::safe_intval($t0 + $t1 + $K[--$ki]); - } - - // @codingStandardsIgnoreStart - return pack("V4", $K[0] ^ $R2, - $K[1] ^ $R3, - $K[2] ^ $R0, - $K[3] ^ $R1); - // @codingStandardsIgnoreEnd - } - - /** - * Setup the performance-optimized function for de/encrypt() - * - * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupInlineCrypt() - */ - protected function setupInlineCrypt() - { - $K = $this->K; - $init_crypt = ' - static $S0, $S1, $S2, $S3; - if (!$S0) { - for ($i = 0; $i < 256; ++$i) { - $S0[] = (int)$this->S0[$i]; - $S1[] = (int)$this->S1[$i]; - $S2[] = (int)$this->S2[$i]; - $S3[] = (int)$this->S3[$i]; - } - } - '; - - $safeint = self::safe_intval_inline(); - - // Generating encrypt code: - $encrypt_block = ' - $in = unpack("V4", $in); - $R0 = ' . $K[0] . ' ^ $in[1]; - $R1 = ' . $K[1] . ' ^ $in[2]; - $R2 = ' . $K[2] . ' ^ $in[3]; - $R3 = ' . $K[3] . ' ^ $in[4]; - '; - for ($ki = 7, $i = 0; $i < 8; ++$i) { - $encrypt_block .= ' - $t0 = $S0[ $R0 & 0xff] ^ - $S1[($R0 >> 8) & 0xff] ^ - $S2[($R0 >> 16) & 0xff] ^ - $S3[($R0 >> 24) & 0xff]; - $t1 = $S0[($R1 >> 24) & 0xff] ^ - $S1[ $R1 & 0xff] ^ - $S2[($R1 >> 8) & 0xff] ^ - $S3[($R1 >> 16) & 0xff]; - $R2^= ' . sprintf($safeint, '$t0 + $t1 + ' . $K[++$ki]) . '; - $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31); - $R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ' . sprintf($safeint, '($t0 + ($t1 << 1) + ' . $K[++$ki] . ')') . '; - - $t0 = $S0[ $R2 & 0xff] ^ - $S1[($R2 >> 8) & 0xff] ^ - $S2[($R2 >> 16) & 0xff] ^ - $S3[($R2 >> 24) & 0xff]; - $t1 = $S0[($R3 >> 24) & 0xff] ^ - $S1[ $R3 & 0xff] ^ - $S2[($R3 >> 8) & 0xff] ^ - $S3[($R3 >> 16) & 0xff]; - $R0^= ' . sprintf($safeint, '($t0 + $t1 + ' . $K[++$ki] . ')') . '; - $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31); - $R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ' . sprintf($safeint, '($t0 + ($t1 << 1) + ' . $K[++$ki] . ')') . '; - '; - } - $encrypt_block .= ' - $in = pack("V4", ' . $K[4] . ' ^ $R2, - ' . $K[5] . ' ^ $R3, - ' . $K[6] . ' ^ $R0, - ' . $K[7] . ' ^ $R1); - '; - - // Generating decrypt code: - $decrypt_block = ' - $in = unpack("V4", $in); - $R0 = ' . $K[4] . ' ^ $in[1]; - $R1 = ' . $K[5] . ' ^ $in[2]; - $R2 = ' . $K[6] . ' ^ $in[3]; - $R3 = ' . $K[7] . ' ^ $in[4]; - '; - for ($ki = 40, $i = 0; $i < 8; ++$i) { - $decrypt_block .= ' - $t0 = $S0[$R0 & 0xff] ^ - $S1[$R0 >> 8 & 0xff] ^ - $S2[$R0 >> 16 & 0xff] ^ - $S3[$R0 >> 24 & 0xff]; - $t1 = $S0[$R1 >> 24 & 0xff] ^ - $S1[$R1 & 0xff] ^ - $S2[$R1 >> 8 & 0xff] ^ - $S3[$R1 >> 16 & 0xff]; - $R3^= ' . sprintf($safeint, '$t0 + ($t1 << 1) + ' . $K[--$ki]) . '; - $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31; - $R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ' . sprintf($safeint, '($t0 + $t1 + ' . $K[--$ki] . ')') . '; - - $t0 = $S0[$R2 & 0xff] ^ - $S1[$R2 >> 8 & 0xff] ^ - $S2[$R2 >> 16 & 0xff] ^ - $S3[$R2 >> 24 & 0xff]; - $t1 = $S0[$R3 >> 24 & 0xff] ^ - $S1[$R3 & 0xff] ^ - $S2[$R3 >> 8 & 0xff] ^ - $S3[$R3 >> 16 & 0xff]; - $R1^= ' . sprintf($safeint, '$t0 + ($t1 << 1) + ' . $K[--$ki]) . '; - $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31; - $R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ' . sprintf($safeint, '($t0 + $t1 + ' . $K[--$ki] . ')') . '; - '; - } - $decrypt_block .= ' - $in = pack("V4", ' . $K[0] . ' ^ $R2, - ' . $K[1] . ' ^ $R3, - ' . $K[2] . ' ^ $R0, - ' . $K[3] . ' ^ $R1); - '; - - $this->inline_crypt = $this->createInlineCryptFunction( - [ - 'init_crypt' => $init_crypt, - 'init_encrypt' => '', - 'init_decrypt' => '', - 'encrypt_block' => $encrypt_block, - 'decrypt_block' => $decrypt_block - ] - ); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/BadConfigurationException.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/BadConfigurationException.php deleted file mode 100644 index 1aabcae0..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/BadConfigurationException.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Exception; - -/** - * BadConfigurationException - * - * @author Jim Wigginton - */ -class BadConfigurationException extends \RuntimeException -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/BadDecryptionException.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/BadDecryptionException.php deleted file mode 100644 index 88331dce..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/BadDecryptionException.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Exception; - -/** - * BadDecryptionException - * - * @author Jim Wigginton - */ -class BadDecryptionException extends \RuntimeException -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/BadModeException.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/BadModeException.php deleted file mode 100644 index 87689b22..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/BadModeException.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Exception; - -/** - * BadModeException - * - * @author Jim Wigginton - */ -class BadModeException extends \RuntimeException -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/ConnectionClosedException.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/ConnectionClosedException.php deleted file mode 100644 index 6aaccbad..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/ConnectionClosedException.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Exception; - -/** - * ConnectionClosedException - * - * @author Jim Wigginton - */ -class ConnectionClosedException extends \RuntimeException -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/FileNotFoundException.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/FileNotFoundException.php deleted file mode 100644 index 66e72709..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/FileNotFoundException.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Exception; - -/** - * FileNotFoundException - * - * @author Jim Wigginton - */ -class FileNotFoundException extends \RuntimeException -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/InconsistentSetupException.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/InconsistentSetupException.php deleted file mode 100644 index 23c38fb0..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/InconsistentSetupException.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Exception; - -/** - * InconsistentSetupException - * - * @author Jim Wigginton - */ -class InconsistentSetupException extends \RuntimeException -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/InsufficientSetupException.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/InsufficientSetupException.php deleted file mode 100644 index 4f4114d7..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/InsufficientSetupException.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Exception; - -/** - * InsufficientSetupException - * - * @author Jim Wigginton - */ -class InsufficientSetupException extends \RuntimeException -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/NoKeyLoadedException.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/NoKeyLoadedException.php deleted file mode 100644 index 7ec2fe9b..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/NoKeyLoadedException.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Exception; - -/** - * NoKeyLoadedException - * - * @author Jim Wigginton - */ -class NoKeyLoadedException extends \RuntimeException -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/NoSupportedAlgorithmsException.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/NoSupportedAlgorithmsException.php deleted file mode 100644 index b3ea8f38..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/NoSupportedAlgorithmsException.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Exception; - -/** - * NoSupportedAlgorithmsException - * - * @author Jim Wigginton - */ -class NoSupportedAlgorithmsException extends \RuntimeException -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/UnableToConnectException.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/UnableToConnectException.php deleted file mode 100644 index bfa005b4..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/UnableToConnectException.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Exception; - -/** - * UnableToConnectException - * - * @author Jim Wigginton - */ -class UnableToConnectException extends \RuntimeException -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/UnsupportedAlgorithmException.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/UnsupportedAlgorithmException.php deleted file mode 100644 index 210a9a5c..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/UnsupportedAlgorithmException.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Exception; - -/** - * UnsupportedAlgorithmException - * - * @author Jim Wigginton - */ -class UnsupportedAlgorithmException extends \RuntimeException -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/UnsupportedCurveException.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/UnsupportedCurveException.php deleted file mode 100644 index 99152152..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/UnsupportedCurveException.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Exception; - -/** - * UnsupportedCurveException - * - * @author Jim Wigginton - */ -class UnsupportedCurveException extends \RuntimeException -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/UnsupportedFormatException.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/UnsupportedFormatException.php deleted file mode 100644 index e207d7e2..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/UnsupportedFormatException.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Exception; - -/** - * UnsupportedFormatException - * - * @author Jim Wigginton - */ -class UnsupportedFormatException extends \RuntimeException -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/UnsupportedOperationException.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/UnsupportedOperationException.php deleted file mode 100644 index 9a115444..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Exception/UnsupportedOperationException.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Exception; - -/** - * UnsupportedOperationException - * - * @author Jim Wigginton - */ -class UnsupportedOperationException extends \RuntimeException -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ANSI.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ANSI.php deleted file mode 100644 index 5803a372..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ANSI.php +++ /dev/null @@ -1,551 +0,0 @@ - - * @copyright 2012 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File; - -/** - * Pure-PHP ANSI Decoder - * - * @author Jim Wigginton - */ -class ANSI -{ - /** - * Max Width - * - * @var int - */ - private $max_x; - - /** - * Max Height - * - * @var int - */ - private $max_y; - - /** - * Max History - * - * @var int - */ - private $max_history; - - /** - * History - * - * @var array - */ - private $history; - - /** - * History Attributes - * - * @var array - */ - private $history_attrs; - - /** - * Current Column - * - * @var int - */ - private $x; - - /** - * Current Row - * - * @var int - */ - private $y; - - /** - * Old Column - * - * @var int - */ - private $old_x; - - /** - * Old Row - * - * @var int - */ - private $old_y; - - /** - * An empty attribute cell - * - * @var object - */ - private $base_attr_cell; - - /** - * The current attribute cell - * - * @var object - */ - private $attr_cell; - - /** - * An empty attribute row - * - * @var array - */ - private $attr_row; - - /** - * The current screen text - * - * @var list - */ - private $screen; - - /** - * The current screen attributes - * - * @var array - */ - private $attrs; - - /** - * Current ANSI code - * - * @var string - */ - private $ansi; - - /** - * Tokenization - * - * @var array - */ - private $tokenization; - - /** - * Default Constructor. - * - * @return \phpseclib3\File\ANSI - */ - public function __construct() - { - $attr_cell = new \stdClass(); - $attr_cell->bold = false; - $attr_cell->underline = false; - $attr_cell->blink = false; - $attr_cell->background = 'black'; - $attr_cell->foreground = 'white'; - $attr_cell->reverse = false; - $this->base_attr_cell = clone $attr_cell; - $this->attr_cell = clone $attr_cell; - - $this->setHistory(200); - $this->setDimensions(80, 24); - } - - /** - * Set terminal width and height - * - * Resets the screen as well - * - * @param int $x - * @param int $y - */ - public function setDimensions($x, $y) - { - $this->max_x = $x - 1; - $this->max_y = $y - 1; - $this->x = $this->y = 0; - $this->history = $this->history_attrs = []; - $this->attr_row = array_fill(0, $this->max_x + 2, $this->base_attr_cell); - $this->screen = array_fill(0, $this->max_y + 1, ''); - $this->attrs = array_fill(0, $this->max_y + 1, $this->attr_row); - $this->ansi = ''; - } - - /** - * Set the number of lines that should be logged past the terminal height - * - * @param int $history - */ - public function setHistory($history) - { - $this->max_history = $history; - } - - /** - * Load a string - * - * @param string $source - */ - public function loadString($source) - { - $this->setDimensions($this->max_x + 1, $this->max_y + 1); - $this->appendString($source); - } - - /** - * Appdend a string - * - * @param string $source - */ - public function appendString($source) - { - $this->tokenization = ['']; - for ($i = 0; $i < strlen($source); $i++) { - if (strlen($this->ansi)) { - $this->ansi .= $source[$i]; - $chr = ord($source[$i]); - // http://en.wikipedia.org/wiki/ANSI_escape_code#Sequence_elements - // single character CSI's not currently supported - switch (true) { - case $this->ansi == "\x1B=": - $this->ansi = ''; - continue 2; - case strlen($this->ansi) == 2 && $chr >= 64 && $chr <= 95 && $chr != ord('['): - case strlen($this->ansi) > 2 && $chr >= 64 && $chr <= 126: - break; - default: - continue 2; - } - $this->tokenization[] = $this->ansi; - $this->tokenization[] = ''; - // http://ascii-table.com/ansi-escape-sequences-vt-100.php - switch ($this->ansi) { - case "\x1B[H": // Move cursor to upper left corner - $this->old_x = $this->x; - $this->old_y = $this->y; - $this->x = $this->y = 0; - break; - case "\x1B[J": // Clear screen from cursor down - $this->history = array_merge($this->history, array_slice(array_splice($this->screen, $this->y + 1), 0, $this->old_y)); - $this->screen = array_merge($this->screen, array_fill($this->y, $this->max_y, '')); - - $this->history_attrs = array_merge($this->history_attrs, array_slice(array_splice($this->attrs, $this->y + 1), 0, $this->old_y)); - $this->attrs = array_merge($this->attrs, array_fill($this->y, $this->max_y, $this->attr_row)); - - if (count($this->history) == $this->max_history) { - array_shift($this->history); - array_shift($this->history_attrs); - } - // fall-through - case "\x1B[K": // Clear screen from cursor right - $this->screen[$this->y] = substr($this->screen[$this->y], 0, $this->x); - - array_splice($this->attrs[$this->y], $this->x + 1, $this->max_x - $this->x, array_fill($this->x, $this->max_x - ($this->x - 1), $this->base_attr_cell)); - break; - case "\x1B[2K": // Clear entire line - $this->screen[$this->y] = str_repeat(' ', $this->x); - $this->attrs[$this->y] = $this->attr_row; - break; - case "\x1B[?1h": // set cursor key to application - case "\x1B[?25h": // show the cursor - case "\x1B(B": // set united states g0 character set - break; - case "\x1BE": // Move to next line - $this->newLine(); - $this->x = 0; - break; - default: - switch (true) { - case preg_match('#\x1B\[(\d+)B#', $this->ansi, $match): // Move cursor down n lines - $this->old_y = $this->y; - $this->y += (int) $match[1]; - break; - case preg_match('#\x1B\[(\d+);(\d+)H#', $this->ansi, $match): // Move cursor to screen location v,h - $this->old_x = $this->x; - $this->old_y = $this->y; - $this->x = $match[2] - 1; - $this->y = (int) $match[1] - 1; - break; - case preg_match('#\x1B\[(\d+)C#', $this->ansi, $match): // Move cursor right n lines - $this->old_x = $this->x; - $this->x += $match[1]; - break; - case preg_match('#\x1B\[(\d+)D#', $this->ansi, $match): // Move cursor left n lines - $this->old_x = $this->x; - $this->x -= $match[1]; - if ($this->x < 0) { - $this->x = 0; - } - break; - case preg_match('#\x1B\[(\d+);(\d+)r#', $this->ansi, $match): // Set top and bottom lines of a window - break; - case preg_match('#\x1B\[(\d*(?:;\d*)*)m#', $this->ansi, $match): // character attributes - $attr_cell = &$this->attr_cell; - $mods = explode(';', $match[1]); - foreach ($mods as $mod) { - switch ($mod) { - case '': - case '0': // Turn off character attributes - $attr_cell = clone $this->base_attr_cell; - break; - case '1': // Turn bold mode on - $attr_cell->bold = true; - break; - case '4': // Turn underline mode on - $attr_cell->underline = true; - break; - case '5': // Turn blinking mode on - $attr_cell->blink = true; - break; - case '7': // Turn reverse video on - $attr_cell->reverse = !$attr_cell->reverse; - $temp = $attr_cell->background; - $attr_cell->background = $attr_cell->foreground; - $attr_cell->foreground = $temp; - break; - default: // set colors - //$front = $attr_cell->reverse ? &$attr_cell->background : &$attr_cell->foreground; - $front = &$attr_cell->{ $attr_cell->reverse ? 'background' : 'foreground' }; - //$back = $attr_cell->reverse ? &$attr_cell->foreground : &$attr_cell->background; - $back = &$attr_cell->{ $attr_cell->reverse ? 'foreground' : 'background' }; - switch ($mod) { - // @codingStandardsIgnoreStart - case '30': $front = 'black'; break; - case '31': $front = 'red'; break; - case '32': $front = 'green'; break; - case '33': $front = 'yellow'; break; - case '34': $front = 'blue'; break; - case '35': $front = 'magenta'; break; - case '36': $front = 'cyan'; break; - case '37': $front = 'white'; break; - - case '40': $back = 'black'; break; - case '41': $back = 'red'; break; - case '42': $back = 'green'; break; - case '43': $back = 'yellow'; break; - case '44': $back = 'blue'; break; - case '45': $back = 'magenta'; break; - case '46': $back = 'cyan'; break; - case '47': $back = 'white'; break; - // @codingStandardsIgnoreEnd - - default: - //user_error('Unsupported attribute: ' . $mod); - $this->ansi = ''; - break 2; - } - } - } - break; - default: - //user_error("{$this->ansi} is unsupported\r\n"); - } - } - $this->ansi = ''; - continue; - } - - $this->tokenization[count($this->tokenization) - 1] .= $source[$i]; - switch ($source[$i]) { - case "\r": - $this->x = 0; - break; - case "\n": - $this->newLine(); - break; - case "\x08": // backspace - if ($this->x) { - $this->x--; - $this->attrs[$this->y][$this->x] = clone $this->base_attr_cell; - $this->screen[$this->y] = substr_replace( - $this->screen[$this->y], - $source[$i], - $this->x, - 1 - ); - } - break; - case "\x0F": // shift - break; - case "\x1B": // start ANSI escape code - $this->tokenization[count($this->tokenization) - 1] = substr($this->tokenization[count($this->tokenization) - 1], 0, -1); - //if (!strlen($this->tokenization[count($this->tokenization) - 1])) { - // array_pop($this->tokenization); - //} - $this->ansi .= "\x1B"; - break; - default: - $this->attrs[$this->y][$this->x] = clone $this->attr_cell; - if ($this->x > strlen($this->screen[$this->y])) { - $this->screen[$this->y] = str_repeat(' ', $this->x); - } - $this->screen[$this->y] = substr_replace( - $this->screen[$this->y], - $source[$i], - $this->x, - 1 - ); - - if ($this->x > $this->max_x) { - $this->x = 0; - $this->newLine(); - } else { - $this->x++; - } - } - } - } - - /** - * Add a new line - * - * Also update the $this->screen and $this->history buffers - * - */ - private function newLine() - { - //if ($this->y < $this->max_y) { - // $this->y++; - //} - - while ($this->y >= $this->max_y) { - $this->history = array_merge($this->history, [array_shift($this->screen)]); - $this->screen[] = ''; - - $this->history_attrs = array_merge($this->history_attrs, [array_shift($this->attrs)]); - $this->attrs[] = $this->attr_row; - - if (count($this->history) >= $this->max_history) { - array_shift($this->history); - array_shift($this->history_attrs); - } - - $this->y--; - } - $this->y++; - } - - /** - * Returns the current coordinate without preformating - * - * @param \stdClass $last_attr - * @param \stdClass $cur_attr - * @param string $char - * @return string - */ - private function processCoordinate(\stdClass $last_attr, \stdClass $cur_attr, $char) - { - $output = ''; - - if ($last_attr != $cur_attr) { - $close = $open = ''; - if ($last_attr->foreground != $cur_attr->foreground) { - if ($cur_attr->foreground != 'white') { - $open .= ''; - } - if ($last_attr->foreground != 'white') { - $close = '' . $close; - } - } - if ($last_attr->background != $cur_attr->background) { - if ($cur_attr->background != 'black') { - $open .= ''; - } - if ($last_attr->background != 'black') { - $close = '' . $close; - } - } - if ($last_attr->bold != $cur_attr->bold) { - if ($cur_attr->bold) { - $open .= ''; - } else { - $close = '' . $close; - } - } - if ($last_attr->underline != $cur_attr->underline) { - if ($cur_attr->underline) { - $open .= ''; - } else { - $close = '' . $close; - } - } - if ($last_attr->blink != $cur_attr->blink) { - if ($cur_attr->blink) { - $open .= ''; - } else { - $close = '' . $close; - } - } - $output .= $close . $open; - } - - $output .= htmlspecialchars($char); - - return $output; - } - - /** - * Returns the current screen without preformating - * - * @return string - */ - private function getScreenHelper() - { - $output = ''; - $last_attr = $this->base_attr_cell; - for ($i = 0; $i <= $this->max_y; $i++) { - for ($j = 0; $j <= $this->max_x; $j++) { - $cur_attr = $this->attrs[$i][$j]; - $output .= $this->processCoordinate($last_attr, $cur_attr, isset($this->screen[$i][$j]) ? $this->screen[$i][$j] : ''); - $last_attr = $this->attrs[$i][$j]; - } - $output .= "\r\n"; - } - $output = substr($output, 0, -2); - // close any remaining open tags - $output .= $this->processCoordinate($last_attr, $this->base_attr_cell, ''); - return rtrim($output); - } - - /** - * Returns the current screen - * - * @return string - */ - public function getScreen() - { - return '
' . $this->getScreenHelper() . '
'; - } - - /** - * Returns the current screen and the x previous lines - * - * @return string - */ - public function getHistory() - { - $scrollback = ''; - $last_attr = $this->base_attr_cell; - for ($i = 0; $i < count($this->history); $i++) { - for ($j = 0; $j <= $this->max_x + 1; $j++) { - $cur_attr = $this->history_attrs[$i][$j]; - $scrollback .= $this->processCoordinate($last_attr, $cur_attr, isset($this->history[$i][$j]) ? $this->history[$i][$j] : ''); - $last_attr = $this->history_attrs[$i][$j]; - } - $scrollback .= "\r\n"; - } - $base_attr_cell = $this->base_attr_cell; - $this->base_attr_cell = $last_attr; - $scrollback .= $this->getScreen(); - $this->base_attr_cell = $base_attr_cell; - - return '
' . $scrollback . '
'; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php deleted file mode 100644 index e21589c5..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php +++ /dev/null @@ -1,1509 +0,0 @@ - - * @copyright 2012 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File; - -use DateTime; -use phpseclib3\Common\Functions\Strings; -use phpseclib3\File\ASN1\Element; -use phpseclib3\Math\BigInteger; - -/** - * Pure-PHP ASN.1 Parser - * - * @author Jim Wigginton - */ -abstract class ASN1 -{ - // Tag Classes - // http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=12 - const CLASS_UNIVERSAL = 0; - const CLASS_APPLICATION = 1; - const CLASS_CONTEXT_SPECIFIC = 2; - const CLASS_PRIVATE = 3; - - // Tag Classes - // http://www.obj-sys.com/asn1tutorial/node124.html - const TYPE_BOOLEAN = 1; - const TYPE_INTEGER = 2; - const TYPE_BIT_STRING = 3; - const TYPE_OCTET_STRING = 4; - const TYPE_NULL = 5; - const TYPE_OBJECT_IDENTIFIER = 6; - //const TYPE_OBJECT_DESCRIPTOR = 7; - //const TYPE_INSTANCE_OF = 8; // EXTERNAL - const TYPE_REAL = 9; - const TYPE_ENUMERATED = 10; - //const TYPE_EMBEDDED = 11; - const TYPE_UTF8_STRING = 12; - //const TYPE_RELATIVE_OID = 13; - const TYPE_SEQUENCE = 16; // SEQUENCE OF - const TYPE_SET = 17; // SET OF - - // More Tag Classes - // http://www.obj-sys.com/asn1tutorial/node10.html - const TYPE_NUMERIC_STRING = 18; - const TYPE_PRINTABLE_STRING = 19; - const TYPE_TELETEX_STRING = 20; // T61String - const TYPE_VIDEOTEX_STRING = 21; - const TYPE_IA5_STRING = 22; - const TYPE_UTC_TIME = 23; - const TYPE_GENERALIZED_TIME = 24; - const TYPE_GRAPHIC_STRING = 25; - const TYPE_VISIBLE_STRING = 26; // ISO646String - const TYPE_GENERAL_STRING = 27; - const TYPE_UNIVERSAL_STRING = 28; - //const TYPE_CHARACTER_STRING = 29; - const TYPE_BMP_STRING = 30; - - // Tag Aliases - // These tags are kinda place holders for other tags. - const TYPE_CHOICE = -1; - const TYPE_ANY = -2; - - /** - * ASN.1 object identifiers - * - * @var array - * @link http://en.wikipedia.org/wiki/Object_identifier - */ - private static $oids = []; - - /** - * ASN.1 object identifier reverse mapping - * - * @var array - */ - private static $reverseOIDs = []; - - /** - * Default date format - * - * @var string - * @link http://php.net/class.datetime - */ - private static $format = 'D, d M Y H:i:s O'; - - /** - * Filters - * - * If the mapping type is self::TYPE_ANY what do we actually encode it as? - * - * @var array - * @see self::encode_der() - */ - private static $filters; - - /** - * Current Location of most recent ASN.1 encode process - * - * Useful for debug purposes - * - * @var array - * @see self::encode_der() - */ - private static $location; - - /** - * DER Encoded String - * - * In case we need to create ASN1\Element object's.. - * - * @var string - * @see self::decodeDER() - */ - private static $encoded; - - /** - * Type mapping table for the ANY type. - * - * Structured or unknown types are mapped to a \phpseclib3\File\ASN1\Element. - * Unambiguous types get the direct mapping (int/real/bool). - * Others are mapped as a choice, with an extra indexing level. - * - * @var array - */ - const ANY_MAP = [ - self::TYPE_BOOLEAN => true, - self::TYPE_INTEGER => true, - self::TYPE_BIT_STRING => 'bitString', - self::TYPE_OCTET_STRING => 'octetString', - self::TYPE_NULL => 'null', - self::TYPE_OBJECT_IDENTIFIER => 'objectIdentifier', - self::TYPE_REAL => true, - self::TYPE_ENUMERATED => 'enumerated', - self::TYPE_UTF8_STRING => 'utf8String', - self::TYPE_NUMERIC_STRING => 'numericString', - self::TYPE_PRINTABLE_STRING => 'printableString', - self::TYPE_TELETEX_STRING => 'teletexString', - self::TYPE_VIDEOTEX_STRING => 'videotexString', - self::TYPE_IA5_STRING => 'ia5String', - self::TYPE_UTC_TIME => 'utcTime', - self::TYPE_GENERALIZED_TIME => 'generalTime', - self::TYPE_GRAPHIC_STRING => 'graphicString', - self::TYPE_VISIBLE_STRING => 'visibleString', - self::TYPE_GENERAL_STRING => 'generalString', - self::TYPE_UNIVERSAL_STRING => 'universalString', - //self::TYPE_CHARACTER_STRING => 'characterString', - self::TYPE_BMP_STRING => 'bmpString' - ]; - - /** - * String type to character size mapping table. - * - * Non-convertable types are absent from this table. - * size == 0 indicates variable length encoding. - * - * @var array - */ - const STRING_TYPE_SIZE = [ - self::TYPE_UTF8_STRING => 0, - self::TYPE_BMP_STRING => 2, - self::TYPE_UNIVERSAL_STRING => 4, - self::TYPE_PRINTABLE_STRING => 1, - self::TYPE_TELETEX_STRING => 1, - self::TYPE_IA5_STRING => 1, - self::TYPE_VISIBLE_STRING => 1, - ]; - - /** - * Parse BER-encoding - * - * Serves a similar purpose to openssl's asn1parse - * - * @param Element|string $encoded - * @return ?array - */ - public static function decodeBER($encoded) - { - if ($encoded instanceof Element) { - $encoded = $encoded->element; - } - - self::$encoded = $encoded; - - $decoded = self::decode_ber($encoded); - if ($decoded === false) { - return null; - } - - return [self::decode_ber($encoded)]; - } - - /** - * Parse BER-encoding (Helper function) - * - * Sometimes we want to get the BER encoding of a particular tag. $start lets us do that without having to reencode. - * $encoded is passed by reference for the recursive calls done for self::TYPE_BIT_STRING and - * self::TYPE_OCTET_STRING. In those cases, the indefinite length is used. - * - * @param string $encoded - * @param int $start - * @param int $encoded_pos - * @return array|bool - */ - private static function decode_ber($encoded, $start = 0, $encoded_pos = 0) - { - $current = ['start' => $start]; - - if (!isset($encoded[$encoded_pos])) { - return false; - } - $type = ord($encoded[$encoded_pos++]); - $startOffset = 1; - - $constructed = ($type >> 5) & 1; - - $tag = $type & 0x1F; - if ($tag == 0x1F) { - $tag = 0; - // process septets (since the eighth bit is ignored, it's not an octet) - do { - if (!isset($encoded[$encoded_pos])) { - return false; - } - $temp = ord($encoded[$encoded_pos++]); - $startOffset++; - $loop = $temp >> 7; - $tag <<= 7; - $temp &= 0x7F; - // "bits 7 to 1 of the first subsequent octet shall not all be zero" - if ($startOffset == 2 && $temp == 0) { - return false; - } - $tag |= $temp; - } while ($loop); - } - - $start += $startOffset; - - // Length, as discussed in paragraph 8.1.3 of X.690-0207.pdf#page=13 - if (!isset($encoded[$encoded_pos])) { - return false; - } - $length = ord($encoded[$encoded_pos++]); - $start++; - if ($length == 0x80) { // indefinite length - // "[A sender shall] use the indefinite form (see 8.1.3.6) if the encoding is constructed and is not all - // immediately available." -- paragraph 8.1.3.2.c - $length = strlen($encoded) - $encoded_pos; - } elseif ($length & 0x80) { // definite length, long form - // technically, the long form of the length can be represented by up to 126 octets (bytes), but we'll only - // support it up to four. - $length &= 0x7F; - $temp = substr($encoded, $encoded_pos, $length); - $encoded_pos += $length; - // tags of indefinte length don't really have a header length; this length includes the tag - $current += ['headerlength' => $length + 2]; - $start += $length; - extract(unpack('Nlength', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4))); - /** @var integer $length */ - } else { - $current += ['headerlength' => 2]; - } - - if ($length > (strlen($encoded) - $encoded_pos)) { - return false; - } - - $content = substr($encoded, $encoded_pos, $length); - $content_pos = 0; - - // at this point $length can be overwritten. it's only accurate for definite length things as is - - /* Class is UNIVERSAL, APPLICATION, PRIVATE, or CONTEXT-SPECIFIC. The UNIVERSAL class is restricted to the ASN.1 - built-in types. It defines an application-independent data type that must be distinguishable from all other - data types. The other three classes are user defined. The APPLICATION class distinguishes data types that - have a wide, scattered use within a particular presentation context. PRIVATE distinguishes data types within - a particular organization or country. CONTEXT-SPECIFIC distinguishes members of a sequence or set, the - alternatives of a CHOICE, or universally tagged set members. Only the class number appears in braces for this - data type; the term CONTEXT-SPECIFIC does not appear. - - -- http://www.obj-sys.com/asn1tutorial/node12.html */ - $class = ($type >> 6) & 3; - switch ($class) { - case self::CLASS_APPLICATION: - case self::CLASS_PRIVATE: - case self::CLASS_CONTEXT_SPECIFIC: - if (!$constructed) { - return [ - 'type' => $class, - 'constant' => $tag, - 'content' => $content, - 'length' => $length + $start - $current['start'] - ] + $current; - } - - $newcontent = []; - $remainingLength = $length; - while ($remainingLength > 0) { - $temp = self::decode_ber($content, $start, $content_pos); - if ($temp === false) { - break; - } - $length = $temp['length']; - // end-of-content octets - see paragraph 8.1.5 - if (substr($content, $content_pos + $length, 2) == "\0\0") { - $length += 2; - $start += $length; - $newcontent[] = $temp; - break; - } - $start += $length; - $remainingLength -= $length; - $newcontent[] = $temp; - $content_pos += $length; - } - - return [ - 'type' => $class, - 'constant' => $tag, - // the array encapsulation is for BC with the old format - 'content' => $newcontent, - // the only time when $content['headerlength'] isn't defined is when the length is indefinite. - // the absence of $content['headerlength'] is how we know if something is indefinite or not. - // technically, it could be defined to be 2 and then another indicator could be used but whatever. - 'length' => $start - $current['start'] - ] + $current; - } - - $current += ['type' => $tag]; - - // decode UNIVERSAL tags - switch ($tag) { - case self::TYPE_BOOLEAN: - // "The contents octets shall consist of a single octet." -- paragraph 8.2.1 - if ($constructed || strlen($content) != 1) { - return false; - } - $current['content'] = (bool) ord($content[$content_pos]); - break; - case self::TYPE_INTEGER: - case self::TYPE_ENUMERATED: - if ($constructed) { - return false; - } - $current['content'] = new BigInteger(substr($content, $content_pos), -256); - break; - case self::TYPE_REAL: // not currently supported - return false; - case self::TYPE_BIT_STRING: - // The initial octet shall encode, as an unsigned binary integer with bit 1 as the least significant bit, - // the number of unused bits in the final subsequent octet. The number shall be in the range zero to - // seven. - if (!$constructed) { - $current['content'] = substr($content, $content_pos); - } else { - $temp = self::decode_ber($content, $start, $content_pos); - if ($temp === false) { - return false; - } - $length -= (strlen($content) - $content_pos); - $last = count($temp) - 1; - for ($i = 0; $i < $last; $i++) { - // all subtags should be bit strings - if ($temp[$i]['type'] != self::TYPE_BIT_STRING) { - return false; - } - $current['content'] .= substr($temp[$i]['content'], 1); - } - // all subtags should be bit strings - if ($temp[$last]['type'] != self::TYPE_BIT_STRING) { - return false; - } - $current['content'] = $temp[$last]['content'][0] . $current['content'] . substr($temp[$i]['content'], 1); - } - break; - case self::TYPE_OCTET_STRING: - if (!$constructed) { - $current['content'] = substr($content, $content_pos); - } else { - $current['content'] = ''; - $length = 0; - while (substr($content, $content_pos, 2) != "\0\0") { - $temp = self::decode_ber($content, $length + $start, $content_pos); - if ($temp === false) { - return false; - } - $content_pos += $temp['length']; - // all subtags should be octet strings - if ($temp['type'] != self::TYPE_OCTET_STRING) { - return false; - } - $current['content'] .= $temp['content']; - $length += $temp['length']; - } - if (substr($content, $content_pos, 2) == "\0\0") { - $length += 2; // +2 for the EOC - } - } - break; - case self::TYPE_NULL: - // "The contents octets shall not contain any octets." -- paragraph 8.8.2 - if ($constructed || strlen($content)) { - return false; - } - break; - case self::TYPE_SEQUENCE: - case self::TYPE_SET: - if (!$constructed) { - return false; - } - $offset = 0; - $current['content'] = []; - $content_len = strlen($content); - while ($content_pos < $content_len) { - // if indefinite length construction was used and we have an end-of-content string next - // see paragraphs 8.1.1.3, 8.1.3.2, 8.1.3.6, 8.1.5, and (for an example) 8.6.4.2 - if (!isset($current['headerlength']) && substr($content, $content_pos, 2) == "\0\0") { - $length = $offset + 2; // +2 for the EOC - break 2; - } - $temp = self::decode_ber($content, $start + $offset, $content_pos); - if ($temp === false) { - return false; - } - $content_pos += $temp['length']; - $current['content'][] = $temp; - $offset += $temp['length']; - } - break; - case self::TYPE_OBJECT_IDENTIFIER: - if ($constructed) { - return false; - } - $current['content'] = self::decodeOID(substr($content, $content_pos)); - if ($current['content'] === false) { - return false; - } - break; - /* Each character string type shall be encoded as if it had been declared: - [UNIVERSAL x] IMPLICIT OCTET STRING - - -- X.690-0207.pdf#page=23 (paragraph 8.21.3) - - Per that, we're not going to do any validation. If there are any illegal characters in the string, - we don't really care */ - case self::TYPE_NUMERIC_STRING: - // 0,1,2,3,4,5,6,7,8,9, and space - case self::TYPE_PRINTABLE_STRING: - // Upper and lower case letters, digits, space, apostrophe, left/right parenthesis, plus sign, comma, - // hyphen, full stop, solidus, colon, equal sign, question mark - case self::TYPE_TELETEX_STRING: - // The Teletex character set in CCITT's T61, space, and delete - // see http://en.wikipedia.org/wiki/Teletex#Character_sets - case self::TYPE_VIDEOTEX_STRING: - // The Videotex character set in CCITT's T.100 and T.101, space, and delete - case self::TYPE_VISIBLE_STRING: - // Printing character sets of international ASCII, and space - case self::TYPE_IA5_STRING: - // International Alphabet 5 (International ASCII) - case self::TYPE_GRAPHIC_STRING: - // All registered G sets, and space - case self::TYPE_GENERAL_STRING: - // All registered C and G sets, space and delete - case self::TYPE_UTF8_STRING: - // ???? - case self::TYPE_BMP_STRING: - if ($constructed) { - return false; - } - $current['content'] = substr($content, $content_pos); - break; - case self::TYPE_UTC_TIME: - case self::TYPE_GENERALIZED_TIME: - if ($constructed) { - return false; - } - $current['content'] = self::decodeTime(substr($content, $content_pos), $tag); - break; - default: - return false; - } - - $start += $length; - - // ie. length is the length of the full TLV encoding - it's not just the length of the value - return $current + ['length' => $start - $current['start']]; - } - - /** - * ASN.1 Map - * - * Provides an ASN.1 semantic mapping ($mapping) from a parsed BER-encoding to a human readable format. - * - * "Special" mappings may be applied on a per tag-name basis via $special. - * - * @param array $decoded - * @param array $mapping - * @param array $special - * @return array|bool|Element|string|null - */ - public static function asn1map(array $decoded, $mapping, $special = []) - { - if (isset($mapping['explicit']) && is_array($decoded['content'])) { - $decoded = $decoded['content'][0]; - } - - switch (true) { - case $mapping['type'] == self::TYPE_ANY: - $intype = $decoded['type']; - // !isset(self::ANY_MAP[$intype]) produces a fatal error on PHP 5.6 - if (isset($decoded['constant']) || !array_key_exists($intype, self::ANY_MAP) || (ord(self::$encoded[$decoded['start']]) & 0x20)) { - return new Element(substr(self::$encoded, $decoded['start'], $decoded['length'])); - } - $inmap = self::ANY_MAP[$intype]; - if (is_string($inmap)) { - return [$inmap => self::asn1map($decoded, ['type' => $intype] + $mapping, $special)]; - } - break; - case $mapping['type'] == self::TYPE_CHOICE: - foreach ($mapping['children'] as $key => $option) { - switch (true) { - case isset($option['constant']) && $option['constant'] == $decoded['constant']: - case !isset($option['constant']) && $option['type'] == $decoded['type']: - $value = self::asn1map($decoded, $option, $special); - break; - case !isset($option['constant']) && $option['type'] == self::TYPE_CHOICE: - $v = self::asn1map($decoded, $option, $special); - if (isset($v)) { - $value = $v; - } - } - if (isset($value)) { - if (isset($special[$key])) { - $value = $special[$key]($value); - } - return [$key => $value]; - } - } - return null; - case isset($mapping['implicit']): - case isset($mapping['explicit']): - case $decoded['type'] == $mapping['type']: - break; - default: - // if $decoded['type'] and $mapping['type'] are both strings, but different types of strings, - // let it through - switch (true) { - case $decoded['type'] < 18: // self::TYPE_NUMERIC_STRING == 18 - case $decoded['type'] > 30: // self::TYPE_BMP_STRING == 30 - case $mapping['type'] < 18: - case $mapping['type'] > 30: - return null; - } - } - - if (isset($mapping['implicit'])) { - $decoded['type'] = $mapping['type']; - } - - switch ($decoded['type']) { - case self::TYPE_SEQUENCE: - $map = []; - - // ignore the min and max - if (isset($mapping['min']) && isset($mapping['max'])) { - $child = $mapping['children']; - foreach ($decoded['content'] as $content) { - if (($map[] = self::asn1map($content, $child, $special)) === null) { - return null; - } - } - - return $map; - } - - $n = count($decoded['content']); - $i = 0; - - foreach ($mapping['children'] as $key => $child) { - $maymatch = $i < $n; // Match only existing input. - if ($maymatch) { - $temp = $decoded['content'][$i]; - - if ($child['type'] != self::TYPE_CHOICE) { - // Get the mapping and input class & constant. - $childClass = $tempClass = self::CLASS_UNIVERSAL; - $constant = null; - if (isset($temp['constant'])) { - $tempClass = $temp['type']; - } - if (isset($child['class'])) { - $childClass = $child['class']; - $constant = $child['cast']; - } elseif (isset($child['constant'])) { - $childClass = self::CLASS_CONTEXT_SPECIFIC; - $constant = $child['constant']; - } - - if (isset($constant) && isset($temp['constant'])) { - // Can only match if constants and class match. - $maymatch = $constant == $temp['constant'] && $childClass == $tempClass; - } else { - // Can only match if no constant expected and type matches or is generic. - $maymatch = !isset($child['constant']) && array_search($child['type'], [$temp['type'], self::TYPE_ANY, self::TYPE_CHOICE]) !== false; - } - } - } - - if ($maymatch) { - // Attempt submapping. - $candidate = self::asn1map($temp, $child, $special); - $maymatch = $candidate !== null; - } - - if ($maymatch) { - // Got the match: use it. - if (isset($special[$key])) { - $candidate = $special[$key]($candidate); - } - $map[$key] = $candidate; - $i++; - } elseif (isset($child['default'])) { - $map[$key] = $child['default']; - } elseif (!isset($child['optional'])) { - return null; // Syntax error. - } - } - - // Fail mapping if all input items have not been consumed. - return $i < $n ? null : $map; - - // the main diff between sets and sequences is the encapsulation of the foreach in another for loop - case self::TYPE_SET: - $map = []; - - // ignore the min and max - if (isset($mapping['min']) && isset($mapping['max'])) { - $child = $mapping['children']; - foreach ($decoded['content'] as $content) { - if (($map[] = self::asn1map($content, $child, $special)) === null) { - return null; - } - } - - return $map; - } - - for ($i = 0; $i < count($decoded['content']); $i++) { - $temp = $decoded['content'][$i]; - $tempClass = self::CLASS_UNIVERSAL; - if (isset($temp['constant'])) { - $tempClass = $temp['type']; - } - - foreach ($mapping['children'] as $key => $child) { - if (isset($map[$key])) { - continue; - } - $maymatch = true; - if ($child['type'] != self::TYPE_CHOICE) { - $childClass = self::CLASS_UNIVERSAL; - $constant = null; - if (isset($child['class'])) { - $childClass = $child['class']; - $constant = $child['cast']; - } elseif (isset($child['constant'])) { - $childClass = self::CLASS_CONTEXT_SPECIFIC; - $constant = $child['constant']; - } - - if (isset($constant) && isset($temp['constant'])) { - // Can only match if constants and class match. - $maymatch = $constant == $temp['constant'] && $childClass == $tempClass; - } else { - // Can only match if no constant expected and type matches or is generic. - $maymatch = !isset($child['constant']) && array_search($child['type'], [$temp['type'], self::TYPE_ANY, self::TYPE_CHOICE]) !== false; - } - } - - if ($maymatch) { - // Attempt submapping. - $candidate = self::asn1map($temp, $child, $special); - $maymatch = $candidate !== null; - } - - if (!$maymatch) { - break; - } - - // Got the match: use it. - if (isset($special[$key])) { - $candidate = $special[$key]($candidate); - } - $map[$key] = $candidate; - break; - } - } - - foreach ($mapping['children'] as $key => $child) { - if (!isset($map[$key])) { - if (isset($child['default'])) { - $map[$key] = $child['default']; - } elseif (!isset($child['optional'])) { - return null; - } - } - } - return $map; - case self::TYPE_OBJECT_IDENTIFIER: - return isset(self::$oids[$decoded['content']]) ? self::$oids[$decoded['content']] : $decoded['content']; - case self::TYPE_UTC_TIME: - case self::TYPE_GENERALIZED_TIME: - // for explicitly tagged optional stuff - if (is_array($decoded['content'])) { - $decoded['content'] = $decoded['content'][0]['content']; - } - // for implicitly tagged optional stuff - // in theory, doing isset($mapping['implicit']) would work but malformed certs do exist - // in the wild that OpenSSL decodes without issue so we'll support them as well - if (!is_object($decoded['content'])) { - $decoded['content'] = self::decodeTime($decoded['content'], $decoded['type']); - } - return $decoded['content'] ? $decoded['content']->format(self::$format) : false; - case self::TYPE_BIT_STRING: - if (isset($mapping['mapping'])) { - $offset = ord($decoded['content'][0]); - $size = (strlen($decoded['content']) - 1) * 8 - $offset; - /* - From X.680-0207.pdf#page=46 (21.7): - - "When a "NamedBitList" is used in defining a bitstring type ASN.1 encoding rules are free to add (or remove) - arbitrarily any trailing 0 bits to (or from) values that are being encoded or decoded. Application designers should - therefore ensure that different semantics are not associated with such values which differ only in the number of trailing - 0 bits." - */ - $bits = count($mapping['mapping']) == $size ? [] : array_fill(0, count($mapping['mapping']) - $size, false); - for ($i = strlen($decoded['content']) - 1; $i > 0; $i--) { - $current = ord($decoded['content'][$i]); - for ($j = $offset; $j < 8; $j++) { - $bits[] = (bool) ($current & (1 << $j)); - } - $offset = 0; - } - $values = []; - $map = array_reverse($mapping['mapping']); - foreach ($map as $i => $value) { - if ($bits[$i]) { - $values[] = $value; - } - } - return $values; - } - // fall-through - case self::TYPE_OCTET_STRING: - return $decoded['content']; - case self::TYPE_NULL: - return ''; - case self::TYPE_BOOLEAN: - case self::TYPE_NUMERIC_STRING: - case self::TYPE_PRINTABLE_STRING: - case self::TYPE_TELETEX_STRING: - case self::TYPE_VIDEOTEX_STRING: - case self::TYPE_IA5_STRING: - case self::TYPE_GRAPHIC_STRING: - case self::TYPE_VISIBLE_STRING: - case self::TYPE_GENERAL_STRING: - case self::TYPE_UNIVERSAL_STRING: - case self::TYPE_UTF8_STRING: - case self::TYPE_BMP_STRING: - return $decoded['content']; - case self::TYPE_INTEGER: - case self::TYPE_ENUMERATED: - $temp = $decoded['content']; - if (isset($mapping['implicit'])) { - $temp = new BigInteger($decoded['content'], -256); - } - if (isset($mapping['mapping'])) { - $temp = (int) $temp->toString(); - return isset($mapping['mapping'][$temp]) ? - $mapping['mapping'][$temp] : - false; - } - return $temp; - } - } - - /** - * DER-decode the length - * - * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See - * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information. - * - * @param string $string - * @return int - */ - public static function decodeLength(&$string) - { - $length = ord(Strings::shift($string)); - if ($length & 0x80) { // definite length, long form - $length &= 0x7F; - $temp = Strings::shift($string, $length); - list(, $length) = unpack('N', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4)); - } - return $length; - } - - /** - * ASN.1 Encode - * - * DER-encodes an ASN.1 semantic mapping ($mapping). Some libraries would probably call this function - * an ASN.1 compiler. - * - * "Special" mappings can be applied via $special. - * - * @param Element|string|array $source - * @param array $mapping - * @param array $special - * @return string - */ - public static function encodeDER($source, $mapping, $special = []) - { - self::$location = []; - return self::encode_der($source, $mapping, null, $special); - } - - /** - * ASN.1 Encode (Helper function) - * - * @param Element|string|array|null $source - * @param array $mapping - * @param int $idx - * @param array $special - * @return string - */ - private static function encode_der($source, array $mapping, $idx = null, array $special = []) - { - if ($source instanceof Element) { - return $source->element; - } - - // do not encode (implicitly optional) fields with value set to default - if (isset($mapping['default']) && $source === $mapping['default']) { - return ''; - } - - if (isset($idx)) { - if (isset($special[$idx])) { - $source = $special[$idx]($source); - } - self::$location[] = $idx; - } - - $tag = $mapping['type']; - - switch ($tag) { - case self::TYPE_SET: // Children order is not important, thus process in sequence. - case self::TYPE_SEQUENCE: - $tag |= 0x20; // set the constructed bit - - // ignore the min and max - if (isset($mapping['min']) && isset($mapping['max'])) { - $value = []; - $child = $mapping['children']; - - foreach ($source as $content) { - $temp = self::encode_der($content, $child, null, $special); - if ($temp === false) { - return false; - } - $value[] = $temp; - } - /* "The encodings of the component values of a set-of value shall appear in ascending order, the encodings being compared - as octet strings with the shorter components being padded at their trailing end with 0-octets. - NOTE - The padding octets are for comparison purposes only and do not appear in the encodings." - - -- sec 11.6 of http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf */ - if ($mapping['type'] == self::TYPE_SET) { - sort($value); - } - $value = implode('', $value); - break; - } - - $value = ''; - foreach ($mapping['children'] as $key => $child) { - if (!array_key_exists($key, $source)) { - if (!isset($child['optional'])) { - return false; - } - continue; - } - - $temp = self::encode_der($source[$key], $child, $key, $special); - if ($temp === false) { - return false; - } - - // An empty child encoding means it has been optimized out. - // Else we should have at least one tag byte. - if ($temp === '') { - continue; - } - - // if isset($child['constant']) is true then isset($child['optional']) should be true as well - if (isset($child['constant'])) { - /* - From X.680-0207.pdf#page=58 (30.6): - - "The tagging construction specifies explicit tagging if any of the following holds: - ... - c) the "Tag Type" alternative is used and the value of "TagDefault" for the module is IMPLICIT TAGS or - AUTOMATIC TAGS, but the type defined by "Type" is an untagged choice type, an untagged open type, or - an untagged "DummyReference" (see ITU-T Rec. X.683 | ISO/IEC 8824-4, 8.3)." - */ - if (isset($child['explicit']) || $child['type'] == self::TYPE_CHOICE) { - $subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | 0x20 | $child['constant']); - $temp = $subtag . self::encodeLength(strlen($temp)) . $temp; - } else { - $subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | (ord($temp[0]) & 0x20) | $child['constant']); - $temp = $subtag . substr($temp, 1); - } - } - $value .= $temp; - } - break; - case self::TYPE_CHOICE: - $temp = false; - - foreach ($mapping['children'] as $key => $child) { - if (!isset($source[$key])) { - continue; - } - - $temp = self::encode_der($source[$key], $child, $key, $special); - if ($temp === false) { - return false; - } - - // An empty child encoding means it has been optimized out. - // Else we should have at least one tag byte. - if ($temp === '') { - continue; - } - - $tag = ord($temp[0]); - - // if isset($child['constant']) is true then isset($child['optional']) should be true as well - if (isset($child['constant'])) { - if (isset($child['explicit']) || $child['type'] == self::TYPE_CHOICE) { - $subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | 0x20 | $child['constant']); - $temp = $subtag . self::encodeLength(strlen($temp)) . $temp; - } else { - $subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | (ord($temp[0]) & 0x20) | $child['constant']); - $temp = $subtag . substr($temp, 1); - } - } - } - - if (isset($idx)) { - array_pop(self::$location); - } - - if ($temp && isset($mapping['cast'])) { - $temp[0] = chr(($mapping['class'] << 6) | ($tag & 0x20) | $mapping['cast']); - } - - return $temp; - case self::TYPE_INTEGER: - case self::TYPE_ENUMERATED: - if (!isset($mapping['mapping'])) { - if (is_numeric($source)) { - $source = new BigInteger($source); - } - $value = $source->toBytes(true); - } else { - $value = array_search($source, $mapping['mapping']); - if ($value === false) { - return false; - } - $value = new BigInteger($value); - $value = $value->toBytes(true); - } - if (!strlen($value)) { - $value = chr(0); - } - break; - case self::TYPE_UTC_TIME: - case self::TYPE_GENERALIZED_TIME: - $format = $mapping['type'] == self::TYPE_UTC_TIME ? 'y' : 'Y'; - $format .= 'mdHis'; - // if $source does _not_ include timezone information within it then assume that the timezone is GMT - $date = new \DateTime($source, new \DateTimeZone('GMT')); - // if $source _does_ include timezone information within it then convert the time to GMT - $date->setTimezone(new \DateTimeZone('GMT')); - $value = $date->format($format) . 'Z'; - break; - case self::TYPE_BIT_STRING: - if (isset($mapping['mapping'])) { - $bits = array_fill(0, count($mapping['mapping']), 0); - $size = 0; - for ($i = 0; $i < count($mapping['mapping']); $i++) { - if (in_array($mapping['mapping'][$i], $source)) { - $bits[$i] = 1; - $size = $i; - } - } - - if (isset($mapping['min']) && $mapping['min'] >= 1 && $size < $mapping['min']) { - $size = $mapping['min'] - 1; - } - - $offset = 8 - (($size + 1) & 7); - $offset = $offset !== 8 ? $offset : 0; - - $value = chr($offset); - - for ($i = $size + 1; $i < count($mapping['mapping']); $i++) { - unset($bits[$i]); - } - - $bits = implode('', array_pad($bits, $size + $offset + 1, 0)); - $bytes = explode(' ', rtrim(chunk_split($bits, 8, ' '))); - foreach ($bytes as $byte) { - $value .= chr(bindec($byte)); - } - - break; - } - // fall-through - case self::TYPE_OCTET_STRING: - /* The initial octet shall encode, as an unsigned binary integer with bit 1 as the least significant bit, - the number of unused bits in the final subsequent octet. The number shall be in the range zero to seven. - - -- http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=16 */ - $value = $source; - break; - case self::TYPE_OBJECT_IDENTIFIER: - $value = self::encodeOID($source); - break; - case self::TYPE_ANY: - $loc = self::$location; - if (isset($idx)) { - array_pop(self::$location); - } - - switch (true) { - case !isset($source): - return self::encode_der(null, ['type' => self::TYPE_NULL] + $mapping, null, $special); - case is_int($source): - case $source instanceof BigInteger: - return self::encode_der($source, ['type' => self::TYPE_INTEGER] + $mapping, null, $special); - case is_float($source): - return self::encode_der($source, ['type' => self::TYPE_REAL] + $mapping, null, $special); - case is_bool($source): - return self::encode_der($source, ['type' => self::TYPE_BOOLEAN] + $mapping, null, $special); - case is_array($source) && count($source) == 1: - $typename = implode('', array_keys($source)); - $outtype = array_search($typename, self::ANY_MAP, true); - if ($outtype !== false) { - return self::encode_der($source[$typename], ['type' => $outtype] + $mapping, null, $special); - } - } - - $filters = self::$filters; - foreach ($loc as $part) { - if (!isset($filters[$part])) { - $filters = false; - break; - } - $filters = $filters[$part]; - } - if ($filters === false) { - throw new \RuntimeException('No filters defined for ' . implode('/', $loc)); - } - return self::encode_der($source, $filters + $mapping, null, $special); - case self::TYPE_NULL: - $value = ''; - break; - case self::TYPE_NUMERIC_STRING: - case self::TYPE_TELETEX_STRING: - case self::TYPE_PRINTABLE_STRING: - case self::TYPE_UNIVERSAL_STRING: - case self::TYPE_UTF8_STRING: - case self::TYPE_BMP_STRING: - case self::TYPE_IA5_STRING: - case self::TYPE_VISIBLE_STRING: - case self::TYPE_VIDEOTEX_STRING: - case self::TYPE_GRAPHIC_STRING: - case self::TYPE_GENERAL_STRING: - $value = $source; - break; - case self::TYPE_BOOLEAN: - $value = $source ? "\xFF" : "\x00"; - break; - default: - throw new \RuntimeException('Mapping provides no type definition for ' . implode('/', self::$location)); - } - - if (isset($idx)) { - array_pop(self::$location); - } - - if (isset($mapping['cast'])) { - if (isset($mapping['explicit']) || $mapping['type'] == self::TYPE_CHOICE) { - $value = chr($tag) . self::encodeLength(strlen($value)) . $value; - $tag = ($mapping['class'] << 6) | 0x20 | $mapping['cast']; - } else { - $tag = ($mapping['class'] << 6) | (ord($temp[0]) & 0x20) | $mapping['cast']; - } - } - - return chr($tag) . self::encodeLength(strlen($value)) . $value; - } - - /** - * BER-decode the OID - * - * Called by _decode_ber() - * - * @param string $content - * @return string - */ - public static function decodeOID($content) - { - static $eighty; - if (!$eighty) { - $eighty = new BigInteger(80); - } - - $oid = []; - $pos = 0; - $len = strlen($content); - - if (ord($content[$len - 1]) & 0x80) { - return false; - } - - $n = new BigInteger(); - while ($pos < $len) { - $temp = ord($content[$pos++]); - $n = $n->bitwise_leftShift(7); - $n = $n->bitwise_or(new BigInteger($temp & 0x7F)); - if (~$temp & 0x80) { - $oid[] = $n; - $n = new BigInteger(); - } - } - $part1 = array_shift($oid); - $first = floor(ord($content[0]) / 40); - /* - "This packing of the first two object identifier components recognizes that only three values are allocated from the root - node, and at most 39 subsequent values from nodes reached by X = 0 and X = 1." - - -- https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=22 - */ - if ($first <= 2) { // ie. 0 <= ord($content[0]) < 120 (0x78) - array_unshift($oid, ord($content[0]) % 40); - array_unshift($oid, $first); - } else { - array_unshift($oid, $part1->subtract($eighty)); - array_unshift($oid, 2); - } - - return implode('.', $oid); - } - - /** - * DER-encode the OID - * - * Called by _encode_der() - * - * @param string $source - * @return string - */ - public static function encodeOID($source) - { - static $mask, $zero, $forty; - if (!$mask) { - $mask = new BigInteger(0x7F); - $zero = new BigInteger(); - $forty = new BigInteger(40); - } - - if (!preg_match('#(?:\d+\.)+#', $source)) { - $oid = isset(self::$reverseOIDs[$source]) ? self::$reverseOIDs[$source] : false; - } else { - $oid = $source; - } - if ($oid === false) { - throw new \RuntimeException('Invalid OID'); - } - - $parts = explode('.', $oid); - $part1 = array_shift($parts); - $part2 = array_shift($parts); - - $first = new BigInteger($part1); - $first = $first->multiply($forty); - $first = $first->add(new BigInteger($part2)); - - array_unshift($parts, $first->toString()); - - $value = ''; - foreach ($parts as $part) { - if (!$part) { - $temp = "\0"; - } else { - $temp = ''; - $part = new BigInteger($part); - while (!$part->equals($zero)) { - $submask = $part->bitwise_and($mask); - $submask->setPrecision(8); - $temp = (chr(0x80) | $submask->toBytes()) . $temp; - $part = $part->bitwise_rightShift(7); - } - $temp[strlen($temp) - 1] = $temp[strlen($temp) - 1] & chr(0x7F); - } - $value .= $temp; - } - - return $value; - } - - /** - * BER-decode the time - * - * Called by _decode_ber() and in the case of implicit tags asn1map(). - * - * @param string $content - * @param int $tag - * @return \DateTime|false - */ - private static function decodeTime($content, $tag) - { - /* UTCTime: - http://tools.ietf.org/html/rfc5280#section-4.1.2.5.1 - http://www.obj-sys.com/asn1tutorial/node15.html - - GeneralizedTime: - http://tools.ietf.org/html/rfc5280#section-4.1.2.5.2 - http://www.obj-sys.com/asn1tutorial/node14.html */ - - $format = 'YmdHis'; - - if ($tag == self::TYPE_UTC_TIME) { - // https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=28 says "the seconds - // element shall always be present" but none-the-less I've seen X509 certs where it isn't and if the - // browsers parse it phpseclib ought to too - if (preg_match('#^(\d{10})(Z|[+-]\d{4})$#', $content, $matches)) { - $content = $matches[1] . '00' . $matches[2]; - } - $prefix = substr($content, 0, 2) >= 50 ? '19' : '20'; - $content = $prefix . $content; - } elseif (strpos($content, '.') !== false) { - $format .= '.u'; - } - - if ($content[strlen($content) - 1] == 'Z') { - $content = substr($content, 0, -1) . '+0000'; - } - - if (strpos($content, '-') !== false || strpos($content, '+') !== false) { - $format .= 'O'; - } - - // error supression isn't necessary as of PHP 7.0: - // http://php.net/manual/en/migration70.other-changes.php - return @\DateTime::createFromFormat($format, $content); - } - - /** - * Set the time format - * - * Sets the time / date format for asn1map(). - * - * @param string $format - */ - public static function setTimeFormat($format) - { - self::$format = $format; - } - - /** - * Load OIDs - * - * Load the relevant OIDs for a particular ASN.1 semantic mapping. - * Previously loaded OIDs are retained. - * - * @param array $oids - */ - public static function loadOIDs(array $oids) - { - self::$reverseOIDs += $oids; - self::$oids = array_flip(self::$reverseOIDs); - } - - /** - * Set filters - * - * See \phpseclib3\File\X509, etc, for an example. - * Previously loaded filters are not retained. - * - * @param array $filters - */ - public static function setFilters(array $filters) - { - self::$filters = $filters; - } - - /** - * String type conversion - * - * This is a lazy conversion, dealing only with character size. - * No real conversion table is used. - * - * @param string $in - * @param int $from - * @param int $to - * @return string - */ - public static function convert($in, $from = self::TYPE_UTF8_STRING, $to = self::TYPE_UTF8_STRING) - { - // isset(self::STRING_TYPE_SIZE[$from] returns a fatal error on PHP 5.6 - if (!array_key_exists($from, self::STRING_TYPE_SIZE) || !array_key_exists($to, self::STRING_TYPE_SIZE)) { - return false; - } - $insize = self::STRING_TYPE_SIZE[$from]; - $outsize = self::STRING_TYPE_SIZE[$to]; - $inlength = strlen($in); - $out = ''; - - for ($i = 0; $i < $inlength;) { - if ($inlength - $i < $insize) { - return false; - } - - // Get an input character as a 32-bit value. - $c = ord($in[$i++]); - switch (true) { - case $insize == 4: - $c = ($c << 8) | ord($in[$i++]); - $c = ($c << 8) | ord($in[$i++]); - // fall-through - case $insize == 2: - $c = ($c << 8) | ord($in[$i++]); - // fall-through - case $insize == 1: - break; - case ($c & 0x80) == 0x00: - break; - case ($c & 0x40) == 0x00: - return false; - default: - $bit = 6; - do { - if ($bit > 25 || $i >= $inlength || (ord($in[$i]) & 0xC0) != 0x80) { - return false; - } - $c = ($c << 6) | (ord($in[$i++]) & 0x3F); - $bit += 5; - $mask = 1 << $bit; - } while ($c & $bit); - $c &= $mask - 1; - break; - } - - // Convert and append the character to output string. - $v = ''; - switch (true) { - case $outsize == 4: - $v .= chr($c & 0xFF); - $c >>= 8; - $v .= chr($c & 0xFF); - $c >>= 8; - // fall-through - case $outsize == 2: - $v .= chr($c & 0xFF); - $c >>= 8; - // fall-through - case $outsize == 1: - $v .= chr($c & 0xFF); - $c >>= 8; - if ($c) { - return false; - } - break; - case ($c & 0x80000000) != 0: - return false; - case $c >= 0x04000000: - $v .= chr(0x80 | ($c & 0x3F)); - $c = ($c >> 6) | 0x04000000; - // fall-through - case $c >= 0x00200000: - $v .= chr(0x80 | ($c & 0x3F)); - $c = ($c >> 6) | 0x00200000; - // fall-through - case $c >= 0x00010000: - $v .= chr(0x80 | ($c & 0x3F)); - $c = ($c >> 6) | 0x00010000; - // fall-through - case $c >= 0x00000800: - $v .= chr(0x80 | ($c & 0x3F)); - $c = ($c >> 6) | 0x00000800; - // fall-through - case $c >= 0x00000080: - $v .= chr(0x80 | ($c & 0x3F)); - $c = ($c >> 6) | 0x000000C0; - // fall-through - default: - $v .= chr($c); - break; - } - $out .= strrev($v); - } - return $out; - } - - /** - * Extract raw BER from Base64 encoding - * - * @param string $str - * @return string - */ - public static function extractBER($str) - { - /* X.509 certs are assumed to be base64 encoded but sometimes they'll have additional things in them - * above and beyond the ceritificate. - * ie. some may have the following preceding the -----BEGIN CERTIFICATE----- line: - * - * Bag Attributes - * localKeyID: 01 00 00 00 - * subject=/O=organization/OU=org unit/CN=common name - * issuer=/O=organization/CN=common name - */ - if (strlen($str) > ini_get('pcre.backtrack_limit')) { - $temp = $str; - } else { - $temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1); - $temp = preg_replace('#-+END.*[\r\n ]*.*#ms', '', $temp, 1); - } - // remove new lines - $temp = str_replace(["\r", "\n", ' '], '', $temp); - // remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff - $temp = preg_replace('#^-+[^-]+-+|-+[^-]+-+$#', '', $temp); - $temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? Strings::base64_decode($temp) : false; - return $temp != false ? $temp : $str; - } - - /** - * DER-encode the length - * - * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See - * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information. - * - * @param int $length - * @return string - */ - public static function encodeLength($length) - { - if ($length <= 0x7F) { - return chr($length); - } - - $temp = ltrim(pack('N', $length), chr(0)); - return pack('Ca*', 0x80 | strlen($temp), $temp); - } - - /** - * Returns the OID corresponding to a name - * - * What's returned in the associative array returned by loadX509() (or load*()) is either a name or an OID if - * no OID to name mapping is available. The problem with this is that what may be an unmapped OID in one version - * of phpseclib may not be unmapped in the next version, so apps that are looking at this OID may not be able - * to work from version to version. - * - * This method will return the OID if a name is passed to it and if no mapping is avialable it'll assume that - * what's being passed to it already is an OID and return that instead. A few examples. - * - * getOID('2.16.840.1.101.3.4.2.1') == '2.16.840.1.101.3.4.2.1' - * getOID('id-sha256') == '2.16.840.1.101.3.4.2.1' - * getOID('zzz') == 'zzz' - * - * @param string $name - * @return string - */ - public static function getOID($name) - { - return isset(self::$reverseOIDs[$name]) ? self::$reverseOIDs[$name] : $name; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Element.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Element.php deleted file mode 100644 index 6540b421..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Element.php +++ /dev/null @@ -1,43 +0,0 @@ - - * @copyright 2012 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1; - -/** - * ASN.1 Raw Element - * - * An ASN.1 ANY mapping will return an ASN1\Element object. Use of this object - * will also bypass the normal encoding rules in ASN1::encodeDER() - * - * @author Jim Wigginton - */ -class Element -{ - /** - * Raw element value - * - * @var string - */ - public $element; - - /** - * Constructor - * - * @param string $encoded - * @return \phpseclib3\File\ASN1\Element - */ - public function __construct($encoded) - { - $this->element = $encoded; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AccessDescription.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AccessDescription.php deleted file mode 100644 index 1cbc5a59..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AccessDescription.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * AccessDescription - * - * @author Jim Wigginton - */ -abstract class AccessDescription -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'accessMethod' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], - 'accessLocation' => GeneralName::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AdministrationDomainName.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AdministrationDomainName.php deleted file mode 100644 index 04183a13..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AdministrationDomainName.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * AdministrationDomainName - * - * @author Jim Wigginton - */ -abstract class AdministrationDomainName -{ - const MAP = [ - 'type' => ASN1::TYPE_CHOICE, - // if class isn't present it's assumed to be \phpseclib3\File\ASN1::CLASS_UNIVERSAL or - // (if constant is present) \phpseclib3\File\ASN1::CLASS_CONTEXT_SPECIFIC - 'class' => ASN1::CLASS_APPLICATION, - 'cast' => 2, - 'children' => [ - 'numeric' => ['type' => ASN1::TYPE_NUMERIC_STRING], - 'printable' => ['type' => ASN1::TYPE_PRINTABLE_STRING] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AlgorithmIdentifier.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AlgorithmIdentifier.php deleted file mode 100644 index 0da7eb10..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AlgorithmIdentifier.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * AlgorithmIdentifier - * - * @author Jim Wigginton - */ -abstract class AlgorithmIdentifier -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'algorithm' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], - 'parameters' => [ - 'type' => ASN1::TYPE_ANY, - 'optional' => true - ] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AnotherName.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AnotherName.php deleted file mode 100644 index d96c170b..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AnotherName.php +++ /dev/null @@ -1,37 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * AnotherName - * - * @author Jim Wigginton - */ -abstract class AnotherName -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'type-id' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], - 'value' => [ - 'type' => ASN1::TYPE_ANY, - 'constant' => 0, - 'optional' => true, - 'explicit' => true - ] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Attribute.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Attribute.php deleted file mode 100644 index 38a6aeef..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Attribute.php +++ /dev/null @@ -1,37 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * Attribute - * - * @author Jim Wigginton - */ -abstract class Attribute -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'type' => AttributeType::MAP, - 'value' => [ - 'type' => ASN1::TYPE_SET, - 'min' => 1, - 'max' => -1, - 'children' => AttributeValue::MAP - ] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AttributeType.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AttributeType.php deleted file mode 100644 index 5cbc2bcc..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AttributeType.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * AttributeType - * - * @author Jim Wigginton - */ -abstract class AttributeType -{ - const MAP = ['type' => ASN1::TYPE_OBJECT_IDENTIFIER]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AttributeTypeAndValue.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AttributeTypeAndValue.php deleted file mode 100644 index fe414f16..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AttributeTypeAndValue.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * AttributeTypeAndValue - * - * @author Jim Wigginton - */ -abstract class AttributeTypeAndValue -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'type' => AttributeType::MAP, - 'value' => AttributeValue::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AttributeValue.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AttributeValue.php deleted file mode 100644 index 3b3b6d2e..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AttributeValue.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * AttributeValue - * - * @author Jim Wigginton - */ -abstract class AttributeValue -{ - const MAP = ['type' => ASN1::TYPE_ANY]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Attributes.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Attributes.php deleted file mode 100644 index cd53ecfa..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Attributes.php +++ /dev/null @@ -1,31 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * Attributes - * - * @author Jim Wigginton - */ -abstract class Attributes -{ - const MAP = [ - 'type' => ASN1::TYPE_SET, - 'min' => 1, - 'max' => -1, - 'children' => Attribute::MAP - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AuthorityInfoAccessSyntax.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AuthorityInfoAccessSyntax.php deleted file mode 100644 index 3e80a55d..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AuthorityInfoAccessSyntax.php +++ /dev/null @@ -1,31 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * AuthorityInfoAccessSyntax - * - * @author Jim Wigginton - */ -abstract class AuthorityInfoAccessSyntax -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => -1, - 'children' => AccessDescription::MAP - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AuthorityKeyIdentifier.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AuthorityKeyIdentifier.php deleted file mode 100644 index e7ec5b28..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AuthorityKeyIdentifier.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * AuthorityKeyIdentifier - * - * @author Jim Wigginton - */ -abstract class AuthorityKeyIdentifier -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'keyIdentifier' => [ - 'constant' => 0, - 'optional' => true, - 'implicit' => true - ] + KeyIdentifier::MAP, - 'authorityCertIssuer' => [ - 'constant' => 1, - 'optional' => true, - 'implicit' => true - ] + GeneralNames::MAP, - 'authorityCertSerialNumber' => [ - 'constant' => 2, - 'optional' => true, - 'implicit' => true - ] + CertificateSerialNumber::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BaseDistance.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BaseDistance.php deleted file mode 100644 index e59668ab..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BaseDistance.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * BaseDistance - * - * @author Jim Wigginton - */ -abstract class BaseDistance -{ - const MAP = ['type' => ASN1::TYPE_INTEGER]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BasicConstraints.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BasicConstraints.php deleted file mode 100644 index 587ef1b0..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BasicConstraints.php +++ /dev/null @@ -1,39 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * BasicConstraints - * - * @author Jim Wigginton - */ -abstract class BasicConstraints -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'cA' => [ - 'type' => ASN1::TYPE_BOOLEAN, - 'optional' => true, - 'default' => false - ], - 'pathLenConstraint' => [ - 'type' => ASN1::TYPE_INTEGER, - 'optional' => true - ] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BuiltInDomainDefinedAttribute.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BuiltInDomainDefinedAttribute.php deleted file mode 100644 index e81bc78e..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BuiltInDomainDefinedAttribute.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * BuiltInDomainDefinedAttribute - * - * @author Jim Wigginton - */ -abstract class BuiltInDomainDefinedAttribute -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'type' => ['type' => ASN1::TYPE_PRINTABLE_STRING], - 'value' => ['type' => ASN1::TYPE_PRINTABLE_STRING] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BuiltInDomainDefinedAttributes.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BuiltInDomainDefinedAttributes.php deleted file mode 100644 index 471e88f9..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BuiltInDomainDefinedAttributes.php +++ /dev/null @@ -1,31 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * BuiltInDomainDefinedAttributes - * - * @author Jim Wigginton - */ -abstract class BuiltInDomainDefinedAttributes -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => 4, // ub-domain-defined-attributes - 'children' => BuiltInDomainDefinedAttribute::MAP - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BuiltInStandardAttributes.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BuiltInStandardAttributes.php deleted file mode 100644 index 752f400d..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BuiltInStandardAttributes.php +++ /dev/null @@ -1,67 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * BuiltInStandardAttributes - * - * @author Jim Wigginton - */ -abstract class BuiltInStandardAttributes -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'country-name' => ['optional' => true] + CountryName::MAP, - 'administration-domain-name' => ['optional' => true] + AdministrationDomainName::MAP, - 'network-address' => [ - 'constant' => 0, - 'optional' => true, - 'implicit' => true - ] + NetworkAddress::MAP, - 'terminal-identifier' => [ - 'constant' => 1, - 'optional' => true, - 'implicit' => true - ] + TerminalIdentifier::MAP, - 'private-domain-name' => [ - 'constant' => 2, - 'optional' => true, - 'explicit' => true - ] + PrivateDomainName::MAP, - 'organization-name' => [ - 'constant' => 3, - 'optional' => true, - 'implicit' => true - ] + OrganizationName::MAP, - 'numeric-user-identifier' => [ - 'constant' => 4, - 'optional' => true, - 'implicit' => true - ] + NumericUserIdentifier::MAP, - 'personal-name' => [ - 'constant' => 5, - 'optional' => true, - 'implicit' => true - ] + PersonalName::MAP, - 'organizational-unit-names' => [ - 'constant' => 6, - 'optional' => true, - 'implicit' => true - ] + OrganizationalUnitNames::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CPSuri.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CPSuri.php deleted file mode 100644 index 56e58887..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CPSuri.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * CPSuri - * - * @author Jim Wigginton - */ -abstract class CPSuri -{ - const MAP = ['type' => ASN1::TYPE_IA5_STRING]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CRLDistributionPoints.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CRLDistributionPoints.php deleted file mode 100644 index 79860b2f..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CRLDistributionPoints.php +++ /dev/null @@ -1,31 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * CRLDistributionPoints - * - * @author Jim Wigginton - */ -abstract class CRLDistributionPoints -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => -1, - 'children' => DistributionPoint::MAP - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CRLNumber.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CRLNumber.php deleted file mode 100644 index f6cb9567..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CRLNumber.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * CRLNumber - * - * @author Jim Wigginton - */ -abstract class CRLNumber -{ - const MAP = ['type' => ASN1::TYPE_INTEGER]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CRLReason.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CRLReason.php deleted file mode 100644 index d3736529..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CRLReason.php +++ /dev/null @@ -1,41 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * CRLReason - * - * @author Jim Wigginton - */ -abstract class CRLReason -{ - const MAP = [ - 'type' => ASN1::TYPE_ENUMERATED, - 'mapping' => [ - 'unspecified', - 'keyCompromise', - 'cACompromise', - 'affiliationChanged', - 'superseded', - 'cessationOfOperation', - 'certificateHold', - // Value 7 is not used. - 8 => 'removeFromCRL', - 'privilegeWithdrawn', - 'aACompromise' - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertPolicyId.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertPolicyId.php deleted file mode 100644 index d7e7776e..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertPolicyId.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * CertPolicyId - * - * @author Jim Wigginton - */ -abstract class CertPolicyId -{ - const MAP = ['type' => ASN1::TYPE_OBJECT_IDENTIFIER]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Certificate.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Certificate.php deleted file mode 100644 index 01943a0d..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Certificate.php +++ /dev/null @@ -1,33 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * Certificate - * - * @author Jim Wigginton - */ -abstract class Certificate -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'tbsCertificate' => TBSCertificate::MAP, - 'signatureAlgorithm' => AlgorithmIdentifier::MAP, - 'signature' => ['type' => ASN1::TYPE_BIT_STRING] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificateIssuer.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificateIssuer.php deleted file mode 100644 index ccd68dde..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificateIssuer.php +++ /dev/null @@ -1,24 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -/** - * CertificateIssuer - * - * @author Jim Wigginton - */ -abstract class CertificateIssuer -{ - const MAP = GeneralNames::MAP; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificateList.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificateList.php deleted file mode 100644 index d54ed6d9..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificateList.php +++ /dev/null @@ -1,33 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * CertificateList - * - * @author Jim Wigginton - */ -abstract class CertificateList -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'tbsCertList' => TBSCertList::MAP, - 'signatureAlgorithm' => AlgorithmIdentifier::MAP, - 'signature' => ['type' => ASN1::TYPE_BIT_STRING] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificatePolicies.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificatePolicies.php deleted file mode 100644 index ec0fa6b5..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificatePolicies.php +++ /dev/null @@ -1,31 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * CertificatePolicies - * - * @author Jim Wigginton - */ -abstract class CertificatePolicies -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => -1, - 'children' => PolicyInformation::MAP - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificateSerialNumber.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificateSerialNumber.php deleted file mode 100644 index 06ec944c..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificateSerialNumber.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * CertificateSerialNumber - * - * @author Jim Wigginton - */ -abstract class CertificateSerialNumber -{ - const MAP = ['type' => ASN1::TYPE_INTEGER]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificationRequest.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificationRequest.php deleted file mode 100644 index 2da70ed6..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificationRequest.php +++ /dev/null @@ -1,33 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * CertificationRequest - * - * @author Jim Wigginton - */ -abstract class CertificationRequest -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'certificationRequestInfo' => CertificationRequestInfo::MAP, - 'signatureAlgorithm' => AlgorithmIdentifier::MAP, - 'signature' => ['type' => ASN1::TYPE_BIT_STRING] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificationRequestInfo.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificationRequestInfo.php deleted file mode 100644 index ce6dc880..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificationRequestInfo.php +++ /dev/null @@ -1,41 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * CertificationRequestInfo - * - * @author Jim Wigginton - */ -abstract class CertificationRequestInfo -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'version' => [ - 'type' => ASN1::TYPE_INTEGER, - 'mapping' => ['v1'] - ], - 'subject' => Name::MAP, - 'subjectPKInfo' => SubjectPublicKeyInfo::MAP, - 'attributes' => [ - 'constant' => 0, - 'optional' => true, - 'implicit' => true - ] + Attributes::MAP, - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Characteristic_two.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Characteristic_two.php deleted file mode 100644 index 5bf59bb8..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Characteristic_two.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * Characteristic_two - * - * @author Jim Wigginton - */ -abstract class Characteristic_two -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'm' => ['type' => ASN1::TYPE_INTEGER], // field size 2**m - 'basis' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], - 'parameters' => [ - 'type' => ASN1::TYPE_ANY, - 'optional' => true - ] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CountryName.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CountryName.php deleted file mode 100644 index 737d844d..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CountryName.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * CountryName - * - * @author Jim Wigginton - */ -abstract class CountryName -{ - const MAP = [ - 'type' => ASN1::TYPE_CHOICE, - // if class isn't present it's assumed to be \phpseclib3\File\ASN1::CLASS_UNIVERSAL or - // (if constant is present) \phpseclib3\File\ASN1::CLASS_CONTEXT_SPECIFIC - 'class' => ASN1::CLASS_APPLICATION, - 'cast' => 1, - 'children' => [ - 'x121-dcc-code' => ['type' => ASN1::TYPE_NUMERIC_STRING], - 'iso-3166-alpha2-code' => ['type' => ASN1::TYPE_PRINTABLE_STRING] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Curve.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Curve.php deleted file mode 100644 index 621f1035..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Curve.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * Curve - * - * @author Jim Wigginton - */ -abstract class Curve -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'a' => FieldElement::MAP, - 'b' => FieldElement::MAP, - 'seed' => [ - 'type' => ASN1::TYPE_BIT_STRING, - 'optional' => true - ] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DHParameter.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DHParameter.php deleted file mode 100644 index 26863dbc..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DHParameter.php +++ /dev/null @@ -1,38 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * DHParameter - * - * @author Jim Wigginton - */ -abstract class DHParameter -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'prime' => ['type' => ASN1::TYPE_INTEGER], - 'base' => ['type' => ASN1::TYPE_INTEGER], - 'privateValueLength' => [ - 'type' => ASN1::TYPE_INTEGER, - 'optional' => true - ] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DSAParams.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DSAParams.php deleted file mode 100644 index 7af397bb..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DSAParams.php +++ /dev/null @@ -1,33 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * DSAParams - * - * @author Jim Wigginton - */ -abstract class DSAParams -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'p' => ['type' => ASN1::TYPE_INTEGER], - 'q' => ['type' => ASN1::TYPE_INTEGER], - 'g' => ['type' => ASN1::TYPE_INTEGER] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DSAPrivateKey.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DSAPrivateKey.php deleted file mode 100644 index d97cd023..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DSAPrivateKey.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * DSAPrivateKey - * - * @author Jim Wigginton - */ -abstract class DSAPrivateKey -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'version' => ['type' => ASN1::TYPE_INTEGER], - 'p' => ['type' => ASN1::TYPE_INTEGER], - 'q' => ['type' => ASN1::TYPE_INTEGER], - 'g' => ['type' => ASN1::TYPE_INTEGER], - 'y' => ['type' => ASN1::TYPE_INTEGER], - 'x' => ['type' => ASN1::TYPE_INTEGER] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DSAPublicKey.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DSAPublicKey.php deleted file mode 100644 index f795747a..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DSAPublicKey.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * DSAPublicKey - * - * @author Jim Wigginton - */ -abstract class DSAPublicKey -{ - const MAP = ['type' => ASN1::TYPE_INTEGER]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DigestInfo.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DigestInfo.php deleted file mode 100644 index b38ff3c4..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DigestInfo.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * DigestInfo - * - * from https://tools.ietf.org/html/rfc2898#appendix-A.3 - * - * @author Jim Wigginton - */ -abstract class DigestInfo -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'digestAlgorithm' => AlgorithmIdentifier::MAP, - 'digest' => ['type' => ASN1::TYPE_OCTET_STRING] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DirectoryString.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DirectoryString.php deleted file mode 100644 index 45218e3e..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DirectoryString.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * DirectoryString - * - * @author Jim Wigginton - */ -abstract class DirectoryString -{ - const MAP = [ - 'type' => ASN1::TYPE_CHOICE, - 'children' => [ - 'teletexString' => ['type' => ASN1::TYPE_TELETEX_STRING], - 'printableString' => ['type' => ASN1::TYPE_PRINTABLE_STRING], - 'universalString' => ['type' => ASN1::TYPE_UNIVERSAL_STRING], - 'utf8String' => ['type' => ASN1::TYPE_UTF8_STRING], - 'bmpString' => ['type' => ASN1::TYPE_BMP_STRING] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DisplayText.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DisplayText.php deleted file mode 100644 index a13e6a64..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DisplayText.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * DisplayText - * - * @author Jim Wigginton - */ -abstract class DisplayText -{ - const MAP = [ - 'type' => ASN1::TYPE_CHOICE, - 'children' => [ - 'ia5String' => ['type' => ASN1::TYPE_IA5_STRING], - 'visibleString' => ['type' => ASN1::TYPE_VISIBLE_STRING], - 'bmpString' => ['type' => ASN1::TYPE_BMP_STRING], - 'utf8String' => ['type' => ASN1::TYPE_UTF8_STRING] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DistributionPoint.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DistributionPoint.php deleted file mode 100644 index 4d9af6b5..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DistributionPoint.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * DistributionPoint - * - * @author Jim Wigginton - */ -abstract class DistributionPoint -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'distributionPoint' => [ - 'constant' => 0, - 'optional' => true, - 'explicit' => true - ] + DistributionPointName::MAP, - 'reasons' => [ - 'constant' => 1, - 'optional' => true, - 'implicit' => true - ] + ReasonFlags::MAP, - 'cRLIssuer' => [ - 'constant' => 2, - 'optional' => true, - 'implicit' => true - ] + GeneralNames::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DistributionPointName.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DistributionPointName.php deleted file mode 100644 index bc0cec8f..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DistributionPointName.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * DistributionPointName - * - * @author Jim Wigginton - */ -abstract class DistributionPointName -{ - const MAP = [ - 'type' => ASN1::TYPE_CHOICE, - 'children' => [ - 'fullName' => [ - 'constant' => 0, - 'optional' => true, - 'implicit' => true - ] + GeneralNames::MAP, - 'nameRelativeToCRLIssuer' => [ - 'constant' => 1, - 'optional' => true, - 'implicit' => true - ] + RelativeDistinguishedName::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DssSigValue.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DssSigValue.php deleted file mode 100644 index 2af74088..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DssSigValue.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * DssSigValue - * - * @author Jim Wigginton - */ -abstract class DssSigValue -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'r' => ['type' => ASN1::TYPE_INTEGER], - 's' => ['type' => ASN1::TYPE_INTEGER] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ECParameters.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ECParameters.php deleted file mode 100644 index f25f6faa..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ECParameters.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * ECParameters - * - * ECParameters ::= CHOICE { - * namedCurve OBJECT IDENTIFIER - * -- implicitCurve NULL - * -- specifiedCurve SpecifiedECDomain - * } - * -- implicitCurve and specifiedCurve MUST NOT be used in PKIX. - * -- Details for SpecifiedECDomain can be found in [X9.62]. - * -- Any future additions to this CHOICE should be coordinated - * -- with ANSI X9. - * - * @author Jim Wigginton - */ -abstract class ECParameters -{ - const MAP = [ - 'type' => ASN1::TYPE_CHOICE, - 'children' => [ - 'namedCurve' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], - 'implicitCurve' => ['type' => ASN1::TYPE_NULL], - 'specifiedCurve' => SpecifiedECDomain::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ECPoint.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ECPoint.php deleted file mode 100644 index fb11db83..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ECPoint.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * ECPoint - * - * @author Jim Wigginton - */ -abstract class ECPoint -{ - const MAP = ['type' => ASN1::TYPE_OCTET_STRING]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ECPrivateKey.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ECPrivateKey.php deleted file mode 100644 index 7454f387..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ECPrivateKey.php +++ /dev/null @@ -1,48 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * ECPrivateKey - * - * @author Jim Wigginton - */ -abstract class ECPrivateKey -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'version' => [ - 'type' => ASN1::TYPE_INTEGER, - 'mapping' => [1 => 'ecPrivkeyVer1'] - ], - 'privateKey' => ['type' => ASN1::TYPE_OCTET_STRING], - 'parameters' => [ - 'constant' => 0, - 'optional' => true, - 'explicit' => true - ] + ECParameters::MAP, - 'publicKey' => [ - 'type' => ASN1::TYPE_BIT_STRING, - 'constant' => 1, - 'optional' => true, - 'explicit' => true - ] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EDIPartyName.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EDIPartyName.php deleted file mode 100644 index ea7dcf19..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EDIPartyName.php +++ /dev/null @@ -1,42 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * EDIPartyName - * - * @author Jim Wigginton - */ -abstract class EDIPartyName -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'nameAssigner' => [ - 'constant' => 0, - 'optional' => true, - 'implicit' => true - ] + DirectoryString::MAP, - // partyName is technically required but \phpseclib3\File\ASN1 doesn't currently support non-optional constants and - // setting it to optional gets the job done in any event. - 'partyName' => [ - 'constant' => 1, - 'optional' => true, - 'implicit' => true - ] + DirectoryString::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EcdsaSigValue.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EcdsaSigValue.php deleted file mode 100644 index 8ab9ff1e..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EcdsaSigValue.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * EcdsaSigValue - * - * @author Jim Wigginton - */ -abstract class EcdsaSigValue -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'r' => ['type' => ASN1::TYPE_INTEGER], - 's' => ['type' => ASN1::TYPE_INTEGER] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EncryptedData.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EncryptedData.php deleted file mode 100644 index 8d8739e1..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EncryptedData.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * EncryptedData - * - * @author Jim Wigginton - */ -abstract class EncryptedData -{ - const MAP = ['type' => ASN1::TYPE_OCTET_STRING]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EncryptedPrivateKeyInfo.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EncryptedPrivateKeyInfo.php deleted file mode 100644 index 2c935676..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EncryptedPrivateKeyInfo.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * EncryptedPrivateKeyInfo - * - * @author Jim Wigginton - */ -abstract class EncryptedPrivateKeyInfo -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'encryptionAlgorithm' => AlgorithmIdentifier::MAP, - 'encryptedData' => EncryptedData::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ExtKeyUsageSyntax.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ExtKeyUsageSyntax.php deleted file mode 100644 index f9bc5def..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ExtKeyUsageSyntax.php +++ /dev/null @@ -1,31 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * ExtKeyUsageSyntax - * - * @author Jim Wigginton - */ -abstract class ExtKeyUsageSyntax -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => -1, - 'children' => KeyPurposeId::MAP - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Extension.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Extension.php deleted file mode 100644 index e32668fb..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Extension.php +++ /dev/null @@ -1,43 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * Extension - * - * A certificate using system MUST reject the certificate if it encounters - * a critical extension it does not recognize; however, a non-critical - * extension may be ignored if it is not recognized. - * - * http://tools.ietf.org/html/rfc5280#section-4.2 - * - * @author Jim Wigginton - */ -abstract class Extension -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'extnId' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], - 'critical' => [ - 'type' => ASN1::TYPE_BOOLEAN, - 'optional' => true, - 'default' => false - ], - 'extnValue' => ['type' => ASN1::TYPE_OCTET_STRING] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ExtensionAttribute.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ExtensionAttribute.php deleted file mode 100644 index 565b36d3..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ExtensionAttribute.php +++ /dev/null @@ -1,42 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * ExtensionAttribute - * - * @author Jim Wigginton - */ -abstract class ExtensionAttribute -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'extension-attribute-type' => [ - 'type' => ASN1::TYPE_PRINTABLE_STRING, - 'constant' => 0, - 'optional' => true, - 'implicit' => true - ], - 'extension-attribute-value' => [ - 'type' => ASN1::TYPE_ANY, - 'constant' => 1, - 'optional' => true, - 'explicit' => true - ] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ExtensionAttributes.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ExtensionAttributes.php deleted file mode 100644 index a2e9bfae..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ExtensionAttributes.php +++ /dev/null @@ -1,31 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * ExtensionAttributes - * - * @author Jim Wigginton - */ -abstract class ExtensionAttributes -{ - const MAP = [ - 'type' => ASN1::TYPE_SET, - 'min' => 1, - 'max' => 256, // ub-extension-attributes - 'children' => ExtensionAttribute::MAP - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Extensions.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Extensions.php deleted file mode 100644 index 5015c976..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Extensions.php +++ /dev/null @@ -1,33 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * Extensions - * - * @author Jim Wigginton - */ -abstract class Extensions -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - // technically, it's MAX, but we'll assume anything < 0 is MAX - 'max' => -1, - // if 'children' isn't an array then 'min' and 'max' must be defined - 'children' => Extension::MAP - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/FieldElement.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/FieldElement.php deleted file mode 100644 index 31734078..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/FieldElement.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * FieldElement - * - * @author Jim Wigginton - */ -abstract class FieldElement -{ - const MAP = ['type' => ASN1::TYPE_OCTET_STRING]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/FieldID.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/FieldID.php deleted file mode 100644 index e32a9c03..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/FieldID.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * FieldID - * - * @author Jim Wigginton - */ -abstract class FieldID -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'fieldType' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], - 'parameters' => [ - 'type' => ASN1::TYPE_ANY, - 'optional' => true - ] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralName.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralName.php deleted file mode 100644 index 57d86da8..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralName.php +++ /dev/null @@ -1,80 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * GeneralName - * - * @author Jim Wigginton - */ -abstract class GeneralName -{ - const MAP = [ - 'type' => ASN1::TYPE_CHOICE, - 'children' => [ - 'otherName' => [ - 'constant' => 0, - 'optional' => true, - 'implicit' => true - ] + AnotherName::MAP, - 'rfc822Name' => [ - 'type' => ASN1::TYPE_IA5_STRING, - 'constant' => 1, - 'optional' => true, - 'implicit' => true - ], - 'dNSName' => [ - 'type' => ASN1::TYPE_IA5_STRING, - 'constant' => 2, - 'optional' => true, - 'implicit' => true - ], - 'x400Address' => [ - 'constant' => 3, - 'optional' => true, - 'implicit' => true - ] + ORAddress::MAP, - 'directoryName' => [ - 'constant' => 4, - 'optional' => true, - 'explicit' => true - ] + Name::MAP, - 'ediPartyName' => [ - 'constant' => 5, - 'optional' => true, - 'implicit' => true - ] + EDIPartyName::MAP, - 'uniformResourceIdentifier' => [ - 'type' => ASN1::TYPE_IA5_STRING, - 'constant' => 6, - 'optional' => true, - 'implicit' => true - ], - 'iPAddress' => [ - 'type' => ASN1::TYPE_OCTET_STRING, - 'constant' => 7, - 'optional' => true, - 'implicit' => true - ], - 'registeredID' => [ - 'type' => ASN1::TYPE_OBJECT_IDENTIFIER, - 'constant' => 8, - 'optional' => true, - 'implicit' => true - ] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralNames.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralNames.php deleted file mode 100644 index 5d931532..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralNames.php +++ /dev/null @@ -1,31 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * GeneralNames - * - * @author Jim Wigginton - */ -abstract class GeneralNames -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => -1, - 'children' => GeneralName::MAP - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralSubtree.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralSubtree.php deleted file mode 100644 index 5388db55..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralSubtree.php +++ /dev/null @@ -1,42 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * GeneralSubtree - * - * @author Jim Wigginton - */ -abstract class GeneralSubtree -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'base' => GeneralName::MAP, - 'minimum' => [ - 'constant' => 0, - 'optional' => true, - 'implicit' => true, - 'default' => '0' - ] + BaseDistance::MAP, - 'maximum' => [ - 'constant' => 1, - 'optional' => true, - 'implicit' => true, - ] + BaseDistance::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralSubtrees.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralSubtrees.php deleted file mode 100644 index 27548cfe..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralSubtrees.php +++ /dev/null @@ -1,31 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * GeneralSubtrees - * - * @author Jim Wigginton - */ -abstract class GeneralSubtrees -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => -1, - 'children' => GeneralSubtree::MAP - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/HashAlgorithm.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/HashAlgorithm.php deleted file mode 100644 index deb13cab..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/HashAlgorithm.php +++ /dev/null @@ -1,24 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -/** - * HashAglorithm - * - * @author Jim Wigginton - */ -abstract class HashAlgorithm -{ - const MAP = AlgorithmIdentifier::MAP; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/HoldInstructionCode.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/HoldInstructionCode.php deleted file mode 100644 index 88d6ff3e..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/HoldInstructionCode.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * HoldInstructionCode - * - * @author Jim Wigginton - */ -abstract class HoldInstructionCode -{ - const MAP = ['type' => ASN1::TYPE_OBJECT_IDENTIFIER]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/InvalidityDate.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/InvalidityDate.php deleted file mode 100644 index f34b5f72..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/InvalidityDate.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * InvalidityDate - * - * @author Jim Wigginton - */ -abstract class InvalidityDate -{ - const MAP = ['type' => ASN1::TYPE_GENERALIZED_TIME]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/IssuerAltName.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/IssuerAltName.php deleted file mode 100644 index e9d03244..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/IssuerAltName.php +++ /dev/null @@ -1,24 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -/** - * IssuerAltName - * - * @author Jim Wigginton - */ -abstract class IssuerAltName -{ - const MAP = GeneralNames::MAP; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/IssuingDistributionPoint.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/IssuingDistributionPoint.php deleted file mode 100644 index 415996f5..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/IssuingDistributionPoint.php +++ /dev/null @@ -1,68 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * IssuingDistributionPoint - * - * @author Jim Wigginton - */ -abstract class IssuingDistributionPoint -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'distributionPoint' => [ - 'constant' => 0, - 'optional' => true, - 'explicit' => true - ] + DistributionPointName::MAP, - 'onlyContainsUserCerts' => [ - 'type' => ASN1::TYPE_BOOLEAN, - 'constant' => 1, - 'optional' => true, - 'default' => false, - 'implicit' => true - ], - 'onlyContainsCACerts' => [ - 'type' => ASN1::TYPE_BOOLEAN, - 'constant' => 2, - 'optional' => true, - 'default' => false, - 'implicit' => true - ], - 'onlySomeReasons' => [ - 'constant' => 3, - 'optional' => true, - 'implicit' => true - ] + ReasonFlags::MAP, - 'indirectCRL' => [ - 'type' => ASN1::TYPE_BOOLEAN, - 'constant' => 4, - 'optional' => true, - 'default' => false, - 'implicit' => true - ], - 'onlyContainsAttributeCerts' => [ - 'type' => ASN1::TYPE_BOOLEAN, - 'constant' => 5, - 'optional' => true, - 'default' => false, - 'implicit' => true - ] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/KeyIdentifier.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/KeyIdentifier.php deleted file mode 100644 index 82a41519..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/KeyIdentifier.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * KeyIdentifier - * - * @author Jim Wigginton - */ -abstract class KeyIdentifier -{ - const MAP = ['type' => ASN1::TYPE_OCTET_STRING]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/KeyPurposeId.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/KeyPurposeId.php deleted file mode 100644 index b8509f19..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/KeyPurposeId.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * KeyPurposeId - * - * @author Jim Wigginton - */ -abstract class KeyPurposeId -{ - const MAP = ['type' => ASN1::TYPE_OBJECT_IDENTIFIER]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/KeyUsage.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/KeyUsage.php deleted file mode 100644 index 827ce033..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/KeyUsage.php +++ /dev/null @@ -1,39 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * KeyUsage - * - * @author Jim Wigginton - */ -abstract class KeyUsage -{ - const MAP = [ - 'type' => ASN1::TYPE_BIT_STRING, - 'mapping' => [ - 'digitalSignature', - 'nonRepudiation', - 'keyEncipherment', - 'dataEncipherment', - 'keyAgreement', - 'keyCertSign', - 'cRLSign', - 'encipherOnly', - 'decipherOnly' - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/MaskGenAlgorithm.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/MaskGenAlgorithm.php deleted file mode 100644 index ea3f998b..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/MaskGenAlgorithm.php +++ /dev/null @@ -1,24 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -/** - * MaskGenAglorithm - * - * @author Jim Wigginton - */ -abstract class MaskGenAlgorithm -{ - const MAP = AlgorithmIdentifier::MAP; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Name.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Name.php deleted file mode 100644 index a6a9009d..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Name.php +++ /dev/null @@ -1,31 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * Name - * - * @author Jim Wigginton - */ -abstract class Name -{ - const MAP = [ - 'type' => ASN1::TYPE_CHOICE, - 'children' => [ - 'rdnSequence' => RDNSequence::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NameConstraints.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NameConstraints.php deleted file mode 100644 index 80486f94..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NameConstraints.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * NameConstraints - * - * @author Jim Wigginton - */ -abstract class NameConstraints -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'permittedSubtrees' => [ - 'constant' => 0, - 'optional' => true, - 'implicit' => true - ] + GeneralSubtrees::MAP, - 'excludedSubtrees' => [ - 'constant' => 1, - 'optional' => true, - 'implicit' => true - ] + GeneralSubtrees::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NetworkAddress.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NetworkAddress.php deleted file mode 100644 index 6c68df00..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NetworkAddress.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * NetworkAddress - * - * @author Jim Wigginton - */ -abstract class NetworkAddress -{ - const MAP = ['type' => ASN1::TYPE_NUMERIC_STRING]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NoticeReference.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NoticeReference.php deleted file mode 100644 index 9eec123a..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NoticeReference.php +++ /dev/null @@ -1,37 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * NoticeReference - * - * @author Jim Wigginton - */ -abstract class NoticeReference -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'organization' => DisplayText::MAP, - 'noticeNumbers' => [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => 200, - 'children' => ['type' => ASN1::TYPE_INTEGER] - ] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NumericUserIdentifier.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NumericUserIdentifier.php deleted file mode 100644 index 635a89dc..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NumericUserIdentifier.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * NumericUserIdentifier - * - * @author Jim Wigginton - */ -abstract class NumericUserIdentifier -{ - const MAP = ['type' => ASN1::TYPE_NUMERIC_STRING]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ORAddress.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ORAddress.php deleted file mode 100644 index b853abe8..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ORAddress.php +++ /dev/null @@ -1,33 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * ORAddress - * - * @author Jim Wigginton - */ -abstract class ORAddress -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'built-in-standard-attributes' => BuiltInStandardAttributes::MAP, - 'built-in-domain-defined-attributes' => ['optional' => true] + BuiltInDomainDefinedAttributes::MAP, - 'extension-attributes' => ['optional' => true] + ExtensionAttributes::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OneAsymmetricKey.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OneAsymmetricKey.php deleted file mode 100644 index 59530248..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OneAsymmetricKey.php +++ /dev/null @@ -1,48 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * OneAsymmetricKey - * - * @author Jim Wigginton - */ -abstract class OneAsymmetricKey -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'version' => [ - 'type' => ASN1::TYPE_INTEGER, - 'mapping' => ['v1', 'v2'] - ], - 'privateKeyAlgorithm' => AlgorithmIdentifier::MAP, - 'privateKey' => PrivateKey::MAP, - 'attributes' => [ - 'constant' => 0, - 'optional' => true, - 'implicit' => true - ] + Attributes::MAP, - 'publicKey' => [ - 'constant' => 1, - 'optional' => true, - 'implicit' => true - ] + PublicKey::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OrganizationName.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OrganizationName.php deleted file mode 100644 index b5cc9491..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OrganizationName.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * OrganizationName - * - * @author Jim Wigginton - */ -abstract class OrganizationName -{ - const MAP = ['type' => ASN1::TYPE_PRINTABLE_STRING]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OrganizationalUnitNames.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OrganizationalUnitNames.php deleted file mode 100644 index b3e57809..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OrganizationalUnitNames.php +++ /dev/null @@ -1,31 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * OrganizationalUnitNames - * - * @author Jim Wigginton - */ -abstract class OrganizationalUnitNames -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => 4, // ub-organizational-units - 'children' => ['type' => ASN1::TYPE_PRINTABLE_STRING] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OtherPrimeInfo.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OtherPrimeInfo.php deleted file mode 100644 index 5d565605..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OtherPrimeInfo.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * OtherPrimeInfo - * - * @author Jim Wigginton - */ -abstract class OtherPrimeInfo -{ - // version must be multi if otherPrimeInfos present - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'prime' => ['type' => ASN1::TYPE_INTEGER], // ri - 'exponent' => ['type' => ASN1::TYPE_INTEGER], // di - 'coefficient' => ['type' => ASN1::TYPE_INTEGER] // ti - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OtherPrimeInfos.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OtherPrimeInfos.php deleted file mode 100644 index 9802a808..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OtherPrimeInfos.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * OtherPrimeInfos - * - * @author Jim Wigginton - */ -abstract class OtherPrimeInfos -{ - // version must be multi if otherPrimeInfos present - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => -1, - 'children' => OtherPrimeInfo::MAP - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBEParameter.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBEParameter.php deleted file mode 100644 index 8eb27cf6..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBEParameter.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * PBEParameter - * - * from https://tools.ietf.org/html/rfc2898#appendix-A.3 - * - * @author Jim Wigginton - */ -abstract class PBEParameter -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'salt' => ['type' => ASN1::TYPE_OCTET_STRING], - 'iterationCount' => ['type' => ASN1::TYPE_INTEGER] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBES2params.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBES2params.php deleted file mode 100644 index bd31699f..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBES2params.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * PBES2params - * - * from https://tools.ietf.org/html/rfc2898#appendix-A.3 - * - * @author Jim Wigginton - */ -abstract class PBES2params -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'keyDerivationFunc' => AlgorithmIdentifier::MAP, - 'encryptionScheme' => AlgorithmIdentifier::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBKDF2params.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBKDF2params.php deleted file mode 100644 index 2dafed9c..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBKDF2params.php +++ /dev/null @@ -1,41 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * PBKDF2params - * - * from https://tools.ietf.org/html/rfc2898#appendix-A.3 - * - * @author Jim Wigginton - */ -abstract class PBKDF2params -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - // technically, this is a CHOICE in RFC2898 but the other "choice" is, currently, more of a placeholder - // in the RFC - 'salt' => ['type' => ASN1::TYPE_OCTET_STRING], - 'iterationCount' => ['type' => ASN1::TYPE_INTEGER], - 'keyLength' => [ - 'type' => ASN1::TYPE_INTEGER, - 'optional' => true - ], - 'prf' => AlgorithmIdentifier::MAP + ['optional' => true] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBMAC1params.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBMAC1params.php deleted file mode 100644 index 91319f58..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBMAC1params.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * PBMAC1params - * - * from https://tools.ietf.org/html/rfc2898#appendix-A.3 - * - * @author Jim Wigginton - */ -abstract class PBMAC1params -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'keyDerivationFunc' => AlgorithmIdentifier::MAP, - 'messageAuthScheme' => AlgorithmIdentifier::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PKCS9String.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PKCS9String.php deleted file mode 100644 index 87d0862f..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PKCS9String.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * PKCS9String - * - * @author Jim Wigginton - */ -abstract class PKCS9String -{ - const MAP = [ - 'type' => ASN1::TYPE_CHOICE, - 'children' => [ - 'ia5String' => ['type' => ASN1::TYPE_IA5_STRING], - 'directoryString' => DirectoryString::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Pentanomial.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Pentanomial.php deleted file mode 100644 index b8c8c02f..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Pentanomial.php +++ /dev/null @@ -1,33 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * Pentanomial - * - * @author Jim Wigginton - */ -abstract class Pentanomial -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'k1' => ['type' => ASN1::TYPE_INTEGER], // k1 > 0 - 'k2' => ['type' => ASN1::TYPE_INTEGER], // k2 > k1 - 'k3' => ['type' => ASN1::TYPE_INTEGER], // k3 > h2 - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PersonalName.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PersonalName.php deleted file mode 100644 index 14e2860e..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PersonalName.php +++ /dev/null @@ -1,54 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * PersonalName - * - * @author Jim Wigginton - */ -abstract class PersonalName -{ - const MAP = [ - 'type' => ASN1::TYPE_SET, - 'children' => [ - 'surname' => [ - 'type' => ASN1::TYPE_PRINTABLE_STRING, - 'constant' => 0, - 'optional' => true, - 'implicit' => true - ], - 'given-name' => [ - 'type' => ASN1::TYPE_PRINTABLE_STRING, - 'constant' => 1, - 'optional' => true, - 'implicit' => true - ], - 'initials' => [ - 'type' => ASN1::TYPE_PRINTABLE_STRING, - 'constant' => 2, - 'optional' => true, - 'implicit' => true - ], - 'generation-qualifier' => [ - 'type' => ASN1::TYPE_PRINTABLE_STRING, - 'constant' => 3, - 'optional' => true, - 'implicit' => true - ] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyInformation.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyInformation.php deleted file mode 100644 index 1625d199..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyInformation.php +++ /dev/null @@ -1,38 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * PolicyInformation - * - * @author Jim Wigginton - */ -abstract class PolicyInformation -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'policyIdentifier' => CertPolicyId::MAP, - 'policyQualifiers' => [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 0, - 'max' => -1, - 'optional' => true, - 'children' => PolicyQualifierInfo::MAP - ] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyMappings.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyMappings.php deleted file mode 100644 index d30b8523..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyMappings.php +++ /dev/null @@ -1,37 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * PolicyMappings - * - * @author Jim Wigginton - */ -abstract class PolicyMappings -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => -1, - 'children' => [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'issuerDomainPolicy' => CertPolicyId::MAP, - 'subjectDomainPolicy' => CertPolicyId::MAP - ] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyQualifierId.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyQualifierId.php deleted file mode 100644 index 7b7cd6a7..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyQualifierId.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * PolicyQualifierId - * - * @author Jim Wigginton - */ -abstract class PolicyQualifierId -{ - const MAP = ['type' => ASN1::TYPE_OBJECT_IDENTIFIER]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyQualifierInfo.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyQualifierInfo.php deleted file mode 100644 index d227702e..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyQualifierInfo.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * PolicyQualifierInfo - * - * @author Jim Wigginton - */ -abstract class PolicyQualifierInfo -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'policyQualifierId' => PolicyQualifierId::MAP, - 'qualifier' => ['type' => ASN1::TYPE_ANY] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PostalAddress.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PostalAddress.php deleted file mode 100644 index 142b309e..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PostalAddress.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * PostalAddress - * - * @author Jim Wigginton - */ -abstract class PostalAddress -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'optional' => true, - 'min' => 1, - 'max' => -1, - 'children' => DirectoryString::MAP - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Prime_p.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Prime_p.php deleted file mode 100644 index 77430344..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Prime_p.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * Prime_p - * - * @author Jim Wigginton - */ -abstract class Prime_p -{ - const MAP = ['type' => ASN1::TYPE_INTEGER]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateDomainName.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateDomainName.php deleted file mode 100644 index 195dcaa5..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateDomainName.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * PrivateDomainName - * - * @author Jim Wigginton - */ -abstract class PrivateDomainName -{ - const MAP = [ - 'type' => ASN1::TYPE_CHOICE, - 'children' => [ - 'numeric' => ['type' => ASN1::TYPE_NUMERIC_STRING], - 'printable' => ['type' => ASN1::TYPE_PRINTABLE_STRING] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateKey.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateKey.php deleted file mode 100644 index 3c895941..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateKey.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * PrivateKey - * - * @author Jim Wigginton - */ -abstract class PrivateKey -{ - const MAP = ['type' => ASN1::TYPE_OCTET_STRING]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateKeyInfo.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateKeyInfo.php deleted file mode 100644 index b440b78d..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateKeyInfo.php +++ /dev/null @@ -1,41 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * PrivateKeyInfo - * - * @author Jim Wigginton - */ -abstract class PrivateKeyInfo -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'version' => [ - 'type' => ASN1::TYPE_INTEGER, - 'mapping' => ['v1'] - ], - 'privateKeyAlgorithm' => AlgorithmIdentifier::MAP, - 'privateKey' => PrivateKey::MAP, - 'attributes' => [ - 'constant' => 0, - 'optional' => true, - 'implicit' => true - ] + Attributes::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateKeyUsagePeriod.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateKeyUsagePeriod.php deleted file mode 100644 index 5b87036e..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateKeyUsagePeriod.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * PrivateKeyUsagePeriod - * - * @author Jim Wigginton - */ -abstract class PrivateKeyUsagePeriod -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'notBefore' => [ - 'constant' => 0, - 'optional' => true, - 'implicit' => true, - 'type' => ASN1::TYPE_GENERALIZED_TIME], - 'notAfter' => [ - 'constant' => 1, - 'optional' => true, - 'implicit' => true, - 'type' => ASN1::TYPE_GENERALIZED_TIME] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PublicKey.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PublicKey.php deleted file mode 100644 index 48409204..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PublicKey.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * PublicKey - * - * @author Jim Wigginton - */ -abstract class PublicKey -{ - const MAP = ['type' => ASN1::TYPE_BIT_STRING]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PublicKeyAndChallenge.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PublicKeyAndChallenge.php deleted file mode 100644 index 432581e4..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PublicKeyAndChallenge.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * PublicKeyAndChallenge - * - * @author Jim Wigginton - */ -abstract class PublicKeyAndChallenge -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'spki' => SubjectPublicKeyInfo::MAP, - 'challenge' => ['type' => ASN1::TYPE_IA5_STRING] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PublicKeyInfo.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PublicKeyInfo.php deleted file mode 100644 index b39a341f..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PublicKeyInfo.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * PublicKeyInfo - * - * this format is not formally defined anywhere but is none-the-less the form you - * get when you do "openssl rsa -in private.pem -outform PEM -pubout" - * - * @author Jim Wigginton - */ -abstract class PublicKeyInfo -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'publicKeyAlgorithm' => AlgorithmIdentifier::MAP, - 'publicKey' => ['type' => ASN1::TYPE_BIT_STRING] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RC2CBCParameter.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RC2CBCParameter.php deleted file mode 100644 index 48649abd..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RC2CBCParameter.php +++ /dev/null @@ -1,37 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * RC2CBCParameter - * - * from https://tools.ietf.org/html/rfc2898#appendix-A.3 - * - * @author Jim Wigginton - */ -abstract class RC2CBCParameter -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'rc2ParametersVersion' => [ - 'type' => ASN1::TYPE_INTEGER, - 'optional' => true - ], - 'iv' => ['type' => ASN1::TYPE_OCTET_STRING] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RDNSequence.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RDNSequence.php deleted file mode 100644 index 04b071c2..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RDNSequence.php +++ /dev/null @@ -1,38 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * RDNSequence - * - * In practice, RDNs containing multiple name-value pairs (called "multivalued RDNs") are rare, - * but they can be useful at times when either there is no unique attribute in the entry or you - * want to ensure that the entry's DN contains some useful identifying information. - * - * - https://www.opends.org/wiki/page/DefinitionRelativeDistinguishedName - * - * @author Jim Wigginton - */ -abstract class RDNSequence -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - // RDNSequence does not define a min or a max, which means it doesn't have one - 'min' => 0, - 'max' => -1, - 'children' => RelativeDistinguishedName::MAP - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RSAPrivateKey.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RSAPrivateKey.php deleted file mode 100644 index 8c19c658..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RSAPrivateKey.php +++ /dev/null @@ -1,44 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * RSAPrivateKey - * - * @author Jim Wigginton - */ -abstract class RSAPrivateKey -{ - // version must be multi if otherPrimeInfos present - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'version' => [ - 'type' => ASN1::TYPE_INTEGER, - 'mapping' => ['two-prime', 'multi'] - ], - 'modulus' => ['type' => ASN1::TYPE_INTEGER], // n - 'publicExponent' => ['type' => ASN1::TYPE_INTEGER], // e - 'privateExponent' => ['type' => ASN1::TYPE_INTEGER], // d - 'prime1' => ['type' => ASN1::TYPE_INTEGER], // p - 'prime2' => ['type' => ASN1::TYPE_INTEGER], // q - 'exponent1' => ['type' => ASN1::TYPE_INTEGER], // d mod (p-1) - 'exponent2' => ['type' => ASN1::TYPE_INTEGER], // d mod (q-1) - 'coefficient' => ['type' => ASN1::TYPE_INTEGER], // (inverse of q) mod p - 'otherPrimeInfos' => OtherPrimeInfos::MAP + ['optional' => true] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RSAPublicKey.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RSAPublicKey.php deleted file mode 100644 index b14c32c4..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RSAPublicKey.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * RSAPublicKey - * - * @author Jim Wigginton - */ -abstract class RSAPublicKey -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'modulus' => ['type' => ASN1::TYPE_INTEGER], - 'publicExponent' => ['type' => ASN1::TYPE_INTEGER] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RSASSA_PSS_params.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RSASSA_PSS_params.php deleted file mode 100644 index 1a784bf4..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RSASSA_PSS_params.php +++ /dev/null @@ -1,58 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * RSASSA_PSS_params - * - * @author Jim Wigginton - */ -abstract class RSASSA_PSS_params -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'hashAlgorithm' => [ - 'constant' => 0, - 'optional' => true, - 'explicit' => true, - //'default' => 'sha1Identifier' - ] + HashAlgorithm::MAP, - 'maskGenAlgorithm' => [ - 'constant' => 1, - 'optional' => true, - 'explicit' => true, - //'default' => 'mgf1SHA1Identifier' - ] + MaskGenAlgorithm::MAP, - 'saltLength' => [ - 'type' => ASN1::TYPE_INTEGER, - 'constant' => 2, - 'optional' => true, - 'explicit' => true, - 'default' => 20 - ], - 'trailerField' => [ - 'type' => ASN1::TYPE_INTEGER, - 'constant' => 3, - 'optional' => true, - 'explicit' => true, - 'default' => 1 - ] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ReasonFlags.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ReasonFlags.php deleted file mode 100644 index 2e62fcdb..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ReasonFlags.php +++ /dev/null @@ -1,39 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * ReasonFlags - * - * @author Jim Wigginton - */ -abstract class ReasonFlags -{ - const MAP = [ - 'type' => ASN1::TYPE_BIT_STRING, - 'mapping' => [ - 'unused', - 'keyCompromise', - 'cACompromise', - 'affiliationChanged', - 'superseded', - 'cessationOfOperation', - 'certificateHold', - 'privilegeWithdrawn', - 'aACompromise' - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RelativeDistinguishedName.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RelativeDistinguishedName.php deleted file mode 100644 index a0421f73..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RelativeDistinguishedName.php +++ /dev/null @@ -1,37 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * RelativeDistinguishedName - * - * In practice, RDNs containing multiple name-value pairs (called "multivalued RDNs") are rare, - * but they can be useful at times when either there is no unique attribute in the entry or you - * want to ensure that the entry's DN contains some useful identifying information. - * - * - https://www.opends.org/wiki/page/DefinitionRelativeDistinguishedName - * - * @author Jim Wigginton - */ -abstract class RelativeDistinguishedName -{ - const MAP = [ - 'type' => ASN1::TYPE_SET, - 'min' => 1, - 'max' => -1, - 'children' => AttributeTypeAndValue::MAP - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RevokedCertificate.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RevokedCertificate.php deleted file mode 100644 index ff759eb7..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RevokedCertificate.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * RevokedCertificate - * - * @author Jim Wigginton - */ -abstract class RevokedCertificate -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'userCertificate' => CertificateSerialNumber::MAP, - 'revocationDate' => Time::MAP, - 'crlEntryExtensions' => [ - 'optional' => true - ] + Extensions::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SignedPublicKeyAndChallenge.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SignedPublicKeyAndChallenge.php deleted file mode 100644 index 0f482a26..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SignedPublicKeyAndChallenge.php +++ /dev/null @@ -1,33 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * SignedPublicKeyAndChallenge - * - * @author Jim Wigginton - */ -abstract class SignedPublicKeyAndChallenge -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'publicKeyAndChallenge' => PublicKeyAndChallenge::MAP, - 'signatureAlgorithm' => AlgorithmIdentifier::MAP, - 'signature' => ['type' => ASN1::TYPE_BIT_STRING] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SpecifiedECDomain.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SpecifiedECDomain.php deleted file mode 100644 index 7408a563..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SpecifiedECDomain.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * SpecifiedECDomain - * - * @author Jim Wigginton - */ -abstract class SpecifiedECDomain -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'version' => [ - 'type' => ASN1::TYPE_INTEGER, - 'mapping' => [1 => 'ecdpVer1', 'ecdpVer2', 'ecdpVer3'] - ], - 'fieldID' => FieldID::MAP, - 'curve' => Curve::MAP, - 'base' => ECPoint::MAP, - 'order' => ['type' => ASN1::TYPE_INTEGER], - 'cofactor' => [ - 'type' => ASN1::TYPE_INTEGER, - 'optional' => true - ], - 'hash' => ['optional' => true] + HashAlgorithm::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectAltName.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectAltName.php deleted file mode 100644 index 39138a94..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectAltName.php +++ /dev/null @@ -1,24 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -/** - * SubjectAltName - * - * @author Jim Wigginton - */ -abstract class SubjectAltName -{ - const MAP = GeneralNames::MAP; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectDirectoryAttributes.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectDirectoryAttributes.php deleted file mode 100644 index f2e206f6..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectDirectoryAttributes.php +++ /dev/null @@ -1,31 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * SubjectDirectoryAttributes - * - * @author Jim Wigginton - */ -abstract class SubjectDirectoryAttributes -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => -1, - 'children' => Attribute::MAP - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectInfoAccessSyntax.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectInfoAccessSyntax.php deleted file mode 100644 index 1ff241f7..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectInfoAccessSyntax.php +++ /dev/null @@ -1,31 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * SubjectInfoAccessSyntax - * - * @author Jim Wigginton - */ -abstract class SubjectInfoAccessSyntax -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'min' => 1, - 'max' => -1, - 'children' => AccessDescription::MAP - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectPublicKeyInfo.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectPublicKeyInfo.php deleted file mode 100644 index 0d53d540..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectPublicKeyInfo.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * SubjectPublicKeyInfo - * - * @author Jim Wigginton - */ -abstract class SubjectPublicKeyInfo -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'algorithm' => AlgorithmIdentifier::MAP, - 'subjectPublicKey' => ['type' => ASN1::TYPE_BIT_STRING] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/TBSCertList.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/TBSCertList.php deleted file mode 100644 index 49b3cfc5..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/TBSCertList.php +++ /dev/null @@ -1,54 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * TBSCertList - * - * @author Jim Wigginton - */ -abstract class TBSCertList -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'version' => [ - 'type' => ASN1::TYPE_INTEGER, - 'mapping' => ['v1', 'v2', 'v3'], - 'optional' => true, - 'default' => 'v2' - ], - 'signature' => AlgorithmIdentifier::MAP, - 'issuer' => Name::MAP, - 'thisUpdate' => Time::MAP, - 'nextUpdate' => [ - 'optional' => true - ] + Time::MAP, - 'revokedCertificates' => [ - 'type' => ASN1::TYPE_SEQUENCE, - 'optional' => true, - 'min' => 0, - 'max' => -1, - 'children' => RevokedCertificate::MAP - ], - 'crlExtensions' => [ - 'constant' => 0, - 'optional' => true, - 'explicit' => true - ] + Extensions::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/TBSCertificate.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/TBSCertificate.php deleted file mode 100644 index 007360c9..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/TBSCertificate.php +++ /dev/null @@ -1,65 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * TBSCertificate - * - * @author Jim Wigginton - */ -abstract class TBSCertificate -{ - // assert($TBSCertificate['children']['signature'] == $Certificate['children']['signatureAlgorithm']) - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - // technically, default implies optional, but we'll define it as being optional, none-the-less, just to - // reenforce that fact - 'version' => [ - 'type' => ASN1::TYPE_INTEGER, - 'constant' => 0, - 'optional' => true, - 'explicit' => true, - 'mapping' => ['v1', 'v2', 'v3'], - 'default' => 'v1' - ], - 'serialNumber' => CertificateSerialNumber::MAP, - 'signature' => AlgorithmIdentifier::MAP, - 'issuer' => Name::MAP, - 'validity' => Validity::MAP, - 'subject' => Name::MAP, - 'subjectPublicKeyInfo' => SubjectPublicKeyInfo::MAP, - // implicit means that the T in the TLV structure is to be rewritten, regardless of the type - 'issuerUniqueID' => [ - 'constant' => 1, - 'optional' => true, - 'implicit' => true - ] + UniqueIdentifier::MAP, - 'subjectUniqueID' => [ - 'constant' => 2, - 'optional' => true, - 'implicit' => true - ] + UniqueIdentifier::MAP, - // doesn't use the EXPLICIT keyword but if - // it's not IMPLICIT, it's EXPLICIT - 'extensions' => [ - 'constant' => 3, - 'optional' => true, - 'explicit' => true - ] + Extensions::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/TerminalIdentifier.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/TerminalIdentifier.php deleted file mode 100644 index 7f6d9d2e..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/TerminalIdentifier.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * TerminalIdentifier - * - * @author Jim Wigginton - */ -abstract class TerminalIdentifier -{ - const MAP = ['type' => ASN1::TYPE_PRINTABLE_STRING]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Time.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Time.php deleted file mode 100644 index 744ee704..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Time.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * Time - * - * @author Jim Wigginton - */ -abstract class Time -{ - const MAP = [ - 'type' => ASN1::TYPE_CHOICE, - 'children' => [ - 'utcTime' => ['type' => ASN1::TYPE_UTC_TIME], - 'generalTime' => ['type' => ASN1::TYPE_GENERALIZED_TIME] - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Trinomial.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Trinomial.php deleted file mode 100644 index 33baa91e..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Trinomial.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * Trinomial - * - * @author Jim Wigginton - */ -abstract class Trinomial -{ - const MAP = ['type' => ASN1::TYPE_INTEGER]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/UniqueIdentifier.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/UniqueIdentifier.php deleted file mode 100644 index f4c954bb..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/UniqueIdentifier.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * UniqueIdentifier - * - * @author Jim Wigginton - */ -abstract class UniqueIdentifier -{ - const MAP = ['type' => ASN1::TYPE_BIT_STRING]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/UserNotice.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/UserNotice.php deleted file mode 100644 index 98d527b7..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/UserNotice.php +++ /dev/null @@ -1,38 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * UserNotice - * - * @author Jim Wigginton - */ -abstract class UserNotice -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'noticeRef' => [ - 'optional' => true, - 'implicit' => true - ] + NoticeReference::MAP, - 'explicitText' => [ - 'optional' => true, - 'implicit' => true - ] + DisplayText::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Validity.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Validity.php deleted file mode 100644 index 8ef64cf5..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Validity.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * Validity - * - * @author Jim Wigginton - */ -abstract class Validity -{ - const MAP = [ - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => [ - 'notBefore' => Time::MAP, - 'notAfter' => Time::MAP - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/netscape_ca_policy_url.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/netscape_ca_policy_url.php deleted file mode 100644 index 2ab15728..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/netscape_ca_policy_url.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * netscape_ca_policy_url - * - * @author Jim Wigginton - */ -abstract class netscape_ca_policy_url -{ - const MAP = ['type' => ASN1::TYPE_IA5_STRING]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/netscape_cert_type.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/netscape_cert_type.php deleted file mode 100644 index 49e8da4b..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/netscape_cert_type.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * netscape_cert_type - * - * mapping is from - * - * @author Jim Wigginton - */ -abstract class netscape_cert_type -{ - const MAP = [ - 'type' => ASN1::TYPE_BIT_STRING, - 'mapping' => [ - 'SSLClient', - 'SSLServer', - 'Email', - 'ObjectSigning', - 'Reserved', - 'SSLCA', - 'EmailCA', - 'ObjectSigningCA' - ] - ]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/netscape_comment.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/netscape_comment.php deleted file mode 100644 index d3ff4ddf..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/netscape_comment.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2016 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File\ASN1\Maps; - -use phpseclib3\File\ASN1; - -/** - * netscape_comment - * - * @author Jim Wigginton - */ -abstract class netscape_comment -{ - const MAP = ['type' => ASN1::TYPE_IA5_STRING]; -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/X509.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/File/X509.php deleted file mode 100644 index 7aa278f2..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/File/X509.php +++ /dev/null @@ -1,3990 +0,0 @@ - - * @copyright 2012 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\File; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\Common\PrivateKey; -use phpseclib3\Crypt\Common\PublicKey; -use phpseclib3\Crypt\DSA; -use phpseclib3\Crypt\EC; -use phpseclib3\Crypt\Hash; -use phpseclib3\Crypt\PublicKeyLoader; -use phpseclib3\Crypt\Random; -use phpseclib3\Crypt\RSA; -use phpseclib3\Crypt\RSA\Formats\Keys\PSS; -use phpseclib3\Exception\UnsupportedAlgorithmException; -use phpseclib3\File\ASN1\Element; -use phpseclib3\File\ASN1\Maps; -use phpseclib3\Math\BigInteger; - -/** - * Pure-PHP X.509 Parser - * - * @author Jim Wigginton - */ -class X509 -{ - /** - * Flag to only accept signatures signed by certificate authorities - * - * Not really used anymore but retained all the same to suppress E_NOTICEs from old installs - * - */ - const VALIDATE_SIGNATURE_BY_CA = 1; - - /** - * Return internal array representation - * - * @see \phpseclib3\File\X509::getDN() - */ - const DN_ARRAY = 0; - /** - * Return string - * - * @see \phpseclib3\File\X509::getDN() - */ - const DN_STRING = 1; - /** - * Return ASN.1 name string - * - * @see \phpseclib3\File\X509::getDN() - */ - const DN_ASN1 = 2; - /** - * Return OpenSSL compatible array - * - * @see \phpseclib3\File\X509::getDN() - */ - const DN_OPENSSL = 3; - /** - * Return canonical ASN.1 RDNs string - * - * @see \phpseclib3\File\X509::getDN() - */ - const DN_CANON = 4; - /** - * Return name hash for file indexing - * - * @see \phpseclib3\File\X509::getDN() - */ - const DN_HASH = 5; - - /** - * Save as PEM - * - * ie. a base64-encoded PEM with a header and a footer - * - * @see \phpseclib3\File\X509::saveX509() - * @see \phpseclib3\File\X509::saveCSR() - * @see \phpseclib3\File\X509::saveCRL() - */ - const FORMAT_PEM = 0; - /** - * Save as DER - * - * @see \phpseclib3\File\X509::saveX509() - * @see \phpseclib3\File\X509::saveCSR() - * @see \phpseclib3\File\X509::saveCRL() - */ - const FORMAT_DER = 1; - /** - * Save as a SPKAC - * - * @see \phpseclib3\File\X509::saveX509() - * @see \phpseclib3\File\X509::saveCSR() - * @see \phpseclib3\File\X509::saveCRL() - * - * Only works on CSRs. Not currently supported. - */ - const FORMAT_SPKAC = 2; - /** - * Auto-detect the format - * - * Used only by the load*() functions - * - * @see \phpseclib3\File\X509::saveX509() - * @see \phpseclib3\File\X509::saveCSR() - * @see \phpseclib3\File\X509::saveCRL() - */ - const FORMAT_AUTO_DETECT = 3; - - /** - * Attribute value disposition. - * If disposition is >= 0, this is the index of the target value. - */ - const ATTR_ALL = -1; // All attribute values (array). - const ATTR_APPEND = -2; // Add a value. - const ATTR_REPLACE = -3; // Clear first, then add a value. - - /** - * Distinguished Name - * - * @var array - */ - private $dn; - - /** - * Public key - * - * @var string|PublicKey - */ - private $publicKey; - - /** - * Private key - * - * @var string|PrivateKey - */ - private $privateKey; - - /** - * The certificate authorities - * - * @var array - */ - private $CAs; - - /** - * The currently loaded certificate - * - * @var array - */ - private $currentCert; - - /** - * The signature subject - * - * There's no guarantee \phpseclib3\File\X509 is going to re-encode an X.509 cert in the same way it was originally - * encoded so we take save the portion of the original cert that the signature would have made for. - * - * @var string - */ - private $signatureSubject; - - /** - * Certificate Start Date - * - * @var string - */ - private $startDate; - - /** - * Certificate End Date - * - * @var string|Element - */ - private $endDate; - - /** - * Serial Number - * - * @var string - */ - private $serialNumber; - - /** - * Key Identifier - * - * See {@link http://tools.ietf.org/html/rfc5280#section-4.2.1.1 RFC5280#section-4.2.1.1} and - * {@link http://tools.ietf.org/html/rfc5280#section-4.2.1.2 RFC5280#section-4.2.1.2}. - * - * @var string - */ - private $currentKeyIdentifier; - - /** - * CA Flag - * - * @var bool - */ - private $caFlag = false; - - /** - * SPKAC Challenge - * - * @var string - */ - private $challenge; - - /** - * @var array - */ - private $extensionValues = []; - - /** - * OIDs loaded - * - * @var bool - */ - private static $oidsLoaded = false; - - /** - * Recursion Limit - * - * @var int - */ - private static $recur_limit = 5; - - /** - * URL fetch flag - * - * @var bool - */ - private static $disable_url_fetch = false; - - /** - * @var array - */ - private static $extensions = []; - - /** - * @var ?array - */ - private $ipAddresses = null; - - /** - * @var ?array - */ - private $domains = null; - - /** - * Default Constructor. - * - * @return \phpseclib3\File\X509 - */ - public function __construct() - { - // Explicitly Tagged Module, 1988 Syntax - // http://tools.ietf.org/html/rfc5280#appendix-A.1 - - if (!self::$oidsLoaded) { - // OIDs from RFC5280 and those RFCs mentioned in RFC5280#section-4.1.1.2 - ASN1::loadOIDs([ - //'id-pkix' => '1.3.6.1.5.5.7', - //'id-pe' => '1.3.6.1.5.5.7.1', - //'id-qt' => '1.3.6.1.5.5.7.2', - //'id-kp' => '1.3.6.1.5.5.7.3', - //'id-ad' => '1.3.6.1.5.5.7.48', - 'id-qt-cps' => '1.3.6.1.5.5.7.2.1', - 'id-qt-unotice' => '1.3.6.1.5.5.7.2.2', - 'id-ad-ocsp' => '1.3.6.1.5.5.7.48.1', - 'id-ad-caIssuers' => '1.3.6.1.5.5.7.48.2', - 'id-ad-timeStamping' => '1.3.6.1.5.5.7.48.3', - 'id-ad-caRepository' => '1.3.6.1.5.5.7.48.5', - //'id-at' => '2.5.4', - 'id-at-name' => '2.5.4.41', - 'id-at-surname' => '2.5.4.4', - 'id-at-givenName' => '2.5.4.42', - 'id-at-initials' => '2.5.4.43', - 'id-at-generationQualifier' => '2.5.4.44', - 'id-at-commonName' => '2.5.4.3', - 'id-at-localityName' => '2.5.4.7', - 'id-at-stateOrProvinceName' => '2.5.4.8', - 'id-at-organizationName' => '2.5.4.10', - 'id-at-organizationalUnitName' => '2.5.4.11', - 'id-at-title' => '2.5.4.12', - 'id-at-description' => '2.5.4.13', - 'id-at-dnQualifier' => '2.5.4.46', - 'id-at-countryName' => '2.5.4.6', - 'id-at-serialNumber' => '2.5.4.5', - 'id-at-pseudonym' => '2.5.4.65', - 'id-at-postalCode' => '2.5.4.17', - 'id-at-streetAddress' => '2.5.4.9', - 'id-at-uniqueIdentifier' => '2.5.4.45', - 'id-at-role' => '2.5.4.72', - 'id-at-postalAddress' => '2.5.4.16', - - //'id-domainComponent' => '0.9.2342.19200300.100.1.25', - //'pkcs-9' => '1.2.840.113549.1.9', - 'pkcs-9-at-emailAddress' => '1.2.840.113549.1.9.1', - //'id-ce' => '2.5.29', - 'id-ce-authorityKeyIdentifier' => '2.5.29.35', - 'id-ce-subjectKeyIdentifier' => '2.5.29.14', - 'id-ce-keyUsage' => '2.5.29.15', - 'id-ce-privateKeyUsagePeriod' => '2.5.29.16', - 'id-ce-certificatePolicies' => '2.5.29.32', - //'anyPolicy' => '2.5.29.32.0', - - 'id-ce-policyMappings' => '2.5.29.33', - - 'id-ce-subjectAltName' => '2.5.29.17', - 'id-ce-issuerAltName' => '2.5.29.18', - 'id-ce-subjectDirectoryAttributes' => '2.5.29.9', - 'id-ce-basicConstraints' => '2.5.29.19', - 'id-ce-nameConstraints' => '2.5.29.30', - 'id-ce-policyConstraints' => '2.5.29.36', - 'id-ce-cRLDistributionPoints' => '2.5.29.31', - 'id-ce-extKeyUsage' => '2.5.29.37', - //'anyExtendedKeyUsage' => '2.5.29.37.0', - 'id-kp-serverAuth' => '1.3.6.1.5.5.7.3.1', - 'id-kp-clientAuth' => '1.3.6.1.5.5.7.3.2', - 'id-kp-codeSigning' => '1.3.6.1.5.5.7.3.3', - 'id-kp-emailProtection' => '1.3.6.1.5.5.7.3.4', - 'id-kp-timeStamping' => '1.3.6.1.5.5.7.3.8', - 'id-kp-OCSPSigning' => '1.3.6.1.5.5.7.3.9', - 'id-ce-inhibitAnyPolicy' => '2.5.29.54', - 'id-ce-freshestCRL' => '2.5.29.46', - 'id-pe-authorityInfoAccess' => '1.3.6.1.5.5.7.1.1', - 'id-pe-subjectInfoAccess' => '1.3.6.1.5.5.7.1.11', - 'id-ce-cRLNumber' => '2.5.29.20', - 'id-ce-issuingDistributionPoint' => '2.5.29.28', - 'id-ce-deltaCRLIndicator' => '2.5.29.27', - 'id-ce-cRLReasons' => '2.5.29.21', - 'id-ce-certificateIssuer' => '2.5.29.29', - 'id-ce-holdInstructionCode' => '2.5.29.23', - //'holdInstruction' => '1.2.840.10040.2', - 'id-holdinstruction-none' => '1.2.840.10040.2.1', - 'id-holdinstruction-callissuer' => '1.2.840.10040.2.2', - 'id-holdinstruction-reject' => '1.2.840.10040.2.3', - 'id-ce-invalidityDate' => '2.5.29.24', - - 'rsaEncryption' => '1.2.840.113549.1.1.1', - 'md2WithRSAEncryption' => '1.2.840.113549.1.1.2', - 'md5WithRSAEncryption' => '1.2.840.113549.1.1.4', - 'sha1WithRSAEncryption' => '1.2.840.113549.1.1.5', - 'sha224WithRSAEncryption' => '1.2.840.113549.1.1.14', - 'sha256WithRSAEncryption' => '1.2.840.113549.1.1.11', - 'sha384WithRSAEncryption' => '1.2.840.113549.1.1.12', - 'sha512WithRSAEncryption' => '1.2.840.113549.1.1.13', - - 'id-ecPublicKey' => '1.2.840.10045.2.1', - 'ecdsa-with-SHA1' => '1.2.840.10045.4.1', - // from https://tools.ietf.org/html/rfc5758#section-3.2 - 'ecdsa-with-SHA224' => '1.2.840.10045.4.3.1', - 'ecdsa-with-SHA256' => '1.2.840.10045.4.3.2', - 'ecdsa-with-SHA384' => '1.2.840.10045.4.3.3', - 'ecdsa-with-SHA512' => '1.2.840.10045.4.3.4', - - 'id-dsa' => '1.2.840.10040.4.1', - 'id-dsa-with-sha1' => '1.2.840.10040.4.3', - // from https://tools.ietf.org/html/rfc5758#section-3.1 - 'id-dsa-with-sha224' => '2.16.840.1.101.3.4.3.1', - 'id-dsa-with-sha256' => '2.16.840.1.101.3.4.3.2', - - // from https://tools.ietf.org/html/rfc8410: - 'id-Ed25519' => '1.3.101.112', - 'id-Ed448' => '1.3.101.113', - - 'id-RSASSA-PSS' => '1.2.840.113549.1.1.10', - - //'id-sha224' => '2.16.840.1.101.3.4.2.4', - //'id-sha256' => '2.16.840.1.101.3.4.2.1', - //'id-sha384' => '2.16.840.1.101.3.4.2.2', - //'id-sha512' => '2.16.840.1.101.3.4.2.3', - //'id-GostR3411-94-with-GostR3410-94' => '1.2.643.2.2.4', - //'id-GostR3411-94-with-GostR3410-2001' => '1.2.643.2.2.3', - //'id-GostR3410-2001' => '1.2.643.2.2.20', - //'id-GostR3410-94' => '1.2.643.2.2.19', - // Netscape Object Identifiers from "Netscape Certificate Extensions" - 'netscape' => '2.16.840.1.113730', - 'netscape-cert-extension' => '2.16.840.1.113730.1', - 'netscape-cert-type' => '2.16.840.1.113730.1.1', - 'netscape-comment' => '2.16.840.1.113730.1.13', - 'netscape-ca-policy-url' => '2.16.840.1.113730.1.8', - // the following are X.509 extensions not supported by phpseclib - 'id-pe-logotype' => '1.3.6.1.5.5.7.1.12', - 'entrustVersInfo' => '1.2.840.113533.7.65.0', - 'verisignPrivate' => '2.16.840.1.113733.1.6.9', - // for Certificate Signing Requests - // see http://tools.ietf.org/html/rfc2985 - 'pkcs-9-at-unstructuredName' => '1.2.840.113549.1.9.2', // PKCS #9 unstructured name - 'pkcs-9-at-challengePassword' => '1.2.840.113549.1.9.7', // Challenge password for certificate revocations - 'pkcs-9-at-extensionRequest' => '1.2.840.113549.1.9.14' // Certificate extension request - ]); - } - } - - /** - * Load X.509 certificate - * - * Returns an associative array describing the X.509 cert or a false if the cert failed to load - * - * @param array|string $cert - * @param int $mode - * @return mixed - */ - public function loadX509($cert, $mode = self::FORMAT_AUTO_DETECT) - { - if (is_array($cert) && isset($cert['tbsCertificate'])) { - unset($this->currentCert); - unset($this->currentKeyIdentifier); - $this->dn = $cert['tbsCertificate']['subject']; - if (!isset($this->dn)) { - return false; - } - $this->currentCert = $cert; - - $currentKeyIdentifier = $this->getExtension('id-ce-subjectKeyIdentifier'); - $this->currentKeyIdentifier = is_string($currentKeyIdentifier) ? $currentKeyIdentifier : null; - - unset($this->signatureSubject); - - return $cert; - } - - if ($mode != self::FORMAT_DER) { - $newcert = ASN1::extractBER($cert); - if ($mode == self::FORMAT_PEM && $cert == $newcert) { - return false; - } - $cert = $newcert; - } - - if ($cert === false) { - $this->currentCert = false; - return false; - } - - $decoded = ASN1::decodeBER($cert); - - if ($decoded) { - $x509 = ASN1::asn1map($decoded[0], Maps\Certificate::MAP); - } - if (!isset($x509) || $x509 === false) { - $this->currentCert = false; - return false; - } - - $this->signatureSubject = substr($cert, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']); - - if ($this->isSubArrayValid($x509, 'tbsCertificate/extensions')) { - $this->mapInExtensions($x509, 'tbsCertificate/extensions'); - } - $this->mapInDNs($x509, 'tbsCertificate/issuer/rdnSequence'); - $this->mapInDNs($x509, 'tbsCertificate/subject/rdnSequence'); - - $key = $x509['tbsCertificate']['subjectPublicKeyInfo']; - $key = ASN1::encodeDER($key, Maps\SubjectPublicKeyInfo::MAP); - $x509['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'] = - "-----BEGIN PUBLIC KEY-----\r\n" . - chunk_split(base64_encode($key), 64) . - "-----END PUBLIC KEY-----"; - - $this->currentCert = $x509; - $this->dn = $x509['tbsCertificate']['subject']; - - $currentKeyIdentifier = $this->getExtension('id-ce-subjectKeyIdentifier'); - $this->currentKeyIdentifier = is_string($currentKeyIdentifier) ? $currentKeyIdentifier : null; - - return $x509; - } - - /** - * Save X.509 certificate - * - * @param array $cert - * @param int $format optional - * @return string - */ - public function saveX509(array $cert, $format = self::FORMAT_PEM) - { - if (!is_array($cert) || !isset($cert['tbsCertificate'])) { - return false; - } - - switch (true) { - // "case !$a: case !$b: break; default: whatever();" is the same thing as "if ($a && $b) whatever()" - case !($algorithm = $this->subArray($cert, 'tbsCertificate/subjectPublicKeyInfo/algorithm/algorithm')): - case is_object($cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']): - break; - default: - $cert['tbsCertificate']['subjectPublicKeyInfo'] = new Element( - base64_decode(preg_replace('#-.+-|[\r\n]#', '', $cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'])) - ); - } - - if ($algorithm == 'rsaEncryption') { - $cert['signatureAlgorithm']['parameters'] = null; - $cert['tbsCertificate']['signature']['parameters'] = null; - } - - $filters = []; - $type_utf8_string = ['type' => ASN1::TYPE_UTF8_STRING]; - $filters['tbsCertificate']['signature']['parameters'] = $type_utf8_string; - $filters['tbsCertificate']['signature']['issuer']['rdnSequence']['value'] = $type_utf8_string; - $filters['tbsCertificate']['issuer']['rdnSequence']['value'] = $type_utf8_string; - $filters['tbsCertificate']['subject']['rdnSequence']['value'] = $type_utf8_string; - $filters['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['parameters'] = $type_utf8_string; - $filters['signatureAlgorithm']['parameters'] = $type_utf8_string; - $filters['authorityCertIssuer']['directoryName']['rdnSequence']['value'] = $type_utf8_string; - //$filters['policyQualifiers']['qualifier'] = $type_utf8_string; - $filters['distributionPoint']['fullName']['directoryName']['rdnSequence']['value'] = $type_utf8_string; - $filters['directoryName']['rdnSequence']['value'] = $type_utf8_string; - - foreach (self::$extensions as $extension) { - $filters['tbsCertificate']['extensions'][] = $extension; - } - - /* in the case of policyQualifiers/qualifier, the type has to be \phpseclib3\File\ASN1::TYPE_IA5_STRING. - \phpseclib3\File\ASN1::TYPE_PRINTABLE_STRING will cause OpenSSL's X.509 parser to spit out random - characters. - */ - $filters['policyQualifiers']['qualifier'] - = ['type' => ASN1::TYPE_IA5_STRING]; - - ASN1::setFilters($filters); - - $this->mapOutExtensions($cert, 'tbsCertificate/extensions'); - $this->mapOutDNs($cert, 'tbsCertificate/issuer/rdnSequence'); - $this->mapOutDNs($cert, 'tbsCertificate/subject/rdnSequence'); - - $cert = ASN1::encodeDER($cert, Maps\Certificate::MAP); - - switch ($format) { - case self::FORMAT_DER: - return $cert; - // case self::FORMAT_PEM: - default: - return "-----BEGIN CERTIFICATE-----\r\n" . chunk_split(Strings::base64_encode($cert), 64) . '-----END CERTIFICATE-----'; - } - } - - /** - * Map extension values from octet string to extension-specific internal - * format. - * - * @param array $root (by reference) - * @param string $path - */ - private function mapInExtensions(array &$root, $path) - { - $extensions = &$this->subArrayUnchecked($root, $path); - - if ($extensions) { - for ($i = 0; $i < count($extensions); $i++) { - $id = $extensions[$i]['extnId']; - $value = &$extensions[$i]['extnValue']; - /* [extnValue] contains the DER encoding of an ASN.1 value - corresponding to the extension type identified by extnID */ - $map = $this->getMapping($id); - if (!is_bool($map)) { - $decoder = $id == 'id-ce-nameConstraints' ? - [static::class, 'decodeNameConstraintIP'] : - [static::class, 'decodeIP']; - $decoded = ASN1::decodeBER($value); - if (!$decoded) { - continue; - } - $mapped = ASN1::asn1map($decoded[0], $map, ['iPAddress' => $decoder]); - $value = $mapped === false ? $decoded[0] : $mapped; - - if ($id == 'id-ce-certificatePolicies') { - for ($j = 0; $j < count($value); $j++) { - if (!isset($value[$j]['policyQualifiers'])) { - continue; - } - for ($k = 0; $k < count($value[$j]['policyQualifiers']); $k++) { - $subid = $value[$j]['policyQualifiers'][$k]['policyQualifierId']; - $map = $this->getMapping($subid); - $subvalue = &$value[$j]['policyQualifiers'][$k]['qualifier']; - if ($map !== false) { - $decoded = ASN1::decodeBER($subvalue); - if (!$decoded) { - continue; - } - $mapped = ASN1::asn1map($decoded[0], $map); - $subvalue = $mapped === false ? $decoded[0] : $mapped; - } - } - } - } - } - } - } - } - - /** - * Map extension values from extension-specific internal format to - * octet string. - * - * @param array $root (by reference) - * @param string $path - */ - private function mapOutExtensions(array &$root, $path) - { - $extensions = &$this->subArray($root, $path, !empty($this->extensionValues)); - - foreach ($this->extensionValues as $id => $data) { - extract($data); - $newext = [ - 'extnId' => $id, - 'extnValue' => $value, - 'critical' => $critical - ]; - if ($replace) { - foreach ($extensions as $key => $value) { - if ($value['extnId'] == $id) { - $extensions[$key] = $newext; - continue 2; - } - } - } - $extensions[] = $newext; - } - - if (is_array($extensions)) { - $size = count($extensions); - for ($i = 0; $i < $size; $i++) { - if ($extensions[$i] instanceof Element) { - continue; - } - - $id = $extensions[$i]['extnId']; - $value = &$extensions[$i]['extnValue']; - - switch ($id) { - case 'id-ce-certificatePolicies': - for ($j = 0; $j < count($value); $j++) { - if (!isset($value[$j]['policyQualifiers'])) { - continue; - } - for ($k = 0; $k < count($value[$j]['policyQualifiers']); $k++) { - $subid = $value[$j]['policyQualifiers'][$k]['policyQualifierId']; - $map = $this->getMapping($subid); - $subvalue = &$value[$j]['policyQualifiers'][$k]['qualifier']; - if ($map !== false) { - // by default \phpseclib3\File\ASN1 will try to render qualifier as a \phpseclib3\File\ASN1::TYPE_IA5_STRING since it's - // actual type is \phpseclib3\File\ASN1::TYPE_ANY - $subvalue = new Element(ASN1::encodeDER($subvalue, $map)); - } - } - } - break; - case 'id-ce-authorityKeyIdentifier': // use 00 as the serial number instead of an empty string - if (isset($value['authorityCertSerialNumber'])) { - if ($value['authorityCertSerialNumber']->toBytes() == '') { - $temp = chr((ASN1::CLASS_CONTEXT_SPECIFIC << 6) | 2) . "\1\0"; - $value['authorityCertSerialNumber'] = new Element($temp); - } - } - } - - /* [extnValue] contains the DER encoding of an ASN.1 value - corresponding to the extension type identified by extnID */ - $map = $this->getMapping($id); - if (is_bool($map)) { - if (!$map) { - //user_error($id . ' is not a currently supported extension'); - unset($extensions[$i]); - } - } else { - $value = ASN1::encodeDER($value, $map, ['iPAddress' => [static::class, 'encodeIP']]); - } - } - } - } - - /** - * Map attribute values from ANY type to attribute-specific internal - * format. - * - * @param array $root (by reference) - * @param string $path - */ - private function mapInAttributes(&$root, $path) - { - $attributes = &$this->subArray($root, $path); - - if (is_array($attributes)) { - for ($i = 0; $i < count($attributes); $i++) { - $id = $attributes[$i]['type']; - /* $value contains the DER encoding of an ASN.1 value - corresponding to the attribute type identified by type */ - $map = $this->getMapping($id); - if (is_array($attributes[$i]['value'])) { - $values = &$attributes[$i]['value']; - for ($j = 0; $j < count($values); $j++) { - $value = ASN1::encodeDER($values[$j], Maps\AttributeValue::MAP); - $decoded = ASN1::decodeBER($value); - if (!is_bool($map)) { - if (!$decoded) { - continue; - } - $mapped = ASN1::asn1map($decoded[0], $map); - if ($mapped !== false) { - $values[$j] = $mapped; - } - if ($id == 'pkcs-9-at-extensionRequest' && $this->isSubArrayValid($values, $j)) { - $this->mapInExtensions($values, $j); - } - } elseif ($map) { - $values[$j] = $value; - } - } - } - } - } - } - - /** - * Map attribute values from attribute-specific internal format to - * ANY type. - * - * @param array $root (by reference) - * @param string $path - */ - private function mapOutAttributes(&$root, $path) - { - $attributes = &$this->subArray($root, $path); - - if (is_array($attributes)) { - $size = count($attributes); - for ($i = 0; $i < $size; $i++) { - /* [value] contains the DER encoding of an ASN.1 value - corresponding to the attribute type identified by type */ - $id = $attributes[$i]['type']; - $map = $this->getMapping($id); - if ($map === false) { - //user_error($id . ' is not a currently supported attribute', E_USER_NOTICE); - unset($attributes[$i]); - } elseif (is_array($attributes[$i]['value'])) { - $values = &$attributes[$i]['value']; - for ($j = 0; $j < count($values); $j++) { - switch ($id) { - case 'pkcs-9-at-extensionRequest': - $this->mapOutExtensions($values, $j); - break; - } - - if (!is_bool($map)) { - $temp = ASN1::encodeDER($values[$j], $map); - $decoded = ASN1::decodeBER($temp); - if (!$decoded) { - continue; - } - $values[$j] = ASN1::asn1map($decoded[0], Maps\AttributeValue::MAP); - } - } - } - } - } - } - - /** - * Map DN values from ANY type to DN-specific internal - * format. - * - * @param array $root (by reference) - * @param string $path - */ - private function mapInDNs(array &$root, $path) - { - $dns = &$this->subArray($root, $path); - - if (is_array($dns)) { - for ($i = 0; $i < count($dns); $i++) { - for ($j = 0; $j < count($dns[$i]); $j++) { - $type = $dns[$i][$j]['type']; - $value = &$dns[$i][$j]['value']; - if (is_object($value) && $value instanceof Element) { - $map = $this->getMapping($type); - if (!is_bool($map)) { - $decoded = ASN1::decodeBER($value); - if (!$decoded) { - continue; - } - $value = ASN1::asn1map($decoded[0], $map); - } - } - } - } - } - } - - /** - * Map DN values from DN-specific internal format to - * ANY type. - * - * @param array $root (by reference) - * @param string $path - */ - private function mapOutDNs(array &$root, $path) - { - $dns = &$this->subArray($root, $path); - - if (is_array($dns)) { - $size = count($dns); - for ($i = 0; $i < $size; $i++) { - for ($j = 0; $j < count($dns[$i]); $j++) { - $type = $dns[$i][$j]['type']; - $value = &$dns[$i][$j]['value']; - if (is_object($value) && $value instanceof Element) { - continue; - } - - $map = $this->getMapping($type); - if (!is_bool($map)) { - $value = new Element(ASN1::encodeDER($value, $map)); - } - } - } - } - } - - /** - * Associate an extension ID to an extension mapping - * - * @param string $extnId - * @return mixed - */ - private function getMapping($extnId) - { - if (!is_string($extnId)) { // eg. if it's a \phpseclib3\File\ASN1\Element object - return true; - } - - if (isset(self::$extensions[$extnId])) { - return self::$extensions[$extnId]; - } - - switch ($extnId) { - case 'id-ce-keyUsage': - return Maps\KeyUsage::MAP; - case 'id-ce-basicConstraints': - return Maps\BasicConstraints::MAP; - case 'id-ce-subjectKeyIdentifier': - return Maps\KeyIdentifier::MAP; - case 'id-ce-cRLDistributionPoints': - return Maps\CRLDistributionPoints::MAP; - case 'id-ce-authorityKeyIdentifier': - return Maps\AuthorityKeyIdentifier::MAP; - case 'id-ce-certificatePolicies': - return Maps\CertificatePolicies::MAP; - case 'id-ce-extKeyUsage': - return Maps\ExtKeyUsageSyntax::MAP; - case 'id-pe-authorityInfoAccess': - return Maps\AuthorityInfoAccessSyntax::MAP; - case 'id-ce-subjectAltName': - return Maps\SubjectAltName::MAP; - case 'id-ce-subjectDirectoryAttributes': - return Maps\SubjectDirectoryAttributes::MAP; - case 'id-ce-privateKeyUsagePeriod': - return Maps\PrivateKeyUsagePeriod::MAP; - case 'id-ce-issuerAltName': - return Maps\IssuerAltName::MAP; - case 'id-ce-policyMappings': - return Maps\PolicyMappings::MAP; - case 'id-ce-nameConstraints': - return Maps\NameConstraints::MAP; - - case 'netscape-cert-type': - return Maps\netscape_cert_type::MAP; - case 'netscape-comment': - return Maps\netscape_comment::MAP; - case 'netscape-ca-policy-url': - return Maps\netscape_ca_policy_url::MAP; - - // since id-qt-cps isn't a constructed type it will have already been decoded as a string by the time it gets - // back around to asn1map() and we don't want it decoded again. - //case 'id-qt-cps': - // return Maps\CPSuri::MAP; - case 'id-qt-unotice': - return Maps\UserNotice::MAP; - - // the following OIDs are unsupported but we don't want them to give notices when calling saveX509(). - case 'id-pe-logotype': // http://www.ietf.org/rfc/rfc3709.txt - case 'entrustVersInfo': - // http://support.microsoft.com/kb/287547 - case '1.3.6.1.4.1.311.20.2': // szOID_ENROLL_CERTTYPE_EXTENSION - case '1.3.6.1.4.1.311.21.1': // szOID_CERTSRV_CA_VERSION - // "SET Secure Electronic Transaction Specification" - // http://www.maithean.com/docs/set_bk3.pdf - case '2.23.42.7.0': // id-set-hashedRootKey - // "Certificate Transparency" - // https://tools.ietf.org/html/rfc6962 - case '1.3.6.1.4.1.11129.2.4.2': - // "Qualified Certificate statements" - // https://tools.ietf.org/html/rfc3739#section-3.2.6 - case '1.3.6.1.5.5.7.1.3': - return true; - - // CSR attributes - case 'pkcs-9-at-unstructuredName': - return Maps\PKCS9String::MAP; - case 'pkcs-9-at-challengePassword': - return Maps\DirectoryString::MAP; - case 'pkcs-9-at-extensionRequest': - return Maps\Extensions::MAP; - - // CRL extensions. - case 'id-ce-cRLNumber': - return Maps\CRLNumber::MAP; - case 'id-ce-deltaCRLIndicator': - return Maps\CRLNumber::MAP; - case 'id-ce-issuingDistributionPoint': - return Maps\IssuingDistributionPoint::MAP; - case 'id-ce-freshestCRL': - return Maps\CRLDistributionPoints::MAP; - case 'id-ce-cRLReasons': - return Maps\CRLReason::MAP; - case 'id-ce-invalidityDate': - return Maps\InvalidityDate::MAP; - case 'id-ce-certificateIssuer': - return Maps\CertificateIssuer::MAP; - case 'id-ce-holdInstructionCode': - return Maps\HoldInstructionCode::MAP; - case 'id-at-postalAddress': - return Maps\PostalAddress::MAP; - } - - return false; - } - - /** - * Load an X.509 certificate as a certificate authority - * - * @param string $cert - * @return bool - */ - public function loadCA($cert) - { - $olddn = $this->dn; - $oldcert = $this->currentCert; - $oldsigsubj = $this->signatureSubject; - $oldkeyid = $this->currentKeyIdentifier; - - $cert = $this->loadX509($cert); - if (!$cert) { - $this->dn = $olddn; - $this->currentCert = $oldcert; - $this->signatureSubject = $oldsigsubj; - $this->currentKeyIdentifier = $oldkeyid; - - return false; - } - - /* From RFC5280 "PKIX Certificate and CRL Profile": - - If the keyUsage extension is present, then the subject public key - MUST NOT be used to verify signatures on certificates or CRLs unless - the corresponding keyCertSign or cRLSign bit is set. */ - //$keyUsage = $this->getExtension('id-ce-keyUsage'); - //if ($keyUsage && !in_array('keyCertSign', $keyUsage)) { - // return false; - //} - - /* From RFC5280 "PKIX Certificate and CRL Profile": - - The cA boolean indicates whether the certified public key may be used - to verify certificate signatures. If the cA boolean is not asserted, - then the keyCertSign bit in the key usage extension MUST NOT be - asserted. If the basic constraints extension is not present in a - version 3 certificate, or the extension is present but the cA boolean - is not asserted, then the certified public key MUST NOT be used to - verify certificate signatures. */ - //$basicConstraints = $this->getExtension('id-ce-basicConstraints'); - //if (!$basicConstraints || !$basicConstraints['cA']) { - // return false; - //} - - $this->CAs[] = $cert; - - $this->dn = $olddn; - $this->currentCert = $oldcert; - $this->signatureSubject = $oldsigsubj; - - return true; - } - - /** - * Validate an X.509 certificate against a URL - * - * From RFC2818 "HTTP over TLS": - * - * Matching is performed using the matching rules specified by - * [RFC2459]. If more than one identity of a given type is present in - * the certificate (e.g., more than one dNSName name, a match in any one - * of the set is considered acceptable.) Names may contain the wildcard - * character * which is considered to match any single domain name - * component or component fragment. E.g., *.a.com matches foo.a.com but - * not bar.foo.a.com. f*.com matches foo.com but not bar.com. - * - * @param string $url - * @return bool - */ - public function validateURL($url) - { - if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) { - return false; - } - - $components = parse_url($url); - if (!isset($components['host'])) { - return false; - } - - if ($names = $this->getExtension('id-ce-subjectAltName')) { - foreach ($names as $name) { - foreach ($name as $key => $value) { - $value = str_replace(['.', '*'], ['\.', '[^.]*'], $value); - switch ($key) { - case 'dNSName': - /* From RFC2818 "HTTP over TLS": - - If a subjectAltName extension of type dNSName is present, that MUST - be used as the identity. Otherwise, the (most specific) Common Name - field in the Subject field of the certificate MUST be used. Although - the use of the Common Name is existing practice, it is deprecated and - Certification Authorities are encouraged to use the dNSName instead. */ - if (preg_match('#^' . $value . '$#', $components['host'])) { - return true; - } - break; - case 'iPAddress': - /* From RFC2818 "HTTP over TLS": - - In some cases, the URI is specified as an IP address rather than a - hostname. In this case, the iPAddress subjectAltName must be present - in the certificate and must exactly match the IP in the URI. */ - if (preg_match('#(?:\d{1-3}\.){4}#', $components['host'] . '.') && preg_match('#^' . $value . '$#', $components['host'])) { - return true; - } - } - } - } - return false; - } - - if ($value = $this->getDNProp('id-at-commonName')) { - $value = str_replace(['.', '*'], ['\.', '[^.]*'], $value[0]); - return preg_match('#^' . $value . '$#', $components['host']) === 1; - } - - return false; - } - - /** - * Validate a date - * - * If $date isn't defined it is assumed to be the current date. - * - * @param \DateTimeInterface|string $date optional - * @return bool - */ - public function validateDate($date = null) - { - if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) { - return false; - } - - if (!isset($date)) { - $date = new \DateTimeImmutable('now', new \DateTimeZone(@date_default_timezone_get())); - } - - $notBefore = $this->currentCert['tbsCertificate']['validity']['notBefore']; - $notBefore = isset($notBefore['generalTime']) ? $notBefore['generalTime'] : $notBefore['utcTime']; - - $notAfter = $this->currentCert['tbsCertificate']['validity']['notAfter']; - $notAfter = isset($notAfter['generalTime']) ? $notAfter['generalTime'] : $notAfter['utcTime']; - - if (is_string($date)) { - $date = new \DateTimeImmutable($date, new \DateTimeZone(@date_default_timezone_get())); - } - - $notBefore = new \DateTimeImmutable($notBefore, new \DateTimeZone(@date_default_timezone_get())); - $notAfter = new \DateTimeImmutable($notAfter, new \DateTimeZone(@date_default_timezone_get())); - - return $date >= $notBefore && $date <= $notAfter; - } - - /** - * Fetches a URL - * - * @param string $url - * @return bool|string - */ - private static function fetchURL($url) - { - if (self::$disable_url_fetch) { - return false; - } - - $parts = parse_url($url); - $data = ''; - switch ($parts['scheme']) { - case 'http': - $fsock = @fsockopen($parts['host'], isset($parts['port']) ? $parts['port'] : 80); - if (!$fsock) { - return false; - } - $path = $parts['path']; - if (isset($parts['query'])) { - $path .= '?' . $parts['query']; - } - fputs($fsock, "GET $path HTTP/1.0\r\n"); - fputs($fsock, "Host: $parts[host]\r\n\r\n"); - $line = fgets($fsock, 1024); - if (strlen($line) < 3) { - return false; - } - preg_match('#HTTP/1.\d (\d{3})#', $line, $temp); - if ($temp[1] != '200') { - return false; - } - - // skip the rest of the headers in the http response - while (!feof($fsock) && fgets($fsock, 1024) != "\r\n") { - } - - while (!feof($fsock)) { - $temp = fread($fsock, 1024); - if ($temp === false) { - return false; - } - $data .= $temp; - } - - break; - //case 'ftp': - //case 'ldap': - //default: - } - - return $data; - } - - /** - * Validates an intermediate cert as identified via authority info access extension - * - * See https://tools.ietf.org/html/rfc4325 for more info - * - * @param bool $caonly - * @param int $count - * @return bool - */ - private function testForIntermediate($caonly, $count) - { - $opts = $this->getExtension('id-pe-authorityInfoAccess'); - if (!is_array($opts)) { - return false; - } - foreach ($opts as $opt) { - if ($opt['accessMethod'] == 'id-ad-caIssuers') { - // accessLocation is a GeneralName. GeneralName fields support stuff like email addresses, IP addresses, LDAP, - // etc, but we're only supporting URI's. URI's and LDAP are the only thing https://tools.ietf.org/html/rfc4325 - // discusses - if (isset($opt['accessLocation']['uniformResourceIdentifier'])) { - $url = $opt['accessLocation']['uniformResourceIdentifier']; - break; - } - } - } - - if (!isset($url)) { - return false; - } - - $cert = static::fetchURL($url); - if (!is_string($cert)) { - return false; - } - - $parent = new static(); - $parent->CAs = $this->CAs; - /* - "Conforming applications that support HTTP or FTP for accessing - certificates MUST be able to accept .cer files and SHOULD be able - to accept .p7c files." -- https://tools.ietf.org/html/rfc4325 - - A .p7c file is 'a "certs-only" CMS message as specified in RFC 2797" - - These are currently unsupported - */ - if (!is_array($parent->loadX509($cert))) { - return false; - } - - if (!$parent->validateSignatureCountable($caonly, ++$count)) { - return false; - } - - $this->CAs[] = $parent->currentCert; - //$this->loadCA($cert); - - return true; - } - - /** - * Validate a signature - * - * Works on X.509 certs, CSR's and CRL's. - * Returns true if the signature is verified, false if it is not correct or null on error - * - * By default returns false for self-signed certs. Call validateSignature(false) to make this support - * self-signed. - * - * The behavior of this function is inspired by {@link http://php.net/openssl-verify openssl_verify}. - * - * @param bool $caonly optional - * @return mixed - */ - public function validateSignature($caonly = true) - { - return $this->validateSignatureCountable($caonly, 0); - } - - /** - * Validate a signature - * - * Performs said validation whilst keeping track of how many times validation method is called - * - * @param bool $caonly - * @param int $count - * @return mixed - */ - private function validateSignatureCountable($caonly, $count) - { - if (!is_array($this->currentCert) || !isset($this->signatureSubject)) { - return null; - } - - if ($count == self::$recur_limit) { - return false; - } - - /* TODO: - "emailAddress attribute values are not case-sensitive (e.g., "subscriber@example.com" is the same as "SUBSCRIBER@EXAMPLE.COM")." - -- http://tools.ietf.org/html/rfc5280#section-4.1.2.6 - - implement pathLenConstraint in the id-ce-basicConstraints extension */ - - switch (true) { - case isset($this->currentCert['tbsCertificate']): - // self-signed cert - switch (true) { - case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertificate']['issuer'] === $this->currentCert['tbsCertificate']['subject']: - case defined('FILE_X509_IGNORE_TYPE') && $this->getIssuerDN(self::DN_STRING) === $this->getDN(self::DN_STRING): - $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier'); - $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier'); - switch (true) { - case !is_array($authorityKey): - case !$subjectKeyID: - case isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID: - $signingCert = $this->currentCert; // working cert - } - } - - if (!empty($this->CAs)) { - for ($i = 0; $i < count($this->CAs); $i++) { - // even if the cert is a self-signed one we still want to see if it's a CA; - // if not, we'll conditionally return an error - $ca = $this->CAs[$i]; - switch (true) { - case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertificate']['issuer'] === $ca['tbsCertificate']['subject']: - case defined('FILE_X509_IGNORE_TYPE') && $this->getDN(self::DN_STRING, $this->currentCert['tbsCertificate']['issuer']) === $this->getDN(self::DN_STRING, $ca['tbsCertificate']['subject']): - $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier'); - $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca); - switch (true) { - case !is_array($authorityKey): - case !$subjectKeyID: - case isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID: - if (is_array($authorityKey) && isset($authorityKey['authorityCertSerialNumber']) && !$authorityKey['authorityCertSerialNumber']->equals($ca['tbsCertificate']['serialNumber'])) { - break 2; // serial mismatch - check other ca - } - $signingCert = $ca; // working cert - break 3; - } - } - } - if (count($this->CAs) == $i && $caonly) { - return $this->testForIntermediate($caonly, $count) && $this->validateSignature($caonly); - } - } elseif (!isset($signingCert) || $caonly) { - return $this->testForIntermediate($caonly, $count) && $this->validateSignature($caonly); - } - return $this->validateSignatureHelper( - $signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'], - $signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'], - $this->currentCert['signatureAlgorithm']['algorithm'], - substr($this->currentCert['signature'], 1), - $this->signatureSubject - ); - case isset($this->currentCert['certificationRequestInfo']): - return $this->validateSignatureHelper( - $this->currentCert['certificationRequestInfo']['subjectPKInfo']['algorithm']['algorithm'], - $this->currentCert['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'], - $this->currentCert['signatureAlgorithm']['algorithm'], - substr($this->currentCert['signature'], 1), - $this->signatureSubject - ); - case isset($this->currentCert['publicKeyAndChallenge']): - return $this->validateSignatureHelper( - $this->currentCert['publicKeyAndChallenge']['spki']['algorithm']['algorithm'], - $this->currentCert['publicKeyAndChallenge']['spki']['subjectPublicKey'], - $this->currentCert['signatureAlgorithm']['algorithm'], - substr($this->currentCert['signature'], 1), - $this->signatureSubject - ); - case isset($this->currentCert['tbsCertList']): - if (!empty($this->CAs)) { - for ($i = 0; $i < count($this->CAs); $i++) { - $ca = $this->CAs[$i]; - switch (true) { - case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertList']['issuer'] === $ca['tbsCertificate']['subject']: - case defined('FILE_X509_IGNORE_TYPE') && $this->getDN(self::DN_STRING, $this->currentCert['tbsCertList']['issuer']) === $this->getDN(self::DN_STRING, $ca['tbsCertificate']['subject']): - $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier'); - $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca); - switch (true) { - case !is_array($authorityKey): - case !$subjectKeyID: - case isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID: - if (is_array($authorityKey) && isset($authorityKey['authorityCertSerialNumber']) && !$authorityKey['authorityCertSerialNumber']->equals($ca['tbsCertificate']['serialNumber'])) { - break 2; // serial mismatch - check other ca - } - $signingCert = $ca; // working cert - break 3; - } - } - } - } - if (!isset($signingCert)) { - return false; - } - return $this->validateSignatureHelper( - $signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'], - $signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'], - $this->currentCert['signatureAlgorithm']['algorithm'], - substr($this->currentCert['signature'], 1), - $this->signatureSubject - ); - default: - return false; - } - } - - /** - * Validates a signature - * - * Returns true if the signature is verified and false if it is not correct. - * If the algorithms are unsupposed an exception is thrown. - * - * @param string $publicKeyAlgorithm - * @param string $publicKey - * @param string $signatureAlgorithm - * @param string $signature - * @param string $signatureSubject - * @throws \phpseclib3\Exception\UnsupportedAlgorithmException if the algorithm is unsupported - * @return bool - */ - private function validateSignatureHelper($publicKeyAlgorithm, $publicKey, $signatureAlgorithm, $signature, $signatureSubject) - { - switch ($publicKeyAlgorithm) { - case 'id-RSASSA-PSS': - $key = RSA::loadFormat('PSS', $publicKey); - break; - case 'rsaEncryption': - $key = RSA::loadFormat('PKCS8', $publicKey); - switch ($signatureAlgorithm) { - case 'id-RSASSA-PSS': - break; - case 'md2WithRSAEncryption': - case 'md5WithRSAEncryption': - case 'sha1WithRSAEncryption': - case 'sha224WithRSAEncryption': - case 'sha256WithRSAEncryption': - case 'sha384WithRSAEncryption': - case 'sha512WithRSAEncryption': - $key = $key - ->withHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm)) - ->withPadding(RSA::SIGNATURE_PKCS1); - break; - default: - throw new UnsupportedAlgorithmException('Signature algorithm unsupported'); - } - break; - case 'id-Ed25519': - case 'id-Ed448': - $key = EC::loadFormat('PKCS8', $publicKey); - break; - case 'id-ecPublicKey': - $key = EC::loadFormat('PKCS8', $publicKey); - switch ($signatureAlgorithm) { - case 'ecdsa-with-SHA1': - case 'ecdsa-with-SHA224': - case 'ecdsa-with-SHA256': - case 'ecdsa-with-SHA384': - case 'ecdsa-with-SHA512': - $key = $key - ->withHash(preg_replace('#^ecdsa-with-#', '', strtolower($signatureAlgorithm))); - break; - default: - throw new UnsupportedAlgorithmException('Signature algorithm unsupported'); - } - break; - case 'id-dsa': - $key = DSA::loadFormat('PKCS8', $publicKey); - switch ($signatureAlgorithm) { - case 'id-dsa-with-sha1': - case 'id-dsa-with-sha224': - case 'id-dsa-with-sha256': - $key = $key - ->withHash(preg_replace('#^id-dsa-with-#', '', strtolower($signatureAlgorithm))); - break; - default: - throw new UnsupportedAlgorithmException('Signature algorithm unsupported'); - } - break; - default: - throw new UnsupportedAlgorithmException('Public key algorithm unsupported'); - } - - return $key->verify($signatureSubject, $signature); - } - - /** - * Sets the recursion limit - * - * When validating a signature it may be necessary to download intermediate certs from URI's. - * An intermediate cert that linked to itself would result in an infinite loop so to prevent - * that we set a recursion limit. A negative number means that there is no recursion limit. - * - * @param int $count - */ - public static function setRecurLimit($count) - { - self::$recur_limit = $count; - } - - /** - * Prevents URIs from being automatically retrieved - * - */ - public static function disableURLFetch() - { - self::$disable_url_fetch = true; - } - - /** - * Allows URIs to be automatically retrieved - * - */ - public static function enableURLFetch() - { - self::$disable_url_fetch = false; - } - - /** - * Decodes an IP address - * - * Takes in a base64 encoded "blob" and returns a human readable IP address - * - * @param string $ip - * @return string - */ - public static function decodeIP($ip) - { - return inet_ntop($ip); - } - - /** - * Decodes an IP address in a name constraints extension - * - * Takes in a base64 encoded "blob" and returns a human readable IP address / mask - * - * @param string $ip - * @return array - */ - public static function decodeNameConstraintIP($ip) - { - $size = strlen($ip) >> 1; - $mask = substr($ip, $size); - $ip = substr($ip, 0, $size); - return [inet_ntop($ip), inet_ntop($mask)]; - } - - /** - * Encodes an IP address - * - * Takes a human readable IP address into a base64-encoded "blob" - * - * @param string|array $ip - * @return string - */ - public static function encodeIP($ip) - { - return is_string($ip) ? - inet_pton($ip) : - inet_pton($ip[0]) . inet_pton($ip[1]); - } - - /** - * "Normalizes" a Distinguished Name property - * - * @param string $propName - * @return mixed - */ - private function translateDNProp($propName) - { - switch (strtolower($propName)) { - case 'id-at-countryname': - case 'countryname': - case 'c': - return 'id-at-countryName'; - case 'id-at-organizationname': - case 'organizationname': - case 'o': - return 'id-at-organizationName'; - case 'id-at-dnqualifier': - case 'dnqualifier': - return 'id-at-dnQualifier'; - case 'id-at-commonname': - case 'commonname': - case 'cn': - return 'id-at-commonName'; - case 'id-at-stateorprovincename': - case 'stateorprovincename': - case 'state': - case 'province': - case 'provincename': - case 'st': - return 'id-at-stateOrProvinceName'; - case 'id-at-localityname': - case 'localityname': - case 'l': - return 'id-at-localityName'; - case 'id-emailaddress': - case 'emailaddress': - return 'pkcs-9-at-emailAddress'; - case 'id-at-serialnumber': - case 'serialnumber': - return 'id-at-serialNumber'; - case 'id-at-postalcode': - case 'postalcode': - return 'id-at-postalCode'; - case 'id-at-streetaddress': - case 'streetaddress': - return 'id-at-streetAddress'; - case 'id-at-name': - case 'name': - return 'id-at-name'; - case 'id-at-givenname': - case 'givenname': - return 'id-at-givenName'; - case 'id-at-surname': - case 'surname': - case 'sn': - return 'id-at-surname'; - case 'id-at-initials': - case 'initials': - return 'id-at-initials'; - case 'id-at-generationqualifier': - case 'generationqualifier': - return 'id-at-generationQualifier'; - case 'id-at-organizationalunitname': - case 'organizationalunitname': - case 'ou': - return 'id-at-organizationalUnitName'; - case 'id-at-pseudonym': - case 'pseudonym': - return 'id-at-pseudonym'; - case 'id-at-title': - case 'title': - return 'id-at-title'; - case 'id-at-description': - case 'description': - return 'id-at-description'; - case 'id-at-role': - case 'role': - return 'id-at-role'; - case 'id-at-uniqueidentifier': - case 'uniqueidentifier': - case 'x500uniqueidentifier': - return 'id-at-uniqueIdentifier'; - case 'postaladdress': - case 'id-at-postaladdress': - return 'id-at-postalAddress'; - default: - return false; - } - } - - /** - * Set a Distinguished Name property - * - * @param string $propName - * @param mixed $propValue - * @param string $type optional - * @return bool - */ - public function setDNProp($propName, $propValue, $type = 'utf8String') - { - if (empty($this->dn)) { - $this->dn = ['rdnSequence' => []]; - } - - if (($propName = $this->translateDNProp($propName)) === false) { - return false; - } - - foreach ((array) $propValue as $v) { - if (!is_array($v) && isset($type)) { - $v = [$type => $v]; - } - $this->dn['rdnSequence'][] = [ - [ - 'type' => $propName, - 'value' => $v - ] - ]; - } - - return true; - } - - /** - * Remove Distinguished Name properties - * - * @param string $propName - */ - public function removeDNProp($propName) - { - if (empty($this->dn)) { - return; - } - - if (($propName = $this->translateDNProp($propName)) === false) { - return; - } - - $dn = &$this->dn['rdnSequence']; - $size = count($dn); - for ($i = 0; $i < $size; $i++) { - if ($dn[$i][0]['type'] == $propName) { - unset($dn[$i]); - } - } - - $dn = array_values($dn); - // fix for https://bugs.php.net/75433 affecting PHP 7.2 - if (!isset($dn[0])) { - $dn = array_splice($dn, 0, 0); - } - } - - /** - * Get Distinguished Name properties - * - * @param string $propName - * @param array $dn optional - * @param bool $withType optional - * @return mixed - */ - public function getDNProp($propName, array $dn = null, $withType = false) - { - if (!isset($dn)) { - $dn = $this->dn; - } - - if (empty($dn)) { - return false; - } - - if (($propName = $this->translateDNProp($propName)) === false) { - return false; - } - - $filters = []; - $filters['value'] = ['type' => ASN1::TYPE_UTF8_STRING]; - ASN1::setFilters($filters); - $this->mapOutDNs($dn, 'rdnSequence'); - $dn = $dn['rdnSequence']; - $result = []; - for ($i = 0; $i < count($dn); $i++) { - if ($dn[$i][0]['type'] == $propName) { - $v = $dn[$i][0]['value']; - if (!$withType) { - if (is_array($v)) { - foreach ($v as $type => $s) { - $type = array_search($type, ASN1::ANY_MAP); - if ($type !== false && array_key_exists($type, ASN1::STRING_TYPE_SIZE)) { - $s = ASN1::convert($s, $type); - if ($s !== false) { - $v = $s; - break; - } - } - } - if (is_array($v)) { - $v = array_pop($v); // Always strip data type. - } - } elseif (is_object($v) && $v instanceof Element) { - $map = $this->getMapping($propName); - if (!is_bool($map)) { - $decoded = ASN1::decodeBER($v); - if (!$decoded) { - return false; - } - $v = ASN1::asn1map($decoded[0], $map); - } - } - } - $result[] = $v; - } - } - - return $result; - } - - /** - * Set a Distinguished Name - * - * @param mixed $dn - * @param bool $merge optional - * @param string $type optional - * @return bool - */ - public function setDN($dn, $merge = false, $type = 'utf8String') - { - if (!$merge) { - $this->dn = null; - } - - if (is_array($dn)) { - if (isset($dn['rdnSequence'])) { - $this->dn = $dn; // No merge here. - return true; - } - - // handles stuff generated by openssl_x509_parse() - foreach ($dn as $prop => $value) { - if (!$this->setDNProp($prop, $value, $type)) { - return false; - } - } - return true; - } - - // handles everything else - $results = preg_split('#((?:^|, *|/)(?:C=|O=|OU=|CN=|L=|ST=|SN=|postalCode=|streetAddress=|emailAddress=|serialNumber=|organizationalUnitName=|title=|description=|role=|x500UniqueIdentifier=|postalAddress=))#', $dn, -1, PREG_SPLIT_DELIM_CAPTURE); - for ($i = 1; $i < count($results); $i += 2) { - $prop = trim($results[$i], ', =/'); - $value = $results[$i + 1]; - if (!$this->setDNProp($prop, $value, $type)) { - return false; - } - } - - return true; - } - - /** - * Get the Distinguished Name for a certificates subject - * - * @param mixed $format optional - * @param array $dn optional - * @return array|bool|string - */ - public function getDN($format = self::DN_ARRAY, array $dn = null) - { - if (!isset($dn)) { - $dn = isset($this->currentCert['tbsCertList']) ? $this->currentCert['tbsCertList']['issuer'] : $this->dn; - } - - switch ((int) $format) { - case self::DN_ARRAY: - return $dn; - case self::DN_ASN1: - $filters = []; - $filters['rdnSequence']['value'] = ['type' => ASN1::TYPE_UTF8_STRING]; - ASN1::setFilters($filters); - $this->mapOutDNs($dn, 'rdnSequence'); - return ASN1::encodeDER($dn, Maps\Name::MAP); - case self::DN_CANON: - // No SEQUENCE around RDNs and all string values normalized as - // trimmed lowercase UTF-8 with all spacing as one blank. - // constructed RDNs will not be canonicalized - $filters = []; - $filters['value'] = ['type' => ASN1::TYPE_UTF8_STRING]; - ASN1::setFilters($filters); - $result = ''; - $this->mapOutDNs($dn, 'rdnSequence'); - foreach ($dn['rdnSequence'] as $rdn) { - foreach ($rdn as $i => $attr) { - $attr = &$rdn[$i]; - if (is_array($attr['value'])) { - foreach ($attr['value'] as $type => $v) { - $type = array_search($type, ASN1::ANY_MAP, true); - if ($type !== false && array_key_exists($type, ASN1::STRING_TYPE_SIZE)) { - $v = ASN1::convert($v, $type); - if ($v !== false) { - $v = preg_replace('/\s+/', ' ', $v); - $attr['value'] = strtolower(trim($v)); - break; - } - } - } - } - } - $result .= ASN1::encodeDER($rdn, Maps\RelativeDistinguishedName::MAP); - } - return $result; - case self::DN_HASH: - $dn = $this->getDN(self::DN_CANON, $dn); - $hash = new Hash('sha1'); - $hash = $hash->hash($dn); - extract(unpack('Vhash', $hash)); - return strtolower(Strings::bin2hex(pack('N', $hash))); - } - - // Default is to return a string. - $start = true; - $output = ''; - - $result = []; - $filters = []; - $filters['rdnSequence']['value'] = ['type' => ASN1::TYPE_UTF8_STRING]; - ASN1::setFilters($filters); - $this->mapOutDNs($dn, 'rdnSequence'); - - foreach ($dn['rdnSequence'] as $field) { - $prop = $field[0]['type']; - $value = $field[0]['value']; - - $delim = ', '; - switch ($prop) { - case 'id-at-countryName': - $desc = 'C'; - break; - case 'id-at-stateOrProvinceName': - $desc = 'ST'; - break; - case 'id-at-organizationName': - $desc = 'O'; - break; - case 'id-at-organizationalUnitName': - $desc = 'OU'; - break; - case 'id-at-commonName': - $desc = 'CN'; - break; - case 'id-at-localityName': - $desc = 'L'; - break; - case 'id-at-surname': - $desc = 'SN'; - break; - case 'id-at-uniqueIdentifier': - $delim = '/'; - $desc = 'x500UniqueIdentifier'; - break; - case 'id-at-postalAddress': - $delim = '/'; - $desc = 'postalAddress'; - break; - default: - $delim = '/'; - $desc = preg_replace('#.+-([^-]+)$#', '$1', $prop); - } - - if (!$start) { - $output .= $delim; - } - if (is_array($value)) { - foreach ($value as $type => $v) { - $type = array_search($type, ASN1::ANY_MAP, true); - if ($type !== false && array_key_exists($type, ASN1::STRING_TYPE_SIZE)) { - $v = ASN1::convert($v, $type); - if ($v !== false) { - $value = $v; - break; - } - } - } - if (is_array($value)) { - $value = array_pop($value); // Always strip data type. - } - } elseif (is_object($value) && $value instanceof Element) { - $callback = function ($x) { - return '\x' . bin2hex($x[0]); - }; - $value = strtoupper(preg_replace_callback('#[^\x20-\x7E]#', $callback, $value->element)); - } - $output .= $desc . '=' . $value; - $result[$desc] = isset($result[$desc]) ? - array_merge((array) $result[$desc], [$value]) : - $value; - $start = false; - } - - return $format == self::DN_OPENSSL ? $result : $output; - } - - /** - * Get the Distinguished Name for a certificate/crl issuer - * - * @param int $format optional - * @return mixed - */ - public function getIssuerDN($format = self::DN_ARRAY) - { - switch (true) { - case !isset($this->currentCert) || !is_array($this->currentCert): - break; - case isset($this->currentCert['tbsCertificate']): - return $this->getDN($format, $this->currentCert['tbsCertificate']['issuer']); - case isset($this->currentCert['tbsCertList']): - return $this->getDN($format, $this->currentCert['tbsCertList']['issuer']); - } - - return false; - } - - /** - * Get the Distinguished Name for a certificate/csr subject - * Alias of getDN() - * - * @param int $format optional - * @return mixed - */ - public function getSubjectDN($format = self::DN_ARRAY) - { - switch (true) { - case !empty($this->dn): - return $this->getDN($format); - case !isset($this->currentCert) || !is_array($this->currentCert): - break; - case isset($this->currentCert['tbsCertificate']): - return $this->getDN($format, $this->currentCert['tbsCertificate']['subject']); - case isset($this->currentCert['certificationRequestInfo']): - return $this->getDN($format, $this->currentCert['certificationRequestInfo']['subject']); - } - - return false; - } - - /** - * Get an individual Distinguished Name property for a certificate/crl issuer - * - * @param string $propName - * @param bool $withType optional - * @return mixed - */ - public function getIssuerDNProp($propName, $withType = false) - { - switch (true) { - case !isset($this->currentCert) || !is_array($this->currentCert): - break; - case isset($this->currentCert['tbsCertificate']): - return $this->getDNProp($propName, $this->currentCert['tbsCertificate']['issuer'], $withType); - case isset($this->currentCert['tbsCertList']): - return $this->getDNProp($propName, $this->currentCert['tbsCertList']['issuer'], $withType); - } - - return false; - } - - /** - * Get an individual Distinguished Name property for a certificate/csr subject - * - * @param string $propName - * @param bool $withType optional - * @return mixed - */ - public function getSubjectDNProp($propName, $withType = false) - { - switch (true) { - case !empty($this->dn): - return $this->getDNProp($propName, null, $withType); - case !isset($this->currentCert) || !is_array($this->currentCert): - break; - case isset($this->currentCert['tbsCertificate']): - return $this->getDNProp($propName, $this->currentCert['tbsCertificate']['subject'], $withType); - case isset($this->currentCert['certificationRequestInfo']): - return $this->getDNProp($propName, $this->currentCert['certificationRequestInfo']['subject'], $withType); - } - - return false; - } - - /** - * Get the certificate chain for the current cert - * - * @return mixed - */ - public function getChain() - { - $chain = [$this->currentCert]; - - if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) { - return false; - } - if (empty($this->CAs)) { - return $chain; - } - while (true) { - $currentCert = $chain[count($chain) - 1]; - for ($i = 0; $i < count($this->CAs); $i++) { - $ca = $this->CAs[$i]; - if ($currentCert['tbsCertificate']['issuer'] === $ca['tbsCertificate']['subject']) { - $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier', $currentCert); - $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca); - switch (true) { - case !is_array($authorityKey): - case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID: - if ($currentCert === $ca) { - break 3; - } - $chain[] = $ca; - break 2; - } - } - } - if ($i == count($this->CAs)) { - break; - } - } - foreach ($chain as $key => $value) { - $chain[$key] = new X509(); - $chain[$key]->loadX509($value); - } - return $chain; - } - - /** - * Returns the current cert - * - * @return array|bool - */ - public function &getCurrentCert() - { - return $this->currentCert; - } - - /** - * Set public key - * - * Key needs to be a \phpseclib3\Crypt\RSA object - * - * @param PublicKey $key - * @return void - */ - public function setPublicKey(PublicKey $key) - { - $this->publicKey = $key; - } - - /** - * Set private key - * - * Key needs to be a \phpseclib3\Crypt\RSA object - * - * @param PrivateKey $key - */ - public function setPrivateKey(PrivateKey $key) - { - $this->privateKey = $key; - } - - /** - * Set challenge - * - * Used for SPKAC CSR's - * - * @param string $challenge - */ - public function setChallenge($challenge) - { - $this->challenge = $challenge; - } - - /** - * Gets the public key - * - * Returns a \phpseclib3\Crypt\RSA object or a false. - * - * @return mixed - */ - public function getPublicKey() - { - if (isset($this->publicKey)) { - return $this->publicKey; - } - - if (isset($this->currentCert) && is_array($this->currentCert)) { - $paths = [ - 'tbsCertificate/subjectPublicKeyInfo', - 'certificationRequestInfo/subjectPKInfo', - 'publicKeyAndChallenge/spki' - ]; - foreach ($paths as $path) { - $keyinfo = $this->subArray($this->currentCert, $path); - if (!empty($keyinfo)) { - break; - } - } - } - if (empty($keyinfo)) { - return false; - } - - $key = $keyinfo['subjectPublicKey']; - - switch ($keyinfo['algorithm']['algorithm']) { - case 'id-RSASSA-PSS': - return RSA::loadFormat('PSS', $key); - case 'rsaEncryption': - return RSA::loadFormat('PKCS8', $key)->withPadding(RSA::SIGNATURE_PKCS1); - case 'id-ecPublicKey': - case 'id-Ed25519': - case 'id-Ed448': - return EC::loadFormat('PKCS8', $key); - case 'id-dsa': - return DSA::loadFormat('PKCS8', $key); - } - - return false; - } - - /** - * Load a Certificate Signing Request - * - * @param string $csr - * @param int $mode - * @return mixed - */ - public function loadCSR($csr, $mode = self::FORMAT_AUTO_DETECT) - { - if (is_array($csr) && isset($csr['certificationRequestInfo'])) { - unset($this->currentCert); - unset($this->currentKeyIdentifier); - unset($this->signatureSubject); - $this->dn = $csr['certificationRequestInfo']['subject']; - if (!isset($this->dn)) { - return false; - } - - $this->currentCert = $csr; - return $csr; - } - - // see http://tools.ietf.org/html/rfc2986 - - if ($mode != self::FORMAT_DER) { - $newcsr = ASN1::extractBER($csr); - if ($mode == self::FORMAT_PEM && $csr == $newcsr) { - return false; - } - $csr = $newcsr; - } - $orig = $csr; - - if ($csr === false) { - $this->currentCert = false; - return false; - } - - $decoded = ASN1::decodeBER($csr); - - if (!$decoded) { - $this->currentCert = false; - return false; - } - - $csr = ASN1::asn1map($decoded[0], Maps\CertificationRequest::MAP); - if (!isset($csr) || $csr === false) { - $this->currentCert = false; - return false; - } - - $this->mapInAttributes($csr, 'certificationRequestInfo/attributes'); - $this->mapInDNs($csr, 'certificationRequestInfo/subject/rdnSequence'); - - $this->dn = $csr['certificationRequestInfo']['subject']; - - $this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']); - - $key = $csr['certificationRequestInfo']['subjectPKInfo']; - $key = ASN1::encodeDER($key, Maps\SubjectPublicKeyInfo::MAP); - $csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'] = - "-----BEGIN PUBLIC KEY-----\r\n" . - chunk_split(base64_encode($key), 64) . - "-----END PUBLIC KEY-----"; - - $this->currentKeyIdentifier = null; - $this->currentCert = $csr; - - $this->publicKey = null; - $this->publicKey = $this->getPublicKey(); - - return $csr; - } - - /** - * Save CSR request - * - * @param array $csr - * @param int $format optional - * @return string - */ - public function saveCSR(array $csr, $format = self::FORMAT_PEM) - { - if (!is_array($csr) || !isset($csr['certificationRequestInfo'])) { - return false; - } - - switch (true) { - case !($algorithm = $this->subArray($csr, 'certificationRequestInfo/subjectPKInfo/algorithm/algorithm')): - case is_object($csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']): - break; - default: - $csr['certificationRequestInfo']['subjectPKInfo'] = new Element( - base64_decode(preg_replace('#-.+-|[\r\n]#', '', $csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'])) - ); - } - - $filters = []; - $filters['certificationRequestInfo']['subject']['rdnSequence']['value'] - = ['type' => ASN1::TYPE_UTF8_STRING]; - - ASN1::setFilters($filters); - - $this->mapOutDNs($csr, 'certificationRequestInfo/subject/rdnSequence'); - $this->mapOutAttributes($csr, 'certificationRequestInfo/attributes'); - $csr = ASN1::encodeDER($csr, Maps\CertificationRequest::MAP); - - switch ($format) { - case self::FORMAT_DER: - return $csr; - // case self::FORMAT_PEM: - default: - return "-----BEGIN CERTIFICATE REQUEST-----\r\n" . chunk_split(Strings::base64_encode($csr), 64) . '-----END CERTIFICATE REQUEST-----'; - } - } - - /** - * Load a SPKAC CSR - * - * SPKAC's are produced by the HTML5 keygen element: - * - * https://developer.mozilla.org/en-US/docs/HTML/Element/keygen - * - * @param string $spkac - * @return mixed - */ - public function loadSPKAC($spkac) - { - if (is_array($spkac) && isset($spkac['publicKeyAndChallenge'])) { - unset($this->currentCert); - unset($this->currentKeyIdentifier); - unset($this->signatureSubject); - $this->currentCert = $spkac; - return $spkac; - } - - // see http://www.w3.org/html/wg/drafts/html/master/forms.html#signedpublickeyandchallenge - - // OpenSSL produces SPKAC's that are preceded by the string SPKAC= - $temp = preg_replace('#(?:SPKAC=)|[ \r\n\\\]#', '', $spkac); - $temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? Strings::base64_decode($temp) : false; - if ($temp != false) { - $spkac = $temp; - } - $orig = $spkac; - - if ($spkac === false) { - $this->currentCert = false; - return false; - } - - $decoded = ASN1::decodeBER($spkac); - - if (!$decoded) { - $this->currentCert = false; - return false; - } - - $spkac = ASN1::asn1map($decoded[0], Maps\SignedPublicKeyAndChallenge::MAP); - - if (!isset($spkac) || !is_array($spkac)) { - $this->currentCert = false; - return false; - } - - $this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']); - - $key = $spkac['publicKeyAndChallenge']['spki']; - $key = ASN1::encodeDER($key, Maps\SubjectPublicKeyInfo::MAP); - $spkac['publicKeyAndChallenge']['spki']['subjectPublicKey'] = - "-----BEGIN PUBLIC KEY-----\r\n" . - chunk_split(base64_encode($key), 64) . - "-----END PUBLIC KEY-----"; - - $this->currentKeyIdentifier = null; - $this->currentCert = $spkac; - - $this->publicKey = null; - $this->publicKey = $this->getPublicKey(); - - return $spkac; - } - - /** - * Save a SPKAC CSR request - * - * @param array $spkac - * @param int $format optional - * @return string - */ - public function saveSPKAC(array $spkac, $format = self::FORMAT_PEM) - { - if (!is_array($spkac) || !isset($spkac['publicKeyAndChallenge'])) { - return false; - } - - $algorithm = $this->subArray($spkac, 'publicKeyAndChallenge/spki/algorithm/algorithm'); - switch (true) { - case !$algorithm: - case is_object($spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']): - break; - default: - $spkac['publicKeyAndChallenge']['spki'] = new Element( - base64_decode(preg_replace('#-.+-|[\r\n]#', '', $spkac['publicKeyAndChallenge']['spki']['subjectPublicKey'])) - ); - } - - $spkac = ASN1::encodeDER($spkac, Maps\SignedPublicKeyAndChallenge::MAP); - - switch ($format) { - case self::FORMAT_DER: - return $spkac; - // case self::FORMAT_PEM: - default: - // OpenSSL's implementation of SPKAC requires the SPKAC be preceded by SPKAC= and since there are pretty much - // no other SPKAC decoders phpseclib will use that same format - return 'SPKAC=' . Strings::base64_encode($spkac); - } - } - - /** - * Load a Certificate Revocation List - * - * @param string $crl - * @param int $mode - * @return mixed - */ - public function loadCRL($crl, $mode = self::FORMAT_AUTO_DETECT) - { - if (is_array($crl) && isset($crl['tbsCertList'])) { - $this->currentCert = $crl; - unset($this->signatureSubject); - return $crl; - } - - if ($mode != self::FORMAT_DER) { - $newcrl = ASN1::extractBER($crl); - if ($mode == self::FORMAT_PEM && $crl == $newcrl) { - return false; - } - $crl = $newcrl; - } - $orig = $crl; - - if ($crl === false) { - $this->currentCert = false; - return false; - } - - $decoded = ASN1::decodeBER($crl); - - if (!$decoded) { - $this->currentCert = false; - return false; - } - - $crl = ASN1::asn1map($decoded[0], Maps\CertificateList::MAP); - if (!isset($crl) || $crl === false) { - $this->currentCert = false; - return false; - } - - $this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']); - - $this->mapInDNs($crl, 'tbsCertList/issuer/rdnSequence'); - if ($this->isSubArrayValid($crl, 'tbsCertList/crlExtensions')) { - $this->mapInExtensions($crl, 'tbsCertList/crlExtensions'); - } - if ($this->isSubArrayValid($crl, 'tbsCertList/revokedCertificates')) { - $rclist_ref = &$this->subArrayUnchecked($crl, 'tbsCertList/revokedCertificates'); - if ($rclist_ref) { - $rclist = $crl['tbsCertList']['revokedCertificates']; - foreach ($rclist as $i => $extension) { - if ($this->isSubArrayValid($rclist, "$i/crlEntryExtensions")) { - $this->mapInExtensions($rclist_ref, "$i/crlEntryExtensions"); - } - } - } - } - - $this->currentKeyIdentifier = null; - $this->currentCert = $crl; - - return $crl; - } - - /** - * Save Certificate Revocation List. - * - * @param array $crl - * @param int $format optional - * @return string - */ - public function saveCRL(array $crl, $format = self::FORMAT_PEM) - { - if (!is_array($crl) || !isset($crl['tbsCertList'])) { - return false; - } - - $filters = []; - $filters['tbsCertList']['issuer']['rdnSequence']['value'] - = ['type' => ASN1::TYPE_UTF8_STRING]; - $filters['tbsCertList']['signature']['parameters'] - = ['type' => ASN1::TYPE_UTF8_STRING]; - $filters['signatureAlgorithm']['parameters'] - = ['type' => ASN1::TYPE_UTF8_STRING]; - - if (empty($crl['tbsCertList']['signature']['parameters'])) { - $filters['tbsCertList']['signature']['parameters'] - = ['type' => ASN1::TYPE_NULL]; - } - - if (empty($crl['signatureAlgorithm']['parameters'])) { - $filters['signatureAlgorithm']['parameters'] - = ['type' => ASN1::TYPE_NULL]; - } - - ASN1::setFilters($filters); - - $this->mapOutDNs($crl, 'tbsCertList/issuer/rdnSequence'); - $this->mapOutExtensions($crl, 'tbsCertList/crlExtensions'); - $rclist = &$this->subArray($crl, 'tbsCertList/revokedCertificates'); - if (is_array($rclist)) { - foreach ($rclist as $i => $extension) { - $this->mapOutExtensions($rclist, "$i/crlEntryExtensions"); - } - } - - $crl = ASN1::encodeDER($crl, Maps\CertificateList::MAP); - - switch ($format) { - case self::FORMAT_DER: - return $crl; - // case self::FORMAT_PEM: - default: - return "-----BEGIN X509 CRL-----\r\n" . chunk_split(Strings::base64_encode($crl), 64) . '-----END X509 CRL-----'; - } - } - - /** - * Helper function to build a time field according to RFC 3280 section - * - 4.1.2.5 Validity - * - 5.1.2.4 This Update - * - 5.1.2.5 Next Update - * - 5.1.2.6 Revoked Certificates - * by choosing utcTime iff year of date given is before 2050 and generalTime else. - * - * @param string $date in format date('D, d M Y H:i:s O') - * @return array|Element - */ - private function timeField($date) - { - if ($date instanceof Element) { - return $date; - } - $dateObj = new \DateTimeImmutable($date, new \DateTimeZone('GMT')); - $year = $dateObj->format('Y'); // the same way ASN1.php parses this - if ($year < 2050) { - return ['utcTime' => $date]; - } else { - return ['generalTime' => $date]; - } - } - - /** - * Sign an X.509 certificate - * - * $issuer's private key needs to be loaded. - * $subject can be either an existing X.509 cert (if you want to resign it), - * a CSR or something with the DN and public key explicitly set. - * - * @return mixed - */ - public function sign(X509 $issuer, X509 $subject) - { - if (!is_object($issuer->privateKey) || empty($issuer->dn)) { - return false; - } - - if (isset($subject->publicKey) && !($subjectPublicKey = $subject->formatSubjectPublicKey())) { - return false; - } - - $currentCert = isset($this->currentCert) ? $this->currentCert : null; - $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null; - $signatureAlgorithm = self::identifySignatureAlgorithm($issuer->privateKey); - - if (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertificate'])) { - $this->currentCert = $subject->currentCert; - $this->currentCert['tbsCertificate']['signature'] = $signatureAlgorithm; - $this->currentCert['signatureAlgorithm'] = $signatureAlgorithm; - - if (!empty($this->startDate)) { - $this->currentCert['tbsCertificate']['validity']['notBefore'] = $this->timeField($this->startDate); - } - if (!empty($this->endDate)) { - $this->currentCert['tbsCertificate']['validity']['notAfter'] = $this->timeField($this->endDate); - } - if (!empty($this->serialNumber)) { - $this->currentCert['tbsCertificate']['serialNumber'] = $this->serialNumber; - } - if (!empty($subject->dn)) { - $this->currentCert['tbsCertificate']['subject'] = $subject->dn; - } - if (!empty($subject->publicKey)) { - $this->currentCert['tbsCertificate']['subjectPublicKeyInfo'] = $subjectPublicKey; - } - $this->removeExtension('id-ce-authorityKeyIdentifier'); - if (isset($subject->domains)) { - $this->removeExtension('id-ce-subjectAltName'); - } - } elseif (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertList'])) { - return false; - } else { - if (!isset($subject->publicKey)) { - return false; - } - - $startDate = new \DateTimeImmutable('now', new \DateTimeZone(@date_default_timezone_get())); - $startDate = !empty($this->startDate) ? $this->startDate : $startDate->format('D, d M Y H:i:s O'); - - $endDate = new \DateTimeImmutable('+1 year', new \DateTimeZone(@date_default_timezone_get())); - $endDate = !empty($this->endDate) ? $this->endDate : $endDate->format('D, d M Y H:i:s O'); - - /* "The serial number MUST be a positive integer" - "Conforming CAs MUST NOT use serialNumber values longer than 20 octets." - -- https://tools.ietf.org/html/rfc5280#section-4.1.2.2 - - for the integer to be positive the leading bit needs to be 0 hence the - application of a bitmap - */ - $serialNumber = !empty($this->serialNumber) ? - $this->serialNumber : - new BigInteger(Random::string(20) & ("\x7F" . str_repeat("\xFF", 19)), 256); - - $this->currentCert = [ - 'tbsCertificate' => - [ - 'version' => 'v3', - 'serialNumber' => $serialNumber, // $this->setSerialNumber() - 'signature' => $signatureAlgorithm, - 'issuer' => false, // this is going to be overwritten later - 'validity' => [ - 'notBefore' => $this->timeField($startDate), // $this->setStartDate() - 'notAfter' => $this->timeField($endDate) // $this->setEndDate() - ], - 'subject' => $subject->dn, - 'subjectPublicKeyInfo' => $subjectPublicKey - ], - 'signatureAlgorithm' => $signatureAlgorithm, - 'signature' => false // this is going to be overwritten later - ]; - - // Copy extensions from CSR. - $csrexts = $subject->getAttribute('pkcs-9-at-extensionRequest', 0); - - if (!empty($csrexts)) { - $this->currentCert['tbsCertificate']['extensions'] = $csrexts; - } - } - - $this->currentCert['tbsCertificate']['issuer'] = $issuer->dn; - - if (isset($issuer->currentKeyIdentifier)) { - $this->setExtension('id-ce-authorityKeyIdentifier', [ - //'authorityCertIssuer' => array( - // array( - // 'directoryName' => $issuer->dn - // ) - //), - 'keyIdentifier' => $issuer->currentKeyIdentifier - ]); - //$extensions = &$this->currentCert['tbsCertificate']['extensions']; - //if (isset($issuer->serialNumber)) { - // $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber; - //} - //unset($extensions); - } - - if (isset($subject->currentKeyIdentifier)) { - $this->setExtension('id-ce-subjectKeyIdentifier', $subject->currentKeyIdentifier); - } - - $altName = []; - - if (isset($subject->domains) && count($subject->domains)) { - $altName = array_map(['\phpseclib3\File\X509', 'dnsName'], $subject->domains); - } - - if (isset($subject->ipAddresses) && count($subject->ipAddresses)) { - // should an IP address appear as the CN if no domain name is specified? idk - //$ips = count($subject->domains) ? $subject->ipAddresses : array_slice($subject->ipAddresses, 1); - $ipAddresses = []; - foreach ($subject->ipAddresses as $ipAddress) { - $encoded = $subject->ipAddress($ipAddress); - if ($encoded !== false) { - $ipAddresses[] = $encoded; - } - } - if (count($ipAddresses)) { - $altName = array_merge($altName, $ipAddresses); - } - } - - if (!empty($altName)) { - $this->setExtension('id-ce-subjectAltName', $altName); - } - - if ($this->caFlag) { - $keyUsage = $this->getExtension('id-ce-keyUsage'); - if (!$keyUsage) { - $keyUsage = []; - } - - $this->setExtension( - 'id-ce-keyUsage', - array_values(array_unique(array_merge($keyUsage, ['cRLSign', 'keyCertSign']))) - ); - - $basicConstraints = $this->getExtension('id-ce-basicConstraints'); - if (!$basicConstraints) { - $basicConstraints = []; - } - - $this->setExtension( - 'id-ce-basicConstraints', - array_merge(['cA' => true], $basicConstraints), - true - ); - - if (!isset($subject->currentKeyIdentifier)) { - $this->setExtension('id-ce-subjectKeyIdentifier', $this->computeKeyIdentifier($this->currentCert), false, false); - } - } - - // resync $this->signatureSubject - // save $tbsCertificate in case there are any \phpseclib3\File\ASN1\Element objects in it - $tbsCertificate = $this->currentCert['tbsCertificate']; - $this->loadX509($this->saveX509($this->currentCert)); - - $result = $this->currentCert; - $this->currentCert['signature'] = $result['signature'] = "\0" . $issuer->privateKey->sign($this->signatureSubject); - $result['tbsCertificate'] = $tbsCertificate; - - $this->currentCert = $currentCert; - $this->signatureSubject = $signatureSubject; - - return $result; - } - - /** - * Sign a CSR - * - * @return mixed - */ - public function signCSR() - { - if (!is_object($this->privateKey) || empty($this->dn)) { - return false; - } - - $origPublicKey = $this->publicKey; - $this->publicKey = $this->privateKey->getPublicKey(); - $publicKey = $this->formatSubjectPublicKey(); - $this->publicKey = $origPublicKey; - - $currentCert = isset($this->currentCert) ? $this->currentCert : null; - $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null; - $signatureAlgorithm = self::identifySignatureAlgorithm($this->privateKey); - - if (isset($this->currentCert) && is_array($this->currentCert) && isset($this->currentCert['certificationRequestInfo'])) { - $this->currentCert['signatureAlgorithm'] = $signatureAlgorithm; - if (!empty($this->dn)) { - $this->currentCert['certificationRequestInfo']['subject'] = $this->dn; - } - $this->currentCert['certificationRequestInfo']['subjectPKInfo'] = $publicKey; - } else { - $this->currentCert = [ - 'certificationRequestInfo' => - [ - 'version' => 'v1', - 'subject' => $this->dn, - 'subjectPKInfo' => $publicKey - ], - 'signatureAlgorithm' => $signatureAlgorithm, - 'signature' => false // this is going to be overwritten later - ]; - } - - // resync $this->signatureSubject - // save $certificationRequestInfo in case there are any \phpseclib3\File\ASN1\Element objects in it - $certificationRequestInfo = $this->currentCert['certificationRequestInfo']; - $this->loadCSR($this->saveCSR($this->currentCert)); - - $result = $this->currentCert; - $this->currentCert['signature'] = $result['signature'] = "\0" . $this->privateKey->sign($this->signatureSubject); - $result['certificationRequestInfo'] = $certificationRequestInfo; - - $this->currentCert = $currentCert; - $this->signatureSubject = $signatureSubject; - - return $result; - } - - /** - * Sign a SPKAC - * - * @return mixed - */ - public function signSPKAC() - { - if (!is_object($this->privateKey)) { - return false; - } - - $origPublicKey = $this->publicKey; - $this->publicKey = $this->privateKey->getPublicKey(); - $publicKey = $this->formatSubjectPublicKey(); - $this->publicKey = $origPublicKey; - - $currentCert = isset($this->currentCert) ? $this->currentCert : null; - $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null; - $signatureAlgorithm = self::identifySignatureAlgorithm($this->privateKey); - - // re-signing a SPKAC seems silly but since everything else supports re-signing why not? - if (isset($this->currentCert) && is_array($this->currentCert) && isset($this->currentCert['publicKeyAndChallenge'])) { - $this->currentCert['signatureAlgorithm'] = $signatureAlgorithm; - $this->currentCert['publicKeyAndChallenge']['spki'] = $publicKey; - if (!empty($this->challenge)) { - // the bitwise AND ensures that the output is a valid IA5String - $this->currentCert['publicKeyAndChallenge']['challenge'] = $this->challenge & str_repeat("\x7F", strlen($this->challenge)); - } - } else { - $this->currentCert = [ - 'publicKeyAndChallenge' => - [ - 'spki' => $publicKey, - // quoting , - // "A challenge string that is submitted along with the public key. Defaults to an empty string if not specified." - // both Firefox and OpenSSL ("openssl spkac -key private.key") behave this way - // we could alternatively do this instead if we ignored the specs: - // Random::string(8) & str_repeat("\x7F", 8) - 'challenge' => !empty($this->challenge) ? $this->challenge : '' - ], - 'signatureAlgorithm' => $signatureAlgorithm, - 'signature' => false // this is going to be overwritten later - ]; - } - - // resync $this->signatureSubject - // save $publicKeyAndChallenge in case there are any \phpseclib3\File\ASN1\Element objects in it - $publicKeyAndChallenge = $this->currentCert['publicKeyAndChallenge']; - $this->loadSPKAC($this->saveSPKAC($this->currentCert)); - - $result = $this->currentCert; - $this->currentCert['signature'] = $result['signature'] = "\0" . $this->privateKey->sign($this->signatureSubject); - $result['publicKeyAndChallenge'] = $publicKeyAndChallenge; - - $this->currentCert = $currentCert; - $this->signatureSubject = $signatureSubject; - - return $result; - } - - /** - * Sign a CRL - * - * $issuer's private key needs to be loaded. - * - * @return mixed - */ - public function signCRL(X509 $issuer, X509 $crl) - { - if (!is_object($issuer->privateKey) || empty($issuer->dn)) { - return false; - } - - $currentCert = isset($this->currentCert) ? $this->currentCert : null; - $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null; - $signatureAlgorithm = self::identifySignatureAlgorithm($issuer->privateKey); - - $thisUpdate = new \DateTimeImmutable('now', new \DateTimeZone(@date_default_timezone_get())); - $thisUpdate = !empty($this->startDate) ? $this->startDate : $thisUpdate->format('D, d M Y H:i:s O'); - - if (isset($crl->currentCert) && is_array($crl->currentCert) && isset($crl->currentCert['tbsCertList'])) { - $this->currentCert = $crl->currentCert; - $this->currentCert['tbsCertList']['signature'] = $signatureAlgorithm; - $this->currentCert['signatureAlgorithm'] = $signatureAlgorithm; - } else { - $this->currentCert = [ - 'tbsCertList' => - [ - 'version' => 'v2', - 'signature' => $signatureAlgorithm, - 'issuer' => false, // this is going to be overwritten later - 'thisUpdate' => $this->timeField($thisUpdate) // $this->setStartDate() - ], - 'signatureAlgorithm' => $signatureAlgorithm, - 'signature' => false // this is going to be overwritten later - ]; - } - - $tbsCertList = &$this->currentCert['tbsCertList']; - $tbsCertList['issuer'] = $issuer->dn; - $tbsCertList['thisUpdate'] = $this->timeField($thisUpdate); - - if (!empty($this->endDate)) { - $tbsCertList['nextUpdate'] = $this->timeField($this->endDate); // $this->setEndDate() - } else { - unset($tbsCertList['nextUpdate']); - } - - if (!empty($this->serialNumber)) { - $crlNumber = $this->serialNumber; - } else { - $crlNumber = $this->getExtension('id-ce-cRLNumber'); - // "The CRL number is a non-critical CRL extension that conveys a - // monotonically increasing sequence number for a given CRL scope and - // CRL issuer. This extension allows users to easily determine when a - // particular CRL supersedes another CRL." - // -- https://tools.ietf.org/html/rfc5280#section-5.2.3 - $crlNumber = $crlNumber !== false ? $crlNumber->add(new BigInteger(1)) : null; - } - - $this->removeExtension('id-ce-authorityKeyIdentifier'); - $this->removeExtension('id-ce-issuerAltName'); - - // Be sure version >= v2 if some extension found. - $version = isset($tbsCertList['version']) ? $tbsCertList['version'] : 0; - if (!$version) { - if (!empty($tbsCertList['crlExtensions'])) { - $version = 1; // v2. - } elseif (!empty($tbsCertList['revokedCertificates'])) { - foreach ($tbsCertList['revokedCertificates'] as $cert) { - if (!empty($cert['crlEntryExtensions'])) { - $version = 1; // v2. - } - } - } - - if ($version) { - $tbsCertList['version'] = $version; - } - } - - // Store additional extensions. - if (!empty($tbsCertList['version'])) { // At least v2. - if (!empty($crlNumber)) { - $this->setExtension('id-ce-cRLNumber', $crlNumber); - } - - if (isset($issuer->currentKeyIdentifier)) { - $this->setExtension('id-ce-authorityKeyIdentifier', [ - //'authorityCertIssuer' => array( - // ] - // 'directoryName' => $issuer->dn - // ] - //), - 'keyIdentifier' => $issuer->currentKeyIdentifier - ]); - //$extensions = &$tbsCertList['crlExtensions']; - //if (isset($issuer->serialNumber)) { - // $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber; - //} - //unset($extensions); - } - - $issuerAltName = $this->getExtension('id-ce-subjectAltName', $issuer->currentCert); - - if ($issuerAltName !== false) { - $this->setExtension('id-ce-issuerAltName', $issuerAltName); - } - } - - if (empty($tbsCertList['revokedCertificates'])) { - unset($tbsCertList['revokedCertificates']); - } - - unset($tbsCertList); - - // resync $this->signatureSubject - // save $tbsCertList in case there are any \phpseclib3\File\ASN1\Element objects in it - $tbsCertList = $this->currentCert['tbsCertList']; - $this->loadCRL($this->saveCRL($this->currentCert)); - - $result = $this->currentCert; - $this->currentCert['signature'] = $result['signature'] = "\0" . $issuer->privateKey->sign($this->signatureSubject); - $result['tbsCertList'] = $tbsCertList; - - $this->currentCert = $currentCert; - $this->signatureSubject = $signatureSubject; - - return $result; - } - - /** - * Identify signature algorithm from key settings - * - * @param PrivateKey $key - * @throws \phpseclib3\Exception\UnsupportedAlgorithmException if the algorithm is unsupported - * @return array - */ - private static function identifySignatureAlgorithm(PrivateKey $key) - { - if ($key instanceof RSA) { - if ($key->getPadding() & RSA::SIGNATURE_PSS) { - $r = PSS::load($key->withPassword()->toString('PSS')); - return [ - 'algorithm' => 'id-RSASSA-PSS', - 'parameters' => PSS::savePSSParams($r) - ]; - } - switch ($key->getHash()) { - case 'md2': - case 'md5': - case 'sha1': - case 'sha224': - case 'sha256': - case 'sha384': - case 'sha512': - return ['algorithm' => $key->getHash() . 'WithRSAEncryption']; - } - throw new UnsupportedAlgorithmException('The only supported hash algorithms for RSA are: md2, md5, sha1, sha224, sha256, sha384, sha512'); - } - - if ($key instanceof DSA) { - switch ($key->getHash()) { - case 'sha1': - case 'sha224': - case 'sha256': - return ['algorithm' => 'id-dsa-with-' . $key->getHash()]; - } - throw new UnsupportedAlgorithmException('The only supported hash algorithms for DSA are: sha1, sha224, sha256'); - } - - if ($key instanceof EC) { - switch ($key->getCurve()) { - case 'Ed25519': - case 'Ed448': - return ['algorithm' => 'id-' . $key->getCurve()]; - } - switch ($key->getHash()) { - case 'sha1': - case 'sha224': - case 'sha256': - case 'sha384': - case 'sha512': - return ['algorithm' => 'ecdsa-with-' . strtoupper($key->getHash())]; - } - throw new UnsupportedAlgorithmException('The only supported hash algorithms for EC are: sha1, sha224, sha256, sha384, sha512'); - } - - throw new UnsupportedAlgorithmException('The only supported public key classes are: RSA, DSA, EC'); - } - - /** - * Set certificate start date - * - * @param \DateTimeInterface|string $date - */ - public function setStartDate($date) - { - if (!is_object($date) || !($date instanceof \DateTimeInterface)) { - $date = new \DateTimeImmutable($date, new \DateTimeZone(@date_default_timezone_get())); - } - - $this->startDate = $date->format('D, d M Y H:i:s O'); - } - - /** - * Set certificate end date - * - * @param \DateTimeInterface|string $date - */ - public function setEndDate($date) - { - /* - To indicate that a certificate has no well-defined expiration date, - the notAfter SHOULD be assigned the GeneralizedTime value of - 99991231235959Z. - - -- http://tools.ietf.org/html/rfc5280#section-4.1.2.5 - */ - if (is_string($date) && strtolower($date) === 'lifetime') { - $temp = '99991231235959Z'; - $temp = chr(ASN1::TYPE_GENERALIZED_TIME) . ASN1::encodeLength(strlen($temp)) . $temp; - $this->endDate = new Element($temp); - } else { - if (!is_object($date) || !($date instanceof \DateTimeInterface)) { - $date = new \DateTimeImmutable($date, new \DateTimeZone(@date_default_timezone_get())); - } - - $this->endDate = $date->format('D, d M Y H:i:s O'); - } - } - - /** - * Set Serial Number - * - * @param string $serial - * @param int $base optional - */ - public function setSerialNumber($serial, $base = -256) - { - $this->serialNumber = new BigInteger($serial, $base); - } - - /** - * Turns the certificate into a certificate authority - * - */ - public function makeCA() - { - $this->caFlag = true; - } - - /** - * Check for validity of subarray - * - * This is intended for use in conjunction with _subArrayUnchecked(), - * implementing the checks included in _subArray() but without copying - * a potentially large array by passing its reference by-value to is_array(). - * - * @param array $root - * @param string $path - * @return boolean - */ - private function isSubArrayValid(array $root, $path) - { - if (!is_array($root)) { - return false; - } - - foreach (explode('/', $path) as $i) { - if (!is_array($root)) { - return false; - } - - if (!isset($root[$i])) { - return true; - } - - $root = $root[$i]; - } - - return true; - } - - /** - * Get a reference to a subarray - * - * This variant of _subArray() does no is_array() checking, - * so $root should be checked with _isSubArrayValid() first. - * - * This is here for performance reasons: - * Passing a reference (i.e. $root) by-value (i.e. to is_array()) - * creates a copy. If $root is an especially large array, this is expensive. - * - * @param array $root - * @param string $path absolute path with / as component separator - * @param bool $create optional - * @return array|false - */ - private function &subArrayUnchecked(array &$root, $path, $create = false) - { - $false = false; - - foreach (explode('/', $path) as $i) { - if (!isset($root[$i])) { - if (!$create) { - return $false; - } - - $root[$i] = []; - } - - $root = &$root[$i]; - } - - return $root; - } - - /** - * Get a reference to a subarray - * - * @param array $root - * @param string $path absolute path with / as component separator - * @param bool $create optional - * @return array|false - */ - private function &subArray(array &$root = null, $path, $create = false) - { - $false = false; - - if (!is_array($root)) { - return $false; - } - - foreach (explode('/', $path) as $i) { - if (!is_array($root)) { - return $false; - } - - if (!isset($root[$i])) { - if (!$create) { - return $false; - } - - $root[$i] = []; - } - - $root = &$root[$i]; - } - - return $root; - } - - /** - * Get a reference to an extension subarray - * - * @param array $root - * @param string $path optional absolute path with / as component separator - * @param bool $create optional - * @return array|false - */ - private function &extensions(array &$root = null, $path = null, $create = false) - { - if (!isset($root)) { - $root = $this->currentCert; - } - - switch (true) { - case !empty($path): - case !is_array($root): - break; - case isset($root['tbsCertificate']): - $path = 'tbsCertificate/extensions'; - break; - case isset($root['tbsCertList']): - $path = 'tbsCertList/crlExtensions'; - break; - case isset($root['certificationRequestInfo']): - $pth = 'certificationRequestInfo/attributes'; - $attributes = &$this->subArray($root, $pth, $create); - - if (is_array($attributes)) { - foreach ($attributes as $key => $value) { - if ($value['type'] == 'pkcs-9-at-extensionRequest') { - $path = "$pth/$key/value/0"; - break 2; - } - } - if ($create) { - $key = count($attributes); - $attributes[] = ['type' => 'pkcs-9-at-extensionRequest', 'value' => []]; - $path = "$pth/$key/value/0"; - } - } - break; - } - - $extensions = &$this->subArray($root, $path, $create); - - if (!is_array($extensions)) { - $false = false; - return $false; - } - - return $extensions; - } - - /** - * Remove an Extension - * - * @param string $id - * @param string $path optional - * @return bool - */ - private function removeExtensionHelper($id, $path = null) - { - $extensions = &$this->extensions($this->currentCert, $path); - - if (!is_array($extensions)) { - return false; - } - - $result = false; - foreach ($extensions as $key => $value) { - if ($value['extnId'] == $id) { - unset($extensions[$key]); - $result = true; - } - } - - $extensions = array_values($extensions); - // fix for https://bugs.php.net/75433 affecting PHP 7.2 - if (!isset($extensions[0])) { - $extensions = array_splice($extensions, 0, 0); - } - return $result; - } - - /** - * Get an Extension - * - * Returns the extension if it exists and false if not - * - * @param string $id - * @param array $cert optional - * @param string $path optional - * @return mixed - */ - private function getExtensionHelper($id, array $cert = null, $path = null) - { - $extensions = $this->extensions($cert, $path); - - if (!is_array($extensions)) { - return false; - } - - foreach ($extensions as $key => $value) { - if ($value['extnId'] == $id) { - return $value['extnValue']; - } - } - - return false; - } - - /** - * Returns a list of all extensions in use - * - * @param array $cert optional - * @param string $path optional - * @return array - */ - private function getExtensionsHelper(array $cert = null, $path = null) - { - $exts = $this->extensions($cert, $path); - $extensions = []; - - if (is_array($exts)) { - foreach ($exts as $extension) { - $extensions[] = $extension['extnId']; - } - } - - return $extensions; - } - - /** - * Set an Extension - * - * @param string $id - * @param mixed $value - * @param bool $critical optional - * @param bool $replace optional - * @param string $path optional - * @return bool - */ - private function setExtensionHelper($id, $value, $critical = false, $replace = true, $path = null) - { - $extensions = &$this->extensions($this->currentCert, $path, true); - - if (!is_array($extensions)) { - return false; - } - - $newext = ['extnId' => $id, 'critical' => $critical, 'extnValue' => $value]; - - foreach ($extensions as $key => $value) { - if ($value['extnId'] == $id) { - if (!$replace) { - return false; - } - - $extensions[$key] = $newext; - return true; - } - } - - $extensions[] = $newext; - return true; - } - - /** - * Remove a certificate, CSR or CRL Extension - * - * @param string $id - * @return bool - */ - public function removeExtension($id) - { - return $this->removeExtensionHelper($id); - } - - /** - * Get a certificate, CSR or CRL Extension - * - * Returns the extension if it exists and false if not - * - * @param string $id - * @param array $cert optional - * @param string $path - * @return mixed - */ - public function getExtension($id, array $cert = null, $path = null) - { - return $this->getExtensionHelper($id, $cert, $path); - } - - /** - * Returns a list of all extensions in use in certificate, CSR or CRL - * - * @param array $cert optional - * @param string $path optional - * @return array - */ - public function getExtensions(array $cert = null, $path = null) - { - return $this->getExtensionsHelper($cert, $path); - } - - /** - * Set a certificate, CSR or CRL Extension - * - * @param string $id - * @param mixed $value - * @param bool $critical optional - * @param bool $replace optional - * @return bool - */ - public function setExtension($id, $value, $critical = false, $replace = true) - { - return $this->setExtensionHelper($id, $value, $critical, $replace); - } - - /** - * Remove a CSR attribute. - * - * @param string $id - * @param int $disposition optional - * @return bool - */ - public function removeAttribute($id, $disposition = self::ATTR_ALL) - { - $attributes = &$this->subArray($this->currentCert, 'certificationRequestInfo/attributes'); - - if (!is_array($attributes)) { - return false; - } - - $result = false; - foreach ($attributes as $key => $attribute) { - if ($attribute['type'] == $id) { - $n = count($attribute['value']); - switch (true) { - case $disposition == self::ATTR_APPEND: - case $disposition == self::ATTR_REPLACE: - return false; - case $disposition >= $n: - $disposition -= $n; - break; - case $disposition == self::ATTR_ALL: - case $n == 1: - unset($attributes[$key]); - $result = true; - break; - default: - unset($attributes[$key]['value'][$disposition]); - $attributes[$key]['value'] = array_values($attributes[$key]['value']); - $result = true; - break; - } - if ($result && $disposition != self::ATTR_ALL) { - break; - } - } - } - - $attributes = array_values($attributes); - return $result; - } - - /** - * Get a CSR attribute - * - * Returns the attribute if it exists and false if not - * - * @param string $id - * @param int $disposition optional - * @param array $csr optional - * @return mixed - */ - public function getAttribute($id, $disposition = self::ATTR_ALL, array $csr = null) - { - if (empty($csr)) { - $csr = $this->currentCert; - } - - $attributes = $this->subArray($csr, 'certificationRequestInfo/attributes'); - - if (!is_array($attributes)) { - return false; - } - - foreach ($attributes as $key => $attribute) { - if ($attribute['type'] == $id) { - $n = count($attribute['value']); - switch (true) { - case $disposition == self::ATTR_APPEND: - case $disposition == self::ATTR_REPLACE: - return false; - case $disposition == self::ATTR_ALL: - return $attribute['value']; - case $disposition >= $n: - $disposition -= $n; - break; - default: - return $attribute['value'][$disposition]; - } - } - } - - return false; - } - - /** - * Returns a list of all CSR attributes in use - * - * @param array $csr optional - * @return array - */ - public function getAttributes(array $csr = null) - { - if (empty($csr)) { - $csr = $this->currentCert; - } - - $attributes = $this->subArray($csr, 'certificationRequestInfo/attributes'); - $attrs = []; - - if (is_array($attributes)) { - foreach ($attributes as $attribute) { - $attrs[] = $attribute['type']; - } - } - - return $attrs; - } - - /** - * Set a CSR attribute - * - * @param string $id - * @param mixed $value - * @param int $disposition optional - * @return bool - */ - public function setAttribute($id, $value, $disposition = self::ATTR_ALL) - { - $attributes = &$this->subArray($this->currentCert, 'certificationRequestInfo/attributes', true); - - if (!is_array($attributes)) { - return false; - } - - switch ($disposition) { - case self::ATTR_REPLACE: - $disposition = self::ATTR_APPEND; - // fall-through - case self::ATTR_ALL: - $this->removeAttribute($id); - break; - } - - foreach ($attributes as $key => $attribute) { - if ($attribute['type'] == $id) { - $n = count($attribute['value']); - switch (true) { - case $disposition == self::ATTR_APPEND: - $last = $key; - break; - case $disposition >= $n: - $disposition -= $n; - break; - default: - $attributes[$key]['value'][$disposition] = $value; - return true; - } - } - } - - switch (true) { - case $disposition >= 0: - return false; - case isset($last): - $attributes[$last]['value'][] = $value; - break; - default: - $attributes[] = ['type' => $id, 'value' => $disposition == self::ATTR_ALL ? $value : [$value]]; - break; - } - - return true; - } - - /** - * Sets the subject key identifier - * - * This is used by the id-ce-authorityKeyIdentifier and the id-ce-subjectKeyIdentifier extensions. - * - * @param string $value - */ - public function setKeyIdentifier($value) - { - if (empty($value)) { - unset($this->currentKeyIdentifier); - } else { - $this->currentKeyIdentifier = $value; - } - } - - /** - * Compute a public key identifier. - * - * Although key identifiers may be set to any unique value, this function - * computes key identifiers from public key according to the two - * recommended methods (4.2.1.2 RFC 3280). - * Highly polymorphic: try to accept all possible forms of key: - * - Key object - * - \phpseclib3\File\X509 object with public or private key defined - * - Certificate or CSR array - * - \phpseclib3\File\ASN1\Element object - * - PEM or DER string - * - * @param mixed $key optional - * @param int $method optional - * @return string binary key identifier - */ - public function computeKeyIdentifier($key = null, $method = 1) - { - if (is_null($key)) { - $key = $this; - } - - switch (true) { - case is_string($key): - break; - case is_array($key) && isset($key['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']): - return $this->computeKeyIdentifier($key['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'], $method); - case is_array($key) && isset($key['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']): - return $this->computeKeyIdentifier($key['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'], $method); - case !is_object($key): - return false; - case $key instanceof Element: - // Assume the element is a bitstring-packed key. - $decoded = ASN1::decodeBER($key->element); - if (!$decoded) { - return false; - } - $raw = ASN1::asn1map($decoded[0], ['type' => ASN1::TYPE_BIT_STRING]); - if (empty($raw)) { - return false; - } - // If the key is private, compute identifier from its corresponding public key. - $key = PublicKeyLoader::load($raw); - if ($key instanceof PrivateKey) { // If private. - return $this->computeKeyIdentifier($key, $method); - } - $key = $raw; // Is a public key. - break; - case $key instanceof X509: - if (isset($key->publicKey)) { - return $this->computeKeyIdentifier($key->publicKey, $method); - } - if (isset($key->privateKey)) { - return $this->computeKeyIdentifier($key->privateKey, $method); - } - if (isset($key->currentCert['tbsCertificate']) || isset($key->currentCert['certificationRequestInfo'])) { - return $this->computeKeyIdentifier($key->currentCert, $method); - } - return false; - default: // Should be a key object (i.e.: \phpseclib3\Crypt\RSA). - $key = $key->getPublicKey(); - break; - } - - // If in PEM format, convert to binary. - $key = ASN1::extractBER($key); - - // Now we have the key string: compute its sha-1 sum. - $hash = new Hash('sha1'); - $hash = $hash->hash($key); - - if ($method == 2) { - $hash = substr($hash, -8); - $hash[0] = chr((ord($hash[0]) & 0x0F) | 0x40); - } - - return $hash; - } - - /** - * Format a public key as appropriate - * - * @return array|false - */ - private function formatSubjectPublicKey() - { - $format = $this->publicKey instanceof RSA && ($this->publicKey->getPadding() & RSA::SIGNATURE_PSS) ? - 'PSS' : - 'PKCS8'; - - $publicKey = base64_decode(preg_replace('#-.+-|[\r\n]#', '', $this->publicKey->toString($format))); - - $decoded = ASN1::decodeBER($publicKey); - if (!$decoded) { - return false; - } - $mapped = ASN1::asn1map($decoded[0], Maps\SubjectPublicKeyInfo::MAP); - if (!is_array($mapped)) { - return false; - } - - $mapped['subjectPublicKey'] = $this->publicKey->toString($format); - - return $mapped; - } - - /** - * Set the domain name's which the cert is to be valid for - * - * @param mixed ...$domains - * @return void - */ - public function setDomain(...$domains) - { - $this->domains = $domains; - $this->removeDNProp('id-at-commonName'); - $this->setDNProp('id-at-commonName', $this->domains[0]); - } - - /** - * Set the IP Addresses's which the cert is to be valid for - * - * @param mixed[] ...$ipAddresses - */ - public function setIPAddress(...$ipAddresses) - { - $this->ipAddresses = $ipAddresses; - /* - if (!isset($this->domains)) { - $this->removeDNProp('id-at-commonName'); - $this->setDNProp('id-at-commonName', $this->ipAddresses[0]); - } - */ - } - - /** - * Helper function to build domain array - * - * @param string $domain - * @return array - */ - private static function dnsName($domain) - { - return ['dNSName' => $domain]; - } - - /** - * Helper function to build IP Address array - * - * (IPv6 is not currently supported) - * - * @param string $address - * @return array - */ - private function iPAddress($address) - { - return ['iPAddress' => $address]; - } - - /** - * Get the index of a revoked certificate. - * - * @param array $rclist - * @param string $serial - * @param bool $create optional - * @return int|false - */ - private function revokedCertificate(array &$rclist, $serial, $create = false) - { - $serial = new BigInteger($serial); - - foreach ($rclist as $i => $rc) { - if (!($serial->compare($rc['userCertificate']))) { - return $i; - } - } - - if (!$create) { - return false; - } - - $i = count($rclist); - $revocationDate = new \DateTimeImmutable('now', new \DateTimeZone(@date_default_timezone_get())); - $rclist[] = ['userCertificate' => $serial, - 'revocationDate' => $this->timeField($revocationDate->format('D, d M Y H:i:s O'))]; - return $i; - } - - /** - * Revoke a certificate. - * - * @param string $serial - * @param string $date optional - * @return bool - */ - public function revoke($serial, $date = null) - { - if (isset($this->currentCert['tbsCertList'])) { - if (is_array($rclist = &$this->subArray($this->currentCert, 'tbsCertList/revokedCertificates', true))) { - if ($this->revokedCertificate($rclist, $serial) === false) { // If not yet revoked - if (($i = $this->revokedCertificate($rclist, $serial, true)) !== false) { - if (!empty($date)) { - $rclist[$i]['revocationDate'] = $this->timeField($date); - } - - return true; - } - } - } - } - - return false; - } - - /** - * Unrevoke a certificate. - * - * @param string $serial - * @return bool - */ - public function unrevoke($serial) - { - if (is_array($rclist = &$this->subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) { - if (($i = $this->revokedCertificate($rclist, $serial)) !== false) { - unset($rclist[$i]); - $rclist = array_values($rclist); - return true; - } - } - - return false; - } - - /** - * Get a revoked certificate. - * - * @param string $serial - * @return mixed - */ - public function getRevoked($serial) - { - if (is_array($rclist = $this->subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) { - if (($i = $this->revokedCertificate($rclist, $serial)) !== false) { - return $rclist[$i]; - } - } - - return false; - } - - /** - * List revoked certificates - * - * @param array $crl optional - * @return array|bool - */ - public function listRevoked(array $crl = null) - { - if (!isset($crl)) { - $crl = $this->currentCert; - } - - if (!isset($crl['tbsCertList'])) { - return false; - } - - $result = []; - - if (is_array($rclist = $this->subArray($crl, 'tbsCertList/revokedCertificates'))) { - foreach ($rclist as $rc) { - $result[] = $rc['userCertificate']->toString(); - } - } - - return $result; - } - - /** - * Remove a Revoked Certificate Extension - * - * @param string $serial - * @param string $id - * @return bool - */ - public function removeRevokedCertificateExtension($serial, $id) - { - if (is_array($rclist = &$this->subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) { - if (($i = $this->revokedCertificate($rclist, $serial)) !== false) { - return $this->removeExtensionHelper($id, "tbsCertList/revokedCertificates/$i/crlEntryExtensions"); - } - } - - return false; - } - - /** - * Get a Revoked Certificate Extension - * - * Returns the extension if it exists and false if not - * - * @param string $serial - * @param string $id - * @param array $crl optional - * @return mixed - */ - public function getRevokedCertificateExtension($serial, $id, array $crl = null) - { - if (!isset($crl)) { - $crl = $this->currentCert; - } - - if (is_array($rclist = $this->subArray($crl, 'tbsCertList/revokedCertificates'))) { - if (($i = $this->revokedCertificate($rclist, $serial)) !== false) { - return $this->getExtension($id, $crl, "tbsCertList/revokedCertificates/$i/crlEntryExtensions"); - } - } - - return false; - } - - /** - * Returns a list of all extensions in use for a given revoked certificate - * - * @param string $serial - * @param array $crl optional - * @return array|bool - */ - public function getRevokedCertificateExtensions($serial, array $crl = null) - { - if (!isset($crl)) { - $crl = $this->currentCert; - } - - if (is_array($rclist = $this->subArray($crl, 'tbsCertList/revokedCertificates'))) { - if (($i = $this->revokedCertificate($rclist, $serial)) !== false) { - return $this->getExtensions($crl, "tbsCertList/revokedCertificates/$i/crlEntryExtensions"); - } - } - - return false; - } - - /** - * Set a Revoked Certificate Extension - * - * @param string $serial - * @param string $id - * @param mixed $value - * @param bool $critical optional - * @param bool $replace optional - * @return bool - */ - public function setRevokedCertificateExtension($serial, $id, $value, $critical = false, $replace = true) - { - if (isset($this->currentCert['tbsCertList'])) { - if (is_array($rclist = &$this->subArray($this->currentCert, 'tbsCertList/revokedCertificates', true))) { - if (($i = $this->revokedCertificate($rclist, $serial, true)) !== false) { - return $this->setExtensionHelper($id, $value, $critical, $replace, "tbsCertList/revokedCertificates/$i/crlEntryExtensions"); - } - } - } - - return false; - } - - /** - * Register the mapping for a custom/unsupported extension. - * - * @param string $id - * @param array $mapping - */ - public static function registerExtension($id, array $mapping) - { - if (isset(self::$extensions[$id]) && self::$extensions[$id] !== $mapping) { - throw new \RuntimeException( - 'Extension ' . $id . ' has already been defined with a different mapping.' - ); - } - - self::$extensions[$id] = $mapping; - } - - /** - * Register the mapping for a custom/unsupported extension. - * - * @param string $id - * - * @return array|null - */ - public static function getRegisteredExtension($id) - { - return isset(self::$extensions[$id]) ? self::$extensions[$id] : null; - } - - /** - * Register the mapping for a custom/unsupported extension. - * - * @param string $id - * @param mixed $value - * @param bool $critical - * @param bool $replace - */ - public function setExtensionValue($id, $value, $critical = false, $replace = false) - { - $this->extensionValues[$id] = compact('critical', 'replace', 'value'); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php deleted file mode 100644 index 70491abd..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php +++ /dev/null @@ -1,891 +0,0 @@ - - * add($b); - * - * echo $c->toString(); // outputs 5 - * ?> - * - * - * @author Jim Wigginton - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - */ - -namespace phpseclib3\Math; - -use phpseclib3\Exception\BadConfigurationException; -use phpseclib3\Math\BigInteger\Engines\Engine; - -/** - * Pure-PHP arbitrary precision integer arithmetic library. Supports base-2, base-10, base-16, and base-256 - * numbers. - * - * @author Jim Wigginton - */ -class BigInteger implements \JsonSerializable -{ - /** - * Main Engine - * - * @var class-string - */ - private static $mainEngine; - - /** - * Selected Engines - * - * @var list - */ - private static $engines; - - /** - * The actual BigInteger object - * - * @var object - */ - private $value; - - /** - * Mode independent value used for serialization. - * - * @see self::__sleep() - * @see self::__wakeup() - * @var string - */ - private $hex; - - /** - * Precision (used only for serialization) - * - * @see self::__sleep() - * @see self::__wakeup() - * @var int - */ - private $precision; - - /** - * Sets engine type. - * - * Throws an exception if the type is invalid - * - * @param string $main - * @param list $modexps optional - * @return void - */ - public static function setEngine($main, array $modexps = ['DefaultEngine']) - { - self::$engines = []; - - $fqmain = 'phpseclib3\\Math\\BigInteger\\Engines\\' . $main; - if (!class_exists($fqmain) || !method_exists($fqmain, 'isValidEngine')) { - throw new \InvalidArgumentException("$main is not a valid engine"); - } - if (!$fqmain::isValidEngine()) { - throw new BadConfigurationException("$main is not setup correctly on this system"); - } - /** @var class-string $fqmain */ - self::$mainEngine = $fqmain; - - if (!in_array('Default', $modexps)) { - $modexps[] = 'DefaultEngine'; - } - - $found = false; - foreach ($modexps as $modexp) { - try { - $fqmain::setModExpEngine($modexp); - $found = true; - break; - } catch (\Exception $e) { - } - } - - if (!$found) { - throw new BadConfigurationException("No valid modular exponentiation engine found for $main"); - } - - self::$engines = [$main, $modexp]; - } - - /** - * Returns the engine type - * - * @return string[] - */ - public static function getEngine() - { - self::initialize_static_variables(); - - return self::$engines; - } - - /** - * Initialize static variables - */ - private static function initialize_static_variables() - { - if (!isset(self::$mainEngine)) { - $engines = [ - ['GMP'], - ['PHP64', ['OpenSSL']], - ['BCMath', ['OpenSSL']], - ['PHP32', ['OpenSSL']] - ]; - foreach ($engines as $engine) { - try { - self::setEngine($engine[0], isset($engine[1]) ? $engine[1] : []); - break; - } catch (\Exception $e) { - } - } - } - } - - /** - * Converts base-2, base-10, base-16, and binary strings (base-256) to BigIntegers. - * - * If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using - * two's compliment. The sole exception to this is -10, which is treated the same as 10 is. - * - * @param string|int|BigInteger\Engines\Engine $x Base-10 number or base-$base number if $base set. - * @param int $base - */ - public function __construct($x = 0, $base = 10) - { - self::initialize_static_variables(); - - if ($x instanceof self::$mainEngine) { - $this->value = clone $x; - } elseif ($x instanceof BigInteger\Engines\Engine) { - $this->value = new static("$x"); - $this->value->setPrecision($x->getPrecision()); - } else { - $this->value = new self::$mainEngine($x, $base); - } - } - - /** - * Converts a BigInteger to a base-10 number. - * - * @return string - */ - public function toString() - { - return $this->value->toString(); - } - - /** - * __toString() magic method - */ - public function __toString() - { - return (string)$this->value; - } - - /** - * __debugInfo() magic method - * - * Will be called, automatically, when print_r() or var_dump() are called - */ - public function __debugInfo() - { - return $this->value->__debugInfo(); - } - - /** - * Converts a BigInteger to a byte string (eg. base-256). - * - * @param bool $twos_compliment - * @return string - */ - public function toBytes($twos_compliment = false) - { - return $this->value->toBytes($twos_compliment); - } - - /** - * Converts a BigInteger to a hex string (eg. base-16). - * - * @param bool $twos_compliment - * @return string - */ - public function toHex($twos_compliment = false) - { - return $this->value->toHex($twos_compliment); - } - - /** - * Converts a BigInteger to a bit string (eg. base-2). - * - * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're - * saved as two's compliment. - * - * @param bool $twos_compliment - * @return string - */ - public function toBits($twos_compliment = false) - { - return $this->value->toBits($twos_compliment); - } - - /** - * Adds two BigIntegers. - * - * @param BigInteger $y - * @return BigInteger - */ - public function add(BigInteger $y) - { - return new static($this->value->add($y->value)); - } - - /** - * Subtracts two BigIntegers. - * - * @param BigInteger $y - * @return BigInteger - */ - public function subtract(BigInteger $y) - { - return new static($this->value->subtract($y->value)); - } - - /** - * Multiplies two BigIntegers - * - * @param BigInteger $x - * @return BigInteger - */ - public function multiply(BigInteger $x) - { - return new static($this->value->multiply($x->value)); - } - - /** - * Divides two BigIntegers. - * - * Returns an array whose first element contains the quotient and whose second element contains the - * "common residue". If the remainder would be positive, the "common residue" and the remainder are the - * same. If the remainder would be negative, the "common residue" is equal to the sum of the remainder - * and the divisor (basically, the "common residue" is the first positive modulo). - * - * Here's an example: - * - * divide($b); - * - * echo $quotient->toString(); // outputs 0 - * echo "\r\n"; - * echo $remainder->toString(); // outputs 10 - * ?> - * - * - * @param BigInteger $y - * @return BigInteger[] - */ - public function divide(BigInteger $y) - { - list($q, $r) = $this->value->divide($y->value); - return [ - new static($q), - new static($r) - ]; - } - - /** - * Calculates modular inverses. - * - * Say you have (30 mod 17 * x mod 17) mod 17 == 1. x can be found using modular inverses. - * - * @param BigInteger $n - * @return BigInteger - */ - public function modInverse(BigInteger $n) - { - return new static($this->value->modInverse($n->value)); - } - - /** - * Calculates modular inverses. - * - * Say you have (30 mod 17 * x mod 17) mod 17 == 1. x can be found using modular inverses. - * - * @param BigInteger $n - * @return BigInteger[] - */ - public function extendedGCD(BigInteger $n) - { - extract($this->value->extendedGCD($n->value)); - /** - * @var BigInteger $gcd - * @var BigInteger $x - * @var BigInteger $y - */ - return [ - 'gcd' => new static($gcd), - 'x' => new static($x), - 'y' => new static($y) - ]; - } - - /** - * Calculates the greatest common divisor - * - * Say you have 693 and 609. The GCD is 21. - * - * @param BigInteger $n - * @return BigInteger - */ - public function gcd(BigInteger $n) - { - return new static($this->value->gcd($n->value)); - } - - /** - * Absolute value. - * - * @return BigInteger - */ - public function abs() - { - return new static($this->value->abs()); - } - - /** - * Set Precision - * - * Some bitwise operations give different results depending on the precision being used. Examples include left - * shift, not, and rotates. - * - * @param int $bits - */ - public function setPrecision($bits) - { - $this->value->setPrecision($bits); - } - - /** - * Get Precision - * - * Returns the precision if it exists, false if it doesn't - * - * @return int|bool - */ - public function getPrecision() - { - return $this->value->getPrecision(); - } - - /** - * Serialize - * - * Will be called, automatically, when serialize() is called on a BigInteger object. - * - * __sleep() / __wakeup() have been around since PHP 4.0 - * - * \Serializable was introduced in PHP 5.1 and deprecated in PHP 8.1: - * https://wiki.php.net/rfc/phase_out_serializable - * - * __serialize() / __unserialize() were introduced in PHP 7.4: - * https://wiki.php.net/rfc/custom_object_serialization - * - * @return array - */ - public function __sleep() - { - $this->hex = $this->toHex(true); - $vars = ['hex']; - if ($this->getPrecision() > 0) { - $vars[] = 'precision'; - } - return $vars; - } - - /** - * Serialize - * - * Will be called, automatically, when unserialize() is called on a BigInteger object. - */ - public function __wakeup() - { - $temp = new static($this->hex, -16); - $this->value = $temp->value; - if ($this->precision > 0) { - // recalculate $this->bitmask - $this->setPrecision($this->precision); - } - } - - /** - * JSON Serialize - * - * Will be called, automatically, when json_encode() is called on a BigInteger object. - * - * @return array{hex: string, precision?: int] - */ - #[\ReturnTypeWillChange] - public function jsonSerialize() - { - $result = ['hex' => $this->toHex(true)]; - if ($this->precision > 0) { - $result['precision'] = $this->getPrecision(); - } - return $result; - } - - /** - * Performs modular exponentiation. - * - * @param BigInteger $e - * @param BigInteger $n - * @return BigInteger - */ - public function powMod(BigInteger $e, BigInteger $n) - { - return new static($this->value->powMod($e->value, $n->value)); - } - - /** - * Performs modular exponentiation. - * - * @param BigInteger $e - * @param BigInteger $n - * @return BigInteger - */ - public function modPow(BigInteger $e, BigInteger $n) - { - return new static($this->value->modPow($e->value, $n->value)); - } - - /** - * Compares two numbers. - * - * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite. The reason for this - * is demonstrated thusly: - * - * $x > $y: $x->compare($y) > 0 - * $x < $y: $x->compare($y) < 0 - * $x == $y: $x->compare($y) == 0 - * - * Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y). - * - * {@internal Could return $this->subtract($x), but that's not as fast as what we do do.} - * - * @param BigInteger $y - * @return int in case < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal. - * @see self::equals() - */ - public function compare(BigInteger $y) - { - return $this->value->compare($y->value); - } - - /** - * Tests the equality of two numbers. - * - * If you need to see if one number is greater than or less than another number, use BigInteger::compare() - * - * @param BigInteger $x - * @return bool - */ - public function equals(BigInteger $x) - { - return $this->value->equals($x->value); - } - - /** - * Logical Not - * - * @return BigInteger - */ - public function bitwise_not() - { - return new static($this->value->bitwise_not()); - } - - /** - * Logical And - * - * @param BigInteger $x - * @return BigInteger - */ - public function bitwise_and(BigInteger $x) - { - return new static($this->value->bitwise_and($x->value)); - } - - /** - * Logical Or - * - * @param BigInteger $x - * @return BigInteger - */ - public function bitwise_or(BigInteger $x) - { - return new static($this->value->bitwise_or($x->value)); - } - - /** - * Logical Exclusive Or - * - * @param BigInteger $x - * @return BigInteger - */ - public function bitwise_xor(BigInteger $x) - { - return new static($this->value->bitwise_xor($x->value)); - } - - /** - * Logical Right Shift - * - * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift. - * - * @param int $shift - * @return BigInteger - */ - public function bitwise_rightShift($shift) - { - return new static($this->value->bitwise_rightShift($shift)); - } - - /** - * Logical Left Shift - * - * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift. - * - * @param int $shift - * @return BigInteger - */ - public function bitwise_leftShift($shift) - { - return new static($this->value->bitwise_leftShift($shift)); - } - - /** - * Logical Left Rotate - * - * Instead of the top x bits being dropped they're appended to the shifted bit string. - * - * @param int $shift - * @return BigInteger - */ - public function bitwise_leftRotate($shift) - { - return new static($this->value->bitwise_leftRotate($shift)); - } - - /** - * Logical Right Rotate - * - * Instead of the bottom x bits being dropped they're prepended to the shifted bit string. - * - * @param int $shift - * @return BigInteger - */ - public function bitwise_rightRotate($shift) - { - return new static($this->value->bitwise_rightRotate($shift)); - } - - /** - * Returns the smallest and largest n-bit number - * - * @param int $bits - * @return BigInteger[] - */ - public static function minMaxBits($bits) - { - self::initialize_static_variables(); - - $class = self::$mainEngine; - extract($class::minMaxBits($bits)); - /** @var BigInteger $min - * @var BigInteger $max - */ - return [ - 'min' => new static($min), - 'max' => new static($max) - ]; - } - - /** - * Return the size of a BigInteger in bits - * - * @return int - */ - public function getLength() - { - return $this->value->getLength(); - } - - /** - * Return the size of a BigInteger in bytes - * - * @return int - */ - public function getLengthInBytes() - { - return $this->value->getLengthInBytes(); - } - - /** - * Generates a random number of a certain size - * - * Bit length is equal to $size - * - * @param int $size - * @return BigInteger - */ - public static function random($size) - { - self::initialize_static_variables(); - - $class = self::$mainEngine; - return new static($class::random($size)); - } - - /** - * Generates a random prime number of a certain size - * - * Bit length is equal to $size - * - * @param int $size - * @return BigInteger - */ - public static function randomPrime($size) - { - self::initialize_static_variables(); - - $class = self::$mainEngine; - return new static($class::randomPrime($size)); - } - - /** - * Generate a random prime number between a range - * - * If there's not a prime within the given range, false will be returned. - * - * @param BigInteger $min - * @param BigInteger $max - * @return false|BigInteger - */ - public static function randomRangePrime(BigInteger $min, BigInteger $max) - { - $class = self::$mainEngine; - return new static($class::randomRangePrime($min->value, $max->value)); - } - - /** - * Generate a random number between a range - * - * Returns a random number between $min and $max where $min and $max - * can be defined using one of the two methods: - * - * BigInteger::randomRange($min, $max) - * BigInteger::randomRange($max, $min) - * - * @param BigInteger $min - * @param BigInteger $max - * @return BigInteger - */ - public static function randomRange(BigInteger $min, BigInteger $max) - { - $class = self::$mainEngine; - return new static($class::randomRange($min->value, $max->value)); - } - - /** - * Checks a numer to see if it's prime - * - * Assuming the $t parameter is not set, this function has an error rate of 2**-80. The main motivation for the - * $t parameter is distributability. BigInteger::randomPrime() can be distributed across multiple pageloads - * on a website instead of just one. - * - * @param int|bool $t - * @return bool - */ - public function isPrime($t = false) - { - return $this->value->isPrime($t); - } - - /** - * Calculates the nth root of a biginteger. - * - * Returns the nth root of a positive biginteger, where n defaults to 2 - * - * @param int $n optional - * @return BigInteger - */ - public function root($n = 2) - { - return new static($this->value->root($n)); - } - - /** - * Performs exponentiation. - * - * @param BigInteger $n - * @return BigInteger - */ - public function pow(BigInteger $n) - { - return new static($this->value->pow($n->value)); - } - - /** - * Return the minimum BigInteger between an arbitrary number of BigIntegers. - * - * @param BigInteger ...$nums - * @return BigInteger - */ - public static function min(BigInteger ...$nums) - { - $class = self::$mainEngine; - $nums = array_map(function ($num) { - return $num->value; - }, $nums); - return new static($class::min(...$nums)); - } - - /** - * Return the maximum BigInteger between an arbitrary number of BigIntegers. - * - * @param BigInteger ...$nums - * @return BigInteger - */ - public static function max(BigInteger ...$nums) - { - $class = self::$mainEngine; - $nums = array_map(function ($num) { - return $num->value; - }, $nums); - return new static($class::max(...$nums)); - } - - /** - * Tests BigInteger to see if it is between two integers, inclusive - * - * @param BigInteger $min - * @param BigInteger $max - * @return bool - */ - public function between(BigInteger $min, BigInteger $max) - { - return $this->value->between($min->value, $max->value); - } - - /** - * Clone - */ - public function __clone() - { - $this->value = clone $this->value; - } - - /** - * Is Odd? - * - * @return bool - */ - public function isOdd() - { - return $this->value->isOdd(); - } - - /** - * Tests if a bit is set - * - * @param int $x - * @return bool - */ - public function testBit($x) - { - return $this->value->testBit($x); - } - - /** - * Is Negative? - * - * @return bool - */ - public function isNegative() - { - return $this->value->isNegative(); - } - - /** - * Negate - * - * Given $k, returns -$k - * - * @return BigInteger - */ - public function negate() - { - return new static($this->value->negate()); - } - - /** - * Scan for 1 and right shift by that amount - * - * ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s)); - * - * @param BigInteger $r - * @return int - */ - public static function scan1divide(BigInteger $r) - { - $class = self::$mainEngine; - return $class::scan1divide($r->value); - } - - /** - * Create Recurring Modulo Function - * - * Sometimes it may be desirable to do repeated modulos with the same number outside of - * modular exponentiation - * - * @return callable - */ - public function createRecurringModuloFunction() - { - $func = $this->value->createRecurringModuloFunction(); - return function (BigInteger $x) use ($func) { - return new static($func($x->value)); - }; - } - - /** - * Bitwise Split - * - * Splits BigInteger's into chunks of $split bits - * - * @param int $split - * @return BigInteger[] - */ - public function bitwise_split($split) - { - return array_map(function ($val) { - return new static($val); - }, $this->value->bitwise_split($split)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath.php deleted file mode 100644 index 7c5ca9fb..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath.php +++ /dev/null @@ -1,697 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Exception\BadConfigurationException; - -/** - * BCMath Engine. - * - * @author Jim Wigginton - */ -class BCMath extends Engine -{ - /** - * Can Bitwise operations be done fast? - * - * @see parent::bitwise_leftRotate() - * @see parent::bitwise_rightRotate() - */ - const FAST_BITWISE = false; - - /** - * Engine Directory - * - * @see parent::setModExpEngine - */ - const ENGINE_DIR = 'BCMath'; - - /** - * Test for engine validity - * - * @return bool - * @see parent::__construct() - */ - public static function isValidEngine() - { - return extension_loaded('bcmath'); - } - - /** - * Default constructor - * - * @param mixed $x integer Base-10 number or base-$base number if $base set. - * @param int $base - * @see parent::__construct() - */ - public function __construct($x = 0, $base = 10) - { - if (!isset(static::$isValidEngine[static::class])) { - static::$isValidEngine[static::class] = self::isValidEngine(); - } - if (!static::$isValidEngine[static::class]) { - throw new BadConfigurationException('BCMath is not setup correctly on this system'); - } - - $this->value = '0'; - - parent::__construct($x, $base); - } - - /** - * Initialize a BCMath BigInteger Engine instance - * - * @param int $base - * @see parent::__construct() - */ - protected function initialize($base) - { - switch (abs($base)) { - case 256: - // round $len to the nearest 4 - $len = (strlen($this->value) + 3) & ~3; - - $x = str_pad($this->value, $len, chr(0), STR_PAD_LEFT); - - $this->value = '0'; - for ($i = 0; $i < $len; $i += 4) { - $this->value = bcmul($this->value, '4294967296', 0); // 4294967296 == 2**32 - $this->value = bcadd( - $this->value, - 0x1000000 * ord($x[$i]) + ((ord($x[$i + 1]) << 16) | (ord( - $x[$i + 2] - ) << 8) | ord($x[$i + 3])), - 0 - ); - } - - if ($this->is_negative) { - $this->value = '-' . $this->value; - } - break; - case 16: - $x = (strlen($this->value) & 1) ? '0' . $this->value : $this->value; - $temp = new self(Strings::hex2bin($x), 256); - $this->value = $this->is_negative ? '-' . $temp->value : $temp->value; - $this->is_negative = false; - break; - case 10: - // explicitly casting $x to a string is necessary, here, since doing $x[0] on -1 yields different - // results then doing it on '-1' does (modInverse does $x[0]) - $this->value = $this->value === '-' ? '0' : (string)$this->value; - } - } - - /** - * Converts a BigInteger to a base-10 number. - * - * @return string - */ - public function toString() - { - if ($this->value === '0') { - return '0'; - } - - return ltrim($this->value, '0'); - } - - /** - * Converts a BigInteger to a byte string (eg. base-256). - * - * @param bool $twos_compliment - * @return string - */ - public function toBytes($twos_compliment = false) - { - if ($twos_compliment) { - return $this->toBytesHelper(); - } - - $value = ''; - $current = $this->value; - - if ($current[0] == '-') { - $current = substr($current, 1); - } - - while (bccomp($current, '0', 0) > 0) { - $temp = bcmod($current, '16777216'); - $value = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $value; - $current = bcdiv($current, '16777216', 0); - } - - return $this->precision > 0 ? - substr(str_pad($value, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) : - ltrim($value, chr(0)); - } - - /** - * Adds two BigIntegers. - * - * @param BCMath $y - * @return BCMath - */ - public function add(BCMath $y) - { - $temp = new self(); - $temp->value = bcadd($this->value, $y->value); - - return $this->normalize($temp); - } - - /** - * Subtracts two BigIntegers. - * - * @param BCMath $y - * @return BCMath - */ - public function subtract(BCMath $y) - { - $temp = new self(); - $temp->value = bcsub($this->value, $y->value); - - return $this->normalize($temp); - } - - /** - * Multiplies two BigIntegers. - * - * @param BCMath $x - * @return BCMath - */ - public function multiply(BCMath $x) - { - $temp = new self(); - $temp->value = bcmul($this->value, $x->value); - - return $this->normalize($temp); - } - - /** - * Divides two BigIntegers. - * - * Returns an array whose first element contains the quotient and whose second element contains the - * "common residue". If the remainder would be positive, the "common residue" and the remainder are the - * same. If the remainder would be negative, the "common residue" is equal to the sum of the remainder - * and the divisor (basically, the "common residue" is the first positive modulo). - * - * @param BCMath $y - * @return array{static, static} - */ - public function divide(BCMath $y) - { - $quotient = new self(); - $remainder = new self(); - - $quotient->value = bcdiv($this->value, $y->value, 0); - $remainder->value = bcmod($this->value, $y->value); - - if ($remainder->value[0] == '-') { - $remainder->value = bcadd($remainder->value, $y->value[0] == '-' ? substr($y->value, 1) : $y->value, 0); - } - - return [$this->normalize($quotient), $this->normalize($remainder)]; - } - - /** - * Calculates modular inverses. - * - * Say you have (30 mod 17 * x mod 17) mod 17 == 1. x can be found using modular inverses. - * - * @param BCMath $n - * @return false|BCMath - */ - public function modInverse(BCMath $n) - { - return $this->modInverseHelper($n); - } - - /** - * Calculates the greatest common divisor and Bezout's identity. - * - * Say you have 693 and 609. The GCD is 21. Bezout's identity states that there exist integers x and y such that - * 693*x + 609*y == 21. In point of fact, there are actually an infinite number of x and y combinations and which - * combination is returned is dependent upon which mode is in use. See - * {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bezout's identity - Wikipedia} for more information. - * - * @param BCMath $n - * @return array{gcd: static, x: static, y: static} - */ - public function extendedGCD(BCMath $n) - { - // it might be faster to use the binary xGCD algorithim here, as well, but (1) that algorithim works - // best when the base is a power of 2 and (2) i don't think it'd make much difference, anyway. as is, - // the basic extended euclidean algorithim is what we're using. - - $u = $this->value; - $v = $n->value; - - $a = '1'; - $b = '0'; - $c = '0'; - $d = '1'; - - while (bccomp($v, '0', 0) != 0) { - $q = bcdiv($u, $v, 0); - - $temp = $u; - $u = $v; - $v = bcsub($temp, bcmul($v, $q, 0), 0); - - $temp = $a; - $a = $c; - $c = bcsub($temp, bcmul($a, $q, 0), 0); - - $temp = $b; - $b = $d; - $d = bcsub($temp, bcmul($b, $q, 0), 0); - } - - return [ - 'gcd' => $this->normalize(new static($u)), - 'x' => $this->normalize(new static($a)), - 'y' => $this->normalize(new static($b)) - ]; - } - - /** - * Calculates the greatest common divisor - * - * Say you have 693 and 609. The GCD is 21. - * - * @param BCMath $n - * @return BCMath - */ - public function gcd(BCMath $n) - { - extract($this->extendedGCD($n)); - /** @var BCMath $gcd */ - return $gcd; - } - - /** - * Absolute value. - * - * @return BCMath - */ - public function abs() - { - $temp = new static(); - $temp->value = strlen($this->value) && $this->value[0] == '-' ? - substr($this->value, 1) : - $this->value; - - return $temp; - } - - /** - * Logical And - * - * @param BCMath $x - * @return BCMath - */ - public function bitwise_and(BCMath $x) - { - return $this->bitwiseAndHelper($x); - } - - /** - * Logical Or - * - * @param BCMath $x - * @return BCMath - */ - public function bitwise_or(BCMath $x) - { - return $this->bitwiseXorHelper($x); - } - - /** - * Logical Exclusive Or - * - * @param BCMath $x - * @return BCMath - */ - public function bitwise_xor(BCMath $x) - { - return $this->bitwiseXorHelper($x); - } - - /** - * Logical Right Shift - * - * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift. - * - * @param int $shift - * @return BCMath - */ - public function bitwise_rightShift($shift) - { - $temp = new static(); - $temp->value = bcdiv($this->value, bcpow('2', $shift, 0), 0); - - return $this->normalize($temp); - } - - /** - * Logical Left Shift - * - * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift. - * - * @param int $shift - * @return BCMath - */ - public function bitwise_leftShift($shift) - { - $temp = new static(); - $temp->value = bcmul($this->value, bcpow('2', $shift, 0), 0); - - return $this->normalize($temp); - } - - /** - * Compares two numbers. - * - * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite. The reason for this - * is demonstrated thusly: - * - * $x > $y: $x->compare($y) > 0 - * $x < $y: $x->compare($y) < 0 - * $x == $y: $x->compare($y) == 0 - * - * Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y). - * - * {@internal Could return $this->subtract($x), but that's not as fast as what we do do.} - * - * @param BCMath $y - * @return int in case < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal. - * @see self::equals() - */ - public function compare(BCMath $y) - { - return bccomp($this->value, $y->value, 0); - } - - /** - * Tests the equality of two numbers. - * - * If you need to see if one number is greater than or less than another number, use BigInteger::compare() - * - * @param BCMath $x - * @return bool - */ - public function equals(BCMath $x) - { - return $this->value == $x->value; - } - - /** - * Performs modular exponentiation. - * - * @param BCMath $e - * @param BCMath $n - * @return BCMath - */ - public function modPow(BCMath $e, BCMath $n) - { - return $this->powModOuter($e, $n); - } - - /** - * Performs modular exponentiation. - * - * Alias for modPow(). - * - * @param BCMath $e - * @param BCMath $n - * @return BCMath - */ - public function powMod(BCMath $e, BCMath $n) - { - return $this->powModOuter($e, $n); - } - - /** - * Performs modular exponentiation. - * - * @param BCMath $e - * @param BCMath $n - * @return BCMath - */ - protected function powModInner(BCMath $e, BCMath $n) - { - try { - $class = static::$modexpEngine[static::class]; - return $class::powModHelper($this, $e, $n, static::class); - } catch (\Exception $err) { - return BCMath\DefaultEngine::powModHelper($this, $e, $n, static::class); - } - } - - /** - * Normalize - * - * Removes leading zeros and truncates (if necessary) to maintain the appropriate precision - * - * @param BCMath $result - * @return BCMath - */ - protected function normalize(BCMath $result) - { - $result->precision = $this->precision; - $result->bitmask = $this->bitmask; - - if ($result->bitmask !== false) { - $result->value = bcmod($result->value, $result->bitmask->value); - } - - return $result; - } - - /** - * Generate a random prime number between a range - * - * If there's not a prime within the given range, false will be returned. - * - * @param BCMath $min - * @param BCMath $max - * @return false|BCMath - */ - public static function randomRangePrime(BCMath $min, BCMath $max) - { - return self::randomRangePrimeOuter($min, $max); - } - - /** - * Generate a random number between a range - * - * Returns a random number between $min and $max where $min and $max - * can be defined using one of the two methods: - * - * BigInteger::randomRange($min, $max) - * BigInteger::randomRange($max, $min) - * - * @param BCMath $min - * @param BCMath $max - * @return BCMath - */ - public static function randomRange(BCMath $min, BCMath $max) - { - return self::randomRangeHelper($min, $max); - } - - /** - * Make the current number odd - * - * If the current number is odd it'll be unchanged. If it's even, one will be added to it. - * - * @see self::randomPrime() - */ - protected function make_odd() - { - if (!$this->isOdd()) { - $this->value = bcadd($this->value, '1'); - } - } - - /** - * Test the number against small primes. - * - * @see self::isPrime() - */ - protected function testSmallPrimes() - { - if ($this->value === '1') { - return false; - } - if ($this->value === '2') { - return true; - } - if ($this->value[strlen($this->value) - 1] % 2 == 0) { - return false; - } - - $value = $this->value; - - foreach (self::PRIMES as $prime) { - $r = bcmod($this->value, $prime); - if ($r == '0') { - return $this->value == $prime; - } - } - - return true; - } - - /** - * Scan for 1 and right shift by that amount - * - * ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s)); - * - * @param BCMath $r - * @return int - * @see self::isPrime() - */ - public static function scan1divide(BCMath $r) - { - $r_value = &$r->value; - $s = 0; - // if $n was 1, $r would be 0 and this would be an infinite loop, hence our $this->equals(static::$one[static::class]) check earlier - while ($r_value[strlen($r_value) - 1] % 2 == 0) { - $r_value = bcdiv($r_value, '2', 0); - ++$s; - } - - return $s; - } - - /** - * Performs exponentiation. - * - * @param BCMath $n - * @return BCMath - */ - public function pow(BCMath $n) - { - $temp = new self(); - $temp->value = bcpow($this->value, $n->value); - - return $this->normalize($temp); - } - - /** - * Return the minimum BigInteger between an arbitrary number of BigIntegers. - * - * @param BCMath ...$nums - * @return BCMath - */ - public static function min(BCMath ...$nums) - { - return self::minHelper($nums); - } - - /** - * Return the maximum BigInteger between an arbitrary number of BigIntegers. - * - * @param BCMath ...$nums - * @return BCMath - */ - public static function max(BCMath ...$nums) - { - return self::maxHelper($nums); - } - - /** - * Tests BigInteger to see if it is between two integers, inclusive - * - * @param BCMath $min - * @param BCMath $max - * @return bool - */ - public function between(BCMath $min, BCMath $max) - { - return $this->compare($min) >= 0 && $this->compare($max) <= 0; - } - - /** - * Set Bitmask - * - * @param int $bits - * @return Engine - * @see self::setPrecision() - */ - protected static function setBitmask($bits) - { - $temp = parent::setBitmask($bits); - return $temp->add(static::$one[static::class]); - } - - /** - * Is Odd? - * - * @return bool - */ - public function isOdd() - { - return $this->value[strlen($this->value) - 1] % 2 == 1; - } - - /** - * Tests if a bit is set - * - * @return bool - */ - public function testBit($x) - { - return bccomp( - bcmod($this->value, bcpow('2', $x + 1, 0)), - bcpow('2', $x, 0), - 0 - ) >= 0; - } - - /** - * Is Negative? - * - * @return bool - */ - public function isNegative() - { - return strlen($this->value) && $this->value[0] == '-'; - } - - /** - * Negate - * - * Given $k, returns -$k - * - * @return BCMath - */ - public function negate() - { - $temp = clone $this; - - if (!strlen($temp->value)) { - return $temp; - } - - $temp->value = $temp->value[0] == '-' ? - substr($this->value, 1) : - '-' . $this->value; - - return $temp; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Base.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Base.php deleted file mode 100644 index fe21e041..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Base.php +++ /dev/null @@ -1,110 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines\BCMath; - -use phpseclib3\Math\BigInteger\Engines\BCMath; - -/** - * Sliding Window Exponentiation Engine - * - * @author Jim Wigginton - */ -abstract class Base extends BCMath -{ - /** - * Cache constants - * - * $cache[self::VARIABLE] tells us whether or not the cached data is still valid. - * - */ - const VARIABLE = 0; - /** - * $cache[self::DATA] contains the cached data. - * - */ - const DATA = 1; - - /** - * Test for engine validity - * - * @return bool - */ - public static function isValidEngine() - { - return static::class != __CLASS__; - } - - /** - * Performs modular exponentiation. - * - * @param BCMath $x - * @param BCMath $e - * @param BCMath $n - * @param string $class - * @return BCMath - */ - protected static function powModHelper(BCMath $x, BCMath $e, BCMath $n, $class) - { - if (empty($e->value)) { - $temp = new $class(); - $temp->value = '1'; - return $x->normalize($temp); - } - - return $x->normalize(static::slidingWindow($x, $e, $n, $class)); - } - - /** - * Modular reduction preparation - * - * @param string $x - * @param string $n - * @param string $class - * @see self::slidingWindow() - * @return string - */ - protected static function prepareReduce($x, $n, $class) - { - return static::reduce($x, $n); - } - - /** - * Modular multiply - * - * @param string $x - * @param string $y - * @param string $n - * @param string $class - * @see self::slidingWindow() - * @return string - */ - protected static function multiplyReduce($x, $y, $n, $class) - { - return static::reduce(bcmul($x, $y), $n); - } - - /** - * Modular square - * - * @param string $x - * @param string $n - * @param string $class - * @see self::slidingWindow() - * @return string - */ - protected static function squareReduce($x, $n, $class) - { - return static::reduce(bcmul($x, $x), $n); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/BuiltIn.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/BuiltIn.php deleted file mode 100644 index b7ca8a2c..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/BuiltIn.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines\BCMath; - -use phpseclib3\Math\BigInteger\Engines\BCMath; - -/** - * Built-In BCMath Modular Exponentiation Engine - * - * @author Jim Wigginton - */ -abstract class BuiltIn extends BCMath -{ - /** - * Performs modular exponentiation. - * - * @param BCMath $x - * @param BCMath $e - * @param BCMath $n - * @return BCMath - */ - protected static function powModHelper(BCMath $x, BCMath $e, BCMath $n) - { - $temp = new BCMath(); - $temp->value = bcpowmod($x->value, $e->value, $n->value); - - return $x->normalize($temp); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/DefaultEngine.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/DefaultEngine.php deleted file mode 100644 index b2d9fa95..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/DefaultEngine.php +++ /dev/null @@ -1,25 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines\BCMath; - -use phpseclib3\Math\BigInteger\Engines\BCMath\Reductions\Barrett; - -/** - * PHP Default Modular Exponentiation Engine - * - * @author Jim Wigginton - */ -abstract class DefaultEngine extends Barrett -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/OpenSSL.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/OpenSSL.php deleted file mode 100644 index aed94942..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/OpenSSL.php +++ /dev/null @@ -1,25 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines\BCMath; - -use phpseclib3\Math\BigInteger\Engines\OpenSSL as Progenitor; - -/** - * OpenSSL Modular Exponentiation Engine - * - * @author Jim Wigginton - */ -abstract class OpenSSL extends Progenitor -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Reductions/Barrett.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Reductions/Barrett.php deleted file mode 100644 index 0fb7eaeb..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Reductions/Barrett.php +++ /dev/null @@ -1,187 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines\BCMath\Reductions; - -use phpseclib3\Math\BigInteger\Engines\BCMath\Base; - -/** - * PHP Barrett Modular Exponentiation Engine - * - * @author Jim Wigginton - */ -abstract class Barrett extends Base -{ - /** - * Cache constants - * - * $cache[self::VARIABLE] tells us whether or not the cached data is still valid. - * - */ - const VARIABLE = 0; - /** - * $cache[self::DATA] contains the cached data. - * - */ - const DATA = 1; - - /** - * Barrett Modular Reduction - * - * See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=14 HAC 14.3.3} / - * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=165 MPM 6.2.5} for more information. Modified slightly, - * so as not to require negative numbers (initially, this script didn't support negative numbers). - * - * Employs "folding", as described at - * {@link http://www.cosic.esat.kuleuven.be/publications/thesis-149.pdf#page=66 thesis-149.pdf#page=66}. To quote from - * it, "the idea [behind folding] is to find a value x' such that x (mod m) = x' (mod m), with x' being smaller than x." - * - * Unfortunately, the "Barrett Reduction with Folding" algorithm described in thesis-149.pdf is not, as written, all that - * usable on account of (1) its not using reasonable radix points as discussed in - * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=162 MPM 6.2.2} and (2) the fact that, even with reasonable - * radix points, it only works when there are an even number of digits in the denominator. The reason for (2) is that - * (x >> 1) + (x >> 1) != x / 2 + x / 2. If x is even, they're the same, but if x is odd, they're not. See the in-line - * comments for details. - * - * @param string $n - * @param string $m - * @return string - */ - protected static function reduce($n, $m) - { - static $cache = [ - self::VARIABLE => [], - self::DATA => [] - ]; - - $m_length = strlen($m); - - if (strlen($n) > 2 * $m_length) { - return bcmod($n, $m); - } - - // if (m.length >> 1) + 2 <= m.length then m is too small and n can't be reduced - if ($m_length < 5) { - return self::regularBarrett($n, $m); - } - // n = 2 * m.length - - if (($key = array_search($m, $cache[self::VARIABLE])) === false) { - $key = count($cache[self::VARIABLE]); - $cache[self::VARIABLE][] = $m; - - $lhs = '1' . str_repeat('0', $m_length + ($m_length >> 1)); - $u = bcdiv($lhs, $m, 0); - $m1 = bcsub($lhs, bcmul($u, $m)); - - $cache[self::DATA][] = [ - 'u' => $u, // m.length >> 1 (technically (m.length >> 1) + 1) - 'm1' => $m1 // m.length - ]; - } else { - extract($cache[self::DATA][$key]); - } - - $cutoff = $m_length + ($m_length >> 1); - - $lsd = substr($n, -$cutoff); - $msd = substr($n, 0, -$cutoff); - - $temp = bcmul($msd, $m1); // m.length + (m.length >> 1) - $n = bcadd($lsd, $temp); // m.length + (m.length >> 1) + 1 (so basically we're adding two same length numbers) - //if ($m_length & 1) { - // return self::regularBarrett($n, $m); - //} - - // (m.length + (m.length >> 1) + 1) - (m.length - 1) == (m.length >> 1) + 2 - $temp = substr($n, 0, -$m_length + 1); - // if even: ((m.length >> 1) + 2) + (m.length >> 1) == m.length + 2 - // if odd: ((m.length >> 1) + 2) + (m.length >> 1) == (m.length - 1) + 2 == m.length + 1 - $temp = bcmul($temp, $u); - // if even: (m.length + 2) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) + 1 - // if odd: (m.length + 1) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) - $temp = substr($temp, 0, -($m_length >> 1) - 1); - // if even: (m.length - (m.length >> 1) + 1) + m.length = 2 * m.length - (m.length >> 1) + 1 - // if odd: (m.length - (m.length >> 1)) + m.length = 2 * m.length - (m.length >> 1) - $temp = bcmul($temp, $m); - - // at this point, if m had an odd number of digits, we'd be subtracting a 2 * m.length - (m.length >> 1) digit - // number from a m.length + (m.length >> 1) + 1 digit number. ie. there'd be an extra digit and the while loop - // following this comment would loop a lot (hence our calling _regularBarrett() in that situation). - - $result = bcsub($n, $temp); - - //if (bccomp($result, '0') < 0) { - if ($result[0] == '-') { - $temp = '1' . str_repeat('0', $m_length + 1); - $result = bcadd($result, $temp); - } - - while (bccomp($result, $m) >= 0) { - $result = bcsub($result, $m); - } - - return $result; - } - - /** - * (Regular) Barrett Modular Reduction - * - * For numbers with more than four digits BigInteger::_barrett() is faster. The difference between that and this - * is that this function does not fold the denominator into a smaller form. - * - * @param string $x - * @param string $n - * @return string - */ - private static function regularBarrett($x, $n) - { - static $cache = [ - self::VARIABLE => [], - self::DATA => [] - ]; - - $n_length = strlen($n); - - if (strlen($x) > 2 * $n_length) { - return bcmod($x, $n); - } - - if (($key = array_search($n, $cache[self::VARIABLE])) === false) { - $key = count($cache[self::VARIABLE]); - $cache[self::VARIABLE][] = $n; - $lhs = '1' . str_repeat('0', 2 * $n_length); - $cache[self::DATA][] = bcdiv($lhs, $n, 0); - } - - $temp = substr($x, 0, -$n_length + 1); - $temp = bcmul($temp, $cache[self::DATA][$key]); - $temp = substr($temp, 0, -$n_length - 1); - - $r1 = substr($x, -$n_length - 1); - $r2 = substr(bcmul($temp, $n), -$n_length - 1); - $result = bcsub($r1, $r2); - - //if (bccomp($result, '0') < 0) { - if ($result[0] == '-') { - $q = '1' . str_repeat('0', $n_length + 1); - $result = bcadd($result, $q); - } - - while (bccomp($result, $n) >= 0) { - $result = bcsub($result, $n); - } - - return $result; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Reductions/EvalBarrett.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Reductions/EvalBarrett.php deleted file mode 100644 index e033ba57..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Reductions/EvalBarrett.php +++ /dev/null @@ -1,108 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines\BCMath\Reductions; - -use phpseclib3\Math\BigInteger\Engines\BCMath; -use phpseclib3\Math\BigInteger\Engines\BCMath\Base; - -/** - * PHP Barrett Modular Exponentiation Engine - * - * @author Jim Wigginton - */ -abstract class EvalBarrett extends Base -{ - /** - * Custom Reduction Function - * - * @see self::generateCustomReduction - */ - private static $custom_reduction; - - /** - * Barrett Modular Reduction - * - * This calls a dynamically generated loop unrolled function that's specific to a given modulo. - * Array lookups are avoided as are if statements testing for how many bits the host OS supports, etc. - * - * @param string $n - * @param string $m - * @return string - */ - protected static function reduce($n, $m) - { - $inline = self::$custom_reduction; - return $inline($n); - } - - /** - * Generate Custom Reduction - * - * @param BCMath $m - * @param string $class - * @return callable|void - */ - protected static function generateCustomReduction(BCMath $m, $class) - { - $m_length = strlen($m); - - if ($m_length < 5) { - $code = 'return bcmod($x, $n);'; - eval('$func = function ($n) { ' . $code . '};'); - self::$custom_reduction = $func; - return; - } - - $lhs = '1' . str_repeat('0', $m_length + ($m_length >> 1)); - $u = bcdiv($lhs, $m, 0); - $m1 = bcsub($lhs, bcmul($u, $m)); - - $cutoff = $m_length + ($m_length >> 1); - - $m = "'$m'"; - $u = "'$u'"; - $m1 = "'$m1'"; - - $code = ' - $lsd = substr($n, -' . $cutoff . '); - $msd = substr($n, 0, -' . $cutoff . '); - - $temp = bcmul($msd, ' . $m1 . '); - $n = bcadd($lsd, $temp); - - $temp = substr($n, 0, ' . (-$m_length + 1) . '); - $temp = bcmul($temp, ' . $u . '); - $temp = substr($temp, 0, ' . (-($m_length >> 1) - 1) . '); - $temp = bcmul($temp, ' . $m . '); - - $result = bcsub($n, $temp); - - if ($result[0] == \'-\') { - $temp = \'1' . str_repeat('0', $m_length + 1) . '\'; - $result = bcadd($result, $temp); - } - - while (bccomp($result, ' . $m . ') >= 0) { - $result = bcsub($result, ' . $m . '); - } - - return $result;'; - - eval('$func = function ($n) { ' . $code . '};'); - - self::$custom_reduction = $func; - - return $func; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/Engine.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/Engine.php deleted file mode 100644 index 2b00bc37..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/Engine.php +++ /dev/null @@ -1,1280 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\Random; -use phpseclib3\Exception\BadConfigurationException; -use phpseclib3\Math\BigInteger; - -/** - * Base Engine. - * - * @author Jim Wigginton - */ -abstract class Engine implements \JsonSerializable -{ - /* final protected */ const PRIMES = [ - 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, - 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, - 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, - 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, - 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, - 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, - 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, - 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, - 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, - 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, - 953, 967, 971, 977, 983, 991, 997, - ]; - - /** - * BigInteger(0) - * - * @var array, static> - */ - protected static $zero = []; - - /** - * BigInteger(1) - * - * @var array, static> - */ - protected static $one = []; - - /** - * BigInteger(2) - * - * @var array, static> - */ - protected static $two = []; - - /** - * Modular Exponentiation Engine - * - * @var array, class-string> - */ - protected static $modexpEngine; - - /** - * Engine Validity Flag - * - * @var array, bool> - */ - protected static $isValidEngine; - - /** - * Holds the BigInteger's value - * - * @var \GMP|string|array|int - */ - protected $value; - - /** - * Holds the BigInteger's sign - * - * @var bool - */ - protected $is_negative; - - /** - * Precision - * - * @see static::setPrecision() - * @var int - */ - protected $precision = -1; - - /** - * Precision Bitmask - * - * @see static::setPrecision() - * @var static|false - */ - protected $bitmask = false; - - /** - * Recurring Modulo Function - * - * @var callable - */ - protected $reduce; - - /** - * Mode independent value used for serialization. - * - * @see self::__sleep() - * @see self::__wakeup() - * @var string - */ - protected $hex; - - /** - * Default constructor - * - * @param int|numeric-string $x integer Base-10 number or base-$base number if $base set. - * @param int $base - */ - public function __construct($x = 0, $base = 10) - { - if (!array_key_exists(static::class, static::$zero)) { - static::$zero[static::class] = null; // Placeholder to prevent infinite loop. - static::$zero[static::class] = new static(0); - static::$one[static::class] = new static(1); - static::$two[static::class] = new static(2); - } - - // '0' counts as empty() but when the base is 256 '0' is equal to ord('0') or 48 - // '0' is the only value like this per http://php.net/empty - if (empty($x) && (abs($base) != 256 || $x !== '0')) { - return; - } - - switch ($base) { - case -256: - case 256: - if ($base == -256 && (ord($x[0]) & 0x80)) { - $this->value = ~$x; - $this->is_negative = true; - } else { - $this->value = $x; - $this->is_negative = false; - } - - $this->initialize($base); - - if ($this->is_negative) { - $temp = $this->add(new static('-1')); - $this->value = $temp->value; - } - break; - case -16: - case 16: - if ($base > 0 && $x[0] == '-') { - $this->is_negative = true; - $x = substr($x, 1); - } - - $x = preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#s', '$1', $x); - - $is_negative = false; - if ($base < 0 && hexdec($x[0]) >= 8) { - $this->is_negative = $is_negative = true; - $x = Strings::bin2hex(~Strings::hex2bin($x)); - } - - $this->value = $x; - $this->initialize($base); - - if ($is_negative) { - $temp = $this->add(new static('-1')); - $this->value = $temp->value; - } - break; - case -10: - case 10: - // (?value = preg_replace('#(?value) || $this->value == '-') { - $this->value = '0'; - } - $this->initialize($base); - break; - case -2: - case 2: - if ($base > 0 && $x[0] == '-') { - $this->is_negative = true; - $x = substr($x, 1); - } - - $x = preg_replace('#^([01]*).*#s', '$1', $x); - - $temp = new static(Strings::bits2bin($x), 128 * $base); // ie. either -16 or +16 - $this->value = $temp->value; - if ($temp->is_negative) { - $this->is_negative = true; - } - - break; - default: - // base not supported, so we'll let $this == 0 - } - } - - /** - * Sets engine type. - * - * Throws an exception if the type is invalid - * - * @param class-string $engine - */ - public static function setModExpEngine($engine) - { - $fqengine = '\\phpseclib3\\Math\\BigInteger\\Engines\\' . static::ENGINE_DIR . '\\' . $engine; - if (!class_exists($fqengine) || !method_exists($fqengine, 'isValidEngine')) { - throw new \InvalidArgumentException("$engine is not a valid engine"); - } - if (!$fqengine::isValidEngine()) { - throw new BadConfigurationException("$engine is not setup correctly on this system"); - } - static::$modexpEngine[static::class] = $fqengine; - } - - /** - * Converts a BigInteger to a byte string (eg. base-256). - * - * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're - * saved as two's compliment. - * @return string - */ - protected function toBytesHelper() - { - $comparison = $this->compare(new static()); - if ($comparison == 0) { - return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; - } - - $temp = $comparison < 0 ? $this->add(new static(1)) : $this; - $bytes = $temp->toBytes(); - - if (!strlen($bytes)) { // eg. if the number we're trying to convert is -1 - $bytes = chr(0); - } - - if (ord($bytes[0]) & 0x80) { - $bytes = chr(0) . $bytes; - } - - return $comparison < 0 ? ~$bytes : $bytes; - } - - /** - * Converts a BigInteger to a hex string (eg. base-16). - * - * @param bool $twos_compliment - * @return string - */ - public function toHex($twos_compliment = false) - { - return Strings::bin2hex($this->toBytes($twos_compliment)); - } - - /** - * Converts a BigInteger to a bit string (eg. base-2). - * - * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're - * saved as two's compliment. - * - * @param bool $twos_compliment - * @return string - */ - public function toBits($twos_compliment = false) - { - $hex = $this->toBytes($twos_compliment); - $bits = Strings::bin2bits($hex); - - $result = $this->precision > 0 ? substr($bits, -$this->precision) : ltrim($bits, '0'); - - if ($twos_compliment && $this->compare(new static()) > 0 && $this->precision <= 0) { - return '0' . $result; - } - - return $result; - } - - /** - * Calculates modular inverses. - * - * Say you have (30 mod 17 * x mod 17) mod 17 == 1. x can be found using modular inverses. - * - * {@internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=21 HAC 14.64} for more information.} - * - * @param Engine $n - * @return static|false - */ - protected function modInverseHelper(Engine $n) - { - // $x mod -$n == $x mod $n. - $n = $n->abs(); - - if ($this->compare(static::$zero[static::class]) < 0) { - $temp = $this->abs(); - $temp = $temp->modInverse($n); - return $this->normalize($n->subtract($temp)); - } - - extract($this->extendedGCD($n)); - /** - * @var Engine $gcd - * @var Engine $x - */ - - if (!$gcd->equals(static::$one[static::class])) { - return false; - } - - $x = $x->compare(static::$zero[static::class]) < 0 ? $x->add($n) : $x; - - return $this->compare(static::$zero[static::class]) < 0 ? $this->normalize($n->subtract($x)) : $this->normalize($x); - } - - /** - * Serialize - * - * Will be called, automatically, when serialize() is called on a BigInteger object. - * - * @return array - */ - public function __sleep() - { - $this->hex = $this->toHex(true); - $vars = ['hex']; - if ($this->precision > 0) { - $vars[] = 'precision'; - } - return $vars; - } - - /** - * Serialize - * - * Will be called, automatically, when unserialize() is called on a BigInteger object. - * - * @return void - */ - public function __wakeup() - { - $temp = new static($this->hex, -16); - $this->value = $temp->value; - $this->is_negative = $temp->is_negative; - if ($this->precision > 0) { - // recalculate $this->bitmask - $this->setPrecision($this->precision); - } - } - - /** - * JSON Serialize - * - * Will be called, automatically, when json_encode() is called on a BigInteger object. - * - * @return array{hex: string, precision?: int] - */ - #[\ReturnTypeWillChange] - public function jsonSerialize() - { - $result = ['hex' => $this->toHex(true)]; - if ($this->precision > 0) { - $result['precision'] = $this->precision; - } - return $result; - } - - /** - * Converts a BigInteger to a base-10 number. - * - * @return string - */ - public function __toString() - { - return $this->toString(); - } - - /** - * __debugInfo() magic method - * - * Will be called, automatically, when print_r() or var_dump() are called - * - * @return array - */ - public function __debugInfo() - { - $result = [ - 'value' => '0x' . $this->toHex(true), - 'engine' => basename(static::class) - ]; - return $this->precision > 0 ? $result + ['precision' => $this->precision] : $result; - } - - /** - * Set Precision - * - * Some bitwise operations give different results depending on the precision being used. Examples include left - * shift, not, and rotates. - * - * @param int $bits - */ - public function setPrecision($bits) - { - if ($bits < 1) { - $this->precision = -1; - $this->bitmask = false; - - return; - } - $this->precision = $bits; - $this->bitmask = static::setBitmask($bits); - - $temp = $this->normalize($this); - $this->value = $temp->value; - } - - /** - * Get Precision - * - * Returns the precision if it exists, -1 if it doesn't - * - * @return int - */ - public function getPrecision() - { - return $this->precision; - } - - /** - * Set Bitmask - * @return static - * @param int $bits - * @see self::setPrecision() - */ - protected static function setBitmask($bits) - { - return new static(chr((1 << ($bits & 0x7)) - 1) . str_repeat(chr(0xFF), $bits >> 3), 256); - } - - /** - * Logical Not - * - * @return Engine|string - */ - public function bitwise_not() - { - // calculuate "not" without regard to $this->precision - // (will always result in a smaller number. ie. ~1 isn't 1111 1110 - it's 0) - $temp = $this->toBytes(); - if ($temp == '') { - return $this->normalize(static::$zero[static::class]); - } - $pre_msb = decbin(ord($temp[0])); - $temp = ~$temp; - $msb = decbin(ord($temp[0])); - if (strlen($msb) == 8) { - $msb = substr($msb, strpos($msb, '0')); - } - $temp[0] = chr(bindec($msb)); - - // see if we need to add extra leading 1's - $current_bits = strlen($pre_msb) + 8 * strlen($temp) - 8; - $new_bits = $this->precision - $current_bits; - if ($new_bits <= 0) { - return $this->normalize(new static($temp, 256)); - } - - // generate as many leading 1's as we need to. - $leading_ones = chr((1 << ($new_bits & 0x7)) - 1) . str_repeat(chr(0xFF), $new_bits >> 3); - - self::base256_lshift($leading_ones, $current_bits); - - $temp = str_pad($temp, strlen($leading_ones), chr(0), STR_PAD_LEFT); - - return $this->normalize(new static($leading_ones | $temp, 256)); - } - - /** - * Logical Left Shift - * - * Shifts binary strings $shift bits, essentially multiplying by 2**$shift. - * - * @param string $x - * @param int $shift - * @return void - */ - protected static function base256_lshift(&$x, $shift) - { - if ($shift == 0) { - return; - } - - $num_bytes = $shift >> 3; // eg. floor($shift/8) - $shift &= 7; // eg. $shift % 8 - - $carry = 0; - for ($i = strlen($x) - 1; $i >= 0; --$i) { - $temp = ord($x[$i]) << $shift | $carry; - $x[$i] = chr($temp); - $carry = $temp >> 8; - } - $carry = ($carry != 0) ? chr($carry) : ''; - $x = $carry . $x . str_repeat(chr(0), $num_bytes); - } - - /** - * Logical Left Rotate - * - * Instead of the top x bits being dropped they're appended to the shifted bit string. - * - * @param int $shift - * @return Engine - */ - public function bitwise_leftRotate($shift) - { - $bits = $this->toBytes(); - - if ($this->precision > 0) { - $precision = $this->precision; - if (static::FAST_BITWISE) { - $mask = $this->bitmask->toBytes(); - } else { - $mask = $this->bitmask->subtract(new static(1)); - $mask = $mask->toBytes(); - } - } else { - $temp = ord($bits[0]); - for ($i = 0; $temp >> $i; ++$i) { - } - $precision = 8 * strlen($bits) - 8 + $i; - $mask = chr((1 << ($precision & 0x7)) - 1) . str_repeat(chr(0xFF), $precision >> 3); - } - - if ($shift < 0) { - $shift += $precision; - } - $shift %= $precision; - - if (!$shift) { - return clone $this; - } - - $left = $this->bitwise_leftShift($shift); - $left = $left->bitwise_and(new static($mask, 256)); - $right = $this->bitwise_rightShift($precision - $shift); - $result = static::FAST_BITWISE ? $left->bitwise_or($right) : $left->add($right); - return $this->normalize($result); - } - - /** - * Logical Right Rotate - * - * Instead of the bottom x bits being dropped they're prepended to the shifted bit string. - * - * @param int $shift - * @return Engine - */ - public function bitwise_rightRotate($shift) - { - return $this->bitwise_leftRotate(-$shift); - } - - /** - * Returns the smallest and largest n-bit number - * - * @param int $bits - * @return array{min: static, max: static} - */ - public static function minMaxBits($bits) - { - $bytes = $bits >> 3; - $min = str_repeat(chr(0), $bytes); - $max = str_repeat(chr(0xFF), $bytes); - $msb = $bits & 7; - if ($msb) { - $min = chr(1 << ($msb - 1)) . $min; - $max = chr((1 << $msb) - 1) . $max; - } else { - $min[0] = chr(0x80); - } - return [ - 'min' => new static($min, 256), - 'max' => new static($max, 256) - ]; - } - - /** - * Return the size of a BigInteger in bits - * - * @return int - */ - public function getLength() - { - return strlen($this->toBits()); - } - - /** - * Return the size of a BigInteger in bytes - * - * @return int - */ - public function getLengthInBytes() - { - return strlen($this->toBytes()); - } - - /** - * Performs some pre-processing for powMod - * - * @param Engine $e - * @param Engine $n - * @return static|false - */ - protected function powModOuter(Engine $e, Engine $n) - { - $n = $this->bitmask !== false && $this->bitmask->compare($n) < 0 ? $this->bitmask : $n->abs(); - - if ($e->compare(new static()) < 0) { - $e = $e->abs(); - - $temp = $this->modInverse($n); - if ($temp === false) { - return false; - } - - return $this->normalize($temp->powModInner($e, $n)); - } - - return $this->powModInner($e, $n); - } - - /** - * Sliding Window k-ary Modular Exponentiation - * - * Based on {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=27 HAC 14.85} / - * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=210 MPM 7.7}. In a departure from those algorithims, - * however, this function performs a modular reduction after every multiplication and squaring operation. - * As such, this function has the same preconditions that the reductions being used do. - * - * @template T of Engine - * @param Engine $x - * @param Engine $e - * @param Engine $n - * @param class-string $class - * @return T - */ - protected static function slidingWindow(Engine $x, Engine $e, Engine $n, $class) - { - static $window_ranges = [7, 25, 81, 241, 673, 1793]; // from BigInteger.java's oddModPow function - //static $window_ranges = [0, 7, 36, 140, 450, 1303, 3529]; // from MPM 7.3.1 - - $e_bits = $e->toBits(); - $e_length = strlen($e_bits); - - // calculate the appropriate window size. - // $window_size == 3 if $window_ranges is between 25 and 81, for example. - for ($i = 0, $window_size = 1; $i < count($window_ranges) && $e_length > $window_ranges[$i]; ++$window_size, ++$i) { - } - - $n_value = $n->value; - - if (method_exists(static::class, 'generateCustomReduction')) { - static::generateCustomReduction($n, $class); - } - - // precompute $this^0 through $this^$window_size - $powers = []; - $powers[1] = static::prepareReduce($x->value, $n_value, $class); - $powers[2] = static::squareReduce($powers[1], $n_value, $class); - - // we do every other number since substr($e_bits, $i, $j+1) (see below) is supposed to end - // in a 1. ie. it's supposed to be odd. - $temp = 1 << ($window_size - 1); - for ($i = 1; $i < $temp; ++$i) { - $i2 = $i << 1; - $powers[$i2 + 1] = static::multiplyReduce($powers[$i2 - 1], $powers[2], $n_value, $class); - } - - $result = new $class(1); - $result = static::prepareReduce($result->value, $n_value, $class); - - for ($i = 0; $i < $e_length;) { - if (!$e_bits[$i]) { - $result = static::squareReduce($result, $n_value, $class); - ++$i; - } else { - for ($j = $window_size - 1; $j > 0; --$j) { - if (!empty($e_bits[$i + $j])) { - break; - } - } - - // eg. the length of substr($e_bits, $i, $j + 1) - for ($k = 0; $k <= $j; ++$k) { - $result = static::squareReduce($result, $n_value, $class); - } - - $result = static::multiplyReduce($result, $powers[bindec(substr($e_bits, $i, $j + 1))], $n_value, $class); - - $i += $j + 1; - } - } - - $temp = new $class(); - $temp->value = static::reduce($result, $n_value, $class); - - return $temp; - } - - /** - * Generates a random number of a certain size - * - * Bit length is equal to $size - * - * @param int $size - * @return Engine - */ - public static function random($size) - { - extract(static::minMaxBits($size)); - /** - * @var BigInteger $min - * @var BigInteger $max - */ - return static::randomRange($min, $max); - } - - /** - * Generates a random prime number of a certain size - * - * Bit length is equal to $size - * - * @param int $size - * @return Engine - */ - public static function randomPrime($size) - { - extract(static::minMaxBits($size)); - /** - * @var static $min - * @var static $max - */ - return static::randomRangePrime($min, $max); - } - - /** - * Performs some pre-processing for randomRangePrime - * - * @param Engine $min - * @param Engine $max - * @return static|false - */ - protected static function randomRangePrimeOuter(Engine $min, Engine $max) - { - $compare = $max->compare($min); - - if (!$compare) { - return $min->isPrime() ? $min : false; - } elseif ($compare < 0) { - // if $min is bigger then $max, swap $min and $max - $temp = $max; - $max = $min; - $min = $temp; - } - - $x = static::randomRange($min, $max); - - return static::randomRangePrimeInner($x, $min, $max); - } - - /** - * Generate a random number between a range - * - * Returns a random number between $min and $max where $min and $max - * can be defined using one of the two methods: - * - * BigInteger::randomRange($min, $max) - * BigInteger::randomRange($max, $min) - * - * @param Engine $min - * @param Engine $max - * @return Engine - */ - protected static function randomRangeHelper(Engine $min, Engine $max) - { - $compare = $max->compare($min); - - if (!$compare) { - return $min; - } elseif ($compare < 0) { - // if $min is bigger then $max, swap $min and $max - $temp = $max; - $max = $min; - $min = $temp; - } - - if (!isset(static::$one[static::class])) { - static::$one[static::class] = new static(1); - } - - $max = $max->subtract($min->subtract(static::$one[static::class])); - - $size = strlen(ltrim($max->toBytes(), chr(0))); - - /* - doing $random % $max doesn't work because some numbers will be more likely to occur than others. - eg. if $max is 140 and $random's max is 255 then that'd mean both $random = 5 and $random = 145 - would produce 5 whereas the only value of random that could produce 139 would be 139. ie. - not all numbers would be equally likely. some would be more likely than others. - - creating a whole new random number until you find one that is within the range doesn't work - because, for sufficiently small ranges, the likelihood that you'd get a number within that range - would be pretty small. eg. with $random's max being 255 and if your $max being 1 the probability - would be pretty high that $random would be greater than $max. - - phpseclib works around this using the technique described here: - - http://crypto.stackexchange.com/questions/5708/creating-a-small-number-from-a-cryptographically-secure-random-string - */ - $random_max = new static(chr(1) . str_repeat("\0", $size), 256); - $random = new static(Random::string($size), 256); - - list($max_multiple) = $random_max->divide($max); - $max_multiple = $max_multiple->multiply($max); - - while ($random->compare($max_multiple) >= 0) { - $random = $random->subtract($max_multiple); - $random_max = $random_max->subtract($max_multiple); - $random = $random->bitwise_leftShift(8); - $random = $random->add(new static(Random::string(1), 256)); - $random_max = $random_max->bitwise_leftShift(8); - list($max_multiple) = $random_max->divide($max); - $max_multiple = $max_multiple->multiply($max); - } - list(, $random) = $random->divide($max); - - return $random->add($min); - } - - /** - * Performs some post-processing for randomRangePrime - * - * @param Engine $x - * @param Engine $min - * @param Engine $max - * @return static|false - */ - protected static function randomRangePrimeInner(Engine $x, Engine $min, Engine $max) - { - if (!isset(static::$two[static::class])) { - static::$two[static::class] = new static('2'); - } - - $x->make_odd(); - if ($x->compare($max) > 0) { - // if $x > $max then $max is even and if $min == $max then no prime number exists between the specified range - if ($min->equals($max)) { - return false; - } - $x = clone $min; - $x->make_odd(); - } - - $initial_x = clone $x; - - while (true) { - if ($x->isPrime()) { - return $x; - } - - $x = $x->add(static::$two[static::class]); - - if ($x->compare($max) > 0) { - $x = clone $min; - if ($x->equals(static::$two[static::class])) { - return $x; - } - $x->make_odd(); - } - - if ($x->equals($initial_x)) { - return false; - } - } - } - - /** - * Sets the $t parameter for primality testing - * - * @return int - */ - protected function setupIsPrime() - { - $length = $this->getLengthInBytes(); - - // see HAC 4.49 "Note (controlling the error probability)" - // @codingStandardsIgnoreStart - if ($length >= 163) { $t = 2; } // floor(1300 / 8) - else if ($length >= 106) { $t = 3; } // floor( 850 / 8) - else if ($length >= 81 ) { $t = 4; } // floor( 650 / 8) - else if ($length >= 68 ) { $t = 5; } // floor( 550 / 8) - else if ($length >= 56 ) { $t = 6; } // floor( 450 / 8) - else if ($length >= 50 ) { $t = 7; } // floor( 400 / 8) - else if ($length >= 43 ) { $t = 8; } // floor( 350 / 8) - else if ($length >= 37 ) { $t = 9; } // floor( 300 / 8) - else if ($length >= 31 ) { $t = 12; } // floor( 250 / 8) - else if ($length >= 25 ) { $t = 15; } // floor( 200 / 8) - else if ($length >= 18 ) { $t = 18; } // floor( 150 / 8) - else { $t = 27; } - // @codingStandardsIgnoreEnd - - return $t; - } - - /** - * Tests Primality - * - * Uses the {@link http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test Miller-Rabin primality test}. - * See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=8 HAC 4.24} for more info. - * - * @param int $t - * @return bool - */ - protected function testPrimality($t) - { - if (!$this->testSmallPrimes()) { - return false; - } - - $n = clone $this; - $n_1 = $n->subtract(static::$one[static::class]); - $n_2 = $n->subtract(static::$two[static::class]); - - $r = clone $n_1; - $s = static::scan1divide($r); - - for ($i = 0; $i < $t; ++$i) { - $a = static::randomRange(static::$two[static::class], $n_2); - $y = $a->modPow($r, $n); - - if (!$y->equals(static::$one[static::class]) && !$y->equals($n_1)) { - for ($j = 1; $j < $s && !$y->equals($n_1); ++$j) { - $y = $y->modPow(static::$two[static::class], $n); - if ($y->equals(static::$one[static::class])) { - return false; - } - } - - if (!$y->equals($n_1)) { - return false; - } - } - } - - return true; - } - - /** - * Checks a numer to see if it's prime - * - * Assuming the $t parameter is not set, this function has an error rate of 2**-80. The main motivation for the - * $t parameter is distributability. BigInteger::randomPrime() can be distributed across multiple pageloads - * on a website instead of just one. - * - * @param int|bool $t - * @return bool - */ - public function isPrime($t = false) - { - if (!$t) { - $t = $this->setupIsPrime(); - } - return $this->testPrimality($t); - } - - /** - * Performs a few preliminary checks on root - * - * @param int $n - * @return Engine - */ - protected function rootHelper($n) - { - if ($n < 1) { - return clone static::$zero[static::class]; - } // we want positive exponents - if ($this->compare(static::$one[static::class]) < 0) { - return clone static::$zero[static::class]; - } // we want positive numbers - if ($this->compare(static::$two[static::class]) < 0) { - return clone static::$one[static::class]; - } // n-th root of 1 or 2 is 1 - - return $this->rootInner($n); - } - - /** - * Calculates the nth root of a biginteger. - * - * Returns the nth root of a positive biginteger, where n defaults to 2 - * - * {@internal This function is based off of {@link http://mathforum.org/library/drmath/view/52605.html this page} and {@link http://stackoverflow.com/questions/11242920/calculating-nth-root-with-bcmath-in-php this stackoverflow question}.} - * - * @param int $n - * @return Engine - */ - protected function rootInner($n) - { - $n = new static($n); - - // g is our guess number - $g = static::$two[static::class]; - // while (g^n < num) g=g*2 - while ($g->pow($n)->compare($this) < 0) { - $g = $g->multiply(static::$two[static::class]); - } - // if (g^n==num) num is a power of 2, we're lucky, end of job - // == 0 bccomp(bcpow($g, $n), $n->value)==0 - if ($g->pow($n)->equals($this) > 0) { - $root = $g; - return $this->normalize($root); - } - - // if we're here num wasn't a power of 2 :( - $og = $g; // og means original guess and here is our upper bound - $g = $g->divide(static::$two[static::class])[0]; // g is set to be our lower bound - $step = $og->subtract($g)->divide(static::$two[static::class])[0]; // step is the half of upper bound - lower bound - $g = $g->add($step); // we start at lower bound + step , basically in the middle of our interval - - // while step>1 - - while ($step->compare(static::$one[static::class]) == 1) { - $guess = $g->pow($n); - $step = $step->divide(static::$two[static::class])[0]; - $comp = $guess->compare($this); // compare our guess with real number - switch ($comp) { - case -1: // if guess is lower we add the new step - $g = $g->add($step); - break; - case 1: // if guess is higher we sub the new step - $g = $g->subtract($step); - break; - case 0: // if guess is exactly the num we're done, we return the value - $root = $g; - break 2; - } - } - - if ($comp == 1) { - $g = $g->subtract($step); - } - - // whatever happened, g is the closest guess we can make so return it - $root = $g; - - return $this->normalize($root); - } - - /** - * Calculates the nth root of a biginteger. - * - * @param int $n - * @return Engine - */ - public function root($n = 2) - { - return $this->rootHelper($n); - } - - /** - * Return the minimum BigInteger between an arbitrary number of BigIntegers. - * - * @param array $nums - * @return Engine - */ - protected static function minHelper(array $nums) - { - if (count($nums) == 1) { - return $nums[0]; - } - $min = $nums[0]; - for ($i = 1; $i < count($nums); $i++) { - $min = $min->compare($nums[$i]) > 0 ? $nums[$i] : $min; - } - return $min; - } - - /** - * Return the minimum BigInteger between an arbitrary number of BigIntegers. - * - * @param array $nums - * @return Engine - */ - protected static function maxHelper(array $nums) - { - if (count($nums) == 1) { - return $nums[0]; - } - $max = $nums[0]; - for ($i = 1; $i < count($nums); $i++) { - $max = $max->compare($nums[$i]) < 0 ? $nums[$i] : $max; - } - return $max; - } - - /** - * Create Recurring Modulo Function - * - * Sometimes it may be desirable to do repeated modulos with the same number outside of - * modular exponentiation - * - * @return callable - */ - public function createRecurringModuloFunction() - { - $class = static::class; - - $fqengine = !method_exists(static::$modexpEngine[static::class], 'reduce') ? - '\\phpseclib3\\Math\\BigInteger\\Engines\\' . static::ENGINE_DIR . '\\DefaultEngine' : - static::$modexpEngine[static::class]; - if (method_exists($fqengine, 'generateCustomReduction')) { - $func = $fqengine::generateCustomReduction($this, static::class); - return eval('return function(' . static::class . ' $x) use ($func, $class) { - $r = new $class(); - $r->value = $func($x->value); - return $r; - };'); - } - $n = $this->value; - return eval('return function(' . static::class . ' $x) use ($n, $fqengine, $class) { - $r = new $class(); - $r->value = $fqengine::reduce($x->value, $n, $class); - return $r; - };'); - } - - /** - * Calculates the greatest common divisor and Bezout's identity. - * - * @param Engine $n - * @return array{gcd: Engine, x: Engine, y: Engine} - */ - protected function extendedGCDHelper(Engine $n) - { - $u = clone $this; - $v = clone $n; - - $one = new static(1); - $zero = new static(); - - $a = clone $one; - $b = clone $zero; - $c = clone $zero; - $d = clone $one; - - while (!$v->equals($zero)) { - list($q) = $u->divide($v); - - $temp = $u; - $u = $v; - $v = $temp->subtract($v->multiply($q)); - - $temp = $a; - $a = $c; - $c = $temp->subtract($a->multiply($q)); - - $temp = $b; - $b = $d; - $d = $temp->subtract($b->multiply($q)); - } - - return [ - 'gcd' => $u, - 'x' => $a, - 'y' => $b - ]; - } - - /** - * Bitwise Split - * - * Splits BigInteger's into chunks of $split bits - * - * @param int $split - * @return Engine[] - */ - public function bitwise_split($split) - { - if ($split < 1) { - throw new \RuntimeException('Offset must be greater than 1'); - } - - $mask = static::$one[static::class]->bitwise_leftShift($split)->subtract(static::$one[static::class]); - - $num = clone $this; - - $vals = []; - while (!$num->equals(static::$zero[static::class])) { - $vals[] = $num->bitwise_and($mask); - $num = $num->bitwise_rightShift($split); - } - - return array_reverse($vals); - } - - /** - * Logical And - * - * @param Engine $x - * @return Engine - */ - protected function bitwiseAndHelper(Engine $x) - { - $left = $this->toBytes(true); - $right = $x->toBytes(true); - - $length = max(strlen($left), strlen($right)); - - $left = str_pad($left, $length, chr(0), STR_PAD_LEFT); - $right = str_pad($right, $length, chr(0), STR_PAD_LEFT); - - return $this->normalize(new static($left & $right, -256)); - } - - /** - * Logical Or - * - * @param Engine $x - * @return Engine - */ - protected function bitwiseOrHelper(Engine $x) - { - $left = $this->toBytes(true); - $right = $x->toBytes(true); - - $length = max(strlen($left), strlen($right)); - - $left = str_pad($left, $length, chr(0), STR_PAD_LEFT); - $right = str_pad($right, $length, chr(0), STR_PAD_LEFT); - - return $this->normalize(new static($left | $right, -256)); - } - - /** - * Logical Exclusive Or - * - * @param Engine $x - * @return Engine - */ - protected function bitwiseXorHelper(Engine $x) - { - $left = $this->toBytes(true); - $right = $x->toBytes(true); - - $length = max(strlen($left), strlen($right)); - - - $left = str_pad($left, $length, chr(0), STR_PAD_LEFT); - $right = str_pad($right, $length, chr(0), STR_PAD_LEFT); - return $this->normalize(new static($left ^ $right, -256)); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/GMP.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/GMP.php deleted file mode 100644 index f6163629..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/GMP.php +++ /dev/null @@ -1,694 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines; - -use phpseclib3\Exception\BadConfigurationException; - -/** - * GMP Engine. - * - * @author Jim Wigginton - */ -class GMP extends Engine -{ - /** - * Can Bitwise operations be done fast? - * - * @see parent::bitwise_leftRotate() - * @see parent::bitwise_rightRotate() - */ - const FAST_BITWISE = true; - - /** - * Engine Directory - * - * @see parent::setModExpEngine - */ - const ENGINE_DIR = 'GMP'; - - /** - * Test for engine validity - * - * @return bool - * @see parent::__construct() - */ - public static function isValidEngine() - { - return extension_loaded('gmp'); - } - - /** - * Default constructor - * - * @param mixed $x integer Base-10 number or base-$base number if $base set. - * @param int $base - * @see parent::__construct() - */ - public function __construct($x = 0, $base = 10) - { - if (!isset(static::$isValidEngine[static::class])) { - static::$isValidEngine[static::class] = self::isValidEngine(); - } - if (!static::$isValidEngine[static::class]) { - throw new BadConfigurationException('GMP is not setup correctly on this system'); - } - - if ($x instanceof \GMP) { - $this->value = $x; - return; - } - - $this->value = gmp_init(0); - - parent::__construct($x, $base); - } - - /** - * Initialize a GMP BigInteger Engine instance - * - * @param int $base - * @see parent::__construct() - */ - protected function initialize($base) - { - switch (abs($base)) { - case 256: - $this->value = gmp_import($this->value); - if ($this->is_negative) { - $this->value = -$this->value; - } - break; - case 16: - $temp = $this->is_negative ? '-0x' . $this->value : '0x' . $this->value; - $this->value = gmp_init($temp); - break; - case 10: - $this->value = gmp_init(isset($this->value) ? $this->value : '0'); - } - } - - /** - * Converts a BigInteger to a base-10 number. - * - * @return string - */ - public function toString() - { - return (string)$this->value; - } - - /** - * Converts a BigInteger to a bit string (eg. base-2). - * - * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're - * saved as two's compliment. - * - * @param bool $twos_compliment - * @return string - */ - public function toBits($twos_compliment = false) - { - $hex = $this->toHex($twos_compliment); - - $bits = gmp_strval(gmp_init($hex, 16), 2); - - if ($this->precision > 0) { - $bits = substr($bits, -$this->precision); - } - - if ($twos_compliment && $this->compare(new static()) > 0 && $this->precision <= 0) { - return '0' . $bits; - } - - return $bits; - } - - /** - * Converts a BigInteger to a byte string (eg. base-256). - * - * @param bool $twos_compliment - * @return string - */ - public function toBytes($twos_compliment = false) - { - if ($twos_compliment) { - return $this->toBytesHelper(); - } - - if (gmp_cmp($this->value, gmp_init(0)) == 0) { - return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; - } - - $temp = gmp_export($this->value); - - return $this->precision > 0 ? - substr(str_pad($temp, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) : - ltrim($temp, chr(0)); - } - - /** - * Adds two BigIntegers. - * - * @param GMP $y - * @return GMP - */ - public function add(GMP $y) - { - $temp = new self(); - $temp->value = $this->value + $y->value; - - return $this->normalize($temp); - } - - /** - * Subtracts two BigIntegers. - * - * @param GMP $y - * @return GMP - */ - public function subtract(GMP $y) - { - $temp = new self(); - $temp->value = $this->value - $y->value; - - return $this->normalize($temp); - } - - /** - * Multiplies two BigIntegers. - * - * @param GMP $x - * @return GMP - */ - public function multiply(GMP $x) - { - $temp = new self(); - $temp->value = $this->value * $x->value; - - return $this->normalize($temp); - } - - /** - * Divides two BigIntegers. - * - * Returns an array whose first element contains the quotient and whose second element contains the - * "common residue". If the remainder would be positive, the "common residue" and the remainder are the - * same. If the remainder would be negative, the "common residue" is equal to the sum of the remainder - * and the divisor (basically, the "common residue" is the first positive modulo). - * - * @param GMP $y - * @return array{GMP, GMP} - */ - public function divide(GMP $y) - { - $quotient = new self(); - $remainder = new self(); - - list($quotient->value, $remainder->value) = gmp_div_qr($this->value, $y->value); - - if (gmp_sign($remainder->value) < 0) { - $remainder->value = $remainder->value + gmp_abs($y->value); - } - - return [$this->normalize($quotient), $this->normalize($remainder)]; - } - - /** - * Compares two numbers. - * - * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite. The reason for this - * is demonstrated thusly: - * - * $x > $y: $x->compare($y) > 0 - * $x < $y: $x->compare($y) < 0 - * $x == $y: $x->compare($y) == 0 - * - * Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y). - * - * {@internal Could return $this->subtract($x), but that's not as fast as what we do do.} - * - * @param GMP $y - * @return int in case < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal. - * @see self::equals() - */ - public function compare(GMP $y) - { - $r = gmp_cmp($this->value, $y->value); - if ($r < -1) { - $r = -1; - } - if ($r > 1) { - $r = 1; - } - return $r; - } - - /** - * Tests the equality of two numbers. - * - * If you need to see if one number is greater than or less than another number, use BigInteger::compare() - * - * @param GMP $x - * @return bool - */ - public function equals(GMP $x) - { - return $this->value == $x->value; - } - - /** - * Calculates modular inverses. - * - * Say you have (30 mod 17 * x mod 17) mod 17 == 1. x can be found using modular inverses. - * - * @param GMP $n - * @return false|GMP - */ - public function modInverse(GMP $n) - { - $temp = new self(); - $temp->value = gmp_invert($this->value, $n->value); - - return $temp->value === false ? false : $this->normalize($temp); - } - - /** - * Calculates the greatest common divisor and Bezout's identity. - * - * Say you have 693 and 609. The GCD is 21. Bezout's identity states that there exist integers x and y such that - * 693*x + 609*y == 21. In point of fact, there are actually an infinite number of x and y combinations and which - * combination is returned is dependent upon which mode is in use. See - * {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bezout's identity - Wikipedia} for more information. - * - * @param GMP $n - * @return GMP[] - */ - public function extendedGCD(GMP $n) - { - extract(gmp_gcdext($this->value, $n->value)); - - return [ - 'gcd' => $this->normalize(new self($g)), - 'x' => $this->normalize(new self($s)), - 'y' => $this->normalize(new self($t)) - ]; - } - - /** - * Calculates the greatest common divisor - * - * Say you have 693 and 609. The GCD is 21. - * - * @param GMP $n - * @return GMP - */ - public function gcd(GMP $n) - { - $r = gmp_gcd($this->value, $n->value); - return $this->normalize(new self($r)); - } - - /** - * Absolute value. - * - * @return GMP - */ - public function abs() - { - $temp = new self(); - $temp->value = gmp_abs($this->value); - - return $temp; - } - - /** - * Logical And - * - * @param GMP $x - * @return GMP - */ - public function bitwise_and(GMP $x) - { - $temp = new self(); - $temp->value = $this->value & $x->value; - - return $this->normalize($temp); - } - - /** - * Logical Or - * - * @param GMP $x - * @return GMP - */ - public function bitwise_or(GMP $x) - { - $temp = new self(); - $temp->value = $this->value | $x->value; - - return $this->normalize($temp); - } - - /** - * Logical Exclusive Or - * - * @param GMP $x - * @return GMP - */ - public function bitwise_xor(GMP $x) - { - $temp = new self(); - $temp->value = $this->value ^ $x->value; - - return $this->normalize($temp); - } - - /** - * Logical Right Shift - * - * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift. - * - * @param int $shift - * @return GMP - */ - public function bitwise_rightShift($shift) - { - // 0xFFFFFFFF >> 2 == -1 (on 32-bit systems) - // gmp_init('0xFFFFFFFF') >> 2 == gmp_init('0x3FFFFFFF') - - $temp = new self(); - $temp->value = $this->value >> $shift; - - return $this->normalize($temp); - } - - /** - * Logical Left Shift - * - * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift. - * - * @param int $shift - * @return GMP - */ - public function bitwise_leftShift($shift) - { - $temp = new self(); - $temp->value = $this->value << $shift; - - return $this->normalize($temp); - } - - /** - * Performs modular exponentiation. - * - * @param GMP $e - * @param GMP $n - * @return GMP - */ - public function modPow(GMP $e, GMP $n) - { - return $this->powModOuter($e, $n); - } - - /** - * Performs modular exponentiation. - * - * Alias for modPow(). - * - * @param GMP $e - * @param GMP $n - * @return GMP - */ - public function powMod(GMP $e, GMP $n) - { - return $this->powModOuter($e, $n); - } - - /** - * Performs modular exponentiation. - * - * @param GMP $e - * @param GMP $n - * @return GMP - */ - protected function powModInner(GMP $e, GMP $n) - { - $class = static::$modexpEngine[static::class]; - return $class::powModHelper($this, $e, $n); - } - - /** - * Normalize - * - * Removes leading zeros and truncates (if necessary) to maintain the appropriate precision - * - * @param GMP $result - * @return GMP - */ - protected function normalize(GMP $result) - { - $result->precision = $this->precision; - $result->bitmask = $this->bitmask; - - if ($result->bitmask !== false) { - $flip = $result->value < 0; - if ($flip) { - $result->value = -$result->value; - } - $result->value = $result->value & $result->bitmask->value; - if ($flip) { - $result->value = -$result->value; - } - } - - return $result; - } - - /** - * Performs some post-processing for randomRangePrime - * - * @param Engine $x - * @param Engine $min - * @param Engine $max - * @return GMP - */ - protected static function randomRangePrimeInner(Engine $x, Engine $min, Engine $max) - { - $p = gmp_nextprime($x->value); - - if ($p <= $max->value) { - return new self($p); - } - - if ($min->value != $x->value) { - $x = new self($x->value - 1); - } - - return self::randomRangePrime($min, $x); - } - - /** - * Generate a random prime number between a range - * - * If there's not a prime within the given range, false will be returned. - * - * @param GMP $min - * @param GMP $max - * @return false|GMP - */ - public static function randomRangePrime(GMP $min, GMP $max) - { - return self::randomRangePrimeOuter($min, $max); - } - - /** - * Generate a random number between a range - * - * Returns a random number between $min and $max where $min and $max - * can be defined using one of the two methods: - * - * BigInteger::randomRange($min, $max) - * BigInteger::randomRange($max, $min) - * - * @param GMP $min - * @param GMP $max - * @return GMP - */ - public static function randomRange(GMP $min, GMP $max) - { - return self::randomRangeHelper($min, $max); - } - - /** - * Make the current number odd - * - * If the current number is odd it'll be unchanged. If it's even, one will be added to it. - * - * @see self::randomPrime() - */ - protected function make_odd() - { - gmp_setbit($this->value, 0); - } - - /** - * Tests Primality - * - * @param int $t - * @return bool - */ - protected function testPrimality($t) - { - return gmp_prob_prime($this->value, $t) != 0; - } - - /** - * Calculates the nth root of a biginteger. - * - * Returns the nth root of a positive biginteger, where n defaults to 2 - * - * @param int $n - * @return GMP - */ - protected function rootInner($n) - { - $root = new self(); - $root->value = gmp_root($this->value, $n); - return $this->normalize($root); - } - - /** - * Performs exponentiation. - * - * @param GMP $n - * @return GMP - */ - public function pow(GMP $n) - { - $temp = new self(); - $temp->value = $this->value ** $n->value; - - return $this->normalize($temp); - } - - /** - * Return the minimum BigInteger between an arbitrary number of BigIntegers. - * - * @param GMP ...$nums - * @return GMP - */ - public static function min(GMP ...$nums) - { - return self::minHelper($nums); - } - - /** - * Return the maximum BigInteger between an arbitrary number of BigIntegers. - * - * @param GMP ...$nums - * @return GMP - */ - public static function max(GMP ...$nums) - { - return self::maxHelper($nums); - } - - /** - * Tests BigInteger to see if it is between two integers, inclusive - * - * @param GMP $min - * @param GMP $max - * @return bool - */ - public function between(GMP $min, GMP $max) - { - return $this->compare($min) >= 0 && $this->compare($max) <= 0; - } - - /** - * Create Recurring Modulo Function - * - * Sometimes it may be desirable to do repeated modulos with the same number outside of - * modular exponentiation - * - * @return callable - */ - public function createRecurringModuloFunction() - { - $temp = $this->value; - return function (GMP $x) use ($temp) { - return new GMP($x->value % $temp); - }; - } - - /** - * Scan for 1 and right shift by that amount - * - * ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s)); - * - * @param GMP $r - * @return int - */ - public static function scan1divide(GMP $r) - { - $s = gmp_scan1($r->value, 0); - $r->value >>= $s; - return $s; - } - - /** - * Is Odd? - * - * @return bool - */ - public function isOdd() - { - return gmp_testbit($this->value, 0); - } - - /** - * Tests if a bit is set - * - * @return bool - */ - public function testBit($x) - { - return gmp_testbit($this->value, $x); - } - - /** - * Is Negative? - * - * @return bool - */ - public function isNegative() - { - return gmp_sign($this->value) == -1; - } - - /** - * Negate - * - * Given $k, returns -$k - * - * @return GMP - */ - public function negate() - { - $temp = clone $this; - $temp->value = -$this->value; - - return $temp; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/GMP/DefaultEngine.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/GMP/DefaultEngine.php deleted file mode 100644 index bc219fbe..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/GMP/DefaultEngine.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines\GMP; - -use phpseclib3\Math\BigInteger\Engines\GMP; - -/** - * GMP Modular Exponentiation Engine - * - * @author Jim Wigginton - */ -abstract class DefaultEngine extends GMP -{ - /** - * Performs modular exponentiation. - * - * @param GMP $x - * @param GMP $e - * @param GMP $n - * @return GMP - */ - protected static function powModHelper(GMP $x, GMP $e, GMP $n) - { - $temp = new GMP(); - $temp->value = gmp_powm($x->value, $e->value, $n->value); - - return $x->normalize($temp); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/OpenSSL.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/OpenSSL.php deleted file mode 100644 index e33a9f19..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/OpenSSL.php +++ /dev/null @@ -1,68 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines; - -use phpseclib3\Crypt\RSA\Formats\Keys\PKCS8; -use phpseclib3\Math\BigInteger; - -/** - * OpenSSL Modular Exponentiation Engine - * - * @author Jim Wigginton - */ -abstract class OpenSSL -{ - /** - * Test for engine validity - * - * @return bool - */ - public static function isValidEngine() - { - return extension_loaded('openssl') && static::class != __CLASS__; - } - - /** - * Performs modular exponentiation. - * - * @param Engine $x - * @param Engine $e - * @param Engine $n - * @return Engine - */ - public static function powModHelper(Engine $x, Engine $e, Engine $n) - { - if ($n->getLengthInBytes() < 31 || $n->getLengthInBytes() > 16384) { - throw new \OutOfRangeException('Only modulo between 31 and 16384 bits are accepted'); - } - - $key = PKCS8::savePublicKey( - new BigInteger($n), - new BigInteger($e) - ); - - $plaintext = str_pad($x->toBytes(), $n->getLengthInBytes(), "\0", STR_PAD_LEFT); - - // this is easily prone to failure. if the modulo is a multiple of 2 or 3 or whatever it - // won't work and you'll get a "failure: error:0906D06C:PEM routines:PEM_read_bio:no start line" - // error. i suppose, for even numbers, we could do what PHP\Montgomery.php does, but then what - // about odd numbers divisible by 3, by 5, etc? - if (!openssl_public_encrypt($plaintext, $result, $key, OPENSSL_NO_PADDING)) { - throw new \UnexpectedValueException(openssl_error_string()); - } - - $class = get_class($x); - return new $class($result, 256); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP.php deleted file mode 100644 index ab9bdc99..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP.php +++ /dev/null @@ -1,1329 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Exception\BadConfigurationException; - -/** - * Pure-PHP Engine. - * - * @author Jim Wigginton - */ -abstract class PHP extends Engine -{ - /**#@+ - * Array constants - * - * Rather than create a thousands and thousands of new BigInteger objects in repeated function calls to add() and - * multiply() or whatever, we'll just work directly on arrays, taking them in as parameters and returning them. - * - */ - /** - * $result[self::VALUE] contains the value. - */ - const VALUE = 0; - /** - * $result[self::SIGN] contains the sign. - */ - const SIGN = 1; - /**#@-*/ - - /** - * Karatsuba Cutoff - * - * At what point do we switch between Karatsuba multiplication and schoolbook long multiplication? - * - */ - const KARATSUBA_CUTOFF = 25; - - /** - * Can Bitwise operations be done fast? - * - * @see parent::bitwise_leftRotate() - * @see parent::bitwise_rightRotate() - */ - const FAST_BITWISE = true; - - /** - * Engine Directory - * - * @see parent::setModExpEngine - */ - const ENGINE_DIR = 'PHP'; - - /** - * Default constructor - * - * @param mixed $x integer Base-10 number or base-$base number if $base set. - * @param int $base - * @return PHP - * @see parent::__construct() - */ - public function __construct($x = 0, $base = 10) - { - if (!isset(static::$isValidEngine[static::class])) { - static::$isValidEngine[static::class] = static::isValidEngine(); - } - if (!static::$isValidEngine[static::class]) { - throw new BadConfigurationException(static::class . ' is not setup correctly on this system'); - } - - $this->value = []; - parent::__construct($x, $base); - } - - /** - * Initialize a PHP BigInteger Engine instance - * - * @param int $base - * @see parent::__construct() - */ - protected function initialize($base) - { - switch (abs($base)) { - case 16: - $x = (strlen($this->value) & 1) ? '0' . $this->value : $this->value; - $temp = new static(Strings::hex2bin($x), 256); - $this->value = $temp->value; - break; - case 10: - $temp = new static(); - - $multiplier = new static(); - $multiplier->value = [static::MAX10]; - - $x = $this->value; - - if ($x[0] == '-') { - $this->is_negative = true; - $x = substr($x, 1); - } - - $x = str_pad( - $x, - strlen($x) + ((static::MAX10LEN - 1) * strlen($x)) % static::MAX10LEN, - 0, - STR_PAD_LEFT - ); - while (strlen($x)) { - $temp = $temp->multiply($multiplier); - $temp = $temp->add(new static($this->int2bytes(substr($x, 0, static::MAX10LEN)), 256)); - $x = substr($x, static::MAX10LEN); - } - - $this->value = $temp->value; - } - } - - /** - * Pads strings so that unpack may be used on them - * - * @param string $str - * @return string - */ - protected function pad($str) - { - $length = strlen($str); - - $pad = 4 - (strlen($str) % 4); - - return str_pad($str, $length + $pad, "\0", STR_PAD_LEFT); - } - - /** - * Converts a BigInteger to a base-10 number. - * - * @return string - */ - public function toString() - { - if (!count($this->value)) { - return '0'; - } - - $temp = clone $this; - $temp->bitmask = false; - $temp->is_negative = false; - - $divisor = new static(); - $divisor->value = [static::MAX10]; - $result = ''; - while (count($temp->value)) { - list($temp, $mod) = $temp->divide($divisor); - $result = str_pad( - isset($mod->value[0]) ? $mod->value[0] : '', - static::MAX10LEN, - '0', - STR_PAD_LEFT - ) . $result; - } - $result = ltrim($result, '0'); - if (empty($result)) { - $result = '0'; - } - - if ($this->is_negative) { - $result = '-' . $result; - } - - return $result; - } - - /** - * Converts a BigInteger to a byte string (eg. base-256). - * - * @param bool $twos_compliment - * @return string - */ - public function toBytes($twos_compliment = false) - { - if ($twos_compliment) { - return $this->toBytesHelper(); - } - - if (!count($this->value)) { - return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; - } - - $result = $this->bitwise_small_split(8); - $result = implode('', array_map('chr', $result)); - - return $this->precision > 0 ? - str_pad( - substr($result, -(($this->precision + 7) >> 3)), - ($this->precision + 7) >> 3, - chr(0), - STR_PAD_LEFT - ) : - $result; - } - - /** - * Performs addition. - * - * @param array $x_value - * @param bool $x_negative - * @param array $y_value - * @param bool $y_negative - * @return array - */ - protected static function addHelper(array $x_value, $x_negative, array $y_value, $y_negative) - { - $x_size = count($x_value); - $y_size = count($y_value); - - if ($x_size == 0) { - return [ - self::VALUE => $y_value, - self::SIGN => $y_negative - ]; - } elseif ($y_size == 0) { - return [ - self::VALUE => $x_value, - self::SIGN => $x_negative - ]; - } - - // subtract, if appropriate - if ($x_negative != $y_negative) { - if ($x_value == $y_value) { - return [ - self::VALUE => [], - self::SIGN => false - ]; - } - - $temp = self::subtractHelper($x_value, false, $y_value, false); - $temp[self::SIGN] = self::compareHelper($x_value, false, $y_value, false) > 0 ? - $x_negative : $y_negative; - - return $temp; - } - - if ($x_size < $y_size) { - $size = $x_size; - $value = $y_value; - } else { - $size = $y_size; - $value = $x_value; - } - - $value[count($value)] = 0; // just in case the carry adds an extra digit - - $carry = 0; - for ($i = 0, $j = 1; $j < $size; $i += 2, $j += 2) { - //$sum = $x_value[$j] * static::BASE_FULL + $x_value[$i] + $y_value[$j] * static::BASE_FULL + $y_value[$i] + $carry; - $sum = ($x_value[$j] + $y_value[$j]) * static::BASE_FULL + $x_value[$i] + $y_value[$i] + $carry; - $carry = $sum >= static::MAX_DIGIT2; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1 - $sum = $carry ? $sum - static::MAX_DIGIT2 : $sum; - - $temp = static::BASE === 26 ? intval($sum / 0x4000000) : ($sum >> 31); - - $value[$i] = (int)($sum - static::BASE_FULL * $temp); // eg. a faster alternative to fmod($sum, 0x4000000) - $value[$j] = $temp; - } - - if ($j == $size) { // ie. if $y_size is odd - $sum = $x_value[$i] + $y_value[$i] + $carry; - $carry = $sum >= static::BASE_FULL; - $value[$i] = $carry ? $sum - static::BASE_FULL : $sum; - ++$i; // ie. let $i = $j since we've just done $value[$i] - } - - if ($carry) { - for (; $value[$i] == static::MAX_DIGIT; ++$i) { - $value[$i] = 0; - } - ++$value[$i]; - } - - return [ - self::VALUE => self::trim($value), - self::SIGN => $x_negative - ]; - } - - /** - * Performs subtraction. - * - * @param array $x_value - * @param bool $x_negative - * @param array $y_value - * @param bool $y_negative - * @return array - */ - public static function subtractHelper(array $x_value, $x_negative, array $y_value, $y_negative) - { - $x_size = count($x_value); - $y_size = count($y_value); - - if ($x_size == 0) { - return [ - self::VALUE => $y_value, - self::SIGN => !$y_negative - ]; - } elseif ($y_size == 0) { - return [ - self::VALUE => $x_value, - self::SIGN => $x_negative - ]; - } - - // add, if appropriate (ie. -$x - +$y or +$x - -$y) - if ($x_negative != $y_negative) { - $temp = self::addHelper($x_value, false, $y_value, false); - $temp[self::SIGN] = $x_negative; - - return $temp; - } - - $diff = self::compareHelper($x_value, $x_negative, $y_value, $y_negative); - - if (!$diff) { - return [ - self::VALUE => [], - self::SIGN => false - ]; - } - - // switch $x and $y around, if appropriate. - if ((!$x_negative && $diff < 0) || ($x_negative && $diff > 0)) { - $temp = $x_value; - $x_value = $y_value; - $y_value = $temp; - - $x_negative = !$x_negative; - - $x_size = count($x_value); - $y_size = count($y_value); - } - - // at this point, $x_value should be at least as big as - if not bigger than - $y_value - - $carry = 0; - for ($i = 0, $j = 1; $j < $y_size; $i += 2, $j += 2) { - $sum = ($x_value[$j] - $y_value[$j]) * static::BASE_FULL + $x_value[$i] - $y_value[$i] - $carry; - - $carry = $sum < 0; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1 - $sum = $carry ? $sum + static::MAX_DIGIT2 : $sum; - - $temp = static::BASE === 26 ? intval($sum / 0x4000000) : ($sum >> 31); - - $x_value[$i] = (int)($sum - static::BASE_FULL * $temp); - $x_value[$j] = $temp; - } - - if ($j == $y_size) { // ie. if $y_size is odd - $sum = $x_value[$i] - $y_value[$i] - $carry; - $carry = $sum < 0; - $x_value[$i] = $carry ? $sum + static::BASE_FULL : $sum; - ++$i; - } - - if ($carry) { - for (; !$x_value[$i]; ++$i) { - $x_value[$i] = static::MAX_DIGIT; - } - --$x_value[$i]; - } - - return [ - self::VALUE => self::trim($x_value), - self::SIGN => $x_negative - ]; - } - - /** - * Performs multiplication. - * - * @param array $x_value - * @param bool $x_negative - * @param array $y_value - * @param bool $y_negative - * @return array - */ - protected static function multiplyHelper(array $x_value, $x_negative, array $y_value, $y_negative) - { - //if ( $x_value == $y_value ) { - // return [ - // self::VALUE => self::square($x_value), - // self::SIGN => $x_sign != $y_value - // ]; - //} - - $x_length = count($x_value); - $y_length = count($y_value); - - if (!$x_length || !$y_length) { // a 0 is being multiplied - return [ - self::VALUE => [], - self::SIGN => false - ]; - } - - return [ - self::VALUE => min($x_length, $y_length) < 2 * self::KARATSUBA_CUTOFF ? - self::trim(self::regularMultiply($x_value, $y_value)) : - self::trim(self::karatsuba($x_value, $y_value)), - self::SIGN => $x_negative != $y_negative - ]; - } - - /** - * Performs Karatsuba multiplication on two BigIntegers - * - * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and - * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=120 MPM 5.2.3}. - * - * @param array $x_value - * @param array $y_value - * @return array - */ - private static function karatsuba(array $x_value, array $y_value) - { - $m = min(count($x_value) >> 1, count($y_value) >> 1); - - if ($m < self::KARATSUBA_CUTOFF) { - return self::regularMultiply($x_value, $y_value); - } - - $x1 = array_slice($x_value, $m); - $x0 = array_slice($x_value, 0, $m); - $y1 = array_slice($y_value, $m); - $y0 = array_slice($y_value, 0, $m); - - $z2 = self::karatsuba($x1, $y1); - $z0 = self::karatsuba($x0, $y0); - - $z1 = self::addHelper($x1, false, $x0, false); - $temp = self::addHelper($y1, false, $y0, false); - $z1 = self::karatsuba($z1[self::VALUE], $temp[self::VALUE]); - $temp = self::addHelper($z2, false, $z0, false); - $z1 = self::subtractHelper($z1, false, $temp[self::VALUE], false); - - $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2); - $z1[self::VALUE] = array_merge(array_fill(0, $m, 0), $z1[self::VALUE]); - - $xy = self::addHelper($z2, false, $z1[self::VALUE], $z1[self::SIGN]); - $xy = self::addHelper($xy[self::VALUE], $xy[self::SIGN], $z0, false); - - return $xy[self::VALUE]; - } - - /** - * Performs long multiplication on two BigIntegers - * - * Modeled after 'multiply' in MutableBigInteger.java. - * - * @param array $x_value - * @param array $y_value - * @return array - */ - protected static function regularMultiply(array $x_value, array $y_value) - { - $x_length = count($x_value); - $y_length = count($y_value); - - if (!$x_length || !$y_length) { // a 0 is being multiplied - return []; - } - - $product_value = self::array_repeat(0, $x_length + $y_length); - - // the following for loop could be removed if the for loop following it - // (the one with nested for loops) initially set $i to 0, but - // doing so would also make the result in one set of unnecessary adds, - // since on the outermost loops first pass, $product->value[$k] is going - // to always be 0 - - $carry = 0; - for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0 - $temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0 - $carry = static::BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31); - $product_value[$j] = (int)($temp - static::BASE_FULL * $carry); - } - - $product_value[$j] = $carry; - - // the above for loop is what the previous comment was talking about. the - // following for loop is the "one with nested for loops" - for ($i = 1; $i < $y_length; ++$i) { - $carry = 0; - - for ($j = 0, $k = $i; $j < $x_length; ++$j, ++$k) { - $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry; - $carry = static::BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31); - $product_value[$k] = (int)($temp - static::BASE_FULL * $carry); - } - - $product_value[$k] = $carry; - } - - return $product_value; - } - - /** - * Divides two BigIntegers. - * - * Returns an array whose first element contains the quotient and whose second element contains the - * "common residue". If the remainder would be positive, the "common residue" and the remainder are the - * same. If the remainder would be negative, the "common residue" is equal to the sum of the remainder - * and the divisor (basically, the "common residue" is the first positive modulo). - * - * @return array{static, static} - * @internal This function is based off of - * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=9 HAC 14.20}. - */ - protected function divideHelper(PHP $y) - { - if (count($y->value) == 1) { - list($q, $r) = $this->divide_digit($this->value, $y->value[0]); - $quotient = new static(); - $remainder = new static(); - $quotient->value = $q; - $remainder->value = [$r]; - $quotient->is_negative = $this->is_negative != $y->is_negative; - return [$this->normalize($quotient), $this->normalize($remainder)]; - } - - $x = clone $this; - $y = clone $y; - - $x_sign = $x->is_negative; - $y_sign = $y->is_negative; - - $x->is_negative = $y->is_negative = false; - - $diff = $x->compare($y); - - if (!$diff) { - $temp = new static(); - $temp->value = [1]; - $temp->is_negative = $x_sign != $y_sign; - return [$this->normalize($temp), $this->normalize(static::$zero[static::class])]; - } - - if ($diff < 0) { - // if $x is negative, "add" $y. - if ($x_sign) { - $x = $y->subtract($x); - } - return [$this->normalize(static::$zero[static::class]), $this->normalize($x)]; - } - - // normalize $x and $y as described in HAC 14.23 / 14.24 - $msb = $y->value[count($y->value) - 1]; - for ($shift = 0; !($msb & static::MSB); ++$shift) { - $msb <<= 1; - } - $x->lshift($shift); - $y->lshift($shift); - $y_value = &$y->value; - - $x_max = count($x->value) - 1; - $y_max = count($y->value) - 1; - - $quotient = new static(); - $quotient_value = &$quotient->value; - $quotient_value = self::array_repeat(0, $x_max - $y_max + 1); - - static $temp, $lhs, $rhs; - if (!isset($temp)) { - $temp = new static(); - $lhs = new static(); - $rhs = new static(); - } - if (static::class != get_class($temp)) { - $temp = new static(); - $lhs = new static(); - $rhs = new static(); - } - $temp_value = &$temp->value; - $rhs_value = &$rhs->value; - - // $temp = $y << ($x_max - $y_max-1) in base 2**26 - $temp_value = array_merge(self::array_repeat(0, $x_max - $y_max), $y_value); - - while ($x->compare($temp) >= 0) { - // calculate the "common residue" - ++$quotient_value[$x_max - $y_max]; - $x = $x->subtract($temp); - $x_max = count($x->value) - 1; - } - - for ($i = $x_max; $i >= $y_max + 1; --$i) { - $x_value = &$x->value; - $x_window = [ - isset($x_value[$i]) ? $x_value[$i] : 0, - isset($x_value[$i - 1]) ? $x_value[$i - 1] : 0, - isset($x_value[$i - 2]) ? $x_value[$i - 2] : 0 - ]; - $y_window = [ - $y_value[$y_max], - ($y_max > 0) ? $y_value[$y_max - 1] : 0 - ]; - - $q_index = $i - $y_max - 1; - if ($x_window[0] == $y_window[0]) { - $quotient_value[$q_index] = static::MAX_DIGIT; - } else { - $quotient_value[$q_index] = self::safe_divide( - $x_window[0] * static::BASE_FULL + $x_window[1], - $y_window[0] - ); - } - - $temp_value = [$y_window[1], $y_window[0]]; - - $lhs->value = [$quotient_value[$q_index]]; - $lhs = $lhs->multiply($temp); - - $rhs_value = [$x_window[2], $x_window[1], $x_window[0]]; - - while ($lhs->compare($rhs) > 0) { - --$quotient_value[$q_index]; - - $lhs->value = [$quotient_value[$q_index]]; - $lhs = $lhs->multiply($temp); - } - - $adjust = self::array_repeat(0, $q_index); - $temp_value = [$quotient_value[$q_index]]; - $temp = $temp->multiply($y); - $temp_value = &$temp->value; - if (count($temp_value)) { - $temp_value = array_merge($adjust, $temp_value); - } - - $x = $x->subtract($temp); - - if ($x->compare(static::$zero[static::class]) < 0) { - $temp_value = array_merge($adjust, $y_value); - $x = $x->add($temp); - - --$quotient_value[$q_index]; - } - - $x_max = count($x_value) - 1; - } - - // unnormalize the remainder - $x->rshift($shift); - - $quotient->is_negative = $x_sign != $y_sign; - - // calculate the "common residue", if appropriate - if ($x_sign) { - $y->rshift($shift); - $x = $y->subtract($x); - } - - return [$this->normalize($quotient), $this->normalize($x)]; - } - - /** - * Divides a BigInteger by a regular integer - * - * abc / x = a00 / x + b0 / x + c / x - * - * @param array $dividend - * @param int $divisor - * @return array - */ - private static function divide_digit(array $dividend, $divisor) - { - $carry = 0; - $result = []; - - for ($i = count($dividend) - 1; $i >= 0; --$i) { - $temp = static::BASE_FULL * $carry + $dividend[$i]; - $result[$i] = self::safe_divide($temp, $divisor); - $carry = (int)($temp - $divisor * $result[$i]); - } - - return [$result, $carry]; - } - - /** - * Single digit division - * - * Even if int64 is being used the division operator will return a float64 value - * if the dividend is not evenly divisible by the divisor. Since a float64 doesn't - * have the precision of int64 this is a problem so, when int64 is being used, - * we'll guarantee that the dividend is divisible by first subtracting the remainder. - * - * @param int $x - * @param int $y - * @return int - */ - private static function safe_divide($x, $y) - { - if (static::BASE === 26) { - return (int)($x / $y); - } - - // static::BASE === 31 - /** @var int */ - return ($x - ($x % $y)) / $y; - } - - /** - * Convert an array / boolean to a PHP BigInteger object - * - * @param array $arr - * @return static - */ - protected function convertToObj(array $arr) - { - $result = new static(); - $result->value = $arr[self::VALUE]; - $result->is_negative = $arr[self::SIGN]; - - return $this->normalize($result); - } - - /** - * Normalize - * - * Removes leading zeros and truncates (if necessary) to maintain the appropriate precision - * - * @param PHP $result - * @return static - */ - protected function normalize(PHP $result) - { - $result->precision = $this->precision; - $result->bitmask = $this->bitmask; - - $value = &$result->value; - - if (!count($value)) { - $result->is_negative = false; - return $result; - } - - $value = static::trim($value); - - if (!empty($result->bitmask->value)) { - $length = min(count($value), count($result->bitmask->value)); - $value = array_slice($value, 0, $length); - - for ($i = 0; $i < $length; ++$i) { - $value[$i] = $value[$i] & $result->bitmask->value[$i]; - } - - $value = static::trim($value); - } - - return $result; - } - - /** - * Compares two numbers. - * - * @param array $x_value - * @param bool $x_negative - * @param array $y_value - * @param bool $y_negative - * @return int - * @see static::compare() - */ - protected static function compareHelper(array $x_value, $x_negative, array $y_value, $y_negative) - { - if ($x_negative != $y_negative) { - return (!$x_negative && $y_negative) ? 1 : -1; - } - - $result = $x_negative ? -1 : 1; - - if (count($x_value) != count($y_value)) { - return (count($x_value) > count($y_value)) ? $result : -$result; - } - $size = max(count($x_value), count($y_value)); - - $x_value = array_pad($x_value, $size, 0); - $y_value = array_pad($y_value, $size, 0); - - for ($i = count($x_value) - 1; $i >= 0; --$i) { - if ($x_value[$i] != $y_value[$i]) { - return ($x_value[$i] > $y_value[$i]) ? $result : -$result; - } - } - - return 0; - } - - /** - * Absolute value. - * - * @return PHP - */ - public function abs() - { - $temp = new static(); - $temp->value = $this->value; - - return $temp; - } - - /** - * Trim - * - * Removes leading zeros - * - * @param list $value - * @return list - */ - protected static function trim(array $value) - { - for ($i = count($value) - 1; $i >= 0; --$i) { - if ($value[$i]) { - break; - } - unset($value[$i]); - } - - return $value; - } - - /** - * Logical Right Shift - * - * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift. - * - * @param int $shift - * @return PHP - */ - public function bitwise_rightShift($shift) - { - $temp = new static(); - - // could just replace lshift with this, but then all lshift() calls would need to be rewritten - // and I don't want to do that... - $temp->value = $this->value; - $temp->rshift($shift); - - return $this->normalize($temp); - } - - /** - * Logical Left Shift - * - * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift. - * - * @param int $shift - * @return PHP - */ - public function bitwise_leftShift($shift) - { - $temp = new static(); - // could just replace _rshift with this, but then all _lshift() calls would need to be rewritten - // and I don't want to do that... - $temp->value = $this->value; - $temp->lshift($shift); - - return $this->normalize($temp); - } - - /** - * Converts 32-bit integers to bytes. - * - * @param int $x - * @return string - */ - private static function int2bytes($x) - { - return ltrim(pack('N', $x), chr(0)); - } - - /** - * Array Repeat - * - * @param int $input - * @param int $multiplier - * @return array - */ - protected static function array_repeat($input, $multiplier) - { - return $multiplier ? array_fill(0, $multiplier, $input) : []; - } - - /** - * Logical Left Shift - * - * Shifts BigInteger's by $shift bits. - * - * @param int $shift - */ - protected function lshift($shift) - { - if ($shift == 0) { - return; - } - - $num_digits = (int)($shift / static::BASE); - $shift %= static::BASE; - $shift = 1 << $shift; - - $carry = 0; - - for ($i = 0; $i < count($this->value); ++$i) { - $temp = $this->value[$i] * $shift + $carry; - $carry = static::BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31); - $this->value[$i] = (int)($temp - $carry * static::BASE_FULL); - } - - if ($carry) { - $this->value[count($this->value)] = $carry; - } - - while ($num_digits--) { - array_unshift($this->value, 0); - } - } - - /** - * Logical Right Shift - * - * Shifts BigInteger's by $shift bits. - * - * @param int $shift - */ - protected function rshift($shift) - { - if ($shift == 0) { - return; - } - - $num_digits = (int)($shift / static::BASE); - $shift %= static::BASE; - $carry_shift = static::BASE - $shift; - $carry_mask = (1 << $shift) - 1; - - if ($num_digits) { - $this->value = array_slice($this->value, $num_digits); - } - - $carry = 0; - - for ($i = count($this->value) - 1; $i >= 0; --$i) { - $temp = $this->value[$i] >> $shift | $carry; - $carry = ($this->value[$i] & $carry_mask) << $carry_shift; - $this->value[$i] = $temp; - } - - $this->value = static::trim($this->value); - } - - /** - * Performs modular exponentiation. - * - * @param PHP $e - * @param PHP $n - * @return PHP - */ - protected function powModInner(PHP $e, PHP $n) - { - try { - $class = static::$modexpEngine[static::class]; - return $class::powModHelper($this, $e, $n, static::class); - } catch (\Exception $err) { - return PHP\DefaultEngine::powModHelper($this, $e, $n, static::class); - } - } - - /** - * Performs squaring - * - * @param list $x - * @return list - */ - protected static function square(array $x) - { - return count($x) < 2 * self::KARATSUBA_CUTOFF ? - self::trim(self::baseSquare($x)) : - self::trim(self::karatsubaSquare($x)); - } - - /** - * Performs traditional squaring on two BigIntegers - * - * Squaring can be done faster than multiplying a number by itself can be. See - * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=7 HAC 14.2.4} / - * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=141 MPM 5.3} for more information. - * - * @param array $value - * @return array - */ - protected static function baseSquare(array $value) - { - if (empty($value)) { - return []; - } - $square_value = self::array_repeat(0, 2 * count($value)); - - for ($i = 0, $max_index = count($value) - 1; $i <= $max_index; ++$i) { - $i2 = $i << 1; - - $temp = $square_value[$i2] + $value[$i] * $value[$i]; - $carry = static::BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31); - $square_value[$i2] = (int)($temp - static::BASE_FULL * $carry); - - // note how we start from $i+1 instead of 0 as we do in multiplication. - for ($j = $i + 1, $k = $i2 + 1; $j <= $max_index; ++$j, ++$k) { - $temp = $square_value[$k] + 2 * $value[$j] * $value[$i] + $carry; - $carry = static::BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31); - $square_value[$k] = (int)($temp - static::BASE_FULL * $carry); - } - - // the following line can yield values larger 2**15. at this point, PHP should switch - // over to floats. - $square_value[$i + $max_index + 1] = $carry; - } - - return $square_value; - } - - /** - * Performs Karatsuba "squaring" on two BigIntegers - * - * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and - * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=151 MPM 5.3.4}. - * - * @param array $value - * @return array - */ - protected static function karatsubaSquare(array $value) - { - $m = count($value) >> 1; - - if ($m < self::KARATSUBA_CUTOFF) { - return self::baseSquare($value); - } - - $x1 = array_slice($value, $m); - $x0 = array_slice($value, 0, $m); - - $z2 = self::karatsubaSquare($x1); - $z0 = self::karatsubaSquare($x0); - - $z1 = self::addHelper($x1, false, $x0, false); - $z1 = self::karatsubaSquare($z1[self::VALUE]); - $temp = self::addHelper($z2, false, $z0, false); - $z1 = self::subtractHelper($z1, false, $temp[self::VALUE], false); - - $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2); - $z1[self::VALUE] = array_merge(array_fill(0, $m, 0), $z1[self::VALUE]); - - $xx = self::addHelper($z2, false, $z1[self::VALUE], $z1[self::SIGN]); - $xx = self::addHelper($xx[self::VALUE], $xx[self::SIGN], $z0, false); - - return $xx[self::VALUE]; - } - - /** - * Make the current number odd - * - * If the current number is odd it'll be unchanged. If it's even, one will be added to it. - * - * @see self::randomPrime() - */ - protected function make_odd() - { - $this->value[0] |= 1; - } - - /** - * Test the number against small primes. - * - * @see self::isPrime() - */ - protected function testSmallPrimes() - { - if ($this->value == [1]) { - return false; - } - if ($this->value == [2]) { - return true; - } - if (~$this->value[0] & 1) { - return false; - } - - $value = $this->value; - foreach (static::PRIMES as $prime) { - list(, $r) = self::divide_digit($value, $prime); - if (!$r) { - return count($value) == 1 && $value[0] == $prime; - } - } - - return true; - } - - /** - * Scan for 1 and right shift by that amount - * - * ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s)); - * - * @param PHP $r - * @return int - * @see self::isPrime() - */ - public static function scan1divide(PHP $r) - { - $r_value = &$r->value; - for ($i = 0, $r_length = count($r_value); $i < $r_length; ++$i) { - $temp = ~$r_value[$i] & static::MAX_DIGIT; - for ($j = 1; ($temp >> $j) & 1; ++$j) { - } - if ($j <= static::BASE) { - break; - } - } - $s = static::BASE * $i + $j; - $r->rshift($s); - return $s; - } - - /** - * Performs exponentiation. - * - * @param PHP $n - * @return PHP - */ - protected function powHelper(PHP $n) - { - if ($n->compare(static::$zero[static::class]) == 0) { - return new static(1); - } // n^0 = 1 - - $temp = clone $this; - while (!$n->equals(static::$one[static::class])) { - $temp = $temp->multiply($this); - $n = $n->subtract(static::$one[static::class]); - } - - return $temp; - } - - /** - * Is Odd? - * - * @return bool - */ - public function isOdd() - { - return (bool)($this->value[0] & 1); - } - - /** - * Tests if a bit is set - * - * @return bool - */ - public function testBit($x) - { - $digit = (int) floor($x / static::BASE); - $bit = $x % static::BASE; - - if (!isset($this->value[$digit])) { - return false; - } - - return (bool)($this->value[$digit] & (1 << $bit)); - } - - /** - * Is Negative? - * - * @return bool - */ - public function isNegative() - { - return $this->is_negative; - } - - /** - * Negate - * - * Given $k, returns -$k - * - * @return static - */ - public function negate() - { - $temp = clone $this; - $temp->is_negative = !$temp->is_negative; - - return $temp; - } - - /** - * Bitwise Split - * - * Splits BigInteger's into chunks of $split bits - * - * @param int $split - * @return list - */ - public function bitwise_split($split) - { - if ($split < 1) { - throw new \RuntimeException('Offset must be greater than 1'); - } - - $width = (int)($split / static::BASE); - if (!$width) { - $arr = $this->bitwise_small_split($split); - return array_map(function ($digit) { - $temp = new static(); - $temp->value = $digit != 0 ? [$digit] : []; - return $temp; - }, $arr); - } - - $vals = []; - $val = $this->value; - - $i = $overflow = 0; - $len = count($val); - while ($i < $len) { - $digit = []; - if (!$overflow) { - $digit = array_slice($val, $i, $width); - $i += $width; - $overflow = $split % static::BASE; - if ($overflow) { - $mask = (1 << $overflow) - 1; - $temp = isset($val[$i]) ? $val[$i] : 0; - $digit[] = $temp & $mask; - } - } else { - $remaining = static::BASE - $overflow; - $tempsplit = $split - $remaining; - $tempwidth = (int)($tempsplit / static::BASE + 1); - $digit = array_slice($val, $i, $tempwidth); - $i += $tempwidth; - $tempoverflow = $tempsplit % static::BASE; - if ($tempoverflow) { - $tempmask = (1 << $tempoverflow) - 1; - $temp = isset($val[$i]) ? $val[$i] : 0; - $digit[] = $temp & $tempmask; - } - $newbits = 0; - for ($j = count($digit) - 1; $j >= 0; $j--) { - $temp = $digit[$j] & $mask; - $digit[$j] = ($digit[$j] >> $overflow) | ($newbits << $remaining); - $newbits = $temp; - } - $overflow = $tempoverflow; - $mask = $tempmask; - } - $temp = new static(); - $temp->value = static::trim($digit); - $vals[] = $temp; - } - - return array_reverse($vals); - } - - /** - * Bitwise Split where $split < static::BASE - * - * @param int $split - * @return list - */ - private function bitwise_small_split($split) - { - $vals = []; - $val = $this->value; - - $mask = (1 << $split) - 1; - - $i = $overflow = 0; - $len = count($val); - $val[] = 0; - $remaining = static::BASE; - while ($i != $len) { - $digit = $val[$i] & $mask; - $val[$i] >>= $split; - if (!$overflow) { - $remaining -= $split; - $overflow = $split <= $remaining ? 0 : $split - $remaining; - - if (!$remaining) { - $i++; - $remaining = static::BASE; - $overflow = 0; - } - } elseif (++$i != $len) { - $tempmask = (1 << $overflow) - 1; - $digit |= ($val[$i] & $tempmask) << $remaining; - $val[$i] >>= $overflow; - $remaining = static::BASE - $overflow; - $overflow = $split <= $remaining ? 0 : $split - $remaining; - } - - $vals[] = $digit; - } - - while ($vals[count($vals) - 1] == 0) { - unset($vals[count($vals) - 1]); - } - - return array_reverse($vals); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Base.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Base.php deleted file mode 100644 index 40f64bd1..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Base.php +++ /dev/null @@ -1,143 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines\PHP; - -use phpseclib3\Math\BigInteger\Engines\PHP; - -/** - * PHP Modular Exponentiation Engine - * - * @author Jim Wigginton - */ -abstract class Base extends PHP -{ - /** - * Cache constants - * - * $cache[self::VARIABLE] tells us whether or not the cached data is still valid. - * - */ - const VARIABLE = 0; - /** - * $cache[self::DATA] contains the cached data. - * - */ - const DATA = 1; - - /** - * Test for engine validity - * - * @return bool - */ - public static function isValidEngine() - { - return static::class != __CLASS__; - } - - /** - * Performs modular exponentiation. - * - * The most naive approach to modular exponentiation has very unreasonable requirements, and - * and although the approach involving repeated squaring does vastly better, it, too, is impractical - * for our purposes. The reason being that division - by far the most complicated and time-consuming - * of the basic operations (eg. +,-,*,/) - occurs multiple times within it. - * - * Modular reductions resolve this issue. Although an individual modular reduction takes more time - * then an individual division, when performed in succession (with the same modulo), they're a lot faster. - * - * The two most commonly used modular reductions are Barrett and Montgomery reduction. Montgomery reduction, - * although faster, only works when the gcd of the modulo and of the base being used is 1. In RSA, when the - * base is a power of two, the modulo - a product of two primes - is always going to have a gcd of 1 (because - * the product of two odd numbers is odd), but what about when RSA isn't used? - * - * In contrast, Barrett reduction has no such constraint. As such, some bigint implementations perform a - * Barrett reduction after every operation in the modpow function. Others perform Barrett reductions when the - * modulo is even and Montgomery reductions when the modulo is odd. BigInteger.java's modPow method, however, - * uses a trick involving the Chinese Remainder Theorem to factor the even modulo into two numbers - one odd and - * the other, a power of two - and recombine them, later. This is the method that this modPow function uses. - * {@link http://islab.oregonstate.edu/papers/j34monex.pdf Montgomery Reduction with Even Modulus} elaborates. - * - * @param PHP $x - * @param PHP $e - * @param PHP $n - * @param string $class - * @return PHP - */ - protected static function powModHelper(PHP $x, PHP $e, PHP $n, $class) - { - if (empty($e->value)) { - $temp = new $class(); - $temp->value = [1]; - return $x->normalize($temp); - } - - if ($e->value == [1]) { - list(, $temp) = $x->divide($n); - return $x->normalize($temp); - } - - if ($e->value == [2]) { - $temp = new $class(); - $temp->value = $class::square($x->value); - list(, $temp) = $temp->divide($n); - return $x->normalize($temp); - } - - return $x->normalize(static::slidingWindow($x, $e, $n, $class)); - } - - /** - * Modular reduction preparation - * - * @param array $x - * @param array $n - * @param string $class - * @see self::slidingWindow() - * @return array - */ - protected static function prepareReduce(array $x, array $n, $class) - { - return static::reduce($x, $n, $class); - } - - /** - * Modular multiply - * - * @param array $x - * @param array $y - * @param array $n - * @param string $class - * @see self::slidingWindow() - * @return array - */ - protected static function multiplyReduce(array $x, array $y, array $n, $class) - { - $temp = $class::multiplyHelper($x, false, $y, false); - return static::reduce($temp[self::VALUE], $n, $class); - } - - /** - * Modular square - * - * @param array $x - * @param array $n - * @param string $class - * @see self::slidingWindow() - * @return array - */ - protected static function squareReduce(array $x, array $n, $class) - { - return static::reduce($class::square($x), $n, $class); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/DefaultEngine.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/DefaultEngine.php deleted file mode 100644 index 6d33532e..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/DefaultEngine.php +++ /dev/null @@ -1,25 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines\PHP; - -use phpseclib3\Math\BigInteger\Engines\PHP\Reductions\EvalBarrett; - -/** - * PHP Default Modular Exponentiation Engine - * - * @author Jim Wigginton - */ -abstract class DefaultEngine extends EvalBarrett -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Montgomery.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Montgomery.php deleted file mode 100644 index 09f825f9..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Montgomery.php +++ /dev/null @@ -1,89 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines\PHP; - -use phpseclib3\Math\BigInteger\Engines\Engine; -use phpseclib3\Math\BigInteger\Engines\PHP; -use phpseclib3\Math\BigInteger\Engines\PHP\Reductions\PowerOfTwo; - -/** - * PHP Montgomery Modular Exponentiation Engine - * - * @author Jim Wigginton - */ -abstract class Montgomery extends Base -{ - /** - * Test for engine validity - * - * @return bool - */ - public static function isValidEngine() - { - return static::class != __CLASS__; - } - - /** - * Performs modular exponentiation. - * - * @template T of Engine - * @param Engine $x - * @param Engine $e - * @param Engine $n - * @param class-string $class - * @return T - */ - protected static function slidingWindow(Engine $x, Engine $e, Engine $n, $class) - { - // is the modulo odd? - if ($n->value[0] & 1) { - return parent::slidingWindow($x, $e, $n, $class); - } - // if it's not, it's even - - // find the lowest set bit (eg. the max pow of 2 that divides $n) - for ($i = 0; $i < count($n->value); ++$i) { - if ($n->value[$i]) { - $temp = decbin($n->value[$i]); - $j = strlen($temp) - strrpos($temp, '1') - 1; - $j += $class::BASE * $i; - break; - } - } - // at this point, 2^$j * $n/(2^$j) == $n - - $mod1 = clone $n; - $mod1->rshift($j); - $mod2 = new $class(); - $mod2->value = [1]; - $mod2->lshift($j); - - $part1 = $mod1->value != [1] ? parent::slidingWindow($x, $e, $mod1, $class) : new $class(); - $part2 = PowerOfTwo::slidingWindow($x, $e, $mod2, $class); - - $y1 = $mod2->modInverse($mod1); - $y2 = $mod1->modInverse($mod2); - - $result = $part1->multiply($mod2); - $result = $result->multiply($y1); - - $temp = $part2->multiply($mod1); - $temp = $temp->multiply($y2); - - $result = $result->add($temp); - list(, $result) = $result->divide($n); - - return $result; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/OpenSSL.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/OpenSSL.php deleted file mode 100644 index eddd25e2..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/OpenSSL.php +++ /dev/null @@ -1,25 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines\PHP; - -use phpseclib3\Math\BigInteger\Engines\OpenSSL as Progenitor; - -/** - * OpenSSL Modular Exponentiation Engine - * - * @author Jim Wigginton - */ -abstract class OpenSSL extends Progenitor -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Barrett.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Barrett.php deleted file mode 100644 index 3518d76f..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Barrett.php +++ /dev/null @@ -1,281 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines\PHP\Reductions; - -use phpseclib3\Math\BigInteger\Engines\PHP; -use phpseclib3\Math\BigInteger\Engines\PHP\Base; - -/** - * PHP Barrett Modular Exponentiation Engine - * - * @author Jim Wigginton - */ -abstract class Barrett extends Base -{ - /** - * Barrett Modular Reduction - * - * See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=14 HAC 14.3.3} / - * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=165 MPM 6.2.5} for more information. Modified slightly, - * so as not to require negative numbers (initially, this script didn't support negative numbers). - * - * Employs "folding", as described at - * {@link http://www.cosic.esat.kuleuven.be/publications/thesis-149.pdf#page=66 thesis-149.pdf#page=66}. To quote from - * it, "the idea [behind folding] is to find a value x' such that x (mod m) = x' (mod m), with x' being smaller than x." - * - * Unfortunately, the "Barrett Reduction with Folding" algorithm described in thesis-149.pdf is not, as written, all that - * usable on account of (1) its not using reasonable radix points as discussed in - * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=162 MPM 6.2.2} and (2) the fact that, even with reasonable - * radix points, it only works when there are an even number of digits in the denominator. The reason for (2) is that - * (x >> 1) + (x >> 1) != x / 2 + x / 2. If x is even, they're the same, but if x is odd, they're not. See the in-line - * comments for details. - * - * @param array $n - * @param array $m - * @param class-string $class - * @return array - */ - protected static function reduce(array $n, array $m, $class) - { - static $cache = [ - self::VARIABLE => [], - self::DATA => [] - ]; - - $m_length = count($m); - - // if (self::compareHelper($n, $static::square($m)) >= 0) { - if (count($n) > 2 * $m_length) { - $lhs = new $class(); - $rhs = new $class(); - $lhs->value = $n; - $rhs->value = $m; - list(, $temp) = $lhs->divide($rhs); - return $temp->value; - } - - // if (m.length >> 1) + 2 <= m.length then m is too small and n can't be reduced - if ($m_length < 5) { - return self::regularBarrett($n, $m, $class); - } - // n = 2 * m.length - - if (($key = array_search($m, $cache[self::VARIABLE])) === false) { - $key = count($cache[self::VARIABLE]); - $cache[self::VARIABLE][] = $m; - - $lhs = new $class(); - $lhs_value = &$lhs->value; - $lhs_value = self::array_repeat(0, $m_length + ($m_length >> 1)); - $lhs_value[] = 1; - $rhs = new $class(); - $rhs->value = $m; - - list($u, $m1) = $lhs->divide($rhs); - $u = $u->value; - $m1 = $m1->value; - - $cache[self::DATA][] = [ - 'u' => $u, // m.length >> 1 (technically (m.length >> 1) + 1) - 'm1' => $m1 // m.length - ]; - } else { - extract($cache[self::DATA][$key]); - } - - $cutoff = $m_length + ($m_length >> 1); - $lsd = array_slice($n, 0, $cutoff); // m.length + (m.length >> 1) - $msd = array_slice($n, $cutoff); // m.length >> 1 - - $lsd = self::trim($lsd); - $temp = $class::multiplyHelper($msd, false, $m1, false); // m.length + (m.length >> 1) - $n = $class::addHelper($lsd, false, $temp[self::VALUE], false); // m.length + (m.length >> 1) + 1 (so basically we're adding two same length numbers) - //if ($m_length & 1) { - // return self::regularBarrett($n[self::VALUE], $m, $class); - //} - - // (m.length + (m.length >> 1) + 1) - (m.length - 1) == (m.length >> 1) + 2 - $temp = array_slice($n[self::VALUE], $m_length - 1); - // if even: ((m.length >> 1) + 2) + (m.length >> 1) == m.length + 2 - // if odd: ((m.length >> 1) + 2) + (m.length >> 1) == (m.length - 1) + 2 == m.length + 1 - $temp = $class::multiplyHelper($temp, false, $u, false); - // if even: (m.length + 2) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) + 1 - // if odd: (m.length + 1) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) - $temp = array_slice($temp[self::VALUE], ($m_length >> 1) + 1); - // if even: (m.length - (m.length >> 1) + 1) + m.length = 2 * m.length - (m.length >> 1) + 1 - // if odd: (m.length - (m.length >> 1)) + m.length = 2 * m.length - (m.length >> 1) - $temp = $class::multiplyHelper($temp, false, $m, false); - - // at this point, if m had an odd number of digits, we'd be subtracting a 2 * m.length - (m.length >> 1) digit - // number from a m.length + (m.length >> 1) + 1 digit number. ie. there'd be an extra digit and the while loop - // following this comment would loop a lot (hence our calling _regularBarrett() in that situation). - - $result = $class::subtractHelper($n[self::VALUE], false, $temp[self::VALUE], false); - - while (self::compareHelper($result[self::VALUE], $result[self::SIGN], $m, false) >= 0) { - $result = $class::subtractHelper($result[self::VALUE], $result[self::SIGN], $m, false); - } - - return $result[self::VALUE]; - } - - /** - * (Regular) Barrett Modular Reduction - * - * For numbers with more than four digits BigInteger::_barrett() is faster. The difference between that and this - * is that this function does not fold the denominator into a smaller form. - * - * @param array $x - * @param array $n - * @param string $class - * @return array - */ - private static function regularBarrett(array $x, array $n, $class) - { - static $cache = [ - self::VARIABLE => [], - self::DATA => [] - ]; - - $n_length = count($n); - - if (count($x) > 2 * $n_length) { - $lhs = new $class(); - $rhs = new $class(); - $lhs->value = $x; - $rhs->value = $n; - list(, $temp) = $lhs->divide($rhs); - return $temp->value; - } - - if (($key = array_search($n, $cache[self::VARIABLE])) === false) { - $key = count($cache[self::VARIABLE]); - $cache[self::VARIABLE][] = $n; - $lhs = new $class(); - $lhs_value = &$lhs->value; - $lhs_value = self::array_repeat(0, 2 * $n_length); - $lhs_value[] = 1; - $rhs = new $class(); - $rhs->value = $n; - list($temp, ) = $lhs->divide($rhs); // m.length - $cache[self::DATA][] = $temp->value; - } - - // 2 * m.length - (m.length - 1) = m.length + 1 - $temp = array_slice($x, $n_length - 1); - // (m.length + 1) + m.length = 2 * m.length + 1 - $temp = $class::multiplyHelper($temp, false, $cache[self::DATA][$key], false); - // (2 * m.length + 1) - (m.length - 1) = m.length + 2 - $temp = array_slice($temp[self::VALUE], $n_length + 1); - - // m.length + 1 - $result = array_slice($x, 0, $n_length + 1); - // m.length + 1 - $temp = self::multiplyLower($temp, false, $n, false, $n_length + 1, $class); - // $temp == array_slice($class::regularMultiply($temp, false, $n, false)->value, 0, $n_length + 1) - - if (self::compareHelper($result, false, $temp[self::VALUE], $temp[self::SIGN]) < 0) { - $corrector_value = self::array_repeat(0, $n_length + 1); - $corrector_value[count($corrector_value)] = 1; - $result = $class::addHelper($result, false, $corrector_value, false); - $result = $result[self::VALUE]; - } - - // at this point, we're subtracting a number with m.length + 1 digits from another number with m.length + 1 digits - $result = $class::subtractHelper($result, false, $temp[self::VALUE], $temp[self::SIGN]); - while (self::compareHelper($result[self::VALUE], $result[self::SIGN], $n, false) > 0) { - $result = $class::subtractHelper($result[self::VALUE], $result[self::SIGN], $n, false); - } - - return $result[self::VALUE]; - } - - /** - * Performs long multiplication up to $stop digits - * - * If you're going to be doing array_slice($product->value, 0, $stop), some cycles can be saved. - * - * @see self::regularBarrett() - * @param array $x_value - * @param bool $x_negative - * @param array $y_value - * @param bool $y_negative - * @param int $stop - * @param string $class - * @return array - */ - private static function multiplyLower(array $x_value, $x_negative, array $y_value, $y_negative, $stop, $class) - { - $x_length = count($x_value); - $y_length = count($y_value); - - if (!$x_length || !$y_length) { // a 0 is being multiplied - return [ - self::VALUE => [], - self::SIGN => false - ]; - } - - if ($x_length < $y_length) { - $temp = $x_value; - $x_value = $y_value; - $y_value = $temp; - - $x_length = count($x_value); - $y_length = count($y_value); - } - - $product_value = self::array_repeat(0, $x_length + $y_length); - - // the following for loop could be removed if the for loop following it - // (the one with nested for loops) initially set $i to 0, but - // doing so would also make the result in one set of unnecessary adds, - // since on the outermost loops first pass, $product->value[$k] is going - // to always be 0 - - $carry = 0; - - for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0, $k = $i - $temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0 - $carry = $class::BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31); - $product_value[$j] = (int) ($temp - $class::BASE_FULL * $carry); - } - - if ($j < $stop) { - $product_value[$j] = $carry; - } - - // the above for loop is what the previous comment was talking about. the - // following for loop is the "one with nested for loops" - - for ($i = 1; $i < $y_length; ++$i) { - $carry = 0; - - for ($j = 0, $k = $i; $j < $x_length && $k < $stop; ++$j, ++$k) { - $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry; - $carry = $class::BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31); - $product_value[$k] = (int) ($temp - $class::BASE_FULL * $carry); - } - - if ($k < $stop) { - $product_value[$k] = $carry; - } - } - - return [ - self::VALUE => self::trim($product_value), - self::SIGN => $x_negative != $y_negative - ]; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Classic.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Classic.php deleted file mode 100644 index 54f3b863..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Classic.php +++ /dev/null @@ -1,42 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines\PHP\Reductions; - -use phpseclib3\Math\BigInteger\Engines\PHP\Base; - -/** - * PHP Classic Modular Exponentiation Engine - * - * @author Jim Wigginton - */ -abstract class Classic extends Base -{ - /** - * Regular Division - * - * @param array $x - * @param array $n - * @param string $class - * @return array - */ - protected static function reduce(array $x, array $n, $class) - { - $lhs = new $class(); - $lhs->value = $x; - $rhs = new $class(); - $rhs->value = $n; - list(, $temp) = $lhs->divide($rhs); - return $temp->value; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/EvalBarrett.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/EvalBarrett.php deleted file mode 100644 index 2f943317..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/EvalBarrett.php +++ /dev/null @@ -1,484 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines\PHP\Reductions; - -use phpseclib3\Math\BigInteger\Engines\PHP; -use phpseclib3\Math\BigInteger\Engines\PHP\Base; - -/** - * PHP Dynamic Barrett Modular Exponentiation Engine - * - * @author Jim Wigginton - */ -abstract class EvalBarrett extends Base -{ - /** - * Custom Reduction Function - * - * @see self::generateCustomReduction - */ - private static $custom_reduction; - - /** - * Barrett Modular Reduction - * - * This calls a dynamically generated loop unrolled function that's specific to a given modulo. - * Array lookups are avoided as are if statements testing for how many bits the host OS supports, etc. - * - * @param array $n - * @param array $m - * @param string $class - * @return array - */ - protected static function reduce(array $n, array $m, $class) - { - $inline = self::$custom_reduction; - return $inline($n); - } - - /** - * Generate Custom Reduction - * - * @param PHP $m - * @param string $class - * @return callable - */ - protected static function generateCustomReduction(PHP $m, $class) - { - $m_length = count($m->value); - - if ($m_length < 5) { - $code = ' - $lhs = new ' . $class . '(); - $lhs->value = $x; - $rhs = new ' . $class . '(); - $rhs->value = [' . - implode(',', array_map(self::class . '::float2string', $m->value)) . ']; - list(, $temp) = $lhs->divide($rhs); - return $temp->value; - '; - eval('$func = function ($x) { ' . $code . '};'); - self::$custom_reduction = $func; - //self::$custom_reduction = \Closure::bind($func, $m, $class); - return $func; - } - - $lhs = new $class(); - $lhs_value = &$lhs->value; - - $lhs_value = self::array_repeat(0, $m_length + ($m_length >> 1)); - $lhs_value[] = 1; - $rhs = new $class(); - - list($u, $m1) = $lhs->divide($m); - - if ($class::BASE != 26) { - $u = $u->value; - } else { - $lhs_value = self::array_repeat(0, 2 * $m_length); - $lhs_value[] = 1; - $rhs = new $class(); - - list($u) = $lhs->divide($m); - $u = $u->value; - } - - $m = $m->value; - $m1 = $m1->value; - - $cutoff = count($m) + (count($m) >> 1); - - $code = ' - if (count($n) > ' . (2 * count($m)) . ') { - $lhs = new ' . $class . '(); - $rhs = new ' . $class . '(); - $lhs->value = $n; - $rhs->value = [' . - implode(',', array_map(self::class . '::float2string', $m)) . ']; - list(, $temp) = $lhs->divide($rhs); - return $temp->value; - } - - $lsd = array_slice($n, 0, ' . $cutoff . '); - $msd = array_slice($n, ' . $cutoff . ');'; - - $code .= self::generateInlineTrim('msd'); - $code .= self::generateInlineMultiply('msd', $m1, 'temp', $class); - $code .= self::generateInlineAdd('lsd', 'temp', 'n', $class); - - $code .= '$temp = array_slice($n, ' . (count($m) - 1) . ');'; - $code .= self::generateInlineMultiply('temp', $u, 'temp2', $class); - $code .= self::generateInlineTrim('temp2'); - - $code .= $class::BASE == 26 ? - '$temp = array_slice($temp2, ' . (count($m) + 1) . ');' : - '$temp = array_slice($temp2, ' . ((count($m) >> 1) + 1) . ');'; - $code .= self::generateInlineMultiply('temp', $m, 'temp2', $class); - $code .= self::generateInlineTrim('temp2'); - - /* - if ($class::BASE == 26) { - $code.= '$n = array_slice($n, 0, ' . (count($m) + 1) . '); - $temp2 = array_slice($temp2, 0, ' . (count($m) + 1) . ');'; - } - */ - - $code .= self::generateInlineSubtract2('n', 'temp2', 'temp', $class); - - $subcode = self::generateInlineSubtract1('temp', $m, 'temp2', $class); - $subcode .= '$temp = $temp2;'; - - $code .= self::generateInlineCompare($m, 'temp', $subcode); - - $code .= 'return $temp;'; - - eval('$func = function ($n) { ' . $code . '};'); - - self::$custom_reduction = $func; - - return $func; - - //self::$custom_reduction = \Closure::bind($func, $m, $class); - } - - /** - * Inline Trim - * - * Removes leading zeros - * - * @param string $name - * @return string - */ - private static function generateInlineTrim($name) - { - return ' - for ($i = count($' . $name . ') - 1; $i >= 0; --$i) { - if ($' . $name . '[$i]) { - break; - } - unset($' . $name . '[$i]); - }'; - } - - /** - * Inline Multiply (unknown, known) - * - * @param string $input - * @param array $arr - * @param string $output - * @param string $class - * @return string - */ - private static function generateInlineMultiply($input, array $arr, $output, $class) - { - if (!count($arr)) { - return 'return [];'; - } - - $regular = ' - $length = count($' . $input . '); - if (!$length) { - $' . $output . ' = []; - }else{ - $' . $output . ' = array_fill(0, $length + ' . count($arr) . ', 0); - $carry = 0;'; - - for ($i = 0; $i < count($arr); $i++) { - $regular .= ' - $subtemp = $' . $input . '[0] * ' . $arr[$i]; - $regular .= $i ? ' + $carry;' : ';'; - - $regular .= '$carry = '; - $regular .= $class::BASE === 26 ? - 'intval($subtemp / 0x4000000);' : - '$subtemp >> 31;'; - $regular .= - '$' . $output . '[' . $i . '] = '; - if ($class::BASE === 26) { - $regular .= '(int) ('; - } - $regular .= '$subtemp - ' . $class::BASE_FULL . ' * $carry'; - $regular .= $class::BASE === 26 ? ');' : ';'; - } - - $regular .= '$' . $output . '[' . count($arr) . '] = $carry;'; - - $regular .= ' - for ($i = 1; $i < $length; ++$i) {'; - - for ($j = 0; $j < count($arr); $j++) { - $regular .= $j ? '$k++;' : '$k = $i;'; - $regular .= ' - $subtemp = $' . $output . '[$k] + $' . $input . '[$i] * ' . $arr[$j]; - $regular .= $j ? ' + $carry;' : ';'; - - $regular .= '$carry = '; - $regular .= $class::BASE === 26 ? - 'intval($subtemp / 0x4000000);' : - '$subtemp >> 31;'; - $regular .= - '$' . $output . '[$k] = '; - if ($class::BASE === 26) { - $regular .= '(int) ('; - } - $regular .= '$subtemp - ' . $class::BASE_FULL . ' * $carry'; - $regular .= $class::BASE === 26 ? ');' : ';'; - } - - $regular .= '$' . $output . '[++$k] = $carry; $carry = 0;'; - - $regular .= '}}'; - - //if (count($arr) < 2 * self::KARATSUBA_CUTOFF) { - //} - - return $regular; - } - - /** - * Inline Addition - * - * @param string $x - * @param string $y - * @param string $result - * @param string $class - * @return string - */ - private static function generateInlineAdd($x, $y, $result, $class) - { - $code = ' - $length = max(count($' . $x . '), count($' . $y . ')); - $' . $result . ' = array_pad($' . $x . ', $length + 1, 0); - $_' . $y . ' = array_pad($' . $y . ', $length, 0); - $carry = 0; - for ($i = 0, $j = 1; $j < $length; $i+=2, $j+=2) { - $sum = ($' . $result . '[$j] + $_' . $y . '[$j]) * ' . $class::BASE_FULL . ' - + $' . $result . '[$i] + $_' . $y . '[$i] + - $carry; - $carry = $sum >= ' . self::float2string($class::MAX_DIGIT2) . '; - $sum = $carry ? $sum - ' . self::float2string($class::MAX_DIGIT2) . ' : $sum;'; - - $code .= $class::BASE === 26 ? - '$upper = intval($sum / 0x4000000); $' . $result . '[$i] = (int) ($sum - ' . $class::BASE_FULL . ' * $upper);' : - '$upper = $sum >> 31; $' . $result . '[$i] = $sum - ' . $class::BASE_FULL . ' * $upper;'; - $code .= ' - $' . $result . '[$j] = $upper; - } - if ($j == $length) { - $sum = $' . $result . '[$i] + $_' . $y . '[$i] + $carry; - $carry = $sum >= ' . self::float2string($class::BASE_FULL) . '; - $' . $result . '[$i] = $carry ? $sum - ' . self::float2string($class::BASE_FULL) . ' : $sum; - ++$i; - } - if ($carry) { - for (; $' . $result . '[$i] == ' . $class::MAX_DIGIT . '; ++$i) { - $' . $result . '[$i] = 0; - } - ++$' . $result . '[$i]; - }'; - $code .= self::generateInlineTrim($result); - - return $code; - } - - /** - * Inline Subtraction 2 - * - * For when $known is more digits than $unknown. This is the harder use case to optimize for. - * - * @param string $known - * @param string $unknown - * @param string $result - * @param string $class - * @return string - */ - private static function generateInlineSubtract2($known, $unknown, $result, $class) - { - $code = ' - $' . $result . ' = $' . $known . '; - $carry = 0; - $size = count($' . $unknown . '); - for ($i = 0, $j = 1; $j < $size; $i+= 2, $j+= 2) { - $sum = ($' . $known . '[$j] - $' . $unknown . '[$j]) * ' . $class::BASE_FULL . ' + $' . $known . '[$i] - - $' . $unknown . '[$i] - - $carry; - $carry = $sum < 0; - if ($carry) { - $sum+= ' . self::float2string($class::MAX_DIGIT2) . '; - } - $subtemp = '; - $code .= $class::BASE === 26 ? - 'intval($sum / 0x4000000);' : - '$sum >> 31;'; - $code .= '$' . $result . '[$i] = '; - if ($class::BASE === 26) { - $code .= '(int) ('; - } - $code .= '$sum - ' . $class::BASE_FULL . ' * $subtemp'; - if ($class::BASE === 26) { - $code .= ')'; - } - $code .= '; - $' . $result . '[$j] = $subtemp; - } - if ($j == $size) { - $sum = $' . $known . '[$i] - $' . $unknown . '[$i] - $carry; - $carry = $sum < 0; - $' . $result . '[$i] = $carry ? $sum + ' . $class::BASE_FULL . ' : $sum; - ++$i; - } - - if ($carry) { - for (; !$' . $result . '[$i]; ++$i) { - $' . $result . '[$i] = ' . $class::MAX_DIGIT . '; - } - --$' . $result . '[$i]; - }'; - - $code .= self::generateInlineTrim($result); - - return $code; - } - - /** - * Inline Subtraction 1 - * - * For when $unknown is more digits than $known. This is the easier use case to optimize for. - * - * @param string $unknown - * @param array $known - * @param string $result - * @param string $class - * @return string - */ - private static function generateInlineSubtract1($unknown, array $known, $result, $class) - { - $code = '$' . $result . ' = $' . $unknown . ';'; - for ($i = 0, $j = 1; $j < count($known); $i += 2, $j += 2) { - $code .= '$sum = $' . $unknown . '[' . $j . '] * ' . $class::BASE_FULL . ' + $' . $unknown . '[' . $i . '] - '; - $code .= self::float2string($known[$j] * $class::BASE_FULL + $known[$i]); - if ($i != 0) { - $code .= ' - $carry'; - } - - $code .= '; - if ($carry = $sum < 0) { - $sum+= ' . self::float2string($class::MAX_DIGIT2) . '; - } - $subtemp = '; - $code .= $class::BASE === 26 ? - 'intval($sum / 0x4000000);' : - '$sum >> 31;'; - $code .= ' - $' . $result . '[' . $i . '] = '; - if ($class::BASE === 26) { - $code .= ' (int) ('; - } - $code .= '$sum - ' . $class::BASE_FULL . ' * $subtemp'; - if ($class::BASE === 26) { - $code .= ')'; - } - $code .= '; - $' . $result . '[' . $j . '] = $subtemp;'; - } - - $code .= '$i = ' . $i . ';'; - - if ($j == count($known)) { - $code .= ' - $sum = $' . $unknown . '[' . $i . '] - ' . $known[$i] . ' - $carry; - $carry = $sum < 0; - $' . $result . '[' . $i . '] = $carry ? $sum + ' . $class::BASE_FULL . ' : $sum; - ++$i;'; - } - - $code .= ' - if ($carry) { - for (; !$' . $result . '[$i]; ++$i) { - $' . $result . '[$i] = ' . $class::MAX_DIGIT . '; - } - --$' . $result . '[$i]; - }'; - $code .= self::generateInlineTrim($result); - - return $code; - } - - /** - * Inline Comparison - * - * If $unknown >= $known then loop - * - * @param array $known - * @param string $unknown - * @param string $subcode - * @return string - */ - private static function generateInlineCompare(array $known, $unknown, $subcode) - { - $uniqid = uniqid(); - $code = 'loop_' . $uniqid . ': - $clength = count($' . $unknown . '); - switch (true) { - case $clength < ' . count($known) . ': - goto end_' . $uniqid . '; - case $clength > ' . count($known) . ':'; - for ($i = count($known) - 1; $i >= 0; $i--) { - $code .= ' - case $' . $unknown . '[' . $i . '] > ' . $known[$i] . ': - goto subcode_' . $uniqid . '; - case $' . $unknown . '[' . $i . '] < ' . $known[$i] . ': - goto end_' . $uniqid . ';'; - } - $code .= ' - default: - // do subcode - } - - subcode_' . $uniqid . ':' . $subcode . ' - goto loop_' . $uniqid . '; - - end_' . $uniqid . ':'; - - return $code; - } - - /** - * Convert a float to a string - * - * If you do echo floatval(pow(2, 52)) you'll get 4.6116860184274E+18. It /can/ be displayed without a loss of - * precision but displayed in this way there will be precision loss, hence the need for this method. - * - * @param int|float $num - * @return string - */ - private static function float2string($num) - { - if (!is_float($num)) { - return (string) $num; - } - - if ($num < 0) { - return '-' . self::float2string(abs($num)); - } - - $temp = ''; - while ($num) { - $temp = fmod($num, 10) . $temp; - $num = floor($num / 10); - } - - return $temp; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Montgomery.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Montgomery.php deleted file mode 100644 index a34035e7..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Montgomery.php +++ /dev/null @@ -1,126 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines\PHP\Reductions; - -use phpseclib3\Math\BigInteger\Engines\PHP\Montgomery as Progenitor; - -/** - * PHP Montgomery Modular Exponentiation Engine - * - * @author Jim Wigginton - */ -abstract class Montgomery extends Progenitor -{ - /** - * Prepare a number for use in Montgomery Modular Reductions - * - * @param array $x - * @param array $n - * @param string $class - * @return array - */ - protected static function prepareReduce(array $x, array $n, $class) - { - $lhs = new $class(); - $lhs->value = array_merge(self::array_repeat(0, count($n)), $x); - $rhs = new $class(); - $rhs->value = $n; - - list(, $temp) = $lhs->divide($rhs); - return $temp->value; - } - - /** - * Montgomery Multiply - * - * Interleaves the montgomery reduction and long multiplication algorithms together as described in - * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=13 HAC 14.36} - * - * @param array $x - * @param array $n - * @param string $class - * @return array - */ - protected static function reduce(array $x, array $n, $class) - { - static $cache = [ - self::VARIABLE => [], - self::DATA => [] - ]; - - if (($key = array_search($n, $cache[self::VARIABLE])) === false) { - $key = count($cache[self::VARIABLE]); - $cache[self::VARIABLE][] = $x; - $cache[self::DATA][] = self::modInverse67108864($n, $class); - } - - $k = count($n); - - $result = [self::VALUE => $x]; - - for ($i = 0; $i < $k; ++$i) { - $temp = $result[self::VALUE][$i] * $cache[self::DATA][$key]; - $temp = $temp - $class::BASE_FULL * ($class::BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31)); - $temp = $class::regularMultiply([$temp], $n); - $temp = array_merge(self::array_repeat(0, $i), $temp); - $result = $class::addHelper($result[self::VALUE], false, $temp, false); - } - - $result[self::VALUE] = array_slice($result[self::VALUE], $k); - - if (self::compareHelper($result, false, $n, false) >= 0) { - $result = $class::subtractHelper($result[self::VALUE], false, $n, false); - } - - return $result[self::VALUE]; - } - - /** - * Modular Inverse of a number mod 2**26 (eg. 67108864) - * - * Based off of the bnpInvDigit function implemented and justified in the following URL: - * - * {@link http://www-cs-students.stanford.edu/~tjw/jsbn/jsbn.js} - * - * The following URL provides more info: - * - * {@link http://groups.google.com/group/sci.crypt/msg/7a137205c1be7d85} - * - * As for why we do all the bitmasking... strange things can happen when converting from floats to ints. For - * instance, on some computers, var_dump((int) -4294967297) yields int(-1) and on others, it yields - * int(-2147483648). To avoid problems stemming from this, we use bitmasks to guarantee that ints aren't - * auto-converted to floats. The outermost bitmask is present because without it, there's no guarantee that - * the "residue" returned would be the so-called "common residue". We use fmod, in the last step, because the - * maximum possible $x is 26 bits and the maximum $result is 16 bits. Thus, we have to be able to handle up to - * 40 bits, which only 64-bit floating points will support. - * - * Thanks to Pedro Gimeno Fortea for input! - * - * @param array $x - * @param string $class - * @return int - */ - protected static function modInverse67108864(array $x, $class) // 2**26 == 67,108,864 - { - $x = -$x[0]; - $result = $x & 0x3; // x**-1 mod 2**2 - $result = ($result * (2 - $x * $result)) & 0xF; // x**-1 mod 2**4 - $result = ($result * (2 - ($x & 0xFF) * $result)) & 0xFF; // x**-1 mod 2**8 - $result = ($result * ((2 - ($x & 0xFFFF) * $result) & 0xFFFF)) & 0xFFFF; // x**-1 mod 2**16 - $result = $class::BASE == 26 ? - fmod($result * (2 - fmod($x * $result, $class::BASE_FULL)), $class::BASE_FULL) : // x**-1 mod 2**26 - ($result * (2 - ($x * $result) % $class::BASE_FULL)) % $class::BASE_FULL; - return $result & $class::MAX_DIGIT; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/MontgomeryMult.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/MontgomeryMult.php deleted file mode 100644 index 4fed3c3f..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/MontgomeryMult.php +++ /dev/null @@ -1,76 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines\PHP\Reductions; - -use phpseclib3\Math\BigInteger\Engines\PHP; - -/** - * PHP Montgomery Modular Exponentiation Engine with interleaved multiplication - * - * @author Jim Wigginton - */ -abstract class MontgomeryMult extends Montgomery -{ - /** - * Montgomery Multiply - * - * Interleaves the montgomery reduction and long multiplication algorithms together as described in - * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=13 HAC 14.36} - * - * @see self::_prepMontgomery() - * @see self::_montgomery() - * @param array $x - * @param array $y - * @param array $m - * @param class-string $class - * @return array - */ - public static function multiplyReduce(array $x, array $y, array $m, $class) - { - // the following code, although not callable, can be run independently of the above code - // although the above code performed better in my benchmarks the following could might - // perform better under different circumstances. in lieu of deleting it it's just been - // made uncallable - - static $cache = [ - self::VARIABLE => [], - self::DATA => [] - ]; - - if (($key = array_search($m, $cache[self::VARIABLE])) === false) { - $key = count($cache[self::VARIABLE]); - $cache[self::VARIABLE][] = $m; - $cache[self::DATA][] = self::modInverse67108864($m, $class); - } - - $n = max(count($x), count($y), count($m)); - $x = array_pad($x, $n, 0); - $y = array_pad($y, $n, 0); - $m = array_pad($m, $n, 0); - $a = [self::VALUE => self::array_repeat(0, $n + 1)]; - for ($i = 0; $i < $n; ++$i) { - $temp = $a[self::VALUE][0] + $x[$i] * $y[0]; - $temp = $temp - $class::BASE_FULL * ($class::BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31)); - $temp = $temp * $cache[self::DATA][$key]; - $temp = $temp - $class::BASE_FULL * ($class::BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31)); - $temp = $class::addHelper($class::regularMultiply([$x[$i]], $y), false, $class::regularMultiply([$temp], $m), false); - $a = $class::addHelper($a[self::VALUE], false, $temp[self::VALUE], false); - $a[self::VALUE] = array_slice($a[self::VALUE], 1); - } - if (self::compareHelper($a[self::VALUE], false, $m, false) >= 0) { - $a = $class::subtractHelper($a[self::VALUE], false, $m, false); - } - return $a[self::VALUE]; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/PowerOfTwo.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/PowerOfTwo.php deleted file mode 100644 index 9da133a1..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/PowerOfTwo.php +++ /dev/null @@ -1,59 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines\PHP\Reductions; - -use phpseclib3\Math\BigInteger\Engines\PHP\Base; - -/** - * PHP Power Of Two Modular Exponentiation Engine - * - * @author Jim Wigginton - */ -abstract class PowerOfTwo extends Base -{ - /** - * Prepare a number for use in Montgomery Modular Reductions - * - * @param array $x - * @param array $n - * @param string $class - * @return array - */ - protected static function prepareReduce(array $x, array $n, $class) - { - return self::reduce($x, $n, $class); - } - - /** - * Power Of Two Reduction - * - * @param array $x - * @param array $n - * @param string $class - * @return array - */ - protected static function reduce(array $x, array $n, $class) - { - $lhs = new $class(); - $lhs->value = $x; - $rhs = new $class(); - $rhs->value = $n; - - $temp = new $class(); - $temp->value = [1]; - - $result = $lhs->bitwise_and($rhs->subtract($temp)); - return $result->value; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP32.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP32.php deleted file mode 100644 index 964cd170..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP32.php +++ /dev/null @@ -1,371 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines; - -/** - * Pure-PHP 32-bit Engine. - * - * Uses 64-bit floats if int size is 4 bits - * - * @author Jim Wigginton - */ -class PHP32 extends PHP -{ - // Constants used by PHP.php - const BASE = 26; - const BASE_FULL = 0x4000000; - const MAX_DIGIT = 0x3FFFFFF; - const MSB = 0x2000000; - - /** - * MAX10 in greatest MAX10LEN satisfying - * MAX10 = 10**MAX10LEN <= 2**BASE. - */ - const MAX10 = 10000000; - - /** - * MAX10LEN in greatest MAX10LEN satisfying - * MAX10 = 10**MAX10LEN <= 2**BASE. - */ - const MAX10LEN = 7; - const MAX_DIGIT2 = 4503599627370496; - - /** - * Initialize a PHP32 BigInteger Engine instance - * - * @param int $base - * @see parent::initialize() - */ - protected function initialize($base) - { - if ($base != 256 && $base != -256) { - return parent::initialize($base); - } - - $val = $this->value; - $this->value = []; - $vals = &$this->value; - $i = strlen($val); - if (!$i) { - return; - } - - while (true) { - $i -= 4; - if ($i < 0) { - if ($i == -4) { - break; - } - $val = substr($val, 0, 4 + $i); - $val = str_pad($val, 4, "\0", STR_PAD_LEFT); - if ($val == "\0\0\0\0") { - break; - } - $i = 0; - } - list(, $digit) = unpack('N', substr($val, $i, 4)); - if ($digit < 0) { - $digit += 0xFFFFFFFF + 1; - } - $step = count($vals) & 3; - if ($step) { - $digit = floor($digit / pow(2, 2 * $step)); - } - if ($step != 3) { - $digit &= static::MAX_DIGIT; - $i++; - } - $vals[] = $digit; - } - while (end($vals) === 0) { - array_pop($vals); - } - reset($vals); - } - - /** - * Test for engine validity - * - * @see parent::__construct() - * @return bool - */ - public static function isValidEngine() - { - return PHP_INT_SIZE >= 4; - } - - /** - * Adds two BigIntegers. - * - * @param PHP32 $y - * @return PHP32 - */ - public function add(PHP32 $y) - { - $temp = self::addHelper($this->value, $this->is_negative, $y->value, $y->is_negative); - - return $this->convertToObj($temp); - } - - /** - * Subtracts two BigIntegers. - * - * @param PHP32 $y - * @return PHP32 - */ - public function subtract(PHP32 $y) - { - $temp = self::subtractHelper($this->value, $this->is_negative, $y->value, $y->is_negative); - - return $this->convertToObj($temp); - } - - /** - * Multiplies two BigIntegers. - * - * @param PHP32 $y - * @return PHP32 - */ - public function multiply(PHP32 $y) - { - $temp = self::multiplyHelper($this->value, $this->is_negative, $y->value, $y->is_negative); - - return $this->convertToObj($temp); - } - - /** - * Divides two BigIntegers. - * - * Returns an array whose first element contains the quotient and whose second element contains the - * "common residue". If the remainder would be positive, the "common residue" and the remainder are the - * same. If the remainder would be negative, the "common residue" is equal to the sum of the remainder - * and the divisor (basically, the "common residue" is the first positive modulo). - * - * @param PHP32 $y - * @return array{PHP32, PHP32} - */ - public function divide(PHP32 $y) - { - return $this->divideHelper($y); - } - - /** - * Calculates modular inverses. - * - * Say you have (30 mod 17 * x mod 17) mod 17 == 1. x can be found using modular inverses. - * @param PHP32 $n - * @return false|PHP32 - */ - public function modInverse(PHP32 $n) - { - return $this->modInverseHelper($n); - } - - /** - * Calculates modular inverses. - * - * Say you have (30 mod 17 * x mod 17) mod 17 == 1. x can be found using modular inverses. - * @param PHP32 $n - * @return PHP32[] - */ - public function extendedGCD(PHP32 $n) - { - return $this->extendedGCDHelper($n); - } - - /** - * Calculates the greatest common divisor - * - * Say you have 693 and 609. The GCD is 21. - * - * @param PHP32 $n - * @return PHP32 - */ - public function gcd(PHP32 $n) - { - return $this->extendedGCD($n)['gcd']; - } - - /** - * Logical And - * - * @param PHP32 $x - * @return PHP32 - */ - public function bitwise_and(PHP32 $x) - { - return $this->bitwiseAndHelper($x); - } - - /** - * Logical Or - * - * @param PHP32 $x - * @return PHP32 - */ - public function bitwise_or(PHP32 $x) - { - return $this->bitwiseOrHelper($x); - } - - /** - * Logical Exclusive Or - * - * @param PHP32 $x - * @return PHP32 - */ - public function bitwise_xor(PHP32 $x) - { - return $this->bitwiseXorHelper($x); - } - - /** - * Compares two numbers. - * - * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite. The reason for this is - * demonstrated thusly: - * - * $x > $y: $x->compare($y) > 0 - * $x < $y: $x->compare($y) < 0 - * $x == $y: $x->compare($y) == 0 - * - * Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y). - * - * {@internal Could return $this->subtract($x), but that's not as fast as what we do do.} - * - * @param PHP32 $y - * @return int in case < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal. - * @see self::equals() - */ - public function compare(PHP32 $y) - { - return $this->compareHelper($this->value, $this->is_negative, $y->value, $y->is_negative); - } - - /** - * Tests the equality of two numbers. - * - * If you need to see if one number is greater than or less than another number, use BigInteger::compare() - * - * @param PHP32 $x - * @return bool - */ - public function equals(PHP32 $x) - { - return $this->value === $x->value && $this->is_negative == $x->is_negative; - } - - /** - * Performs modular exponentiation. - * - * @param PHP32 $e - * @param PHP32 $n - * @return PHP32 - */ - public function modPow(PHP32 $e, PHP32 $n) - { - return $this->powModOuter($e, $n); - } - - /** - * Performs modular exponentiation. - * - * Alias for modPow(). - * - * @param PHP32 $e - * @param PHP32 $n - * @return PHP32 - */ - public function powMod(PHP32 $e, PHP32 $n) - { - return $this->powModOuter($e, $n); - } - - /** - * Generate a random prime number between a range - * - * If there's not a prime within the given range, false will be returned. - * - * @param PHP32 $min - * @param PHP32 $max - * @return false|PHP32 - */ - public static function randomRangePrime(PHP32 $min, PHP32 $max) - { - return self::randomRangePrimeOuter($min, $max); - } - - /** - * Generate a random number between a range - * - * Returns a random number between $min and $max where $min and $max - * can be defined using one of the two methods: - * - * BigInteger::randomRange($min, $max) - * BigInteger::randomRange($max, $min) - * - * @param PHP32 $min - * @param PHP32 $max - * @return PHP32 - */ - public static function randomRange(PHP32 $min, PHP32 $max) - { - return self::randomRangeHelper($min, $max); - } - - /** - * Performs exponentiation. - * - * @param PHP32 $n - * @return PHP32 - */ - public function pow(PHP32 $n) - { - return $this->powHelper($n); - } - - /** - * Return the minimum BigInteger between an arbitrary number of BigIntegers. - * - * @param PHP32 ...$nums - * @return PHP32 - */ - public static function min(PHP32 ...$nums) - { - return self::minHelper($nums); - } - - /** - * Return the maximum BigInteger between an arbitrary number of BigIntegers. - * - * @param PHP32 ...$nums - * @return PHP32 - */ - public static function max(PHP32 ...$nums) - { - return self::maxHelper($nums); - } - - /** - * Tests BigInteger to see if it is between two integers, inclusive - * - * @param PHP32 $min - * @param PHP32 $max - * @return bool - */ - public function between(PHP32 $min, PHP32 $max) - { - return $this->compare($min) >= 0 && $this->compare($max) <= 0; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP64.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP64.php deleted file mode 100644 index ca11c08d..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP64.php +++ /dev/null @@ -1,372 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math\BigInteger\Engines; - -/** - * Pure-PHP 64-bit Engine. - * - * Uses 64-bit integers if int size is 8 bits - * - * @author Jim Wigginton - */ -class PHP64 extends PHP -{ - // Constants used by PHP.php - const BASE = 31; - const BASE_FULL = 0x80000000; - const MAX_DIGIT = 0x7FFFFFFF; - const MSB = 0x40000000; - - /** - * MAX10 in greatest MAX10LEN satisfying - * MAX10 = 10**MAX10LEN <= 2**BASE. - */ - const MAX10 = 1000000000; - - /** - * MAX10LEN in greatest MAX10LEN satisfying - * MAX10 = 10**MAX10LEN <= 2**BASE. - */ - const MAX10LEN = 9; - const MAX_DIGIT2 = 4611686018427387904; - - /** - * Initialize a PHP64 BigInteger Engine instance - * - * @param int $base - * @see parent::initialize() - */ - protected function initialize($base) - { - if ($base != 256 && $base != -256) { - return parent::initialize($base); - } - - $val = $this->value; - $this->value = []; - $vals = &$this->value; - $i = strlen($val); - if (!$i) { - return; - } - - while (true) { - $i -= 4; - if ($i < 0) { - if ($i == -4) { - break; - } - $val = substr($val, 0, 4 + $i); - $val = str_pad($val, 4, "\0", STR_PAD_LEFT); - if ($val == "\0\0\0\0") { - break; - } - $i = 0; - } - list(, $digit) = unpack('N', substr($val, $i, 4)); - $step = count($vals) & 7; - if (!$step) { - $digit &= static::MAX_DIGIT; - $i++; - } else { - $shift = 8 - $step; - $digit >>= $shift; - $shift = 32 - $shift; - $digit &= (1 << $shift) - 1; - $temp = $i > 0 ? ord($val[$i - 1]) : 0; - $digit |= ($temp << $shift) & 0x7F000000; - } - $vals[] = $digit; - } - while (end($vals) === 0) { - array_pop($vals); - } - reset($vals); - } - - /** - * Test for engine validity - * - * @see parent::__construct() - * @return bool - */ - public static function isValidEngine() - { - return PHP_INT_SIZE >= 8; - } - - /** - * Adds two BigIntegers. - * - * @param PHP64 $y - * @return PHP64 - */ - public function add(PHP64 $y) - { - $temp = self::addHelper($this->value, $this->is_negative, $y->value, $y->is_negative); - - return $this->convertToObj($temp); - } - - /** - * Subtracts two BigIntegers. - * - * @param PHP64 $y - * @return PHP64 - */ - public function subtract(PHP64 $y) - { - $temp = self::subtractHelper($this->value, $this->is_negative, $y->value, $y->is_negative); - - return $this->convertToObj($temp); - } - - /** - * Multiplies two BigIntegers. - * - * @param PHP64 $y - * @return PHP64 - */ - public function multiply(PHP64 $y) - { - $temp = self::multiplyHelper($this->value, $this->is_negative, $y->value, $y->is_negative); - - return $this->convertToObj($temp); - } - - /** - * Divides two BigIntegers. - * - * Returns an array whose first element contains the quotient and whose second element contains the - * "common residue". If the remainder would be positive, the "common residue" and the remainder are the - * same. If the remainder would be negative, the "common residue" is equal to the sum of the remainder - * and the divisor (basically, the "common residue" is the first positive modulo). - * - * @param PHP64 $y - * @return array{PHP64, PHP64} - */ - public function divide(PHP64 $y) - { - return $this->divideHelper($y); - } - - /** - * Calculates modular inverses. - * - * Say you have (30 mod 17 * x mod 17) mod 17 == 1. x can be found using modular inverses. - * @param PHP64 $n - * @return false|PHP64 - */ - public function modInverse(PHP64 $n) - { - return $this->modInverseHelper($n); - } - - /** - * Calculates modular inverses. - * - * Say you have (30 mod 17 * x mod 17) mod 17 == 1. x can be found using modular inverses. - * @param PHP64 $n - * @return PHP64[] - */ - public function extendedGCD(PHP64 $n) - { - return $this->extendedGCDHelper($n); - } - - /** - * Calculates the greatest common divisor - * - * Say you have 693 and 609. The GCD is 21. - * - * @param PHP64 $n - * @return PHP64 - */ - public function gcd(PHP64 $n) - { - return $this->extendedGCD($n)['gcd']; - } - - /** - * Logical And - * - * @param PHP64 $x - * @return PHP64 - */ - public function bitwise_and(PHP64 $x) - { - return $this->bitwiseAndHelper($x); - } - - /** - * Logical Or - * - * @param PHP64 $x - * @return PHP64 - */ - public function bitwise_or(PHP64 $x) - { - return $this->bitwiseOrHelper($x); - } - - /** - * Logical Exclusive Or - * - * @param PHP64 $x - * @return PHP64 - */ - public function bitwise_xor(PHP64 $x) - { - return $this->bitwiseXorHelper($x); - } - - /** - * Compares two numbers. - * - * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite. The reason for this is - * demonstrated thusly: - * - * $x > $y: $x->compare($y) > 0 - * $x < $y: $x->compare($y) < 0 - * $x == $y: $x->compare($y) == 0 - * - * Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y). - * - * {@internal Could return $this->subtract($x), but that's not as fast as what we do do.} - * - * @param PHP64 $y - * @return int in case < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal. - * @see self::equals() - */ - public function compare(PHP64 $y) - { - return parent::compareHelper($this->value, $this->is_negative, $y->value, $y->is_negative); - } - - /** - * Tests the equality of two numbers. - * - * If you need to see if one number is greater than or less than another number, use BigInteger::compare() - * - * @param PHP64 $x - * @return bool - */ - public function equals(PHP64 $x) - { - return $this->value === $x->value && $this->is_negative == $x->is_negative; - } - - /** - * Performs modular exponentiation. - * - * @param PHP64 $e - * @param PHP64 $n - * @return PHP64 - */ - public function modPow(PHP64 $e, PHP64 $n) - { - return $this->powModOuter($e, $n); - } - - /** - * Performs modular exponentiation. - * - * Alias for modPow(). - * - * @param PHP64 $e - * @param PHP64 $n - * @return PHP64|false - */ - public function powMod(PHP64 $e, PHP64 $n) - { - return $this->powModOuter($e, $n); - } - - /** - * Generate a random prime number between a range - * - * If there's not a prime within the given range, false will be returned. - * - * @param PHP64 $min - * @param PHP64 $max - * @return false|PHP64 - */ - public static function randomRangePrime(PHP64 $min, PHP64 $max) - { - return self::randomRangePrimeOuter($min, $max); - } - - /** - * Generate a random number between a range - * - * Returns a random number between $min and $max where $min and $max - * can be defined using one of the two methods: - * - * BigInteger::randomRange($min, $max) - * BigInteger::randomRange($max, $min) - * - * @param PHP64 $min - * @param PHP64 $max - * @return PHP64 - */ - public static function randomRange(PHP64 $min, PHP64 $max) - { - return self::randomRangeHelper($min, $max); - } - - /** - * Performs exponentiation. - * - * @param PHP64 $n - * @return PHP64 - */ - public function pow(PHP64 $n) - { - return $this->powHelper($n); - } - - /** - * Return the minimum BigInteger between an arbitrary number of BigIntegers. - * - * @param PHP64 ...$nums - * @return PHP64 - */ - public static function min(PHP64 ...$nums) - { - return self::minHelper($nums); - } - - /** - * Return the maximum BigInteger between an arbitrary number of BigIntegers. - * - * @param PHP64 ...$nums - * @return PHP64 - */ - public static function max(PHP64 ...$nums) - { - return self::maxHelper($nums); - } - - /** - * Tests BigInteger to see if it is between two integers, inclusive - * - * @param PHP64 $min - * @param PHP64 $max - * @return bool - */ - public function between(PHP64 $min, PHP64 $max) - { - return $this->compare($min) >= 0 && $this->compare($max) <= 0; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BinaryField.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BinaryField.php deleted file mode 100644 index 3e21a67a..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BinaryField.php +++ /dev/null @@ -1,194 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - */ - -namespace phpseclib3\Math; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Math\BinaryField\Integer; -use phpseclib3\Math\Common\FiniteField; - -/** - * Binary Finite Fields - * - * @author Jim Wigginton - */ -class BinaryField extends FiniteField -{ - /** - * Instance Counter - * - * @var int - */ - private static $instanceCounter = 0; - - /** - * Keeps track of current instance - * - * @var int - */ - protected $instanceID; - - /** @var BigInteger */ - private $randomMax; - - /** - * Default constructor - */ - public function __construct(...$indices) - { - $m = array_shift($indices); - $val = str_repeat('0', $m) . '1'; - foreach ($indices as $index) { - $val[$index] = '1'; - } - $modulo = static::base2ToBase256(strrev($val)); - - $mStart = 2 * $m - 2; - $t = ceil($m / 8); - $finalMask = chr((1 << ($m % 8)) - 1); - if ($finalMask == "\0") { - $finalMask = "\xFF"; - } - $bitLen = $mStart + 1; - $pad = ceil($bitLen / 8); - $h = $bitLen & 7; - $h = $h ? 8 - $h : 0; - - $r = rtrim(substr($val, 0, -1), '0'); - $u = [static::base2ToBase256(strrev($r))]; - for ($i = 1; $i < 8; $i++) { - $u[] = static::base2ToBase256(strrev(str_repeat('0', $i) . $r)); - } - - // implements algorithm 2.40 (in section 2.3.5) in "Guide to Elliptic Curve Cryptography" - // with W = 8 - $reduce = function ($c) use ($u, $mStart, $m, $t, $finalMask, $pad, $h) { - $c = str_pad($c, $pad, "\0", STR_PAD_LEFT); - for ($i = $mStart; $i >= $m;) { - $g = $h >> 3; - $mask = $h & 7; - $mask = $mask ? 1 << (7 - $mask) : 0x80; - for (; $mask > 0; $mask >>= 1, $i--, $h++) { - if (ord($c[$g]) & $mask) { - $temp = $i - $m; - $j = $temp >> 3; - $k = $temp & 7; - $t1 = $j ? substr($c, 0, -$j) : $c; - $length = strlen($t1); - if ($length) { - $t2 = str_pad($u[$k], $length, "\0", STR_PAD_LEFT); - $temp = $t1 ^ $t2; - $c = $j ? substr_replace($c, $temp, 0, $length) : $temp; - } - } - } - } - $c = substr($c, -$t); - if (strlen($c) == $t) { - $c[0] = $c[0] & $finalMask; - } - return ltrim($c, "\0"); - }; - - $this->instanceID = self::$instanceCounter++; - Integer::setModulo($this->instanceID, $modulo); - Integer::setRecurringModuloFunction($this->instanceID, $reduce); - - $this->randomMax = new BigInteger($modulo, 2); - } - - /** - * Returns an instance of a dynamically generated PrimeFieldInteger class - * - * @param string $num - * @return Integer - */ - public function newInteger($num) - { - return new Integer($this->instanceID, $num instanceof BigInteger ? $num->toBytes() : $num); - } - - /** - * Returns an integer on the finite field between one and the prime modulo - * - * @return Integer - */ - public function randomInteger() - { - static $one; - if (!isset($one)) { - $one = new BigInteger(1); - } - - return new Integer($this->instanceID, BigInteger::randomRange($one, $this->randomMax)->toBytes()); - } - - /** - * Returns the length of the modulo in bytes - * - * @return int - */ - public function getLengthInBytes() - { - return strlen(Integer::getModulo($this->instanceID)); - } - - /** - * Returns the length of the modulo in bits - * - * @return int - */ - public function getLength() - { - return strlen(Integer::getModulo($this->instanceID)) << 3; - } - - /** - * Converts a base-2 string to a base-256 string - * - * @param string $x - * @param int|null $size - * @return string - */ - public static function base2ToBase256($x, $size = null) - { - $str = Strings::bits2bin($x); - - $pad = strlen($x) >> 3; - if (strlen($x) & 3) { - $pad++; - } - $str = str_pad($str, $pad, "\0", STR_PAD_LEFT); - if (isset($size)) { - $str = str_pad($str, $size, "\0", STR_PAD_LEFT); - } - - return $str; - } - - /** - * Converts a base-256 string to a base-2 string - * - * @param string $x - * @return string - */ - public static function base256ToBase2($x) - { - if (function_exists('gmp_import')) { - return gmp_strval(gmp_import($x), 2); - } - - return Strings::bin2bits($x); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BinaryField/Integer.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BinaryField/Integer.php deleted file mode 100644 index 8e880589..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/BinaryField/Integer.php +++ /dev/null @@ -1,516 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - */ - -namespace phpseclib3\Math\BinaryField; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Math\BigInteger; -use phpseclib3\Math\BinaryField; -use phpseclib3\Math\Common\FiniteField\Integer as Base; - -/** - * Binary Finite Fields - * - * @author Jim Wigginton - */ -class Integer extends Base -{ - /** - * Holds the BinaryField's value - * - * @var string - */ - protected $value; - - /** - * Keeps track of current instance - * - * @var int - */ - protected $instanceID; - - /** - * Holds the PrimeField's modulo - * - * @var array - */ - protected static $modulo; - - /** - * Holds a pre-generated function to perform modulo reductions - * - * @var callable[] - */ - protected static $reduce; - - /** - * Default constructor - */ - public function __construct($instanceID, $num = '') - { - $this->instanceID = $instanceID; - if (!strlen($num)) { - $this->value = ''; - } else { - $reduce = static::$reduce[$instanceID]; - $this->value = $reduce($num); - } - } - - /** - * Set the modulo for a given instance - * @param int $instanceID - * @param string $modulo - */ - public static function setModulo($instanceID, $modulo) - { - static::$modulo[$instanceID] = $modulo; - } - - /** - * Set the modulo for a given instance - */ - public static function setRecurringModuloFunction($instanceID, callable $function) - { - static::$reduce[$instanceID] = $function; - } - - /** - * Tests a parameter to see if it's of the right instance - * - * Throws an exception if the incorrect class is being utilized - */ - private static function checkInstance(self $x, self $y) - { - if ($x->instanceID != $y->instanceID) { - throw new \UnexpectedValueException('The instances of the two BinaryField\Integer objects do not match'); - } - } - - /** - * Tests the equality of two numbers. - * - * @return bool - */ - public function equals(self $x) - { - static::checkInstance($this, $x); - - return $this->value == $x->value; - } - - /** - * Compares two numbers. - * - * @return int - */ - public function compare(self $x) - { - static::checkInstance($this, $x); - - $a = $this->value; - $b = $x->value; - - $length = max(strlen($a), strlen($b)); - - $a = str_pad($a, $length, "\0", STR_PAD_LEFT); - $b = str_pad($b, $length, "\0", STR_PAD_LEFT); - - return strcmp($a, $b); - } - - /** - * Returns the degree of the polynomial - * - * @param string $x - * @return int - */ - private static function deg($x) - { - $x = ltrim($x, "\0"); - $xbit = decbin(ord($x[0])); - $xlen = $xbit == '0' ? 0 : strlen($xbit); - $len = strlen($x); - if (!$len) { - return -1; - } - return 8 * strlen($x) - 9 + $xlen; - } - - /** - * Perform polynomial division - * - * @return string[] - * @link https://en.wikipedia.org/wiki/Polynomial_greatest_common_divisor#Euclidean_division - */ - private static function polynomialDivide($x, $y) - { - // in wikipedia's description of the algorithm, lc() is the leading coefficient. over a binary field that's - // always going to be 1. - - $q = chr(0); - $d = static::deg($y); - $r = $x; - while (($degr = static::deg($r)) >= $d) { - $s = '1' . str_repeat('0', $degr - $d); - $s = BinaryField::base2ToBase256($s); - $length = max(strlen($s), strlen($q)); - $q = !isset($q) ? $s : - str_pad($q, $length, "\0", STR_PAD_LEFT) ^ - str_pad($s, $length, "\0", STR_PAD_LEFT); - $s = static::polynomialMultiply($s, $y); - $length = max(strlen($r), strlen($s)); - $r = str_pad($r, $length, "\0", STR_PAD_LEFT) ^ - str_pad($s, $length, "\0", STR_PAD_LEFT); - } - - return [ltrim($q, "\0"), ltrim($r, "\0")]; - } - - /** - * Perform polynomial multiplation in the traditional way - * - * @return string - * @link https://en.wikipedia.org/wiki/Finite_field_arithmetic#Multiplication - */ - private static function regularPolynomialMultiply($x, $y) - { - $precomputed = [ltrim($x, "\0")]; - $x = strrev(BinaryField::base256ToBase2($x)); - $y = strrev(BinaryField::base256ToBase2($y)); - if (strlen($x) == strlen($y)) { - $length = strlen($x); - } else { - $length = max(strlen($x), strlen($y)); - $x = str_pad($x, $length, '0'); - $y = str_pad($y, $length, '0'); - } - $result = str_repeat('0', 2 * $length - 1); - $result = BinaryField::base2ToBase256($result); - $size = strlen($result); - $x = strrev($x); - - // precompute left shift 1 through 7 - for ($i = 1; $i < 8; $i++) { - $precomputed[$i] = BinaryField::base2ToBase256($x . str_repeat('0', $i)); - } - for ($i = 0; $i < strlen($y); $i++) { - if ($y[$i] == '1') { - $temp = $precomputed[$i & 7] . str_repeat("\0", $i >> 3); - $result ^= str_pad($temp, $size, "\0", STR_PAD_LEFT); - } - } - - return $result; - } - - /** - * Perform polynomial multiplation - * - * Uses karatsuba multiplication to reduce x-bit multiplications to a series of 32-bit multiplications - * - * @return string - * @link https://en.wikipedia.org/wiki/Karatsuba_algorithm - */ - private static function polynomialMultiply($x, $y) - { - if (strlen($x) == strlen($y)) { - $length = strlen($x); - } else { - $length = max(strlen($x), strlen($y)); - $x = str_pad($x, $length, "\0", STR_PAD_LEFT); - $y = str_pad($y, $length, "\0", STR_PAD_LEFT); - } - - switch (true) { - case PHP_INT_SIZE == 8 && $length <= 4: - return $length != 4 ? - self::subMultiply(str_pad($x, 4, "\0", STR_PAD_LEFT), str_pad($y, 4, "\0", STR_PAD_LEFT)) : - self::subMultiply($x, $y); - case PHP_INT_SIZE == 4 || $length > 32: - return self::regularPolynomialMultiply($x, $y); - } - - $m = $length >> 1; - - $x1 = substr($x, 0, -$m); - $x0 = substr($x, -$m); - $y1 = substr($y, 0, -$m); - $y0 = substr($y, -$m); - - $z2 = self::polynomialMultiply($x1, $y1); - $z0 = self::polynomialMultiply($x0, $y0); - $z1 = self::polynomialMultiply( - self::subAdd2($x1, $x0), - self::subAdd2($y1, $y0) - ); - - $z1 = self::subAdd3($z1, $z2, $z0); - - $xy = self::subAdd3( - $z2 . str_repeat("\0", 2 * $m), - $z1 . str_repeat("\0", $m), - $z0 - ); - - return ltrim($xy, "\0"); - } - - /** - * Perform polynomial multiplication on 2x 32-bit numbers, returning - * a 64-bit number - * - * @param string $x - * @param string $y - * @return string - * @link https://www.bearssl.org/constanttime.html#ghash-for-gcm - */ - private static function subMultiply($x, $y) - { - $x = unpack('N', $x)[1]; - $y = unpack('N', $y)[1]; - - $x0 = $x & 0x11111111; - $x1 = $x & 0x22222222; - $x2 = $x & 0x44444444; - $x3 = $x & 0x88888888; - - $y0 = $y & 0x11111111; - $y1 = $y & 0x22222222; - $y2 = $y & 0x44444444; - $y3 = $y & 0x88888888; - - $z0 = ($x0 * $y0) ^ ($x1 * $y3) ^ ($x2 * $y2) ^ ($x3 * $y1); - $z1 = ($x0 * $y1) ^ ($x1 * $y0) ^ ($x2 * $y3) ^ ($x3 * $y2); - $z2 = ($x0 * $y2) ^ ($x1 * $y1) ^ ($x2 * $y0) ^ ($x3 * $y3); - $z3 = ($x0 * $y3) ^ ($x1 * $y2) ^ ($x2 * $y1) ^ ($x3 * $y0); - - $z0 &= 0x1111111111111111; - $z1 &= 0x2222222222222222; - $z2 &= 0x4444444444444444; - $z3 &= -8608480567731124088; // 0x8888888888888888 gets interpreted as a float - - $z = $z0 | $z1 | $z2 | $z3; - - return pack('J', $z); - } - - /** - * Adds two numbers - * - * @param string $x - * @param string $y - * @return string - */ - private static function subAdd2($x, $y) - { - $length = max(strlen($x), strlen($y)); - $x = str_pad($x, $length, "\0", STR_PAD_LEFT); - $y = str_pad($y, $length, "\0", STR_PAD_LEFT); - return $x ^ $y; - } - - /** - * Adds three numbers - * - * @param string $x - * @param string $y - * @return string - */ - private static function subAdd3($x, $y, $z) - { - $length = max(strlen($x), strlen($y), strlen($z)); - $x = str_pad($x, $length, "\0", STR_PAD_LEFT); - $y = str_pad($y, $length, "\0", STR_PAD_LEFT); - $z = str_pad($z, $length, "\0", STR_PAD_LEFT); - return $x ^ $y ^ $z; - } - - /** - * Adds two BinaryFieldIntegers. - * - * @return static - */ - public function add(self $y) - { - static::checkInstance($this, $y); - - $length = strlen(static::$modulo[$this->instanceID]); - - $x = str_pad($this->value, $length, "\0", STR_PAD_LEFT); - $y = str_pad($y->value, $length, "\0", STR_PAD_LEFT); - - return new static($this->instanceID, $x ^ $y); - } - - /** - * Subtracts two BinaryFieldIntegers. - * - * @return static - */ - public function subtract(self $x) - { - return $this->add($x); - } - - /** - * Multiplies two BinaryFieldIntegers. - * - * @return static - */ - public function multiply(self $y) - { - static::checkInstance($this, $y); - - return new static($this->instanceID, static::polynomialMultiply($this->value, $y->value)); - } - - /** - * Returns the modular inverse of a BinaryFieldInteger - * - * @return static - */ - public function modInverse() - { - $remainder0 = static::$modulo[$this->instanceID]; - $remainder1 = $this->value; - - if ($remainder1 == '') { - return new static($this->instanceID); - } - - $aux0 = "\0"; - $aux1 = "\1"; - while ($remainder1 != "\1") { - list($q, $r) = static::polynomialDivide($remainder0, $remainder1); - $remainder0 = $remainder1; - $remainder1 = $r; - // the auxiliary in row n is given by the sum of the auxiliary in - // row n-2 and the product of the quotient and the auxiliary in row - // n-1 - $temp = static::polynomialMultiply($aux1, $q); - $aux = str_pad($aux0, strlen($temp), "\0", STR_PAD_LEFT) ^ - str_pad($temp, strlen($aux0), "\0", STR_PAD_LEFT); - $aux0 = $aux1; - $aux1 = $aux; - } - - $temp = new static($this->instanceID); - $temp->value = ltrim($aux1, "\0"); - return $temp; - } - - /** - * Divides two PrimeFieldIntegers. - * - * @return static - */ - public function divide(self $x) - { - static::checkInstance($this, $x); - - $x = $x->modInverse(); - return $this->multiply($x); - } - - /** - * Negate - * - * A negative number can be written as 0-12. With modulos, 0 is the same thing as the modulo - * so 0-12 is the same thing as modulo-12 - * - * @return object - */ - public function negate() - { - $x = str_pad($this->value, strlen(static::$modulo[$this->instanceID]), "\0", STR_PAD_LEFT); - - return new static($this->instanceID, $x ^ static::$modulo[$this->instanceID]); - } - - /** - * Returns the modulo - * - * @return string - */ - public static function getModulo($instanceID) - { - return static::$modulo[$instanceID]; - } - - /** - * Converts an Integer to a byte string (eg. base-256). - * - * @return string - */ - public function toBytes() - { - return str_pad($this->value, strlen(static::$modulo[$this->instanceID]), "\0", STR_PAD_LEFT); - } - - /** - * Converts an Integer to a hex string (eg. base-16). - * - * @return string - */ - public function toHex() - { - return Strings::bin2hex($this->toBytes()); - } - - /** - * Converts an Integer to a bit string (eg. base-2). - * - * @return string - */ - public function toBits() - { - //return str_pad(BinaryField::base256ToBase2($this->value), strlen(static::$modulo[$this->instanceID]), '0', STR_PAD_LEFT); - return BinaryField::base256ToBase2($this->value); - } - - /** - * Converts an Integer to a BigInteger - * - * @return string - */ - public function toBigInteger() - { - return new BigInteger($this->value, 256); - } - - /** - * __toString() magic method - * - */ - public function __toString() - { - return (string) $this->toBigInteger(); - } - - /** - * __debugInfo() magic method - * - */ - public function __debugInfo() - { - return ['value' => $this->toHex()]; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/Common/FiniteField.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/Common/FiniteField.php deleted file mode 100644 index 2ea5f485..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/Common/FiniteField.php +++ /dev/null @@ -1,22 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - */ - -namespace phpseclib3\Math\Common; - -/** - * Finite Fields - * - * @author Jim Wigginton - */ -abstract class FiniteField -{ -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/Common/FiniteField/Integer.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/Common/FiniteField/Integer.php deleted file mode 100644 index 3c959e94..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/Common/FiniteField/Integer.php +++ /dev/null @@ -1,44 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - */ - -namespace phpseclib3\Math\Common\FiniteField; - -/** - * Finite Field Integer - * - * @author Jim Wigginton - */ -abstract class Integer implements \JsonSerializable -{ - /** - * JSON Serialize - * - * Will be called, automatically, when json_encode() is called on a BigInteger object. - * - * PHP Serialize isn't supported because unserializing would require the factory be - * serialized as well and that just sounds like too much - * - * @return array{hex: string} - */ - #[\ReturnTypeWillChange] - public function jsonSerialize() - { - return ['hex' => $this->toHex(true)]; - } - - /** - * Converts an Integer to a hex string (eg. base-16). - * - * @return string - */ - abstract public function toHex(); -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/PrimeField.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/PrimeField.php deleted file mode 100644 index 1a0667f0..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/PrimeField.php +++ /dev/null @@ -1,118 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger - */ - -namespace phpseclib3\Math; - -use phpseclib3\Math\Common\FiniteField; -use phpseclib3\Math\PrimeField\Integer; - -/** - * Prime Finite Fields - * - * @author Jim Wigginton - */ -class PrimeField extends FiniteField -{ - /** - * Instance Counter - * - * @var int - */ - private static $instanceCounter = 0; - - /** - * Keeps track of current instance - * - * @var int - */ - protected $instanceID; - - /** - * Default constructor - */ - public function __construct(BigInteger $modulo) - { - if (!$modulo->isPrime()) { - throw new \UnexpectedValueException('PrimeField requires a prime number be passed to the constructor'); - } - - $this->instanceID = self::$instanceCounter++; - Integer::setModulo($this->instanceID, $modulo); - Integer::setRecurringModuloFunction($this->instanceID, $modulo->createRecurringModuloFunction()); - } - - /** - * Use a custom defined modular reduction function - * - * @return void - */ - public function setReduction(\Closure $func) - { - $this->reduce = $func->bindTo($this, $this); - } - - /** - * Returns an instance of a dynamically generated PrimeFieldInteger class - * - * @return Integer - */ - public function newInteger(BigInteger $num) - { - return new Integer($this->instanceID, $num); - } - - /** - * Returns an integer on the finite field between one and the prime modulo - * - * @return Integer - */ - public function randomInteger() - { - static $one; - if (!isset($one)) { - $one = new BigInteger(1); - } - - return new Integer($this->instanceID, BigInteger::randomRange($one, Integer::getModulo($this->instanceID))); - } - - /** - * Returns the length of the modulo in bytes - * - * @return int - */ - public function getLengthInBytes() - { - return Integer::getModulo($this->instanceID)->getLengthInBytes(); - } - - /** - * Returns the length of the modulo in bits - * - * @return int - */ - public function getLength() - { - return Integer::getModulo($this->instanceID)->getLength(); - } - - /** - * Destructor - */ - public function __destruct() - { - Integer::cleanupCache($this->instanceID); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/PrimeField/Integer.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/PrimeField/Integer.php deleted file mode 100644 index 748f9a49..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Math/PrimeField/Integer.php +++ /dev/null @@ -1,416 +0,0 @@ - - * @copyright 2017 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - */ - -namespace phpseclib3\Math\PrimeField; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Math\BigInteger; -use phpseclib3\Math\Common\FiniteField\Integer as Base; - -/** - * Prime Finite Fields - * - * @author Jim Wigginton - */ -class Integer extends Base -{ - /** - * Holds the PrimeField's value - * - * @var BigInteger - */ - protected $value; - - /** - * Keeps track of current instance - * - * @var int - */ - protected $instanceID; - - /** - * Holds the PrimeField's modulo - * - * @var array - */ - protected static $modulo; - - /** - * Holds a pre-generated function to perform modulo reductions - * - * @var array - */ - protected static $reduce; - - /** - * Zero - * - * @var BigInteger - */ - protected static $zero; - - /** - * Default constructor - * - * @param int $instanceID - */ - public function __construct($instanceID, BigInteger $num = null) - { - $this->instanceID = $instanceID; - if (!isset($num)) { - $this->value = clone static::$zero[static::class]; - } else { - $reduce = static::$reduce[$instanceID]; - $this->value = $reduce($num); - } - } - - /** - * Set the modulo for a given instance - * - * @param int $instanceID - * @return void - */ - public static function setModulo($instanceID, BigInteger $modulo) - { - static::$modulo[$instanceID] = $modulo; - } - - /** - * Set the modulo for a given instance - * - * @param int $instanceID - * @return void - */ - public static function setRecurringModuloFunction($instanceID, callable $function) - { - static::$reduce[$instanceID] = $function; - if (!isset(static::$zero[static::class])) { - static::$zero[static::class] = new BigInteger(); - } - } - - /** - * Delete the modulo for a given instance - */ - public static function cleanupCache($instanceID) - { - unset(static::$modulo[$instanceID]); - unset(static::$reduce[$instanceID]); - } - - /** - * Returns the modulo - * - * @param int $instanceID - * @return BigInteger - */ - public static function getModulo($instanceID) - { - return static::$modulo[$instanceID]; - } - - /** - * Tests a parameter to see if it's of the right instance - * - * Throws an exception if the incorrect class is being utilized - * - * @return void - */ - public static function checkInstance(self $x, self $y) - { - if ($x->instanceID != $y->instanceID) { - throw new \UnexpectedValueException('The instances of the two PrimeField\Integer objects do not match'); - } - } - - /** - * Tests the equality of two numbers. - * - * @return bool - */ - public function equals(self $x) - { - static::checkInstance($this, $x); - - return $this->value->equals($x->value); - } - - /** - * Compares two numbers. - * - * @return int - */ - public function compare(self $x) - { - static::checkInstance($this, $x); - - return $this->value->compare($x->value); - } - - /** - * Adds two PrimeFieldIntegers. - * - * @return static - */ - public function add(self $x) - { - static::checkInstance($this, $x); - - $temp = new static($this->instanceID); - $temp->value = $this->value->add($x->value); - if ($temp->value->compare(static::$modulo[$this->instanceID]) >= 0) { - $temp->value = $temp->value->subtract(static::$modulo[$this->instanceID]); - } - - return $temp; - } - - /** - * Subtracts two PrimeFieldIntegers. - * - * @return static - */ - public function subtract(self $x) - { - static::checkInstance($this, $x); - - $temp = new static($this->instanceID); - $temp->value = $this->value->subtract($x->value); - if ($temp->value->isNegative()) { - $temp->value = $temp->value->add(static::$modulo[$this->instanceID]); - } - - return $temp; - } - - /** - * Multiplies two PrimeFieldIntegers. - * - * @return static - */ - public function multiply(self $x) - { - static::checkInstance($this, $x); - - return new static($this->instanceID, $this->value->multiply($x->value)); - } - - /** - * Divides two PrimeFieldIntegers. - * - * @return static - */ - public function divide(self $x) - { - static::checkInstance($this, $x); - - $denominator = $x->value->modInverse(static::$modulo[$this->instanceID]); - return new static($this->instanceID, $this->value->multiply($denominator)); - } - - /** - * Performs power operation on a PrimeFieldInteger. - * - * @return static - */ - public function pow(BigInteger $x) - { - $temp = new static($this->instanceID); - $temp->value = $this->value->powMod($x, static::$modulo[$this->instanceID]); - - return $temp; - } - - /** - * Calculates the square root - * - * @link https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm - * @return static|false - */ - public function squareRoot() - { - static $one, $two; - if (!isset($one)) { - $one = new BigInteger(1); - $two = new BigInteger(2); - } - $reduce = static::$reduce[$this->instanceID]; - $p_1 = static::$modulo[$this->instanceID]->subtract($one); - $q = clone $p_1; - $s = BigInteger::scan1divide($q); - list($pow) = $p_1->divide($two); - for ($z = $one; !$z->equals(static::$modulo[$this->instanceID]); $z = $z->add($one)) { - $temp = $z->powMod($pow, static::$modulo[$this->instanceID]); - if ($temp->equals($p_1)) { - break; - } - } - - $m = new BigInteger($s); - $c = $z->powMod($q, static::$modulo[$this->instanceID]); - $t = $this->value->powMod($q, static::$modulo[$this->instanceID]); - list($temp) = $q->add($one)->divide($two); - $r = $this->value->powMod($temp, static::$modulo[$this->instanceID]); - - while (!$t->equals($one)) { - for ($i == clone $one; $i->compare($m) < 0; $i = $i->add($one)) { - if ($t->powMod($two->pow($i), static::$modulo[$this->instanceID])->equals($one)) { - break; - } - } - - if ($i->compare($m) == 0) { - return false; - } - $b = $c->powMod($two->pow($m->subtract($i)->subtract($one)), static::$modulo[$this->instanceID]); - $m = $i; - $c = $reduce($b->multiply($b)); - $t = $reduce($t->multiply($c)); - $r = $reduce($r->multiply($b)); - } - - return new static($this->instanceID, $r); - } - - /** - * Is Odd? - * - * @return bool - */ - public function isOdd() - { - return $this->value->isOdd(); - } - - /** - * Negate - * - * A negative number can be written as 0-12. With modulos, 0 is the same thing as the modulo - * so 0-12 is the same thing as modulo-12 - * - * @return static - */ - public function negate() - { - return new static($this->instanceID, static::$modulo[$this->instanceID]->subtract($this->value)); - } - - /** - * Converts an Integer to a byte string (eg. base-256). - * - * @return string - */ - public function toBytes() - { - $length = static::$modulo[$this->instanceID]->getLengthInBytes(); - return str_pad($this->value->toBytes(), $length, "\0", STR_PAD_LEFT); - } - - /** - * Converts an Integer to a hex string (eg. base-16). - * - * @return string - */ - public function toHex() - { - return Strings::bin2hex($this->toBytes()); - } - - /** - * Converts an Integer to a bit string (eg. base-2). - * - * @return string - */ - public function toBits() - { - // return $this->value->toBits(); - static $length; - if (!isset($length)) { - $length = static::$modulo[$this->instanceID]->getLength(); - } - - return str_pad($this->value->toBits(), $length, '0', STR_PAD_LEFT); - } - - /** - * Returns the w-ary non-adjacent form (wNAF) - * - * @param int $w optional - * @return array - */ - public function getNAF($w = 1) - { - $w++; - - $mask = new BigInteger((1 << $w) - 1); - $sub = new BigInteger(1 << $w); - //$sub = new BigInteger(1 << ($w - 1)); - $d = $this->toBigInteger(); - $d_i = []; - - $i = 0; - while ($d->compare(static::$zero[static::class]) > 0) { - if ($d->isOdd()) { - // start mods - - $bigInteger = $d->testBit($w - 1) ? - $d->bitwise_and($mask)->subtract($sub) : - //$sub->subtract($d->bitwise_and($mask)) : - $d->bitwise_and($mask); - // end mods - $d = $d->subtract($bigInteger); - $d_i[$i] = (int) $bigInteger->toString(); - } else { - $d_i[$i] = 0; - } - $shift = !$d->equals(static::$zero[static::class]) && $d->bitwise_and($mask)->equals(static::$zero[static::class]) ? $w : 1; // $w or $w + 1? - $d = $d->bitwise_rightShift($shift); - while (--$shift > 0) { - $d_i[++$i] = 0; - } - $i++; - } - - return $d_i; - } - - /** - * Converts an Integer to a BigInteger - * - * @return BigInteger - */ - public function toBigInteger() - { - return clone $this->value; - } - - /** - * __toString() magic method - * - * @return string - */ - public function __toString() - { - return (string) $this->value; - } - - /** - * __debugInfo() magic method - * - * @return array - */ - public function __debugInfo() - { - return ['value' => $this->toHex()]; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php deleted file mode 100644 index 1c675a6e..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php +++ /dev/null @@ -1,3540 +0,0 @@ - - * login('username', 'password')) { - * exit('Login Failed'); - * } - * - * echo $sftp->pwd() . "\r\n"; - * $sftp->put('filename.ext', 'hello, world!'); - * print_r($sftp->nlist()); - * ?> - * - * - * @author Jim Wigginton - * @copyright 2009 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Net; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Exception\FileNotFoundException; - -/** - * Pure-PHP implementations of SFTP. - * - * @author Jim Wigginton - */ -class SFTP extends SSH2 -{ - /** - * SFTP channel constant - * - * \phpseclib3\Net\SSH2::exec() uses 0 and \phpseclib3\Net\SSH2::read() / \phpseclib3\Net\SSH2::write() use 1. - * - * @see \phpseclib3\Net\SSH2::send_channel_packet() - * @see \phpseclib3\Net\SSH2::get_channel_packet() - */ - const CHANNEL = 0x100; - - /** - * Reads data from a local file. - * - * @see \phpseclib3\Net\SFTP::put() - */ - const SOURCE_LOCAL_FILE = 1; - /** - * Reads data from a string. - * - * @see \phpseclib3\Net\SFTP::put() - */ - // this value isn't really used anymore but i'm keeping it reserved for historical reasons - const SOURCE_STRING = 2; - /** - * Reads data from callback: - * function callback($length) returns string to proceed, null for EOF - * - * @see \phpseclib3\Net\SFTP::put() - */ - const SOURCE_CALLBACK = 16; - /** - * Resumes an upload - * - * @see \phpseclib3\Net\SFTP::put() - */ - const RESUME = 4; - /** - * Append a local file to an already existing remote file - * - * @see \phpseclib3\Net\SFTP::put() - */ - const RESUME_START = 8; - - /** - * Packet Types - * - * @see self::__construct() - * @var array - * @access private - */ - private $packet_types = []; - - /** - * Status Codes - * - * @see self::__construct() - * @var array - * @access private - */ - private $status_codes = []; - - /** @var array */ - private $attributes; - - /** @var array */ - private $open_flags; - - /** @var array */ - private $open_flags5; - - /** @var array */ - private $file_types; - - /** - * The Request ID - * - * The request ID exists in the off chance that a packet is sent out-of-order. Of course, this library doesn't support - * concurrent actions, so it's somewhat academic, here. - * - * @var boolean - * @see self::_send_sftp_packet() - */ - private $use_request_id = false; - - /** - * The Packet Type - * - * The request ID exists in the off chance that a packet is sent out-of-order. Of course, this library doesn't support - * concurrent actions, so it's somewhat academic, here. - * - * @var int - * @see self::_get_sftp_packet() - */ - private $packet_type = -1; - - /** - * Packet Buffer - * - * @var string - * @see self::_get_sftp_packet() - */ - private $packet_buffer = ''; - - /** - * Extensions supported by the server - * - * @var array - * @see self::_initChannel() - */ - private $extensions = []; - - /** - * Server SFTP version - * - * @var int - * @see self::_initChannel() - */ - private $version; - - /** - * Default Server SFTP version - * - * @var int - * @see self::_initChannel() - */ - private $defaultVersion; - - /** - * Preferred SFTP version - * - * @var int - * @see self::_initChannel() - */ - private $preferredVersion = 3; - - /** - * Current working directory - * - * @var string|bool - * @see self::realpath() - * @see self::chdir() - */ - private $pwd = false; - - /** - * Packet Type Log - * - * @see self::getLog() - * @var array - */ - private $packet_type_log = []; - - /** - * Packet Log - * - * @see self::getLog() - * @var array - */ - private $packet_log = []; - - /** - * Real-time log file pointer - * - * @see self::_append_log() - * @var resource|closed-resource - */ - private $realtime_log_file; - - /** - * Real-time log file size - * - * @see self::_append_log() - * @var int - */ - private $realtime_log_size; - - /** - * Real-time log file wrap boolean - * - * @see self::_append_log() - * @var bool - */ - private $realtime_log_wrap; - - /** - * Current log size - * - * Should never exceed self::LOG_MAX_SIZE - * - * @var int - */ - private $log_size; - - /** - * Error information - * - * @see self::getSFTPErrors() - * @see self::getLastSFTPError() - * @var array - */ - private $sftp_errors = []; - - /** - * Stat Cache - * - * Rather than always having to open a directory and close it immediately there after to see if a file is a directory - * we'll cache the results. - * - * @see self::_update_stat_cache() - * @see self::_remove_from_stat_cache() - * @see self::_query_stat_cache() - * @var array - */ - private $stat_cache = []; - - /** - * Max SFTP Packet Size - * - * @see self::__construct() - * @see self::get() - * @var int - */ - private $max_sftp_packet; - - /** - * Stat Cache Flag - * - * @see self::disableStatCache() - * @see self::enableStatCache() - * @var bool - */ - private $use_stat_cache = true; - - /** - * Sort Options - * - * @see self::_comparator() - * @see self::setListOrder() - * @var array - */ - protected $sortOptions = []; - - /** - * Canonicalization Flag - * - * Determines whether or not paths should be canonicalized before being - * passed on to the remote server. - * - * @see self::enablePathCanonicalization() - * @see self::disablePathCanonicalization() - * @see self::realpath() - * @var bool - */ - private $canonicalize_paths = true; - - /** - * Request Buffers - * - * @see self::_get_sftp_packet() - * @var array - */ - private $requestBuffer = []; - - /** - * Preserve timestamps on file downloads / uploads - * - * @see self::get() - * @see self::put() - * @var bool - */ - private $preserveTime = false; - - /** - * Arbitrary Length Packets Flag - * - * Determines whether or not packets of any length should be allowed, - * in cases where the server chooses the packet length (such as - * directory listings). By default, packets are only allowed to be - * 256 * 1024 bytes (SFTP_MAX_MSG_LENGTH from OpenSSH's sftp-common.h) - * - * @see self::enableArbitraryLengthPackets() - * @see self::_get_sftp_packet() - * @var bool - */ - private $allow_arbitrary_length_packets = false; - - /** - * Was the last packet due to the channels being closed or not? - * - * @see self::get() - * @see self::get_sftp_packet() - * @var bool - */ - private $channel_close = false; - - /** - * Has the SFTP channel been partially negotiated? - * - * @var bool - */ - private $partial_init = false; - - /** - * Default Constructor. - * - * Connects to an SFTP server - * - * @param string $host - * @param int $port - * @param int $timeout - */ - public function __construct($host, $port = 22, $timeout = 10) - { - parent::__construct($host, $port, $timeout); - - $this->max_sftp_packet = 1 << 15; - - $this->packet_types = [ - 1 => 'NET_SFTP_INIT', - 2 => 'NET_SFTP_VERSION', - 3 => 'NET_SFTP_OPEN', - 4 => 'NET_SFTP_CLOSE', - 5 => 'NET_SFTP_READ', - 6 => 'NET_SFTP_WRITE', - 7 => 'NET_SFTP_LSTAT', - 9 => 'NET_SFTP_SETSTAT', - 10 => 'NET_SFTP_FSETSTAT', - 11 => 'NET_SFTP_OPENDIR', - 12 => 'NET_SFTP_READDIR', - 13 => 'NET_SFTP_REMOVE', - 14 => 'NET_SFTP_MKDIR', - 15 => 'NET_SFTP_RMDIR', - 16 => 'NET_SFTP_REALPATH', - 17 => 'NET_SFTP_STAT', - 18 => 'NET_SFTP_RENAME', - 19 => 'NET_SFTP_READLINK', - 20 => 'NET_SFTP_SYMLINK', - 21 => 'NET_SFTP_LINK', - - 101 => 'NET_SFTP_STATUS', - 102 => 'NET_SFTP_HANDLE', - 103 => 'NET_SFTP_DATA', - 104 => 'NET_SFTP_NAME', - 105 => 'NET_SFTP_ATTRS', - - 200 => 'NET_SFTP_EXTENDED' - ]; - $this->status_codes = [ - 0 => 'NET_SFTP_STATUS_OK', - 1 => 'NET_SFTP_STATUS_EOF', - 2 => 'NET_SFTP_STATUS_NO_SUCH_FILE', - 3 => 'NET_SFTP_STATUS_PERMISSION_DENIED', - 4 => 'NET_SFTP_STATUS_FAILURE', - 5 => 'NET_SFTP_STATUS_BAD_MESSAGE', - 6 => 'NET_SFTP_STATUS_NO_CONNECTION', - 7 => 'NET_SFTP_STATUS_CONNECTION_LOST', - 8 => 'NET_SFTP_STATUS_OP_UNSUPPORTED', - 9 => 'NET_SFTP_STATUS_INVALID_HANDLE', - 10 => 'NET_SFTP_STATUS_NO_SUCH_PATH', - 11 => 'NET_SFTP_STATUS_FILE_ALREADY_EXISTS', - 12 => 'NET_SFTP_STATUS_WRITE_PROTECT', - 13 => 'NET_SFTP_STATUS_NO_MEDIA', - 14 => 'NET_SFTP_STATUS_NO_SPACE_ON_FILESYSTEM', - 15 => 'NET_SFTP_STATUS_QUOTA_EXCEEDED', - 16 => 'NET_SFTP_STATUS_UNKNOWN_PRINCIPAL', - 17 => 'NET_SFTP_STATUS_LOCK_CONFLICT', - 18 => 'NET_SFTP_STATUS_DIR_NOT_EMPTY', - 19 => 'NET_SFTP_STATUS_NOT_A_DIRECTORY', - 20 => 'NET_SFTP_STATUS_INVALID_FILENAME', - 21 => 'NET_SFTP_STATUS_LINK_LOOP', - 22 => 'NET_SFTP_STATUS_CANNOT_DELETE', - 23 => 'NET_SFTP_STATUS_INVALID_PARAMETER', - 24 => 'NET_SFTP_STATUS_FILE_IS_A_DIRECTORY', - 25 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_CONFLICT', - 26 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_REFUSED', - 27 => 'NET_SFTP_STATUS_DELETE_PENDING', - 28 => 'NET_SFTP_STATUS_FILE_CORRUPT', - 29 => 'NET_SFTP_STATUS_OWNER_INVALID', - 30 => 'NET_SFTP_STATUS_GROUP_INVALID', - 31 => 'NET_SFTP_STATUS_NO_MATCHING_BYTE_RANGE_LOCK' - ]; - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-7.1 - // the order, in this case, matters quite a lot - see \phpseclib3\Net\SFTP::_parseAttributes() to understand why - $this->attributes = [ - 0x00000001 => 'NET_SFTP_ATTR_SIZE', - 0x00000002 => 'NET_SFTP_ATTR_UIDGID', // defined in SFTPv3, removed in SFTPv4+ - 0x00000080 => 'NET_SFTP_ATTR_OWNERGROUP', // defined in SFTPv4+ - 0x00000004 => 'NET_SFTP_ATTR_PERMISSIONS', - 0x00000008 => 'NET_SFTP_ATTR_ACCESSTIME', - 0x00000010 => 'NET_SFTP_ATTR_CREATETIME', // SFTPv4+ - 0x00000020 => 'NET_SFTP_ATTR_MODIFYTIME', - 0x00000040 => 'NET_SFTP_ATTR_ACL', - 0x00000100 => 'NET_SFTP_ATTR_SUBSECOND_TIMES', - 0x00000200 => 'NET_SFTP_ATTR_BITS', // SFTPv5+ - 0x00000400 => 'NET_SFTP_ATTR_ALLOCATION_SIZE', // SFTPv6+ - 0x00000800 => 'NET_SFTP_ATTR_TEXT_HINT', - 0x00001000 => 'NET_SFTP_ATTR_MIME_TYPE', - 0x00002000 => 'NET_SFTP_ATTR_LINK_COUNT', - 0x00004000 => 'NET_SFTP_ATTR_UNTRANSLATED_NAME', - 0x00008000 => 'NET_SFTP_ATTR_CTIME', - // 0x80000000 will yield a floating point on 32-bit systems and converting floating points to integers - // yields inconsistent behavior depending on how php is compiled. so we left shift -1 (which, in - // two's compliment, consists of all 1 bits) by 31. on 64-bit systems this'll yield 0xFFFFFFFF80000000. - // that's not a problem, however, and 'anded' and a 32-bit number, as all the leading 1 bits are ignored. - (PHP_INT_SIZE == 4 ? -1 : 0xFFFFFFFF) => 'NET_SFTP_ATTR_EXTENDED' - ]; - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.3 - // the flag definitions change somewhat in SFTPv5+. if SFTPv5+ support is added to this library, maybe name - // the array for that $this->open5_flags and similarly alter the constant names. - $this->open_flags = [ - 0x00000001 => 'NET_SFTP_OPEN_READ', - 0x00000002 => 'NET_SFTP_OPEN_WRITE', - 0x00000004 => 'NET_SFTP_OPEN_APPEND', - 0x00000008 => 'NET_SFTP_OPEN_CREATE', - 0x00000010 => 'NET_SFTP_OPEN_TRUNCATE', - 0x00000020 => 'NET_SFTP_OPEN_EXCL', - 0x00000040 => 'NET_SFTP_OPEN_TEXT' // defined in SFTPv4 - ]; - // SFTPv5+ changed the flags up: - // https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-8.1.1.3 - $this->open_flags5 = [ - // when SSH_FXF_ACCESS_DISPOSITION is a 3 bit field that controls how the file is opened - 0x00000000 => 'NET_SFTP_OPEN_CREATE_NEW', - 0x00000001 => 'NET_SFTP_OPEN_CREATE_TRUNCATE', - 0x00000002 => 'NET_SFTP_OPEN_OPEN_EXISTING', - 0x00000003 => 'NET_SFTP_OPEN_OPEN_OR_CREATE', - 0x00000004 => 'NET_SFTP_OPEN_TRUNCATE_EXISTING', - // the rest of the flags are not supported - 0x00000008 => 'NET_SFTP_OPEN_APPEND_DATA', // "the offset field of SS_FXP_WRITE requests is ignored" - 0x00000010 => 'NET_SFTP_OPEN_APPEND_DATA_ATOMIC', - 0x00000020 => 'NET_SFTP_OPEN_TEXT_MODE', - 0x00000040 => 'NET_SFTP_OPEN_BLOCK_READ', - 0x00000080 => 'NET_SFTP_OPEN_BLOCK_WRITE', - 0x00000100 => 'NET_SFTP_OPEN_BLOCK_DELETE', - 0x00000200 => 'NET_SFTP_OPEN_BLOCK_ADVISORY', - 0x00000400 => 'NET_SFTP_OPEN_NOFOLLOW', - 0x00000800 => 'NET_SFTP_OPEN_DELETE_ON_CLOSE', - 0x00001000 => 'NET_SFTP_OPEN_ACCESS_AUDIT_ALARM_INFO', - 0x00002000 => 'NET_SFTP_OPEN_ACCESS_BACKUP', - 0x00004000 => 'NET_SFTP_OPEN_BACKUP_STREAM', - 0x00008000 => 'NET_SFTP_OPEN_OVERRIDE_OWNER', - ]; - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-5.2 - // see \phpseclib3\Net\SFTP::_parseLongname() for an explanation - $this->file_types = [ - 1 => 'NET_SFTP_TYPE_REGULAR', - 2 => 'NET_SFTP_TYPE_DIRECTORY', - 3 => 'NET_SFTP_TYPE_SYMLINK', - 4 => 'NET_SFTP_TYPE_SPECIAL', - 5 => 'NET_SFTP_TYPE_UNKNOWN', - // the following types were first defined for use in SFTPv5+ - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-05#section-5.2 - 6 => 'NET_SFTP_TYPE_SOCKET', - 7 => 'NET_SFTP_TYPE_CHAR_DEVICE', - 8 => 'NET_SFTP_TYPE_BLOCK_DEVICE', - 9 => 'NET_SFTP_TYPE_FIFO' - ]; - $this->define_array( - $this->packet_types, - $this->status_codes, - $this->attributes, - $this->open_flags, - $this->open_flags5, - $this->file_types - ); - - if (!defined('NET_SFTP_QUEUE_SIZE')) { - define('NET_SFTP_QUEUE_SIZE', 32); - } - if (!defined('NET_SFTP_UPLOAD_QUEUE_SIZE')) { - define('NET_SFTP_UPLOAD_QUEUE_SIZE', 1024); - } - } - - /** - * Check a few things before SFTP functions are called - * - * @return bool - */ - private function precheck() - { - if (!($this->bitmap & SSH2::MASK_LOGIN)) { - return false; - } - - if ($this->pwd === false) { - return $this->init_sftp_connection(); - } - - return true; - } - - /** - * Partially initialize an SFTP connection - * - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return bool - */ - private function partial_init_sftp_connection() - { - $this->window_size_server_to_client[self::CHANNEL] = $this->window_size; - - $packet = Strings::packSSH2( - 'CsN3', - NET_SSH2_MSG_CHANNEL_OPEN, - 'session', - self::CHANNEL, - $this->window_size, - 0x4000 - ); - - $this->send_binary_packet($packet); - - $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_OPEN; - - $response = $this->get_channel_packet(self::CHANNEL, true); - if ($response === true && $this->isTimeout()) { - return false; - } - - $packet = Strings::packSSH2( - 'CNsbs', - NET_SSH2_MSG_CHANNEL_REQUEST, - $this->server_channels[self::CHANNEL], - 'subsystem', - true, - 'sftp' - ); - $this->send_binary_packet($packet); - - $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST; - - $response = $this->get_channel_packet(self::CHANNEL, true); - if ($response === false) { - // from PuTTY's psftp.exe - $command = "test -x /usr/lib/sftp-server && exec /usr/lib/sftp-server\n" . - "test -x /usr/local/lib/sftp-server && exec /usr/local/lib/sftp-server\n" . - "exec sftp-server"; - // we don't do $this->exec($command, false) because exec() operates on a different channel and plus the SSH_MSG_CHANNEL_OPEN that exec() does - // is redundant - $packet = Strings::packSSH2( - 'CNsCs', - NET_SSH2_MSG_CHANNEL_REQUEST, - $this->server_channels[self::CHANNEL], - 'exec', - 1, - $command - ); - $this->send_binary_packet($packet); - - $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST; - - $response = $this->get_channel_packet(self::CHANNEL, true); - if ($response === false) { - return false; - } - } elseif ($response === true && $this->isTimeout()) { - return false; - } - - $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_DATA; - $this->send_sftp_packet(NET_SFTP_INIT, "\0\0\0\3"); - - $response = $this->get_sftp_packet(); - if ($this->packet_type != NET_SFTP_VERSION) { - throw new \UnexpectedValueException('Expected NET_SFTP_VERSION. ' - . 'Got packet type: ' . $this->packet_type); - } - - $this->use_request_id = true; - - list($this->defaultVersion) = Strings::unpackSSH2('N', $response); - while (!empty($response)) { - list($key, $value) = Strings::unpackSSH2('ss', $response); - $this->extensions[$key] = $value; - } - - $this->partial_init = true; - - return true; - } - - /** - * (Re)initializes the SFTP channel - * - * @return bool - */ - private function init_sftp_connection() - { - if (!$this->partial_init && !$this->partial_init_sftp_connection()) { - return false; - } - - /* - A Note on SFTPv4/5/6 support: - states the following: - - "If the client wishes to interoperate with servers that support noncontiguous version - numbers it SHOULD send '3'" - - Given that the server only sends its version number after the client has already done so, the above - seems to be suggesting that v3 should be the default version. This makes sense given that v3 is the - most popular. - - states the following; - - "If the server did not send the "versions" extension, or the version-from-list was not included, the - server MAY send a status response describing the failure, but MUST then close the channel without - processing any further requests." - - So what do you do if you have a client whose initial SSH_FXP_INIT packet says it implements v3 and - a server whose initial SSH_FXP_VERSION reply says it implements v4 and only v4? If it only implements - v4, the "versions" extension is likely not going to have been sent so version re-negotiation as discussed - in draft-ietf-secsh-filexfer-13 would be quite impossible. As such, what \phpseclib3\Net\SFTP would do is close the - channel and reopen it with a new and updated SSH_FXP_INIT packet. - */ - $this->version = $this->defaultVersion; - if (isset($this->extensions['versions']) && (!$this->preferredVersion || $this->preferredVersion != $this->version)) { - $versions = explode(',', $this->extensions['versions']); - $supported = [6, 5, 4]; - if ($this->preferredVersion) { - $supported = array_diff($supported, [$this->preferredVersion]); - array_unshift($supported, $this->preferredVersion); - } - foreach ($supported as $ver) { - if (in_array($ver, $versions)) { - if ($ver === $this->version) { - break; - } - $this->version = (int) $ver; - $packet = Strings::packSSH2('ss', 'version-select', "$ver"); - $this->send_sftp_packet(NET_SFTP_EXTENDED, $packet); - $response = $this->get_sftp_packet(); - if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. ' - . 'Got packet type: ' . $this->packet_type); - } - list($status) = Strings::unpackSSH2('N', $response); - if ($status != NET_SFTP_STATUS_OK) { - $this->logError($response, $status); - throw new \UnexpectedValueException('Expected NET_SFTP_STATUS_OK. ' - . ' Got ' . $status); - } - break; - } - } - } - - /* - SFTPv4+ defines a 'newline' extension. SFTPv3 seems to have unofficial support for it via 'newline@vandyke.com', - however, I'm not sure what 'newline@vandyke.com' is supposed to do (the fact that it's unofficial means that it's - not in the official SFTPv3 specs) and 'newline@vandyke.com' / 'newline' are likely not drop-in substitutes for - one another due to the fact that 'newline' comes with a SSH_FXF_TEXT bitmask whereas it seems unlikely that - 'newline@vandyke.com' would. - */ - /* - if (isset($this->extensions['newline@vandyke.com'])) { - $this->extensions['newline'] = $this->extensions['newline@vandyke.com']; - unset($this->extensions['newline@vandyke.com']); - } - */ - if ($this->version < 2 || $this->version > 6) { - return false; - } - - $this->pwd = true; - try { - $this->pwd = $this->realpath('.'); - } catch (\UnexpectedValueException $e) { - if (!$this->canonicalize_paths) { - throw $e; - } - $this->canonicalize_paths = false; - $this->reset_connection(NET_SSH2_DISCONNECT_CONNECTION_LOST); - } - - $this->update_stat_cache($this->pwd, []); - - return true; - } - - /** - * Disable the stat cache - * - */ - public function disableStatCache() - { - $this->use_stat_cache = false; - } - - /** - * Enable the stat cache - * - */ - public function enableStatCache() - { - $this->use_stat_cache = true; - } - - /** - * Clear the stat cache - * - */ - public function clearStatCache() - { - $this->stat_cache = []; - } - - /** - * Enable path canonicalization - * - */ - public function enablePathCanonicalization() - { - $this->canonicalize_paths = true; - } - - /** - * Disable path canonicalization - * - * If this is enabled then $sftp->pwd() will not return the canonicalized absolute path - * - */ - public function disablePathCanonicalization() - { - $this->canonicalize_paths = false; - } - - /** - * Enable arbitrary length packets - * - */ - public function enableArbitraryLengthPackets() - { - $this->allow_arbitrary_length_packets = true; - } - - /** - * Disable arbitrary length packets - * - */ - public function disableArbitraryLengthPackets() - { - $this->allow_arbitrary_length_packets = false; - } - - /** - * Returns the current directory name - * - * @return string|bool - */ - public function pwd() - { - if (!$this->precheck()) { - return false; - } - - return $this->pwd; - } - - /** - * Logs errors - * - * @param string $response - * @param int $status - */ - private function logError($response, $status = -1) - { - if ($status == -1) { - list($status) = Strings::unpackSSH2('N', $response); - } - - $error = $this->status_codes[$status]; - - if ($this->version > 2) { - list($message) = Strings::unpackSSH2('s', $response); - $this->sftp_errors[] = "$error: $message"; - } else { - $this->sftp_errors[] = $error; - } - } - - /** - * Canonicalize the Server-Side Path Name - * - * SFTP doesn't provide a mechanism by which the current working directory can be changed, so we'll emulate it. Returns - * the absolute (canonicalized) path. - * - * If canonicalize_paths has been disabled using disablePathCanonicalization(), $path is returned as-is. - * - * @see self::chdir() - * @see self::disablePathCanonicalization() - * @param string $path - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return mixed - */ - public function realpath($path) - { - if ($this->precheck() === false) { - return false; - } - - if (!$this->canonicalize_paths) { - if ($this->pwd === true) { - return '.'; - } - if (!strlen($path) || $path[0] != '/') { - $path = $this->pwd . '/' . $path; - } - $parts = explode('/', $path); - $afterPWD = $beforePWD = []; - foreach ($parts as $part) { - switch ($part) { - //case '': // some SFTP servers /require/ double /'s. see https://github.com/phpseclib/phpseclib/pull/1137 - case '.': - break; - case '..': - if (!empty($afterPWD)) { - array_pop($afterPWD); - } else { - $beforePWD[] = '..'; - } - break; - default: - $afterPWD[] = $part; - } - } - $beforePWD = count($beforePWD) ? implode('/', $beforePWD) : '.'; - return $beforePWD . '/' . implode('/', $afterPWD); - } - - if ($this->pwd === true) { - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.9 - $this->send_sftp_packet(NET_SFTP_REALPATH, Strings::packSSH2('s', $path)); - - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_NAME: - // although SSH_FXP_NAME is implemented differently in SFTPv3 than it is in SFTPv4+, the following - // should work on all SFTP versions since the only part of the SSH_FXP_NAME packet the following looks - // at is the first part and that part is defined the same in SFTP versions 3 through 6. - list(, $filename) = Strings::unpackSSH2('Ns', $response); - return $filename; - case NET_SFTP_STATUS: - $this->logError($response); - return false; - default: - throw new \UnexpectedValueException('Expected NET_SFTP_NAME or NET_SFTP_STATUS. ' - . 'Got packet type: ' . $this->packet_type); - } - } - - if (!strlen($path) || $path[0] != '/') { - $path = $this->pwd . '/' . $path; - } - - $path = explode('/', $path); - $new = []; - foreach ($path as $dir) { - if (!strlen($dir)) { - continue; - } - switch ($dir) { - case '..': - array_pop($new); - // fall-through - case '.': - break; - default: - $new[] = $dir; - } - } - - return '/' . implode('/', $new); - } - - /** - * Changes the current directory - * - * @param string $dir - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return bool - */ - public function chdir($dir) - { - if (!$this->precheck()) { - return false; - } - - // assume current dir if $dir is empty - if ($dir === '') { - $dir = './'; - // suffix a slash if needed - } elseif ($dir[strlen($dir) - 1] != '/') { - $dir .= '/'; - } - - $dir = $this->realpath($dir); - - // confirm that $dir is, in fact, a valid directory - if ($this->use_stat_cache && is_array($this->query_stat_cache($dir))) { - $this->pwd = $dir; - return true; - } - - // we could do a stat on the alleged $dir to see if it's a directory but that doesn't tell us - // the currently logged in user has the appropriate permissions or not. maybe you could see if - // the file's uid / gid match the currently logged in user's uid / gid but how there's no easy - // way to get those with SFTP - - $this->send_sftp_packet(NET_SFTP_OPENDIR, Strings::packSSH2('s', $dir)); - - // see \phpseclib3\Net\SFTP::nlist() for a more thorough explanation of the following - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_HANDLE: - $handle = substr($response, 4); - break; - case NET_SFTP_STATUS: - $this->logError($response); - return false; - default: - throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS' . - 'Got packet type: ' . $this->packet_type); - } - - if (!$this->close_handle($handle)) { - return false; - } - - $this->update_stat_cache($dir, []); - - $this->pwd = $dir; - return true; - } - - /** - * Returns a list of files in the given directory - * - * @param string $dir - * @param bool $recursive - * @return array|false - */ - public function nlist($dir = '.', $recursive = false) - { - return $this->nlist_helper($dir, $recursive, ''); - } - - /** - * Helper method for nlist - * - * @param string $dir - * @param bool $recursive - * @param string $relativeDir - * @return array|false - */ - private function nlist_helper($dir, $recursive, $relativeDir) - { - $files = $this->readlist($dir, false); - - // If we get an int back, then that is an "unexpected" status. - // We do not have a file list, so return false. - if (is_int($files)) { - return false; - } - - if (!$recursive || $files === false) { - return $files; - } - - $result = []; - foreach ($files as $value) { - if ($value == '.' || $value == '..') { - $result[] = $relativeDir . $value; - continue; - } - if (is_array($this->query_stat_cache($this->realpath($dir . '/' . $value)))) { - $temp = $this->nlist_helper($dir . '/' . $value, true, $relativeDir . $value . '/'); - $temp = is_array($temp) ? $temp : []; - $result = array_merge($result, $temp); - } else { - $result[] = $relativeDir . $value; - } - } - - return $result; - } - - /** - * Returns a detailed list of files in the given directory - * - * @param string $dir - * @param bool $recursive - * @return array|false - */ - public function rawlist($dir = '.', $recursive = false) - { - $files = $this->readlist($dir, true); - - // If we get an int back, then that is an "unexpected" status. - // We do not have a file list, so return false. - if (is_int($files)) { - return false; - } - - if (!$recursive || $files === false) { - return $files; - } - - static $depth = 0; - - foreach ($files as $key => $value) { - if ($depth != 0 && $key == '..') { - unset($files[$key]); - continue; - } - $is_directory = false; - if ($key != '.' && $key != '..') { - if ($this->use_stat_cache) { - $is_directory = is_array($this->query_stat_cache($this->realpath($dir . '/' . $key))); - } else { - $stat = $this->lstat($dir . '/' . $key); - $is_directory = $stat && $stat['type'] === NET_SFTP_TYPE_DIRECTORY; - } - } - - if ($is_directory) { - $depth++; - $files[$key] = $this->rawlist($dir . '/' . $key, true); - $depth--; - } else { - $files[$key] = (object) $value; - } - } - - return $files; - } - - /** - * Reads a list, be it detailed or not, of files in the given directory - * - * @param string $dir - * @param bool $raw - * @return array|false - * @throws \UnexpectedValueException on receipt of unexpected packets - */ - private function readlist($dir, $raw = true) - { - if (!$this->precheck()) { - return false; - } - - $dir = $this->realpath($dir . '/'); - if ($dir === false) { - return false; - } - - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.2 - $this->send_sftp_packet(NET_SFTP_OPENDIR, Strings::packSSH2('s', $dir)); - - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_HANDLE: - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.2 - // since 'handle' is the last field in the SSH_FXP_HANDLE packet, we'll just remove the first four bytes that - // represent the length of the string and leave it at that - $handle = substr($response, 4); - break; - case NET_SFTP_STATUS: - // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED - list($status) = Strings::unpackSSH2('N', $response); - $this->logError($response, $status); - return $status; - default: - throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. ' - . 'Got packet type: ' . $this->packet_type); - } - - $this->update_stat_cache($dir, []); - - $contents = []; - while (true) { - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.2 - // why multiple SSH_FXP_READDIR packets would be sent when the response to a single one can span arbitrarily many - // SSH_MSG_CHANNEL_DATA messages is not known to me. - $this->send_sftp_packet(NET_SFTP_READDIR, Strings::packSSH2('s', $handle)); - - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_NAME: - list($count) = Strings::unpackSSH2('N', $response); - for ($i = 0; $i < $count; $i++) { - list($shortname) = Strings::unpackSSH2('s', $response); - // SFTPv4 "removed the long filename from the names structure-- it can now be - // built from information available in the attrs structure." - if ($this->version < 4) { - list($longname) = Strings::unpackSSH2('s', $response); - } - $attributes = $this->parseAttributes($response); - if (!isset($attributes['type']) && $this->version < 4) { - $fileType = $this->parseLongname($longname); - if ($fileType) { - $attributes['type'] = $fileType; - } - } - $contents[$shortname] = $attributes + ['filename' => $shortname]; - - if (isset($attributes['type']) && $attributes['type'] == NET_SFTP_TYPE_DIRECTORY && ($shortname != '.' && $shortname != '..')) { - $this->update_stat_cache($dir . '/' . $shortname, []); - } else { - if ($shortname == '..') { - $temp = $this->realpath($dir . '/..') . '/.'; - } else { - $temp = $dir . '/' . $shortname; - } - $this->update_stat_cache($temp, (object) ['lstat' => $attributes]); - } - // SFTPv6 has an optional boolean end-of-list field, but we'll ignore that, since the - // final SSH_FXP_STATUS packet should tell us that, already. - } - break; - case NET_SFTP_STATUS: - list($status) = Strings::unpackSSH2('N', $response); - if ($status != NET_SFTP_STATUS_EOF) { - $this->logError($response, $status); - return $status; - } - break 2; - default: - throw new \UnexpectedValueException('Expected NET_SFTP_NAME or NET_SFTP_STATUS. ' - . 'Got packet type: ' . $this->packet_type); - } - } - - if (!$this->close_handle($handle)) { - return false; - } - - if (count($this->sortOptions)) { - uasort($contents, [&$this, 'comparator']); - } - - return $raw ? $contents : array_map('strval', array_keys($contents)); - } - - /** - * Compares two rawlist entries using parameters set by setListOrder() - * - * Intended for use with uasort() - * - * @param array $a - * @param array $b - * @return int - */ - private function comparator(array $a, array $b) - { - switch (true) { - case $a['filename'] === '.' || $b['filename'] === '.': - if ($a['filename'] === $b['filename']) { - return 0; - } - return $a['filename'] === '.' ? -1 : 1; - case $a['filename'] === '..' || $b['filename'] === '..': - if ($a['filename'] === $b['filename']) { - return 0; - } - return $a['filename'] === '..' ? -1 : 1; - case isset($a['type']) && $a['type'] === NET_SFTP_TYPE_DIRECTORY: - if (!isset($b['type'])) { - return 1; - } - if ($b['type'] !== $a['type']) { - return -1; - } - break; - case isset($b['type']) && $b['type'] === NET_SFTP_TYPE_DIRECTORY: - return 1; - } - foreach ($this->sortOptions as $sort => $order) { - if (!isset($a[$sort]) || !isset($b[$sort])) { - if (isset($a[$sort])) { - return -1; - } - if (isset($b[$sort])) { - return 1; - } - return 0; - } - switch ($sort) { - case 'filename': - $result = strcasecmp($a['filename'], $b['filename']); - if ($result) { - return $order === SORT_DESC ? -$result : $result; - } - break; - case 'mode': - $a[$sort] &= 07777; - $b[$sort] &= 07777; - // fall-through - default: - if ($a[$sort] === $b[$sort]) { - break; - } - return $order === SORT_ASC ? $a[$sort] - $b[$sort] : $b[$sort] - $a[$sort]; - } - } - } - - /** - * Defines how nlist() and rawlist() will be sorted - if at all. - * - * If sorting is enabled directories and files will be sorted independently with - * directories appearing before files in the resultant array that is returned. - * - * Any parameter returned by stat is a valid sort parameter for this function. - * Filename comparisons are case insensitive. - * - * Examples: - * - * $sftp->setListOrder('filename', SORT_ASC); - * $sftp->setListOrder('size', SORT_DESC, 'filename', SORT_ASC); - * $sftp->setListOrder(true); - * Separates directories from files but doesn't do any sorting beyond that - * $sftp->setListOrder(); - * Don't do any sort of sorting - * - * @param string ...$args - */ - public function setListOrder(...$args) - { - $this->sortOptions = []; - if (empty($args)) { - return; - } - $len = count($args) & 0x7FFFFFFE; - for ($i = 0; $i < $len; $i += 2) { - $this->sortOptions[$args[$i]] = $args[$i + 1]; - } - if (!count($this->sortOptions)) { - $this->sortOptions = ['bogus' => true]; - } - } - - /** - * Save files / directories to cache - * - * @param string $path - * @param mixed $value - */ - private function update_stat_cache($path, $value) - { - if ($this->use_stat_cache === false) { - return; - } - - // preg_replace('#^/|/(?=/)|/$#', '', $dir) == str_replace('//', '/', trim($path, '/')) - $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path)); - - $temp = &$this->stat_cache; - $max = count($dirs) - 1; - foreach ($dirs as $i => $dir) { - // if $temp is an object that means one of two things. - // 1. a file was deleted and changed to a directory behind phpseclib's back - // 2. it's a symlink. when lstat is done it's unclear what it's a symlink to - if (is_object($temp)) { - $temp = []; - } - if (!isset($temp[$dir])) { - $temp[$dir] = []; - } - if ($i === $max) { - if (is_object($temp[$dir]) && is_object($value)) { - if (!isset($value->stat) && isset($temp[$dir]->stat)) { - $value->stat = $temp[$dir]->stat; - } - if (!isset($value->lstat) && isset($temp[$dir]->lstat)) { - $value->lstat = $temp[$dir]->lstat; - } - } - $temp[$dir] = $value; - break; - } - $temp = &$temp[$dir]; - } - } - - /** - * Remove files / directories from cache - * - * @param string $path - * @return bool - */ - private function remove_from_stat_cache($path) - { - $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path)); - - $temp = &$this->stat_cache; - $max = count($dirs) - 1; - foreach ($dirs as $i => $dir) { - if (!is_array($temp)) { - return false; - } - if ($i === $max) { - unset($temp[$dir]); - return true; - } - if (!isset($temp[$dir])) { - return false; - } - $temp = &$temp[$dir]; - } - } - - /** - * Checks cache for path - * - * Mainly used by file_exists - * - * @param string $path - * @return mixed - */ - private function query_stat_cache($path) - { - $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path)); - - $temp = &$this->stat_cache; - foreach ($dirs as $dir) { - if (!is_array($temp)) { - return null; - } - if (!isset($temp[$dir])) { - return null; - } - $temp = &$temp[$dir]; - } - return $temp; - } - - /** - * Returns general information about a file. - * - * Returns an array on success and false otherwise. - * - * @param string $filename - * @return array|false - */ - public function stat($filename) - { - if (!$this->precheck()) { - return false; - } - - $filename = $this->realpath($filename); - if ($filename === false) { - return false; - } - - if ($this->use_stat_cache) { - $result = $this->query_stat_cache($filename); - if (is_array($result) && isset($result['.']) && isset($result['.']->stat)) { - return $result['.']->stat; - } - if (is_object($result) && isset($result->stat)) { - return $result->stat; - } - } - - $stat = $this->stat_helper($filename, NET_SFTP_STAT); - if ($stat === false) { - $this->remove_from_stat_cache($filename); - return false; - } - if (isset($stat['type'])) { - if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) { - $filename .= '/.'; - } - $this->update_stat_cache($filename, (object) ['stat' => $stat]); - return $stat; - } - - $pwd = $this->pwd; - $stat['type'] = $this->chdir($filename) ? - NET_SFTP_TYPE_DIRECTORY : - NET_SFTP_TYPE_REGULAR; - $this->pwd = $pwd; - - if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) { - $filename .= '/.'; - } - $this->update_stat_cache($filename, (object) ['stat' => $stat]); - - return $stat; - } - - /** - * Returns general information about a file or symbolic link. - * - * Returns an array on success and false otherwise. - * - * @param string $filename - * @return array|false - */ - public function lstat($filename) - { - if (!$this->precheck()) { - return false; - } - - $filename = $this->realpath($filename); - if ($filename === false) { - return false; - } - - if ($this->use_stat_cache) { - $result = $this->query_stat_cache($filename); - if (is_array($result) && isset($result['.']) && isset($result['.']->lstat)) { - return $result['.']->lstat; - } - if (is_object($result) && isset($result->lstat)) { - return $result->lstat; - } - } - - $lstat = $this->stat_helper($filename, NET_SFTP_LSTAT); - if ($lstat === false) { - $this->remove_from_stat_cache($filename); - return false; - } - if (isset($lstat['type'])) { - if ($lstat['type'] == NET_SFTP_TYPE_DIRECTORY) { - $filename .= '/.'; - } - $this->update_stat_cache($filename, (object) ['lstat' => $lstat]); - return $lstat; - } - - $stat = $this->stat_helper($filename, NET_SFTP_STAT); - - if ($lstat != $stat) { - $lstat = array_merge($lstat, ['type' => NET_SFTP_TYPE_SYMLINK]); - $this->update_stat_cache($filename, (object) ['lstat' => $lstat]); - return $stat; - } - - $pwd = $this->pwd; - $lstat['type'] = $this->chdir($filename) ? - NET_SFTP_TYPE_DIRECTORY : - NET_SFTP_TYPE_REGULAR; - $this->pwd = $pwd; - - if ($lstat['type'] == NET_SFTP_TYPE_DIRECTORY) { - $filename .= '/.'; - } - $this->update_stat_cache($filename, (object) ['lstat' => $lstat]); - - return $lstat; - } - - /** - * Returns general information about a file or symbolic link - * - * Determines information without calling \phpseclib3\Net\SFTP::realpath(). - * The second parameter can be either NET_SFTP_STAT or NET_SFTP_LSTAT. - * - * @param string $filename - * @param int $type - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return array|false - */ - private function stat_helper($filename, $type) - { - // SFTPv4+ adds an additional 32-bit integer field - flags - to the following: - $packet = Strings::packSSH2('s', $filename); - $this->send_sftp_packet($type, $packet); - - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_ATTRS: - return $this->parseAttributes($response); - case NET_SFTP_STATUS: - $this->logError($response); - return false; - } - - throw new \UnexpectedValueException('Expected NET_SFTP_ATTRS or NET_SFTP_STATUS. ' - . 'Got packet type: ' . $this->packet_type); - } - - /** - * Truncates a file to a given length - * - * @param string $filename - * @param int $new_size - * @return bool - */ - public function truncate($filename, $new_size) - { - $attr = Strings::packSSH2('NQ', NET_SFTP_ATTR_SIZE, $new_size); - - return $this->setstat($filename, $attr, false); - } - - /** - * Sets access and modification time of file. - * - * If the file does not exist, it will be created. - * - * @param string $filename - * @param int $time - * @param int $atime - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return bool - */ - public function touch($filename, $time = null, $atime = null) - { - if (!$this->precheck()) { - return false; - } - - $filename = $this->realpath($filename); - if ($filename === false) { - return false; - } - - if (!isset($time)) { - $time = time(); - } - if (!isset($atime)) { - $atime = $time; - } - - $attr = $this->version < 4 ? - pack('N3', NET_SFTP_ATTR_ACCESSTIME, $atime, $time) : - Strings::packSSH2('NQ2', NET_SFTP_ATTR_ACCESSTIME | NET_SFTP_ATTR_MODIFYTIME, $atime, $time); - - $packet = Strings::packSSH2('s', $filename); - $packet .= $this->version >= 5 ? - pack('N2', 0, NET_SFTP_OPEN_OPEN_EXISTING) : - pack('N', NET_SFTP_OPEN_WRITE | NET_SFTP_OPEN_CREATE | NET_SFTP_OPEN_EXCL); - $packet .= $attr; - - $this->send_sftp_packet(NET_SFTP_OPEN, $packet); - - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_HANDLE: - return $this->close_handle(substr($response, 4)); - case NET_SFTP_STATUS: - $this->logError($response); - break; - default: - throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. ' - . 'Got packet type: ' . $this->packet_type); - } - - return $this->setstat($filename, $attr, false); - } - - /** - * Changes file or directory owner - * - * $uid should be an int for SFTPv3 and a string for SFTPv4+. Ideally the string - * would be of the form "user@dns_domain" but it does not need to be. - * `$sftp->getSupportedVersions()['version']` will return the specific version - * that's being used. - * - * Returns true on success or false on error. - * - * @param string $filename - * @param int|string $uid - * @param bool $recursive - * @return bool - */ - public function chown($filename, $uid, $recursive = false) - { - /* - quoting , - - "To avoid a representation that is tied to a particular underlying - implementation at the client or server, the use of UTF-8 strings has - been chosen. The string should be of the form "user@dns_domain". - This will allow for a client and server that do not use the same - local representation the ability to translate to a common syntax that - can be interpreted by both. In the case where there is no - translation available to the client or server, the attribute value - must be constructed without the "@"." - - phpseclib _could_ auto append the dns_domain to $uid BUT what if it shouldn't - have one? phpseclib would have no way of knowing so rather than guess phpseclib - will just use whatever value the user provided - */ - - $attr = $this->version < 4 ? - // quoting , - // "if the owner or group is specified as -1, then that ID is not changed" - pack('N3', NET_SFTP_ATTR_UIDGID, $uid, -1) : - // quoting , - // "If either the owner or group field is zero length, the field should be - // considered absent, and no change should be made to that specific field - // during a modification operation" - Strings::packSSH2('Nss', NET_SFTP_ATTR_OWNERGROUP, $uid, ''); - - return $this->setstat($filename, $attr, $recursive); - } - - /** - * Changes file or directory group - * - * $gid should be an int for SFTPv3 and a string for SFTPv4+. Ideally the string - * would be of the form "user@dns_domain" but it does not need to be. - * `$sftp->getSupportedVersions()['version']` will return the specific version - * that's being used. - * - * Returns true on success or false on error. - * - * @param string $filename - * @param int|string $gid - * @param bool $recursive - * @return bool - */ - public function chgrp($filename, $gid, $recursive = false) - { - $attr = $this->version < 4 ? - pack('N3', NET_SFTP_ATTR_UIDGID, -1, $gid) : - Strings::packSSH2('Nss', NET_SFTP_ATTR_OWNERGROUP, '', $gid); - - return $this->setstat($filename, $attr, $recursive); - } - - /** - * Set permissions on a file. - * - * Returns the new file permissions on success or false on error. - * If $recursive is true than this just returns true or false. - * - * @param int $mode - * @param string $filename - * @param bool $recursive - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return mixed - */ - public function chmod($mode, $filename, $recursive = false) - { - if (is_string($mode) && is_int($filename)) { - $temp = $mode; - $mode = $filename; - $filename = $temp; - } - - $attr = pack('N2', NET_SFTP_ATTR_PERMISSIONS, $mode & 07777); - if (!$this->setstat($filename, $attr, $recursive)) { - return false; - } - if ($recursive) { - return true; - } - - $filename = $this->realpath($filename); - // rather than return what the permissions *should* be, we'll return what they actually are. this will also - // tell us if the file actually exists. - // incidentally, SFTPv4+ adds an additional 32-bit integer field - flags - to the following: - $packet = pack('Na*', strlen($filename), $filename); - $this->send_sftp_packet(NET_SFTP_STAT, $packet); - - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_ATTRS: - $attrs = $this->parseAttributes($response); - return $attrs['mode']; - case NET_SFTP_STATUS: - $this->logError($response); - return false; - } - - throw new \UnexpectedValueException('Expected NET_SFTP_ATTRS or NET_SFTP_STATUS. ' - . 'Got packet type: ' . $this->packet_type); - } - - /** - * Sets information about a file - * - * @param string $filename - * @param string $attr - * @param bool $recursive - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return bool - */ - private function setstat($filename, $attr, $recursive) - { - if (!$this->precheck()) { - return false; - } - - $filename = $this->realpath($filename); - if ($filename === false) { - return false; - } - - $this->remove_from_stat_cache($filename); - - if ($recursive) { - $i = 0; - $result = $this->setstat_recursive($filename, $attr, $i); - $this->read_put_responses($i); - return $result; - } - - $packet = Strings::packSSH2('s', $filename); - $packet .= $this->version >= 4 ? - pack('a*Ca*', substr($attr, 0, 4), NET_SFTP_TYPE_UNKNOWN, substr($attr, 4)) : - $attr; - $this->send_sftp_packet(NET_SFTP_SETSTAT, $packet); - - /* - "Because some systems must use separate system calls to set various attributes, it is possible that a failure - response will be returned, but yet some of the attributes may be have been successfully modified. If possible, - servers SHOULD avoid this situation; however, clients MUST be aware that this is possible." - - -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.6 - */ - $response = $this->get_sftp_packet(); - if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. ' - . 'Got packet type: ' . $this->packet_type); - } - - list($status) = Strings::unpackSSH2('N', $response); - if ($status != NET_SFTP_STATUS_OK) { - $this->logError($response, $status); - return false; - } - - return true; - } - - /** - * Recursively sets information on directories on the SFTP server - * - * Minimizes directory lookups and SSH_FXP_STATUS requests for speed. - * - * @param string $path - * @param string $attr - * @param int $i - * @return bool - */ - private function setstat_recursive($path, $attr, &$i) - { - if (!$this->read_put_responses($i)) { - return false; - } - $i = 0; - $entries = $this->readlist($path, true); - - if ($entries === false || is_int($entries)) { - return $this->setstat($path, $attr, false); - } - - // normally $entries would have at least . and .. but it might not if the directories - // permissions didn't allow reading - if (empty($entries)) { - return false; - } - - unset($entries['.'], $entries['..']); - foreach ($entries as $filename => $props) { - if (!isset($props['type'])) { - return false; - } - - $temp = $path . '/' . $filename; - if ($props['type'] == NET_SFTP_TYPE_DIRECTORY) { - if (!$this->setstat_recursive($temp, $attr, $i)) { - return false; - } - } else { - $packet = Strings::packSSH2('s', $temp); - $packet .= $this->version >= 4 ? - pack('Ca*', NET_SFTP_TYPE_UNKNOWN, $attr) : - $attr; - $this->send_sftp_packet(NET_SFTP_SETSTAT, $packet); - - $i++; - - if ($i >= NET_SFTP_QUEUE_SIZE) { - if (!$this->read_put_responses($i)) { - return false; - } - $i = 0; - } - } - } - - $packet = Strings::packSSH2('s', $path); - $packet .= $this->version >= 4 ? - pack('Ca*', NET_SFTP_TYPE_UNKNOWN, $attr) : - $attr; - $this->send_sftp_packet(NET_SFTP_SETSTAT, $packet); - - $i++; - - if ($i >= NET_SFTP_QUEUE_SIZE) { - if (!$this->read_put_responses($i)) { - return false; - } - $i = 0; - } - - return true; - } - - /** - * Return the target of a symbolic link - * - * @param string $link - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return mixed - */ - public function readlink($link) - { - if (!$this->precheck()) { - return false; - } - - $link = $this->realpath($link); - - $this->send_sftp_packet(NET_SFTP_READLINK, Strings::packSSH2('s', $link)); - - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_NAME: - break; - case NET_SFTP_STATUS: - $this->logError($response); - return false; - default: - throw new \UnexpectedValueException('Expected NET_SFTP_NAME or NET_SFTP_STATUS. ' - . 'Got packet type: ' . $this->packet_type); - } - - list($count) = Strings::unpackSSH2('N', $response); - // the file isn't a symlink - if (!$count) { - return false; - } - - list($filename) = Strings::unpackSSH2('s', $response); - - return $filename; - } - - /** - * Create a symlink - * - * symlink() creates a symbolic link to the existing target with the specified name link. - * - * @param string $target - * @param string $link - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return bool - */ - public function symlink($target, $link) - { - if (!$this->precheck()) { - return false; - } - - //$target = $this->realpath($target); - $link = $this->realpath($link); - - /* quoting https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-09#section-12.1 : - - Changed the SYMLINK packet to be LINK and give it the ability to - create hard links. Also change it's packet number because many - implementation implemented SYMLINK with the arguments reversed. - Hopefully the new argument names make it clear which way is which. - */ - if ($this->version == 6) { - $type = NET_SFTP_LINK; - $packet = Strings::packSSH2('ssC', $link, $target, 1); - } else { - $type = NET_SFTP_SYMLINK; - /* quoting http://bxr.su/OpenBSD/usr.bin/ssh/PROTOCOL#347 : - - 3.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK - - When OpenSSH's sftp-server was implemented, the order of the arguments - to the SSH_FXP_SYMLINK method was inadvertently reversed. Unfortunately, - the reversal was not noticed until the server was widely deployed. Since - fixing this to follow the specification would cause incompatibility, the - current order was retained. For correct operation, clients should send - SSH_FXP_SYMLINK as follows: - - uint32 id - string targetpath - string linkpath */ - $packet = substr($this->server_identifier, 0, 15) == 'SSH-2.0-OpenSSH' ? - Strings::packSSH2('ss', $target, $link) : - Strings::packSSH2('ss', $link, $target); - } - $this->send_sftp_packet($type, $packet); - - $response = $this->get_sftp_packet(); - if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. ' - . 'Got packet type: ' . $this->packet_type); - } - - list($status) = Strings::unpackSSH2('N', $response); - if ($status != NET_SFTP_STATUS_OK) { - $this->logError($response, $status); - return false; - } - - return true; - } - - /** - * Creates a directory. - * - * @param string $dir - * @param int $mode - * @param bool $recursive - * @return bool - */ - public function mkdir($dir, $mode = -1, $recursive = false) - { - if (!$this->precheck()) { - return false; - } - - $dir = $this->realpath($dir); - - if ($recursive) { - $dirs = explode('/', preg_replace('#/(?=/)|/$#', '', $dir)); - if (empty($dirs[0])) { - array_shift($dirs); - $dirs[0] = '/' . $dirs[0]; - } - for ($i = 0; $i < count($dirs); $i++) { - $temp = array_slice($dirs, 0, $i + 1); - $temp = implode('/', $temp); - $result = $this->mkdir_helper($temp, $mode); - } - return $result; - } - - return $this->mkdir_helper($dir, $mode); - } - - /** - * Helper function for directory creation - * - * @param string $dir - * @param int $mode - * @return bool - */ - private function mkdir_helper($dir, $mode) - { - // send SSH_FXP_MKDIR without any attributes (that's what the \0\0\0\0 is doing) - $this->send_sftp_packet(NET_SFTP_MKDIR, Strings::packSSH2('s', $dir) . "\0\0\0\0"); - - $response = $this->get_sftp_packet(); - if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. ' - . 'Got packet type: ' . $this->packet_type); - } - - list($status) = Strings::unpackSSH2('N', $response); - if ($status != NET_SFTP_STATUS_OK) { - $this->logError($response, $status); - return false; - } - - if ($mode !== -1) { - $this->chmod($mode, $dir); - } - - return true; - } - - /** - * Removes a directory. - * - * @param string $dir - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return bool - */ - public function rmdir($dir) - { - if (!$this->precheck()) { - return false; - } - - $dir = $this->realpath($dir); - if ($dir === false) { - return false; - } - - $this->send_sftp_packet(NET_SFTP_RMDIR, Strings::packSSH2('s', $dir)); - - $response = $this->get_sftp_packet(); - if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. ' - . 'Got packet type: ' . $this->packet_type); - } - - list($status) = Strings::unpackSSH2('N', $response); - if ($status != NET_SFTP_STATUS_OK) { - // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED? - $this->logError($response, $status); - return false; - } - - $this->remove_from_stat_cache($dir); - // the following will do a soft delete, which would be useful if you deleted a file - // and then tried to do a stat on the deleted file. the above, in contrast, does - // a hard delete - //$this->update_stat_cache($dir, false); - - return true; - } - - /** - * Uploads a file to the SFTP server. - * - * By default, \phpseclib3\Net\SFTP::put() does not read from the local filesystem. $data is dumped directly into $remote_file. - * So, for example, if you set $data to 'filename.ext' and then do \phpseclib3\Net\SFTP::get(), you will get a file, twelve bytes - * long, containing 'filename.ext' as its contents. - * - * Setting $mode to self::SOURCE_LOCAL_FILE will change the above behavior. With self::SOURCE_LOCAL_FILE, $remote_file will - * contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how - * large $remote_file will be, as well. - * - * Setting $mode to self::SOURCE_CALLBACK will use $data as callback function, which gets only one parameter -- number - * of bytes to return, and returns a string if there is some data or null if there is no more data - * - * If $data is a resource then it'll be used as a resource instead. - * - * Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take - * care of that, yourself. - * - * $mode can take an additional two parameters - self::RESUME and self::RESUME_START. These are bitwise AND'd with - * $mode. So if you want to resume upload of a 300mb file on the local file system you'd set $mode to the following: - * - * self::SOURCE_LOCAL_FILE | self::RESUME - * - * If you wanted to simply append the full contents of a local file to the full contents of a remote file you'd replace - * self::RESUME with self::RESUME_START. - * - * If $mode & (self::RESUME | self::RESUME_START) then self::RESUME_START will be assumed. - * - * $start and $local_start give you more fine grained control over this process and take precident over self::RESUME - * when they're non-negative. ie. $start could let you write at the end of a file (like self::RESUME) or in the middle - * of one. $local_start could let you start your reading from the end of a file (like self::RESUME_START) or in the - * middle of one. - * - * Setting $local_start to > 0 or $mode | self::RESUME_START doesn't do anything unless $mode | self::SOURCE_LOCAL_FILE. - * - * {@internal ASCII mode for SFTPv4/5/6 can be supported by adding a new function - \phpseclib3\Net\SFTP::setMode().} - * - * @param string $remote_file - * @param string|resource $data - * @param int $mode - * @param int $start - * @param int $local_start - * @param callable|null $progressCallback - * @throws \UnexpectedValueException on receipt of unexpected packets - * @throws \BadFunctionCallException if you're uploading via a callback and the callback function is invalid - * @throws \phpseclib3\Exception\FileNotFoundException if you're uploading via a file and the file doesn't exist - * @return bool - */ - public function put($remote_file, $data, $mode = self::SOURCE_STRING, $start = -1, $local_start = -1, $progressCallback = null) - { - if (!$this->precheck()) { - return false; - } - - $remote_file = $this->realpath($remote_file); - if ($remote_file === false) { - return false; - } - - $this->remove_from_stat_cache($remote_file); - - if ($this->version >= 5) { - $flags = NET_SFTP_OPEN_OPEN_OR_CREATE; - } else { - $flags = NET_SFTP_OPEN_WRITE | NET_SFTP_OPEN_CREATE; - // according to the SFTP specs, NET_SFTP_OPEN_APPEND should "force all writes to append data at the end of the file." - // in practice, it doesn't seem to do that. - //$flags|= ($mode & self::RESUME) ? NET_SFTP_OPEN_APPEND : NET_SFTP_OPEN_TRUNCATE; - } - - if ($start >= 0) { - $offset = $start; - } elseif ($mode & self::RESUME) { - // if NET_SFTP_OPEN_APPEND worked as it should _size() wouldn't need to be called - $size = $this->stat($remote_file)['size']; - $offset = $size !== false ? $size : 0; - } else { - $offset = 0; - if ($this->version >= 5) { - $flags = NET_SFTP_OPEN_CREATE_TRUNCATE; - } else { - $flags |= NET_SFTP_OPEN_TRUNCATE; - } - } - - $this->remove_from_stat_cache($remote_file); - - $packet = Strings::packSSH2('s', $remote_file); - $packet .= $this->version >= 5 ? - pack('N3', 0, $flags, 0) : - pack('N2', $flags, 0); - $this->send_sftp_packet(NET_SFTP_OPEN, $packet); - - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_HANDLE: - $handle = substr($response, 4); - break; - case NET_SFTP_STATUS: - $this->logError($response); - return false; - default: - throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. ' - . 'Got packet type: ' . $this->packet_type); - } - - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.3 - $dataCallback = false; - switch (true) { - case $mode & self::SOURCE_CALLBACK: - if (!is_callable($data)) { - throw new \BadFunctionCallException("\$data should be is_callable() if you specify SOURCE_CALLBACK flag"); - } - $dataCallback = $data; - // do nothing - break; - case is_resource($data): - $mode = $mode & ~self::SOURCE_LOCAL_FILE; - $info = stream_get_meta_data($data); - if (isset($info['wrapper_type']) && $info['wrapper_type'] == 'PHP' && $info['stream_type'] == 'Input') { - $fp = fopen('php://memory', 'w+'); - stream_copy_to_stream($data, $fp); - rewind($fp); - } else { - $fp = $data; - } - break; - case $mode & self::SOURCE_LOCAL_FILE: - if (!is_file($data)) { - throw new FileNotFoundException("$data is not a valid file"); - } - $fp = @fopen($data, 'rb'); - if (!$fp) { - return false; - } - } - - if (isset($fp)) { - $stat = fstat($fp); - $size = !empty($stat) ? $stat['size'] : 0; - - if ($local_start >= 0) { - fseek($fp, $local_start); - $size -= $local_start; - } - } elseif ($dataCallback) { - $size = 0; - } else { - $size = strlen($data); - } - - $sent = 0; - $size = $size < 0 ? ($size & 0x7FFFFFFF) + 0x80000000 : $size; - - $sftp_packet_size = $this->max_sftp_packet; - // make the SFTP packet be exactly the SFTP packet size by including the bytes in the NET_SFTP_WRITE packets "header" - $sftp_packet_size -= strlen($handle) + 25; - $i = $j = 0; - while ($dataCallback || ($size === 0 || $sent < $size)) { - if ($dataCallback) { - $temp = $dataCallback($sftp_packet_size); - if (is_null($temp)) { - break; - } - } else { - $temp = isset($fp) ? fread($fp, $sftp_packet_size) : substr($data, $sent, $sftp_packet_size); - if ($temp === false || $temp === '') { - break; - } - } - - $subtemp = $offset + $sent; - $packet = pack('Na*N3a*', strlen($handle), $handle, $subtemp / 4294967296, $subtemp, strlen($temp), $temp); - try { - $this->send_sftp_packet(NET_SFTP_WRITE, $packet, $j); - } catch (\Exception $e) { - if ($mode & self::SOURCE_LOCAL_FILE) { - fclose($fp); - } - throw $e; - } - $sent += strlen($temp); - if (is_callable($progressCallback)) { - $progressCallback($sent); - } - - $i++; - $j++; - if ($i == NET_SFTP_UPLOAD_QUEUE_SIZE) { - if (!$this->read_put_responses($i)) { - $i = 0; - break; - } - $i = 0; - } - } - - $result = $this->close_handle($handle); - - if (!$this->read_put_responses($i)) { - if ($mode & self::SOURCE_LOCAL_FILE) { - fclose($fp); - } - $this->close_handle($handle); - return false; - } - - if ($mode & SFTP::SOURCE_LOCAL_FILE) { - if (isset($fp) && is_resource($fp)) { - fclose($fp); - } - - if ($this->preserveTime) { - $stat = stat($data); - $attr = $this->version < 4 ? - pack('N3', NET_SFTP_ATTR_ACCESSTIME, $stat['atime'], $stat['mtime']) : - Strings::packSSH2('NQ2', NET_SFTP_ATTR_ACCESSTIME | NET_SFTP_ATTR_MODIFYTIME, $stat['atime'], $stat['mtime']); - if (!$this->setstat($remote_file, $attr, false)) { - throw new \RuntimeException('Error setting file time'); - } - } - } - - return $result; - } - - /** - * Reads multiple successive SSH_FXP_WRITE responses - * - * Sending an SSH_FXP_WRITE packet and immediately reading its response isn't as efficient as blindly sending out $i - * SSH_FXP_WRITEs, in succession, and then reading $i responses. - * - * @param int $i - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - */ - private function read_put_responses($i) - { - while ($i--) { - $response = $this->get_sftp_packet(); - if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. ' - . 'Got packet type: ' . $this->packet_type); - } - - list($status) = Strings::unpackSSH2('N', $response); - if ($status != NET_SFTP_STATUS_OK) { - $this->logError($response, $status); - break; - } - } - - return $i < 0; - } - - /** - * Close handle - * - * @param string $handle - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - */ - private function close_handle($handle) - { - $this->send_sftp_packet(NET_SFTP_CLOSE, pack('Na*', strlen($handle), $handle)); - - // "The client MUST release all resources associated with the handle regardless of the status." - // -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.3 - $response = $this->get_sftp_packet(); - if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. ' - . 'Got packet type: ' . $this->packet_type); - } - - list($status) = Strings::unpackSSH2('N', $response); - if ($status != NET_SFTP_STATUS_OK) { - $this->logError($response, $status); - return false; - } - - return true; - } - - /** - * Downloads a file from the SFTP server. - * - * Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if - * the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the - * operation. - * - * $offset and $length can be used to download files in chunks. - * - * @param string $remote_file - * @param string|bool|resource|callable $local_file - * @param int $offset - * @param int $length - * @param callable|null $progressCallback - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return string|bool - */ - public function get($remote_file, $local_file = false, $offset = 0, $length = -1, $progressCallback = null) - { - if (!$this->precheck()) { - return false; - } - - $remote_file = $this->realpath($remote_file); - if ($remote_file === false) { - return false; - } - - $packet = Strings::packSSH2('s', $remote_file); - $packet .= $this->version >= 5 ? - pack('N3', 0, NET_SFTP_OPEN_OPEN_EXISTING, 0) : - pack('N2', NET_SFTP_OPEN_READ, 0); - $this->send_sftp_packet(NET_SFTP_OPEN, $packet); - - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_HANDLE: - $handle = substr($response, 4); - break; - case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED - $this->logError($response); - return false; - default: - throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. ' - . 'Got packet type: ' . $this->packet_type); - } - - if (is_resource($local_file)) { - $fp = $local_file; - $stat = fstat($fp); - $res_offset = $stat['size']; - } else { - $res_offset = 0; - if ($local_file !== false && !is_callable($local_file)) { - $fp = fopen($local_file, 'wb'); - if (!$fp) { - return false; - } - } else { - $content = ''; - } - } - - $fclose_check = $local_file !== false && !is_callable($local_file) && !is_resource($local_file); - - $start = $offset; - $read = 0; - while (true) { - $i = 0; - - while ($i < NET_SFTP_QUEUE_SIZE && ($length < 0 || $read < $length)) { - $tempoffset = $start + $read; - - $packet_size = $length > 0 ? min($this->max_sftp_packet, $length - $read) : $this->max_sftp_packet; - - $packet = Strings::packSSH2('sN3', $handle, $tempoffset / 4294967296, $tempoffset, $packet_size); - try { - $this->send_sftp_packet(NET_SFTP_READ, $packet, $i); - } catch (\Exception $e) { - if ($fclose_check) { - fclose($fp); - } - throw $e; - } - $packet = null; - $read += $packet_size; - $i++; - } - - if (!$i) { - break; - } - - $packets_sent = $i - 1; - - $clear_responses = false; - while ($i > 0) { - $i--; - - if ($clear_responses) { - $this->get_sftp_packet($packets_sent - $i); - continue; - } else { - $response = $this->get_sftp_packet($packets_sent - $i); - } - - switch ($this->packet_type) { - case NET_SFTP_DATA: - $temp = substr($response, 4); - $offset += strlen($temp); - if ($local_file === false) { - $content .= $temp; - } elseif (is_callable($local_file)) { - $local_file($temp); - } else { - fputs($fp, $temp); - } - if (is_callable($progressCallback)) { - call_user_func($progressCallback, $offset); - } - $temp = null; - break; - case NET_SFTP_STATUS: - // could, in theory, return false if !strlen($content) but we'll hold off for the time being - $this->logError($response); - $clear_responses = true; // don't break out of the loop yet, so we can read the remaining responses - break; - default: - if ($fclose_check) { - fclose($fp); - } - if ($this->channel_close) { - $this->partial_init = false; - $this->init_sftp_connection(); - return false; - } else { - throw new \UnexpectedValueException('Expected NET_SFTP_DATA or NET_SFTP_STATUS. ' - . 'Got packet type: ' . $this->packet_type); - } - } - $response = null; - } - - if ($clear_responses) { - break; - } - } - - if ($length > 0 && $length <= $offset - $start) { - if ($local_file === false) { - $content = substr($content, 0, $length); - } else { - ftruncate($fp, $length + $res_offset); - } - } - - if ($fclose_check) { - fclose($fp); - - if ($this->preserveTime) { - $stat = $this->stat($remote_file); - touch($local_file, $stat['mtime'], $stat['atime']); - } - } - - if (!$this->close_handle($handle)) { - return false; - } - - // if $content isn't set that means a file was written to - return isset($content) ? $content : true; - } - - /** - * Deletes a file on the SFTP server. - * - * @param string $path - * @param bool $recursive - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - */ - public function delete($path, $recursive = true) - { - if (!$this->precheck()) { - return false; - } - - if (is_object($path)) { - // It's an object. Cast it as string before we check anything else. - $path = (string) $path; - } - - if (!is_string($path) || $path == '') { - return false; - } - - $path = $this->realpath($path); - if ($path === false) { - return false; - } - - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3 - $this->send_sftp_packet(NET_SFTP_REMOVE, pack('Na*', strlen($path), $path)); - - $response = $this->get_sftp_packet(); - if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. ' - . 'Got packet type: ' . $this->packet_type); - } - - // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED - list($status) = Strings::unpackSSH2('N', $response); - if ($status != NET_SFTP_STATUS_OK) { - $this->logError($response, $status); - if (!$recursive) { - return false; - } - - $i = 0; - $result = $this->delete_recursive($path, $i); - $this->read_put_responses($i); - return $result; - } - - $this->remove_from_stat_cache($path); - - return true; - } - - /** - * Recursively deletes directories on the SFTP server - * - * Minimizes directory lookups and SSH_FXP_STATUS requests for speed. - * - * @param string $path - * @param int $i - * @return bool - */ - private function delete_recursive($path, &$i) - { - if (!$this->read_put_responses($i)) { - return false; - } - $i = 0; - $entries = $this->readlist($path, true); - - // The folder does not exist at all, so we cannot delete it. - if ($entries === NET_SFTP_STATUS_NO_SUCH_FILE) { - return false; - } - - // Normally $entries would have at least . and .. but it might not if the directories - // permissions didn't allow reading. If this happens then default to an empty list of files. - if ($entries === false || is_int($entries)) { - $entries = []; - } - - unset($entries['.'], $entries['..']); - foreach ($entries as $filename => $props) { - if (!isset($props['type'])) { - return false; - } - - $temp = $path . '/' . $filename; - if ($props['type'] == NET_SFTP_TYPE_DIRECTORY) { - if (!$this->delete_recursive($temp, $i)) { - return false; - } - } else { - $this->send_sftp_packet(NET_SFTP_REMOVE, Strings::packSSH2('s', $temp)); - $this->remove_from_stat_cache($temp); - - $i++; - - if ($i >= NET_SFTP_QUEUE_SIZE) { - if (!$this->read_put_responses($i)) { - return false; - } - $i = 0; - } - } - } - - $this->send_sftp_packet(NET_SFTP_RMDIR, Strings::packSSH2('s', $path)); - $this->remove_from_stat_cache($path); - - $i++; - - if ($i >= NET_SFTP_QUEUE_SIZE) { - if (!$this->read_put_responses($i)) { - return false; - } - $i = 0; - } - - return true; - } - - /** - * Checks whether a file or directory exists - * - * @param string $path - * @return bool - */ - public function file_exists($path) - { - if ($this->use_stat_cache) { - if (!$this->precheck()) { - return false; - } - - $path = $this->realpath($path); - - $result = $this->query_stat_cache($path); - - if (isset($result)) { - // return true if $result is an array or if it's an stdClass object - return $result !== false; - } - } - - return $this->stat($path) !== false; - } - - /** - * Tells whether the filename is a directory - * - * @param string $path - * @return bool - */ - public function is_dir($path) - { - $result = $this->get_stat_cache_prop($path, 'type'); - if ($result === false) { - return false; - } - return $result === NET_SFTP_TYPE_DIRECTORY; - } - - /** - * Tells whether the filename is a regular file - * - * @param string $path - * @return bool - */ - public function is_file($path) - { - $result = $this->get_stat_cache_prop($path, 'type'); - if ($result === false) { - return false; - } - return $result === NET_SFTP_TYPE_REGULAR; - } - - /** - * Tells whether the filename is a symbolic link - * - * @param string $path - * @return bool - */ - public function is_link($path) - { - $result = $this->get_lstat_cache_prop($path, 'type'); - if ($result === false) { - return false; - } - return $result === NET_SFTP_TYPE_SYMLINK; - } - - /** - * Tells whether a file exists and is readable - * - * @param string $path - * @return bool - */ - public function is_readable($path) - { - if (!$this->precheck()) { - return false; - } - - $packet = Strings::packSSH2('sNN', $this->realpath($path), NET_SFTP_OPEN_READ, 0); - $this->send_sftp_packet(NET_SFTP_OPEN, $packet); - - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_HANDLE: - return true; - case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED - return false; - default: - throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. ' - . 'Got packet type: ' . $this->packet_type); - } - } - - /** - * Tells whether the filename is writable - * - * @param string $path - * @return bool - */ - public function is_writable($path) - { - if (!$this->precheck()) { - return false; - } - - $packet = Strings::packSSH2('sNN', $this->realpath($path), NET_SFTP_OPEN_WRITE, 0); - $this->send_sftp_packet(NET_SFTP_OPEN, $packet); - - $response = $this->get_sftp_packet(); - switch ($this->packet_type) { - case NET_SFTP_HANDLE: - return true; - case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED - return false; - default: - throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS. ' - . 'Got packet type: ' . $this->packet_type); - } - } - - /** - * Tells whether the filename is writeable - * - * Alias of is_writable - * - * @param string $path - * @return bool - */ - public function is_writeable($path) - { - return $this->is_writable($path); - } - - /** - * Gets last access time of file - * - * @param string $path - * @return mixed - */ - public function fileatime($path) - { - return $this->get_stat_cache_prop($path, 'atime'); - } - - /** - * Gets file modification time - * - * @param string $path - * @return mixed - */ - public function filemtime($path) - { - return $this->get_stat_cache_prop($path, 'mtime'); - } - - /** - * Gets file permissions - * - * @param string $path - * @return mixed - */ - public function fileperms($path) - { - return $this->get_stat_cache_prop($path, 'mode'); - } - - /** - * Gets file owner - * - * @param string $path - * @return mixed - */ - public function fileowner($path) - { - return $this->get_stat_cache_prop($path, 'uid'); - } - - /** - * Gets file group - * - * @param string $path - * @return mixed - */ - public function filegroup($path) - { - return $this->get_stat_cache_prop($path, 'gid'); - } - - /** - * Gets file size - * - * @param string $path - * @return mixed - */ - public function filesize($path) - { - return $this->get_stat_cache_prop($path, 'size'); - } - - /** - * Gets file type - * - * @param string $path - * @return string|false - */ - public function filetype($path) - { - $type = $this->get_stat_cache_prop($path, 'type'); - if ($type === false) { - return false; - } - - switch ($type) { - case NET_SFTP_TYPE_BLOCK_DEVICE: - return 'block'; - case NET_SFTP_TYPE_CHAR_DEVICE: - return 'char'; - case NET_SFTP_TYPE_DIRECTORY: - return 'dir'; - case NET_SFTP_TYPE_FIFO: - return 'fifo'; - case NET_SFTP_TYPE_REGULAR: - return 'file'; - case NET_SFTP_TYPE_SYMLINK: - return 'link'; - default: - return false; - } - } - - /** - * Return a stat properity - * - * Uses cache if appropriate. - * - * @param string $path - * @param string $prop - * @return mixed - */ - private function get_stat_cache_prop($path, $prop) - { - return $this->get_xstat_cache_prop($path, $prop, 'stat'); - } - - /** - * Return an lstat properity - * - * Uses cache if appropriate. - * - * @param string $path - * @param string $prop - * @return mixed - */ - private function get_lstat_cache_prop($path, $prop) - { - return $this->get_xstat_cache_prop($path, $prop, 'lstat'); - } - - /** - * Return a stat or lstat properity - * - * Uses cache if appropriate. - * - * @param string $path - * @param string $prop - * @param string $type - * @return mixed - */ - private function get_xstat_cache_prop($path, $prop, $type) - { - if (!$this->precheck()) { - return false; - } - - if ($this->use_stat_cache) { - $path = $this->realpath($path); - - $result = $this->query_stat_cache($path); - - if (is_object($result) && isset($result->$type)) { - return $result->{$type}[$prop]; - } - } - - $result = $this->$type($path); - - if ($result === false || !isset($result[$prop])) { - return false; - } - - return $result[$prop]; - } - - /** - * Renames a file or a directory on the SFTP server. - * - * If the file already exists this will return false - * - * @param string $oldname - * @param string $newname - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - */ - public function rename($oldname, $newname) - { - if (!$this->precheck()) { - return false; - } - - $oldname = $this->realpath($oldname); - $newname = $this->realpath($newname); - if ($oldname === false || $newname === false) { - return false; - } - - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3 - $packet = Strings::packSSH2('ss', $oldname, $newname); - if ($this->version >= 5) { - /* quoting https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-05#section-6.5 , - - 'flags' is 0 or a combination of: - - SSH_FXP_RENAME_OVERWRITE 0x00000001 - SSH_FXP_RENAME_ATOMIC 0x00000002 - SSH_FXP_RENAME_NATIVE 0x00000004 - - (none of these are currently supported) */ - $packet .= "\0\0\0\0"; - } - $this->send_sftp_packet(NET_SFTP_RENAME, $packet); - - $response = $this->get_sftp_packet(); - if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. ' - . 'Got packet type: ' . $this->packet_type); - } - - // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED - list($status) = Strings::unpackSSH2('N', $response); - if ($status != NET_SFTP_STATUS_OK) { - $this->logError($response, $status); - return false; - } - - // don't move the stat cache entry over since this operation could very well change the - // atime and mtime attributes - //$this->update_stat_cache($newname, $this->query_stat_cache($oldname)); - $this->remove_from_stat_cache($oldname); - $this->remove_from_stat_cache($newname); - - return true; - } - - /** - * Parse Time - * - * See '7.7. Times' of draft-ietf-secsh-filexfer-13 for more info. - * - * @param string $key - * @param int $flags - * @param string $response - * @return array - */ - private function parseTime($key, $flags, &$response) - { - $attr = []; - list($attr[$key]) = Strings::unpackSSH2('Q', $response); - if ($flags & NET_SFTP_ATTR_SUBSECOND_TIMES) { - list($attr[$key . '-nseconds']) = Strings::unpackSSH2('N', $response); - } - return $attr; - } - - /** - * Parse Attributes - * - * See '7. File Attributes' of draft-ietf-secsh-filexfer-13 for more info. - * - * @param string $response - * @return array - */ - protected function parseAttributes(&$response) - { - if ($this->version >= 4) { - list($flags, $attr['type']) = Strings::unpackSSH2('NC', $response); - } else { - list($flags) = Strings::unpackSSH2('N', $response); - } - - foreach ($this->attributes as $key => $value) { - switch ($flags & $key) { - case NET_SFTP_ATTR_UIDGID: - if ($this->version > 3) { - continue 2; - } - break; - case NET_SFTP_ATTR_CREATETIME: - case NET_SFTP_ATTR_MODIFYTIME: - case NET_SFTP_ATTR_ACL: - case NET_SFTP_ATTR_OWNERGROUP: - case NET_SFTP_ATTR_SUBSECOND_TIMES: - if ($this->version < 4) { - continue 2; - } - break; - case NET_SFTP_ATTR_BITS: - if ($this->version < 5) { - continue 2; - } - break; - case NET_SFTP_ATTR_ALLOCATION_SIZE: - case NET_SFTP_ATTR_TEXT_HINT: - case NET_SFTP_ATTR_MIME_TYPE: - case NET_SFTP_ATTR_LINK_COUNT: - case NET_SFTP_ATTR_UNTRANSLATED_NAME: - case NET_SFTP_ATTR_CTIME: - if ($this->version < 6) { - continue 2; - } - } - switch ($flags & $key) { - case NET_SFTP_ATTR_SIZE: // 0x00000001 - // The size attribute is defined as an unsigned 64-bit integer. - // The following will use floats on 32-bit platforms, if necessary. - // As can be seen in the BigInteger class, floats are generally - // IEEE 754 binary64 "double precision" on such platforms and - // as such can represent integers of at least 2^50 without loss - // of precision. Interpreted in filesize, 2^50 bytes = 1024 TiB. - list($attr['size']) = Strings::unpackSSH2('Q', $response); - break; - case NET_SFTP_ATTR_UIDGID: // 0x00000002 (SFTPv3 only) - list($attr['uid'], $attr['gid']) = Strings::unpackSSH2('NN', $response); - break; - case NET_SFTP_ATTR_PERMISSIONS: // 0x00000004 - list($attr['mode']) = Strings::unpackSSH2('N', $response); - $fileType = $this->parseMode($attr['mode']); - if ($this->version < 4 && $fileType !== false) { - $attr += ['type' => $fileType]; - } - break; - case NET_SFTP_ATTR_ACCESSTIME: // 0x00000008 - if ($this->version >= 4) { - $attr += $this->parseTime('atime', $flags, $response); - break; - } - list($attr['atime'], $attr['mtime']) = Strings::unpackSSH2('NN', $response); - break; - case NET_SFTP_ATTR_CREATETIME: // 0x00000010 (SFTPv4+) - $attr += $this->parseTime('createtime', $flags, $response); - break; - case NET_SFTP_ATTR_MODIFYTIME: // 0x00000020 - $attr += $this->parseTime('mtime', $flags, $response); - break; - case NET_SFTP_ATTR_ACL: // 0x00000040 - // access control list - // see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-04#section-5.7 - // currently unsupported - list($count) = Strings::unpackSSH2('N', $response); - for ($i = 0; $i < $count; $i++) { - list($type, $flag, $mask, $who) = Strings::unpackSSH2('N3s', $result); - } - break; - case NET_SFTP_ATTR_OWNERGROUP: // 0x00000080 - list($attr['owner'], $attr['$group']) = Strings::unpackSSH2('ss', $response); - break; - case NET_SFTP_ATTR_SUBSECOND_TIMES: // 0x00000100 - break; - case NET_SFTP_ATTR_BITS: // 0x00000200 (SFTPv5+) - // see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-05#section-5.8 - // currently unsupported - // tells if you file is: - // readonly, system, hidden, case inensitive, archive, encrypted, compressed, sparse - // append only, immutable, sync - list($attrib_bits, $attrib_bits_valid) = Strings::unpackSSH2('N2', $response); - // if we were actually gonna implement the above it ought to be - // $attr['attrib-bits'] and $attr['attrib-bits-valid'] - // eg. - instead of _ - break; - case NET_SFTP_ATTR_ALLOCATION_SIZE: // 0x00000400 (SFTPv6+) - // see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.4 - // represents the number of bytes that the file consumes on the disk. will - // usually be larger than the 'size' field - list($attr['allocation-size']) = Strings::unpackSSH2('Q', $response); - break; - case NET_SFTP_ATTR_TEXT_HINT: // 0x00000800 - // https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.10 - // currently unsupported - // tells if file is "known text", "guessed text", "known binary", "guessed binary" - list($text_hint) = Strings::unpackSSH2('C', $response); - // the above should be $attr['text-hint'] - break; - case NET_SFTP_ATTR_MIME_TYPE: // 0x00001000 - // see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.11 - list($attr['mime-type']) = Strings::unpackSSH2('s', $response); - break; - case NET_SFTP_ATTR_LINK_COUNT: // 0x00002000 - // see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.12 - list($attr['link-count']) = Strings::unpackSSH2('N', $response); - break; - case NET_SFTP_ATTR_UNTRANSLATED_NAME:// 0x00004000 - // see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.13 - list($attr['untranslated-name']) = Strings::unpackSSH2('s', $response); - break; - case NET_SFTP_ATTR_CTIME: // 0x00008000 - // 'ctime' contains the last time the file attributes were changed. The - // exact meaning of this field depends on the server. - $attr += $this->parseTime('ctime', $flags, $response); - break; - case NET_SFTP_ATTR_EXTENDED: // 0x80000000 - list($count) = Strings::unpackSSH2('N', $response); - for ($i = 0; $i < $count; $i++) { - list($key, $value) = Strings::unpackSSH2('ss', $response); - $attr[$key] = $value; - } - } - } - return $attr; - } - - /** - * Attempt to identify the file type - * - * Quoting the SFTP RFC, "Implementations MUST NOT send bits that are not defined" but they seem to anyway - * - * @param int $mode - * @return int - */ - private function parseMode($mode) - { - // values come from http://lxr.free-electrons.com/source/include/uapi/linux/stat.h#L12 - // see, also, http://linux.die.net/man/2/stat - switch ($mode & 0170000) {// ie. 1111 0000 0000 0000 - case 0000000: // no file type specified - figure out the file type using alternative means - return false; - case 0040000: - return NET_SFTP_TYPE_DIRECTORY; - case 0100000: - return NET_SFTP_TYPE_REGULAR; - case 0120000: - return NET_SFTP_TYPE_SYMLINK; - // new types introduced in SFTPv5+ - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-05#section-5.2 - case 0010000: // named pipe (fifo) - return NET_SFTP_TYPE_FIFO; - case 0020000: // character special - return NET_SFTP_TYPE_CHAR_DEVICE; - case 0060000: // block special - return NET_SFTP_TYPE_BLOCK_DEVICE; - case 0140000: // socket - return NET_SFTP_TYPE_SOCKET; - case 0160000: // whiteout - // "SPECIAL should be used for files that are of - // a known type which cannot be expressed in the protocol" - return NET_SFTP_TYPE_SPECIAL; - default: - return NET_SFTP_TYPE_UNKNOWN; - } - } - - /** - * Parse Longname - * - * SFTPv3 doesn't provide any easy way of identifying a file type. You could try to open - * a file as a directory and see if an error is returned or you could try to parse the - * SFTPv3-specific longname field of the SSH_FXP_NAME packet. That's what this function does. - * The result is returned using the - * {@link http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-5.2 SFTPv4 type constants}. - * - * If the longname is in an unrecognized format bool(false) is returned. - * - * @param string $longname - * @return mixed - */ - private function parseLongname($longname) - { - // http://en.wikipedia.org/wiki/Unix_file_types - // http://en.wikipedia.org/wiki/Filesystem_permissions#Notation_of_traditional_Unix_permissions - if (preg_match('#^[^/]([r-][w-][xstST-]){3}#', $longname)) { - switch ($longname[0]) { - case '-': - return NET_SFTP_TYPE_REGULAR; - case 'd': - return NET_SFTP_TYPE_DIRECTORY; - case 'l': - return NET_SFTP_TYPE_SYMLINK; - default: - return NET_SFTP_TYPE_SPECIAL; - } - } - - return false; - } - - /** - * Sends SFTP Packets - * - * See '6. General Packet Format' of draft-ietf-secsh-filexfer-13 for more info. - * - * @param int $type - * @param string $data - * @param int $request_id - * @see self::_get_sftp_packet() - * @see self::send_channel_packet() - * @return void - */ - private function send_sftp_packet($type, $data, $request_id = 1) - { - // in SSH2.php the timeout is cumulative per function call. eg. exec() will - // timeout after 10s. but for SFTP.php it's cumulative per packet - $this->curTimeout = $this->timeout; - - $packet = $this->use_request_id ? - pack('NCNa*', strlen($data) + 5, $type, $request_id, $data) : - pack('NCa*', strlen($data) + 1, $type, $data); - - $start = microtime(true); - $this->send_channel_packet(self::CHANNEL, $packet); - $stop = microtime(true); - - if (defined('NET_SFTP_LOGGING')) { - $packet_type = '-> ' . $this->packet_types[$type] . - ' (' . round($stop - $start, 4) . 's)'; - $this->append_log($packet_type, $data); - } - } - - /** - * Resets a connection for re-use - * - * @param int $reason - */ - protected function reset_connection($reason) - { - parent::reset_connection($reason); - $this->use_request_id = false; - $this->pwd = false; - $this->requestBuffer = []; - } - - /** - * Receives SFTP Packets - * - * See '6. General Packet Format' of draft-ietf-secsh-filexfer-13 for more info. - * - * Incidentally, the number of SSH_MSG_CHANNEL_DATA messages has no bearing on the number of SFTP packets present. - * There can be one SSH_MSG_CHANNEL_DATA messages containing two SFTP packets or there can be two SSH_MSG_CHANNEL_DATA - * messages containing one SFTP packet. - * - * @see self::_send_sftp_packet() - * @return string - */ - private function get_sftp_packet($request_id = null) - { - $this->channel_close = false; - - if (isset($request_id) && isset($this->requestBuffer[$request_id])) { - $this->packet_type = $this->requestBuffer[$request_id]['packet_type']; - $temp = $this->requestBuffer[$request_id]['packet']; - unset($this->requestBuffer[$request_id]); - return $temp; - } - - // in SSH2.php the timeout is cumulative per function call. eg. exec() will - // timeout after 10s. but for SFTP.php it's cumulative per packet - $this->curTimeout = $this->timeout; - - $start = microtime(true); - - // SFTP packet length - while (strlen($this->packet_buffer) < 4) { - $temp = $this->get_channel_packet(self::CHANNEL, true); - if ($temp === true) { - if ($this->channel_status[self::CHANNEL] === NET_SSH2_MSG_CHANNEL_CLOSE) { - $this->channel_close = true; - } - $this->packet_type = false; - $this->packet_buffer = ''; - return false; - } - $this->packet_buffer .= $temp; - } - if (strlen($this->packet_buffer) < 4) { - throw new \RuntimeException('Packet is too small'); - } - extract(unpack('Nlength', Strings::shift($this->packet_buffer, 4))); - /** @var integer $length */ - - $tempLength = $length; - $tempLength -= strlen($this->packet_buffer); - - // 256 * 1024 is what SFTP_MAX_MSG_LENGTH is set to in OpenSSH's sftp-common.h - if (!$this->allow_arbitrary_length_packets && !$this->use_request_id && $tempLength > 256 * 1024) { - throw new \RuntimeException('Invalid Size'); - } - - // SFTP packet type and data payload - while ($tempLength > 0) { - $temp = $this->get_channel_packet(self::CHANNEL, true); - if ($temp === true) { - if ($this->channel_status[self::CHANNEL] === NET_SSH2_MSG_CHANNEL_CLOSE) { - $this->channel_close = true; - } - $this->packet_type = false; - $this->packet_buffer = ''; - return false; - } - $this->packet_buffer .= $temp; - $tempLength -= strlen($temp); - } - - $stop = microtime(true); - - $this->packet_type = ord(Strings::shift($this->packet_buffer)); - - if ($this->use_request_id) { - extract(unpack('Npacket_id', Strings::shift($this->packet_buffer, 4))); // remove the request id - $length -= 5; // account for the request id and the packet type - } else { - $length -= 1; // account for the packet type - } - - $packet = Strings::shift($this->packet_buffer, $length); - - if (defined('NET_SFTP_LOGGING')) { - $packet_type = '<- ' . $this->packet_types[$this->packet_type] . - ' (' . round($stop - $start, 4) . 's)'; - $this->append_log($packet_type, $packet); - } - - if (isset($request_id) && $this->use_request_id && $packet_id != $request_id) { - $this->requestBuffer[$packet_id] = [ - 'packet_type' => $this->packet_type, - 'packet' => $packet - ]; - return $this->get_sftp_packet($request_id); - } - - return $packet; - } - - /** - * Logs data packets - * - * Makes sure that only the last 1MB worth of packets will be logged - * - * @param string $message_number - * @param string $message - */ - private function append_log($message_number, $message) - { - $this->append_log_helper( - NET_SFTP_LOGGING, - $message_number, - $message, - $this->packet_type_log, - $this->packet_log, - $this->log_size, - $this->realtime_log_file, - $this->realtime_log_wrap, - $this->realtime_log_size - ); - } - - /** - * Returns a log of the packets that have been sent and received. - * - * Returns a string if NET_SFTP_LOGGING == self::LOG_COMPLEX, an array if NET_SFTP_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SFTP_LOGGING') - * - * @return array|string - */ - public function getSFTPLog() - { - if (!defined('NET_SFTP_LOGGING')) { - return false; - } - - switch (NET_SFTP_LOGGING) { - case self::LOG_COMPLEX: - return $this->format_log($this->packet_log, $this->packet_type_log); - break; - //case self::LOG_SIMPLE: - default: - return $this->packet_type_log; - } - } - - /** - * Returns all errors - * - * @return array - */ - public function getSFTPErrors() - { - return $this->sftp_errors; - } - - /** - * Returns the last error - * - * @return string - */ - public function getLastSFTPError() - { - return count($this->sftp_errors) ? $this->sftp_errors[count($this->sftp_errors) - 1] : ''; - } - - /** - * Get supported SFTP versions - * - * @return array - */ - public function getSupportedVersions() - { - if (!($this->bitmap & SSH2::MASK_LOGIN)) { - return false; - } - - if (!$this->partial_init) { - $this->partial_init_sftp_connection(); - } - - $temp = ['version' => $this->defaultVersion]; - if (isset($this->extensions['versions'])) { - $temp['extensions'] = $this->extensions['versions']; - } - return $temp; - } - - /** - * Get supported SFTP versions - * - * @return int|false - */ - public function getNegotiatedVersion() - { - if (!$this->precheck()) { - return false; - } - - return $this->version; - } - - /** - * Set preferred version - * - * If you're preferred version isn't supported then the highest supported - * version of SFTP will be utilized. Set to null or false or int(0) to - * unset the preferred version - * - * @param int $version - */ - public function setPreferredVersion($version) - { - $this->preferredVersion = $version; - } - - /** - * Disconnect - * - * @param int $reason - * @return false - */ - protected function disconnect_helper($reason) - { - $this->pwd = false; - return parent::disconnect_helper($reason); - } - - /** - * Enable Date Preservation - * - */ - public function enableDatePreservation() - { - $this->preserveTime = true; - } - - /** - * Disable Date Preservation - * - */ - public function disableDatePreservation() - { - $this->preserveTime = false; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.php deleted file mode 100644 index 24047b4b..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.php +++ /dev/null @@ -1,756 +0,0 @@ - - * @copyright 2013 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Net\SFTP; - -use phpseclib3\Crypt\Common\PrivateKey; -use phpseclib3\Net\SFTP; -use phpseclib3\Net\SSH2; - -/** - * SFTP Stream Wrapper - * - * @author Jim Wigginton - */ -class Stream -{ - /** - * SFTP instances - * - * Rather than re-create the connection we re-use instances if possible - * - * @var array - */ - public static $instances; - - /** - * SFTP instance - * - * @var object - */ - private $sftp; - - /** - * Path - * - * @var string - */ - private $path; - - /** - * Mode - * - * @var string - */ - private $mode; - - /** - * Position - * - * @var int - */ - private $pos; - - /** - * Size - * - * @var int - */ - private $size; - - /** - * Directory entries - * - * @var array - */ - private $entries; - - /** - * EOF flag - * - * @var bool - */ - private $eof; - - /** - * Context resource - * - * Technically this needs to be publicly accessible so PHP can set it directly - * - * @var resource - */ - public $context; - - /** - * Notification callback function - * - * @var callable - */ - private $notification; - - /** - * Registers this class as a URL wrapper. - * - * @param string $protocol The wrapper name to be registered. - * @return bool True on success, false otherwise. - */ - public static function register($protocol = 'sftp') - { - if (in_array($protocol, stream_get_wrappers(), true)) { - return false; - } - return stream_wrapper_register($protocol, get_called_class()); - } - - /** - * The Constructor - * - */ - public function __construct() - { - if (defined('NET_SFTP_STREAM_LOGGING')) { - echo "__construct()\r\n"; - } - } - - /** - * Path Parser - * - * Extract a path from a URI and actually connect to an SSH server if appropriate - * - * If "notification" is set as a context parameter the message code for successful login is - * NET_SSH2_MSG_USERAUTH_SUCCESS. For a failed login it's NET_SSH2_MSG_USERAUTH_FAILURE. - * - * @param string $path - * @return string - */ - protected function parse_path($path) - { - $orig = $path; - extract(parse_url($path) + ['port' => 22]); - if (isset($query)) { - $path .= '?' . $query; - } elseif (preg_match('/(\?|\?#)$/', $orig)) { - $path .= '?'; - } - if (isset($fragment)) { - $path .= '#' . $fragment; - } elseif ($orig[strlen($orig) - 1] == '#') { - $path .= '#'; - } - - if (!isset($host)) { - return false; - } - - if (isset($this->context)) { - $context = stream_context_get_params($this->context); - if (isset($context['notification'])) { - $this->notification = $context['notification']; - } - } - - if (preg_match('/^{[a-z0-9]+}$/i', $host)) { - $host = SSH2::getConnectionByResourceId($host); - if ($host === false) { - return false; - } - $this->sftp = $host; - } else { - if (isset($this->context)) { - $context = stream_context_get_options($this->context); - } - if (isset($context[$scheme]['session'])) { - $sftp = $context[$scheme]['session']; - } - if (isset($context[$scheme]['sftp'])) { - $sftp = $context[$scheme]['sftp']; - } - if (isset($sftp) && $sftp instanceof SFTP) { - $this->sftp = $sftp; - return $path; - } - if (isset($context[$scheme]['username'])) { - $user = $context[$scheme]['username']; - } - if (isset($context[$scheme]['password'])) { - $pass = $context[$scheme]['password']; - } - if (isset($context[$scheme]['privkey']) && $context[$scheme]['privkey'] instanceof PrivateKey) { - $pass = $context[$scheme]['privkey']; - } - - if (!isset($user) || !isset($pass)) { - return false; - } - - // casting $pass to a string is necessary in the event that it's a \phpseclib3\Crypt\RSA object - if (isset(self::$instances[$host][$port][$user][(string) $pass])) { - $this->sftp = self::$instances[$host][$port][$user][(string) $pass]; - } else { - $this->sftp = new SFTP($host, $port); - $this->sftp->disableStatCache(); - if (isset($this->notification) && is_callable($this->notification)) { - /* if !is_callable($this->notification) we could do this: - - user_error('fopen(): failed to call user notifier', E_USER_WARNING); - - the ftp wrapper gives errors like that when the notifier isn't callable. - i've opted not to do that, however, since the ftp wrapper gives the line - on which the fopen occurred as the line number - not the line that the - user_error is on. - */ - call_user_func($this->notification, STREAM_NOTIFY_CONNECT, STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, 0); - call_user_func($this->notification, STREAM_NOTIFY_AUTH_REQUIRED, STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, 0); - if (!$this->sftp->login($user, $pass)) { - call_user_func($this->notification, STREAM_NOTIFY_AUTH_RESULT, STREAM_NOTIFY_SEVERITY_ERR, 'Login Failure', NET_SSH2_MSG_USERAUTH_FAILURE, 0, 0); - return false; - } - call_user_func($this->notification, STREAM_NOTIFY_AUTH_RESULT, STREAM_NOTIFY_SEVERITY_INFO, 'Login Success', NET_SSH2_MSG_USERAUTH_SUCCESS, 0, 0); - } else { - if (!$this->sftp->login($user, $pass)) { - return false; - } - } - self::$instances[$host][$port][$user][(string) $pass] = $this->sftp; - } - } - - return $path; - } - - /** - * Opens file or URL - * - * @param string $path - * @param string $mode - * @param int $options - * @param string $opened_path - * @return bool - */ - private function _stream_open($path, $mode, $options, &$opened_path) - { - $path = $this->parse_path($path); - - if ($path === false) { - return false; - } - $this->path = $path; - - $this->size = $this->sftp->filesize($path); - $this->mode = preg_replace('#[bt]$#', '', $mode); - $this->eof = false; - - if ($this->size === false) { - if ($this->mode[0] == 'r') { - return false; - } else { - $this->sftp->touch($path); - $this->size = 0; - } - } else { - switch ($this->mode[0]) { - case 'x': - return false; - case 'w': - $this->sftp->truncate($path, 0); - $this->size = 0; - } - } - - $this->pos = $this->mode[0] != 'a' ? 0 : $this->size; - - return true; - } - - /** - * Read from stream - * - * @param int $count - * @return mixed - */ - private function _stream_read($count) - { - switch ($this->mode) { - case 'w': - case 'a': - case 'x': - case 'c': - return false; - } - - // commented out because some files - eg. /dev/urandom - will say their size is 0 when in fact it's kinda infinite - //if ($this->pos >= $this->size) { - // $this->eof = true; - // return false; - //} - - $result = $this->sftp->get($this->path, false, $this->pos, $count); - if (isset($this->notification) && is_callable($this->notification)) { - if ($result === false) { - call_user_func($this->notification, STREAM_NOTIFY_FAILURE, STREAM_NOTIFY_SEVERITY_ERR, $this->sftp->getLastSFTPError(), NET_SFTP_OPEN, 0, 0); - return 0; - } - // seems that PHP calls stream_read in 8k chunks - call_user_func($this->notification, STREAM_NOTIFY_PROGRESS, STREAM_NOTIFY_SEVERITY_INFO, '', 0, strlen($result), $this->size); - } - - if (empty($result)) { // ie. false or empty string - $this->eof = true; - return false; - } - $this->pos += strlen($result); - - return $result; - } - - /** - * Write to stream - * - * @param string $data - * @return int|false - */ - private function _stream_write($data) - { - switch ($this->mode) { - case 'r': - return false; - } - - $result = $this->sftp->put($this->path, $data, SFTP::SOURCE_STRING, $this->pos); - if (isset($this->notification) && is_callable($this->notification)) { - if (!$result) { - call_user_func($this->notification, STREAM_NOTIFY_FAILURE, STREAM_NOTIFY_SEVERITY_ERR, $this->sftp->getLastSFTPError(), NET_SFTP_OPEN, 0, 0); - return 0; - } - // seems that PHP splits up strings into 8k blocks before calling stream_write - call_user_func($this->notification, STREAM_NOTIFY_PROGRESS, STREAM_NOTIFY_SEVERITY_INFO, '', 0, strlen($data), strlen($data)); - } - - if ($result === false) { - return false; - } - $this->pos += strlen($data); - if ($this->pos > $this->size) { - $this->size = $this->pos; - } - $this->eof = false; - return strlen($data); - } - - /** - * Retrieve the current position of a stream - * - * @return int - */ - private function _stream_tell() - { - return $this->pos; - } - - /** - * Tests for end-of-file on a file pointer - * - * In my testing there are four classes functions that normally effect the pointer: - * fseek, fputs / fwrite, fgets / fread and ftruncate. - * - * Only fgets / fread, however, results in feof() returning true. do fputs($fp, 'aaa') on a blank file and feof() - * will return false. do fread($fp, 1) and feof() will then return true. do fseek($fp, 10) on ablank file and feof() - * will return false. do fread($fp, 1) and feof() will then return true. - * - * @return bool - */ - private function _stream_eof() - { - return $this->eof; - } - - /** - * Seeks to specific location in a stream - * - * @param int $offset - * @param int $whence - * @return bool - */ - private function _stream_seek($offset, $whence) - { - switch ($whence) { - case SEEK_SET: - if ($offset < 0) { - return false; - } - break; - case SEEK_CUR: - $offset += $this->pos; - break; - case SEEK_END: - $offset += $this->size; - } - - $this->pos = $offset; - $this->eof = false; - return true; - } - - /** - * Change stream options - * - * @param string $path - * @param int $option - * @param mixed $var - * @return bool - */ - private function _stream_metadata($path, $option, $var) - { - $path = $this->parse_path($path); - if ($path === false) { - return false; - } - - // stream_metadata was introduced in PHP 5.4.0 but as of 5.4.11 the constants haven't been defined - // see http://www.php.net/streamwrapper.stream-metadata and https://bugs.php.net/64246 - // and https://github.com/php/php-src/blob/master/main/php_streams.h#L592 - switch ($option) { - case 1: // PHP_STREAM_META_TOUCH - $time = isset($var[0]) ? $var[0] : null; - $atime = isset($var[1]) ? $var[1] : null; - return $this->sftp->touch($path, $time, $atime); - case 2: // PHP_STREAM_OWNER_NAME - case 3: // PHP_STREAM_GROUP_NAME - return false; - case 4: // PHP_STREAM_META_OWNER - return $this->sftp->chown($path, $var); - case 5: // PHP_STREAM_META_GROUP - return $this->sftp->chgrp($path, $var); - case 6: // PHP_STREAM_META_ACCESS - return $this->sftp->chmod($path, $var) !== false; - } - } - - /** - * Retrieve the underlaying resource - * - * @param int $cast_as - * @return resource - */ - private function _stream_cast($cast_as) - { - return $this->sftp->fsock; - } - - /** - * Advisory file locking - * - * @param int $operation - * @return bool - */ - private function _stream_lock($operation) - { - return false; - } - - /** - * Renames a file or directory - * - * Attempts to rename oldname to newname, moving it between directories if necessary. - * If newname exists, it will be overwritten. This is a departure from what \phpseclib3\Net\SFTP - * does. - * - * @param string $path_from - * @param string $path_to - * @return bool - */ - private function _rename($path_from, $path_to) - { - $path1 = parse_url($path_from); - $path2 = parse_url($path_to); - unset($path1['path'], $path2['path']); - if ($path1 != $path2) { - return false; - } - - $path_from = $this->parse_path($path_from); - $path_to = parse_url($path_to); - if ($path_from === false) { - return false; - } - - $path_to = $path_to['path']; // the $component part of parse_url() was added in PHP 5.1.2 - // "It is an error if there already exists a file with the name specified by newpath." - // -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-6.5 - if (!$this->sftp->rename($path_from, $path_to)) { - if ($this->sftp->stat($path_to)) { - return $this->sftp->delete($path_to, true) && $this->sftp->rename($path_from, $path_to); - } - return false; - } - - return true; - } - - /** - * Open directory handle - * - * The only $options is "whether or not to enforce safe_mode (0x04)". Since safe mode was deprecated in 5.3 and - * removed in 5.4 I'm just going to ignore it. - * - * Also, nlist() is the best that this function is realistically going to be able to do. When an SFTP client - * sends a SSH_FXP_READDIR packet you don't generally get info on just one file but on multiple files. Quoting - * the SFTP specs: - * - * The SSH_FXP_NAME response has the following format: - * - * uint32 id - * uint32 count - * repeats count times: - * string filename - * string longname - * ATTRS attrs - * - * @param string $path - * @param int $options - * @return bool - */ - private function _dir_opendir($path, $options) - { - $path = $this->parse_path($path); - if ($path === false) { - return false; - } - $this->pos = 0; - $this->entries = $this->sftp->nlist($path); - return $this->entries !== false; - } - - /** - * Read entry from directory handle - * - * @return mixed - */ - private function _dir_readdir() - { - if (isset($this->entries[$this->pos])) { - return $this->entries[$this->pos++]; - } - return false; - } - - /** - * Rewind directory handle - * - * @return bool - */ - private function _dir_rewinddir() - { - $this->pos = 0; - return true; - } - - /** - * Close directory handle - * - * @return bool - */ - private function _dir_closedir() - { - return true; - } - - /** - * Create a directory - * - * Only valid $options is STREAM_MKDIR_RECURSIVE - * - * @param string $path - * @param int $mode - * @param int $options - * @return bool - */ - private function _mkdir($path, $mode, $options) - { - $path = $this->parse_path($path); - if ($path === false) { - return false; - } - - return $this->sftp->mkdir($path, $mode, $options & STREAM_MKDIR_RECURSIVE); - } - - /** - * Removes a directory - * - * Only valid $options is STREAM_MKDIR_RECURSIVE per , however, - * does not have a $recursive parameter as mkdir() does so I don't know how - * STREAM_MKDIR_RECURSIVE is supposed to be set. Also, when I try it out with rmdir() I get 8 as - * $options. What does 8 correspond to? - * - * @param string $path - * @param int $options - * @return bool - */ - private function _rmdir($path, $options) - { - $path = $this->parse_path($path); - if ($path === false) { - return false; - } - - return $this->sftp->rmdir($path); - } - - /** - * Flushes the output - * - * See . Always returns true because \phpseclib3\Net\SFTP doesn't cache stuff before writing - * - * @return bool - */ - private function _stream_flush() - { - return true; - } - - /** - * Retrieve information about a file resource - * - * @return mixed - */ - private function _stream_stat() - { - $results = $this->sftp->stat($this->path); - if ($results === false) { - return false; - } - return $results; - } - - /** - * Delete a file - * - * @param string $path - * @return bool - */ - private function _unlink($path) - { - $path = $this->parse_path($path); - if ($path === false) { - return false; - } - - return $this->sftp->delete($path, false); - } - - /** - * Retrieve information about a file - * - * Ignores the STREAM_URL_STAT_QUIET flag because the entirety of \phpseclib3\Net\SFTP\Stream is quiet by default - * might be worthwhile to reconstruct bits 12-16 (ie. the file type) if mode doesn't have them but we'll - * cross that bridge when and if it's reached - * - * @param string $path - * @param int $flags - * @return mixed - */ - private function _url_stat($path, $flags) - { - $path = $this->parse_path($path); - if ($path === false) { - return false; - } - - $results = $flags & STREAM_URL_STAT_LINK ? $this->sftp->lstat($path) : $this->sftp->stat($path); - if ($results === false) { - return false; - } - - return $results; - } - - /** - * Truncate stream - * - * @param int $new_size - * @return bool - */ - private function _stream_truncate($new_size) - { - if (!$this->sftp->truncate($this->path, $new_size)) { - return false; - } - - $this->eof = false; - $this->size = $new_size; - - return true; - } - - /** - * Change stream options - * - * STREAM_OPTION_WRITE_BUFFER isn't supported for the same reason stream_flush isn't. - * The other two aren't supported because of limitations in \phpseclib3\Net\SFTP. - * - * @param int $option - * @param int $arg1 - * @param int $arg2 - * @return bool - */ - private function _stream_set_option($option, $arg1, $arg2) - { - return false; - } - - /** - * Close an resource - * - */ - private function _stream_close() - { - } - - /** - * __call Magic Method - * - * When you're utilizing an SFTP stream you're not calling the methods in this class directly - PHP is calling them for you. - * Which kinda begs the question... what methods is PHP calling and what parameters is it passing to them? This function - * lets you figure that out. - * - * If NET_SFTP_STREAM_LOGGING is defined all calls will be output on the screen and then (regardless of whether or not - * NET_SFTP_STREAM_LOGGING is enabled) the parameters will be passed through to the appropriate method. - * - * @param string $name - * @param array $arguments - * @return mixed - */ - public function __call($name, array $arguments) - { - if (defined('NET_SFTP_STREAM_LOGGING')) { - echo $name . '('; - $last = count($arguments) - 1; - foreach ($arguments as $i => $argument) { - var_export($argument); - if ($i != $last) { - echo ','; - } - } - echo ")\r\n"; - } - $name = '_' . $name; - if (!method_exists($this, $name)) { - return false; - } - return $this->$name(...$arguments); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.php deleted file mode 100644 index 9a0133fd..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.php +++ /dev/null @@ -1,5166 +0,0 @@ - - * login('username', 'password')) { - * exit('Login Failed'); - * } - * - * echo $ssh->exec('pwd'); - * echo $ssh->exec('ls -la'); - * ?> - * - * - * - * login('username', $key)) { - * exit('Login Failed'); - * } - * - * echo $ssh->read('username@username:~$'); - * $ssh->write("ls -la\n"); - * echo $ssh->read('username@username:~$'); - * ?> - * - * - * @author Jim Wigginton - * @copyright 2007 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\Net; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\Blowfish; -use phpseclib3\Crypt\ChaCha20; -use phpseclib3\Crypt\Common\AsymmetricKey; -use phpseclib3\Crypt\Common\PrivateKey; -use phpseclib3\Crypt\Common\PublicKey; -use phpseclib3\Crypt\Common\SymmetricKey; -use phpseclib3\Crypt\DH; -use phpseclib3\Crypt\DSA; -use phpseclib3\Crypt\EC; -use phpseclib3\Crypt\Hash; -use phpseclib3\Crypt\Random; -use phpseclib3\Crypt\RC4; -use phpseclib3\Crypt\Rijndael; -use phpseclib3\Crypt\RSA; -use phpseclib3\Crypt\TripleDES; // Used to do Diffie-Hellman key exchange and DSA/RSA signature verification. -use phpseclib3\Crypt\Twofish; -use phpseclib3\Exception\ConnectionClosedException; -use phpseclib3\Exception\InsufficientSetupException; -use phpseclib3\Exception\NoSupportedAlgorithmsException; -use phpseclib3\Exception\UnableToConnectException; -use phpseclib3\Exception\UnsupportedAlgorithmException; -use phpseclib3\Exception\UnsupportedCurveException; -use phpseclib3\Math\BigInteger; -use phpseclib3\System\SSH\Agent; - -/** - * Pure-PHP implementation of SSHv2. - * - * @author Jim Wigginton - */ -class SSH2 -{ - /**#@+ - * Compression Types - * - */ - /** - * No compression - */ - const NET_SSH2_COMPRESSION_NONE = 1; - /** - * zlib compression - */ - const NET_SSH2_COMPRESSION_ZLIB = 2; - /** - * zlib@openssh.com - */ - const NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH = 3; - /**#@-*/ - - // Execution Bitmap Masks - const MASK_CONSTRUCTOR = 0x00000001; - const MASK_CONNECTED = 0x00000002; - const MASK_LOGIN_REQ = 0x00000004; - const MASK_LOGIN = 0x00000008; - const MASK_SHELL = 0x00000010; - const MASK_WINDOW_ADJUST = 0x00000020; - - /* - * Channel constants - * - * RFC4254 refers not to client and server channels but rather to sender and recipient channels. we don't refer - * to them in that way because RFC4254 toggles the meaning. the client sends a SSH_MSG_CHANNEL_OPEN message with - * a sender channel and the server sends a SSH_MSG_CHANNEL_OPEN_CONFIRMATION in response, with a sender and a - * recipient channel. at first glance, you might conclude that SSH_MSG_CHANNEL_OPEN_CONFIRMATION's sender channel - * would be the same thing as SSH_MSG_CHANNEL_OPEN's sender channel, but it's not, per this snippet: - * The 'recipient channel' is the channel number given in the original - * open request, and 'sender channel' is the channel number allocated by - * the other side. - * - * @see \phpseclib3\Net\SSH2::send_channel_packet() - * @see \phpseclib3\Net\SSH2::get_channel_packet() - */ - const CHANNEL_EXEC = 1; // PuTTy uses 0x100 - const CHANNEL_SHELL = 2; - const CHANNEL_SUBSYSTEM = 3; - const CHANNEL_AGENT_FORWARD = 4; - const CHANNEL_KEEP_ALIVE = 5; - - /** - * Returns the message numbers - * - * @see \phpseclib3\Net\SSH2::getLog() - */ - const LOG_SIMPLE = 1; - /** - * Returns the message content - * - * @see \phpseclib3\Net\SSH2::getLog() - */ - const LOG_COMPLEX = 2; - /** - * Outputs the content real-time - */ - const LOG_REALTIME = 3; - /** - * Dumps the content real-time to a file - */ - const LOG_REALTIME_FILE = 4; - /** - * Outputs the message numbers real-time - */ - const LOG_SIMPLE_REALTIME = 5; - /** - * Make sure that the log never gets larger than this - * - * @see \phpseclib3\Net\SSH2::getLog() - */ - const LOG_MAX_SIZE = 1048576; // 1024 * 1024 - - /** - * Returns when a string matching $expect exactly is found - * - * @see \phpseclib3\Net\SSH2::read() - */ - const READ_SIMPLE = 1; - /** - * Returns when a string matching the regular expression $expect is found - * - * @see \phpseclib3\Net\SSH2::read() - */ - const READ_REGEX = 2; - /** - * Returns whenever a data packet is received. - * - * Some data packets may only contain a single character so it may be necessary - * to call read() multiple times when using this option - * - * @see \phpseclib3\Net\SSH2::read() - */ - const READ_NEXT = 3; - - /** - * The SSH identifier - * - * @var string - */ - private $identifier; - - /** - * The Socket Object - * - * @var resource|closed-resource|null - */ - public $fsock; - - /** - * Execution Bitmap - * - * The bits that are set represent functions that have been called already. This is used to determine - * if a requisite function has been successfully executed. If not, an error should be thrown. - * - * @var int - */ - protected $bitmap = 0; - - /** - * Error information - * - * @see self::getErrors() - * @see self::getLastError() - * @var array - */ - private $errors = []; - - /** - * Server Identifier - * - * @see self::getServerIdentification() - * @var string|false - */ - protected $server_identifier = false; - - /** - * Key Exchange Algorithms - * - * @see self::getKexAlgorithims() - * @var array|false - */ - private $kex_algorithms = false; - - /** - * Key Exchange Algorithm - * - * @see self::getMethodsNegotiated() - * @var string|false - */ - private $kex_algorithm = false; - - /** - * Minimum Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods - * - * @see self::_key_exchange() - * @var int - */ - private $kex_dh_group_size_min = 1536; - - /** - * Preferred Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods - * - * @see self::_key_exchange() - * @var int - */ - private $kex_dh_group_size_preferred = 2048; - - /** - * Maximum Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods - * - * @see self::_key_exchange() - * @var int - */ - private $kex_dh_group_size_max = 4096; - - /** - * Server Host Key Algorithms - * - * @see self::getServerHostKeyAlgorithms() - * @var array|false - */ - private $server_host_key_algorithms = false; - - /** - * Supported Private Key Algorithms - * - * In theory this should be the same as the Server Host Key Algorithms but, in practice, - * some servers (eg. Azure) will support rsa-sha2-512 as a server host key algorithm but - * not a private key algorithm - * - * @see self::privatekey_login() - * @var array|false - */ - private $supported_private_key_algorithms = false; - - /** - * Encryption Algorithms: Client to Server - * - * @see self::getEncryptionAlgorithmsClient2Server() - * @var array|false - */ - private $encryption_algorithms_client_to_server = false; - - /** - * Encryption Algorithms: Server to Client - * - * @see self::getEncryptionAlgorithmsServer2Client() - * @var array|false - */ - private $encryption_algorithms_server_to_client = false; - - /** - * MAC Algorithms: Client to Server - * - * @see self::getMACAlgorithmsClient2Server() - * @var array|false - */ - private $mac_algorithms_client_to_server = false; - - /** - * MAC Algorithms: Server to Client - * - * @see self::getMACAlgorithmsServer2Client() - * @var array|false - */ - private $mac_algorithms_server_to_client = false; - - /** - * Compression Algorithms: Client to Server - * - * @see self::getCompressionAlgorithmsClient2Server() - * @var array|false - */ - private $compression_algorithms_client_to_server = false; - - /** - * Compression Algorithms: Server to Client - * - * @see self::getCompressionAlgorithmsServer2Client() - * @var array|false - */ - private $compression_algorithms_server_to_client = false; - - /** - * Languages: Server to Client - * - * @see self::getLanguagesServer2Client() - * @var array|false - */ - private $languages_server_to_client = false; - - /** - * Languages: Client to Server - * - * @see self::getLanguagesClient2Server() - * @var array|false - */ - private $languages_client_to_server = false; - - /** - * Preferred Algorithms - * - * @see self::setPreferredAlgorithms() - * @var array - */ - private $preferred = []; - - /** - * Block Size for Server to Client Encryption - * - * "Note that the length of the concatenation of 'packet_length', - * 'padding_length', 'payload', and 'random padding' MUST be a multiple - * of the cipher block size or 8, whichever is larger. This constraint - * MUST be enforced, even when using stream ciphers." - * - * -- http://tools.ietf.org/html/rfc4253#section-6 - * - * @see self::__construct() - * @see self::_send_binary_packet() - * @var int - */ - private $encrypt_block_size = 8; - - /** - * Block Size for Client to Server Encryption - * - * @see self::__construct() - * @see self::_get_binary_packet() - * @var int - */ - private $decrypt_block_size = 8; - - /** - * Server to Client Encryption Object - * - * @see self::_get_binary_packet() - * @var SymmetricKey|false - */ - private $decrypt = false; - - /** - * Decryption Algorithm Name - * - * @var string|null - */ - private $decryptName; - - /** - * Decryption Invocation Counter - * - * Used by GCM - * - * @var string|null - */ - private $decryptInvocationCounter; - - /** - * Fixed Part of Nonce - * - * Used by GCM - * - * @var string|null - */ - private $decryptFixedPart; - - /** - * Server to Client Length Encryption Object - * - * @see self::_get_binary_packet() - * @var object - */ - private $lengthDecrypt = false; - - /** - * Client to Server Encryption Object - * - * @see self::_send_binary_packet() - * @var SymmetricKey|false - */ - private $encrypt = false; - - /** - * Encryption Algorithm Name - * - * @var string|null - */ - private $encryptName; - - /** - * Encryption Invocation Counter - * - * Used by GCM - * - * @var string|null - */ - private $encryptInvocationCounter; - - /** - * Fixed Part of Nonce - * - * Used by GCM - * - * @var string|null - */ - private $encryptFixedPart; - - /** - * Client to Server Length Encryption Object - * - * @see self::_send_binary_packet() - * @var object - */ - private $lengthEncrypt = false; - - /** - * Client to Server HMAC Object - * - * @see self::_send_binary_packet() - * @var object - */ - private $hmac_create = false; - - /** - * Client to Server HMAC Name - * - * @var string|false - */ - private $hmac_create_name; - - /** - * Client to Server ETM - * - * @var int|false - */ - private $hmac_create_etm; - - /** - * Server to Client HMAC Object - * - * @see self::_get_binary_packet() - * @var object - */ - private $hmac_check = false; - - /** - * Server to Client HMAC Name - * - * @var string|false - */ - private $hmac_check_name; - - /** - * Server to Client ETM - * - * @var int|false - */ - private $hmac_check_etm; - - /** - * Size of server to client HMAC - * - * We need to know how big the HMAC will be for the server to client direction so that we know how many bytes to read. - * For the client to server side, the HMAC object will make the HMAC as long as it needs to be. All we need to do is - * append it. - * - * @see self::_get_binary_packet() - * @var int - */ - private $hmac_size = false; - - /** - * Server Public Host Key - * - * @see self::getServerPublicHostKey() - * @var string - */ - private $server_public_host_key; - - /** - * Session identifier - * - * "The exchange hash H from the first key exchange is additionally - * used as the session identifier, which is a unique identifier for - * this connection." - * - * -- http://tools.ietf.org/html/rfc4253#section-7.2 - * - * @see self::_key_exchange() - * @var string - */ - private $session_id = false; - - /** - * Exchange hash - * - * The current exchange hash - * - * @see self::_key_exchange() - * @var string - */ - private $exchange_hash = false; - - /** - * Message Numbers - * - * @see self::__construct() - * @var array - * @access private - */ - private $message_numbers = []; - - /** - * Disconnection Message 'reason codes' defined in RFC4253 - * - * @see self::__construct() - * @var array - * @access private - */ - private $disconnect_reasons = []; - - /** - * SSH_MSG_CHANNEL_OPEN_FAILURE 'reason codes', defined in RFC4254 - * - * @see self::__construct() - * @var array - * @access private - */ - private $channel_open_failure_reasons = []; - - /** - * Terminal Modes - * - * @link http://tools.ietf.org/html/rfc4254#section-8 - * @see self::__construct() - * @var array - * @access private - */ - private $terminal_modes = []; - - /** - * SSH_MSG_CHANNEL_EXTENDED_DATA's data_type_codes - * - * @link http://tools.ietf.org/html/rfc4254#section-5.2 - * @see self::__construct() - * @var array - * @access private - */ - private $channel_extended_data_type_codes = []; - - /** - * Send Sequence Number - * - * See 'Section 6.4. Data Integrity' of rfc4253 for more info. - * - * @see self::_send_binary_packet() - * @var int - */ - private $send_seq_no = 0; - - /** - * Get Sequence Number - * - * See 'Section 6.4. Data Integrity' of rfc4253 for more info. - * - * @see self::_get_binary_packet() - * @var int - */ - private $get_seq_no = 0; - - /** - * Server Channels - * - * Maps client channels to server channels - * - * @see self::get_channel_packet() - * @see self::exec() - * @var array - */ - protected $server_channels = []; - - /** - * Channel Buffers - * - * If a client requests a packet from one channel but receives two packets from another those packets should - * be placed in a buffer - * - * @see self::get_channel_packet() - * @see self::exec() - * @var array - */ - private $channel_buffers = []; - - /** - * Channel Status - * - * Contains the type of the last sent message - * - * @see self::get_channel_packet() - * @var array - */ - protected $channel_status = []; - - /** - * Packet Size - * - * Maximum packet size indexed by channel - * - * @see self::send_channel_packet() - * @var array - */ - private $packet_size_client_to_server = []; - - /** - * Message Number Log - * - * @see self::getLog() - * @var array - */ - private $message_number_log = []; - - /** - * Message Log - * - * @see self::getLog() - * @var array - */ - private $message_log = []; - - /** - * The Window Size - * - * Bytes the other party can send before it must wait for the window to be adjusted (0x7FFFFFFF = 2GB) - * - * @var int - * @see self::send_channel_packet() - * @see self::exec() - */ - protected $window_size = 0x7FFFFFFF; - - /** - * What we resize the window to - * - * When PuTTY resizes the window it doesn't add an additional 0x7FFFFFFF bytes - it adds 0x40000000 bytes. - * Some SFTP clients (GoAnywhere) don't support adding 0x7FFFFFFF to the window size after the fact so - * we'll just do what PuTTY does - * - * @var int - * @see self::_send_channel_packet() - * @see self::exec() - */ - private $window_resize = 0x40000000; - - /** - * Window size, server to client - * - * Window size indexed by channel - * - * @see self::send_channel_packet() - * @var array - */ - protected $window_size_server_to_client = []; - - /** - * Window size, client to server - * - * Window size indexed by channel - * - * @see self::get_channel_packet() - * @var array - */ - private $window_size_client_to_server = []; - - /** - * Server signature - * - * Verified against $this->session_id - * - * @see self::getServerPublicHostKey() - * @var string - */ - private $signature = ''; - - /** - * Server signature format - * - * ssh-rsa or ssh-dss. - * - * @see self::getServerPublicHostKey() - * @var string - */ - private $signature_format = ''; - - /** - * Interactive Buffer - * - * @see self::read() - * @var string - */ - private $interactiveBuffer = ''; - - /** - * Current log size - * - * Should never exceed self::LOG_MAX_SIZE - * - * @see self::_send_binary_packet() - * @see self::_get_binary_packet() - * @var int - */ - private $log_size; - - /** - * Timeout - * - * @see self::setTimeout() - */ - protected $timeout; - - /** - * Current Timeout - * - * @see self::get_channel_packet() - */ - protected $curTimeout; - - /** - * Keep Alive Interval - * - * @see self::setKeepAlive() - */ - private $keepAlive; - - /** - * Real-time log file pointer - * - * @see self::_append_log() - * @var resource|closed-resource - */ - private $realtime_log_file; - - /** - * Real-time log file size - * - * @see self::_append_log() - * @var int - */ - private $realtime_log_size; - - /** - * Has the signature been validated? - * - * @see self::getServerPublicHostKey() - * @var bool - */ - private $signature_validated = false; - - /** - * Real-time log file wrap boolean - * - * @see self::_append_log() - * @var bool - */ - private $realtime_log_wrap; - - /** - * Flag to suppress stderr from output - * - * @see self::enableQuietMode() - */ - private $quiet_mode = false; - - /** - * Time of first network activity - * - * @var float - */ - private $last_packet; - - /** - * Exit status returned from ssh if any - * - * @var int - */ - private $exit_status; - - /** - * Flag to request a PTY when using exec() - * - * @var bool - * @see self::enablePTY() - */ - private $request_pty = false; - - /** - * Flag set while exec() is running when using enablePTY() - * - * @var bool - */ - private $in_request_pty_exec = false; - - /** - * Flag set after startSubsystem() is called - * - * @var bool - */ - private $in_subsystem; - - /** - * Contents of stdError - * - * @var string - */ - private $stdErrorLog; - - /** - * The Last Interactive Response - * - * @see self::_keyboard_interactive_process() - * @var string - */ - private $last_interactive_response = ''; - - /** - * Keyboard Interactive Request / Responses - * - * @see self::_keyboard_interactive_process() - * @var array - */ - private $keyboard_requests_responses = []; - - /** - * Banner Message - * - * Quoting from the RFC, "in some jurisdictions, sending a warning message before - * authentication may be relevant for getting legal protection." - * - * @see self::_filter() - * @see self::getBannerMessage() - * @var string - */ - private $banner_message = ''; - - /** - * Did read() timeout or return normally? - * - * @see self::isTimeout() - * @var bool - */ - private $is_timeout = false; - - /** - * Log Boundary - * - * @see self::_format_log() - * @var string - */ - private $log_boundary = ':'; - - /** - * Log Long Width - * - * @see self::_format_log() - * @var int - */ - private $log_long_width = 65; - - /** - * Log Short Width - * - * @see self::_format_log() - * @var int - */ - private $log_short_width = 16; - - /** - * Hostname - * - * @see self::__construct() - * @see self::_connect() - * @var string - */ - private $host; - - /** - * Port Number - * - * @see self::__construct() - * @see self::_connect() - * @var int - */ - private $port; - - /** - * Number of columns for terminal window size - * - * @see self::getWindowColumns() - * @see self::setWindowColumns() - * @see self::setWindowSize() - * @var int - */ - private $windowColumns = 80; - - /** - * Number of columns for terminal window size - * - * @see self::getWindowRows() - * @see self::setWindowRows() - * @see self::setWindowSize() - * @var int - */ - private $windowRows = 24; - - /** - * Crypto Engine - * - * @see self::setCryptoEngine() - * @see self::_key_exchange() - * @var int - */ - private static $crypto_engine = false; - - /** - * A System_SSH_Agent for use in the SSH2 Agent Forwarding scenario - * - * @var Agent - */ - private $agent; - - /** - * Connection storage to replicates ssh2 extension functionality: - * {@link http://php.net/manual/en/wrappers.ssh2.php#refsect1-wrappers.ssh2-examples} - * - * @var array> - */ - private static $connections; - - /** - * Send the identification string first? - * - * @var bool - */ - private $send_id_string_first = true; - - /** - * Send the key exchange initiation packet first? - * - * @var bool - */ - private $send_kex_first = true; - - /** - * Some versions of OpenSSH incorrectly calculate the key size - * - * @var bool - */ - private $bad_key_size_fix = false; - - /** - * Should we try to re-connect to re-establish keys? - * - * @var bool - */ - private $retry_connect = false; - - /** - * Binary Packet Buffer - * - * @var string|false - */ - private $binary_packet_buffer = false; - - /** - * Preferred Signature Format - * - * @var string|false - */ - protected $preferred_signature_format = false; - - /** - * Authentication Credentials - * - * @var array - */ - protected $auth = []; - - /** - * Terminal - * - * @var string - */ - private $term = 'vt100'; - - /** - * The authentication methods that may productively continue authentication. - * - * @see https://tools.ietf.org/html/rfc4252#section-5.1 - * @var array|null - */ - private $auth_methods_to_continue = null; - - /** - * Compression method - * - * @var int - */ - private $compress = self::NET_SSH2_COMPRESSION_NONE; - - /** - * Decompression method - * - * @var int - */ - private $decompress = self::NET_SSH2_COMPRESSION_NONE; - - /** - * Compression context - * - * @var resource|false|null - */ - private $compress_context; - - /** - * Decompression context - * - * @var resource|object - */ - private $decompress_context; - - /** - * Regenerate Compression Context - * - * @var bool - */ - private $regenerate_compression_context = false; - - /** - * Regenerate Decompression Context - * - * @var bool - */ - private $regenerate_decompression_context = false; - - /** - * Smart multi-factor authentication flag - * - * @var bool - */ - private $smartMFA = true; - - /** - * Default Constructor. - * - * $host can either be a string, representing the host, or a stream resource. - * - * @param mixed $host - * @param int $port - * @param int $timeout - * @see self::login() - */ - public function __construct($host, $port = 22, $timeout = 10) - { - $this->message_numbers = [ - 1 => 'NET_SSH2_MSG_DISCONNECT', - 2 => 'NET_SSH2_MSG_IGNORE', - 3 => 'NET_SSH2_MSG_UNIMPLEMENTED', - 4 => 'NET_SSH2_MSG_DEBUG', - 5 => 'NET_SSH2_MSG_SERVICE_REQUEST', - 6 => 'NET_SSH2_MSG_SERVICE_ACCEPT', - 20 => 'NET_SSH2_MSG_KEXINIT', - 21 => 'NET_SSH2_MSG_NEWKEYS', - 30 => 'NET_SSH2_MSG_KEXDH_INIT', - 31 => 'NET_SSH2_MSG_KEXDH_REPLY', - 50 => 'NET_SSH2_MSG_USERAUTH_REQUEST', - 51 => 'NET_SSH2_MSG_USERAUTH_FAILURE', - 52 => 'NET_SSH2_MSG_USERAUTH_SUCCESS', - 53 => 'NET_SSH2_MSG_USERAUTH_BANNER', - - 80 => 'NET_SSH2_MSG_GLOBAL_REQUEST', - 81 => 'NET_SSH2_MSG_REQUEST_SUCCESS', - 82 => 'NET_SSH2_MSG_REQUEST_FAILURE', - 90 => 'NET_SSH2_MSG_CHANNEL_OPEN', - 91 => 'NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION', - 92 => 'NET_SSH2_MSG_CHANNEL_OPEN_FAILURE', - 93 => 'NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST', - 94 => 'NET_SSH2_MSG_CHANNEL_DATA', - 95 => 'NET_SSH2_MSG_CHANNEL_EXTENDED_DATA', - 96 => 'NET_SSH2_MSG_CHANNEL_EOF', - 97 => 'NET_SSH2_MSG_CHANNEL_CLOSE', - 98 => 'NET_SSH2_MSG_CHANNEL_REQUEST', - 99 => 'NET_SSH2_MSG_CHANNEL_SUCCESS', - 100 => 'NET_SSH2_MSG_CHANNEL_FAILURE' - ]; - $this->disconnect_reasons = [ - 1 => 'NET_SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT', - 2 => 'NET_SSH2_DISCONNECT_PROTOCOL_ERROR', - 3 => 'NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED', - 4 => 'NET_SSH2_DISCONNECT_RESERVED', - 5 => 'NET_SSH2_DISCONNECT_MAC_ERROR', - 6 => 'NET_SSH2_DISCONNECT_COMPRESSION_ERROR', - 7 => 'NET_SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE', - 8 => 'NET_SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED', - 9 => 'NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE', - 10 => 'NET_SSH2_DISCONNECT_CONNECTION_LOST', - 11 => 'NET_SSH2_DISCONNECT_BY_APPLICATION', - 12 => 'NET_SSH2_DISCONNECT_TOO_MANY_CONNECTIONS', - 13 => 'NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER', - 14 => 'NET_SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE', - 15 => 'NET_SSH2_DISCONNECT_ILLEGAL_USER_NAME' - ]; - $this->channel_open_failure_reasons = [ - 1 => 'NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED' - ]; - $this->terminal_modes = [ - 0 => 'NET_SSH2_TTY_OP_END' - ]; - $this->channel_extended_data_type_codes = [ - 1 => 'NET_SSH2_EXTENDED_DATA_STDERR' - ]; - - $this->define_array( - $this->message_numbers, - $this->disconnect_reasons, - $this->channel_open_failure_reasons, - $this->terminal_modes, - $this->channel_extended_data_type_codes, - [60 => 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ'], - [60 => 'NET_SSH2_MSG_USERAUTH_PK_OK'], - [60 => 'NET_SSH2_MSG_USERAUTH_INFO_REQUEST', - 61 => 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE'], - // RFC 4419 - diffie-hellman-group-exchange-sha{1,256} - [30 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST_OLD', - 31 => 'NET_SSH2_MSG_KEXDH_GEX_GROUP', - 32 => 'NET_SSH2_MSG_KEXDH_GEX_INIT', - 33 => 'NET_SSH2_MSG_KEXDH_GEX_REPLY', - 34 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST'], - // RFC 5656 - Elliptic Curves (for curve25519-sha256@libssh.org) - [30 => 'NET_SSH2_MSG_KEX_ECDH_INIT', - 31 => 'NET_SSH2_MSG_KEX_ECDH_REPLY'] - ); - - /** - * Typehint is required due to a bug in Psalm: https://github.com/vimeo/psalm/issues/7508 - * @var \WeakReference|SSH2 - */ - self::$connections[$this->getResourceId()] = class_exists('WeakReference') - ? \WeakReference::create($this) - : $this; - - if (is_resource($host)) { - $this->fsock = $host; - return; - } - - if (Strings::is_stringable($host)) { - $this->host = $host; - $this->port = $port; - $this->timeout = $timeout; - } - } - - /** - * Set Crypto Engine Mode - * - * Possible $engine values: - * OpenSSL, mcrypt, Eval, PHP - * - * @param int $engine - */ - public static function setCryptoEngine($engine) - { - self::$crypto_engine = $engine; - } - - /** - * Send Identification String First - * - * https://tools.ietf.org/html/rfc4253#section-4.2 says "when the connection has been established, - * both sides MUST send an identification string". It does not say which side sends it first. In - * theory it shouldn't matter but it is a fact of life that some SSH servers are simply buggy - * - */ - public function sendIdentificationStringFirst() - { - $this->send_id_string_first = true; - } - - /** - * Send Identification String Last - * - * https://tools.ietf.org/html/rfc4253#section-4.2 says "when the connection has been established, - * both sides MUST send an identification string". It does not say which side sends it first. In - * theory it shouldn't matter but it is a fact of life that some SSH servers are simply buggy - * - */ - public function sendIdentificationStringLast() - { - $this->send_id_string_first = false; - } - - /** - * Send SSH_MSG_KEXINIT First - * - * https://tools.ietf.org/html/rfc4253#section-7.1 says "key exchange begins by each sending - * sending the [SSH_MSG_KEXINIT] packet". It does not say which side sends it first. In theory - * it shouldn't matter but it is a fact of life that some SSH servers are simply buggy - * - */ - public function sendKEXINITFirst() - { - $this->send_kex_first = true; - } - - /** - * Send SSH_MSG_KEXINIT Last - * - * https://tools.ietf.org/html/rfc4253#section-7.1 says "key exchange begins by each sending - * sending the [SSH_MSG_KEXINIT] packet". It does not say which side sends it first. In theory - * it shouldn't matter but it is a fact of life that some SSH servers are simply buggy - * - */ - public function sendKEXINITLast() - { - $this->send_kex_first = false; - } - - /** - * Connect to an SSHv2 server - * - * @throws \UnexpectedValueException on receipt of unexpected packets - * @throws \RuntimeException on other errors - */ - private function connect() - { - if ($this->bitmap & self::MASK_CONSTRUCTOR) { - return; - } - - $this->bitmap |= self::MASK_CONSTRUCTOR; - - $this->curTimeout = $this->timeout; - - $this->last_packet = microtime(true); - - if (!is_resource($this->fsock)) { - $start = microtime(true); - // with stream_select a timeout of 0 means that no timeout takes place; - // with fsockopen a timeout of 0 means that you instantly timeout - // to resolve this incompatibility a timeout of 100,000 will be used for fsockopen if timeout is 0 - $this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->curTimeout == 0 ? 100000 : $this->curTimeout); - if (!$this->fsock) { - $host = $this->host . ':' . $this->port; - throw new UnableToConnectException(rtrim("Cannot connect to $host. Error $errno. $errstr")); - } - $elapsed = microtime(true) - $start; - - if ($this->curTimeout) { - $this->curTimeout -= $elapsed; - if ($this->curTimeout < 0) { - throw new \RuntimeException('Connection timed out whilst attempting to open socket connection'); - } - } - } - - $this->identifier = $this->generate_identifier(); - - if ($this->send_id_string_first) { - fputs($this->fsock, $this->identifier . "\r\n"); - } - - /* According to the SSH2 specs, - - "The server MAY send other lines of data before sending the version - string. Each line SHOULD be terminated by a Carriage Return and Line - Feed. Such lines MUST NOT begin with "SSH-", and SHOULD be encoded - in ISO-10646 UTF-8 [RFC3629] (language is not specified). Clients - MUST be able to process such lines." */ - $data = ''; - while (!feof($this->fsock) && !preg_match('#(.*)^(SSH-(\d\.\d+).*)#ms', $data, $matches)) { - $line = ''; - while (true) { - if ($this->curTimeout) { - if ($this->curTimeout < 0) { - throw new \RuntimeException('Connection timed out whilst receiving server identification string'); - } - $read = [$this->fsock]; - $write = $except = null; - $start = microtime(true); - $sec = (int) floor($this->curTimeout); - $usec = (int) (1000000 * ($this->curTimeout - $sec)); - if (@stream_select($read, $write, $except, $sec, $usec) === false) { - throw new \RuntimeException('Connection timed out whilst receiving server identification string'); - } - $elapsed = microtime(true) - $start; - $this->curTimeout -= $elapsed; - } - - $temp = stream_get_line($this->fsock, 255, "\n"); - if ($temp === false) { - throw new \RuntimeException('Error reading from socket'); - } - if (strlen($temp) == 255) { - continue; - } - - $line .= "$temp\n"; - - // quoting RFC4253, "Implementers who wish to maintain - // compatibility with older, undocumented versions of this protocol may - // want to process the identification string without expecting the - // presence of the carriage return character for reasons described in - // Section 5 of this document." - - //if (substr($line, -2) == "\r\n") { - // break; - //} - - break; - } - - $data .= $line; - } - - if (feof($this->fsock)) { - $this->bitmap = 0; - throw new ConnectionClosedException('Connection closed by server'); - } - - $extra = $matches[1]; - - if (defined('NET_SSH2_LOGGING')) { - $this->append_log('<-', $matches[0]); - $this->append_log('->', $this->identifier . "\r\n"); - } - - $this->server_identifier = trim($temp, "\r\n"); - if (strlen($extra)) { - $this->errors[] = $data; - } - - if (version_compare($matches[3], '1.99', '<')) { - $this->bitmap = 0; - throw new UnableToConnectException("Cannot connect to SSH $matches[3] servers"); - } - - if (!$this->send_id_string_first) { - fputs($this->fsock, $this->identifier . "\r\n"); - } - - if (!$this->send_kex_first) { - $response = $this->get_binary_packet(); - - if (is_bool($response) || !strlen($response) || ord($response[0]) != NET_SSH2_MSG_KEXINIT) { - $this->bitmap = 0; - throw new \UnexpectedValueException('Expected SSH_MSG_KEXINIT'); - } - - $this->key_exchange($response); - } - - if ($this->send_kex_first) { - $this->key_exchange(); - } - - $this->bitmap |= self::MASK_CONNECTED; - - return true; - } - - /** - * Generates the SSH identifier - * - * You should overwrite this method in your own class if you want to use another identifier - * - * @return string - */ - private function generate_identifier() - { - $identifier = 'SSH-2.0-phpseclib_3.0'; - - $ext = []; - if (extension_loaded('sodium')) { - $ext[] = 'libsodium'; - } - - if (extension_loaded('openssl')) { - $ext[] = 'openssl'; - } elseif (extension_loaded('mcrypt')) { - $ext[] = 'mcrypt'; - } - - if (extension_loaded('gmp')) { - $ext[] = 'gmp'; - } elseif (extension_loaded('bcmath')) { - $ext[] = 'bcmath'; - } - - if (!empty($ext)) { - $identifier .= ' (' . implode(', ', $ext) . ')'; - } - - return $identifier; - } - - /** - * Key Exchange - * - * @return bool - * @param string|bool $kexinit_payload_server optional - * @throws \UnexpectedValueException on receipt of unexpected packets - * @throws \RuntimeException on other errors - * @throws \phpseclib3\Exception\NoSupportedAlgorithmsException when none of the algorithms phpseclib has loaded are compatible - */ - private function key_exchange($kexinit_payload_server = false) - { - $preferred = $this->preferred; - $send_kex = true; - - $kex_algorithms = isset($preferred['kex']) ? - $preferred['kex'] : - SSH2::getSupportedKEXAlgorithms(); - $server_host_key_algorithms = isset($preferred['hostkey']) ? - $preferred['hostkey'] : - SSH2::getSupportedHostKeyAlgorithms(); - $s2c_encryption_algorithms = isset($preferred['server_to_client']['crypt']) ? - $preferred['server_to_client']['crypt'] : - SSH2::getSupportedEncryptionAlgorithms(); - $c2s_encryption_algorithms = isset($preferred['client_to_server']['crypt']) ? - $preferred['client_to_server']['crypt'] : - SSH2::getSupportedEncryptionAlgorithms(); - $s2c_mac_algorithms = isset($preferred['server_to_client']['mac']) ? - $preferred['server_to_client']['mac'] : - SSH2::getSupportedMACAlgorithms(); - $c2s_mac_algorithms = isset($preferred['client_to_server']['mac']) ? - $preferred['client_to_server']['mac'] : - SSH2::getSupportedMACAlgorithms(); - $s2c_compression_algorithms = isset($preferred['server_to_client']['comp']) ? - $preferred['server_to_client']['comp'] : - SSH2::getSupportedCompressionAlgorithms(); - $c2s_compression_algorithms = isset($preferred['client_to_server']['comp']) ? - $preferred['client_to_server']['comp'] : - SSH2::getSupportedCompressionAlgorithms(); - - // some SSH servers have buggy implementations of some of the above algorithms - switch (true) { - case $this->server_identifier == 'SSH-2.0-SSHD': - case substr($this->server_identifier, 0, 13) == 'SSH-2.0-DLINK': - if (!isset($preferred['server_to_client']['mac'])) { - $s2c_mac_algorithms = array_values(array_diff( - $s2c_mac_algorithms, - ['hmac-sha1-96', 'hmac-md5-96'] - )); - } - if (!isset($preferred['client_to_server']['mac'])) { - $c2s_mac_algorithms = array_values(array_diff( - $c2s_mac_algorithms, - ['hmac-sha1-96', 'hmac-md5-96'] - )); - } - } - - $client_cookie = Random::string(16); - - $kexinit_payload_client = pack('Ca*', NET_SSH2_MSG_KEXINIT, $client_cookie); - $kexinit_payload_client .= Strings::packSSH2( - 'L10bN', - $kex_algorithms, - $server_host_key_algorithms, - $c2s_encryption_algorithms, - $s2c_encryption_algorithms, - $c2s_mac_algorithms, - $s2c_mac_algorithms, - $c2s_compression_algorithms, - $s2c_compression_algorithms, - [], // language, client to server - [], // language, server to client - false, // first_kex_packet_follows - 0 // reserved for future extension - ); - - if ($kexinit_payload_server === false) { - $this->send_binary_packet($kexinit_payload_client); - - $kexinit_payload_server = $this->get_binary_packet(); - - if ( - is_bool($kexinit_payload_server) - || !strlen($kexinit_payload_server) - || ord($kexinit_payload_server[0]) != NET_SSH2_MSG_KEXINIT - ) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_PROTOCOL_ERROR); - throw new \UnexpectedValueException('Expected SSH_MSG_KEXINIT'); - } - - $send_kex = false; - } - - $response = $kexinit_payload_server; - Strings::shift($response, 1); // skip past the message number (it should be SSH_MSG_KEXINIT) - $server_cookie = Strings::shift($response, 16); - - list( - $this->kex_algorithms, - $this->server_host_key_algorithms, - $this->encryption_algorithms_client_to_server, - $this->encryption_algorithms_server_to_client, - $this->mac_algorithms_client_to_server, - $this->mac_algorithms_server_to_client, - $this->compression_algorithms_client_to_server, - $this->compression_algorithms_server_to_client, - $this->languages_client_to_server, - $this->languages_server_to_client, - $first_kex_packet_follows - ) = Strings::unpackSSH2('L10C', $response); - - $this->supported_private_key_algorithms = $this->server_host_key_algorithms; - - if ($send_kex) { - $this->send_binary_packet($kexinit_payload_client); - } - - // we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange - - // we don't initialize any crypto-objects, yet - we do that, later. for now, we need the lengths to make the - // diffie-hellman key exchange as fast as possible - $decrypt = self::array_intersect_first($s2c_encryption_algorithms, $this->encryption_algorithms_server_to_client); - $decryptKeyLength = $this->encryption_algorithm_to_key_size($decrypt); - if ($decryptKeyLength === null) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible server to client encryption algorithms found'); - } - - $encrypt = self::array_intersect_first($c2s_encryption_algorithms, $this->encryption_algorithms_client_to_server); - $encryptKeyLength = $this->encryption_algorithm_to_key_size($encrypt); - if ($encryptKeyLength === null) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible client to server encryption algorithms found'); - } - - // through diffie-hellman key exchange a symmetric key is obtained - $this->kex_algorithm = self::array_intersect_first($kex_algorithms, $this->kex_algorithms); - if ($this->kex_algorithm === false) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible key exchange algorithms found'); - } - - $server_host_key_algorithm = self::array_intersect_first($server_host_key_algorithms, $this->server_host_key_algorithms); - if ($server_host_key_algorithm === false) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible server host key algorithms found'); - } - - $mac_algorithm_out = self::array_intersect_first($c2s_mac_algorithms, $this->mac_algorithms_client_to_server); - if ($mac_algorithm_out === false) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible client to server message authentication algorithms found'); - } - - $mac_algorithm_in = self::array_intersect_first($s2c_mac_algorithms, $this->mac_algorithms_server_to_client); - if ($mac_algorithm_in === false) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible server to client message authentication algorithms found'); - } - - $compression_map = [ - 'none' => self::NET_SSH2_COMPRESSION_NONE, - 'zlib' => self::NET_SSH2_COMPRESSION_ZLIB, - 'zlib@openssh.com' => self::NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH - ]; - - $compression_algorithm_in = self::array_intersect_first($s2c_compression_algorithms, $this->compression_algorithms_server_to_client); - if ($compression_algorithm_in === false) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible server to client compression algorithms found'); - } - $this->decompress = $compression_map[$compression_algorithm_in]; - - $compression_algorithm_out = self::array_intersect_first($c2s_compression_algorithms, $this->compression_algorithms_client_to_server); - if ($compression_algorithm_out === false) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible client to server compression algorithms found'); - } - $this->compress = $compression_map[$compression_algorithm_out]; - - switch ($this->kex_algorithm) { - case 'diffie-hellman-group15-sha512': - case 'diffie-hellman-group16-sha512': - case 'diffie-hellman-group17-sha512': - case 'diffie-hellman-group18-sha512': - case 'ecdh-sha2-nistp521': - $kexHash = new Hash('sha512'); - break; - case 'ecdh-sha2-nistp384': - $kexHash = new Hash('sha384'); - break; - case 'diffie-hellman-group-exchange-sha256': - case 'diffie-hellman-group14-sha256': - case 'ecdh-sha2-nistp256': - case 'curve25519-sha256@libssh.org': - case 'curve25519-sha256': - $kexHash = new Hash('sha256'); - break; - default: - $kexHash = new Hash('sha1'); - } - - // Only relevant in diffie-hellman-group-exchange-sha{1,256}, otherwise empty. - - $exchange_hash_rfc4419 = ''; - - if (strpos($this->kex_algorithm, 'curve25519-sha256') === 0 || strpos($this->kex_algorithm, 'ecdh-sha2-nistp') === 0) { - $curve = strpos($this->kex_algorithm, 'curve25519-sha256') === 0 ? - 'Curve25519' : - substr($this->kex_algorithm, 10); - $ourPrivate = EC::createKey($curve); - $ourPublicBytes = $ourPrivate->getPublicKey()->getEncodedCoordinates(); - $clientKexInitMessage = 'NET_SSH2_MSG_KEX_ECDH_INIT'; - $serverKexReplyMessage = 'NET_SSH2_MSG_KEX_ECDH_REPLY'; - } else { - if (strpos($this->kex_algorithm, 'diffie-hellman-group-exchange') === 0) { - $dh_group_sizes_packed = pack( - 'NNN', - $this->kex_dh_group_size_min, - $this->kex_dh_group_size_preferred, - $this->kex_dh_group_size_max - ); - $packet = pack( - 'Ca*', - NET_SSH2_MSG_KEXDH_GEX_REQUEST, - $dh_group_sizes_packed - ); - $this->send_binary_packet($packet); - $this->updateLogHistory('UNKNOWN (34)', 'NET_SSH2_MSG_KEXDH_GEX_REQUEST'); - - $response = $this->get_binary_packet(); - - list($type, $primeBytes, $gBytes) = Strings::unpackSSH2('Css', $response); - if ($type != NET_SSH2_MSG_KEXDH_GEX_GROUP) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_PROTOCOL_ERROR); - throw new \UnexpectedValueException('Expected SSH_MSG_KEX_DH_GEX_GROUP'); - } - $this->updateLogHistory('NET_SSH2_MSG_KEXDH_REPLY', 'NET_SSH2_MSG_KEXDH_GEX_GROUP'); - $prime = new BigInteger($primeBytes, -256); - $g = new BigInteger($gBytes, -256); - - $exchange_hash_rfc4419 = $dh_group_sizes_packed . Strings::packSSH2( - 'ss', - $primeBytes, - $gBytes - ); - - $params = DH::createParameters($prime, $g); - $clientKexInitMessage = 'NET_SSH2_MSG_KEXDH_GEX_INIT'; - $serverKexReplyMessage = 'NET_SSH2_MSG_KEXDH_GEX_REPLY'; - } else { - $params = DH::createParameters($this->kex_algorithm); - $clientKexInitMessage = 'NET_SSH2_MSG_KEXDH_INIT'; - $serverKexReplyMessage = 'NET_SSH2_MSG_KEXDH_REPLY'; - } - - $keyLength = min($kexHash->getLengthInBytes(), max($encryptKeyLength, $decryptKeyLength)); - - $ourPrivate = DH::createKey($params, 16 * $keyLength); // 2 * 8 * $keyLength - $ourPublic = $ourPrivate->getPublicKey()->toBigInteger(); - $ourPublicBytes = $ourPublic->toBytes(true); - } - - $data = pack('CNa*', constant($clientKexInitMessage), strlen($ourPublicBytes), $ourPublicBytes); - - $this->send_binary_packet($data); - - switch ($clientKexInitMessage) { - case 'NET_SSH2_MSG_KEX_ECDH_INIT': - $this->updateLogHistory('NET_SSH2_MSG_KEXDH_INIT', 'NET_SSH2_MSG_KEX_ECDH_INIT'); - break; - case 'NET_SSH2_MSG_KEXDH_GEX_INIT': - $this->updateLogHistory('UNKNOWN (32)', 'NET_SSH2_MSG_KEXDH_GEX_INIT'); - } - - $response = $this->get_binary_packet(); - - list( - $type, - $server_public_host_key, - $theirPublicBytes, - $this->signature - ) = Strings::unpackSSH2('Csss', $response); - - if ($type != constant($serverKexReplyMessage)) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_PROTOCOL_ERROR); - throw new \UnexpectedValueException("Expected $serverKexReplyMessage"); - } - switch ($serverKexReplyMessage) { - case 'NET_SSH2_MSG_KEX_ECDH_REPLY': - $this->updateLogHistory('NET_SSH2_MSG_KEXDH_REPLY', 'NET_SSH2_MSG_KEX_ECDH_REPLY'); - break; - case 'NET_SSH2_MSG_KEXDH_GEX_REPLY': - $this->updateLogHistory('UNKNOWN (33)', 'NET_SSH2_MSG_KEXDH_GEX_REPLY'); - } - - $this->server_public_host_key = $server_public_host_key; - list($public_key_format) = Strings::unpackSSH2('s', $server_public_host_key); - if (strlen($this->signature) < 4) { - throw new \LengthException('The signature needs at least four bytes'); - } - $temp = unpack('Nlength', substr($this->signature, 0, 4)); - $this->signature_format = substr($this->signature, 4, $temp['length']); - - $keyBytes = DH::computeSecret($ourPrivate, $theirPublicBytes); - if (($keyBytes & "\xFF\x80") === "\x00\x00") { - $keyBytes = substr($keyBytes, 1); - } elseif (($keyBytes[0] & "\x80") === "\x80") { - $keyBytes = "\0$keyBytes"; - } - - $this->exchange_hash = Strings::packSSH2( - 's5', - $this->identifier, - $this->server_identifier, - $kexinit_payload_client, - $kexinit_payload_server, - $this->server_public_host_key - ); - $this->exchange_hash .= $exchange_hash_rfc4419; - $this->exchange_hash .= Strings::packSSH2( - 's3', - $ourPublicBytes, - $theirPublicBytes, - $keyBytes - ); - - $this->exchange_hash = $kexHash->hash($this->exchange_hash); - - if ($this->session_id === false) { - $this->session_id = $this->exchange_hash; - } - - switch ($server_host_key_algorithm) { - case 'rsa-sha2-256': - case 'rsa-sha2-512': - //case 'ssh-rsa': - $expected_key_format = 'ssh-rsa'; - break; - default: - $expected_key_format = $server_host_key_algorithm; - } - if ($public_key_format != $expected_key_format || $this->signature_format != $server_host_key_algorithm) { - switch (true) { - case $this->signature_format == $server_host_key_algorithm: - case $server_host_key_algorithm != 'rsa-sha2-256' && $server_host_key_algorithm != 'rsa-sha2-512': - case $this->signature_format != 'ssh-rsa': - $this->disconnect_helper(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE); - throw new \RuntimeException('Server Host Key Algorithm Mismatch (' . $this->signature_format . ' vs ' . $server_host_key_algorithm . ')'); - } - } - - $packet = pack('C', NET_SSH2_MSG_NEWKEYS); - $this->send_binary_packet($packet); - - $response = $this->get_binary_packet(); - - if ($response === false) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_CONNECTION_LOST); - throw new ConnectionClosedException('Connection closed by server'); - } - - list($type) = Strings::unpackSSH2('C', $response); - if ($type != NET_SSH2_MSG_NEWKEYS) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_PROTOCOL_ERROR); - throw new \UnexpectedValueException('Expected SSH_MSG_NEWKEYS'); - } - - $keyBytes = pack('Na*', strlen($keyBytes), $keyBytes); - - $this->encrypt = self::encryption_algorithm_to_crypt_instance($encrypt); - if ($this->encrypt) { - if (self::$crypto_engine) { - $this->encrypt->setPreferredEngine(self::$crypto_engine); - } - if ($this->encrypt->getBlockLengthInBytes()) { - $this->encrypt_block_size = $this->encrypt->getBlockLengthInBytes(); - } - $this->encrypt->disablePadding(); - - if ($this->encrypt->usesIV()) { - $iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'A' . $this->session_id); - while ($this->encrypt_block_size > strlen($iv)) { - $iv .= $kexHash->hash($keyBytes . $this->exchange_hash . $iv); - } - $this->encrypt->setIV(substr($iv, 0, $this->encrypt_block_size)); - } - - switch ($encrypt) { - case 'aes128-gcm@openssh.com': - case 'aes256-gcm@openssh.com': - $nonce = $kexHash->hash($keyBytes . $this->exchange_hash . 'A' . $this->session_id); - $this->encryptFixedPart = substr($nonce, 0, 4); - $this->encryptInvocationCounter = substr($nonce, 4, 8); - // fall-through - case 'chacha20-poly1305@openssh.com': - break; - default: - $this->encrypt->enableContinuousBuffer(); - } - - $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'C' . $this->session_id); - while ($encryptKeyLength > strlen($key)) { - $key .= $kexHash->hash($keyBytes . $this->exchange_hash . $key); - } - switch ($encrypt) { - case 'chacha20-poly1305@openssh.com': - $encryptKeyLength = 32; - $this->lengthEncrypt = self::encryption_algorithm_to_crypt_instance($encrypt); - $this->lengthEncrypt->setKey(substr($key, 32, 32)); - } - $this->encrypt->setKey(substr($key, 0, $encryptKeyLength)); - $this->encryptName = $encrypt; - } - - $this->decrypt = self::encryption_algorithm_to_crypt_instance($decrypt); - if ($this->decrypt) { - if (self::$crypto_engine) { - $this->decrypt->setPreferredEngine(self::$crypto_engine); - } - if ($this->decrypt->getBlockLengthInBytes()) { - $this->decrypt_block_size = $this->decrypt->getBlockLengthInBytes(); - } - $this->decrypt->disablePadding(); - - if ($this->decrypt->usesIV()) { - $iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'B' . $this->session_id); - while ($this->decrypt_block_size > strlen($iv)) { - $iv .= $kexHash->hash($keyBytes . $this->exchange_hash . $iv); - } - $this->decrypt->setIV(substr($iv, 0, $this->decrypt_block_size)); - } - - switch ($decrypt) { - case 'aes128-gcm@openssh.com': - case 'aes256-gcm@openssh.com': - // see https://tools.ietf.org/html/rfc5647#section-7.1 - $nonce = $kexHash->hash($keyBytes . $this->exchange_hash . 'B' . $this->session_id); - $this->decryptFixedPart = substr($nonce, 0, 4); - $this->decryptInvocationCounter = substr($nonce, 4, 8); - // fall-through - case 'chacha20-poly1305@openssh.com': - break; - default: - $this->decrypt->enableContinuousBuffer(); - } - - $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'D' . $this->session_id); - while ($decryptKeyLength > strlen($key)) { - $key .= $kexHash->hash($keyBytes . $this->exchange_hash . $key); - } - switch ($decrypt) { - case 'chacha20-poly1305@openssh.com': - $decryptKeyLength = 32; - $this->lengthDecrypt = self::encryption_algorithm_to_crypt_instance($decrypt); - $this->lengthDecrypt->setKey(substr($key, 32, 32)); - } - $this->decrypt->setKey(substr($key, 0, $decryptKeyLength)); - $this->decryptName = $decrypt; - } - - /* The "arcfour128" algorithm is the RC4 cipher, as described in - [SCHNEIER], using a 128-bit key. The first 1536 bytes of keystream - generated by the cipher MUST be discarded, and the first byte of the - first encrypted packet MUST be encrypted using the 1537th byte of - keystream. - - -- http://tools.ietf.org/html/rfc4345#section-4 */ - if ($encrypt == 'arcfour128' || $encrypt == 'arcfour256') { - $this->encrypt->encrypt(str_repeat("\0", 1536)); - } - if ($decrypt == 'arcfour128' || $decrypt == 'arcfour256') { - $this->decrypt->decrypt(str_repeat("\0", 1536)); - } - - if (!$this->encrypt->usesNonce()) { - list($this->hmac_create, $createKeyLength) = self::mac_algorithm_to_hash_instance($mac_algorithm_out); - } else { - $this->hmac_create = new \stdClass(); - $this->hmac_create_name = $mac_algorithm_out; - //$mac_algorithm_out = 'none'; - $createKeyLength = 0; - } - - if ($this->hmac_create instanceof Hash) { - $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'E' . $this->session_id); - while ($createKeyLength > strlen($key)) { - $key .= $kexHash->hash($keyBytes . $this->exchange_hash . $key); - } - $this->hmac_create->setKey(substr($key, 0, $createKeyLength)); - $this->hmac_create_name = $mac_algorithm_out; - $this->hmac_create_etm = preg_match('#-etm@openssh\.com$#', $mac_algorithm_out); - } - - if (!$this->decrypt->usesNonce()) { - list($this->hmac_check, $checkKeyLength) = self::mac_algorithm_to_hash_instance($mac_algorithm_in); - $this->hmac_size = $this->hmac_check->getLengthInBytes(); - } else { - $this->hmac_check = new \stdClass(); - $this->hmac_check_name = $mac_algorithm_in; - //$mac_algorithm_in = 'none'; - $checkKeyLength = 0; - $this->hmac_size = 0; - } - - if ($this->hmac_check instanceof Hash) { - $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'F' . $this->session_id); - while ($checkKeyLength > strlen($key)) { - $key .= $kexHash->hash($keyBytes . $this->exchange_hash . $key); - } - $this->hmac_check->setKey(substr($key, 0, $checkKeyLength)); - $this->hmac_check_name = $mac_algorithm_in; - $this->hmac_check_etm = preg_match('#-etm@openssh\.com$#', $mac_algorithm_in); - } - - $this->regenerate_compression_context = $this->regenerate_decompression_context = true; - - return true; - } - - /** - * Maps an encryption algorithm name to the number of key bytes. - * - * @param string $algorithm Name of the encryption algorithm - * @return int|null Number of bytes as an integer or null for unknown - */ - private function encryption_algorithm_to_key_size($algorithm) - { - if ($this->bad_key_size_fix && self::bad_algorithm_candidate($algorithm)) { - return 16; - } - - switch ($algorithm) { - case 'none': - return 0; - case 'aes128-gcm@openssh.com': - case 'aes128-cbc': - case 'aes128-ctr': - case 'arcfour': - case 'arcfour128': - case 'blowfish-cbc': - case 'blowfish-ctr': - case 'twofish128-cbc': - case 'twofish128-ctr': - return 16; - case '3des-cbc': - case '3des-ctr': - case 'aes192-cbc': - case 'aes192-ctr': - case 'twofish192-cbc': - case 'twofish192-ctr': - return 24; - case 'aes256-gcm@openssh.com': - case 'aes256-cbc': - case 'aes256-ctr': - case 'arcfour256': - case 'twofish-cbc': - case 'twofish256-cbc': - case 'twofish256-ctr': - return 32; - case 'chacha20-poly1305@openssh.com': - return 64; - } - return null; - } - - /** - * Maps an encryption algorithm name to an instance of a subclass of - * \phpseclib3\Crypt\Common\SymmetricKey. - * - * @param string $algorithm Name of the encryption algorithm - * @return SymmetricKey|null - */ - private static function encryption_algorithm_to_crypt_instance($algorithm) - { - switch ($algorithm) { - case '3des-cbc': - return new TripleDES('cbc'); - case '3des-ctr': - return new TripleDES('ctr'); - case 'aes256-cbc': - case 'aes192-cbc': - case 'aes128-cbc': - return new Rijndael('cbc'); - case 'aes256-ctr': - case 'aes192-ctr': - case 'aes128-ctr': - return new Rijndael('ctr'); - case 'blowfish-cbc': - return new Blowfish('cbc'); - case 'blowfish-ctr': - return new Blowfish('ctr'); - case 'twofish128-cbc': - case 'twofish192-cbc': - case 'twofish256-cbc': - case 'twofish-cbc': - return new Twofish('cbc'); - case 'twofish128-ctr': - case 'twofish192-ctr': - case 'twofish256-ctr': - return new Twofish('ctr'); - case 'arcfour': - case 'arcfour128': - case 'arcfour256': - return new RC4(); - case 'aes128-gcm@openssh.com': - case 'aes256-gcm@openssh.com': - return new Rijndael('gcm'); - case 'chacha20-poly1305@openssh.com': - return new ChaCha20(); - } - return null; - } - - /** - * Maps an encryption algorithm name to an instance of a subclass of - * \phpseclib3\Crypt\Hash. - * - * @param string $algorithm Name of the encryption algorithm - * @return array{Hash, int}|null - */ - private static function mac_algorithm_to_hash_instance($algorithm) - { - switch ($algorithm) { - case 'umac-64@openssh.com': - case 'umac-64-etm@openssh.com': - return [new Hash('umac-64'), 16]; - case 'umac-128@openssh.com': - case 'umac-128-etm@openssh.com': - return [new Hash('umac-128'), 16]; - case 'hmac-sha2-512': - case 'hmac-sha2-512-etm@openssh.com': - return [new Hash('sha512'), 64]; - case 'hmac-sha2-256': - case 'hmac-sha2-256-etm@openssh.com': - return [new Hash('sha256'), 32]; - case 'hmac-sha1': - case 'hmac-sha1-etm@openssh.com': - return [new Hash('sha1'), 20]; - case 'hmac-sha1-96': - return [new Hash('sha1-96'), 20]; - case 'hmac-md5': - return [new Hash('md5'), 16]; - case 'hmac-md5-96': - return [new Hash('md5-96'), 16]; - } - } - - /* - * Tests whether or not proposed algorithm has a potential for issues - * - * @link https://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/ssh2-aesctr-openssh.html - * @link https://bugzilla.mindrot.org/show_bug.cgi?id=1291 - * @param string $algorithm Name of the encryption algorithm - * @return bool - */ - private static function bad_algorithm_candidate($algorithm) - { - switch ($algorithm) { - case 'arcfour256': - case 'aes192-ctr': - case 'aes256-ctr': - return true; - } - - return false; - } - - /** - * Login - * - * The $password parameter can be a plaintext password, a \phpseclib3\Crypt\RSA|EC|DSA object, a \phpseclib3\System\SSH\Agent object or an array - * - * @param string $username - * @param string|AsymmetricKey|array[]|Agent|null ...$args - * @return bool - * @see self::_login() - */ - public function login($username, ...$args) - { - $this->auth[] = func_get_args(); - - // try logging with 'none' as an authentication method first since that's what - // PuTTY does - if (substr($this->server_identifier, 0, 15) != 'SSH-2.0-CoreFTP' && $this->auth_methods_to_continue === null) { - if ($this->sublogin($username)) { - return true; - } - if (!count($args)) { - return false; - } - } - return $this->sublogin($username, ...$args); - } - - /** - * Login Helper - * - * @param string $username - * @param string ...$args - * @return bool - * @see self::_login_helper() - */ - protected function sublogin($username, ...$args) - { - if (!($this->bitmap & self::MASK_CONSTRUCTOR)) { - $this->connect(); - } - - if (empty($args)) { - return $this->login_helper($username); - } - - foreach ($args as $arg) { - switch (true) { - case $arg instanceof PublicKey: - throw new \UnexpectedValueException('A PublicKey object was passed to the login method instead of a PrivateKey object'); - case $arg instanceof PrivateKey: - case $arg instanceof Agent: - case is_array($arg): - case Strings::is_stringable($arg): - break; - default: - throw new \UnexpectedValueException('$password needs to either be an instance of \phpseclib3\Crypt\Common\PrivateKey, \System\SSH\Agent, an array or a string'); - } - } - - while (count($args)) { - if (!$this->auth_methods_to_continue || !$this->smartMFA) { - $newargs = $args; - $args = []; - } else { - $newargs = []; - foreach ($this->auth_methods_to_continue as $method) { - switch ($method) { - case 'publickey': - foreach ($args as $key => $arg) { - if ($arg instanceof PrivateKey || $arg instanceof Agent) { - $newargs[] = $arg; - unset($args[$key]); - break; - } - } - break; - case 'keyboard-interactive': - $hasArray = $hasString = false; - foreach ($args as $arg) { - if ($hasArray || is_array($arg)) { - $hasArray = true; - break; - } - if ($hasString || Strings::is_stringable($arg)) { - $hasString = true; - break; - } - } - if ($hasArray && $hasString) { - foreach ($args as $key => $arg) { - if (is_array($arg)) { - $newargs[] = $arg; - break 2; - } - } - } - // fall-through - case 'password': - foreach ($args as $key => $arg) { - $newargs[] = $arg; - unset($args[$key]); - break; - } - } - } - } - - if (!count($newargs)) { - return false; - } - - foreach ($newargs as $arg) { - if ($this->login_helper($username, $arg)) { - return true; - } - } - } - return false; - } - - /** - * Login Helper - * - * {@internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis} - * by sending dummy SSH_MSG_IGNORE messages.} - * - * @param string $username - * @param string|AsymmetricKey|array[]|Agent|null ...$args - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - * @throws \RuntimeException on other errors - */ - private function login_helper($username, $password = null) - { - if (!($this->bitmap & self::MASK_CONNECTED)) { - return false; - } - - if (!($this->bitmap & self::MASK_LOGIN_REQ)) { - $packet = Strings::packSSH2('Cs', NET_SSH2_MSG_SERVICE_REQUEST, 'ssh-userauth'); - $this->send_binary_packet($packet); - - try { - $response = $this->get_binary_packet(); - } catch (\Exception $e) { - if ($this->retry_connect) { - $this->retry_connect = false; - $this->connect(); - return $this->login_helper($username, $password); - } - $this->disconnect_helper(NET_SSH2_DISCONNECT_CONNECTION_LOST); - throw new ConnectionClosedException('Connection closed by server'); - } - - list($type, $service) = Strings::unpackSSH2('Cs', $response); - if ($type != NET_SSH2_MSG_SERVICE_ACCEPT || $service != 'ssh-userauth') { - $this->disconnect_helper(NET_SSH2_DISCONNECT_PROTOCOL_ERROR); - throw new \UnexpectedValueException('Expected SSH_MSG_SERVICE_ACCEPT'); - } - $this->bitmap |= self::MASK_LOGIN_REQ; - } - - if (strlen($this->last_interactive_response)) { - return !Strings::is_stringable($password) && !is_array($password) ? false : $this->keyboard_interactive_process($password); - } - - if ($password instanceof PrivateKey) { - return $this->privatekey_login($username, $password); - } - - if ($password instanceof Agent) { - return $this->ssh_agent_login($username, $password); - } - - if (is_array($password)) { - if ($this->keyboard_interactive_login($username, $password)) { - $this->bitmap |= self::MASK_LOGIN; - return true; - } - return false; - } - - if (!isset($password)) { - $packet = Strings::packSSH2( - 'Cs3', - NET_SSH2_MSG_USERAUTH_REQUEST, - $username, - 'ssh-connection', - 'none' - ); - - $this->send_binary_packet($packet); - - $response = $this->get_binary_packet(); - - list($type) = Strings::unpackSSH2('C', $response); - switch ($type) { - case NET_SSH2_MSG_USERAUTH_SUCCESS: - $this->bitmap |= self::MASK_LOGIN; - return true; - case NET_SSH2_MSG_USERAUTH_FAILURE: - list($auth_methods) = Strings::unpackSSH2('L', $response); - $this->auth_methods_to_continue = $auth_methods; - // fall-through - default: - return false; - } - } - - $packet = Strings::packSSH2( - 'Cs3bs', - NET_SSH2_MSG_USERAUTH_REQUEST, - $username, - 'ssh-connection', - 'password', - false, - $password - ); - - // remove the username and password from the logged packet - if (!defined('NET_SSH2_LOGGING')) { - $logged = null; - } else { - $logged = Strings::packSSH2( - 'Cs3bs', - NET_SSH2_MSG_USERAUTH_REQUEST, - $username, - 'ssh-connection', - 'password', - false, - 'password' - ); - } - - $this->send_binary_packet($packet, $logged); - - $response = $this->get_binary_packet(); - if ($response === false) { - return false; - } - list($type) = Strings::unpackSSH2('C', $response); - switch ($type) { - case NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ: // in theory, the password can be changed - $this->updateLogHistory('UNKNOWN (60)', 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ'); - - list($message) = Strings::unpackSSH2('s', $response); - $this->errors[] = 'SSH_MSG_USERAUTH_PASSWD_CHANGEREQ: ' . $message; - - return $this->disconnect_helper(NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER); - case NET_SSH2_MSG_USERAUTH_FAILURE: - // can we use keyboard-interactive authentication? if not then either the login is bad or the server employees - // multi-factor authentication - list($auth_methods, $partial_success) = Strings::unpackSSH2('Lb', $response); - $this->auth_methods_to_continue = $auth_methods; - if (!$partial_success && in_array('keyboard-interactive', $auth_methods)) { - if ($this->keyboard_interactive_login($username, $password)) { - $this->bitmap |= self::MASK_LOGIN; - return true; - } - return false; - } - return false; - case NET_SSH2_MSG_USERAUTH_SUCCESS: - $this->bitmap |= self::MASK_LOGIN; - return true; - } - - return false; - } - - /** - * Login via keyboard-interactive authentication - * - * See {@link http://tools.ietf.org/html/rfc4256 RFC4256} for details. This is not a full-featured keyboard-interactive authenticator. - * - * @param string $username - * @param string|array $password - * @return bool - */ - private function keyboard_interactive_login($username, $password) - { - $packet = Strings::packSSH2( - 'Cs5', - NET_SSH2_MSG_USERAUTH_REQUEST, - $username, - 'ssh-connection', - 'keyboard-interactive', - '', // language tag - '' // submethods - ); - $this->send_binary_packet($packet); - - return $this->keyboard_interactive_process($password); - } - - /** - * Handle the keyboard-interactive requests / responses. - * - * @param string|array ...$responses - * @return bool - * @throws \RuntimeException on connection error - */ - private function keyboard_interactive_process(...$responses) - { - if (strlen($this->last_interactive_response)) { - $response = $this->last_interactive_response; - } else { - $orig = $response = $this->get_binary_packet(); - } - - list($type) = Strings::unpackSSH2('C', $response); - switch ($type) { - case NET_SSH2_MSG_USERAUTH_INFO_REQUEST: - list( - , // name; may be empty - , // instruction; may be empty - , // language tag; may be empty - $num_prompts - ) = Strings::unpackSSH2('s3N', $response); - - for ($i = 0; $i < count($responses); $i++) { - if (is_array($responses[$i])) { - foreach ($responses[$i] as $key => $value) { - $this->keyboard_requests_responses[$key] = $value; - } - unset($responses[$i]); - } - } - $responses = array_values($responses); - - if (isset($this->keyboard_requests_responses)) { - for ($i = 0; $i < $num_prompts; $i++) { - list( - $prompt, // prompt - ie. "Password: "; must not be empty - // echo - ) = Strings::unpackSSH2('sC', $response); - foreach ($this->keyboard_requests_responses as $key => $value) { - if (substr($prompt, 0, strlen($key)) == $key) { - $responses[] = $value; - break; - } - } - } - } - - // see http://tools.ietf.org/html/rfc4256#section-3.2 - if (strlen($this->last_interactive_response)) { - $this->last_interactive_response = ''; - } else { - $this->updateLogHistory('UNKNOWN (60)', 'NET_SSH2_MSG_USERAUTH_INFO_REQUEST'); - } - - if (!count($responses) && $num_prompts) { - $this->last_interactive_response = $orig; - return false; - } - - /* - After obtaining the requested information from the user, the client - MUST respond with an SSH_MSG_USERAUTH_INFO_RESPONSE message. - */ - // see http://tools.ietf.org/html/rfc4256#section-3.4 - $packet = $logged = pack('CN', NET_SSH2_MSG_USERAUTH_INFO_RESPONSE, count($responses)); - for ($i = 0; $i < count($responses); $i++) { - $packet .= Strings::packSSH2('s', $responses[$i]); - $logged .= Strings::packSSH2('s', 'dummy-answer'); - } - - $this->send_binary_packet($packet, $logged); - - $this->updateLogHistory('UNKNOWN (61)', 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE'); - - /* - After receiving the response, the server MUST send either an - SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, or another - SSH_MSG_USERAUTH_INFO_REQUEST message. - */ - // maybe phpseclib should force close the connection after x request / responses? unless something like that is done - // there could be an infinite loop of request / responses. - return $this->keyboard_interactive_process(); - case NET_SSH2_MSG_USERAUTH_SUCCESS: - return true; - case NET_SSH2_MSG_USERAUTH_FAILURE: - list($auth_methods) = Strings::unpackSSH2('L', $response); - $this->auth_methods_to_continue = $auth_methods; - return false; - } - - return false; - } - - /** - * Login with an ssh-agent provided key - * - * @param string $username - * @param \phpseclib3\System\SSH\Agent $agent - * @return bool - */ - private function ssh_agent_login($username, Agent $agent) - { - $this->agent = $agent; - $keys = $agent->requestIdentities(); - foreach ($keys as $key) { - if ($this->privatekey_login($username, $key)) { - return true; - } - } - - return false; - } - - /** - * Login with an RSA private key - * - * {@internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis} - * by sending dummy SSH_MSG_IGNORE messages.} - * - * @param string $username - * @param \phpseclib3\Crypt\Common\PrivateKey $privatekey - * @return bool - * @throws \RuntimeException on connection error - */ - private function privatekey_login($username, PrivateKey $privatekey) - { - $publickey = $privatekey->getPublicKey(); - - if ($publickey instanceof RSA) { - $privatekey = $privatekey->withPadding(RSA::SIGNATURE_PKCS1); - $algos = ['rsa-sha2-256', 'rsa-sha2-512', 'ssh-rsa']; - if (isset($this->preferred['hostkey'])) { - $algos = array_intersect($this->preferred['hostkey'], $algos); - } - $algo = self::array_intersect_first($algos, $this->supported_private_key_algorithms); - switch ($algo) { - case 'rsa-sha2-512': - $hash = 'sha512'; - $signatureType = 'rsa-sha2-512'; - break; - case 'rsa-sha2-256': - $hash = 'sha256'; - $signatureType = 'rsa-sha2-256'; - break; - //case 'ssh-rsa': - default: - $hash = 'sha1'; - $signatureType = 'ssh-rsa'; - } - } elseif ($publickey instanceof EC) { - $privatekey = $privatekey->withSignatureFormat('SSH2'); - $curveName = $privatekey->getCurve(); - switch ($curveName) { - case 'Ed25519': - $hash = 'sha512'; - $signatureType = 'ssh-ed25519'; - break; - case 'secp256r1': // nistp256 - $hash = 'sha256'; - $signatureType = 'ecdsa-sha2-nistp256'; - break; - case 'secp384r1': // nistp384 - $hash = 'sha384'; - $signatureType = 'ecdsa-sha2-nistp384'; - break; - case 'secp521r1': // nistp521 - $hash = 'sha512'; - $signatureType = 'ecdsa-sha2-nistp521'; - break; - default: - if (is_array($curveName)) { - throw new UnsupportedCurveException('Specified Curves are not supported by SSH2'); - } - throw new UnsupportedCurveException('Named Curve of ' . $curveName . ' is not supported by phpseclib3\'s SSH2 implementation'); - } - } elseif ($publickey instanceof DSA) { - $privatekey = $privatekey->withSignatureFormat('SSH2'); - $hash = 'sha1'; - $signatureType = 'ssh-dss'; - } else { - throw new UnsupportedAlgorithmException('Please use either an RSA key, an EC one or a DSA key'); - } - - $publickeyStr = $publickey->toString('OpenSSH', ['binary' => true]); - - $part1 = Strings::packSSH2( - 'Csss', - NET_SSH2_MSG_USERAUTH_REQUEST, - $username, - 'ssh-connection', - 'publickey' - ); - $part2 = Strings::packSSH2('ss', $signatureType, $publickeyStr); - - $packet = $part1 . chr(0) . $part2; - $this->send_binary_packet($packet); - - $response = $this->get_binary_packet(); - - list($type) = Strings::unpackSSH2('C', $response); - switch ($type) { - case NET_SSH2_MSG_USERAUTH_FAILURE: - list($auth_methods) = Strings::unpackSSH2('L', $response); - if (in_array('publickey', $auth_methods) && substr($signatureType, 0, 9) == 'rsa-sha2-') { - $this->supported_private_key_algorithms = array_diff($this->supported_private_key_algorithms, ['rsa-sha2-256', 'rsa-sha2-512']); - return $this->privatekey_login($username, $privatekey); - } - $this->auth_methods_to_continue = $auth_methods; - $this->errors[] = 'SSH_MSG_USERAUTH_FAILURE'; - return false; - case NET_SSH2_MSG_USERAUTH_PK_OK: - // we'll just take it on faith that the public key blob and the public key algorithm name are as - // they should be - $this->updateLogHistory('UNKNOWN (60)', 'NET_SSH2_MSG_USERAUTH_PK_OK'); - break; - case NET_SSH2_MSG_USERAUTH_SUCCESS: - $this->bitmap |= self::MASK_LOGIN; - return true; - default: - $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION); - throw new ConnectionClosedException('Unexpected response to publickey authentication pt 1'); - } - - $packet = $part1 . chr(1) . $part2; - $privatekey = $privatekey->withHash($hash); - $signature = $privatekey->sign(Strings::packSSH2('s', $this->session_id) . $packet); - if ($publickey instanceof RSA) { - $signature = Strings::packSSH2('ss', $signatureType, $signature); - } - $packet .= Strings::packSSH2('s', $signature); - - $this->send_binary_packet($packet); - - $response = $this->get_binary_packet(); - - list($type) = Strings::unpackSSH2('C', $response); - switch ($type) { - case NET_SSH2_MSG_USERAUTH_FAILURE: - // either the login is bad or the server employs multi-factor authentication - list($auth_methods) = Strings::unpackSSH2('L', $response); - $this->auth_methods_to_continue = $auth_methods; - return false; - case NET_SSH2_MSG_USERAUTH_SUCCESS: - $this->bitmap |= self::MASK_LOGIN; - return true; - } - - $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION); - throw new ConnectionClosedException('Unexpected response to publickey authentication pt 2'); - } - - /** - * Return the currently configured timeout - * - * @return int - */ - public function getTimeout() - { - return $this->timeout; - } - - /** - * Set Timeout - * - * $ssh->exec('ping 127.0.0.1'); on a Linux host will never return and will run indefinitely. setTimeout() makes it so it'll timeout. - * Setting $timeout to false or 0 will mean there is no timeout. - * - * @param mixed $timeout - */ - public function setTimeout($timeout) - { - $this->timeout = $this->curTimeout = $timeout; - } - - /** - * Set Keep Alive - * - * Sends an SSH2_MSG_IGNORE message every x seconds, if x is a positive non-zero number. - * - * @param int $interval - */ - public function setKeepAlive($interval) - { - $this->keepAlive = $interval; - } - - /** - * Get the output from stdError - * - */ - public function getStdError() - { - return $this->stdErrorLog; - } - - /** - * Execute Command - * - * If $callback is set to false then \phpseclib3\Net\SSH2::get_channel_packet(self::CHANNEL_EXEC) will need to be called manually. - * In all likelihood, this is not a feature you want to be taking advantage of. - * - * @param string $command - * @return string|bool - * @psalm-return ($callback is callable ? bool : string|bool) - * @throws \RuntimeException on connection error - */ - public function exec($command, callable $callback = null) - { - $this->curTimeout = $this->timeout; - $this->is_timeout = false; - $this->stdErrorLog = ''; - - if (!$this->isAuthenticated()) { - return false; - } - - if ($this->in_request_pty_exec) { - throw new \RuntimeException('If you want to run multiple exec()\'s you will need to disable (and re-enable if appropriate) a PTY for each one.'); - } - - // RFC4254 defines the (client) window size as "bytes the other party can send before it must wait for the window to - // be adjusted". 0x7FFFFFFF is, at 2GB, the max size. technically, it should probably be decremented, but, - // honestly, if you're transferring more than 2GB, you probably shouldn't be using phpseclib, anyway. - // see http://tools.ietf.org/html/rfc4254#section-5.2 for more info - $this->window_size_server_to_client[self::CHANNEL_EXEC] = $this->window_size; - // 0x8000 is the maximum max packet size, per http://tools.ietf.org/html/rfc4253#section-6.1, although since PuTTy - // uses 0x4000, that's what will be used here, as well. - $packet_size = 0x4000; - - $packet = Strings::packSSH2( - 'CsN3', - NET_SSH2_MSG_CHANNEL_OPEN, - 'session', - self::CHANNEL_EXEC, - $this->window_size_server_to_client[self::CHANNEL_EXEC], - $packet_size - ); - $this->send_binary_packet($packet); - - $this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_OPEN; - - $this->get_channel_packet(self::CHANNEL_EXEC); - - if ($this->request_pty === true) { - $terminal_modes = pack('C', NET_SSH2_TTY_OP_END); - $packet = Strings::packSSH2( - 'CNsCsN4s', - NET_SSH2_MSG_CHANNEL_REQUEST, - $this->server_channels[self::CHANNEL_EXEC], - 'pty-req', - 1, - $this->term, - $this->windowColumns, - $this->windowRows, - 0, - 0, - $terminal_modes - ); - - $this->send_binary_packet($packet); - - $this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_REQUEST; - if (!$this->get_channel_packet(self::CHANNEL_EXEC)) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION); - throw new \RuntimeException('Unable to request pseudo-terminal'); - } - - $this->in_request_pty_exec = true; - } - - // sending a pty-req SSH_MSG_CHANNEL_REQUEST message is unnecessary and, in fact, in most cases, slows things - // down. the one place where it might be desirable is if you're doing something like \phpseclib3\Net\SSH2::exec('ping localhost &'). - // with a pty-req SSH_MSG_CHANNEL_REQUEST, exec() will return immediately and the ping process will then - // then immediately terminate. without such a request exec() will loop indefinitely. the ping process won't end but - // neither will your script. - - // although, in theory, the size of SSH_MSG_CHANNEL_REQUEST could exceed the maximum packet size established by - // SSH_MSG_CHANNEL_OPEN_CONFIRMATION, RFC4254#section-5.1 states that the "maximum packet size" refers to the - // "maximum size of an individual data packet". ie. SSH_MSG_CHANNEL_DATA. RFC4254#section-5.2 corroborates. - $packet = Strings::packSSH2( - 'CNsCs', - NET_SSH2_MSG_CHANNEL_REQUEST, - $this->server_channels[self::CHANNEL_EXEC], - 'exec', - 1, - $command - ); - $this->send_binary_packet($packet); - - $this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_REQUEST; - - if (!$this->get_channel_packet(self::CHANNEL_EXEC)) { - return false; - } - - $this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_DATA; - - if ($this->in_request_pty_exec) { - return true; - } - - $output = ''; - while (true) { - $temp = $this->get_channel_packet(self::CHANNEL_EXEC); - switch (true) { - case $temp === true: - return is_callable($callback) ? true : $output; - case $temp === false: - return false; - default: - if (is_callable($callback)) { - if ($callback($temp) === true) { - $this->close_channel(self::CHANNEL_EXEC); - return true; - } - } else { - $output .= $temp; - } - } - } - } - - /** - * Creates an interactive shell - * - * @see self::read() - * @see self::write() - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - * @throws \RuntimeException on other errors - */ - private function initShell() - { - if ($this->in_request_pty_exec === true) { - return true; - } - - $this->window_size_server_to_client[self::CHANNEL_SHELL] = $this->window_size; - $packet_size = 0x4000; - - $packet = Strings::packSSH2( - 'CsN3', - NET_SSH2_MSG_CHANNEL_OPEN, - 'session', - self::CHANNEL_SHELL, - $this->window_size_server_to_client[self::CHANNEL_SHELL], - $packet_size - ); - - $this->send_binary_packet($packet); - - $this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_OPEN; - - $this->get_channel_packet(self::CHANNEL_SHELL); - - $terminal_modes = pack('C', NET_SSH2_TTY_OP_END); - $packet = Strings::packSSH2( - 'CNsbsN4s', - NET_SSH2_MSG_CHANNEL_REQUEST, - $this->server_channels[self::CHANNEL_SHELL], - 'pty-req', - true, // want reply - $this->term, - $this->windowColumns, - $this->windowRows, - 0, - 0, - $terminal_modes - ); - - $this->send_binary_packet($packet); - - $this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_REQUEST; - - if (!$this->get_channel_packet(self::CHANNEL_SHELL)) { - throw new \RuntimeException('Unable to request pty'); - } - - $packet = Strings::packSSH2( - 'CNsb', - NET_SSH2_MSG_CHANNEL_REQUEST, - $this->server_channels[self::CHANNEL_SHELL], - 'shell', - true // want reply - ); - $this->send_binary_packet($packet); - - $response = $this->get_channel_packet(self::CHANNEL_SHELL); - if ($response === false) { - throw new \RuntimeException('Unable to request shell'); - } - - $this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_DATA; - - $this->bitmap |= self::MASK_SHELL; - - return true; - } - - /** - * Return the channel to be used with read() / write() - * - * @see self::read() - * @see self::write() - * @return int - */ - private function get_interactive_channel() - { - switch (true) { - case $this->in_subsystem: - return self::CHANNEL_SUBSYSTEM; - case $this->in_request_pty_exec: - return self::CHANNEL_EXEC; - default: - return self::CHANNEL_SHELL; - } - } - - /** - * Return an available open channel - * - * @return int - */ - private function get_open_channel() - { - $channel = self::CHANNEL_EXEC; - do { - if (isset($this->channel_status[$channel]) && $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_OPEN) { - return $channel; - } - } while ($channel++ < self::CHANNEL_SUBSYSTEM); - - return false; - } - - /** - * Request agent forwarding of remote server - * - * @return bool - */ - public function requestAgentForwarding() - { - $request_channel = $this->get_open_channel(); - if ($request_channel === false) { - return false; - } - - $packet = Strings::packSSH2( - 'CNsC', - NET_SSH2_MSG_CHANNEL_REQUEST, - $this->server_channels[$request_channel], - 'auth-agent-req@openssh.com', - 1 - ); - - $this->channel_status[$request_channel] = NET_SSH2_MSG_CHANNEL_REQUEST; - - $this->send_binary_packet($packet); - - if (!$this->get_channel_packet($request_channel)) { - return false; - } - - $this->channel_status[$request_channel] = NET_SSH2_MSG_CHANNEL_OPEN; - - return true; - } - - /** - * Returns the output of an interactive shell - * - * Returns when there's a match for $expect, which can take the form of a string literal or, - * if $mode == self::READ_REGEX, a regular expression. - * - * @see self::write() - * @param string $expect - * @param int $mode - * @return string|bool|null - * @throws \RuntimeException on connection error - */ - public function read($expect = '', $mode = self::READ_SIMPLE) - { - $this->curTimeout = $this->timeout; - $this->is_timeout = false; - - if (!$this->isAuthenticated()) { - throw new InsufficientSetupException('Operation disallowed prior to login()'); - } - - if (!($this->bitmap & self::MASK_SHELL) && !$this->initShell()) { - throw new \RuntimeException('Unable to initiate an interactive shell session'); - } - - $channel = $this->get_interactive_channel(); - - if ($mode == self::READ_NEXT) { - return $this->get_channel_packet($channel); - } - - $match = $expect; - while (true) { - if ($mode == self::READ_REGEX) { - preg_match($expect, substr($this->interactiveBuffer, -1024), $matches); - $match = isset($matches[0]) ? $matches[0] : ''; - } - $pos = strlen($match) ? strpos($this->interactiveBuffer, $match) : false; - if ($pos !== false) { - return Strings::shift($this->interactiveBuffer, $pos + strlen($match)); - } - $response = $this->get_channel_packet($channel); - if ($response === true) { - $this->in_request_pty_exec = false; - return Strings::shift($this->interactiveBuffer, strlen($this->interactiveBuffer)); - } - - $this->interactiveBuffer .= $response; - } - } - - /** - * Inputs a command into an interactive shell. - * - * @see SSH2::read() - * @param string $cmd - * @return void - * @throws \RuntimeException on connection error - */ - public function write($cmd) - { - if (!$this->isAuthenticated()) { - throw new InsufficientSetupException('Operation disallowed prior to login()'); - } - - if (!($this->bitmap & self::MASK_SHELL) && !$this->initShell()) { - throw new \RuntimeException('Unable to initiate an interactive shell session'); - } - - $this->send_channel_packet($this->get_interactive_channel(), $cmd); - } - - /** - * Start a subsystem. - * - * Right now only one subsystem at a time is supported. To support multiple subsystem's stopSubsystem() could accept - * a string that contained the name of the subsystem, but at that point, only one subsystem of each type could be opened. - * To support multiple subsystem's of the same name maybe it'd be best if startSubsystem() generated a new channel id and - * returns that and then that that was passed into stopSubsystem() but that'll be saved for a future date and implemented - * if there's sufficient demand for such a feature. - * - * @see self::stopSubsystem() - * @param string $subsystem - * @return bool - */ - public function startSubsystem($subsystem) - { - $this->window_size_server_to_client[self::CHANNEL_SUBSYSTEM] = $this->window_size; - - $packet = Strings::packSSH2( - 'CsN3', - NET_SSH2_MSG_CHANNEL_OPEN, - 'session', - self::CHANNEL_SUBSYSTEM, - $this->window_size, - 0x4000 - ); - - $this->send_binary_packet($packet); - - $this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_OPEN; - - $this->get_channel_packet(self::CHANNEL_SUBSYSTEM); - - $packet = Strings::packSSH2( - 'CNsCs', - NET_SSH2_MSG_CHANNEL_REQUEST, - $this->server_channels[self::CHANNEL_SUBSYSTEM], - 'subsystem', - 1, - $subsystem - ); - $this->send_binary_packet($packet); - - $this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_REQUEST; - - if (!$this->get_channel_packet(self::CHANNEL_SUBSYSTEM)) { - return false; - } - - $this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_DATA; - - $this->bitmap |= self::MASK_SHELL; - $this->in_subsystem = true; - - return true; - } - - /** - * Stops a subsystem. - * - * @see self::startSubsystem() - * @return bool - */ - public function stopSubsystem() - { - $this->in_subsystem = false; - $this->close_channel(self::CHANNEL_SUBSYSTEM); - return true; - } - - /** - * Closes a channel - * - * If read() timed out you might want to just close the channel and have it auto-restart on the next read() call - * - */ - public function reset() - { - $this->close_channel($this->get_interactive_channel()); - } - - /** - * Is timeout? - * - * Did exec() or read() return because they timed out or because they encountered the end? - * - */ - public function isTimeout() - { - return $this->is_timeout; - } - - /** - * Disconnect - * - */ - public function disconnect() - { - $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION); - if (isset($this->realtime_log_file) && is_resource($this->realtime_log_file)) { - fclose($this->realtime_log_file); - } - unset(self::$connections[$this->getResourceId()]); - } - - /** - * Destructor. - * - * Will be called, automatically, if you're supporting just PHP5. If you're supporting PHP4, you'll need to call - * disconnect(). - * - */ - public function __destruct() - { - $this->disconnect(); - } - - /** - * Is the connection still active? - * - * @return bool - */ - public function isConnected() - { - return (bool) ($this->bitmap & self::MASK_CONNECTED); - } - - /** - * Have you successfully been logged in? - * - * @return bool - */ - public function isAuthenticated() - { - return (bool) ($this->bitmap & self::MASK_LOGIN); - } - - /** - * Pings a server connection, or tries to reconnect if the connection has gone down - * - * Inspired by http://php.net/manual/en/mysqli.ping.php - * - * @return bool - */ - public function ping() - { - if (!$this->isAuthenticated()) { - if (!empty($this->auth)) { - return $this->reconnect(); - } - return false; - } - - $this->window_size_server_to_client[self::CHANNEL_KEEP_ALIVE] = $this->window_size; - $packet_size = 0x4000; - $packet = Strings::packSSH2( - 'CsN3', - NET_SSH2_MSG_CHANNEL_OPEN, - 'session', - self::CHANNEL_KEEP_ALIVE, - $this->window_size_server_to_client[self::CHANNEL_KEEP_ALIVE], - $packet_size - ); - - try { - $this->send_binary_packet($packet); - - $this->channel_status[self::CHANNEL_KEEP_ALIVE] = NET_SSH2_MSG_CHANNEL_OPEN; - - $response = $this->get_channel_packet(self::CHANNEL_KEEP_ALIVE); - } catch (\RuntimeException $e) { - return $this->reconnect(); - } - - $this->close_channel(self::CHANNEL_KEEP_ALIVE); - return true; - } - - /** - * In situ reconnect method - * - * @return boolean - */ - private function reconnect() - { - $this->reset_connection(NET_SSH2_DISCONNECT_CONNECTION_LOST); - $this->retry_connect = true; - $this->connect(); - foreach ($this->auth as $auth) { - $result = $this->login(...$auth); - } - return $result; - } - - /** - * Resets a connection for re-use - * - * @param int $reason - */ - protected function reset_connection($reason) - { - $this->disconnect_helper($reason); - $this->decrypt = $this->encrypt = false; - $this->decrypt_block_size = $this->encrypt_block_size = 8; - $this->hmac_check = $this->hmac_create = false; - $this->hmac_size = false; - $this->session_id = false; - $this->retry_connect = true; - $this->get_seq_no = $this->send_seq_no = 0; - } - - /** - * Gets Binary Packets - * - * See '6. Binary Packet Protocol' of rfc4253 for more info. - * - * @see self::_send_binary_packet() - * @param bool $skip_channel_filter - * @return bool|string - */ - private function get_binary_packet($skip_channel_filter = false) - { - if ($skip_channel_filter) { - if (!is_resource($this->fsock)) { - throw new \InvalidArgumentException('fsock is not a resource.'); - } - $read = [$this->fsock]; - $write = $except = null; - - if (!$this->curTimeout) { - if ($this->keepAlive <= 0) { - @stream_select($read, $write, $except, null); - } else { - if (!@stream_select($read, $write, $except, $this->keepAlive)) { - $this->send_binary_packet(pack('CN', NET_SSH2_MSG_IGNORE, 0)); - return $this->get_binary_packet(true); - } - } - } else { - if ($this->curTimeout < 0) { - $this->is_timeout = true; - return true; - } - - $start = microtime(true); - - if ($this->keepAlive > 0 && $this->keepAlive < $this->curTimeout) { - if (!@stream_select($read, $write, $except, $this->keepAlive)) { - $this->send_binary_packet(pack('CN', NET_SSH2_MSG_IGNORE, 0)); - $elapsed = microtime(true) - $start; - $this->curTimeout -= $elapsed; - return $this->get_binary_packet(true); - } - $elapsed = microtime(true) - $start; - $this->curTimeout -= $elapsed; - } - - $sec = (int) floor($this->curTimeout); - $usec = (int) (1000000 * ($this->curTimeout - $sec)); - - // this can return a "stream_select(): unable to select [4]: Interrupted system call" error - if (!@stream_select($read, $write, $except, $sec, $usec)) { - $this->is_timeout = true; - return true; - } - $elapsed = microtime(true) - $start; - $this->curTimeout -= $elapsed; - } - } - - if (!is_resource($this->fsock) || feof($this->fsock)) { - $this->bitmap = 0; - $str = 'Connection closed (by server) prematurely'; - if (isset($elapsed)) { - $str .= ' ' . $elapsed . 's'; - } - throw new ConnectionClosedException($str); - } - - $start = microtime(true); - $raw = stream_get_contents($this->fsock, $this->decrypt_block_size); - - if (!strlen($raw)) { - $this->bitmap = 0; - throw new ConnectionClosedException('No data received from server'); - } - - if ($this->decrypt) { - switch ($this->decryptName) { - case 'aes128-gcm@openssh.com': - case 'aes256-gcm@openssh.com': - $this->decrypt->setNonce( - $this->decryptFixedPart . - $this->decryptInvocationCounter - ); - Strings::increment_str($this->decryptInvocationCounter); - $this->decrypt->setAAD($temp = Strings::shift($raw, 4)); - extract(unpack('Npacket_length', $temp)); - /** - * @var integer $packet_length - */ - - $raw .= $this->read_remaining_bytes($packet_length - $this->decrypt_block_size + 4); - $stop = microtime(true); - $tag = stream_get_contents($this->fsock, $this->decrypt_block_size); - $this->decrypt->setTag($tag); - $raw = $this->decrypt->decrypt($raw); - $raw = $temp . $raw; - $remaining_length = 0; - break; - case 'chacha20-poly1305@openssh.com': - // This should be impossible, but we are checking anyway to narrow the type for Psalm. - if (!($this->decrypt instanceof ChaCha20)) { - throw new \LogicException('$this->decrypt is not a ' . ChaCha20::class); - } - - $nonce = pack('N2', 0, $this->get_seq_no); - - $this->lengthDecrypt->setNonce($nonce); - $temp = $this->lengthDecrypt->decrypt($aad = Strings::shift($raw, 4)); - extract(unpack('Npacket_length', $temp)); - /** - * @var integer $packet_length - */ - - $raw .= $this->read_remaining_bytes($packet_length - $this->decrypt_block_size + 4); - $stop = microtime(true); - $tag = stream_get_contents($this->fsock, 16); - - $this->decrypt->setNonce($nonce); - $this->decrypt->setCounter(0); - // this is the same approach that's implemented in Salsa20::createPoly1305Key() - // but we don't want to use the same AEAD construction that RFC8439 describes - // for ChaCha20-Poly1305 so we won't rely on it (see Salsa20::poly1305()) - $this->decrypt->setPoly1305Key( - $this->decrypt->encrypt(str_repeat("\0", 32)) - ); - $this->decrypt->setAAD($aad); - $this->decrypt->setCounter(1); - $this->decrypt->setTag($tag); - $raw = $this->decrypt->decrypt($raw); - $raw = $temp . $raw; - $remaining_length = 0; - break; - default: - if (!$this->hmac_check instanceof Hash || !$this->hmac_check_etm) { - $raw = $this->decrypt->decrypt($raw); - break; - } - extract(unpack('Npacket_length', $temp = Strings::shift($raw, 4))); - /** - * @var integer $packet_length - */ - $raw .= $this->read_remaining_bytes($packet_length - $this->decrypt_block_size + 4); - $stop = microtime(true); - $encrypted = $temp . $raw; - $raw = $temp . $this->decrypt->decrypt($raw); - $remaining_length = 0; - } - } - - if (strlen($raw) < 5) { - $this->bitmap = 0; - throw new \RuntimeException('Plaintext is too short'); - } - extract(unpack('Npacket_length/Cpadding_length', Strings::shift($raw, 5))); - /** - * @var integer $packet_length - * @var integer $padding_length - */ - - if (!isset($remaining_length)) { - $remaining_length = $packet_length + 4 - $this->decrypt_block_size; - } - - $buffer = $this->read_remaining_bytes($remaining_length); - - if (!isset($stop)) { - $stop = microtime(true); - } - if (strlen($buffer)) { - $raw .= $this->decrypt ? $this->decrypt->decrypt($buffer) : $buffer; - } - - $payload = Strings::shift($raw, $packet_length - $padding_length - 1); - $padding = Strings::shift($raw, $padding_length); // should leave $raw empty - - if ($this->hmac_check instanceof Hash) { - $hmac = stream_get_contents($this->fsock, $this->hmac_size); - if ($hmac === false || strlen($hmac) != $this->hmac_size) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_MAC_ERROR); - throw new \RuntimeException('Error reading socket'); - } - - $reconstructed = !$this->hmac_check_etm ? - pack('NCa*', $packet_length, $padding_length, $payload . $padding) : - $encrypted; - if (($this->hmac_check->getHash() & "\xFF\xFF\xFF\xFF") == 'umac') { - $this->hmac_check->setNonce("\0\0\0\0" . pack('N', $this->get_seq_no)); - if ($hmac != $this->hmac_check->hash($reconstructed)) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_MAC_ERROR); - throw new \RuntimeException('Invalid UMAC'); - } - } else { - if ($hmac != $this->hmac_check->hash(pack('Na*', $this->get_seq_no, $reconstructed))) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_MAC_ERROR); - throw new \RuntimeException('Invalid HMAC'); - } - } - } - - switch ($this->decompress) { - case self::NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH: - if (!$this->isAuthenticated()) { - break; - } - // fall-through - case self::NET_SSH2_COMPRESSION_ZLIB: - if ($this->regenerate_decompression_context) { - $this->regenerate_decompression_context = false; - - $cmf = ord($payload[0]); - $cm = $cmf & 0x0F; - if ($cm != 8) { // deflate - user_error("Only CM = 8 ('deflate') is supported ($cm)"); - } - $cinfo = ($cmf & 0xF0) >> 4; - if ($cinfo > 7) { - user_error("CINFO above 7 is not allowed ($cinfo)"); - } - $windowSize = 1 << ($cinfo + 8); - - $flg = ord($payload[1]); - //$fcheck = $flg && 0x0F; - if ((($cmf << 8) | $flg) % 31) { - user_error('fcheck failed'); - } - $fdict = boolval($flg & 0x20); - $flevel = ($flg & 0xC0) >> 6; - - $this->decompress_context = inflate_init(ZLIB_ENCODING_RAW, ['window' => $cinfo + 8]); - $payload = substr($payload, 2); - } - if ($this->decompress_context) { - $payload = inflate_add($this->decompress_context, $payload, ZLIB_PARTIAL_FLUSH); - } - } - - $this->get_seq_no++; - - if (defined('NET_SSH2_LOGGING')) { - $current = microtime(true); - $message_number = isset($this->message_numbers[ord($payload[0])]) ? $this->message_numbers[ord($payload[0])] : 'UNKNOWN (' . ord($payload[0]) . ')'; - $message_number = '<- ' . $message_number . - ' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)'; - $this->append_log($message_number, $payload); - $this->last_packet = $current; - } - - return $this->filter($payload, $skip_channel_filter); - } - - /** - * Read Remaining Bytes - * - * @see self::get_binary_packet() - * @param int $remaining_length - * @return string - */ - private function read_remaining_bytes($remaining_length) - { - if (!$remaining_length) { - return ''; - } - - $adjustLength = false; - if ($this->decrypt) { - switch (true) { - case $this->decryptName == 'aes128-gcm@openssh.com': - case $this->decryptName == 'aes256-gcm@openssh.com': - case $this->decryptName == 'chacha20-poly1305@openssh.com': - case $this->hmac_check instanceof Hash && $this->hmac_check_etm: - $remaining_length += $this->decrypt_block_size - 4; - $adjustLength = true; - } - } - - // quoting , - // "implementations SHOULD check that the packet length is reasonable" - // PuTTY uses 0x9000 as the actual max packet size and so to shall we - // don't do this when GCM mode is used since GCM mode doesn't encrypt the length - if ($remaining_length < -$this->decrypt_block_size || $remaining_length > 0x9000 || $remaining_length % $this->decrypt_block_size != 0) { - if (!$this->bad_key_size_fix && self::bad_algorithm_candidate($this->decrypt ? $this->decryptName : '') && !($this->bitmap & SSH2::MASK_LOGIN)) { - $this->bad_key_size_fix = true; - $this->reset_connection(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - return false; - } - throw new \RuntimeException('Invalid size'); - } - - if ($adjustLength) { - $remaining_length -= $this->decrypt_block_size - 4; - } - - $buffer = ''; - while ($remaining_length > 0) { - $temp = stream_get_contents($this->fsock, $remaining_length); - if ($temp === false || feof($this->fsock)) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_CONNECTION_LOST); - throw new \RuntimeException('Error reading from socket'); - } - $buffer .= $temp; - $remaining_length -= strlen($temp); - } - - return $buffer; - } - - /** - * Filter Binary Packets - * - * Because some binary packets need to be ignored... - * - * @see self::_get_binary_packet() - * @param string $payload - * @param bool $skip_channel_filter - * @return string|bool - */ - private function filter($payload, $skip_channel_filter) - { - switch (ord($payload[0])) { - case NET_SSH2_MSG_DISCONNECT: - Strings::shift($payload, 1); - list($reason_code, $message) = Strings::unpackSSH2('Ns', $payload); - $this->errors[] = 'SSH_MSG_DISCONNECT: ' . $this->disconnect_reasons[$reason_code] . "\r\n$message"; - $this->bitmap = 0; - return false; - case NET_SSH2_MSG_IGNORE: - $payload = $this->get_binary_packet($skip_channel_filter); - break; - case NET_SSH2_MSG_DEBUG: - Strings::shift($payload, 2); // second byte is "always_display" - list($message) = Strings::unpackSSH2('s', $payload); - $this->errors[] = "SSH_MSG_DEBUG: $message"; - $payload = $this->get_binary_packet($skip_channel_filter); - break; - case NET_SSH2_MSG_UNIMPLEMENTED: - return false; - case NET_SSH2_MSG_KEXINIT: - if ($this->session_id !== false) { - if (!$this->key_exchange($payload)) { - $this->bitmap = 0; - return false; - } - $payload = $this->get_binary_packet($skip_channel_filter); - } - } - - // see http://tools.ietf.org/html/rfc4252#section-5.4; only called when the encryption has been activated and when we haven't already logged in - if (($this->bitmap & self::MASK_CONNECTED) && !$this->isAuthenticated() && !is_bool($payload) && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER) { - Strings::shift($payload, 1); - list($this->banner_message) = Strings::unpackSSH2('s', $payload); - $payload = $this->get_binary_packet(); - } - - // only called when we've already logged in - if (($this->bitmap & self::MASK_CONNECTED) && $this->isAuthenticated()) { - if (is_bool($payload)) { - return $payload; - } - - switch (ord($payload[0])) { - case NET_SSH2_MSG_CHANNEL_REQUEST: - if (strlen($payload) == 31) { - extract(unpack('cpacket_type/Nchannel/Nlength', $payload)); - if (substr($payload, 9, $length) == 'keepalive@openssh.com' && isset($this->server_channels[$channel])) { - if (ord(substr($payload, 9 + $length))) { // want reply - $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_SUCCESS, $this->server_channels[$channel])); - } - $payload = $this->get_binary_packet($skip_channel_filter); - } - } - break; - case NET_SSH2_MSG_CHANNEL_DATA: - case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA: - case NET_SSH2_MSG_CHANNEL_CLOSE: - case NET_SSH2_MSG_CHANNEL_EOF: - if (!$skip_channel_filter && !empty($this->server_channels)) { - $this->binary_packet_buffer = $payload; - $this->get_channel_packet(true); - $payload = $this->get_binary_packet(); - } - break; - case NET_SSH2_MSG_GLOBAL_REQUEST: // see http://tools.ietf.org/html/rfc4254#section-4 - Strings::shift($payload, 1); - list($request_name) = Strings::unpackSSH2('s', $payload); - $this->errors[] = "SSH_MSG_GLOBAL_REQUEST: $request_name"; - - try { - $this->send_binary_packet(pack('C', NET_SSH2_MSG_REQUEST_FAILURE)); - } catch (\RuntimeException $e) { - return $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION); - } - - $payload = $this->get_binary_packet($skip_channel_filter); - break; - case NET_SSH2_MSG_CHANNEL_OPEN: // see http://tools.ietf.org/html/rfc4254#section-5.1 - Strings::shift($payload, 1); - list($data, $server_channel) = Strings::unpackSSH2('sN', $payload); - switch ($data) { - case 'auth-agent': - case 'auth-agent@openssh.com': - if (isset($this->agent)) { - $new_channel = self::CHANNEL_AGENT_FORWARD; - - list( - $remote_window_size, - $remote_maximum_packet_size - ) = Strings::unpackSSH2('NN', $payload); - - $this->packet_size_client_to_server[$new_channel] = $remote_window_size; - $this->window_size_server_to_client[$new_channel] = $remote_maximum_packet_size; - $this->window_size_client_to_server[$new_channel] = $this->window_size; - - $packet_size = 0x4000; - - $packet = pack( - 'CN4', - NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, - $server_channel, - $new_channel, - $packet_size, - $packet_size - ); - - $this->server_channels[$new_channel] = $server_channel; - $this->channel_status[$new_channel] = NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION; - $this->send_binary_packet($packet); - } - break; - default: - $packet = Strings::packSSH2( - 'CN2ss', - NET_SSH2_MSG_CHANNEL_OPEN_FAILURE, - $server_channel, - NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED, - '', // description - '' // language tag - ); - - try { - $this->send_binary_packet($packet); - } catch (\RuntimeException $e) { - return $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION); - } - } - - $payload = $this->get_binary_packet($skip_channel_filter); - break; - case NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST: - Strings::shift($payload, 1); - list($channel, $window_size) = Strings::unpackSSH2('NN', $payload); - - $this->window_size_client_to_server[$channel] += $window_size; - - $payload = ($this->bitmap & self::MASK_WINDOW_ADJUST) ? true : $this->get_binary_packet($skip_channel_filter); - } - } - - return $payload; - } - - /** - * Enable Quiet Mode - * - * Suppress stderr from output - * - */ - public function enableQuietMode() - { - $this->quiet_mode = true; - } - - /** - * Disable Quiet Mode - * - * Show stderr in output - * - */ - public function disableQuietMode() - { - $this->quiet_mode = false; - } - - /** - * Returns whether Quiet Mode is enabled or not - * - * @see self::enableQuietMode() - * @see self::disableQuietMode() - * @return bool - */ - public function isQuietModeEnabled() - { - return $this->quiet_mode; - } - - /** - * Enable request-pty when using exec() - * - */ - public function enablePTY() - { - $this->request_pty = true; - } - - /** - * Disable request-pty when using exec() - * - */ - public function disablePTY() - { - if ($this->in_request_pty_exec) { - $this->close_channel(self::CHANNEL_EXEC); - $this->in_request_pty_exec = false; - } - $this->request_pty = false; - } - - /** - * Returns whether request-pty is enabled or not - * - * @see self::enablePTY() - * @see self::disablePTY() - * @return bool - */ - public function isPTYEnabled() - { - return $this->request_pty; - } - - /** - * Gets channel data - * - * Returns the data as a string. bool(true) is returned if: - * - * - the server closes the channel - * - if the connection times out - * - if the channel status is CHANNEL_OPEN and the response was CHANNEL_OPEN_CONFIRMATION - * - if the channel status is CHANNEL_REQUEST and the response was CHANNEL_SUCCESS - * - * bool(false) is returned if: - * - * - if the channel status is CHANNEL_REQUEST and the response was CHANNEL_FAILURE - * - * @param int $client_channel - * @param bool $skip_extended - * @return mixed - * @throws \RuntimeException on connection error - */ - protected function get_channel_packet($client_channel, $skip_extended = false) - { - if (!empty($this->channel_buffers[$client_channel])) { - switch ($this->channel_status[$client_channel]) { - case NET_SSH2_MSG_CHANNEL_REQUEST: - foreach ($this->channel_buffers[$client_channel] as $i => $packet) { - switch (ord($packet[0])) { - case NET_SSH2_MSG_CHANNEL_SUCCESS: - case NET_SSH2_MSG_CHANNEL_FAILURE: - unset($this->channel_buffers[$client_channel][$i]); - return substr($packet, 1); - } - } - break; - default: - return substr(array_shift($this->channel_buffers[$client_channel]), 1); - } - } - - while (true) { - if ($this->binary_packet_buffer !== false) { - $response = $this->binary_packet_buffer; - $this->binary_packet_buffer = false; - } else { - $response = $this->get_binary_packet(true); - if ($response === true && $this->is_timeout) { - if ($client_channel == self::CHANNEL_EXEC && !$this->request_pty) { - $this->close_channel($client_channel); - } - return true; - } - if ($response === false) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_CONNECTION_LOST); - throw new ConnectionClosedException('Connection closed by server'); - } - } - - if ($client_channel == -1 && $response === true) { - return true; - } - list($type, $channel) = Strings::unpackSSH2('CN', $response); - - // will not be setup yet on incoming channel open request - if (isset($channel) && isset($this->channel_status[$channel]) && isset($this->window_size_server_to_client[$channel])) { - $this->window_size_server_to_client[$channel] -= strlen($response); - - // resize the window, if appropriate - if ($this->window_size_server_to_client[$channel] < 0) { - // PuTTY does something more analogous to the following: - //if ($this->window_size_server_to_client[$channel] < 0x3FFFFFFF) { - $packet = pack('CNN', NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST, $this->server_channels[$channel], $this->window_resize); - $this->send_binary_packet($packet); - $this->window_size_server_to_client[$channel] += $this->window_resize; - } - - switch ($type) { - case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA: - /* - if ($client_channel == self::CHANNEL_EXEC) { - $this->send_channel_packet($client_channel, chr(0)); - } - */ - // currently, there's only one possible value for $data_type_code: NET_SSH2_EXTENDED_DATA_STDERR - list($data_type_code, $data) = Strings::unpackSSH2('Ns', $response); - $this->stdErrorLog .= $data; - if ($skip_extended || $this->quiet_mode) { - continue 2; - } - if ($client_channel == $channel && $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_DATA) { - return $data; - } - $this->channel_buffers[$channel][] = chr($type) . $data; - - continue 2; - case NET_SSH2_MSG_CHANNEL_REQUEST: - if ($this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_CLOSE) { - continue 2; - } - list($value) = Strings::unpackSSH2('s', $response); - switch ($value) { - case 'exit-signal': - list( - , // FALSE - $signal_name, - , // core dumped - $error_message - ) = Strings::unpackSSH2('bsbs', $response); - - $this->errors[] = "SSH_MSG_CHANNEL_REQUEST (exit-signal): $signal_name"; - if (strlen($error_message)) { - $this->errors[count($this->errors) - 1] .= "\r\n$error_message"; - } - - $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel])); - $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel])); - - $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_EOF; - - continue 3; - case 'exit-status': - list(, $this->exit_status) = Strings::unpackSSH2('CN', $response); - - // "The client MAY ignore these messages." - // -- http://tools.ietf.org/html/rfc4254#section-6.10 - - continue 3; - default: - // "Some systems may not implement signals, in which case they SHOULD ignore this message." - // -- http://tools.ietf.org/html/rfc4254#section-6.9 - continue 3; - } - } - - switch ($this->channel_status[$channel]) { - case NET_SSH2_MSG_CHANNEL_OPEN: - switch ($type) { - case NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: - list( - $this->server_channels[$channel], - $window_size, - $this->packet_size_client_to_server[$channel] - ) = Strings::unpackSSH2('NNN', $response); - - if ($window_size < 0) { - $window_size &= 0x7FFFFFFF; - $window_size += 0x80000000; - } - $this->window_size_client_to_server[$channel] = $window_size; - $result = $client_channel == $channel ? true : $this->get_channel_packet($client_channel, $skip_extended); - $this->on_channel_open(); - return $result; - case NET_SSH2_MSG_CHANNEL_OPEN_FAILURE: - $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION); - throw new \RuntimeException('Unable to open channel'); - default: - if ($client_channel == $channel) { - $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION); - throw new \RuntimeException('Unexpected response to open request'); - } - return $this->get_channel_packet($client_channel, $skip_extended); - } - break; - case NET_SSH2_MSG_CHANNEL_REQUEST: - switch ($type) { - case NET_SSH2_MSG_CHANNEL_SUCCESS: - return true; - case NET_SSH2_MSG_CHANNEL_FAILURE: - return false; - case NET_SSH2_MSG_CHANNEL_DATA: - list($data) = Strings::unpackSSH2('s', $response); - $this->channel_buffers[$channel][] = chr($type) . $data; - return $this->get_channel_packet($client_channel, $skip_extended); - default: - $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION); - throw new \RuntimeException('Unable to fulfill channel request'); - } - case NET_SSH2_MSG_CHANNEL_CLOSE: - return $type == NET_SSH2_MSG_CHANNEL_CLOSE ? true : $this->get_channel_packet($client_channel, $skip_extended); - } - } - - // ie. $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_DATA - - switch ($type) { - case NET_SSH2_MSG_CHANNEL_DATA: - /* - if ($channel == self::CHANNEL_EXEC) { - // SCP requires null packets, such as this, be sent. further, in the case of the ssh.com SSH server - // this actually seems to make things twice as fast. more to the point, the message right after - // SSH_MSG_CHANNEL_DATA (usually SSH_MSG_IGNORE) won't block for as long as it would have otherwise. - // in OpenSSH it slows things down but only by a couple thousandths of a second. - $this->send_channel_packet($channel, chr(0)); - } - */ - list($data) = Strings::unpackSSH2('s', $response); - - if ($channel == self::CHANNEL_AGENT_FORWARD) { - $agent_response = $this->agent->forwardData($data); - if (!is_bool($agent_response)) { - $this->send_channel_packet($channel, $agent_response); - } - break; - } - - if ($client_channel == $channel) { - return $data; - } - $this->channel_buffers[$channel][] = chr($type) . $data; - break; - case NET_SSH2_MSG_CHANNEL_CLOSE: - $this->curTimeout = 5; - - if ($this->bitmap & self::MASK_SHELL) { - $this->bitmap &= ~self::MASK_SHELL; - } - if ($this->channel_status[$channel] != NET_SSH2_MSG_CHANNEL_EOF) { - $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel])); - } - - $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_CLOSE; - if ($client_channel == $channel) { - return true; - } - // fall-through - case NET_SSH2_MSG_CHANNEL_EOF: - break; - default: - $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION); - throw new \RuntimeException("Error reading channel data ($type)"); - } - } - } - - /** - * Sends Binary Packets - * - * See '6. Binary Packet Protocol' of rfc4253 for more info. - * - * @param string $data - * @param string $logged - * @see self::_get_binary_packet() - * @return void - */ - protected function send_binary_packet($data, $logged = null) - { - if (!is_resource($this->fsock) || feof($this->fsock)) { - $this->bitmap = 0; - throw new ConnectionClosedException('Connection closed prematurely'); - } - - if (!isset($logged)) { - $logged = $data; - } - - switch ($this->compress) { - case self::NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH: - if (!$this->isAuthenticated()) { - break; - } - // fall-through - case self::NET_SSH2_COMPRESSION_ZLIB: - if (!$this->regenerate_compression_context) { - $header = ''; - } else { - $this->regenerate_compression_context = false; - $this->compress_context = deflate_init(ZLIB_ENCODING_RAW, ['window' => 15]); - $header = "\x78\x9C"; - } - if ($this->compress_context) { - $data = $header . deflate_add($this->compress_context, $data, ZLIB_PARTIAL_FLUSH); - } - } - - // 4 (packet length) + 1 (padding length) + 4 (minimal padding amount) == 9 - $packet_length = strlen($data) + 9; - if ($this->encrypt && $this->encrypt->usesNonce()) { - $packet_length -= 4; - } - // round up to the nearest $this->encrypt_block_size - $packet_length += (($this->encrypt_block_size - 1) * $packet_length) % $this->encrypt_block_size; - // subtracting strlen($data) is obvious - subtracting 5 is necessary because of packet_length and padding_length - $padding_length = $packet_length - strlen($data) - 5; - switch (true) { - case $this->encrypt && $this->encrypt->usesNonce(): - case $this->hmac_create instanceof Hash && $this->hmac_create_etm: - $padding_length += 4; - $packet_length += 4; - } - - $padding = Random::string($padding_length); - - // we subtract 4 from packet_length because the packet_length field isn't supposed to include itself - $packet = pack('NCa*', $packet_length - 4, $padding_length, $data . $padding); - - $hmac = ''; - if ($this->hmac_create instanceof Hash && !$this->hmac_create_etm) { - if (($this->hmac_create->getHash() & "\xFF\xFF\xFF\xFF") == 'umac') { - $this->hmac_create->setNonce("\0\0\0\0" . pack('N', $this->send_seq_no)); - $hmac = $this->hmac_create->hash($packet); - } else { - $hmac = $this->hmac_create->hash(pack('Na*', $this->send_seq_no, $packet)); - } - } - - if ($this->encrypt) { - switch ($this->encryptName) { - case 'aes128-gcm@openssh.com': - case 'aes256-gcm@openssh.com': - $this->encrypt->setNonce( - $this->encryptFixedPart . - $this->encryptInvocationCounter - ); - Strings::increment_str($this->encryptInvocationCounter); - $this->encrypt->setAAD($temp = ($packet & "\xFF\xFF\xFF\xFF")); - $packet = $temp . $this->encrypt->encrypt(substr($packet, 4)); - break; - case 'chacha20-poly1305@openssh.com': - // This should be impossible, but we are checking anyway to narrow the type for Psalm. - if (!($this->encrypt instanceof ChaCha20)) { - throw new \LogicException('$this->encrypt is not a ' . ChaCha20::class); - } - - $nonce = pack('N2', 0, $this->send_seq_no); - - $this->encrypt->setNonce($nonce); - $this->lengthEncrypt->setNonce($nonce); - - $length = $this->lengthEncrypt->encrypt($packet & "\xFF\xFF\xFF\xFF"); - - $this->encrypt->setCounter(0); - // this is the same approach that's implemented in Salsa20::createPoly1305Key() - // but we don't want to use the same AEAD construction that RFC8439 describes - // for ChaCha20-Poly1305 so we won't rely on it (see Salsa20::poly1305()) - $this->encrypt->setPoly1305Key( - $this->encrypt->encrypt(str_repeat("\0", 32)) - ); - $this->encrypt->setAAD($length); - $this->encrypt->setCounter(1); - $packet = $length . $this->encrypt->encrypt(substr($packet, 4)); - break; - default: - $packet = $this->hmac_create instanceof Hash && $this->hmac_create_etm ? - ($packet & "\xFF\xFF\xFF\xFF") . $this->encrypt->encrypt(substr($packet, 4)) : - $this->encrypt->encrypt($packet); - } - } - - if ($this->hmac_create instanceof Hash && $this->hmac_create_etm) { - if (($this->hmac_create->getHash() & "\xFF\xFF\xFF\xFF") == 'umac') { - $this->hmac_create->setNonce("\0\0\0\0" . pack('N', $this->send_seq_no)); - $hmac = $this->hmac_create->hash($packet); - } else { - $hmac = $this->hmac_create->hash(pack('Na*', $this->send_seq_no, $packet)); - } - } - - $this->send_seq_no++; - - $packet .= $this->encrypt && $this->encrypt->usesNonce() ? $this->encrypt->getTag() : $hmac; - - $start = microtime(true); - $sent = @fputs($this->fsock, $packet); - $stop = microtime(true); - - if (defined('NET_SSH2_LOGGING')) { - $current = microtime(true); - $message_number = isset($this->message_numbers[ord($logged[0])]) ? $this->message_numbers[ord($logged[0])] : 'UNKNOWN (' . ord($logged[0]) . ')'; - $message_number = '-> ' . $message_number . - ' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)'; - $this->append_log($message_number, $logged); - $this->last_packet = $current; - } - - if (strlen($packet) != $sent) { - $this->bitmap = 0; - throw new \RuntimeException("Only $sent of " . strlen($packet) . " bytes were sent"); - } - } - - /** - * Logs data packets - * - * Makes sure that only the last 1MB worth of packets will be logged - * - * @param string $message_number - * @param string $message - */ - private function append_log($message_number, $message) - { - $this->append_log_helper( - NET_SSH2_LOGGING, - $message_number, - $message, - $this->message_number_log, - $this->message_log, - $this->log_size, - $this->realtime_log_file, - $this->realtime_log_wrap, - $this->realtime_log_size - ); - } - - /** - * Logs data packet helper - * - * @param int $constant - * @param string $message_number - * @param string $message - * @param array &$message_number_log - * @param array &$message_log - * @param int &$log_size - * @param resource &$realtime_log_file - * @param bool &$realtime_log_wrap - * @param int &$realtime_log_size - */ - protected function append_log_helper($constant, $message_number, $message, array &$message_number_log, array &$message_log, &$log_size, &$realtime_log_file, &$realtime_log_wrap, &$realtime_log_size) - { - // remove the byte identifying the message type from all but the first two messages (ie. the identification strings) - if (strlen($message_number) > 2) { - Strings::shift($message); - } - - switch ($constant) { - // useful for benchmarks - case self::LOG_SIMPLE: - $message_number_log[] = $message_number; - break; - case self::LOG_SIMPLE_REALTIME: - echo $message_number; - echo PHP_SAPI == 'cli' ? "\r\n" : '
'; - @flush(); - @ob_flush(); - break; - // the most useful log for SSH2 - case self::LOG_COMPLEX: - $message_number_log[] = $message_number; - $log_size += strlen($message); - $message_log[] = $message; - while ($log_size > self::LOG_MAX_SIZE) { - $log_size -= strlen(array_shift($message_log)); - array_shift($message_number_log); - } - break; - // dump the output out realtime; packets may be interspersed with non packets, - // passwords won't be filtered out and select other packets may not be correctly - // identified - case self::LOG_REALTIME: - switch (PHP_SAPI) { - case 'cli': - $start = $stop = "\r\n"; - break; - default: - $start = '
';
-                        $stop = '
'; - } - echo $start . $this->format_log([$message], [$message_number]) . $stop; - @flush(); - @ob_flush(); - break; - // basically the same thing as self::LOG_REALTIME with the caveat that NET_SSH2_LOG_REALTIME_FILENAME - // needs to be defined and that the resultant log file will be capped out at self::LOG_MAX_SIZE. - // the earliest part of the log file is denoted by the first <<< START >>> and is not going to necessarily - // at the beginning of the file - case self::LOG_REALTIME_FILE: - if (!isset($realtime_log_file)) { - // PHP doesn't seem to like using constants in fopen() - $filename = NET_SSH2_LOG_REALTIME_FILENAME; - $fp = fopen($filename, 'w'); - $realtime_log_file = $fp; - } - if (!is_resource($realtime_log_file)) { - break; - } - $entry = $this->format_log([$message], [$message_number]); - if ($realtime_log_wrap) { - $temp = "<<< START >>>\r\n"; - $entry .= $temp; - fseek($realtime_log_file, ftell($realtime_log_file) - strlen($temp)); - } - $realtime_log_size += strlen($entry); - if ($realtime_log_size > self::LOG_MAX_SIZE) { - fseek($realtime_log_file, 0); - $realtime_log_size = strlen($entry); - $realtime_log_wrap = true; - } - fputs($realtime_log_file, $entry); - } - } - - /** - * Sends channel data - * - * Spans multiple SSH_MSG_CHANNEL_DATAs if appropriate - * - * @param int $client_channel - * @param string $data - * @return void - */ - protected function send_channel_packet($client_channel, $data) - { - while (strlen($data)) { - if (!$this->window_size_client_to_server[$client_channel]) { - $this->bitmap ^= self::MASK_WINDOW_ADJUST; - // using an invalid channel will let the buffers be built up for the valid channels - $this->get_channel_packet(-1); - $this->bitmap ^= self::MASK_WINDOW_ADJUST; - } - - /* The maximum amount of data allowed is determined by the maximum - packet size for the channel, and the current window size, whichever - is smaller. - -- http://tools.ietf.org/html/rfc4254#section-5.2 */ - $max_size = min( - $this->packet_size_client_to_server[$client_channel], - $this->window_size_client_to_server[$client_channel] - ); - - $temp = Strings::shift($data, $max_size); - $packet = Strings::packSSH2( - 'CNs', - NET_SSH2_MSG_CHANNEL_DATA, - $this->server_channels[$client_channel], - $temp - ); - $this->window_size_client_to_server[$client_channel] -= strlen($temp); - $this->send_binary_packet($packet); - } - } - - /** - * Closes and flushes a channel - * - * \phpseclib3\Net\SSH2 doesn't properly close most channels. For exec() channels are normally closed by the server - * and for SFTP channels are presumably closed when the client disconnects. This functions is intended - * for SCP more than anything. - * - * @param int $client_channel - * @param bool $want_reply - * @return void - */ - private function close_channel($client_channel, $want_reply = false) - { - // see http://tools.ietf.org/html/rfc4254#section-5.3 - - $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel])); - - if (!$want_reply) { - $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel])); - } - - $this->channel_status[$client_channel] = NET_SSH2_MSG_CHANNEL_CLOSE; - - $this->curTimeout = 5; - - while (!is_bool($this->get_channel_packet($client_channel))) { - } - - if ($this->is_timeout) { - $this->disconnect(); - } - - if ($want_reply) { - $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel])); - } - - if ($this->bitmap & self::MASK_SHELL) { - $this->bitmap &= ~self::MASK_SHELL; - } - } - - /** - * Disconnect - * - * @param int $reason - * @return false - */ - protected function disconnect_helper($reason) - { - if ($this->bitmap & self::MASK_CONNECTED) { - $data = Strings::packSSH2('CNss', NET_SSH2_MSG_DISCONNECT, $reason, '', ''); - try { - $this->send_binary_packet($data); - } catch (\Exception $e) { - } - } - - $this->bitmap = 0; - if (is_resource($this->fsock) && get_resource_type($this->fsock) === 'stream') { - fclose($this->fsock); - } - - return false; - } - - /** - * Define Array - * - * Takes any number of arrays whose indices are integers and whose values are strings and defines a bunch of - * named constants from it, using the value as the name of the constant and the index as the value of the constant. - * If any of the constants that would be defined already exists, none of the constants will be defined. - * - * @param mixed[] ...$args - * @access protected - */ - protected function define_array(...$args) - { - foreach ($args as $arg) { - foreach ($arg as $key => $value) { - if (!defined($value)) { - define($value, $key); - } else { - break 2; - } - } - } - } - - /** - * Returns a log of the packets that have been sent and received. - * - * Returns a string if NET_SSH2_LOGGING == self::LOG_COMPLEX, an array if NET_SSH2_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SSH2_LOGGING') - * - * @return array|false|string - */ - public function getLog() - { - if (!defined('NET_SSH2_LOGGING')) { - return false; - } - - switch (NET_SSH2_LOGGING) { - case self::LOG_SIMPLE: - return $this->message_number_log; - case self::LOG_COMPLEX: - $log = $this->format_log($this->message_log, $this->message_number_log); - return PHP_SAPI == 'cli' ? $log : '
' . $log . '
'; - default: - return false; - } - } - - /** - * Formats a log for printing - * - * @param array $message_log - * @param array $message_number_log - * @return string - */ - protected function format_log(array $message_log, array $message_number_log) - { - $output = ''; - for ($i = 0; $i < count($message_log); $i++) { - $output .= $message_number_log[$i] . "\r\n"; - $current_log = $message_log[$i]; - $j = 0; - do { - if (strlen($current_log)) { - $output .= str_pad(dechex($j), 7, '0', STR_PAD_LEFT) . '0 '; - } - $fragment = Strings::shift($current_log, $this->log_short_width); - $hex = substr(preg_replace_callback('#.#s', function ($matches) { - return $this->log_boundary . str_pad(dechex(ord($matches[0])), 2, '0', STR_PAD_LEFT); - }, $fragment), strlen($this->log_boundary)); - // replace non ASCII printable characters with dots - // http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters - // also replace < with a . since < messes up the output on web browsers - $raw = preg_replace('#[^\x20-\x7E]|<#', '.', $fragment); - $output .= str_pad($hex, $this->log_long_width - $this->log_short_width, ' ') . $raw . "\r\n"; - $j++; - } while (strlen($current_log)); - $output .= "\r\n"; - } - - return $output; - } - - /** - * Helper function for agent->on_channel_open() - * - * Used when channels are created to inform agent - * of said channel opening. Must be called after - * channel open confirmation received - * - */ - private function on_channel_open() - { - if (isset($this->agent)) { - $this->agent->registerChannelOpen($this); - } - } - - /** - * Returns the first value of the intersection of two arrays or false if - * the intersection is empty. The order is defined by the first parameter. - * - * @param array $array1 - * @param array $array2 - * @return mixed False if intersection is empty, else intersected value. - */ - private static function array_intersect_first(array $array1, array $array2) - { - foreach ($array1 as $value) { - if (in_array($value, $array2)) { - return $value; - } - } - return false; - } - - /** - * Returns all errors - * - * @return string[] - */ - public function getErrors() - { - return $this->errors; - } - - /** - * Returns the last error - * - * @return string - */ - public function getLastError() - { - $count = count($this->errors); - - if ($count > 0) { - return $this->errors[$count - 1]; - } - } - - /** - * Return the server identification. - * - * @return string|false - */ - public function getServerIdentification() - { - $this->connect(); - - return $this->server_identifier; - } - - /** - * Returns a list of algorithms the server supports - * - * @return array - */ - public function getServerAlgorithms() - { - $this->connect(); - - return [ - 'kex' => $this->kex_algorithms, - 'hostkey' => $this->server_host_key_algorithms, - 'client_to_server' => [ - 'crypt' => $this->encryption_algorithms_client_to_server, - 'mac' => $this->mac_algorithms_client_to_server, - 'comp' => $this->compression_algorithms_client_to_server, - 'lang' => $this->languages_client_to_server - ], - 'server_to_client' => [ - 'crypt' => $this->encryption_algorithms_server_to_client, - 'mac' => $this->mac_algorithms_server_to_client, - 'comp' => $this->compression_algorithms_server_to_client, - 'lang' => $this->languages_server_to_client - ] - ]; - } - - /** - * Returns a list of KEX algorithms that phpseclib supports - * - * @return array - */ - public static function getSupportedKEXAlgorithms() - { - $kex_algorithms = [ - // Elliptic Curve Diffie-Hellman Key Agreement (ECDH) using - // Curve25519. See doc/curve25519-sha256@libssh.org.txt in the - // libssh repository for more information. - 'curve25519-sha256', - 'curve25519-sha256@libssh.org', - - 'ecdh-sha2-nistp256', // RFC 5656 - 'ecdh-sha2-nistp384', // RFC 5656 - 'ecdh-sha2-nistp521', // RFC 5656 - - 'diffie-hellman-group-exchange-sha256',// RFC 4419 - 'diffie-hellman-group-exchange-sha1', // RFC 4419 - - // Diffie-Hellman Key Agreement (DH) using integer modulo prime - // groups. - 'diffie-hellman-group14-sha256', - 'diffie-hellman-group14-sha1', // REQUIRED - 'diffie-hellman-group15-sha512', - 'diffie-hellman-group16-sha512', - 'diffie-hellman-group17-sha512', - 'diffie-hellman-group18-sha512', - - 'diffie-hellman-group1-sha1', // REQUIRED - ]; - - return $kex_algorithms; - } - - /** - * Returns a list of host key algorithms that phpseclib supports - * - * @return array - */ - public static function getSupportedHostKeyAlgorithms() - { - return [ - 'ssh-ed25519', // https://tools.ietf.org/html/draft-ietf-curdle-ssh-ed25519-02 - 'ecdsa-sha2-nistp256', // RFC 5656 - 'ecdsa-sha2-nistp384', // RFC 5656 - 'ecdsa-sha2-nistp521', // RFC 5656 - 'rsa-sha2-256', // RFC 8332 - 'rsa-sha2-512', // RFC 8332 - 'ssh-rsa', // RECOMMENDED sign Raw RSA Key - 'ssh-dss' // REQUIRED sign Raw DSS Key - ]; - } - - /** - * Returns a list of symmetric key algorithms that phpseclib supports - * - * @return array - */ - public static function getSupportedEncryptionAlgorithms() - { - $algos = [ - // from : - 'aes128-gcm@openssh.com', - 'aes256-gcm@openssh.com', - - // from : - 'arcfour256', - 'arcfour128', - - //'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key - - // CTR modes from : - 'aes128-ctr', // RECOMMENDED AES (Rijndael) in SDCTR mode, with 128-bit key - 'aes192-ctr', // RECOMMENDED AES with 192-bit key - 'aes256-ctr', // RECOMMENDED AES with 256-bit key - - // from : - // one of the big benefits of chacha20-poly1305 is speed. the problem is... - // libsodium doesn't generate the poly1305 keys in the way ssh does and openssl's PHP bindings don't even - // seem to support poly1305 currently. so even if libsodium or openssl are being used for the chacha20 - // part, pure-PHP has to be used for the poly1305 part and that's gonna cause a big slow down. - // speed-wise it winds up being faster to use AES (when openssl or mcrypt are available) and some HMAC - // (which is always gonna be super fast to compute thanks to the hash extension, which - // "is bundled and compiled into PHP by default") - 'chacha20-poly1305@openssh.com', - - 'twofish128-ctr', // OPTIONAL Twofish in SDCTR mode, with 128-bit key - 'twofish192-ctr', // OPTIONAL Twofish with 192-bit key - 'twofish256-ctr', // OPTIONAL Twofish with 256-bit key - - 'aes128-cbc', // RECOMMENDED AES with a 128-bit key - 'aes192-cbc', // OPTIONAL AES with a 192-bit key - 'aes256-cbc', // OPTIONAL AES in CBC mode, with a 256-bit key - - 'twofish128-cbc', // OPTIONAL Twofish with a 128-bit key - 'twofish192-cbc', // OPTIONAL Twofish with a 192-bit key - 'twofish256-cbc', - 'twofish-cbc', // OPTIONAL alias for "twofish256-cbc" - // (this is being retained for historical reasons) - - 'blowfish-ctr', // OPTIONAL Blowfish in SDCTR mode - - 'blowfish-cbc', // OPTIONAL Blowfish in CBC mode - - '3des-ctr', // RECOMMENDED Three-key 3DES in SDCTR mode - - '3des-cbc', // REQUIRED three-key 3DES in CBC mode - - //'none' // OPTIONAL no encryption; NOT RECOMMENDED - ]; - - if (self::$crypto_engine) { - $engines = [self::$crypto_engine]; - } else { - $engines = [ - 'libsodium', - 'OpenSSL (GCM)', - 'OpenSSL', - 'mcrypt', - 'Eval', - 'PHP' - ]; - } - - $ciphers = []; - - foreach ($engines as $engine) { - foreach ($algos as $algo) { - $obj = self::encryption_algorithm_to_crypt_instance($algo); - if ($obj instanceof Rijndael) { - $obj->setKeyLength(preg_replace('#[^\d]#', '', $algo)); - } - switch ($algo) { - case 'chacha20-poly1305@openssh.com': - case 'arcfour128': - case 'arcfour256': - if ($engine != 'Eval') { - continue 2; - } - break; - case 'aes128-gcm@openssh.com': - case 'aes256-gcm@openssh.com': - if ($engine == 'OpenSSL') { - continue 2; - } - $obj->setNonce('dummydummydu'); - } - if ($obj->isValidEngine($engine)) { - $algos = array_diff($algos, [$algo]); - $ciphers[] = $algo; - } - } - } - - return $ciphers; - } - - /** - * Returns a list of MAC algorithms that phpseclib supports - * - * @return array - */ - public static function getSupportedMACAlgorithms() - { - return [ - 'hmac-sha2-256-etm@openssh.com', - 'hmac-sha2-512-etm@openssh.com', - 'umac-64-etm@openssh.com', - 'umac-128-etm@openssh.com', - 'hmac-sha1-etm@openssh.com', - - // from : - 'hmac-sha2-256',// RECOMMENDED HMAC-SHA256 (digest length = key length = 32) - 'hmac-sha2-512',// OPTIONAL HMAC-SHA512 (digest length = key length = 64) - - // from : - 'umac-64@openssh.com', - 'umac-128@openssh.com', - - 'hmac-sha1-96', // RECOMMENDED first 96 bits of HMAC-SHA1 (digest length = 12, key length = 20) - 'hmac-sha1', // REQUIRED HMAC-SHA1 (digest length = key length = 20) - 'hmac-md5-96', // OPTIONAL first 96 bits of HMAC-MD5 (digest length = 12, key length = 16) - 'hmac-md5', // OPTIONAL HMAC-MD5 (digest length = key length = 16) - //'none' // OPTIONAL no MAC; NOT RECOMMENDED - ]; - } - - /** - * Returns a list of compression algorithms that phpseclib supports - * - * @return array - */ - public static function getSupportedCompressionAlgorithms() - { - $algos = ['none']; // REQUIRED no compression - if (function_exists('deflate_init')) { - $algos[] = 'zlib@openssh.com'; // https://datatracker.ietf.org/doc/html/draft-miller-secsh-compression-delayed - $algos[] = 'zlib'; - } - return $algos; - } - - /** - * Return list of negotiated algorithms - * - * Uses the same format as https://www.php.net/ssh2-methods-negotiated - * - * @return array - */ - public function getAlgorithmsNegotiated() - { - $this->connect(); - - $compression_map = [ - self::NET_SSH2_COMPRESSION_NONE => 'none', - self::NET_SSH2_COMPRESSION_ZLIB => 'zlib', - self::NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH => 'zlib@openssh.com' - ]; - - return [ - 'kex' => $this->kex_algorithm, - 'hostkey' => $this->signature_format, - 'client_to_server' => [ - 'crypt' => $this->encryptName, - 'mac' => $this->hmac_create_name, - 'comp' => $compression_map[$this->compress], - ], - 'server_to_client' => [ - 'crypt' => $this->decryptName, - 'mac' => $this->hmac_check_name, - 'comp' => $compression_map[$this->decompress], - ] - ]; - } - - /** - * Allows you to set the terminal - * - * @param string $term - */ - public function setTerminal($term) - { - $this->term = $term; - } - - /** - * Accepts an associative array with up to four parameters as described at - * - * - * @param array $methods - */ - public function setPreferredAlgorithms(array $methods) - { - $preferred = $methods; - - if (isset($preferred['kex'])) { - $preferred['kex'] = array_intersect( - $preferred['kex'], - static::getSupportedKEXAlgorithms() - ); - } - - if (isset($preferred['hostkey'])) { - $preferred['hostkey'] = array_intersect( - $preferred['hostkey'], - static::getSupportedHostKeyAlgorithms() - ); - } - - $keys = ['client_to_server', 'server_to_client']; - foreach ($keys as $key) { - if (isset($preferred[$key])) { - $a = &$preferred[$key]; - if (isset($a['crypt'])) { - $a['crypt'] = array_intersect( - $a['crypt'], - static::getSupportedEncryptionAlgorithms() - ); - } - if (isset($a['comp'])) { - $a['comp'] = array_intersect( - $a['comp'], - static::getSupportedCompressionAlgorithms() - ); - } - if (isset($a['mac'])) { - $a['mac'] = array_intersect( - $a['mac'], - static::getSupportedMACAlgorithms() - ); - } - } - } - - $keys = [ - 'kex', - 'hostkey', - 'client_to_server/crypt', - 'client_to_server/comp', - 'client_to_server/mac', - 'server_to_client/crypt', - 'server_to_client/comp', - 'server_to_client/mac', - ]; - foreach ($keys as $key) { - $p = $preferred; - $m = $methods; - - $subkeys = explode('/', $key); - foreach ($subkeys as $subkey) { - if (!isset($p[$subkey])) { - continue 2; - } - $p = $p[$subkey]; - $m = $m[$subkey]; - } - - if (count($p) != count($m)) { - $diff = array_diff($m, $p); - $msg = count($diff) == 1 ? - ' is not a supported algorithm' : - ' are not supported algorithms'; - throw new UnsupportedAlgorithmException(implode(', ', $diff) . $msg); - } - } - - $this->preferred = $preferred; - } - - /** - * Returns the banner message. - * - * Quoting from the RFC, "in some jurisdictions, sending a warning message before - * authentication may be relevant for getting legal protection." - * - * @return string - */ - public function getBannerMessage() - { - return $this->banner_message; - } - - /** - * Returns the server public host key. - * - * Caching this the first time you connect to a server and checking the result on subsequent connections - * is recommended. Returns false if the server signature is not signed correctly with the public host key. - * - * @return string|false - * @throws \RuntimeException on badly formatted keys - * @throws \phpseclib3\Exception\NoSupportedAlgorithmsException when the key isn't in a supported format - */ - public function getServerPublicHostKey() - { - if (!($this->bitmap & self::MASK_CONSTRUCTOR)) { - $this->connect(); - } - - $signature = $this->signature; - $server_public_host_key = base64_encode($this->server_public_host_key); - - if ($this->signature_validated) { - return $this->bitmap ? - $this->signature_format . ' ' . $server_public_host_key : - false; - } - - $this->signature_validated = true; - - switch ($this->signature_format) { - case 'ssh-ed25519': - case 'ecdsa-sha2-nistp256': - case 'ecdsa-sha2-nistp384': - case 'ecdsa-sha2-nistp521': - $key = EC::loadFormat('OpenSSH', $server_public_host_key) - ->withSignatureFormat('SSH2'); - switch ($this->signature_format) { - case 'ssh-ed25519': - $hash = 'sha512'; - break; - case 'ecdsa-sha2-nistp256': - $hash = 'sha256'; - break; - case 'ecdsa-sha2-nistp384': - $hash = 'sha384'; - break; - case 'ecdsa-sha2-nistp521': - $hash = 'sha512'; - } - $key = $key->withHash($hash); - break; - case 'ssh-dss': - $key = DSA::loadFormat('OpenSSH', $server_public_host_key) - ->withSignatureFormat('SSH2') - ->withHash('sha1'); - break; - case 'ssh-rsa': - case 'rsa-sha2-256': - case 'rsa-sha2-512': - // could be ssh-rsa, rsa-sha2-256, rsa-sha2-512 - // we don't check here because we already checked in key_exchange - // some signatures have the type embedded within the message and some don't - list(, $signature) = Strings::unpackSSH2('ss', $signature); - - $key = RSA::loadFormat('OpenSSH', $server_public_host_key) - ->withPadding(RSA::SIGNATURE_PKCS1); - switch ($this->signature_format) { - case 'rsa-sha2-512': - $hash = 'sha512'; - break; - case 'rsa-sha2-256': - $hash = 'sha256'; - break; - //case 'ssh-rsa': - default: - $hash = 'sha1'; - } - $key = $key->withHash($hash); - break; - default: - $this->disconnect_helper(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE); - throw new NoSupportedAlgorithmsException('Unsupported signature format'); - } - - if (!$key->verify($this->exchange_hash, $signature)) { - return $this->disconnect_helper(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE); - }; - - return $this->signature_format . ' ' . $server_public_host_key; - } - - /** - * Returns the exit status of an SSH command or false. - * - * @return false|int - */ - public function getExitStatus() - { - if (is_null($this->exit_status)) { - return false; - } - return $this->exit_status; - } - - /** - * Returns the number of columns for the terminal window size. - * - * @return int - */ - public function getWindowColumns() - { - return $this->windowColumns; - } - - /** - * Returns the number of rows for the terminal window size. - * - * @return int - */ - public function getWindowRows() - { - return $this->windowRows; - } - - /** - * Sets the number of columns for the terminal window size. - * - * @param int $value - */ - public function setWindowColumns($value) - { - $this->windowColumns = $value; - } - - /** - * Sets the number of rows for the terminal window size. - * - * @param int $value - */ - public function setWindowRows($value) - { - $this->windowRows = $value; - } - - /** - * Sets the number of columns and rows for the terminal window size. - * - * @param int $columns - * @param int $rows - */ - public function setWindowSize($columns = 80, $rows = 24) - { - $this->windowColumns = $columns; - $this->windowRows = $rows; - } - - /** - * To String Magic Method - * - * @return string - */ - #[\ReturnTypeWillChange] - public function __toString() - { - return $this->getResourceId(); - } - - /** - * Get Resource ID - * - * We use {} because that symbols should not be in URL according to - * {@link http://tools.ietf.org/html/rfc3986#section-2 RFC}. - * It will safe us from any conflicts, because otherwise regexp will - * match all alphanumeric domains. - * - * @return string - */ - public function getResourceId() - { - return '{' . spl_object_hash($this) . '}'; - } - - /** - * Return existing connection - * - * @param string $id - * - * @return bool|SSH2 will return false if no such connection - */ - public static function getConnectionByResourceId($id) - { - if (isset(self::$connections[$id])) { - return self::$connections[$id] instanceof \WeakReference ? self::$connections[$id]->get() : self::$connections[$id]; - } - return false; - } - - /** - * Return all excising connections - * - * @return array - */ - public static function getConnections() - { - if (!class_exists('WeakReference')) { - /** @var array */ - return self::$connections; - } - $temp = []; - foreach (self::$connections as $key => $ref) { - $temp[$key] = $ref->get(); - } - return $temp; - } - - /* - * Update packet types in log history - * - * @param string $old - * @param string $new - */ - private function updateLogHistory($old, $new) - { - if (defined('NET_SSH2_LOGGING') && NET_SSH2_LOGGING == self::LOG_COMPLEX) { - $this->message_number_log[count($this->message_number_log) - 1] = str_replace( - $old, - $new, - $this->message_number_log[count($this->message_number_log) - 1] - ); - } - } - - /** - * Return the list of authentication methods that may productively continue authentication. - * - * @see https://tools.ietf.org/html/rfc4252#section-5.1 - * @return array|null - */ - public function getAuthMethodsToContinue() - { - return $this->auth_methods_to_continue; - } - - /** - * Enables "smart" multi-factor authentication (MFA) - */ - public function enableSmartMFA() - { - $this->smartMFA = true; - } - - /** - * Disables "smart" multi-factor authentication (MFA) - */ - public function disableSmartMFA() - { - $this->smartMFA = false; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/System/SSH/Agent.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/System/SSH/Agent.php deleted file mode 100644 index 26ca3227..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/System/SSH/Agent.php +++ /dev/null @@ -1,286 +0,0 @@ - - * login('username', $agent)) { - * exit('Login Failed'); - * } - * - * echo $ssh->exec('pwd'); - * echo $ssh->exec('ls -la'); - * ?> - * - * - * @author Jim Wigginton - * @copyright 2014 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\System\SSH; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\PublicKeyLoader; -use phpseclib3\Crypt\RSA; -use phpseclib3\Exception\BadConfigurationException; -use phpseclib3\Net\SSH2; -use phpseclib3\System\SSH\Agent\Identity; - -/** - * Pure-PHP ssh-agent client identity factory - * - * requestIdentities() method pumps out \phpseclib3\System\SSH\Agent\Identity objects - * - * @author Jim Wigginton - */ -class Agent -{ - use Common\Traits\ReadBytes; - - // Message numbers - - // to request SSH1 keys you have to use SSH_AGENTC_REQUEST_RSA_IDENTITIES (1) - const SSH_AGENTC_REQUEST_IDENTITIES = 11; - // this is the SSH2 response; the SSH1 response is SSH_AGENT_RSA_IDENTITIES_ANSWER (2). - const SSH_AGENT_IDENTITIES_ANSWER = 12; - // the SSH1 request is SSH_AGENTC_RSA_CHALLENGE (3) - const SSH_AGENTC_SIGN_REQUEST = 13; - // the SSH1 response is SSH_AGENT_RSA_RESPONSE (4) - const SSH_AGENT_SIGN_RESPONSE = 14; - - // Agent forwarding status - - // no forwarding requested and not active - const FORWARD_NONE = 0; - // request agent forwarding when opportune - const FORWARD_REQUEST = 1; - // forwarding has been request and is active - const FORWARD_ACTIVE = 2; - - /** - * Unused - */ - const SSH_AGENT_FAILURE = 5; - - /** - * Socket Resource - * - * @var resource - */ - private $fsock; - - /** - * Agent forwarding status - * - * @var int - */ - private $forward_status = self::FORWARD_NONE; - - /** - * Buffer for accumulating forwarded authentication - * agent data arriving on SSH data channel destined - * for agent unix socket - * - * @var string - */ - private $socket_buffer = ''; - - /** - * Tracking the number of bytes we are expecting - * to arrive for the agent socket on the SSH data - * channel - * - * @var int - */ - private $expected_bytes = 0; - - /** - * Default Constructor - * - * @return \phpseclib3\System\SSH\Agent - * @throws \phpseclib3\Exception\BadConfigurationException if SSH_AUTH_SOCK cannot be found - * @throws \RuntimeException on connection errors - */ - public function __construct($address = null) - { - if (!$address) { - switch (true) { - case isset($_SERVER['SSH_AUTH_SOCK']): - $address = $_SERVER['SSH_AUTH_SOCK']; - break; - case isset($_ENV['SSH_AUTH_SOCK']): - $address = $_ENV['SSH_AUTH_SOCK']; - break; - default: - throw new BadConfigurationException('SSH_AUTH_SOCK not found'); - } - } - - if (in_array('unix', stream_get_transports())) { - $this->fsock = fsockopen('unix://' . $address, 0, $errno, $errstr); - if (!$this->fsock) { - throw new \RuntimeException("Unable to connect to ssh-agent (Error $errno: $errstr)"); - } - } else { - if (substr($address, 0, 9) != '\\\\.\\pipe\\' || strpos(substr($address, 9), '\\') !== false) { - throw new \RuntimeException('Address is not formatted as a named pipe should be'); - } - - $this->fsock = fopen($address, 'r+b'); - if (!$this->fsock) { - throw new \RuntimeException('Unable to open address'); - } - } - } - - /** - * Request Identities - * - * See "2.5.2 Requesting a list of protocol 2 keys" - * Returns an array containing zero or more \phpseclib3\System\SSH\Agent\Identity objects - * - * @return array - * @throws \RuntimeException on receipt of unexpected packets - */ - public function requestIdentities() - { - if (!$this->fsock) { - return []; - } - - $packet = pack('NC', 1, self::SSH_AGENTC_REQUEST_IDENTITIES); - if (strlen($packet) != fputs($this->fsock, $packet)) { - throw new \RuntimeException('Connection closed while requesting identities'); - } - - $length = current(unpack('N', $this->readBytes(4))); - $packet = $this->readBytes($length); - - list($type, $keyCount) = Strings::unpackSSH2('CN', $packet); - if ($type != self::SSH_AGENT_IDENTITIES_ANSWER) { - throw new \RuntimeException('Unable to request identities'); - } - - $identities = []; - for ($i = 0; $i < $keyCount; $i++) { - list($key_blob, $comment) = Strings::unpackSSH2('ss', $packet); - $temp = $key_blob; - list($key_type) = Strings::unpackSSH2('s', $temp); - switch ($key_type) { - case 'ssh-rsa': - case 'ssh-dss': - case 'ssh-ed25519': - case 'ecdsa-sha2-nistp256': - case 'ecdsa-sha2-nistp384': - case 'ecdsa-sha2-nistp521': - $key = PublicKeyLoader::load($key_type . ' ' . base64_encode($key_blob)); - } - // resources are passed by reference by default - if (isset($key)) { - $identity = (new Identity($this->fsock)) - ->withPublicKey($key) - ->withPublicKeyBlob($key_blob); - $identities[] = $identity; - unset($key); - } - } - - return $identities; - } - - /** - * Signal that agent forwarding should - * be requested when a channel is opened - * - * @return void - */ - public function startSSHForwarding() - { - if ($this->forward_status == self::FORWARD_NONE) { - $this->forward_status = self::FORWARD_REQUEST; - } - } - - /** - * Request agent forwarding of remote server - * - * @param \phpseclib3\Net\SSH2 $ssh - * @return bool - */ - private function request_forwarding(SSH2 $ssh) - { - if (!$ssh->requestAgentForwarding()) { - return false; - } - - $this->forward_status = self::FORWARD_ACTIVE; - - return true; - } - - /** - * On successful channel open - * - * This method is called upon successful channel - * open to give the SSH Agent an opportunity - * to take further action. i.e. request agent forwarding - * - * @param \phpseclib3\Net\SSH2 $ssh - */ - public function registerChannelOpen(SSH2 $ssh) - { - if ($this->forward_status == self::FORWARD_REQUEST) { - $this->request_forwarding($ssh); - } - } - - /** - * Forward data to SSH Agent and return data reply - * - * @param string $data - * @return string Data from SSH Agent - * @throws \RuntimeException on connection errors - */ - public function forwardData($data) - { - if ($this->expected_bytes > 0) { - $this->socket_buffer .= $data; - $this->expected_bytes -= strlen($data); - } else { - $agent_data_bytes = current(unpack('N', $data)); - $current_data_bytes = strlen($data); - $this->socket_buffer = $data; - if ($current_data_bytes != $agent_data_bytes + 4) { - $this->expected_bytes = ($agent_data_bytes + 4) - $current_data_bytes; - return false; - } - } - - if (strlen($this->socket_buffer) != fwrite($this->fsock, $this->socket_buffer)) { - throw new \RuntimeException('Connection closed attempting to forward data to SSH agent'); - } - - $this->socket_buffer = ''; - $this->expected_bytes = 0; - - $agent_reply_bytes = current(unpack('N', $this->readBytes(4))); - - $agent_reply_data = $this->readBytes($agent_reply_bytes); - $agent_reply_data = current(unpack('a*', $agent_reply_data)); - - return pack('Na*', $agent_reply_bytes, $agent_reply_data); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/System/SSH/Agent/Identity.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/System/SSH/Agent/Identity.php deleted file mode 100644 index 653e8ea5..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/System/SSH/Agent/Identity.php +++ /dev/null @@ -1,320 +0,0 @@ - - * @copyright 2009 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\System\SSH\Agent; - -use phpseclib3\Common\Functions\Strings; -use phpseclib3\Crypt\Common\PrivateKey; -use phpseclib3\Crypt\Common\PublicKey; -use phpseclib3\Crypt\DSA; -use phpseclib3\Crypt\EC; -use phpseclib3\Crypt\RSA; -use phpseclib3\Exception\UnsupportedAlgorithmException; -use phpseclib3\System\SSH\Agent; -use phpseclib3\System\SSH\Common\Traits\ReadBytes; - -/** - * Pure-PHP ssh-agent client identity object - * - * Instantiation should only be performed by \phpseclib3\System\SSH\Agent class. - * This could be thought of as implementing an interface that phpseclib3\Crypt\RSA - * implements. ie. maybe a Net_SSH_Auth_PublicKey interface or something. - * The methods in this interface would be getPublicKey and sign since those are the - * methods phpseclib looks for to perform public key authentication. - * - * @author Jim Wigginton - * @internal - */ -class Identity implements PrivateKey -{ - use ReadBytes; - - // Signature Flags - // See https://tools.ietf.org/html/draft-miller-ssh-agent-00#section-5.3 - const SSH_AGENT_RSA2_256 = 2; - const SSH_AGENT_RSA2_512 = 4; - - /** - * Key Object - * - * @var PublicKey - * @see self::getPublicKey() - */ - private $key; - - /** - * Key Blob - * - * @var string - * @see self::sign() - */ - private $key_blob; - - /** - * Socket Resource - * - * @var resource - * @see self::sign() - */ - private $fsock; - - /** - * Signature flags - * - * @var int - * @see self::sign() - * @see self::setHash() - */ - private $flags = 0; - - /** - * Curve Aliases - * - * @var array - */ - private static $curveAliases = [ - 'secp256r1' => 'nistp256', - 'secp384r1' => 'nistp384', - 'secp521r1' => 'nistp521', - 'Ed25519' => 'Ed25519' - ]; - - /** - * Default Constructor. - * - * @param resource $fsock - */ - public function __construct($fsock) - { - $this->fsock = $fsock; - } - - /** - * Set Public Key - * - * Called by \phpseclib3\System\SSH\Agent::requestIdentities() - * - * @param \phpseclib3\Crypt\Common\PublicKey $key - */ - public function withPublicKey(PublicKey $key) - { - if ($key instanceof EC) { - if (is_array($key->getCurve()) || !isset(self::$curveAliases[$key->getCurve()])) { - throw new UnsupportedAlgorithmException('The only supported curves are nistp256, nistp384, nistp512 and Ed25519'); - } - } - - $new = clone $this; - $new->key = $key; - return $new; - } - - /** - * Set Public Key - * - * Called by \phpseclib3\System\SSH\Agent::requestIdentities(). The key blob could be extracted from $this->key - * but this saves a small amount of computation. - * - * @param string $key_blob - */ - public function withPublicKeyBlob($key_blob) - { - $new = clone $this; - $new->key_blob = $key_blob; - return $new; - } - - /** - * Get Public Key - * - * Wrapper for $this->key->getPublicKey() - * - * @param string $type optional - * @return mixed - */ - public function getPublicKey($type = 'PKCS8') - { - return $this->key; - } - - /** - * Sets the hash - * - * @param string $hash - */ - public function withHash($hash) - { - $new = clone $this; - - $hash = strtolower($hash); - - if ($this->key instanceof RSA) { - $new->flags = 0; - switch ($hash) { - case 'sha1': - break; - case 'sha256': - $new->flags = self::SSH_AGENT_RSA2_256; - break; - case 'sha512': - $new->flags = self::SSH_AGENT_RSA2_512; - break; - default: - throw new UnsupportedAlgorithmException('The only supported hashes for RSA are sha1, sha256 and sha512'); - } - } - if ($this->key instanceof EC) { - switch ($this->key->getCurve()) { - case 'secp256r1': - $expectedHash = 'sha256'; - break; - case 'secp384r1': - $expectedHash = 'sha384'; - break; - //case 'secp521r1': - //case 'Ed25519': - default: - $expectedHash = 'sha512'; - } - if ($hash != $expectedHash) { - throw new UnsupportedAlgorithmException('The only supported hash for ' . self::$curveAliases[$this->key->getCurve()] . ' is ' . $expectedHash); - } - } - if ($this->key instanceof DSA) { - if ($hash != 'sha1') { - throw new UnsupportedAlgorithmException('The only supported hash for DSA is sha1'); - } - } - return $new; - } - - /** - * Sets the padding - * - * Only PKCS1 padding is supported - * - * @param string $padding - */ - public function withPadding($padding) - { - if (!$this->key instanceof RSA) { - throw new UnsupportedAlgorithmException('Only RSA keys support padding'); - } - if ($padding != RSA::SIGNATURE_PKCS1 && $padding != RSA::SIGNATURE_RELAXED_PKCS1) { - throw new UnsupportedAlgorithmException('ssh-agent can only create PKCS1 signatures'); - } - return $this; - } - - /** - * Determines the signature padding mode - * - * Valid values are: ASN1, SSH2, Raw - * - * @param string $format - */ - public function withSignatureFormat($format) - { - if ($this->key instanceof RSA) { - throw new UnsupportedAlgorithmException('Only DSA and EC keys support signature format setting'); - } - if ($format != 'SSH2') { - throw new UnsupportedAlgorithmException('Only SSH2-formatted signatures are currently supported'); - } - - return $this; - } - - /** - * Returns the curve - * - * Returns a string if it's a named curve, an array if not - * - * @return string|array - */ - public function getCurve() - { - if (!$this->key instanceof EC) { - throw new UnsupportedAlgorithmException('Only EC keys have curves'); - } - - return $this->key->getCurve(); - } - - /** - * Create a signature - * - * See "2.6.2 Protocol 2 private key signature request" - * - * @param string $message - * @return string - * @throws \RuntimeException on connection errors - * @throws \phpseclib3\Exception\UnsupportedAlgorithmException if the algorithm is unsupported - */ - public function sign($message) - { - // the last parameter (currently 0) is for flags and ssh-agent only defines one flag (for ssh-dss): SSH_AGENT_OLD_SIGNATURE - $packet = Strings::packSSH2( - 'CssN', - Agent::SSH_AGENTC_SIGN_REQUEST, - $this->key_blob, - $message, - $this->flags - ); - $packet = Strings::packSSH2('s', $packet); - if (strlen($packet) != fputs($this->fsock, $packet)) { - throw new \RuntimeException('Connection closed during signing'); - } - - $length = current(unpack('N', $this->readBytes(4))); - $packet = $this->readBytes($length); - - list($type, $signature_blob) = Strings::unpackSSH2('Cs', $packet); - if ($type != Agent::SSH_AGENT_SIGN_RESPONSE) { - throw new \RuntimeException('Unable to retrieve signature'); - } - - if (!$this->key instanceof RSA) { - return $signature_blob; - } - - list($type, $signature_blob) = Strings::unpackSSH2('ss', $signature_blob); - - return $signature_blob; - } - - /** - * Returns the private key - * - * @param string $type - * @param array $options optional - * @return string - */ - public function toString($type, array $options = []) - { - throw new \RuntimeException('ssh-agent does not provide a mechanism to get the private key'); - } - - /** - * Sets the password - * - * @param string|bool $password - * @return never - */ - public function withPassword($password = false) - { - throw new \RuntimeException('ssh-agent does not provide a mechanism to get the private key'); - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/System/SSH/Common/Traits/ReadBytes.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/System/SSH/Common/Traits/ReadBytes.php deleted file mode 100644 index 6fd032bd..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/System/SSH/Common/Traits/ReadBytes.php +++ /dev/null @@ -1,37 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib3\System\SSH\Common\Traits; - -/** - * ReadBytes trait - * - * @author Jim Wigginton - */ -trait ReadBytes -{ - /** - * Read data - * - * @param int $length - * @throws \RuntimeException on connection errors - */ - public function readBytes($length) - { - $temp = fread($this->fsock, $length); - if (strlen($temp) != $length) { - throw new \RuntimeException("Expected $length bytes; got " . strlen($temp)); - } - return $temp; - } -} diff --git a/securemail/vendor/phpseclib/phpseclib/phpseclib/bootstrap.php b/securemail/vendor/phpseclib/phpseclib/phpseclib/bootstrap.php deleted file mode 100644 index 517106c3..00000000 --- a/securemail/vendor/phpseclib/phpseclib/phpseclib/bootstrap.php +++ /dev/null @@ -1,22 +0,0 @@ -, 2018,2022\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2022-01-22 17:39+0000\n" +"Last-Translator: Tobias Diekershoff \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/showmore/lang/it/messages.po b/showmore/lang/it/messages.po index e1a917cb..dd619e49 100644 --- a/showmore/lang/it/messages.po +++ b/showmore/lang/it/messages.po @@ -5,33 +5,40 @@ # # Translators: # fabrixxm , 2014-2015,2018 -# Sylke Vicious , 2023 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:16-0500\n" -"PO-Revision-Date: 2014-06-23 12:37+0000\n" -"Last-Translator: Sylke Vicious , 2023\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"POT-Creation-Date: 2018-04-01 11:11-0400\n" +"PO-Revision-Date: 2018-05-28 09:04+0000\n" +"Last-Translator: fabrixxm \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: showmore.php:37 -msgid "Enable Show More" -msgstr "Abilita \"Mostra altro\"" - -#: showmore.php:38 -msgid "Cutting posts after how many characters" -msgstr "Taglia messaggi dopo quanti caratteri" - -#: showmore.php:43 +#: showmore.php:41 showmore.php:45 msgid "\"Show more\" Settings" msgstr "Impostazioni \"Mostra altro\"" -#: showmore.php:119 +#: showmore.php:50 +msgid "Enable Show More" +msgstr "Abilita \"Mostra altro\"" + +#: showmore.php:53 +msgid "Cutting posts after how much characters" +msgstr "Dopo quanti caratteri tagliare il messaggio" + +#: showmore.php:57 +msgid "Save Settings" +msgstr "Salva Impostazioni" + +#: showmore.php:74 +msgid "Show More Settings saved." +msgstr "Impostazioni \"Mostra altro\" salvate." + +#: showmore.php:134 msgid "show more" msgstr "mostra di più" diff --git a/showmore/lang/it/strings.php b/showmore/lang/it/strings.php index ead3ddcb..db17e3a1 100644 --- a/showmore/lang/it/strings.php +++ b/showmore/lang/it/strings.php @@ -3,9 +3,11 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} -$a->strings['Enable Show More'] = 'Abilita "Mostra altro"'; -$a->strings['Cutting posts after how many characters'] = 'Taglia messaggi dopo quanti caratteri'; $a->strings['"Show more" Settings'] = 'Impostazioni "Mostra altro"'; +$a->strings['Enable Show More'] = 'Abilita "Mostra altro"'; +$a->strings['Cutting posts after how much characters'] = 'Dopo quanti caratteri tagliare il messaggio'; +$a->strings['Save Settings'] = 'Salva Impostazioni'; +$a->strings['Show More Settings saved.'] = 'Impostazioni "Mostra altro" salvate.'; $a->strings['show more'] = 'mostra di più'; diff --git a/showmore/lang/ru/messages.po b/showmore/lang/ru/messages.po index 650269b2..2b4c7413 100644 --- a/showmore/lang/ru/messages.po +++ b/showmore/lang/ru/messages.po @@ -4,33 +4,41 @@ # # # Translators: -# Alexander An , 2020,2023 +# Alexander An , 2020 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \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" +"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" "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:37 -msgid "Enable Show More" -msgstr "Включить \"показать ещё\"" - -#: showmore.php:38 -msgid "Cutting posts after how many characters" -msgstr "Обрезать записи после превышения этого числа символов" - -#: showmore.php:43 +#: showmore.php:41 showmore.php:45 msgid "\"Show more\" Settings" msgstr "Настройки \"показать ещё\"" -#: showmore.php:119 +#: showmore.php:50 +msgid "Enable Show More" +msgstr "Включить \"показать ещё\"" + +#: showmore.php:53 +msgid "Cutting posts after how much characters" +msgstr "Обрезать записи после превышения этого числа символов" + +#: showmore.php:57 +msgid "Save Settings" +msgstr "Сохранить настройки" + +#: showmore.php:74 +msgid "Show More Settings saved." +msgstr "Настройки сохранены." + +#: showmore.php:134 msgid "show more" msgstr "показать ещё" diff --git a/showmore/lang/ru/strings.php b/showmore/lang/ru/strings.php index a12af848..da3c9466 100644 --- a/showmore/lang/ru/strings.php +++ b/showmore/lang/ru/strings.php @@ -5,7 +5,9 @@ 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['Enable Show More'] = 'Включить "показать ещё"'; -$a->strings['Cutting posts after how many characters'] = 'Обрезать записи после превышения этого числа символов'; $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['show more'] = 'показать ещё'; diff --git a/showmore_dyn/showmore_dyn.css b/showmore_dyn/showmore_dyn.css index 250d95c6..93cc87a5 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: 9; + z-index: 11; left: 0; display: none; } 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 38b208da..b76033f4 100644 --- a/smiley_pack/lang/smiley_pack_es/smiley_pack_es.php +++ b/smiley_pack/lang/smiley_pack_es/smiley_pack_es.php @@ -27,459 +27,459 @@ function smiley_pack_smilies_es(array &$b) { #Animal smileys. $b['texts'][] = ':conejitoflores'; - $b['icons'][] = '' . ':conejitoflores' . ''; + $b['icons'][] = '' . ':conejitoflores' . ''; $b['texts'][] = ':pollito'; - $b['icons'][] = '' . ':pollito' . ''; + $b['icons'][] = '' . ':pollito' . ''; $b['texts'][] = ':abeja'; - $b['icons'][] = '' . ':abeja' . ''; + $b['icons'][] = '' . ':abeja' . ''; $b['texts'][] = ':mariquita'; - $b['icons'][] = '' . ':mariquita' . ''; + $b['icons'][] = '' . ':mariquita' . ''; $b['texts'][] = ':araña'; - $b['icons'][] = '' . ':araña' . ''; + $b['icons'][] = '' . ':araña' . ''; $b['texts'][] = ':gato'; - $b['icons'][] = '' . ':gato' . ''; + $b['icons'][] = '' . ':gato' . ''; $b['texts'][] = ':conejito'; - $b['icons'][] = '' . ':conejito' . ''; + $b['icons'][] = '' . ':conejito' . ''; $b['texts'][] = ':vaca'; - $b['icons'][] = '' . ':vaca' . ''; + $b['icons'][] = '' . ':vaca' . ''; $b['texts'][] = ':cangrejo'; - $b['icons'][] = '' . ':cangrejo' . ''; + $b['icons'][] = '' . ':cangrejo' . ''; $b['texts'][] = ':delfín'; - $b['icons'][] = '' . ':delfín' . ''; + $b['icons'][] = '' . ':delfín' . ''; $b['texts'][] = ':libélula'; - $b['icons'][] = '' . ':libélula' . ''; + $b['icons'][] = '' . ':libélula' . ''; $b['texts'][] = ':rana'; - $b['icons'][] = '' . ':rana' . ''; + $b['icons'][] = '' . ':rana' . ''; $b['texts'][] = ':hamster'; - $b['icons'][] = '' . ':hamster' . ''; + $b['icons'][] = '' . ':hamster' . ''; $b['texts'][] = ':mono'; - $b['icons'][] = '' . ':mono' . ''; + $b['icons'][] = '' . ':mono' . ''; $b['texts'][] = ':caballo'; - $b['icons'][] = '' . ':caballo' . ''; + $b['icons'][] = '' . ':caballo' . ''; $b['texts'][] = ':loro'; - $b['icons'][] = '' . ':loro' . ''; + $b['icons'][] = '' . ':loro' . ''; $b['texts'][] = ':tux'; - $b['icons'][] = '' . ':tux' . ''; + $b['icons'][] = '' . ':tux' . ''; $b['texts'][] = ':caracol'; - $b['icons'][] = '' . ':caracol' . ''; + $b['icons'][] = '' . ':caracol' . ''; $b['texts'][] = ':oveja'; - $b['icons'][] = '' . ':oveja' . ''; + $b['icons'][] = '' . ':oveja' . ''; $b['texts'][] = ':perro'; - $b['icons'][] = '' . ':perro' . ''; + $b['icons'][] = '' . ':perro' . ''; $b['texts'][] = ':elefante'; - $b['icons'][] = '' . ':elefante' . ''; + $b['icons'][] = '' . ':elefante' . ''; $b['texts'][] = ':pez'; - $b['icons'][] = '' . ':pez' . ''; + $b['icons'][] = '' . ':pez' . ''; $b['texts'][] = ':jirafa'; - $b['icons'][] = '' . ':jirafa' . ''; + $b['icons'][] = '' . ':jirafa' . ''; $b['texts'][] = ':cerdo'; - $b['icons'][] = '' . ':cerdo' . ''; + $b['icons'][] = '' . ':cerdo' . ''; #Baby Smileys $b['texts'][] = ':bebé'; - $b['icons'][] = '' . ':bebé' . ''; + $b['icons'][] = '' . ':bebé' . ''; $b['texts'][] = ':cuna'; - $b['icons'][] = '' . ':cuna' . ''; + $b['icons'][] = '' . ':cuna' . ''; $b['texts'][] = ':embarazada'; - $b['icons'][] = '' . ':embarazada' . ''; + $b['icons'][] = '' . ':embarazada' . ''; $b['texts'][] = ':cigüeña'; - $b['icons'][] = '' . ':cigüeña' . ''; + $b['icons'][] = '' . ':cigüeña' . ''; #Confused Smileys $b['texts'][] = ':confundido'; - $b['icons'][] = '' . ':confundido' . ''; + $b['icons'][] = '' . ':confundido' . ''; $b['texts'][] = ':encogehombros'; - $b['icons'][] = '' . ':encogehombros' . ''; + $b['icons'][] = '' . ':encogehombros' . ''; $b['texts'][] = ':estúpido'; - $b['icons'][] = '' . ':estúpido' . ''; + $b['icons'][] = '' . ':estúpido' . ''; $b['texts'][] = ':aturdidp'; - $b['icons'][] = '' . ':aturdid' . ''; + $b['icons'][] = '' . ':aturdid' . ''; #Cool Smileys $b['texts'][] = ':afro'; - $b['icons'][] = '' . ':afro' . ''; + $b['icons'][] = '' . ':afro' . ''; $b['texts'][] = ':guay'; - $b['icons'][] = '' . ':guay' . ''; + $b['icons'][] = '' . ':guay' . ''; #Devil/Angel Smileys $b['texts'][] = ':ángel'; - $b['icons'][] = '' . ':ángel' . ''; + $b['icons'][] = '' . ':ángel' . ''; $b['texts'][] = ':querubín'; - $b['icons'][] = '' . ':querubín' . ''; + $b['icons'][] = '' . ':querubín' . ''; $b['texts'][] = ':ángeldemonio'; - $b['icons'][] = '' . ':ángeldemonio' . ''; + $b['icons'][] = '' . ':ángeldemonio' . ''; $b['texts'][] = ':gatodemonio'; - $b['icons'][] = '' . ':gatodemonio' . ''; + $b['icons'][] = '' . ':gatodemonio' . ''; $b['texts'][] = ':diabólico'; - $b['icons'][] = '' . ':diabólico' . ''; + $b['icons'][] = '' . ':diabólico' . ''; $b['texts'][] = ':adbalancín'; - $b['icons'][] = '' . ':adbalancín' . ''; + $b['icons'][] = '' . ':adbalancín' . ''; $b['texts'][] = ':vuelvedemonio'; - $b['icons'][] = '' . ':vuelvedemonio' . ''; + $b['icons'][] = '' . ':vuelvedemonio' . ''; $b['texts'][] = ':santo'; - $b['icons'][] = '' . ':santo' . ''; + $b['icons'][] = '' . ':santo' . ''; $b['texts'][] = ':tumba'; - $b['icons'][] = '' . ':tumba' . ''; + $b['icons'][] = '' . ':tumba' . ''; #Unpleasent smileys. $b['texts'][] = ':retrete'; - $b['icons'][] = '' . ':retrete' . ''; + $b['icons'][] = '' . ':retrete' . ''; $b['texts'][] = ':pedoencama'; - $b['icons'][] = '' . ':pedoencama' . ''; + $b['icons'][] = '' . ':pedoencama' . ''; $b['texts'][] = ':vómito'; - $b['icons'][] = '' . ':vómito' . ''; + $b['icons'][] = '' . ':vómito' . ''; $b['texts'][] = ':pedosonrojo'; - $b['icons'][] = '' . ':pedosonrojo' . ''; + $b['icons'][] = '' . ':pedosonrojo' . ''; #Drinks $b['texts'][] = ':té'; - $b['icons'][] = '' . ':té' . ''; + $b['icons'][] = '' . ':té' . ''; $b['texts'][] = ':baba'; - $b['icons'][] = '' . ':baba' . ''; + $b['icons'][] = '' . ':baba' . ''; #Sad smileys $b['texts'][] = ':llorar'; - $b['icons'][] = '' . ':llorar' . ''; + $b['icons'][] = '' . ':llorar' . ''; $b['texts'][] = ':prisonero'; - $b['icons'][] = '' . ':prisonero' . ''; + $b['icons'][] = '' . ':prisonero' . ''; $b['texts'][] = ':suspiro'; - $b['icons'][] = '' . ':suspiro' . ''; + $b['icons'][] = '' . ':suspiro' . ''; #Smoking - only one smiley in here, maybe it needs moving elsewhere? $b['texts'][] = ':fumar'; - $b['icons'][] = '' . ':fumar' . ''; + $b['icons'][] = '' . ':fumar' . ''; #Sport smileys $b['texts'][] = ':baloncesto'; - $b['icons'][] = '' . ':baloncesto' . ''; + $b['icons'][] = '' . ':baloncesto' . ''; $b['texts'][] = ':bolos'; - $b['icons'][] = '' . ':bolos' . ''; + $b['icons'][] = '' . ':bolos' . ''; $b['texts'][] = ':enbici'; - $b['icons'][] = '' . ':enbici' . ''; + $b['icons'][] = '' . ':enbici' . ''; $b['texts'][] = ':dardos'; - $b['icons'][] = '' . ':dardos' . ''; + $b['icons'][] = '' . ':dardos' . ''; $b['texts'][] = ':esgrima'; - $b['icons'][] = '' . ':esgrima' . ''; + $b['icons'][] = '' . ':esgrima' . ''; $b['texts'][] = ':golf'; - $b['icons'][] = '' . ':golf' . ''; + $b['icons'][] = '' . ':golf' . ''; $b['texts'][] = ':malabares'; - $b['icons'][] = '' . ':malabares' . ''; + $b['icons'][] = '' . ':malabares' . ''; $b['texts'][] = ':comba'; - $b['icons'][] = '' . ':comba' . ''; + $b['icons'][] = '' . ':comba' . ''; $b['texts'][] = ':tiroconarco'; - $b['icons'][] = '' . ':tiroconarco' . ''; + $b['icons'][] = '' . ':tiroconarco' . ''; $b['texts'][] = ':fútbol'; - $b['icons'][] = '' . ':fútbol' . ''; + $b['icons'][] = '' . ':fútbol' . ''; $b['texts'][] = ':surf'; - $b['icons'][] = '' . ':surf' . ''; + $b['icons'][] = '' . ':surf' . ''; $b['texts'][] = ':billar'; - $b['icons'][] = '' . ':billar' . ''; + $b['icons'][] = '' . ':billar' . ''; $b['texts'][] = ':tenis'; - $b['icons'][] = '' . ':tenis' . ''; + $b['icons'][] = '' . ':tenis' . ''; $b['texts'][] = ':acaballo'; - $b['icons'][] = '' . ':acaballo' . ''; + $b['icons'][] = '' . ':acaballo' . ''; #Love smileys $b['texts'][] = ':tequiero'; - $b['icons'][] = '' . ':tequiero' . ''; + $b['icons'][] = '' . ':tequiero' . ''; $b['texts'][] = ':enamorada'; - $b['icons'][] = '' . ':enamorada' . ''; + $b['icons'][] = '' . ':enamorada' . ''; $b['texts'][] = ':amor'; - $b['icons'][] = '' . ':amor' . ''; + $b['icons'][] = '' . ':amor' . ''; $b['texts'][] = ':osoamoroso'; - $b['icons'][] = '' . ':osoamoroso' . ''; + $b['icons'][] = '' . ':osoamoroso' . ''; $b['texts'][] = ':camaamor'; - $b['icons'][] = '' . ':camaamor' . ''; + $b['icons'][] = '' . ':camaamor' . ''; $b['texts'][] = ':corazónamor'; - $b['icons'][] = '' . ':corazónamor' . ''; + $b['icons'][] = '' . ':corazónamor' . ''; #Tired/Sleep smileys $b['texts'][] = ':contandoovejas'; - $b['icons'][] = '' . ':contandoovejas' . ''; + $b['icons'][] = '' . ':contandoovejas' . ''; $b['texts'][] = ':hamaca'; - $b['icons'][] = '' . ':hamaca' . ''; + $b['icons'][] = '' . ':hamaca' . ''; $b['texts'][] = ':almohada'; - $b['icons'][] = '' . ':almohada' . ''; + $b['icons'][] = '' . ':almohada' . ''; $b['texts'][] = ':bostezo'; - $b['icons'][] = '' . ':bostezo' . ''; + $b['icons'][] = '' . ':bostezo' . ''; #Fight/Flame/Violent smileys $b['texts'][] = ':pistolas'; - $b['icons'][] = '' . ':pistolas' . ''; + $b['icons'][] = '' . ':pistolas' . ''; $b['texts'][] = ':peleamarciano'; - $b['icons'][] = '' . ':peleamarciano' . ''; + $b['icons'][] = '' . ':peleamarciano' . ''; $b['texts'][] = ':alfa'; - $b['icons'][] = '' . ':alfa' . ''; + $b['icons'][] = '' . ':alfa' . ''; $b['texts'][] = ':ejército'; - $b['icons'][] = '' . ':ejército' . ''; + $b['icons'][] = '' . ':ejército' . ''; $b['texts'][] = ':cabezaflecha'; - $b['icons'][] = '' . ':cabezaflecha' . ''; + $b['icons'][] = '' . ':cabezaflecha' . ''; $b['texts'][] = ':bfg'; - $b['icons'][] = '' . ':bfg' . ''; + $b['icons'][] = '' . ':bfg' . ''; $b['texts'][] = ':arquero'; - $b['icons'][] = '' . ':arquero' . ''; + $b['icons'][] = '' . ':arquero' . ''; $b['texts'][] = ':motosierra'; - $b['icons'][] = '' . ':motosierra' . ''; + $b['icons'][] = '' . ':motosierra' . ''; $b['texts'][] = ':ballesta'; - $b['icons'][] = '' . ':ballesta' . ''; + $b['icons'][] = '' . ':ballesta' . ''; $b['texts'][] = ':cruzado'; - $b['icons'][] = '' . ':cruzado' . ''; + $b['icons'][] = '' . ':cruzado' . ''; $b['texts'][] = ':muerto'; - $b['icons'][] = '' . ':muerto' . ''; + $b['icons'][] = '' . ':muerto' . ''; $b['texts'][] = ':martillazo'; - $b['icons'][] = '' . ':martillazo' . ''; + $b['icons'][] = '' . ':martillazo' . ''; $b['texts'][] = ':pistolalaser'; - $b['icons'][] = '' . ':pistolalaser' . ''; + $b['icons'][] = '' . ':pistolalaser' . ''; $b['texts'][] = ':metralleta'; - $b['icons'][] = '' . ':metralleta' . ''; + $b['icons'][] = '' . ':metralleta' . ''; $b['texts'][] = ':marine'; - $b['icons'][] = '' . ':marine' . ''; + $b['icons'][] = '' . ':marine' . ''; $b['texts'][] = ':sable'; - $b['icons'][] = '' . ':sable' . ''; + $b['icons'][] = '' . ':sable' . ''; $b['texts'][] = ':tanque'; - $b['icons'][] = '' . ':tanque' . ''; + $b['icons'][] = '' . ':tanque' . ''; $b['texts'][] = ':vikingo'; - $b['icons'][] = '' . ':vikingo' . ''; + $b['icons'][] = '' . ':vikingo' . ''; $b['texts'][] = ':bandas'; - $b['icons'][] = '' . ':bandas' . ''; + $b['icons'][] = '' . ':bandas' . ''; $b['texts'][] = ':ácido'; - $b['icons'][] = '' . ':ácido' . ''; + $b['icons'][] = '' . ':ácido' . ''; #Fantasy smileys - monsters and dragons fantasy. The other type of fantasy belongs in adult smileys $b['texts'][] = ':alien'; - $b['icons'][] = '' . ':alien' . ''; + $b['icons'][] = '' . ':alien' . ''; $b['texts'][] = ':bárbaro'; - $b['icons'][] = '' . ':bárbaro' . ''; + $b['icons'][] = '' . ':bárbaro' . ''; $b['texts'][] = ':dinosaurio'; - $b['icons'][] = '' . ':dinosaurio' . ''; + $b['icons'][] = '' . ':dinosaurio' . ''; $b['texts'][] = ':dragón'; - $b['icons'][] = '' . ':dragón' . ''; + $b['icons'][] = '' . ':dragón' . ''; $b['texts'][] = ':draco'; - $b['icons'][] = '' . ':draco' . ''; + $b['icons'][] = '' . ':draco' . ''; $b['texts'][] = ':fantasma'; - $b['icons'][] = '' . ':fantasma' . ''; + $b['icons'][] = '' . ':fantasma' . ''; $b['texts'][] = ':momia'; - $b['icons'][] = '' . ':momia' . ''; + $b['icons'][] = '' . ':momia' . ''; #Food smileys $b['texts'][] = ':mazana'; - $b['icons'][] = '' . ':mazana' . ''; + $b['icons'][] = '' . ':mazana' . ''; $b['texts'][] = ':brócoli'; - $b['icons'][] = '' . ':brócoli' . ''; + $b['icons'][] = '' . ':brócoli' . ''; $b['texts'][] = ':pastel'; - $b['icons'][] = '' . ':pastel' . ''; + $b['icons'][] = '' . ':pastel' . ''; $b['texts'][] = ':zanahoria'; - $b['icons'][] = '' . ':zanahoria' . ''; + $b['icons'][] = '' . ':zanahoria' . ''; $b['texts'][] = ':palomitas'; - $b['icons'][] = '' . ':palomitas' . ''; + $b['icons'][] = '' . ':palomitas' . ''; $b['texts'][] = ':tomate'; - $b['icons'][] = '' . ':tomate' . ''; + $b['icons'][] = '' . ':tomate' . ''; $b['texts'][] = ':plátano'; - $b['icons'][] = '' . ':plátano' . ''; + $b['icons'][] = '' . ':plátano' . ''; $b['texts'][] = ':cocinar'; - $b['icons'][] = '' . ':cocinar' . ''; + $b['icons'][] = '' . ':cocinar' . ''; $b['texts'][] = ':huevofrito'; - $b['icons'][] = '' . ':huevofrito' . ''; + $b['icons'][] = '' . ':huevofrito' . ''; #Happy smileys $b['texts'][] = ':cloud9'; - $b['icons'][] = '' . ':cloud9' . ''; + $b['icons'][] = '' . ':cloud9' . ''; $b['texts'][] = ':tearsofjoy'; - $b['icons'][] = '' . ':tearsofjoy' . ''; + $b['icons'][] = '' . ':tearsofjoy' . ''; #Repsect smileys $b['texts'][] = ':reverencia'; - $b['icons'][] = '' . ':reverencia' . ''; + $b['icons'][] = '' . ':reverencia' . ''; $b['texts'][] = ':bravo'; - $b['icons'][] = '' . ':bravo' . ''; + $b['icons'][] = '' . ':bravo' . ''; $b['texts'][] = ':vivaelrey'; - $b['icons'][] = '' . ':vivaelrey' . ''; + $b['icons'][] = '' . ':vivaelrey' . ''; $b['texts'][] = ':número1'; - $b['icons'][] = '' . ':número1' . ''; + $b['icons'][] = '' . ':número1' . ''; #Laugh smileys $b['texts'][] = ':jajaja'; - $b['icons'][] = '' . ':jajaja' . ''; + $b['icons'][] = '' . ':jajaja' . ''; $b['texts'][] = ':jajatv'; - $b['icons'][] = '' . ':jajatv' . ''; + $b['icons'][] = '' . ':jajatv' . ''; $b['texts'][] = ':meparto'; - $b['icons'][] = '' . ':meparto' . ''; + $b['icons'][] = '' . ':meparto' . ''; #Music smileys $b['texts'][] = ':dj'; - $b['icons'][] = '' . ':dj' . ''; + $b['icons'][] = '' . ':dj' . ''; $b['texts'][] = ':batería'; - $b['icons'][] = '' . ':batería' . ''; + $b['icons'][] = '' . ':batería' . ''; $b['texts'][] = ':elvis'; - $b['icons'][] = '' . ':elivs' . ''; + $b['icons'][] = '' . ':elivs' . ''; $b['texts'][] = ':guitarra'; - $b['icons'][] = '' . ':guitarra' . ''; + $b['icons'][] = '' . ':guitarra' . ''; $b['texts'][] = ':trompeta'; - $b['icons'][] = '' . ':trompeta' . ''; + $b['icons'][] = '' . ':trompeta' . ''; $b['texts'][] = ':violín'; - $b['icons'][] = '' . ':violín' . ''; + $b['icons'][] = '' . ':violín' . ''; #Smileys that used to be in core $b['texts'][] = ':cabezagolpe'; - $b['icons'][] = '' . ':cabezagolpe' . ''; + $b['icons'][] = '' . ':cabezagolpe' . ''; $b['texts'][] = ':barba'; - $b['icons'][] = '' . ':barba' . ''; + $b['icons'][] = '' . ':barba' . ''; $b['texts'][] = ':barbablanca'; - $b['icons'][] = '' . ':barbablanca' . ''; + $b['icons'][] = '' . ':barbablanca' . ''; $b['texts'][] = ':saludosurf'; - $b['icons'][] = '' . ':saludosurf' . ''; + $b['icons'][] = '' . ':saludosurf' . ''; $b['texts'][] = ':\\.../'; - $b['icons'][] = '' . ':\\.../' . ''; + $b['icons'][] = '' . ':\\.../' . ''; $b['texts'][] = ':\\ooo/'; - $b['icons'][] = '' . ':\\ooo/' . ''; + $b['icons'][] = '' . ':\\ooo/' . ''; $b['texts'][] = ':cabezamesa'; - $b['icons'][] = '' . ':cabezamesa' . ''; + $b['icons'][] = '' . ':cabezamesa' . ''; #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' . ''; + $b['icons'][] = '' . ':-d' . ''; $b['texts'][] = ':-o'; - $b['icons'][] = '' . ':-o' . ''; + $b['icons'][] = '' . ':-o' . ''; 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 63cf613e..feceab26 100644 --- a/smiley_pack/lang/smiley_pack_fr/smiley_pack_fr.php +++ b/smiley_pack/lang/smiley_pack_fr/smiley_pack_fr.php @@ -31,377 +31,377 @@ function smiley_pack_fr_smilies(array &$b) #Animal smileys. $b['texts'][] = ':fleurslapin'; - $b['icons'][] = '' . ':fleurslapin' . ''; + $b['icons'][] = '' . ':fleurslapin' . ''; $b['texts'][] = ':poussin'; - $b['icons'][] = '' . ':poussin' . ''; + $b['icons'][] = '' . ':poussin' . ''; $b['texts'][] = ':bourdon'; - $b['icons'][] = '' . ':bourdon' . ''; + $b['icons'][] = '' . ':bourdon' . ''; $b['texts'][] = ':coccinelle'; - $b['icons'][] = '' . ':coccinelle' . ''; + $b['icons'][] = '' . ':coccinelle' . ''; $b['texts'][] = ':araignée'; - $b['icons'][] = '' . ':araignée' . ''; + $b['icons'][] = '' . ':araignée' . ''; $b['texts'][] = ':chat'; - $b['icons'][] = '' . ':chat' . ''; + $b['icons'][] = '' . ':chat' . ''; $b['texts'][] = ':lapin'; - $b['icons'][] = '' . ':lapin' . ''; + $b['icons'][] = '' . ':lapin' . ''; $b['texts'][] = ':poussin'; - $b['icons'][] = '' . ':poussin' . ''; + $b['icons'][] = '' . ':poussin' . ''; $b['texts'][] = ':vache'; - $b['icons'][] = '' . ':vache' . ''; + $b['icons'][] = '' . ':vache' . ''; $b['texts'][] = ':crabe'; - $b['icons'][] = '' . ':crabe' . ''; + $b['icons'][] = '' . ':crabe' . ''; $b['texts'][] = ':dauphin'; - $b['icons'][] = '' . ':dauphin' . ''; + $b['icons'][] = '' . ':dauphin' . ''; $b['texts'][] = ':libellule'; - $b['icons'][] = '' . ':libellule' . ''; + $b['icons'][] = '' . ':libellule' . ''; $b['texts'][] = ':grenouille'; - $b['icons'][] = '' . ':grenouille' . ''; + $b['icons'][] = '' . ':grenouille' . ''; $b['texts'][] = ':singe'; - $b['icons'][] = '' . ':singe' . ''; + $b['icons'][] = '' . ':singe' . ''; $b['texts'][] = ':cheval'; - $b['icons'][] = '' . ':cheval' . ''; + $b['icons'][] = '' . ':cheval' . ''; $b['texts'][] = ':perroquet'; - $b['icons'][] = '' . ':perroquet' . ''; + $b['icons'][] = '' . ':perroquet' . ''; $b['texts'][] = ':escargot'; - $b['icons'][] = '' . ':escargot' . ''; + $b['icons'][] = '' . ':escargot' . ''; $b['texts'][] = ':mouton'; - $b['icons'][] = '' . ':mouton' . ''; + $b['icons'][] = '' . ':mouton' . ''; $b['texts'][] = ':chien'; - $b['icons'][] = '' . ':chien' . ''; + $b['icons'][] = '' . ':chien' . ''; $b['texts'][] = ':éléphant'; - $b['icons'][] = '' . ':éléphant' . ''; + $b['icons'][] = '' . ':éléphant' . ''; $b['texts'][] = ':poisson'; - $b['icons'][] = '' . ':poisson' . ''; + $b['icons'][] = '' . ':poisson' . ''; $b['texts'][] = ':girafe'; - $b['icons'][] = '' . ':girafe' . ''; + $b['icons'][] = '' . ':girafe' . ''; $b['texts'][] = ':cochon'; - $b['icons'][] = '' . ':cochon' . ''; + $b['icons'][] = '' . ':cochon' . ''; #Baby Smileys $b['texts'][] = ':bébé'; - $b['icons'][] = '' . ':bébé' . ''; + $b['icons'][] = '' . ':bébé' . ''; $b['texts'][] = ':litbébé'; - $b['icons'][] = '' . ':litbébé' . ''; + $b['icons'][] = '' . ':litbébé' . ''; $b['texts'][] = ':enceinte'; - $b['icons'][] = '' . ':enceinte' . ''; + $b['icons'][] = '' . ':enceinte' . ''; $b['texts'][] = ':cigogne'; - $b['icons'][] = '' . ':cigogne' . ''; + $b['icons'][] = '' . ':cigogne' . ''; #Confused Smileys $b['texts'][] = ':paumé'; - $b['icons'][] = '' . ':paumé' . ''; + $b['icons'][] = '' . ':paumé' . ''; $b['texts'][] = ':hausseépaules'; - $b['icons'][] = '' . ':hausseépaules' . ''; + $b['icons'][] = '' . ':hausseépaules' . ''; $b['texts'][] = ':stupide'; - $b['icons'][] = '' . ':stupide' . ''; + $b['icons'][] = '' . ':stupide' . ''; $b['texts'][] = ':hébété'; - $b['icons'][] = '' . ':hébété' . ''; + $b['icons'][] = '' . ':hébété' . ''; #Cool Smileys $b['texts'][] = ':afro'; - $b['icons'][] = '' . ':afro' . ''; + $b['icons'][] = '' . ':afro' . ''; #Devil/Angel Smileys $b['texts'][] = ':ange'; - $b['icons'][] = '' . ':ange' . ''; + $b['icons'][] = '' . ':ange' . ''; $b['texts'][] = ':chérubin'; - $b['icons'][] = '' . ':chérubin' . ''; + $b['icons'][] = '' . ':chérubin' . ''; $b['texts'][] = ':démonange'; - $b['icons'][] = '' . ':démonange' . ''; + $b['icons'][] = '' . ':démonange' . ''; $b['texts'][] = ':diablechat'; - $b['icons'][] = '' . ':diablechat' . ''; + $b['icons'][] = '' . ':diablechat' . ''; $b['texts'][] = ':démoniaque'; - $b['icons'][] = '' . ':démoniaque' . ''; + $b['icons'][] = '' . ':démoniaque' . ''; $b['texts'][] = ':bascule'; - $b['icons'][] = '' . ':bascule' . ''; + $b['icons'][] = '' . ':bascule' . ''; $b['texts'][] = ':possédé'; - $b['icons'][] = '' . ':possédé' . ''; + $b['icons'][] = '' . ':possédé' . ''; $b['texts'][] = ':tombe'; - $b['icons'][] = '' . ':tombe' . ''; + $b['icons'][] = '' . ':tombe' . ''; #Unpleasent smileys. $b['texts'][] = ':toilettes'; - $b['icons'][] = '' . ':toilettes' . ''; + $b['icons'][] = '' . ':toilettes' . ''; $b['texts'][] = ':pèteaulit'; - $b['icons'][] = '' . ':pèteaulit' . ''; + $b['icons'][] = '' . ':pèteaulit' . ''; $b['texts'][] = ':pet'; - $b['icons'][] = '' . ':pet' . ''; + $b['icons'][] = '' . ':pet' . ''; #Drinks $b['texts'][] = ':thé'; - $b['icons'][] = '' . ':thé' . ''; + $b['icons'][] = '' . ':thé' . ''; $b['texts'][] = ':salive'; - $b['icons'][] = '' . ':salive' . ''; + $b['icons'][] = '' . ':salive' . ''; #Sad smileys $b['texts'][] = ':pleure'; - $b['icons'][] = '' . ':pleure' . ''; + $b['icons'][] = '' . ':pleure' . ''; $b['texts'][] = ':prisonnier'; - $b['icons'][] = '' . ':prisonnier' . ''; + $b['icons'][] = '' . ':prisonnier' . ''; $b['texts'][] = ':soupir'; - $b['icons'][] = '' . ':soupir' . ''; + $b['icons'][] = '' . ':soupir' . ''; #Smoking - only one smiley in here, maybe it needs moving elsewhere? $b['texts'][] = ':fume'; - $b['icons'][] = '' . ':fume' . ''; + $b['icons'][] = '' . ':fume' . ''; #Sport smileys $b['texts'][] = ':basket'; - $b['icons'][] = '' . ':basket' . ''; + $b['icons'][] = '' . ':basket' . ''; $b['texts'][] = ':vélo'; - $b['icons'][] = '' . ':vélo' . ''; + $b['icons'][] = '' . ':vélo' . ''; $b['texts'][] = ':fléchettes'; - $b['icons'][] = '' . ':fléchettes' . ''; + $b['icons'][] = '' . ':fléchettes' . ''; $b['texts'][] = ':escrime'; - $b['icons'][] = '' . ':escrime' . ''; + $b['icons'][] = '' . ':escrime' . ''; $b['texts'][] = ':jonglage'; - $b['icons'][] = '' . ':jonglage' . ''; + $b['icons'][] = '' . ':jonglage' . ''; $b['texts'][] = ':sautàlacorde'; - $b['icons'][] = '' . ':sautàlacorde' . ''; + $b['icons'][] = '' . ':sautàlacorde' . ''; $b['texts'][] = ':arc'; - $b['icons'][] = '' . ':arc' . ''; + $b['icons'][] = '' . ':arc' . ''; $b['texts'][] = ':surf'; - $b['icons'][] = '' . ':surf' . ''; + $b['icons'][] = '' . ':surf' . ''; $b['texts'][] = ':billard'; - $b['icons'][] = '' . ':billard' . ''; + $b['icons'][] = '' . ':billard' . ''; $b['texts'][] = ':équitation'; - $b['icons'][] = '' . ':équitation' . ''; + $b['icons'][] = '' . ':équitation' . ''; #Love smileys $b['texts'][] = ':jetaime'; - $b['icons'][] = '' . ':jetaime' . ''; + $b['icons'][] = '' . ':jetaime' . ''; $b['texts'][] = ':amoureux'; - $b['icons'][] = '' . ':amoureux' . ''; + $b['icons'][] = '' . ':amoureux' . ''; $b['texts'][] = ':oursamour'; - $b['icons'][] = '' . ':oursamour' . ''; + $b['icons'][] = '' . ':oursamour' . ''; $b['texts'][] = ':amourlit'; - $b['icons'][] = '' . ':amourlit' . ''; + $b['icons'][] = '' . ':amourlit' . ''; $b['texts'][] = ':coeur'; - $b['icons'][] = '' . ':coeur' . ''; + $b['icons'][] = '' . ':coeur' . ''; #Tired/Sleep smileys $b['texts'][] = ':comptemoutons'; - $b['icons'][] = '' . ':comptemoutons' . ''; + $b['icons'][] = '' . ':comptemoutons' . ''; $b['texts'][] = ':hamac'; - $b['icons'][] = '' . ':hamac' . ''; + $b['icons'][] = '' . ':hamac' . ''; $b['texts'][] = ':oreiller'; - $b['icons'][] = '' . ':oreiller' . ''; + $b['icons'][] = '' . ':oreiller' . ''; $b['texts'][] = ':bâille'; - $b['icons'][] = '' . ':bâille' . ''; + $b['icons'][] = '' . ':bâille' . ''; #Fight/Flame/Violent smileys $b['texts'][] = ':2pistolets'; - $b['icons'][] = '' . ':2pistolets' . ''; + $b['icons'][] = '' . ':2pistolets' . ''; $b['texts'][] = ':combatalien'; - $b['icons'][] = '' . ':combatalien' . ''; + $b['icons'][] = '' . ':combatalien' . ''; $b['texts'][] = ':armée'; - $b['icons'][] = '' . ':armée' . ''; + $b['icons'][] = '' . ':armée' . ''; $b['texts'][] = ':flèche'; - $b['icons'][] = '' . ':flèche' . ''; + $b['icons'][] = '' . ':flèche' . ''; $b['texts'][] = ':bfg'; - $b['icons'][] = '' . ':bfg' . ''; + $b['icons'][] = '' . ':bfg' . ''; $b['texts'][] = ':archer'; - $b['icons'][] = '' . ':archer' . ''; + $b['icons'][] = '' . ':archer' . ''; $b['texts'][] = ':tronçonneuse'; - $b['icons'][] = '' . ':tronçonneuse' . ''; + $b['icons'][] = '' . ':tronçonneuse' . ''; $b['texts'][] = ':arbalète'; - $b['icons'][] = '' . ':arbalète' . ''; + $b['icons'][] = '' . ':arbalète' . ''; $b['texts'][] = ':croisé'; - $b['icons'][] = '' . ':croisé' . ''; + $b['icons'][] = '' . ':croisé' . ''; $b['texts'][] = ':mort'; - $b['icons'][] = '' . ':mort' . ''; + $b['icons'][] = '' . ':mort' . ''; $b['texts'][] = ':marteau'; - $b['icons'][] = '' . ':marteau' . ''; + $b['icons'][] = '' . ':marteau' . ''; $b['texts'][] = ':pistoletlaser'; - $b['icons'][] = '' . ':pistoletlaser' . ''; + $b['icons'][] = '' . ':pistoletlaser' . ''; $b['texts'][] = ':mitrailleuse'; - $b['icons'][] = '' . ':mitrailleuse' . ''; + $b['icons'][] = '' . ':mitrailleuse' . ''; $b['texts'][] = ':acide'; - $b['icons'][] = '' . ':acide' . ''; + $b['icons'][] = '' . ':acide' . ''; #Fantasy smileys - monsters and dragons fantasy. The other type of fantasy belongs in adult smileys $b['texts'][] = ':monstrealien'; - $b['icons'][] = '' . ':monstrealien' . ''; + $b['icons'][] = '' . ':monstrealien' . ''; $b['texts'][] = ':barbare'; - $b['icons'][] = '' . ':barbare' . ''; + $b['icons'][] = '' . ':barbare' . ''; $b['texts'][] = ':dinosaure'; - $b['icons'][] = '' . ':dinosaure' . ''; + $b['icons'][] = '' . ':dinosaure' . ''; $b['texts'][] = ':petitdragon'; - $b['icons'][] = '' . ':petitdragon' . ''; + $b['icons'][] = '' . ':petitdragon' . ''; $b['texts'][] = ':fantôme'; - $b['icons'][] = '' . ':fantôme' . ''; + $b['icons'][] = '' . ':fantôme' . ''; $b['texts'][] = ':momie'; - $b['icons'][] = '' . ':momie' . ''; + $b['icons'][] = '' . ':momie' . ''; #Food smileys $b['texts'][] = ':pomme'; - $b['icons'][] = '' . ':pomme' . ''; + $b['icons'][] = '' . ':pomme' . ''; $b['texts'][] = ':brocoli'; - $b['icons'][] = '' . ':brocoli' . ''; + $b['icons'][] = '' . ':brocoli' . ''; $b['texts'][] = ':gâteau'; - $b['icons'][] = '' . ':gâteau' . ''; + $b['icons'][] = '' . ':gâteau' . ''; $b['texts'][] = ':carotte'; - $b['icons'][] = '' . ':carotte' . ''; + $b['icons'][] = '' . ':carotte' . ''; $b['texts'][] = '~popcorn'; - $b['icons'][] = '' . '~popcorn' . ''; + $b['icons'][] = '' . '~popcorn' . ''; $b['texts'][] = ':tomate'; - $b['icons'][] = '' . ':tomate' . ''; + $b['icons'][] = '' . ':tomate' . ''; $b['texts'][] = ':banane'; - $b['icons'][] = '' . ':banane' . ''; + $b['icons'][] = '' . ':banane' . ''; $b['texts'][] = ':cuisine'; - $b['icons'][] = '' . ':cuisine' . ''; + $b['icons'][] = '' . ':cuisine' . ''; $b['texts'][] = ':oeufauplat'; - $b['icons'][] = '' . ':oeufauplat' . ''; + $b['icons'][] = '' . ':oeufauplat' . ''; #Happy smileys $b['texts'][] = ':nuage'; - $b['icons'][] = '' . ':nuage' . ''; + $b['icons'][] = '' . ':nuage' . ''; $b['texts'][] = ':larmesdejoie'; - $b['icons'][] = '' . ':larmesdejoie' . ''; + $b['icons'][] = '' . ':larmesdejoie' . ''; #Repsect smileys $b['texts'][] = ':courbette'; - $b['icons'][] = '' . ':courbette' . ''; + $b['icons'][] = '' . ':courbette' . ''; $b['texts'][] = ':bravo'; - $b['icons'][] = '' . ':bravo' . ''; + $b['icons'][] = '' . ':bravo' . ''; $b['texts'][] = ':viveleroi'; - $b['icons'][] = '' . ':viveleroi' . ''; + $b['icons'][] = '' . ':viveleroi' . ''; $b['texts'][] = ':numéro1'; - $b['icons'][] = '' . ':numéro1' . ''; + $b['icons'][] = '' . ':numéro1' . ''; #Laugh smileys #Music smileys $b['texts'][] = ':batterie'; - $b['icons'][] = '' . ':batterie' . ''; + $b['icons'][] = '' . ':batterie' . ''; $b['texts'][] = ':guitare'; - $b['icons'][] = '' . ':guitare' . ''; + $b['icons'][] = '' . ':guitare' . ''; $b['texts'][] = ':trompette'; - $b['icons'][] = '' . ':trompette' . ''; + $b['icons'][] = '' . ':trompette' . ''; $b['texts'][] = ':violon'; - $b['icons'][] = '' . ':violon' . ''; + $b['icons'][] = '' . ':violon' . ''; #Smileys that used to be in core $b['texts'][] = ':cognetête'; - $b['icons'][] = '' . ':cognetête' . ''; + $b['icons'][] = '' . ':cognetête' . ''; $b['texts'][] = ':barbu'; - $b['icons'][] = '' . ':barbu' . ''; + $b['icons'][] = '' . ':barbu' . ''; $b['texts'][] = ':barbeblanche'; - $b['icons'][] = '' . ':barbeblanche' . ''; + $b['icons'][] = '' . ':barbeblanche' . ''; $b['texts'][] = ':tête'; - $b['icons'][] = '' . ':tête' . ''; + $b['icons'][] = '' . ':tête' . ''; } diff --git a/smiley_pack/smiley_pack.php b/smiley_pack/smiley_pack.php index 4361b2f5..7892eac4 100644 --- a/smiley_pack/smiley_pack.php +++ b/smiley_pack/smiley_pack.php @@ -28,515 +28,515 @@ function smiley_pack_smilies(array &$b) #Animal smileys. $b['texts'][] = ':bunnyflowers:'; - $b['icons'][] = '' . ':bunnyflowers:' . ''; + $b['icons'][] = '' . ':bunnyflowers:' . ''; $b['texts'][] = ':chick:'; - $b['icons'][] = '' . ':chick:' . ''; + $b['icons'][] = '' . ':chick:' . ''; $b['texts'][] = ':bumblebee:'; - $b['icons'][] = '' . ':bee:' . ''; + $b['icons'][] = '' . ':bee:' . ''; $b['texts'][] = ':ladybird:'; - $b['icons'][] = '' . ':ladybird:' . ''; + $b['icons'][] = '' . ':ladybird:' . ''; $b['texts'][] = ':bigspider:'; - $b['icons'][] = '' . ':bigspider:' . ''; + $b['icons'][] = '' . ':bigspider:' . ''; $b['texts'][] = ':cat:'; - $b['icons'][] = '' . ':cat:' . ''; + $b['icons'][] = '' . ':cat:' . ''; $b['texts'][] = ':bunny:'; - $b['icons'][] = '' . ':bunny:' . ''; + $b['icons'][] = '' . ':bunny:' . ''; $b['texts'][] = ':cow:'; - $b['icons'][] = '' . ':cow:' . ''; + $b['icons'][] = '' . ':cow:' . ''; $b['texts'][] = ':crab:'; - $b['icons'][] = '' . ':crab:' . ''; + $b['icons'][] = '' . ':crab:' . ''; $b['texts'][] = ':dolphin:'; - $b['icons'][] = '' . ':dolphin:' . ''; + $b['icons'][] = '' . ':dolphin:' . ''; $b['texts'][] = ':dragonfly:'; - $b['icons'][] = '' . ':dragonfly:' . ''; + $b['icons'][] = '' . ':dragonfly:' . ''; $b['texts'][] = ':frog:'; - $b['icons'][] = '' . ':frog:' . ''; + $b['icons'][] = '' . ':frog:' . ''; $b['texts'][] = ':hamster:'; - $b['icons'][] = '' . ':hamster:' . ''; + $b['icons'][] = '' . ':hamster:' . ''; $b['texts'][] = ':monkey:'; - $b['icons'][] = '' . ':monkey:' . ''; + $b['icons'][] = '' . ':monkey:' . ''; $b['texts'][] = ':horse:'; - $b['icons'][] = '' . ':horse:' . ''; + $b['icons'][] = '' . ':horse:' . ''; $b['texts'][] = ':parrot:'; - $b['icons'][] = '' . ':parrot:' . ''; + $b['icons'][] = '' . ':parrot:' . ''; $b['texts'][] = ':tux:'; - $b['icons'][] = '' . ':tux:' . ''; + $b['icons'][] = '' . ':tux:' . ''; $b['texts'][] = ':snail:'; - $b['icons'][] = '' . ':snail:' . ''; + $b['icons'][] = '' . ':snail:' . ''; $b['texts'][] = ':sheep:'; - $b['icons'][] = '' . ':sheep:' . ''; + $b['icons'][] = '' . ':sheep:' . ''; $b['texts'][] = ':dog:'; - $b['icons'][] = '' . ':dog:' . ''; + $b['icons'][] = '' . ':dog:' . ''; $b['texts'][] = ':elephant:'; - $b['icons'][] = '' . ':elephant:' . ''; + $b['icons'][] = '' . ':elephant:' . ''; $b['texts'][] = ':fish:'; - $b['icons'][] = '' . ':fish:' . ''; + $b['icons'][] = '' . ':fish:' . ''; $b['texts'][] = ':giraffe:'; - $b['icons'][] = '' . ':giraffe:' . ''; + $b['icons'][] = '' . ':giraffe:' . ''; $b['texts'][] = ':pig:'; - $b['icons'][] = '' . ':pig:' . ''; + $b['icons'][] = '' . ':pig:' . ''; #Baby Smileys $b['texts'][] = ':baby:'; - $b['icons'][] = '' . ':baby:' . ''; + $b['icons'][] = '' . ':baby:' . ''; $b['texts'][] = ':babycot:'; - $b['icons'][] = '' . ':babycot:' . ''; + $b['icons'][] = '' . ':babycot:' . ''; $b['texts'][] = ':pregnant:'; - $b['icons'][] = '' . ':pregnant:' . ''; + $b['icons'][] = '' . ':pregnant:' . ''; $b['texts'][] = ':stork:'; - $b['icons'][] = '' . ':stork:' . ''; + $b['icons'][] = '' . ':stork:' . ''; #Confused Smileys $b['texts'][] = ':confused:'; - $b['icons'][] = '' . ':confused:' . ''; + $b['icons'][] = '' . ':confused:' . ''; $b['texts'][] = ':shrug:'; - $b['icons'][] = '' . ':shrug:' . ''; + $b['icons'][] = '' . ':shrug:' . ''; $b['texts'][] = ':stupid:'; - $b['icons'][] = '' . ':stupid:' . ''; + $b['icons'][] = '' . ':stupid:' . ''; $b['texts'][] = ':dazed:'; - $b['icons'][] = '' . ':dazed:' . ''; + $b['icons'][] = '' . ':dazed:' . ''; #Cool Smileys $b['texts'][] = ':affro:'; - $b['icons'][] = '' . ':affro:' . ''; + $b['icons'][] = '' . ':affro:' . ''; #Devil/Angel Smileys $b['texts'][] = ':angel:'; - $b['icons'][] = '' . ':angel:' . ''; + $b['icons'][] = '' . ':angel:' . ''; $b['texts'][] = ':cherub:'; - $b['icons'][] = '' . ':cherub:' . ''; + $b['icons'][] = '' . ':cherub:' . ''; $b['texts'][] = ':devilangel:'; - $b['icons'][] = '' . ':devilangel:' . ''; + $b['icons'][] = '' . ':devilangel:' . ''; $b['texts'][] = ':catdevil:'; - $b['icons'][] = '' . ':catdevil:' . ''; + $b['icons'][] = '' . ':catdevil:' . ''; $b['texts'][] = ':devillish:'; - $b['icons'][] = '' . ':devillish:' . ''; + $b['icons'][] = '' . ':devillish:' . ''; $b['texts'][] = ':daseesaw:'; - $b['icons'][] = '' . ':daseesaw:' . ''; + $b['icons'][] = '' . ':daseesaw:' . ''; $b['texts'][] = ':turnevil:'; - $b['icons'][] = '' . ':turnevil:' . ''; + $b['icons'][] = '' . ':turnevil:' . ''; $b['texts'][] = ':saint:'; - $b['icons'][] = '' . ':saint:' . ''; + $b['icons'][] = '' . ':saint:' . ''; $b['texts'][] = ':graveside:'; - $b['icons'][] = '' . ':graveside:' . ''; + $b['icons'][] = '' . ':graveside:' . ''; #Unpleasent smileys. $b['texts'][] = ':toilet:'; - $b['icons'][] = '' . ':toilet:' . ''; + $b['icons'][] = '' . ':toilet:' . ''; $b['texts'][] = ':fartinbed:'; - $b['icons'][] = '' . ':fartinbed:' . ''; + $b['icons'][] = '' . ':fartinbed:' . ''; $b['texts'][] = ':fartblush:'; - $b['icons'][] = '' . ':fartblush:' . ''; + $b['icons'][] = '' . ':fartblush:' . ''; #Drinks $b['texts'][] = ':tea:'; - $b['icons'][] = '' . ':tea:' . ''; + $b['icons'][] = '' . ':tea:' . ''; $b['texts'][] = ':drool:'; - $b['icons'][] = '' . ':drool:' . ''; + $b['icons'][] = '' . ':drool:' . ''; #Sad smileys $b['texts'][] = ':crying:'; - $b['icons'][] = '' . ':crying:' . ''; + $b['icons'][] = '' . ':crying:' . ''; $b['texts'][] = ':prisoner:'; - $b['icons'][] = '' . ':prisoner:' . ''; + $b['icons'][] = '' . ':prisoner:' . ''; $b['texts'][] = ':sigh:'; - $b['icons'][] = '' . ':sigh:' . ''; + $b['icons'][] = '' . ':sigh:' . ''; #Smoking - only one smiley in here, maybe it needs moving elsewhere? $b['texts'][] = ':smoking:'; - $b['icons'][] = '' . ':smoking:' . ''; + $b['icons'][] = '' . ':smoking:' . ''; #Sport smileys $b['texts'][] = ':basketball:'; - $b['icons'][] = '' . ':basketball:' . ''; + $b['icons'][] = '' . ':basketball:' . ''; $b['texts'][] = '~bowling'; - $b['icons'][] = '' . '~bowling' . ''; + $b['icons'][] = '' . '~bowling' . ''; $b['texts'][] = ':cycling:'; - $b['icons'][] = '' . ':cycling:' . ''; + $b['icons'][] = '' . ':cycling:' . ''; $b['texts'][] = ':darts:'; - $b['icons'][] = '' . ':darts:' . ''; + $b['icons'][] = '' . ':darts:' . ''; $b['texts'][] = ':fencing:'; - $b['icons'][] = '' . ':fencing:' . ''; + $b['icons'][] = '' . ':fencing:' . ''; $b['texts'][] = ':juggling:'; - $b['icons'][] = '' . ':juggling:' . ''; + $b['icons'][] = '' . ':juggling:' . ''; $b['texts'][] = ':skipping:'; - $b['icons'][] = '' . ':skipping:' . ''; + $b['icons'][] = '' . ':skipping:' . ''; $b['texts'][] = ':archery:'; - $b['icons'][] = '' . ':archery:' . ''; + $b['icons'][] = '' . ':archery:' . ''; $b['texts'][] = ':surfing:'; - $b['icons'][] = '' . ':surfing:' . ''; + $b['icons'][] = '' . ':surfing:' . ''; $b['texts'][] = ':snooker:'; - $b['icons'][] = '' . ':snooker:' . ''; + $b['icons'][] = '' . ':snooker:' . ''; $b['texts'][] = ':horseriding:'; - $b['icons'][] = '' . ':horseriding:' . ''; + $b['icons'][] = '' . ':horseriding:' . ''; #Love smileys $b['texts'][] = ':iloveyou:'; - $b['icons'][] = '' . ':iloveyou:' . ''; + $b['icons'][] = '' . ':iloveyou:' . ''; $b['texts'][] = ':inlove:'; - $b['icons'][] = '' . ':inlove:' . ''; + $b['icons'][] = '' . ':inlove:' . ''; $b['texts'][] = '~love'; - $b['icons'][] = '' . ':love' . ''; + $b['icons'][] = '' . ':love' . ''; $b['texts'][] = ':lovebear:'; - $b['icons'][] = '' . ':lovebear:' . ''; + $b['icons'][] = '' . ':lovebear:' . ''; $b['texts'][] = ':lovebed:'; - $b['icons'][] = '' . ':lovebed:' . ''; + $b['icons'][] = '' . ':lovebed:' . ''; $b['texts'][] = ':loveheart:'; - $b['icons'][] = '' . ':loveheart:' . ''; + $b['icons'][] = '' . ':loveheart:' . ''; #Tired/Sleep smileys $b['texts'][] = ':countsheep'; - $b['icons'][] = '' . ':countsheep:' . ''; + $b['icons'][] = '' . ':countsheep:' . ''; $b['texts'][] = ':hammock:'; - $b['icons'][] = '' . ':hammock:' . ''; + $b['icons'][] = '' . ':hammock:' . ''; $b['texts'][] = ':pillow:'; - $b['icons'][] = '' . ':pillow:' . ''; + $b['icons'][] = '' . ':pillow:' . ''; $b['texts'][] = ':yawn:'; - $b['icons'][] = '' . ':yawn:' . ''; + $b['icons'][] = '' . ':yawn:' . ''; #Fight/Flame/Violent smileys $b['texts'][] = ':2guns:'; - $b['icons'][] = '' . ':2guns:' . ''; + $b['icons'][] = '' . ':2guns:' . ''; $b['texts'][] = ':alienfight'; - $b['icons'][] = '' . ':alienfight' . ''; + $b['icons'][] = '' . ':alienfight' . ''; $b['texts'][] = ':army:'; - $b['icons'][] = '' . ':army:' . ''; + $b['icons'][] = '' . ':army:' . ''; $b['texts'][] = ':arrowhead:'; - $b['icons'][] = '' . ':arrowhead:' . ''; + $b['icons'][] = '' . ':arrowhead:' . ''; $b['texts'][] = ':bfg:'; - $b['icons'][] = '' . ':bfg:' . ''; + $b['icons'][] = '' . ':bfg:' . ''; $b['texts'][] = ':bowman:'; - $b['icons'][] = '' . ':bowman:' . ''; + $b['icons'][] = '' . ':bowman:' . ''; $b['texts'][] = ':chainsaw:'; - $b['icons'][] = '' . ':chainsaw:' . ''; + $b['icons'][] = '' . ':chainsaw:' . ''; $b['texts'][] = ':crossbow:'; - $b['icons'][] = '' . ':crossbow:' . ''; + $b['icons'][] = '' . ':crossbow:' . ''; $b['texts'][] = ':crusader:'; - $b['icons'][] = '' . ':crusader:' . ''; + $b['icons'][] = '' . ':crusader:' . ''; $b['texts'][] = ':dead:'; - $b['icons'][] = '' . ':dead:' . ''; + $b['icons'][] = '' . ':dead:' . ''; $b['texts'][] = ':hammersplat:'; - $b['icons'][] = '' . ':hammersplat:' . ''; + $b['icons'][] = '' . ':hammersplat:' . ''; $b['texts'][] = ':lasergun:'; - $b['icons'][] = '' . ':lasergun:' . ''; + $b['icons'][] = '' . ':lasergun:' . ''; $b['texts'][] = ':machinegun:'; - $b['icons'][] = '' . ':machinegun:' . ''; + $b['icons'][] = '' . ':machinegun:' . ''; $b['texts'][] = ':acid:'; - $b['icons'][] = '' . ':acid:' . ''; + $b['icons'][] = '' . ':acid:' . ''; #Fantasy smileys - monsters and dragons fantasy. The other type of fantasy belongs in adult smileys $b['texts'][] = ':alienmonster:'; - $b['icons'][] = '' . ':alienmonster:' . ''; + $b['icons'][] = '' . ':alienmonster:' . ''; $b['texts'][] = ':barbarian:'; - $b['icons'][] = '' . ':barbarian:' . ''; + $b['icons'][] = '' . ':barbarian:' . ''; $b['texts'][] = ':dinosaur:'; - $b['icons'][] = '' . ':dinosaur:' . ''; + $b['icons'][] = '' . ':dinosaur:' . ''; $b['texts'][] = ':dragon:'; - $b['icons'][] = '' . ':dragon:' . ''; + $b['icons'][] = '' . ':dragon:' . ''; $b['texts'][] = ':draco:'; - $b['icons'][] = '' . ':draco:' . ''; + $b['icons'][] = '' . ':draco:' . ''; $b['texts'][] = ':ghost:'; - $b['icons'][] = '' . ':ghost:' . ''; + $b['icons'][] = '' . ':ghost:' . ''; $b['texts'][] = ':mummy:'; - $b['icons'][] = '' . ':mummy:' . ''; + $b['icons'][] = '' . ':mummy:' . ''; #Food smileys $b['texts'][] = ':apple:'; - $b['icons'][] = '' . ':apple:' . ''; + $b['icons'][] = '' . ':apple:' . ''; $b['texts'][] = ':broccoli:'; - $b['icons'][] = '' . ':brocolli:' . ''; + $b['icons'][] = '' . ':brocolli:' . ''; $b['texts'][] = ':cake:'; - $b['icons'][] = '' . ':cake:' . ''; + $b['icons'][] = '' . ':cake:' . ''; $b['texts'][] = ':carrot:'; - $b['icons'][] = '' . ':carrot:' . ''; + $b['icons'][] = '' . ':carrot:' . ''; $b['texts'][] = ':popcorn:'; - $b['icons'][] = '' . ':popcorn:' . ''; + $b['icons'][] = '' . ':popcorn:' . ''; $b['texts'][] = ':tomato:'; - $b['icons'][] = '' . ':tomato:' . ''; + $b['icons'][] = '' . ':tomato:' . ''; $b['texts'][] = ':banana:'; - $b['icons'][] = '' . ':banana:' . ''; + $b['icons'][] = '' . ':banana:' . ''; $b['texts'][] = ':cooking:'; - $b['icons'][] = '' . ':cooking:' . ''; + $b['icons'][] = '' . ':cooking:' . ''; $b['texts'][] = ':fryegg:'; - $b['icons'][] = '' . ':fryegg:' . ''; + $b['icons'][] = '' . ':fryegg:' . ''; $b['texts'][] = ':birthdaycake:'; - $b['icons'][] = '' . ':birthdaycake:' . ''; + $b['icons'][] = '' . ':birthdaycake:' . ''; #Happy smileys $b['texts'][] = ':cloud9:'; - $b['icons'][] = '' . ':cloud9:' . ''; + $b['icons'][] = '' . ':cloud9:' . ''; $b['texts'][] = ':tearsofjoy:'; - $b['icons'][] = '' . ':tearsofjoy:' . ''; + $b['icons'][] = '' . ':tearsofjoy:' . ''; #Repsect smileys $b['texts'][] = ':bow:'; - $b['icons'][] = '' . ':bow:' . ''; + $b['icons'][] = '' . ':bow:' . ''; $b['texts'][] = ':bravo:'; - $b['icons'][] = '' . ':bravo:' . ''; + $b['icons'][] = '' . ':bravo:' . ''; $b['texts'][] = ':hailking:'; - $b['icons'][] = '' . ':hailking:' . ''; + $b['icons'][] = '' . ':hailking:' . ''; $b['texts'][] = ':number1:'; - $b['icons'][] = '' . ':number1:' . ''; + $b['icons'][] = '' . ':number1:' . ''; #Laugh smileys $b['texts'][] = ':hahaha:'; - $b['icons'][] = '' . ':hahaha:' . ''; + $b['icons'][] = '' . ':hahaha:' . ''; $b['texts'][] = ':loltv:'; - $b['icons'][] = '' . ':loltv:' . ''; + $b['icons'][] = '' . ':loltv:' . ''; $b['texts'][] = ':rofl:'; - $b['icons'][] = '' . ':rofl:' . ''; + $b['icons'][] = '' . ':rofl:' . ''; #Music smileys $b['texts'][] = ':drums:'; - $b['icons'][] = '' . ':drums:' . ''; + $b['icons'][] = '' . ':drums:' . ''; $b['texts'][] = ':guitar:'; - $b['icons'][] = '' . ':guitar:' . ''; + $b['icons'][] = '' . ':guitar:' . ''; $b['texts'][] = ':trumpet:'; - $b['icons'][] = '' . ':trumpet:' . ''; + $b['icons'][] = '' . ':trumpet:' . ''; #Smileys that used to be in core $b['texts'][] = ':headbang:'; - $b['icons'][] = '' . ':headbang:' . ''; + $b['icons'][] = '' . ':headbang:' . ''; $b['texts'][] = ':beard:'; - $b['icons'][] = '' . ':beard:' . ''; + $b['icons'][] = '' . ':beard:' . ''; $b['texts'][] = ':whitebeard:'; - $b['icons'][] = '' . ':whitebeard:' . ''; + $b['icons'][] = '' . ':whitebeard:' . ''; $b['texts'][] = ':shaka:'; - $b['icons'][] = '' . ':shaka:' . ''; + $b['icons'][] = '' . ':shaka:' . ''; $b['texts'][] = ':\\.../'; - $b['icons'][] = '' . ':\\.../' . ''; + $b['icons'][] = '' . ':\\.../' . ''; $b['texts'][] = ':\\ooo/'; - $b['icons'][] = '' . ':\\ooo/' . ''; + $b['icons'][] = '' . ':\\ooo/' . ''; $b['texts'][] = ':headdesk:'; - $b['icons'][] = '' . ':headdesk:' . ''; + $b['icons'][] = '' . ':headdesk:' . ''; #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' . ''; + $b['icons'][] = '' . ':-d' . ''; $b['texts'][] = ':-o'; - $b['icons'][] = '' . ':-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. $b['texts'][] = ':cool:'; - $b['icons'][] = '' . ':cool:' . ''; + $b['icons'][] = '' . ':cool:' . ''; $b['texts'][] = ':vomit:'; - $b['icons'][] = '' . ':vomit:' . ''; + $b['icons'][] = '' . ':vomit:' . ''; $b['texts'][] = ':golf:'; - $b['icons'][] = '' . ':golf:' . ''; + $b['icons'][] = '' . ':golf:' . ''; $b['texts'][] = ':football:'; - $b['icons'][] = '' . ':football:' . ''; + $b['icons'][] = '' . ':football:' . ''; $b['texts'][] = ':tennis:'; - $b['icons'][] = '' . ':tennis:' . ''; + $b['icons'][] = '' . ':tennis:' . ''; $b['texts'][] = ':alpha:'; - $b['icons'][] = '' . ':alpha:' . ''; + $b['icons'][] = '' . ':alpha:' . ''; $b['texts'][] = ':marine:'; - $b['icons'][] = '' . ':marine:' . ''; + $b['icons'][] = '' . ':marine:' . ''; $b['texts'][] = ':sabre:'; - $b['icons'][] = '' . ':sabre:' . ''; + $b['icons'][] = '' . ':sabre:' . ''; $b['texts'][] = ':tank:'; - $b['icons'][] = '' . ':tank:' . ''; + $b['icons'][] = '' . ':tank:' . ''; $b['texts'][] = ':viking:'; - $b['icons'][] = '' . ':viking:' . ''; + $b['icons'][] = '' . ':viking:' . ''; $b['texts'][] = ':gangs:'; - $b['icons'][] = '' . ':gangs:' . ''; + $b['icons'][] = '' . ':gangs:' . ''; $b['texts'][] = ':dj:'; - $b['icons'][] = '' . ':dj:' . ''; + $b['icons'][] = '' . ':dj:' . ''; $b['texts'][] = ':elvis:'; - $b['icons'][] = '' . ':elivs:' . ''; + $b['icons'][] = '' . ':elivs:' . ''; $b['texts'][] = ':violin:'; - $b['icons'][] = '' . ':violin:' . ''; + $b['icons'][] = '' . ':violin:' . ''; # New Gif Emoji (@one@loma.ml) # Fediverse $b['texts'][] = ':friendica:'; - $b['icons'][] = '' . ':friendica:' . ''; + $b['icons'][] = '' . ':friendica:' . ''; $b['texts'][] = ':mastodon:'; - $b['icons'][] = '' . ':mastodon:' . ''; + $b['icons'][] = '' . ':mastodon:' . ''; $b['texts'][] = ':pleroma:'; - $b['icons'][] = '' . ':pleroma:' . ''; + $b['icons'][] = '' . ':pleroma:' . ''; $b['texts'][] = ':misskey:'; - $b['icons'][] = '' . ':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['icons'][] = '' . ':pixelfeed:' . ''; $b['texts'][] = ':nextcloud:'; - $b['icons'][] = '' . ':nextcloud:' . ''; + $b['icons'][] = '' . ':nextcloud:' . ''; $b['texts'][] = ':activitypub:'; - $b['icons'][] = '' . ':activitypub:' . ''; + $b['icons'][] = '' . ':activitypub:' . ''; # ccc $b['texts'][] = ':ccc event:'; - $b['icons'][] = '' . ':ccc event:' . ''; + $b['icons'][] = '' . ':ccc event:' . ''; # Commercial $b['texts'][] = ':youtube:'; - $b['icons'][] = '' . ':youtube:' . ''; + $b['icons'][] = '' . ':youtube:' . ''; $b['texts'][] = ':spotify:'; - $b['icons'][] = '' . ':spotify:' . ''; + $b['icons'][] = '' . ':spotify:' . ''; $b['texts'][] = ':twitter:'; - $b['icons'][] = '' . ':twitter:' . ''; + $b['icons'][] = '' . ':twitter:' . ''; $b['texts'][] = ':twitch:'; - $b['icons'][] = '' . ':twitch:' . ''; + $b['icons'][] = '' . ':twitch:' . ''; } diff --git a/smileybutton/lang/cs/messages.po b/smileybutton/lang/cs/messages.po index b3e000e4..71059896 100644 --- a/smileybutton/lang/cs/messages.po +++ b/smileybutton/lang/cs/messages.po @@ -4,25 +4,24 @@ # # # Translators: -# Aditoo, 2018 -# michal_s , 2014 +# Michal Šupler , 2014 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2014-06-23 14:45+0200\n" -"PO-Revision-Date: 2014-06-23 12:45+0000\n" -"Last-Translator: Aditoo, 2018\n" -"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" +"PO-Revision-Date: 2014-07-28 18:15+0000\n" +"Last-Translator: Michal Šupler \n" +"Language-Team: Czech (http://www.transifex.com/projects/p/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" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" #: smileybutton.php:269 msgid "Smileybutton settings" -msgstr "Nastavení Smileybutton" +msgstr "Smileybutton nastavení" #: smileybutton.php:272 msgid "You can hide the button and show the smilies directly." diff --git a/smileybutton/lang/cs/strings.php b/smileybutton/lang/cs/strings.php index 61be9078..20618968 100644 --- a/smileybutton/lang/cs/strings.php +++ b/smileybutton/lang/cs/strings.php @@ -3,9 +3,9 @@ if(! function_exists("string_plural_select_cs")) { function string_plural_select_cs($n){ $n = intval($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; } + if (($n==1)) { return 0; } else if (($n>=2 && $n<=4)) { return 1; } else { return 2; } }} -$a->strings['Smileybutton settings'] = 'Nastavení Smileybutton'; +$a->strings['Smileybutton settings'] = 'Smileybutton nastavení'; $a->strings['You can hide the button and show the smilies directly.'] = 'Můžete skrýt tlačítko a zobrazit rovnou smajlíky.'; $a->strings['Hide the button'] = 'Skrýt tlačítko'; $a->strings['Save Settings'] = 'Uložit Nastavení'; diff --git a/smileybutton/lang/de/messages.po b/smileybutton/lang/de/messages.po index 3d98c0f7..fd2cf54c 100644 --- a/smileybutton/lang/de/messages.po +++ b/smileybutton/lang/de/messages.po @@ -11,9 +11,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2014-06-23 14:45+0200\n" -"PO-Revision-Date: 2014-06-23 12:45+0000\n" -"Last-Translator: Ulf Rompe , 2019\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2019-02-11 13:35+0000\n" +"Last-Translator: Ulf Rompe \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/smileybutton/lang/hu/messages.po b/smileybutton/lang/hu/messages.po index 202a959f..f5cf3363 100644 --- a/smileybutton/lang/hu/messages.po +++ b/smileybutton/lang/hu/messages.po @@ -12,7 +12,7 @@ msgstr "" "POT-Creation-Date: 2014-06-23 14:45+0200\n" "PO-Revision-Date: 2014-06-23 12:45+0000\n" "Last-Translator: Balázs Úr, 2020-2021\n" -"Language-Team: Hungarian (http://app.transifex.com/Friendica/friendica/language/hu/)\n" +"Language-Team: Hungarian (http://www.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" diff --git a/smileybutton/lang/it/strings.php b/smileybutton/lang/it/strings.php index 766bf048..c3edc703 100644 --- a/smileybutton/lang/it/strings.php +++ b/smileybutton/lang/it/strings.php @@ -2,10 +2,10 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ - $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return ($n != 1);; }} -$a->strings['Smileybutton settings'] = 'Impostazioni "Bottone faccine"'; -$a->strings['You can hide the button and show the smilies directly.'] = 'Puoi nascondere il bottone e mostrare le faccine direttamente.'; -$a->strings['Hide the button'] = 'Nascondi il bottone'; -$a->strings['Save Settings'] = 'Salva Impostazioni'; +; +$a->strings["Smileybutton settings"] = "Impostazioni \"Bottone faccine\""; +$a->strings["You can hide the button and show the smilies directly."] = "Puoi nascondere il bottone e mostrare le faccine direttamente."; +$a->strings["Hide the button"] = "Nascondi il bottone"; +$a->strings["Save Settings"] = "Salva Impostazioni"; diff --git a/smileybutton/smileybutton.php b/smileybutton/smileybutton.php index 1df717b7..1f931099 100644 --- a/smileybutton/smileybutton.php +++ b/smileybutton/smileybutton.php @@ -56,29 +56,29 @@ function smileybutton_jot_tool(string &$body) ]; $icons = [ - '<3', - '</3', - ':-)', - ';-)', - ':-(', - ':-P', - ':-X', - ':-D', - ':-O', - '\\o/', - 'O_o', - ':\'(', - ':-!', - ':-/', - ':-[', - '8-)', - ':beer', - ':coffee', - ':facepalm', - ':like', - ':dislike', - '~friendica', - 'red' + '<3', + '</3', + ':-)', + ';-)', + ':-(', + ':-P', + ':-X', + ':-D', + ':-O', + '\\o/', + 'O_o', + ':\'(', + ':-!', + ':-/', + ':-[', + '8-)', + ':beer', + ':coffee', + ':facepalm', + ':like', + ':dislike', + '~friendica', + 'red' ]; // Call hooks to get aditional smileies from other addons @@ -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) % (floor(sqrt(count($params['texts']))) + 1) == 0) { + if (($x + 1) % (sqrt(count($params['texts'])) + 1) == 0) { $s .= ''; } } @@ -110,7 +110,7 @@ function smileybutton_jot_tool(string &$body) $image = 'addon/smileybutton/view/default.png'; } - $image_url = DI::baseUrl() . '/' . $image; + $image_url = DI::baseUrl()->get() . '/' . $image; //Add the hmtl and script to the page $body = <<< EOT diff --git a/smilies_adult/smilies_adult.php b/smilies_adult/smilies_adult.php index e8af21e1..a7e0c383 100644 --- a/smilies_adult/smilies_adult.php +++ b/smilies_adult/smilies_adult.php @@ -20,20 +20,20 @@ function smilies_adult_install() { function smilies_adult_smilies(array &$b) { $b['texts'][] = '(o)(o)'; - $b['icons'][] = '' . '(o)(o)' . ''; + $b['icons'][] = '' . '(o)(o)' . ''; $b['texts'][] = '(.)(.)'; - $b['icons'][] = '' . '(.)(.)' . ''; + $b['icons'][] = '' . '(.)(.)' . ''; $b['texts'][] = ':bong'; - $b['icons'][] = '' . ':bong' . ''; + $b['icons'][] = '' . ':bong' . ''; $b['texts'][] = ':sperm'; - $b['icons'][] = '' . ':sperm' . ''; + $b['icons'][] = '' . ':sperm' . ''; $b['texts'][] = ':drunk'; - $b['icons'][] = '' . ':drunk' . ''; + $b['icons'][] = '' . ':drunk' . ''; $b['texts'][] = ':finger'; - $b['icons'][] = '' . ':finger' . ''; + $b['icons'][] = '' . ':finger' . ''; } diff --git a/startpage/lang/de/messages.po b/startpage/lang/de/messages.po index f8b4ddbc..62adb1cc 100644 --- a/startpage/lang/de/messages.po +++ b/startpage/lang/de/messages.po @@ -11,9 +11,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:16-0500\n" -"PO-Revision-Date: 2014-06-23 12:51+0000\n" -"Last-Translator: Tobias Diekershoff , 2021-2022\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2022-01-22 17:40+0000\n" +"Last-Translator: Tobias Diekershoff \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/startpage/lang/it/messages.po b/startpage/lang/it/messages.po index efabb8f0..a4305d27 100644 --- a/startpage/lang/it/messages.po +++ b/startpage/lang/it/messages.po @@ -5,29 +5,33 @@ # # Translators: # fabrixxm , 2014-2015 -# Sylke Vicious , 2021,2023 +# Sylke Vicious , 2021 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:16-0500\n" -"PO-Revision-Date: 2014-06-23 12:51+0000\n" -"Last-Translator: Sylke Vicious , 2021,2023\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"POT-Creation-Date: 2021-02-01 18:15+0100\n" +"PO-Revision-Date: 2021-02-16 12:47+0000\n" +"Last-Translator: Sylke Vicious \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: startpage.php:70 +#: startpage.php:74 startpage.php:78 +msgid "Startpage" +msgstr "Pagina iniziale" + +#: startpage.php:81 msgid "Home page to load after login - leave blank for profile wall" msgstr "Home page da caricare dopo il login - lasciare in bianco per la bacheca" -#: startpage.php:70 -msgid "Examples: \"network\" or \"notifications/system\"" -msgstr "Esempi: \"rete\" o \"notifiche/sistema\"" +#: startpage.php:84 +msgid "Examples: "network" or "notifications/system"" +msgstr "Esempi: "network" or "notifications/system"" -#: startpage.php:75 -msgid "Startpage" -msgstr "Pagina iniziale" +#: startpage.php:88 +msgid "Save Settings" +msgstr "Salva Impostazioni" diff --git a/startpage/lang/it/strings.php b/startpage/lang/it/strings.php index 111a2abb..b253a774 100644 --- a/startpage/lang/it/strings.php +++ b/startpage/lang/it/strings.php @@ -3,8 +3,9 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} -$a->strings['Home page to load after login - leave blank for profile wall'] = 'Home page da caricare dopo il login - lasciare in bianco per la bacheca'; -$a->strings['Examples: "network" or "notifications/system"'] = 'Esempi: "rete" o "notifiche/sistema"'; $a->strings['Startpage'] = 'Pagina iniziale'; +$a->strings['Home page to load after login - leave blank for profile wall'] = 'Home page da caricare dopo il login - lasciare in bianco per la bacheca'; +$a->strings['Examples: "network" or "notifications/system"'] = 'Esempi: "network" or "notifications/system"'; +$a->strings['Save Settings'] = 'Salva Impostazioni'; diff --git a/statusnet/lang/ar/messages.po b/statusnet/lang/ar/messages.po index 89352f37..96722c86 100644 --- a/statusnet/lang/ar/messages.po +++ b/statusnet/lang/ar/messages.po @@ -10,40 +10,40 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-12-21 22:32+0000\n" +"POT-Creation-Date: 2021-11-21 19:17-0500\n" "PO-Revision-Date: 2014-06-23 12:54+0000\n" "Last-Translator: ButterflyOfFire, 2022\n" -"Language-Team: Arabic (http://app.transifex.com/Friendica/friendica/language/ar/)\n" +"Language-Team: Arabic (http://www.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" -#: statusnet.php:76 +#: statusnet.php:97 msgid "Post to GNU Social" msgstr "" -#: statusnet.php:122 +#: statusnet.php:148 msgid "" "Please contact your site administrator.
The provided API URL is not " "valid." msgstr "" -#: statusnet.php:150 +#: statusnet.php:176 msgid "We could not contact the GNU Social API with the Path you entered." msgstr "" -#: statusnet.php:208 statusnet.php:489 +#: statusnet.php:243 statusnet.php:656 msgid "Save Settings" msgstr "حفظ الإعدادات" -#: statusnet.php:220 +#: statusnet.php:255 #, php-format msgid "Currently connected to: %s" msgstr "" -#: statusnet.php:225 +#: statusnet.php:260 msgid "" "Note: Due your privacy settings (Hide your profile " "details from unknown viewers?) the link potentially included in public " @@ -51,30 +51,30 @@ msgid "" "informing the visitor that the access to your profile has been restricted." msgstr "" -#: statusnet.php:228 +#: statusnet.php:263 msgid "Clear OAuth configuration" msgstr "" -#: statusnet.php:240 +#: statusnet.php:275 msgid "Cancel GNU Social Connection" msgstr "" -#: statusnet.php:247 +#: statusnet.php:283 msgid "Globally Available GNU Social OAuthKeys" msgstr "" -#: statusnet.php:248 +#: statusnet.php:284 msgid "" "There are preconfigured OAuth key pairs for some GNU Social servers " "available. If you are using one of them, please use these credentials. If " "not feel free to connect to any other GNU Social instance (see below)." msgstr "" -#: statusnet.php:249 +#: statusnet.php:285 msgid "Provide your own OAuth Credentials" msgstr "" -#: statusnet.php:250 +#: statusnet.php:286 msgid "" "No consumer key pair for GNU Social found. Register your Friendica Account " "as a desktop application on your GNU Social account, copy the consumer key " @@ -83,7 +83,7 @@ msgid "" " Friendica installation at your favorite GNU Social installation." msgstr "" -#: statusnet.php:251 +#: statusnet.php:287 msgid "" "To connect to your GNU Social account click the button below to get a " "security code from GNU Social which you have to copy into the input box " @@ -91,62 +91,86 @@ msgid "" "posted to GNU Social." msgstr "" -#: statusnet.php:252 +#: statusnet.php:288 msgid "Log in with GNU Social" msgstr "" -#: statusnet.php:253 +#: statusnet.php:289 msgid "Cancel Connection Process" msgstr "" -#: statusnet.php:254 +#: statusnet.php:290 #, php-format msgid "Current GNU Social API is: %s" msgstr "" -#: statusnet.php:271 +#: statusnet.php:307 msgid "OAuth Consumer Key" msgstr "" -#: statusnet.php:272 +#: statusnet.php:308 msgid "OAuth Consumer Secret" msgstr "" -#: statusnet.php:274 statusnet.php:469 statusnet.php:481 +#: statusnet.php:310 statusnet.php:636 statusnet.php:648 msgid "Base API Path (remember the trailing /)" msgstr "" -#: statusnet.php:275 +#: statusnet.php:311 msgid "Copy the security code from GNU Social here" msgstr "" -#: statusnet.php:277 +#: statusnet.php:313 msgid "Allow posting to GNU Social" msgstr "" -#: statusnet.php:277 +#: statusnet.php:313 msgid "" "If enabled all your public postings can be posted to the " "associated GNU Social account. You can choose to do so by default (here) or " "for every posting separately in the posting options when writing the entry." msgstr "" -#: statusnet.php:278 +#: statusnet.php:314 msgid "Post to GNU Social by default" msgstr "" -#: statusnet.php:283 +#: statusnet.php:315 +msgid "Mirror all public posts" +msgstr "" + +#: statusnet.php:316 +msgid "Automatically create contacts" +msgstr "" + +#: statusnet.php:317 +msgid "Import the remote timeline" +msgstr "" + +#: statusnet.php:318 +msgid "Disabled" +msgstr "معطل" + +#: statusnet.php:319 +msgid "Full Timeline" +msgstr "" + +#: statusnet.php:320 +msgid "Only Mentions" +msgstr "" + +#: statusnet.php:326 msgid "GNU Social Import/Export/Mirror" msgstr "" -#: statusnet.php:480 +#: statusnet.php:647 msgid "Site name" msgstr "اسم الموقع" -#: statusnet.php:482 +#: statusnet.php:649 msgid "Consumer Secret" msgstr "" -#: statusnet.php:483 +#: statusnet.php:650 msgid "Consumer Key" msgstr "" diff --git a/statusnet/lang/ar/strings.php b/statusnet/lang/ar/strings.php index 8fa1ef3e..1cd72f3c 100644 --- a/statusnet/lang/ar/strings.php +++ b/statusnet/lang/ar/strings.php @@ -6,4 +6,5 @@ function string_plural_select_ar($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'] = 'حفظ الإعدادات'; +$a->strings['Disabled'] = 'معطل'; $a->strings['Site name'] = 'اسم الموقع'; diff --git a/statusnet/lang/cs/messages.po b/statusnet/lang/cs/messages.po index 6ed2d9b2..851164df 100644 --- a/statusnet/lang/cs/messages.po +++ b/statusnet/lang/cs/messages.po @@ -11,80 +11,80 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-12-21 22:32+0000\n" -"PO-Revision-Date: 2014-06-23 12:54+0000\n" -"Last-Translator: Aditoo, 2018\n" -"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" +"POT-Creation-Date: 2015-07-27 07:21+0200\n" +"PO-Revision-Date: 2018-06-14 14:47+0000\n" +"Last-Translator: Aditoo\n" +"Language-Team: Czech (http://www.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" -#: statusnet.php:76 +#: statusnet.php:151 msgid "Post to GNU Social" msgstr "Poslat na GNU social" -#: statusnet.php:122 +#: statusnet.php:196 msgid "" "Please contact your site administrator.
The provided API URL is not " "valid." msgstr "Obraťte se na administratora webu.
Poskytnutý odkaz na API není platný." -#: statusnet.php:150 +#: statusnet.php:225 msgid "We could not contact the GNU Social API with the Path you entered." msgstr "Nemohli jsme kontaktovat API GNU social pomocí cesty, kterou jste zadal/a." -#: statusnet.php:208 statusnet.php:489 -msgid "Save Settings" -msgstr "Uložit nastavení" +#: statusnet.php:259 +msgid "GNU Social settings updated." +msgstr "Nastavení pro GNU social aktualizována." -#: statusnet.php:220 -#, php-format -msgid "Currently connected to: %s" -msgstr "" +#: statusnet.php:294 statusnet.php:298 +msgid "GNU Social Import/Export/Mirror" +msgstr "Import/export/zrcadlení GNU social" -#: statusnet.php:225 -msgid "" -"Note: Due your privacy settings (Hide your profile " -"details from unknown viewers?) the link potentially included in public " -"postings relayed to GNU Social 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 GNU social 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." - -#: statusnet.php:228 -msgid "Clear OAuth configuration" -msgstr "Vymazat konfiguraci OAuth" - -#: statusnet.php:240 -msgid "Cancel GNU Social Connection" -msgstr "Zrušit spojení s GNU social" - -#: statusnet.php:247 +#: statusnet.php:313 msgid "Globally Available GNU Social OAuthKeys" msgstr "Globálně dostupné OAuth klíče pro GNU" -#: statusnet.php:248 +#: statusnet.php:314 msgid "" "There are preconfigured OAuth key pairs for some GNU Social servers " "available. If you are using one of them, please use these credentials. If " "not feel free to connect to any other GNU Social instance (see below)." msgstr "Jsou dostupné předkonfigurované páry klíčů OAuth pro některé servery GNU social. Pokud některý z nich používáte, prosím používejte tyto kredenciály. Pokud ne, můžete se klidně připojit k jakékoliv jiné instanci GNU social (viz dole)." -#: statusnet.php:249 +#: statusnet.php:320 statusnet.php:337 statusnet.php:364 statusnet.php:371 +#: statusnet.php:416 statusnet.php:699 +msgid "Save Settings" +msgstr "Uložit nastavení" + +#: statusnet.php:322 msgid "Provide your own OAuth Credentials" msgstr "Uveďte své vlastní OAuth přihlašovací údaje" -#: statusnet.php:250 +#: statusnet.php:323 msgid "" "No consumer key pair for GNU Social found. Register your Friendica Account " -"as a desktop application on your GNU Social account, copy the consumer key " -"pair here and enter the API base root.
Before you register your own " -"OAuth key pair ask the administrator if there is already a key pair for this" -" Friendica installation at your favorite GNU Social installation." -msgstr "" +"as an desktop client on your GNU Social account, copy the consumer key pair " +"here and enter the API base root.
Before you register your own OAuth " +"key pair ask the administrator if there is already a key pair for this " +"Friendica installation at your favorited GNU Social installation." +msgstr "Nenalezen žádný pár klíčů pro GNU social. Registrujte svůj účet Friendica na Vašem účtu GNU social jako desktopový klient, zkopírujte sem pár klíčů consumer key a zadejte kořenovou složku API.
Dříve, než si zaregistrujete Váš vlastní pár klíčů, se zeptejte administrátora, jestli již na Vaší oblíbené instalaci GNU social existuje pár klíčů pro tuto instalaci Friendica." -#: statusnet.php:251 +#: statusnet.php:325 +msgid "OAuth Consumer Key" +msgstr "OAuth Consumer Key" + +#: statusnet.php:328 +msgid "OAuth Consumer Secret" +msgstr "OAuth Consumer Secret" + +#: statusnet.php:331 statusnet.php:679 statusnet.php:691 +msgid "Base API Path (remember the trailing /)" +msgstr "Cesta k Base API (nezapomeňte na koncové /)" + +#: statusnet.php:356 msgid "" "To connect to your GNU Social account click the button below to get a " "security code from GNU Social which you have to copy into the input box " @@ -92,62 +92,86 @@ msgid "" "posted to GNU Social." msgstr "Pro připojení k Vašemu účtu na GNU social klikněte na tlačítko níže. Obdržíte bezpečnostní kód od GNU social, ten musíte zkopírovat do vyplňovacího pole níže a odeslat formulář. Pouze Vaše veřejné příspěvky budou odesílány na GNU social." -#: statusnet.php:252 +#: statusnet.php:357 msgid "Log in with GNU Social" msgstr "Přihlásit se pomocí GNU social" -#: statusnet.php:253 -msgid "Cancel Connection Process" -msgstr "Zrušit připojování" - -#: statusnet.php:254 -#, php-format -msgid "Current GNU Social API is: %s" -msgstr "" - -#: statusnet.php:271 -msgid "OAuth Consumer Key" -msgstr "OAuth Consumer Key" - -#: statusnet.php:272 -msgid "OAuth Consumer Secret" -msgstr "OAuth Consumer Secret" - -#: statusnet.php:274 statusnet.php:469 statusnet.php:481 -msgid "Base API Path (remember the trailing /)" -msgstr "Cesta k Base API (nezapomeňte na koncové /)" - -#: statusnet.php:275 +#: statusnet.php:359 msgid "Copy the security code from GNU Social here" msgstr "Zde překopírujte váš bezpečnostní kód z GNU social" -#: statusnet.php:277 -msgid "Allow posting to GNU Social" -msgstr "Povolit posílání příspěvků na GNU social" +#: statusnet.php:365 +msgid "Cancel Connection Process" +msgstr "Zrušit připojování" -#: statusnet.php:277 +#: statusnet.php:367 +msgid "Current GNU Social API is" +msgstr "Aktuální API GNU social je:" + +#: statusnet.php:368 +msgid "Cancel GNU Social Connection" +msgstr "Zrušit spojení s GNU social" + +#: statusnet.php:379 +msgid "Currently connected to: " +msgstr "Aktuálně jste připojen/a k:" + +#: statusnet.php:380 msgid "" "If enabled all your public postings can be posted to the " "associated GNU Social 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 GNU social. 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." -#: statusnet.php:278 -msgid "Post to GNU Social by default" -msgstr "" +#: statusnet.php:382 +msgid "" +"Note: Due your privacy settings (Hide your profile " +"details from unknown viewers?) the link potentially included in public " +"postings relayed to GNU Social 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 GNU social 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." -#: statusnet.php:283 -msgid "GNU Social Import/Export/Mirror" -msgstr "Import/export/zrcadlení GNU social" +#: statusnet.php:385 +msgid "Allow posting to GNU Social" +msgstr "Povolit posílání příspěvků na GNU social" -#: statusnet.php:480 +#: statusnet.php:388 +msgid "Send public postings to GNU Social by default" +msgstr "Ve výchozím stavu posílat veřejné příspěvky na GNU social" + +#: statusnet.php:392 +msgid "" +"Mirror all posts from GNU Social that are no replies or repeated messages" +msgstr "Zrcadlit všechny příspěvky z GNU social, které nejsou odpovědi nebo zopakované zprávy" + +#: statusnet.php:398 +msgid "Import the remote timeline" +msgstr "Importovat vzdálenou časovou osu" + +#: statusnet.php:402 +msgid "Disabled" +msgstr "Zakázáno" + +#: statusnet.php:403 +msgid "Full Timeline" +msgstr "Plná časová osa" + +#: statusnet.php:404 +msgid "Only Mentions" +msgstr "Pouze zmínky" + +#: statusnet.php:413 +msgid "Clear OAuth configuration" +msgstr "Vymazat konfiguraci OAuth" + +#: statusnet.php:690 msgid "Site name" msgstr "Název webu" -#: statusnet.php:482 +#: statusnet.php:692 msgid "Consumer Secret" msgstr "Consumer Secret" -#: statusnet.php:483 +#: statusnet.php:693 msgid "Consumer Key" msgstr "Consumer Key" diff --git a/statusnet/lang/cs/strings.php b/statusnet/lang/cs/strings.php index 991901c3..ce6ea1e4 100644 --- a/statusnet/lang/cs/strings.php +++ b/statusnet/lang/cs/strings.php @@ -8,23 +8,33 @@ function string_plural_select_cs($n){ $a->strings['Post to GNU Social'] = 'Poslat na GNU social'; $a->strings['Please contact your site administrator.
The provided API URL is not valid.'] = 'Obraťte se na administratora webu.
Poskytnutý odkaz na API není platný.'; $a->strings['We could not contact the GNU Social API with the Path you entered.'] = 'Nemohli jsme kontaktovat API GNU social pomocí cesty, kterou jste zadal/a.'; -$a->strings['Save Settings'] = 'Uložit nastavení'; -$a->strings['Note: Due your privacy settings (Hide your profile details from unknown viewers?) the link potentially included in public postings relayed to GNU Social 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 GNU social 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['Clear OAuth configuration'] = 'Vymazat konfiguraci OAuth'; -$a->strings['Cancel GNU Social Connection'] = 'Zrušit spojení s GNU social'; +$a->strings['GNU Social settings updated.'] = 'Nastavení pro GNU social aktualizována.'; +$a->strings['GNU Social Import/Export/Mirror'] = 'Import/export/zrcadlení GNU social'; $a->strings['Globally Available GNU Social OAuthKeys'] = 'Globálně dostupné OAuth klíče pro GNU'; $a->strings['There are preconfigured OAuth key pairs for some GNU Social servers available. If you are using one of them, please use these credentials. If not feel free to connect to any other GNU Social instance (see below).'] = 'Jsou dostupné předkonfigurované páry klíčů OAuth pro některé servery GNU social. Pokud některý z nich používáte, prosím používejte tyto kredenciály. Pokud ne, můžete se klidně připojit k jakékoliv jiné instanci GNU social (viz dole).'; +$a->strings['Save Settings'] = 'Uložit nastavení'; $a->strings['Provide your own OAuth Credentials'] = 'Uveďte své vlastní OAuth přihlašovací údaje'; -$a->strings['To connect to your GNU Social account click the button below to get a security code from GNU Social which you have to copy into the input box below and submit the form. Only your public posts will be posted to GNU Social.'] = 'Pro připojení k Vašemu účtu na GNU social klikněte na tlačítko níže. Obdržíte bezpečnostní kód od GNU social, ten musíte zkopírovat do vyplňovacího pole níže a odeslat formulář. Pouze Vaše veřejné příspěvky budou odesílány na GNU social.'; -$a->strings['Log in with GNU Social'] = 'Přihlásit se pomocí GNU social'; -$a->strings['Cancel Connection Process'] = 'Zrušit připojování'; +$a->strings['No consumer key pair for GNU Social found. Register your Friendica Account as an desktop client on your GNU Social account, copy the consumer key pair here and enter the API base root.
Before you register your own OAuth key pair ask the administrator if there is already a key pair for this Friendica installation at your favorited GNU Social installation.'] = 'Nenalezen žádný pár klíčů pro GNU social. Registrujte svůj účet Friendica na Vašem účtu GNU social jako desktopový klient, zkopírujte sem pár klíčů consumer key a zadejte kořenovou složku API.
Dříve, než si zaregistrujete Váš vlastní pár klíčů, se zeptejte administrátora, jestli již na Vaší oblíbené instalaci GNU social existuje pár klíčů pro tuto instalaci Friendica.'; $a->strings['OAuth Consumer Key'] = 'OAuth Consumer Key'; $a->strings['OAuth Consumer Secret'] = 'OAuth Consumer Secret'; $a->strings['Base API Path (remember the trailing /)'] = 'Cesta k Base API (nezapomeňte na koncové /)'; +$a->strings['To connect to your GNU Social account click the button below to get a security code from GNU Social which you have to copy into the input box below and submit the form. Only your public posts will be posted to GNU Social.'] = 'Pro připojení k Vašemu účtu na GNU social klikněte na tlačítko níže. Obdržíte bezpečnostní kód od GNU social, ten musíte zkopírovat do vyplňovacího pole níže a odeslat formulář. Pouze Vaše veřejné příspěvky budou odesílány na GNU social.'; +$a->strings['Log in with GNU Social'] = 'Přihlásit se pomocí GNU social'; $a->strings['Copy the security code from GNU Social here'] = 'Zde překopírujte váš bezpečnostní kód z GNU social'; -$a->strings['Allow posting to GNU Social'] = 'Povolit posílání příspěvků na GNU social'; +$a->strings['Cancel Connection Process'] = 'Zrušit připojování'; +$a->strings['Current GNU Social API is'] = 'Aktuální API GNU social je:'; +$a->strings['Cancel GNU Social Connection'] = 'Zrušit spojení s GNU social'; +$a->strings['Currently connected to: '] = 'Aktuálně jste připojen/a k:'; $a->strings['If enabled all your public postings can be posted to the associated GNU Social 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 GNU social. 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['GNU Social Import/Export/Mirror'] = 'Import/export/zrcadlení GNU social'; +$a->strings['Note: Due your privacy settings (Hide your profile details from unknown viewers?) the link potentially included in public postings relayed to GNU Social 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 GNU social 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['Allow posting to GNU Social'] = 'Povolit posílání příspěvků na GNU social'; +$a->strings['Send public postings to GNU Social by default'] = 'Ve výchozím stavu posílat veřejné příspěvky na GNU social'; +$a->strings['Mirror all posts from GNU Social that are no replies or repeated messages'] = 'Zrcadlit všechny příspěvky z GNU social, které nejsou odpovědi nebo zopakované zprávy'; +$a->strings['Import the remote timeline'] = 'Importovat vzdálenou časovou osu'; +$a->strings['Disabled'] = 'Zakázáno'; +$a->strings['Full Timeline'] = 'Plná časová osa'; +$a->strings['Only Mentions'] = 'Pouze zmínky'; +$a->strings['Clear OAuth configuration'] = 'Vymazat konfiguraci OAuth'; $a->strings['Site name'] = 'Název webu'; $a->strings['Consumer Secret'] = 'Consumer Secret'; $a->strings['Consumer Key'] = 'Consumer Key'; diff --git a/statusnet/lang/de/messages.po b/statusnet/lang/de/messages.po index 2b92005f..fa9cba59 100644 --- a/statusnet/lang/de/messages.po +++ b/statusnet/lang/de/messages.po @@ -13,40 +13,40 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-12-21 22:32+0000\n" -"PO-Revision-Date: 2014-06-23 12:54+0000\n" -"Last-Translator: Tobias Diekershoff , 2016,2022\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"POT-Creation-Date: 2021-11-21 19:17-0500\n" +"PO-Revision-Date: 2022-01-22 17:42+0000\n" +"Last-Translator: Tobias Diekershoff \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: statusnet.php:76 +#: statusnet.php:97 msgid "Post to GNU Social" msgstr "Auf GNU Social veröffentlichen" -#: statusnet.php:122 +#: statusnet.php:148 msgid "" "Please contact your site administrator.
The provided API URL is not " "valid." msgstr "Bitte kontaktiere den Administrator der Seite.
Die gegebene API URL ist nicht gültig." -#: statusnet.php:150 +#: statusnet.php:176 msgid "We could not contact the GNU Social API with the Path you entered." msgstr "Die GNU Social-API konnte mit dem angegebenen Pfad nicht erreicht werden." -#: statusnet.php:208 statusnet.php:489 +#: statusnet.php:243 statusnet.php:656 msgid "Save Settings" msgstr "Einstellungen speichern" -#: statusnet.php:220 +#: statusnet.php:255 #, php-format msgid "Currently connected to: %s" msgstr "Derzeit verbunden mit: %s" -#: statusnet.php:225 +#: statusnet.php:260 msgid "" "Note: Due your privacy settings (Hide your profile " "details from unknown viewers?) the link potentially included in public " @@ -54,30 +54,30 @@ msgid "" "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 GNU Social-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." -#: statusnet.php:228 +#: statusnet.php:263 msgid "Clear OAuth configuration" msgstr "OAuth-Konfiguration löschen" -#: statusnet.php:240 +#: statusnet.php:275 msgid "Cancel GNU Social Connection" msgstr "Verbindung zum GNU Social-Server abbrechen" -#: statusnet.php:247 +#: statusnet.php:283 msgid "Globally Available GNU Social OAuthKeys" msgstr "Verfügbare OAuth-Schlüssel für GNU Social" -#: statusnet.php:248 +#: statusnet.php:284 msgid "" "There are preconfigured OAuth key pairs for some GNU Social servers " "available. If you are using one of them, please use these credentials. If " "not feel free to connect to any other GNU Social instance (see below)." msgstr "Für einige GNU Social-Server sind voreingestellte OAuth-Schlüsselpaare verfügbar. Solltest du einen dieser Server benutzen, dann verwende bitte diese Schlüssel. Falls nicht, stelle stattdessen eine Verbindung zu irgendeinem anderen StatusNet-Server her (siehe unten)." -#: statusnet.php:249 +#: statusnet.php:285 msgid "Provide your own OAuth Credentials" msgstr "Eigene OAuth-Schlüssel eintragen" -#: statusnet.php:250 +#: statusnet.php:286 msgid "" "No consumer key pair for GNU Social found. Register your Friendica Account " "as a desktop application on your GNU Social account, copy the consumer key " @@ -86,7 +86,7 @@ msgid "" " Friendica installation at your favorite GNU Social installation." msgstr "Kein Consumer-Schlüsselpaar für GNU Social gefunden. Registriere deinen Friendica-Account als Desktop-Client bei deinem GNU Social-Account, kopiere das Consumer-Schlüsselpaar hierher und gib die API-URL ein.
Bevor du dein eigenes Consumer-Schlüsselpaar registrierst, frage den Administrator dieses Friendica-Servers, ob schon ein Schlüsselpaar für diesen Friendica-Server auf diesem GNU Social-Server existiert." -#: statusnet.php:251 +#: statusnet.php:287 msgid "" "To connect to your GNU Social account click the button below to get a " "security code from GNU Social which you have to copy into the input box " @@ -94,62 +94,86 @@ msgid "" "posted to GNU Social." msgstr "Um dein Konto mit einem GNU Social-Konto zu verknüpfen, klicke den Button an, um einen Sicherheitscode von GNU Social zu erhalten, und kopiere diesen in das Eingabefeld weiter unten. Es werden ausschließlich deine öffentlichen Nachrichten an GNU Social gesendet." -#: statusnet.php:252 +#: statusnet.php:288 msgid "Log in with GNU Social" msgstr "Bei GNU Social anmelden" -#: statusnet.php:253 +#: statusnet.php:289 msgid "Cancel Connection Process" msgstr "Verbindungsprozess abbrechen" -#: statusnet.php:254 +#: statusnet.php:290 #, php-format msgid "Current GNU Social API is: %s" msgstr "Derzeitige GNU Social-API-URL lautet %s" -#: statusnet.php:271 +#: statusnet.php:307 msgid "OAuth Consumer Key" msgstr "OAuth Consumer Key" -#: statusnet.php:272 +#: statusnet.php:308 msgid "OAuth Consumer Secret" msgstr "OAuth Consumer Secret" -#: statusnet.php:274 statusnet.php:469 statusnet.php:481 +#: statusnet.php:310 statusnet.php:636 statusnet.php:648 msgid "Base API Path (remember the trailing /)" msgstr "Basis-URL der StatusNet-API (vergiss den abschließenden / nicht)" -#: statusnet.php:275 +#: statusnet.php:311 msgid "Copy the security code from GNU Social here" msgstr "Kopiere den Sicherheitscode von GNU social hier hin" -#: statusnet.php:277 +#: statusnet.php:313 msgid "Allow posting to GNU Social" msgstr "Veröffentlichung bei GNU Social erlauben" -#: statusnet.php:277 +#: statusnet.php:313 msgid "" "If enabled all your public postings can be posted to the " "associated GNU Social 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 GNU Social-Konto veröffentlicht werden. Du kannst das (hier) als Standardverhalten einstellen oder beim Schreiben eines Beitrags in den Beitragsoptionen festlegen." -#: statusnet.php:278 +#: statusnet.php:314 msgid "Post to GNU Social by default" msgstr "Standardmäßig bei GNU Social veröffentlichen" -#: statusnet.php:283 +#: statusnet.php:315 +msgid "Mirror all public posts" +msgstr "Spiegle alle öffentlichen Nachrichten" + +#: statusnet.php:316 +msgid "Automatically create contacts" +msgstr "Automatisch Kontakte anlegen" + +#: statusnet.php:317 +msgid "Import the remote timeline" +msgstr "Importiere die entfernte Zeitleiste" + +#: statusnet.php:318 +msgid "Disabled" +msgstr "Deaktiviert" + +#: statusnet.php:319 +msgid "Full Timeline" +msgstr "Komplette Timeline" + +#: statusnet.php:320 +msgid "Only Mentions" +msgstr "Nur Erwähnungen" + +#: statusnet.php:326 msgid "GNU Social Import/Export/Mirror" msgstr "GNU Social-Import/Export/Spiegeln" -#: statusnet.php:480 +#: statusnet.php:647 msgid "Site name" msgstr "Seitenname" -#: statusnet.php:482 +#: statusnet.php:649 msgid "Consumer Secret" msgstr "Consumer Secret" -#: statusnet.php:483 +#: statusnet.php:650 msgid "Consumer Key" msgstr "Consumer Key" diff --git a/statusnet/lang/de/strings.php b/statusnet/lang/de/strings.php index a35e425c..b381c408 100644 --- a/statusnet/lang/de/strings.php +++ b/statusnet/lang/de/strings.php @@ -28,6 +28,12 @@ $a->strings['Copy the security code from GNU Social here'] = 'Kopiere den Sicher $a->strings['Allow posting to GNU Social'] = 'Veröffentlichung bei GNU Social erlauben'; $a->strings['If enabled all your public postings can be posted to the associated GNU Social 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 GNU Social-Konto veröffentlicht werden. Du kannst das (hier) als Standardverhalten einstellen oder beim Schreiben eines Beitrags in den Beitragsoptionen festlegen.'; $a->strings['Post to GNU Social by default'] = 'Standardmäßig bei GNU Social veröffentlichen'; +$a->strings['Mirror all public posts'] = 'Spiegle alle öffentlichen Nachrichten'; +$a->strings['Automatically create contacts'] = 'Automatisch Kontakte anlegen'; +$a->strings['Import the remote timeline'] = 'Importiere die entfernte Zeitleiste'; +$a->strings['Disabled'] = 'Deaktiviert'; +$a->strings['Full Timeline'] = 'Komplette Timeline'; +$a->strings['Only Mentions'] = 'Nur Erwähnungen'; $a->strings['GNU Social Import/Export/Mirror'] = 'GNU Social-Import/Export/Spiegeln'; $a->strings['Site name'] = 'Seitenname'; $a->strings['Consumer Secret'] = 'Consumer Secret'; diff --git a/statusnet/lang/es/messages.po b/statusnet/lang/es/messages.po index 8ab9a31b..bf9cdcc6 100644 --- a/statusnet/lang/es/messages.po +++ b/statusnet/lang/es/messages.po @@ -9,80 +9,80 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-12-21 22:32+0000\n" -"PO-Revision-Date: 2014-06-23 12:54+0000\n" -"Last-Translator: Albert, 2016\n" -"Language-Team: Spanish (http://app.transifex.com/Friendica/friendica/language/es/)\n" +"POT-Creation-Date: 2015-07-27 07:21+0200\n" +"PO-Revision-Date: 2016-11-17 23:07+0000\n" +"Last-Translator: Albert\n" +"Language-Team: Spanish (http://www.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=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: statusnet.php:76 +#: statusnet.php:151 msgid "Post to GNU Social" msgstr "Publicar en GNU Social" -#: statusnet.php:122 +#: statusnet.php:196 msgid "" "Please contact your site administrator.
The provided API URL is not " "valid." msgstr "Por favor contacte con el administrador de su página.
La URL de API provista no es válida." -#: statusnet.php:150 +#: statusnet.php:225 msgid "We could not contact the GNU Social API with the Path you entered." msgstr "No pudimos contactar con la API de GNU Social con el Camino que introdujo." -#: statusnet.php:208 statusnet.php:489 -msgid "Save Settings" -msgstr "Guardar Ajustes" +#: statusnet.php:259 +msgid "GNU Social settings updated." +msgstr "Ajustes de GNU Social actualizados." -#: statusnet.php:220 -#, php-format -msgid "Currently connected to: %s" -msgstr "" +#: statusnet.php:294 statusnet.php:298 +msgid "GNU Social Import/Export/Mirror" +msgstr "Importar/Exportar/Reflejar GNU Social" -#: statusnet.php:225 -msgid "" -"Note: Due your privacy settings (Hide your profile " -"details from unknown viewers?) the link potentially included in public " -"postings relayed to GNU Social will lead the visitor to a blank page " -"informing the visitor that the access to your profile has been restricted." -msgstr "Nota: Debido a sus ajustes de privacidad (?Ocultar los detalles de su perfil a espectadores desconocidos?) el enlace potencialmente incluído en publicaciones públicas transmitidas a GNU Social llevarán al visitante a una página en blanco informándole de que el acceso a su perfil ha sido restringido." - -#: statusnet.php:228 -msgid "Clear OAuth configuration" -msgstr "Limpiar la configuración de OAuth" - -#: statusnet.php:240 -msgid "Cancel GNU Social Connection" -msgstr "Cancelar la conexión a GNU Social" - -#: statusnet.php:247 +#: statusnet.php:313 msgid "Globally Available GNU Social OAuthKeys" msgstr "Disponible globalmente GNU Social OAuthKeys" -#: statusnet.php:248 +#: statusnet.php:314 msgid "" "There are preconfigured OAuth key pairs for some GNU Social servers " "available. If you are using one of them, please use these credentials. If " "not feel free to connect to any other GNU Social instance (see below)." msgstr "Hay pares de clave preconfigurados OAuth para algunos servidores disponibles de GNU Social. Si está utilizando uno de ellos, por favor utilice estas credenciales. Si no se siente libre de conectar a alguna otra instancia de GNU Social (vea abajo)." -#: statusnet.php:249 +#: statusnet.php:320 statusnet.php:337 statusnet.php:364 statusnet.php:371 +#: statusnet.php:416 statusnet.php:699 +msgid "Save Settings" +msgstr "Guardar Ajustes" + +#: statusnet.php:322 msgid "Provide your own OAuth Credentials" msgstr "Proveer sus propias credenciales de OAuth" -#: statusnet.php:250 +#: statusnet.php:323 msgid "" "No consumer key pair for GNU Social found. Register your Friendica Account " -"as a desktop application on your GNU Social account, copy the consumer key " -"pair here and enter the API base root.
Before you register your own " -"OAuth key pair ask the administrator if there is already a key pair for this" -" Friendica installation at your favorite GNU Social installation." -msgstr "" +"as an desktop client on your GNU Social account, copy the consumer key pair " +"here and enter the API base root.
Before you register your own OAuth " +"key pair ask the administrator if there is already a key pair for this " +"Friendica installation at your favorited GNU Social installation." +msgstr "No se encontró el par de claves de consumidor para GNU Social. Registre su cuenta de Friendica como un cliente de escritorio en su cuenta de GNU, copie el par de claves aquí e introduzca el origen de la API.
Antes de qeu registre su propio par de claves de OAuth pregunte al administrador si ya hay un par de claves para esta instalación de Friendica en su instalación de GNU Social favorita." -#: statusnet.php:251 +#: statusnet.php:325 +msgid "OAuth Consumer Key" +msgstr "Clave de Consumidor de OAuth" + +#: statusnet.php:328 +msgid "OAuth Consumer Secret" +msgstr "Secreto de Consumidor de OAuth" + +#: statusnet.php:331 statusnet.php:679 statusnet.php:691 +msgid "Base API Path (remember the trailing /)" +msgstr "Camino Base de API (Recordar la cola /)" + +#: statusnet.php:356 msgid "" "To connect to your GNU Social account click the button below to get a " "security code from GNU Social which you have to copy into the input box " @@ -90,62 +90,86 @@ msgid "" "posted to GNU Social." msgstr "Para conectarse a su cuenta GNU Social click en el botón de abajo para obtener un código de seguridad de GNU Social que puede copiar en la caja de abajo y enviar el formulario. Sólo sus entradas públicas se publicarán en GNU Social." -#: statusnet.php:252 +#: statusnet.php:357 msgid "Log in with GNU Social" msgstr "Acceder a GNU Social" -#: statusnet.php:253 -msgid "Cancel Connection Process" -msgstr "Cancelar el Proceso de Conexión" - -#: statusnet.php:254 -#, php-format -msgid "Current GNU Social API is: %s" -msgstr "" - -#: statusnet.php:271 -msgid "OAuth Consumer Key" -msgstr "Clave de Consumidor de OAuth" - -#: statusnet.php:272 -msgid "OAuth Consumer Secret" -msgstr "Secreto de Consumidor de OAuth" - -#: statusnet.php:274 statusnet.php:469 statusnet.php:481 -msgid "Base API Path (remember the trailing /)" -msgstr "Camino Base de API (Recordar la cola /)" - -#: statusnet.php:275 +#: statusnet.php:359 msgid "Copy the security code from GNU Social here" msgstr "Copiar el código de seguridad de GNU Social aquí" -#: statusnet.php:277 -msgid "Allow posting to GNU Social" -msgstr "Permitir publicar en GNU Social" +#: statusnet.php:365 +msgid "Cancel Connection Process" +msgstr "Cancelar el Proceso de Conexión" -#: statusnet.php:277 +#: statusnet.php:367 +msgid "Current GNU Social API is" +msgstr "API de GNU Social actual" + +#: statusnet.php:368 +msgid "Cancel GNU Social Connection" +msgstr "Cancelar la conexión a GNU Social" + +#: statusnet.php:379 +msgid "Currently connected to: " +msgstr "Actualmente conectado a:" + +#: statusnet.php:380 msgid "" "If enabled all your public postings can be posted to the " "associated GNU Social 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 está habilitado, todas sus publicaciones públicas pueden publicarse en la cuenta asociada de GNU Social. Puede elegir hacer eso por defecto (aquí) o por cada publicación por separado en las opciones de publicación mientras escribe la entrada." -#: statusnet.php:278 -msgid "Post to GNU Social by default" -msgstr "" +#: statusnet.php:382 +msgid "" +"Note: Due your privacy settings (Hide your profile " +"details from unknown viewers?) the link potentially included in public " +"postings relayed to GNU Social will lead the visitor to a blank page " +"informing the visitor that the access to your profile has been restricted." +msgstr "Nota: Debido a sus ajustes de privacidad (?Ocultar los detalles de su perfil a espectadores desconocidos?) el enlace potencialmente incluído en publicaciones públicas transmitidas a GNU Social llevarán al visitante a una página en blanco informándole de que el acceso a su perfil ha sido restringido." -#: statusnet.php:283 -msgid "GNU Social Import/Export/Mirror" -msgstr "Importar/Exportar/Reflejar GNU Social" +#: statusnet.php:385 +msgid "Allow posting to GNU Social" +msgstr "Permitir publicar en GNU Social" -#: statusnet.php:480 +#: statusnet.php:388 +msgid "Send public postings to GNU Social by default" +msgstr "Enviar las publicaciones públicas a GNU Social por defecto" + +#: statusnet.php:392 +msgid "" +"Mirror all posts from GNU Social that are no replies or repeated messages" +msgstr "Reflejar todas las entradas de GNU Social que no son respuestas o mensajes repetidos" + +#: statusnet.php:398 +msgid "Import the remote timeline" +msgstr "Importar la línea de tiempo remota" + +#: statusnet.php:402 +msgid "Disabled" +msgstr "Deshabilitado" + +#: statusnet.php:403 +msgid "Full Timeline" +msgstr "Línea de Tiempo completa" + +#: statusnet.php:404 +msgid "Only Mentions" +msgstr "Sólo Menciones" + +#: statusnet.php:413 +msgid "Clear OAuth configuration" +msgstr "Limpiar la configuración de OAuth" + +#: statusnet.php:690 msgid "Site name" msgstr "Nombre de la página" -#: statusnet.php:482 +#: statusnet.php:692 msgid "Consumer Secret" msgstr "Secreto de Consumidor" -#: statusnet.php:483 +#: statusnet.php:693 msgid "Consumer Key" msgstr "Clave de Consumidor" diff --git a/statusnet/lang/es/strings.php b/statusnet/lang/es/strings.php index 50df793a..7aa44911 100644 --- a/statusnet/lang/es/strings.php +++ b/statusnet/lang/es/strings.php @@ -3,28 +3,38 @@ if(! function_exists("string_plural_select_es")) { function string_plural_select_es($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $a->strings['Post to GNU Social'] = 'Publicar en GNU Social'; $a->strings['Please contact your site administrator.
The provided API URL is not valid.'] = 'Por favor contacte con el administrador de su página.
La URL de API provista no es válida.'; $a->strings['We could not contact the GNU Social API with the Path you entered.'] = 'No pudimos contactar con la API de GNU Social con el Camino que introdujo.'; -$a->strings['Save Settings'] = 'Guardar Ajustes'; -$a->strings['Note: Due your privacy settings (Hide your profile details from unknown viewers?) the link potentially included in public postings relayed to GNU Social will lead the visitor to a blank page informing the visitor that the access to your profile has been restricted.'] = 'Nota: Debido a sus ajustes de privacidad (?Ocultar los detalles de su perfil a espectadores desconocidos?) el enlace potencialmente incluído en publicaciones públicas transmitidas a GNU Social llevarán al visitante a una página en blanco informándole de que el acceso a su perfil ha sido restringido.'; -$a->strings['Clear OAuth configuration'] = 'Limpiar la configuración de OAuth'; -$a->strings['Cancel GNU Social Connection'] = 'Cancelar la conexión a GNU Social'; +$a->strings['GNU Social settings updated.'] = 'Ajustes de GNU Social actualizados.'; +$a->strings['GNU Social Import/Export/Mirror'] = 'Importar/Exportar/Reflejar GNU Social'; $a->strings['Globally Available GNU Social OAuthKeys'] = 'Disponible globalmente GNU Social OAuthKeys'; $a->strings['There are preconfigured OAuth key pairs for some GNU Social servers available. If you are using one of them, please use these credentials. If not feel free to connect to any other GNU Social instance (see below).'] = 'Hay pares de clave preconfigurados OAuth para algunos servidores disponibles de GNU Social. Si está utilizando uno de ellos, por favor utilice estas credenciales. Si no se siente libre de conectar a alguna otra instancia de GNU Social (vea abajo).'; +$a->strings['Save Settings'] = 'Guardar Ajustes'; $a->strings['Provide your own OAuth Credentials'] = 'Proveer sus propias credenciales de OAuth'; -$a->strings['To connect to your GNU Social account click the button below to get a security code from GNU Social which you have to copy into the input box below and submit the form. Only your public posts will be posted to GNU Social.'] = 'Para conectarse a su cuenta GNU Social click en el botón de abajo para obtener un código de seguridad de GNU Social que puede copiar en la caja de abajo y enviar el formulario. Sólo sus entradas públicas se publicarán en GNU Social.'; -$a->strings['Log in with GNU Social'] = 'Acceder a GNU Social'; -$a->strings['Cancel Connection Process'] = 'Cancelar el Proceso de Conexión'; +$a->strings['No consumer key pair for GNU Social found. Register your Friendica Account as an desktop client on your GNU Social account, copy the consumer key pair here and enter the API base root.
Before you register your own OAuth key pair ask the administrator if there is already a key pair for this Friendica installation at your favorited GNU Social installation.'] = 'No se encontró el par de claves de consumidor para GNU Social. Registre su cuenta de Friendica como un cliente de escritorio en su cuenta de GNU, copie el par de claves aquí e introduzca el origen de la API.
Antes de qeu registre su propio par de claves de OAuth pregunte al administrador si ya hay un par de claves para esta instalación de Friendica en su instalación de GNU Social favorita.'; $a->strings['OAuth Consumer Key'] = 'Clave de Consumidor de OAuth'; $a->strings['OAuth Consumer Secret'] = 'Secreto de Consumidor de OAuth'; $a->strings['Base API Path (remember the trailing /)'] = 'Camino Base de API (Recordar la cola /)'; +$a->strings['To connect to your GNU Social account click the button below to get a security code from GNU Social which you have to copy into the input box below and submit the form. Only your public posts will be posted to GNU Social.'] = 'Para conectarse a su cuenta GNU Social click en el botón de abajo para obtener un código de seguridad de GNU Social que puede copiar en la caja de abajo y enviar el formulario. Sólo sus entradas públicas se publicarán en GNU Social.'; +$a->strings['Log in with GNU Social'] = 'Acceder a GNU Social'; $a->strings['Copy the security code from GNU Social here'] = 'Copiar el código de seguridad de GNU Social aquí'; -$a->strings['Allow posting to GNU Social'] = 'Permitir publicar en GNU Social'; +$a->strings['Cancel Connection Process'] = 'Cancelar el Proceso de Conexión'; +$a->strings['Current GNU Social API is'] = 'API de GNU Social actual'; +$a->strings['Cancel GNU Social Connection'] = 'Cancelar la conexión a GNU Social'; +$a->strings['Currently connected to: '] = 'Actualmente conectado a:'; $a->strings['If enabled all your public postings can be posted to the associated GNU Social account. You can choose to do so by default (here) or for every posting separately in the posting options when writing the entry.'] = 'Si está habilitado, todas sus publicaciones públicas pueden publicarse en la cuenta asociada de GNU Social. Puede elegir hacer eso por defecto (aquí) o por cada publicación por separado en las opciones de publicación mientras escribe la entrada.'; -$a->strings['GNU Social Import/Export/Mirror'] = 'Importar/Exportar/Reflejar GNU Social'; +$a->strings['Note: Due your privacy settings (Hide your profile details from unknown viewers?) the link potentially included in public postings relayed to GNU Social will lead the visitor to a blank page informing the visitor that the access to your profile has been restricted.'] = 'Nota: Debido a sus ajustes de privacidad (?Ocultar los detalles de su perfil a espectadores desconocidos?) el enlace potencialmente incluído en publicaciones públicas transmitidas a GNU Social llevarán al visitante a una página en blanco informándole de que el acceso a su perfil ha sido restringido.'; +$a->strings['Allow posting to GNU Social'] = 'Permitir publicar en GNU Social'; +$a->strings['Send public postings to GNU Social by default'] = 'Enviar las publicaciones públicas a GNU Social por defecto'; +$a->strings['Mirror all posts from GNU Social that are no replies or repeated messages'] = 'Reflejar todas las entradas de GNU Social que no son respuestas o mensajes repetidos'; +$a->strings['Import the remote timeline'] = 'Importar la línea de tiempo remota'; +$a->strings['Disabled'] = 'Deshabilitado'; +$a->strings['Full Timeline'] = 'Línea de Tiempo completa'; +$a->strings['Only Mentions'] = 'Sólo Menciones'; +$a->strings['Clear OAuth configuration'] = 'Limpiar la configuración de OAuth'; $a->strings['Site name'] = 'Nombre de la página'; $a->strings['Consumer Secret'] = 'Secreto de Consumidor'; $a->strings['Consumer Key'] = 'Clave de Consumidor'; diff --git a/statusnet/lang/fr/messages.po b/statusnet/lang/fr/messages.po index b9623537..92f185c0 100644 --- a/statusnet/lang/fr/messages.po +++ b/statusnet/lang/fr/messages.po @@ -12,40 +12,40 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-12-21 22:32+0000\n" +"POT-Creation-Date: 2021-11-21 19:17-0500\n" "PO-Revision-Date: 2014-06-23 12:54+0000\n" "Last-Translator: Nicolas Derive, 2022\n" -"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n" +"Language-Team: French (http://www.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" -#: statusnet.php:76 +#: statusnet.php:97 msgid "Post to GNU Social" msgstr "Publier sur GNU Social" -#: statusnet.php:122 +#: statusnet.php:148 msgid "" "Please contact your site administrator.
The provided API URL is not " "valid." msgstr "Merci de contacter l'administrateur du site.
L'URL d'API fournie est invalide." -#: statusnet.php:150 +#: statusnet.php:176 msgid "We could not contact the GNU Social API with the Path you entered." msgstr "Impossible de se connecter à l'API GNU Social avec le chemin indiqué." -#: statusnet.php:208 statusnet.php:489 +#: statusnet.php:243 statusnet.php:656 msgid "Save Settings" msgstr "Sauvegarder les paramètres" -#: statusnet.php:220 +#: statusnet.php:255 #, php-format msgid "Currently connected to: %s" msgstr "Actuellement connecté à : %s" -#: statusnet.php:225 +#: statusnet.php:260 msgid "" "Note: Due your privacy settings (Hide your profile " "details from unknown viewers?) the link potentially included in public " @@ -53,30 +53,30 @@ msgid "" "informing the visitor that the access to your profile has been restricted." msgstr "Note: En lien avec vos paramètres de confidentialité (Masquer vos détails de profil de visiteurs inconnus ?) le lien potentiellement inclus dans vos publications publiques relayées à GNU Social emmèneront le visiteur à une page blanche l'informant que l'accès à votre profil a été restreint." -#: statusnet.php:228 +#: statusnet.php:263 msgid "Clear OAuth configuration" msgstr "Effacer la configuration OAuth" -#: statusnet.php:240 +#: statusnet.php:275 msgid "Cancel GNU Social Connection" msgstr "Annuler la connexion à GNU Social" -#: statusnet.php:247 +#: statusnet.php:283 msgid "Globally Available GNU Social OAuthKeys" msgstr "Clés OAuth de GNU Social disponibles globalement" -#: statusnet.php:248 +#: statusnet.php:284 msgid "" "There are preconfigured OAuth key pairs for some GNU Social servers " "available. If you are using one of them, please use these credentials. If " "not feel free to connect to any other GNU Social instance (see below)." msgstr "Il y a des paires des clés OAuth préconfigurées disponibles pour certains serveurs GNU Social. Si vous utilisez l'une d'elles, merci d'utiliser ces identifiants. Si non, soyez libre de vous connecter à n'importe quelle autre instance GNU Social (voir ci-dessous)." -#: statusnet.php:249 +#: statusnet.php:285 msgid "Provide your own OAuth Credentials" msgstr "Fournissez vos propres identifiants OAuth" -#: statusnet.php:250 +#: statusnet.php:286 msgid "" "No consumer key pair for GNU Social found. Register your Friendica Account " "as a desktop application on your GNU Social account, copy the consumer key " @@ -85,7 +85,7 @@ msgid "" " Friendica installation at your favorite GNU Social installation." msgstr "Aucune paire de clés cliente pour GNU Social n'a été trouvée. Enregistrez votre compte Friendica comme une application de bureau sur votre compte GNU Social, copiez la paire de clés cliente ici et saisissez la racine de base de l'API.
Avant d'enregistrer votre propre paire de clés, demandez à l'administrateur si il y a déjà une paire de clés pour cette installation de Friendica sur votre installation GNU Social favorite." -#: statusnet.php:251 +#: statusnet.php:287 msgid "" "To connect to your GNU Social account click the button below to get a " "security code from GNU Social which you have to copy into the input box " @@ -93,62 +93,86 @@ msgid "" "posted to GNU Social." msgstr "Pour vous connecter à votre compte GNU Social, cliquez sur le bouton ci-dessous pour obtenir un code de sécurité de GNU Social, que vous devrez copier dans le champ de saisie ci-dessous, puis validez le formulaire. Seules vos publications publiques seront relayées sur GNU Social." -#: statusnet.php:252 +#: statusnet.php:288 msgid "Log in with GNU Social" msgstr "Se connecter avec GNU Social" -#: statusnet.php:253 +#: statusnet.php:289 msgid "Cancel Connection Process" msgstr "Annuler le processus de connexion" -#: statusnet.php:254 +#: statusnet.php:290 #, php-format msgid "Current GNU Social API is: %s" msgstr "L'API GNU Social actuelle est : %s" -#: statusnet.php:271 +#: statusnet.php:307 msgid "OAuth Consumer Key" msgstr "Clé d'Utilisateur OAuth" -#: statusnet.php:272 +#: statusnet.php:308 msgid "OAuth Consumer Secret" msgstr "Secret d'Utilisateur OAuth" -#: statusnet.php:274 statusnet.php:469 statusnet.php:481 +#: statusnet.php:310 statusnet.php:636 statusnet.php:648 msgid "Base API Path (remember the trailing /)" msgstr "Chemin de base de l'API (n'oubliez pas le / final)" -#: statusnet.php:275 +#: statusnet.php:311 msgid "Copy the security code from GNU Social here" msgstr "Coller le code de sécurité de GNU Social ici" -#: statusnet.php:277 +#: statusnet.php:313 msgid "Allow posting to GNU Social" msgstr "Autoriser la publication sur GNU Social" -#: statusnet.php:277 +#: statusnet.php:313 msgid "" "If enabled all your public postings can be posted to the " "associated GNU Social 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 activé, toutes vos publications publiques pourront être relayées sur le compte GNU Social associé. Vous pouvez choisir de faire cela par défaut (ici) ou individuellement pour chaque publication dans les options de publications au moment ou vous la créez." -#: statusnet.php:278 +#: statusnet.php:314 msgid "Post to GNU Social by default" msgstr "Publier sur GNU Social par défaut" -#: statusnet.php:283 +#: statusnet.php:315 +msgid "Mirror all public posts" +msgstr "Refléter toutes les publications publiques" + +#: statusnet.php:316 +msgid "Automatically create contacts" +msgstr "Créer les contacts automatiquement" + +#: statusnet.php:317 +msgid "Import the remote timeline" +msgstr "Importer la Timeline distante" + +#: statusnet.php:318 +msgid "Disabled" +msgstr "Désactiver" + +#: statusnet.php:319 +msgid "Full Timeline" +msgstr "Timeline complète" + +#: statusnet.php:320 +msgid "Only Mentions" +msgstr "Mentions uniquement" + +#: statusnet.php:326 msgid "GNU Social Import/Export/Mirror" msgstr "Import/Export/Miroir GNU Social" -#: statusnet.php:480 +#: statusnet.php:647 msgid "Site name" msgstr "Nom du site" -#: statusnet.php:482 +#: statusnet.php:649 msgid "Consumer Secret" msgstr "Secret d'Utilisateur" -#: statusnet.php:483 +#: statusnet.php:650 msgid "Consumer Key" msgstr "Clé d'Utilisateur" diff --git a/statusnet/lang/fr/strings.php b/statusnet/lang/fr/strings.php index 0809548f..9672216a 100644 --- a/statusnet/lang/fr/strings.php +++ b/statusnet/lang/fr/strings.php @@ -28,6 +28,12 @@ $a->strings['Copy the security code from GNU Social here'] = 'Coller le code de $a->strings['Allow posting to GNU Social'] = 'Autoriser la publication sur GNU Social'; $a->strings['If enabled all your public postings can be posted to the associated GNU Social account. You can choose to do so by default (here) or for every posting separately in the posting options when writing the entry.'] = 'Si activé, toutes vos publications publiques pourront être relayées sur le compte GNU Social associé. Vous pouvez choisir de faire cela par défaut (ici) ou individuellement pour chaque publication dans les options de publications au moment ou vous la créez.'; $a->strings['Post to GNU Social by default'] = 'Publier sur GNU Social par défaut'; +$a->strings['Mirror all public posts'] = 'Refléter toutes les publications publiques'; +$a->strings['Automatically create contacts'] = 'Créer les contacts automatiquement'; +$a->strings['Import the remote timeline'] = 'Importer la Timeline distante'; +$a->strings['Disabled'] = 'Désactiver'; +$a->strings['Full Timeline'] = 'Timeline complète'; +$a->strings['Only Mentions'] = 'Mentions uniquement'; $a->strings['GNU Social Import/Export/Mirror'] = 'Import/Export/Miroir GNU Social'; $a->strings['Site name'] = 'Nom du site'; $a->strings['Consumer Secret'] = 'Secret d\'Utilisateur'; diff --git a/statusnet/lang/hu/messages.po b/statusnet/lang/hu/messages.po index 4d54bc6a..ec800d85 100644 --- a/statusnet/lang/hu/messages.po +++ b/statusnet/lang/hu/messages.po @@ -9,40 +9,40 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-12-21 22:32+0000\n" +"POT-Creation-Date: 2021-11-21 19:17-0500\n" "PO-Revision-Date: 2014-06-23 12:54+0000\n" "Last-Translator: Balázs Úr, 2020-2021\n" -"Language-Team: Hungarian (http://app.transifex.com/Friendica/friendica/language/hu/)\n" +"Language-Team: Hungarian (http://www.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" -#: statusnet.php:76 +#: statusnet.php:97 msgid "Post to GNU Social" msgstr "Beküldés a GNU Socialra" -#: statusnet.php:122 +#: statusnet.php:148 msgid "" "Please contact your site administrator.
The provided API URL is not " "valid." msgstr "Vegye fel a kapcsolatot az oldal adminisztrátorával.
A megadott API URL nem érvényes." -#: statusnet.php:150 +#: statusnet.php:176 msgid "We could not contact the GNU Social API with the Path you entered." msgstr "Nem tudtunk kapcsolatba lépni a GNU Social API-val azon az útvonalon, amelyet megadott." -#: statusnet.php:208 statusnet.php:489 +#: statusnet.php:243 statusnet.php:656 msgid "Save Settings" msgstr "Beállítások mentése" -#: statusnet.php:220 +#: statusnet.php:255 #, php-format msgid "Currently connected to: %s" msgstr "Jelenleg ehhez kapcsolódott: %s" -#: statusnet.php:225 +#: statusnet.php:260 msgid "" "Note: Due your privacy settings (Hide your profile " "details from unknown viewers?) the link potentially included in public " @@ -50,30 +50,30 @@ msgid "" "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 GNU Socialra 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." -#: statusnet.php:228 +#: statusnet.php:263 msgid "Clear OAuth configuration" msgstr "OAuth beállítás törlése" -#: statusnet.php:240 +#: statusnet.php:275 msgid "Cancel GNU Social Connection" msgstr "GNU Social kapcsolódás megszakítása" -#: statusnet.php:247 +#: statusnet.php:283 msgid "Globally Available GNU Social OAuthKeys" msgstr "Globálisan elérhető GNU Social OAuth-kulcsok" -#: statusnet.php:248 +#: statusnet.php:284 msgid "" "There are preconfigured OAuth key pairs for some GNU Social servers " "available. If you are using one of them, please use these credentials. If " "not feel free to connect to any other GNU Social instance (see below)." msgstr "Előre beállított OAuth-kulcspárok érhetők el néhány GNU Social kiszolgálóhoz. Ha ezek egyikét használja, akkor használja ezeket a hitelesítési adatokat. Ha nem használja, akkor nyugodtan kapcsolódjon bármely egyéb GNU Social példányhoz (lásd lent)." -#: statusnet.php:249 +#: statusnet.php:285 msgid "Provide your own OAuth Credentials" msgstr "Adja meg a saját OAuth hitelesítési adatait" -#: statusnet.php:250 +#: statusnet.php:286 msgid "" "No consumer key pair for GNU Social found. Register your Friendica Account " "as a desktop application on your GNU Social account, copy the consumer key " @@ -82,7 +82,7 @@ msgid "" " Friendica installation at your favorite GNU Social installation." msgstr "Nem találhatók felhasználói kulcspárok a GNU Socialhoz. Regisztrálja a Friendica fiókját asztali alkalmazásként a GNU Social fiókjánál, másolja be a felhasználói kulcspárt ide, és adja meg az API alapgyökerét.
Mielőtt saját OAuth kulcspárt regisztrálna, kérdezze meg az adminisztrátort, hogy van-e már kulcspár ehhez a Friendica telepítéshez a kedvenc GNU Social telepítésénél." -#: statusnet.php:251 +#: statusnet.php:287 msgid "" "To connect to your GNU Social account click the button below to get a " "security code from GNU Social which you have to copy into the input box " @@ -90,62 +90,86 @@ msgid "" "posted to GNU Social." msgstr "A GNU Social fiókhoz való kapcsolódáshoz kattintson a lenti gombra, hogy megkapja a biztonsági kódot a GNU Socialtó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 GNU Socialra." -#: statusnet.php:252 +#: statusnet.php:288 msgid "Log in with GNU Social" msgstr "Bejelentkezés GNU Social használatával" -#: statusnet.php:253 +#: statusnet.php:289 msgid "Cancel Connection Process" msgstr "Kapcsolódási folyamat megszakítása" -#: statusnet.php:254 +#: statusnet.php:290 #, php-format msgid "Current GNU Social API is: %s" msgstr "A jelenlegi GNU Social API: %s" -#: statusnet.php:271 +#: statusnet.php:307 msgid "OAuth Consumer Key" msgstr "OAuth felhasználói kulcs" -#: statusnet.php:272 +#: statusnet.php:308 msgid "OAuth Consumer Secret" msgstr "OAuth felhasználói titok" -#: statusnet.php:274 statusnet.php:469 statusnet.php:481 +#: statusnet.php:310 statusnet.php:636 statusnet.php:648 msgid "Base API Path (remember the trailing /)" msgstr "Alap API útvonal (ne felejtse el a záró / karaktert)" -#: statusnet.php:275 +#: statusnet.php:311 msgid "Copy the security code from GNU Social here" msgstr "Másolja be ide a GNU Socialtól származó biztonsági kódot" -#: statusnet.php:277 +#: statusnet.php:313 msgid "Allow posting to GNU Social" msgstr "Beküldés engedélyezése a GNU Socialra" -#: statusnet.php:277 +#: statusnet.php:313 msgid "" "If enabled all your public postings can be posted to the " "associated GNU Social 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 GNU Social 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." -#: statusnet.php:278 +#: statusnet.php:314 msgid "Post to GNU Social by default" msgstr "Beküldés a GNU Socialra alapértelmezetten" -#: statusnet.php:283 +#: statusnet.php:315 +msgid "Mirror all public posts" +msgstr "Összes nyilvános bejegyzés tükrözése" + +#: statusnet.php:316 +msgid "Automatically create contacts" +msgstr "Partnerek automatikus létrehozása" + +#: statusnet.php:317 +msgid "Import the remote timeline" +msgstr "A távoli idővonal importálása" + +#: statusnet.php:318 +msgid "Disabled" +msgstr "Letiltva" + +#: statusnet.php:319 +msgid "Full Timeline" +msgstr "Teljes idővonal" + +#: statusnet.php:320 +msgid "Only Mentions" +msgstr "Csak említések" + +#: statusnet.php:326 msgid "GNU Social Import/Export/Mirror" msgstr "GNU Social importálás, exportálás vagy tükrözés" -#: statusnet.php:480 +#: statusnet.php:647 msgid "Site name" msgstr "Oldal neve" -#: statusnet.php:482 +#: statusnet.php:649 msgid "Consumer Secret" msgstr "Felhasználói titok" -#: statusnet.php:483 +#: statusnet.php:650 msgid "Consumer Key" msgstr "Felhasználói kulcs" diff --git a/statusnet/lang/hu/strings.php b/statusnet/lang/hu/strings.php index b1fe1550..aa202430 100644 --- a/statusnet/lang/hu/strings.php +++ b/statusnet/lang/hu/strings.php @@ -28,6 +28,12 @@ $a->strings['Copy the security code from GNU Social here'] = 'Másolja be ide a $a->strings['Allow posting to GNU Social'] = 'Beküldés engedélyezése a GNU Socialra'; $a->strings['If enabled all your public postings can be posted to the associated GNU Social 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 GNU Social 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['Post to GNU Social by default'] = 'Beküldés a GNU Socialra alapértelmezetten'; +$a->strings['Mirror all public posts'] = 'Összes nyilvános bejegyzés tükrözése'; +$a->strings['Automatically create contacts'] = 'Partnerek automatikus létrehozása'; +$a->strings['Import the remote timeline'] = 'A távoli idővonal importálása'; +$a->strings['Disabled'] = 'Letiltva'; +$a->strings['Full Timeline'] = 'Teljes idővonal'; +$a->strings['Only Mentions'] = 'Csak említések'; $a->strings['GNU Social Import/Export/Mirror'] = 'GNU Social importálás, exportálás vagy tükrözés'; $a->strings['Site name'] = 'Oldal neve'; $a->strings['Consumer Secret'] = 'Felhasználói titok'; diff --git a/statusnet/lang/is/messages.po b/statusnet/lang/is/messages.po index fbf4e25d..512c6560 100644 --- a/statusnet/lang/is/messages.po +++ b/statusnet/lang/is/messages.po @@ -9,80 +9,80 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-12-21 22:32+0000\n" -"PO-Revision-Date: 2014-06-23 12:54+0000\n" -"Last-Translator: Sveinn í Felli , 2018\n" -"Language-Team: Icelandic (http://app.transifex.com/Friendica/friendica/language/is/)\n" +"POT-Creation-Date: 2015-07-27 07:21+0200\n" +"PO-Revision-Date: 2018-05-24 10:00+0000\n" +"Last-Translator: Sveinn í Felli \n" +"Language-Team: Icelandic (http://www.transifex.com/Friendica/friendica/language/is/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: is\n" "Plural-Forms: nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);\n" -#: statusnet.php:76 +#: statusnet.php:151 msgid "Post to GNU Social" msgstr "Senda á GNU Social" -#: statusnet.php:122 +#: statusnet.php:196 msgid "" "Please contact your site administrator.
The provided API URL is not " "valid." msgstr "Hafðu samband við kerfisstjóra.
Uppgefin API-slóð er ógild." -#: statusnet.php:150 +#: statusnet.php:225 msgid "We could not contact the GNU Social API with the Path you entered." msgstr "Ekki náðist í GNU Social API með slóðinni sem þú gafst upp." -#: statusnet.php:208 statusnet.php:489 -msgid "Save Settings" -msgstr "Vista stillingar" +#: statusnet.php:259 +msgid "GNU Social settings updated." +msgstr "Stillingar GNU Social uppfærðar." -#: statusnet.php:220 -#, php-format -msgid "Currently connected to: %s" +#: statusnet.php:294 statusnet.php:298 +msgid "GNU Social Import/Export/Mirror" msgstr "" -#: statusnet.php:225 -msgid "" -"Note: Due your privacy settings (Hide your profile " -"details from unknown viewers?) the link potentially included in public " -"postings relayed to GNU Social will lead the visitor to a blank page " -"informing the visitor that the access to your profile has been restricted." -msgstr "" - -#: statusnet.php:228 -msgid "Clear OAuth configuration" -msgstr "Hreinsa OAuth stillingar" - -#: statusnet.php:240 -msgid "Cancel GNU Social Connection" -msgstr "Hætta við GNU Social tengingu" - -#: statusnet.php:247 +#: statusnet.php:313 msgid "Globally Available GNU Social OAuthKeys" msgstr "Víðværir OAuth-lyklar GNU Social eru til taks" -#: statusnet.php:248 +#: statusnet.php:314 msgid "" "There are preconfigured OAuth key pairs for some GNU Social servers " "available. If you are using one of them, please use these credentials. If " "not feel free to connect to any other GNU Social instance (see below)." msgstr "Það eru forstillt OAuth-lyklapör í sumum GNU Social þjónum. Ef þú ert að nota slíkt par, notaðu þá þau auðkenni. Ef ekki þá er þér frjálst að tengjast hvaða öðrum GNU Social þjónum (sjá fyrir neðan)." -#: statusnet.php:249 +#: statusnet.php:320 statusnet.php:337 statusnet.php:364 statusnet.php:371 +#: statusnet.php:416 statusnet.php:699 +msgid "Save Settings" +msgstr "Vista stillingar" + +#: statusnet.php:322 msgid "Provide your own OAuth Credentials" msgstr "Gefðu upp eigin OAuth auðkenni" -#: statusnet.php:250 +#: statusnet.php:323 msgid "" "No consumer key pair for GNU Social found. Register your Friendica Account " -"as a desktop application on your GNU Social account, copy the consumer key " -"pair here and enter the API base root.
Before you register your own " -"OAuth key pair ask the administrator if there is already a key pair for this" -" Friendica installation at your favorite GNU Social installation." +"as an desktop client on your GNU Social account, copy the consumer key pair " +"here and enter the API base root.
Before you register your own OAuth " +"key pair ask the administrator if there is already a key pair for this " +"Friendica installation at your favorited GNU Social installation." msgstr "" -#: statusnet.php:251 +#: statusnet.php:325 +msgid "OAuth Consumer Key" +msgstr "OAuth-lykill notanda" + +#: statusnet.php:328 +msgid "OAuth Consumer Secret" +msgstr "OAuth-leyniorð notanda" + +#: statusnet.php:331 statusnet.php:679 statusnet.php:691 +msgid "Base API Path (remember the trailing /)" +msgstr "Grunn API-slóð (muna eftir / í endann)" + +#: statusnet.php:356 msgid "" "To connect to your GNU Social account click the button below to get a " "security code from GNU Social which you have to copy into the input box " @@ -90,62 +90,86 @@ msgid "" "posted to GNU Social." msgstr "Til að tengjast GNU Social notandaaðgangnum ýttu á hnappinn hér fyrir neðan, þá fæst öryggislykill frá GNU Social sem þarf að afrita í svæðið fyrir neðan og senda inn. Aðeins opinberar færslur munu flæða yfir á GNU Social." -#: statusnet.php:252 +#: statusnet.php:357 msgid "Log in with GNU Social" msgstr "Skrá inn með GNU Social" -#: statusnet.php:253 -msgid "Cancel Connection Process" -msgstr "Hætta við tengiferli" - -#: statusnet.php:254 -#, php-format -msgid "Current GNU Social API is: %s" -msgstr "" - -#: statusnet.php:271 -msgid "OAuth Consumer Key" -msgstr "OAuth-lykill notanda" - -#: statusnet.php:272 -msgid "OAuth Consumer Secret" -msgstr "OAuth-leyniorð notanda" - -#: statusnet.php:274 statusnet.php:469 statusnet.php:481 -msgid "Base API Path (remember the trailing /)" -msgstr "Grunn API-slóð (muna eftir / í endann)" - -#: statusnet.php:275 +#: statusnet.php:359 msgid "Copy the security code from GNU Social here" msgstr "Afrita öryggislykil frá GNU Social hingað" -#: statusnet.php:277 -msgid "Allow posting to GNU Social" -msgstr "Leyfa sendingu færslna til GNU Social" +#: statusnet.php:365 +msgid "Cancel Connection Process" +msgstr "Hætta við tengiferli" -#: statusnet.php:277 +#: statusnet.php:367 +msgid "Current GNU Social API is" +msgstr "Núverandi GNU Social API er" + +#: statusnet.php:368 +msgid "Cancel GNU Social Connection" +msgstr "Hætta við GNU Social tengingu" + +#: statusnet.php:379 +msgid "Currently connected to: " +msgstr "Núna tengdur við:" + +#: statusnet.php:380 msgid "" "If enabled all your public postings can be posted to the " "associated GNU Social account. You can choose to do so by default (here) or " "for every posting separately in the posting options when writing the entry." msgstr "Ef virkt þá geta allar opinberu stöðu meldingarnar þínar verið birtar á tengdri GNU Social síðu. Þú getur valið að gera þetta sjálfvirkt (hér) eða fyrir hvern póst í senn þegar hann er skrifaður." -#: statusnet.php:278 -msgid "Post to GNU Social by default" +#: statusnet.php:382 +msgid "" +"Note: Due your privacy settings (Hide your profile " +"details from unknown viewers?) the link potentially included in public " +"postings relayed to GNU Social will lead the visitor to a blank page " +"informing the visitor that the access to your profile has been restricted." msgstr "" -#: statusnet.php:283 -msgid "GNU Social Import/Export/Mirror" +#: statusnet.php:385 +msgid "Allow posting to GNU Social" +msgstr "Leyfa sendingu færslna til GNU Social" + +#: statusnet.php:388 +msgid "Send public postings to GNU Social by default" +msgstr "Sjálfgefið senda opinberar færslur á GNU Social" + +#: statusnet.php:392 +msgid "" +"Mirror all posts from GNU Social that are no replies or repeated messages" msgstr "" -#: statusnet.php:480 +#: statusnet.php:398 +msgid "Import the remote timeline" +msgstr "Flytja inn fjartengdu tímalínuna" + +#: statusnet.php:402 +msgid "Disabled" +msgstr "Slökkt" + +#: statusnet.php:403 +msgid "Full Timeline" +msgstr "Öll tímalínan" + +#: statusnet.php:404 +msgid "Only Mentions" +msgstr "" + +#: statusnet.php:413 +msgid "Clear OAuth configuration" +msgstr "Hreinsa OAuth stillingar" + +#: statusnet.php:690 msgid "Site name" msgstr "Heiti vefsvæðis" -#: statusnet.php:482 +#: statusnet.php:692 msgid "Consumer Secret" msgstr "Leyniorð notanda" -#: statusnet.php:483 +#: statusnet.php:693 msgid "Consumer Key" msgstr "Lykill notanda" diff --git a/statusnet/lang/is/strings.php b/statusnet/lang/is/strings.php index 18a3b8b6..bdf3c9a3 100644 --- a/statusnet/lang/is/strings.php +++ b/statusnet/lang/is/strings.php @@ -8,21 +8,28 @@ function string_plural_select_is($n){ $a->strings['Post to GNU Social'] = 'Senda á GNU Social'; $a->strings['Please contact your site administrator.
The provided API URL is not valid.'] = 'Hafðu samband við kerfisstjóra.
Uppgefin API-slóð er ógild.'; $a->strings['We could not contact the GNU Social API with the Path you entered.'] = 'Ekki náðist í GNU Social API með slóðinni sem þú gafst upp.'; -$a->strings['Save Settings'] = 'Vista stillingar'; -$a->strings['Clear OAuth configuration'] = 'Hreinsa OAuth stillingar'; -$a->strings['Cancel GNU Social Connection'] = 'Hætta við GNU Social tengingu'; +$a->strings['GNU Social settings updated.'] = 'Stillingar GNU Social uppfærðar.'; $a->strings['Globally Available GNU Social OAuthKeys'] = 'Víðværir OAuth-lyklar GNU Social eru til taks'; $a->strings['There are preconfigured OAuth key pairs for some GNU Social servers available. If you are using one of them, please use these credentials. If not feel free to connect to any other GNU Social instance (see below).'] = 'Það eru forstillt OAuth-lyklapör í sumum GNU Social þjónum. Ef þú ert að nota slíkt par, notaðu þá þau auðkenni. Ef ekki þá er þér frjálst að tengjast hvaða öðrum GNU Social þjónum (sjá fyrir neðan).'; +$a->strings['Save Settings'] = 'Vista stillingar'; $a->strings['Provide your own OAuth Credentials'] = 'Gefðu upp eigin OAuth auðkenni'; -$a->strings['To connect to your GNU Social account click the button below to get a security code from GNU Social which you have to copy into the input box below and submit the form. Only your public posts will be posted to GNU Social.'] = 'Til að tengjast GNU Social notandaaðgangnum ýttu á hnappinn hér fyrir neðan, þá fæst öryggislykill frá GNU Social sem þarf að afrita í svæðið fyrir neðan og senda inn. Aðeins opinberar færslur munu flæða yfir á GNU Social.'; -$a->strings['Log in with GNU Social'] = 'Skrá inn með GNU Social'; -$a->strings['Cancel Connection Process'] = 'Hætta við tengiferli'; $a->strings['OAuth Consumer Key'] = 'OAuth-lykill notanda'; $a->strings['OAuth Consumer Secret'] = 'OAuth-leyniorð notanda'; $a->strings['Base API Path (remember the trailing /)'] = 'Grunn API-slóð (muna eftir / í endann)'; +$a->strings['To connect to your GNU Social account click the button below to get a security code from GNU Social which you have to copy into the input box below and submit the form. Only your public posts will be posted to GNU Social.'] = 'Til að tengjast GNU Social notandaaðgangnum ýttu á hnappinn hér fyrir neðan, þá fæst öryggislykill frá GNU Social sem þarf að afrita í svæðið fyrir neðan og senda inn. Aðeins opinberar færslur munu flæða yfir á GNU Social.'; +$a->strings['Log in with GNU Social'] = 'Skrá inn með GNU Social'; $a->strings['Copy the security code from GNU Social here'] = 'Afrita öryggislykil frá GNU Social hingað'; -$a->strings['Allow posting to GNU Social'] = 'Leyfa sendingu færslna til GNU Social'; +$a->strings['Cancel Connection Process'] = 'Hætta við tengiferli'; +$a->strings['Current GNU Social API is'] = 'Núverandi GNU Social API er'; +$a->strings['Cancel GNU Social Connection'] = 'Hætta við GNU Social tengingu'; +$a->strings['Currently connected to: '] = 'Núna tengdur við:'; $a->strings['If enabled all your public postings can be posted to the associated GNU Social account. You can choose to do so by default (here) or for every posting separately in the posting options when writing the entry.'] = 'Ef virkt þá geta allar opinberu stöðu meldingarnar þínar verið birtar á tengdri GNU Social síðu. Þú getur valið að gera þetta sjálfvirkt (hér) eða fyrir hvern póst í senn þegar hann er skrifaður.'; +$a->strings['Allow posting to GNU Social'] = 'Leyfa sendingu færslna til GNU Social'; +$a->strings['Send public postings to GNU Social by default'] = 'Sjálfgefið senda opinberar færslur á GNU Social'; +$a->strings['Import the remote timeline'] = 'Flytja inn fjartengdu tímalínuna'; +$a->strings['Disabled'] = 'Slökkt'; +$a->strings['Full Timeline'] = 'Öll tímalínan'; +$a->strings['Clear OAuth configuration'] = 'Hreinsa OAuth stillingar'; $a->strings['Site name'] = 'Heiti vefsvæðis'; $a->strings['Consumer Secret'] = 'Leyniorð notanda'; $a->strings['Consumer Key'] = 'Lykill notanda'; diff --git a/statusnet/lang/it/messages.po b/statusnet/lang/it/messages.po index 6cc89fc9..9216db8f 100644 --- a/statusnet/lang/it/messages.po +++ b/statusnet/lang/it/messages.po @@ -5,85 +5,85 @@ # # Translators: # fabrixxm , 2014-2015 -# Sylke Vicious , 2020,2023 +# Sylke Vicious , 2020 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-12-21 22:32+0000\n" -"PO-Revision-Date: 2014-06-23 12:54+0000\n" -"Last-Translator: Sylke Vicious , 2020,2023\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"POT-Creation-Date: 2015-07-27 07:21+0200\n" +"PO-Revision-Date: 2020-09-17 11:40+0000\n" +"Last-Translator: Sylke Vicious \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: statusnet.php:76 +#: statusnet.php:151 msgid "Post to GNU Social" msgstr "Invia a GNU Social" -#: statusnet.php:122 +#: statusnet.php:196 msgid "" "Please contact your site administrator.
The provided API URL is not " "valid." msgstr "Contatta l'amministratore del sito.
L'URL delle API fornito non è valido." -#: statusnet.php:150 +#: statusnet.php:225 msgid "We could not contact the GNU Social API with the Path you entered." msgstr "Non possiamo conttattare le API di GNU Social con il percorso che hai inserito." -#: statusnet.php:208 statusnet.php:489 -msgid "Save Settings" -msgstr "Salva Impostazioni" +#: statusnet.php:259 +msgid "GNU Social settings updated." +msgstr "Impostazioni di GNU Social aggiornate." -#: statusnet.php:220 -#, php-format -msgid "Currently connected to: %s" -msgstr "Attualmente connesso a: %s" +#: statusnet.php:294 statusnet.php:298 +msgid "GNU Social Import/Export/Mirror" +msgstr "Esporta/Importa/Clona GNU Social" -#: statusnet.php:225 -msgid "" -"Note: Due your privacy settings (Hide your profile " -"details from unknown viewers?) the link potentially included in public " -"postings relayed to GNU Social 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 GNU Social porterà i visitatori a una pagina bianca con una nota che li informa che l'accesso al tuo profilo è stato limitato." - -#: statusnet.php:228 -msgid "Clear OAuth configuration" -msgstr "Rimuovi la configurazione OAuth" - -#: statusnet.php:240 -msgid "Cancel GNU Social Connection" -msgstr "Annulla la connessione a GNU Social" - -#: statusnet.php:247 +#: statusnet.php:313 msgid "Globally Available GNU Social OAuthKeys" msgstr "OAuthKeys globali di GNU Social" -#: statusnet.php:248 +#: statusnet.php:314 msgid "" "There are preconfigured OAuth key pairs for some GNU Social servers " "available. If you are using one of them, please use these credentials. If " "not feel free to connect to any other GNU Social instance (see below)." msgstr "Esistono coppie di chiavi OAuth precofigurate per alcuni server GNU Social. Se usi uno di questi server, per favore scegli queste credenziali. Altrimenti sei libero di collegarti a un'altra installazione di GNU Social (vedi sotto)." -#: statusnet.php:249 +#: statusnet.php:320 statusnet.php:337 statusnet.php:364 statusnet.php:371 +#: statusnet.php:416 statusnet.php:699 +msgid "Save Settings" +msgstr "Salva Impostazioni" + +#: statusnet.php:322 msgid "Provide your own OAuth Credentials" msgstr "Fornisci le tue credenziali OAuth" -#: statusnet.php:250 +#: statusnet.php:323 msgid "" "No consumer key pair for GNU Social found. Register your Friendica Account " -"as a desktop application on your GNU Social account, copy the consumer key " -"pair here and enter the API base root.
Before you register your own " -"OAuth key pair ask the administrator if there is already a key pair for this" -" Friendica installation at your favorite GNU Social installation." -msgstr "Coppia di chiavi consumer per GNU Social non trovata. Registra il tuo Account Friendica come applicazione desktop nel tuo account GNU Social, copia la coppia di chiavi consumer qui e inserisci il percorso delle API.
Prima di registrare una tua coppia di chiavi OAuth chiedi all'amministratore se esiste già una coppia di chiavi tra questa installazione Friendica e l'installazione GNU Social." +"as an desktop client on your GNU Social account, copy the consumer key pair " +"here and enter the API base root.
Before you register your own OAuth " +"key pair ask the administrator if there is already a key pair for this " +"Friendica installation at your favorited GNU Social installation." +msgstr "Nessuna coppia di chiavi consumer trovate per GNU Social. Registra il tuo account Friendica come un client desktop nel tuo account GNU Social, copia la coppia di chiavi consumer qui e inserisci l'url base delle API.
Prima di registrare la tua coppia di chiavi OAuth, chiedi all'amministratore se esiste già una coppia di chiavi per questo sito Friendica presso la tua installazione GNU Social preferita." -#: statusnet.php:251 +#: statusnet.php:325 +msgid "OAuth Consumer Key" +msgstr "OAuth Consumer Key" + +#: statusnet.php:328 +msgid "OAuth Consumer Secret" +msgstr "OAuth Consumer Secret" + +#: statusnet.php:331 statusnet.php:679 statusnet.php:691 +msgid "Base API Path (remember the trailing /)" +msgstr "Indirizzo di base per le API (ricorda la / alla fine)" + +#: statusnet.php:356 msgid "" "To connect to your GNU Social account click the button below to get a " "security code from GNU Social which you have to copy into the input box " @@ -91,62 +91,86 @@ msgid "" "posted to GNU Social." msgstr "Per collegare il tuo account GNU Social, clicca sul bottone per ottenere un codice di sicurezza da GNU Social, che dovrai copiare nel box sottostante e poi inviare la form. Solo i tuoi messaggi pubblici saranno inviati a GNU Social." -#: statusnet.php:252 +#: statusnet.php:357 msgid "Log in with GNU Social" msgstr "Accedi con GNU Social" -#: statusnet.php:253 -msgid "Cancel Connection Process" -msgstr "Annulla il processo di connessione" - -#: statusnet.php:254 -#, php-format -msgid "Current GNU Social API is: %s" -msgstr "La API attuale di GNU Social è: %s" - -#: statusnet.php:271 -msgid "OAuth Consumer Key" -msgstr "OAuth Consumer Key" - -#: statusnet.php:272 -msgid "OAuth Consumer Secret" -msgstr "OAuth Consumer Secret" - -#: statusnet.php:274 statusnet.php:469 statusnet.php:481 -msgid "Base API Path (remember the trailing /)" -msgstr "Indirizzo di base per le API (ricorda la / alla fine)" - -#: statusnet.php:275 +#: statusnet.php:359 msgid "Copy the security code from GNU Social here" msgstr "Copia il codice di sicurezza da GNU Social qui" -#: statusnet.php:277 -msgid "Allow posting to GNU Social" -msgstr "Permetti l'invio a GNU Social" +#: statusnet.php:365 +msgid "Cancel Connection Process" +msgstr "Annulla il processo di connessione" -#: statusnet.php:277 +#: statusnet.php:367 +msgid "Current GNU Social API is" +msgstr "Le API GNU Social correnti sono" + +#: statusnet.php:368 +msgid "Cancel GNU Social Connection" +msgstr "Annulla la connessione a GNU Social" + +#: statusnet.php:379 +msgid "Currently connected to: " +msgstr "Al momento connesso con:" + +#: statusnet.php:380 msgid "" "If enabled all your public postings can be posted to the " "associated GNU Social 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 GNU Social associato. Puoi scegliere di farlo sempre (qui) o ogni volta che invii, nelle impostazioni di privacy del messaggio." -#: statusnet.php:278 -msgid "Post to GNU Social by default" -msgstr "Pubblica su GNU Social per impostazione predefinita" +#: statusnet.php:382 +msgid "" +"Note: Due your privacy settings (Hide your profile " +"details from unknown viewers?) the link potentially included in public " +"postings relayed to GNU Social 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 GNU Social porterà i visitatori a una pagina bianca con una nota che li informa che l'accesso al tuo profilo è stato limitato." -#: statusnet.php:283 -msgid "GNU Social Import/Export/Mirror" -msgstr "Esporta/Importa/Clona GNU Social" +#: statusnet.php:385 +msgid "Allow posting to GNU Social" +msgstr "Permetti l'invio a GNU Social" -#: statusnet.php:480 +#: statusnet.php:388 +msgid "Send public postings to GNU Social by default" +msgstr "Invia sempre i messaggi pubblici a GNU Social" + +#: statusnet.php:392 +msgid "" +"Mirror all posts from GNU Social that are no replies or repeated messages" +msgstr "Clona tutti i messaggi da GNU Social che non sono risposte o messaggi ripetuti" + +#: statusnet.php:398 +msgid "Import the remote timeline" +msgstr "Importa la timeline remota" + +#: statusnet.php:402 +msgid "Disabled" +msgstr "Disabilitato" + +#: statusnet.php:403 +msgid "Full Timeline" +msgstr "Timeline completa" + +#: statusnet.php:404 +msgid "Only Mentions" +msgstr "Solo menzioni" + +#: statusnet.php:413 +msgid "Clear OAuth configuration" +msgstr "Rimuovi la configurazione OAuth" + +#: statusnet.php:690 msgid "Site name" msgstr "Nome del sito" -#: statusnet.php:482 +#: statusnet.php:692 msgid "Consumer Secret" msgstr "Consumer Secret" -#: statusnet.php:483 +#: statusnet.php:693 msgid "Consumer Key" msgstr "Consumer Key" diff --git a/statusnet/lang/it/strings.php b/statusnet/lang/it/strings.php index 309f8bb2..06bc8b12 100644 --- a/statusnet/lang/it/strings.php +++ b/statusnet/lang/it/strings.php @@ -3,32 +3,38 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $a->strings['Post to GNU Social'] = 'Invia a GNU Social'; $a->strings['Please contact your site administrator.
The provided API URL is not valid.'] = 'Contatta l\'amministratore del sito.
L\'URL delle API fornito non è valido.'; $a->strings['We could not contact the GNU Social API with the Path you entered.'] = 'Non possiamo conttattare le API di GNU Social con il percorso che hai inserito.'; -$a->strings['Save Settings'] = 'Salva Impostazioni'; -$a->strings['Currently connected to: %s'] = 'Attualmente connesso a: %s'; -$a->strings['Note: Due your privacy settings (Hide your profile details from unknown viewers?) the link potentially included in public postings relayed to GNU Social 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 GNU Social porterà i visitatori a una pagina bianca con una nota che li informa che l\'accesso al tuo profilo è stato limitato.'; -$a->strings['Clear OAuth configuration'] = 'Rimuovi la configurazione OAuth'; -$a->strings['Cancel GNU Social Connection'] = 'Annulla la connessione a GNU Social'; +$a->strings['GNU Social settings updated.'] = 'Impostazioni di GNU Social aggiornate.'; +$a->strings['GNU Social Import/Export/Mirror'] = 'Esporta/Importa/Clona GNU Social'; $a->strings['Globally Available GNU Social OAuthKeys'] = 'OAuthKeys globali di GNU Social'; $a->strings['There are preconfigured OAuth key pairs for some GNU Social servers available. If you are using one of them, please use these credentials. If not feel free to connect to any other GNU Social instance (see below).'] = 'Esistono coppie di chiavi OAuth precofigurate per alcuni server GNU Social. Se usi uno di questi server, per favore scegli queste credenziali. Altrimenti sei libero di collegarti a un\'altra installazione di GNU Social (vedi sotto).'; +$a->strings['Save Settings'] = 'Salva Impostazioni'; $a->strings['Provide your own OAuth Credentials'] = 'Fornisci le tue credenziali OAuth'; -$a->strings['No consumer key pair for GNU Social found. Register your Friendica Account as a desktop application on your GNU Social account, copy the consumer key pair here and enter the API base root.
Before you register your own OAuth key pair ask the administrator if there is already a key pair for this Friendica installation at your favorite GNU Social installation.'] = 'Coppia di chiavi consumer per GNU Social non trovata. Registra il tuo Account Friendica come applicazione desktop nel tuo account GNU Social, copia la coppia di chiavi consumer qui e inserisci il percorso delle API.
Prima di registrare una tua coppia di chiavi OAuth chiedi all\'amministratore se esiste già una coppia di chiavi tra questa installazione Friendica e l\'installazione GNU Social.'; -$a->strings['To connect to your GNU Social account click the button below to get a security code from GNU Social which you have to copy into the input box below and submit the form. Only your public posts will be posted to GNU Social.'] = 'Per collegare il tuo account GNU Social, clicca sul bottone per ottenere un codice di sicurezza da GNU Social, che dovrai copiare nel box sottostante e poi inviare la form. Solo i tuoi messaggi pubblici saranno inviati a GNU Social.'; -$a->strings['Log in with GNU Social'] = 'Accedi con GNU Social'; -$a->strings['Cancel Connection Process'] = 'Annulla il processo di connessione'; -$a->strings['Current GNU Social API is: %s'] = 'La API attuale di GNU Social è: %s'; +$a->strings['No consumer key pair for GNU Social found. Register your Friendica Account as an desktop client on your GNU Social account, copy the consumer key pair here and enter the API base root.
Before you register your own OAuth key pair ask the administrator if there is already a key pair for this Friendica installation at your favorited GNU Social installation.'] = 'Nessuna coppia di chiavi consumer trovate per GNU Social. Registra il tuo account Friendica come un client desktop nel tuo account GNU Social, copia la coppia di chiavi consumer qui e inserisci l\'url base delle API.
Prima di registrare la tua coppia di chiavi OAuth, chiedi all\'amministratore se esiste già una coppia di chiavi per questo sito Friendica presso la tua installazione GNU Social preferita.'; $a->strings['OAuth Consumer Key'] = 'OAuth Consumer Key'; $a->strings['OAuth Consumer Secret'] = 'OAuth Consumer Secret'; $a->strings['Base API Path (remember the trailing /)'] = 'Indirizzo di base per le API (ricorda la / alla fine)'; +$a->strings['To connect to your GNU Social account click the button below to get a security code from GNU Social which you have to copy into the input box below and submit the form. Only your public posts will be posted to GNU Social.'] = 'Per collegare il tuo account GNU Social, clicca sul bottone per ottenere un codice di sicurezza da GNU Social, che dovrai copiare nel box sottostante e poi inviare la form. Solo i tuoi messaggi pubblici saranno inviati a GNU Social.'; +$a->strings['Log in with GNU Social'] = 'Accedi con GNU Social'; $a->strings['Copy the security code from GNU Social here'] = 'Copia il codice di sicurezza da GNU Social qui'; -$a->strings['Allow posting to GNU Social'] = 'Permetti l\'invio a GNU Social'; +$a->strings['Cancel Connection Process'] = 'Annulla il processo di connessione'; +$a->strings['Current GNU Social API is'] = 'Le API GNU Social correnti sono'; +$a->strings['Cancel GNU Social Connection'] = 'Annulla la connessione a GNU Social'; +$a->strings['Currently connected to: '] = 'Al momento connesso con:'; $a->strings['If enabled all your public postings can be posted to the associated GNU Social 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 GNU Social associato. Puoi scegliere di farlo sempre (qui) o ogni volta che invii, nelle impostazioni di privacy del messaggio.'; -$a->strings['Post to GNU Social by default'] = 'Pubblica su GNU Social per impostazione predefinita'; -$a->strings['GNU Social Import/Export/Mirror'] = 'Esporta/Importa/Clona GNU Social'; +$a->strings['Note: Due your privacy settings (Hide your profile details from unknown viewers?) the link potentially included in public postings relayed to GNU Social 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 GNU Social porterà i visitatori a una pagina bianca con una nota che li informa che l\'accesso al tuo profilo è stato limitato.'; +$a->strings['Allow posting to GNU Social'] = 'Permetti l\'invio a GNU Social'; +$a->strings['Send public postings to GNU Social by default'] = 'Invia sempre i messaggi pubblici a GNU Social'; +$a->strings['Mirror all posts from GNU Social that are no replies or repeated messages'] = 'Clona tutti i messaggi da GNU Social che non sono risposte o messaggi ripetuti'; +$a->strings['Import the remote timeline'] = 'Importa la timeline remota'; +$a->strings['Disabled'] = 'Disabilitato'; +$a->strings['Full Timeline'] = 'Timeline completa'; +$a->strings['Only Mentions'] = 'Solo menzioni'; +$a->strings['Clear OAuth configuration'] = 'Rimuovi la configurazione OAuth'; $a->strings['Site name'] = 'Nome del sito'; $a->strings['Consumer Secret'] = 'Consumer Secret'; $a->strings['Consumer Key'] = 'Consumer Key'; diff --git a/statusnet/lang/nl/messages.po b/statusnet/lang/nl/messages.po index 0537d80b..e3d82e6e 100644 --- a/statusnet/lang/nl/messages.po +++ b/statusnet/lang/nl/messages.po @@ -9,80 +9,80 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-12-21 22:32+0000\n" -"PO-Revision-Date: 2014-06-23 12:54+0000\n" -"Last-Translator: Jeroen De Meerleer , 2018\n" -"Language-Team: Dutch (http://app.transifex.com/Friendica/friendica/language/nl/)\n" +"POT-Creation-Date: 2015-07-27 07:21+0200\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" "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" -#: statusnet.php:76 +#: statusnet.php:151 msgid "Post to GNU Social" msgstr "Post naar GNU Social" -#: statusnet.php:122 +#: statusnet.php:196 msgid "" "Please contact your site administrator.
The provided API URL is not " "valid." msgstr "" -#: statusnet.php:150 +#: statusnet.php:225 msgid "We could not contact the GNU Social API with the Path you entered." msgstr "" -#: statusnet.php:208 statusnet.php:489 -msgid "Save Settings" -msgstr "Instellingen opslaan" +#: statusnet.php:259 +msgid "GNU Social settings updated." +msgstr "GNU Social instellingen opgeslagen" -#: statusnet.php:220 -#, php-format -msgid "Currently connected to: %s" -msgstr "" +#: statusnet.php:294 statusnet.php:298 +msgid "GNU Social Import/Export/Mirror" +msgstr "GNU Social Import/Exporteren/Spiegelen" -#: statusnet.php:225 -msgid "" -"Note: Due your privacy settings (Hide your profile " -"details from unknown viewers?) the link potentially included in public " -"postings relayed to GNU Social will lead the visitor to a blank page " -"informing the visitor that the access to your profile has been restricted." -msgstr "" - -#: statusnet.php:228 -msgid "Clear OAuth configuration" -msgstr "" - -#: statusnet.php:240 -msgid "Cancel GNU Social Connection" -msgstr "" - -#: statusnet.php:247 +#: statusnet.php:313 msgid "Globally Available GNU Social OAuthKeys" msgstr "" -#: statusnet.php:248 +#: statusnet.php:314 msgid "" "There are preconfigured OAuth key pairs for some GNU Social servers " "available. If you are using one of them, please use these credentials. If " "not feel free to connect to any other GNU Social instance (see below)." msgstr "" -#: statusnet.php:249 +#: statusnet.php:320 statusnet.php:337 statusnet.php:364 statusnet.php:371 +#: statusnet.php:416 statusnet.php:699 +msgid "Save Settings" +msgstr "Instellingen opslaan" + +#: statusnet.php:322 msgid "Provide your own OAuth Credentials" msgstr "" -#: statusnet.php:250 +#: statusnet.php:323 msgid "" "No consumer key pair for GNU Social found. Register your Friendica Account " -"as a desktop application on your GNU Social account, copy the consumer key " -"pair here and enter the API base root.
Before you register your own " -"OAuth key pair ask the administrator if there is already a key pair for this" -" Friendica installation at your favorite GNU Social installation." +"as an desktop client on your GNU Social account, copy the consumer key pair " +"here and enter the API base root.
Before you register your own OAuth " +"key pair ask the administrator if there is already a key pair for this " +"Friendica installation at your favorited GNU Social installation." msgstr "" -#: statusnet.php:251 +#: statusnet.php:325 +msgid "OAuth Consumer Key" +msgstr "" + +#: statusnet.php:328 +msgid "OAuth Consumer Secret" +msgstr "" + +#: statusnet.php:331 statusnet.php:679 statusnet.php:691 +msgid "Base API Path (remember the trailing /)" +msgstr "" + +#: statusnet.php:356 msgid "" "To connect to your GNU Social account click the button below to get a " "security code from GNU Social which you have to copy into the input box " @@ -90,62 +90,86 @@ msgid "" "posted to GNU Social." msgstr "" -#: statusnet.php:252 +#: statusnet.php:357 msgid "Log in with GNU Social" msgstr "" -#: statusnet.php:253 -msgid "Cancel Connection Process" -msgstr "" - -#: statusnet.php:254 -#, php-format -msgid "Current GNU Social API is: %s" -msgstr "" - -#: statusnet.php:271 -msgid "OAuth Consumer Key" -msgstr "" - -#: statusnet.php:272 -msgid "OAuth Consumer Secret" -msgstr "" - -#: statusnet.php:274 statusnet.php:469 statusnet.php:481 -msgid "Base API Path (remember the trailing /)" -msgstr "" - -#: statusnet.php:275 +#: statusnet.php:359 msgid "Copy the security code from GNU Social here" msgstr "" -#: statusnet.php:277 -msgid "Allow posting to GNU Social" -msgstr "Plaatsen op GNU Social toestaan" +#: statusnet.php:365 +msgid "Cancel Connection Process" +msgstr "" -#: statusnet.php:277 +#: statusnet.php:367 +msgid "Current GNU Social API is" +msgstr "" + +#: statusnet.php:368 +msgid "Cancel GNU Social Connection" +msgstr "" + +#: statusnet.php:379 +msgid "Currently connected to: " +msgstr "" + +#: statusnet.php:380 msgid "" "If enabled all your public postings can be posted to the " "associated GNU Social account. You can choose to do so by default (here) or " "for every posting separately in the posting options when writing the entry." msgstr "" -#: statusnet.php:278 -msgid "Post to GNU Social by default" +#: statusnet.php:382 +msgid "" +"Note: Due your privacy settings (Hide your profile " +"details from unknown viewers?) the link potentially included in public " +"postings relayed to GNU Social will lead the visitor to a blank page " +"informing the visitor that the access to your profile has been restricted." msgstr "" -#: statusnet.php:283 -msgid "GNU Social Import/Export/Mirror" -msgstr "GNU Social Import/Exporteren/Spiegelen" +#: statusnet.php:385 +msgid "Allow posting to GNU Social" +msgstr "Plaatsen op GNU Social toestaan" -#: statusnet.php:480 +#: statusnet.php:388 +msgid "Send public postings to GNU Social by default" +msgstr "Verzend publieke berichten naar GNU Social als standaard instellen" + +#: statusnet.php:392 +msgid "" +"Mirror all posts from GNU Social that are no replies or repeated messages" +msgstr "" + +#: statusnet.php:398 +msgid "Import the remote timeline" +msgstr "" + +#: statusnet.php:402 +msgid "Disabled" +msgstr "Uitgeschakeld" + +#: statusnet.php:403 +msgid "Full Timeline" +msgstr "" + +#: statusnet.php:404 +msgid "Only Mentions" +msgstr "" + +#: statusnet.php:413 +msgid "Clear OAuth configuration" +msgstr "" + +#: statusnet.php:690 msgid "Site name" msgstr "" -#: statusnet.php:482 +#: statusnet.php:692 msgid "Consumer Secret" msgstr "" -#: statusnet.php:483 +#: statusnet.php:693 msgid "Consumer Key" msgstr "" diff --git a/statusnet/lang/nl/strings.php b/statusnet/lang/nl/strings.php index 038d2ac5..2914e7d4 100644 --- a/statusnet/lang/nl/strings.php +++ b/statusnet/lang/nl/strings.php @@ -6,6 +6,9 @@ function string_plural_select_nl($n){ return intval($n != 1); }} $a->strings['Post to GNU Social'] = 'Post naar GNU Social'; +$a->strings['GNU Social settings updated.'] = 'GNU Social instellingen opgeslagen'; +$a->strings['GNU Social Import/Export/Mirror'] = 'GNU Social Import/Exporteren/Spiegelen'; $a->strings['Save Settings'] = 'Instellingen opslaan'; $a->strings['Allow posting to GNU Social'] = 'Plaatsen op GNU Social toestaan'; -$a->strings['GNU Social Import/Export/Mirror'] = 'GNU Social Import/Exporteren/Spiegelen'; +$a->strings['Send public postings to GNU Social by default'] = 'Verzend publieke berichten naar GNU Social als standaard instellen'; +$a->strings['Disabled'] = 'Uitgeschakeld'; diff --git a/statusnet/lang/pl/messages.po b/statusnet/lang/pl/messages.po index 0f0fa1db..cfde6e2e 100644 --- a/statusnet/lang/pl/messages.po +++ b/statusnet/lang/pl/messages.po @@ -11,40 +11,40 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-12-21 22:32+0000\n" +"POT-Creation-Date: 2021-11-21 19:17-0500\n" "PO-Revision-Date: 2014-06-23 12:54+0000\n" "Last-Translator: Piotr Strębski , 2022\n" -"Language-Team: Polish (http://app.transifex.com/Friendica/friendica/language/pl/)\n" +"Language-Team: Polish (http://www.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" -#: statusnet.php:76 +#: statusnet.php:97 msgid "Post to GNU Social" msgstr "Opublikuj w GNU Social" -#: statusnet.php:122 +#: statusnet.php:148 msgid "" "Please contact your site administrator.
The provided API URL is not " "valid." msgstr "Skontaktuj się z administratorem witryny.
Podany adres URL interfejsu API jest nieprawidłowy." -#: statusnet.php:150 +#: statusnet.php:176 msgid "We could not contact the GNU Social API with the Path you entered." msgstr "Nie mogliśmy skontaktować się z GNU Social API z wprowadzoną ścieżką." -#: statusnet.php:208 statusnet.php:489 +#: statusnet.php:243 statusnet.php:656 msgid "Save Settings" msgstr "Zapisz ustawienia" -#: statusnet.php:220 +#: statusnet.php:255 #, php-format msgid "Currently connected to: %s" msgstr "Obecnie połączony z: %s" -#: statusnet.php:225 +#: statusnet.php:260 msgid "" "Note: Due your privacy settings (Hide your profile " "details from unknown viewers?) the link potentially included in public " @@ -52,30 +52,30 @@ msgid "" "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." -#: statusnet.php:228 +#: statusnet.php:263 msgid "Clear OAuth configuration" msgstr "Wyczyść konfigurację OAuth" -#: statusnet.php:240 +#: statusnet.php:275 msgid "Cancel GNU Social Connection" msgstr "Anuluj połaczenie z GNU Social" -#: statusnet.php:247 +#: statusnet.php:283 msgid "Globally Available GNU Social OAuthKeys" msgstr "Globalnie dostępne GNU Social OAuthKeys" -#: statusnet.php:248 +#: statusnet.php:284 msgid "" "There are preconfigured OAuth key pairs for some GNU Social servers " "available. If you are using one of them, please use these credentials. If " "not feel free to connect to any other GNU Social instance (see below)." msgstr "Istnieją wstępnie skonfigurowane pary kluczy OAuth dla niektórych serwerów społecznościowych GNU. Jeśli używasz jednego z nich, użyj tych poświadczeń. Jeśli nie, możesz połączyć się z dowolną inną instancją społecznościową GNU (patrz poniżej)." -#: statusnet.php:249 +#: statusnet.php:285 msgid "Provide your own OAuth Credentials" msgstr "Podaj własne dane uwierzytelniające OAuth" -#: statusnet.php:250 +#: statusnet.php:286 msgid "" "No consumer key pair for GNU Social found. Register your Friendica Account " "as a desktop application on your GNU Social account, copy the consumer key " @@ -84,7 +84,7 @@ msgid "" " Friendica installation at your favorite GNU Social installation." msgstr "Nie znaleziono pary kluczy konsumenckich dla GNU Social. Zarejestruj swoje konto Friendica jako aplikację komputerową na swoim koncie GNU Social, skopiuj tutaj parę kluczy klienta i wprowadź podstawowy root API.
Przed zarejestrowaniem własnej pary kluczy OAuth zapytaj administratora, czy istnieje już para kluczy dla tej instalacji Friendica pod adresem Twojej ulubionej instalacji GNU Social." -#: statusnet.php:251 +#: statusnet.php:287 msgid "" "To connect to your GNU Social account click the button below to get a " "security code from GNU Social which you have to copy into the input box " @@ -92,62 +92,86 @@ msgid "" "posted to GNU Social." msgstr "Aby połączyć się z kontem społecznościowym GNU, kliknij przycisk poniżej, aby uzyskać kod bezpieczeństwa z GNU Social, który musisz skopiować do poniższego pola wprowadzania i przesłać formularz. Tylko twoje publiczne posty będą publikowane w GNU Social." -#: statusnet.php:252 +#: statusnet.php:288 msgid "Log in with GNU Social" msgstr "Zaloguj się za pomocą GNU Social" -#: statusnet.php:253 +#: statusnet.php:289 msgid "Cancel Connection Process" msgstr "Anuluj proces połączenia" -#: statusnet.php:254 +#: statusnet.php:290 #, php-format msgid "Current GNU Social API is: %s" msgstr "Obecne API GNU Social to: %s" -#: statusnet.php:271 +#: statusnet.php:307 msgid "OAuth Consumer Key" msgstr "Klucz klienta OAuth" -#: statusnet.php:272 +#: statusnet.php:308 msgid "OAuth Consumer Secret" msgstr "Tajny klucz klienta OAuth" -#: statusnet.php:274 statusnet.php:469 statusnet.php:481 +#: statusnet.php:310 statusnet.php:636 statusnet.php:648 msgid "Base API Path (remember the trailing /)" msgstr "Podstawowa ścieżka interfejsu API (pamiętaj na końcu /)" -#: statusnet.php:275 +#: statusnet.php:311 msgid "Copy the security code from GNU Social here" msgstr "Skopiuj tutaj kod bezpieczeństwa z GNU Social" -#: statusnet.php:277 +#: statusnet.php:313 msgid "Allow posting to GNU Social" msgstr "Zezwalaj na publikowanie w GNU Social" -#: statusnet.php:277 +#: statusnet.php:313 msgid "" "If enabled all your public postings can be posted to the " "associated GNU Social 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ą zostać wysłane na powiązane konto społecznościowe GNU. Możesz to zrobić domyślnie (tutaj) lub dla każdego komentarza osobno w opcjach komentarza podczas pisania wpisu." -#: statusnet.php:278 +#: statusnet.php:314 msgid "Post to GNU Social by default" msgstr "Publikuj domyślnie w GNU Social" -#: statusnet.php:283 +#: statusnet.php:315 +msgid "Mirror all public posts" +msgstr "Odbij wszystkie publiczne wpisy" + +#: statusnet.php:316 +msgid "Automatically create contacts" +msgstr "Automatycznie twórz kontakty" + +#: statusnet.php:317 +msgid "Import the remote timeline" +msgstr "Zaimportuj na zdalnej oś czasu" + +#: statusnet.php:318 +msgid "Disabled" +msgstr "Wyłącz" + +#: statusnet.php:319 +msgid "Full Timeline" +msgstr "Pełna oś czasu" + +#: statusnet.php:320 +msgid "Only Mentions" +msgstr "Tylko wzmianki" + +#: statusnet.php:326 msgid "GNU Social Import/Export/Mirror" msgstr "GNU Social Import/Export/Mirror" -#: statusnet.php:480 +#: statusnet.php:647 msgid "Site name" msgstr "Nazwa strony" -#: statusnet.php:482 +#: statusnet.php:649 msgid "Consumer Secret" msgstr "Tajny klucz klienta" -#: statusnet.php:483 +#: statusnet.php:650 msgid "Consumer Key" msgstr "Klucz klienta" diff --git a/statusnet/lang/pl/strings.php b/statusnet/lang/pl/strings.php index 53b38655..76333a2a 100644 --- a/statusnet/lang/pl/strings.php +++ b/statusnet/lang/pl/strings.php @@ -28,6 +28,12 @@ $a->strings['Copy the security code from GNU Social here'] = 'Skopiuj tutaj kod $a->strings['Allow posting to GNU Social'] = 'Zezwalaj na publikowanie w GNU Social'; $a->strings['If enabled all your public postings can be posted to the associated GNU Social 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ą zostać wysłane na powiązane konto społecznościowe GNU. Możesz to zrobić domyślnie (tutaj) lub dla każdego komentarza osobno w opcjach komentarza podczas pisania wpisu.'; $a->strings['Post to GNU Social by default'] = 'Publikuj domyślnie w GNU Social'; +$a->strings['Mirror all public posts'] = 'Odbij wszystkie publiczne wpisy'; +$a->strings['Automatically create contacts'] = 'Automatycznie twórz kontakty'; +$a->strings['Import the remote timeline'] = 'Zaimportuj na zdalnej oś czasu'; +$a->strings['Disabled'] = 'Wyłącz'; +$a->strings['Full Timeline'] = 'Pełna oś czasu'; +$a->strings['Only Mentions'] = 'Tylko wzmianki'; $a->strings['GNU Social Import/Export/Mirror'] = 'GNU Social Import/Export/Mirror'; $a->strings['Site name'] = 'Nazwa strony'; $a->strings['Consumer Secret'] = 'Tajny klucz klienta'; diff --git a/statusnet/lang/sv/messages.po b/statusnet/lang/sv/messages.po index 0c0b4807..de131c33 100644 --- a/statusnet/lang/sv/messages.po +++ b/statusnet/lang/sv/messages.po @@ -9,40 +9,40 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-12-21 22:32+0000\n" -"PO-Revision-Date: 2014-06-23 12:54+0000\n" -"Last-Translator: Kristoffer Grundström , 2022\n" -"Language-Team: Swedish (http://app.transifex.com/Friendica/friendica/language/sv/)\n" +"POT-Creation-Date: 2021-11-21 19:17-0500\n" +"PO-Revision-Date: 2022-01-16 01:06+0000\n" +"Last-Translator: Kristoffer Grundström \n" +"Language-Team: Swedish (http://www.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" -#: statusnet.php:76 +#: statusnet.php:97 msgid "Post to GNU Social" msgstr "" -#: statusnet.php:122 +#: statusnet.php:148 msgid "" "Please contact your site administrator.
The provided API URL is not " "valid." msgstr "" -#: statusnet.php:150 +#: statusnet.php:176 msgid "We could not contact the GNU Social API with the Path you entered." msgstr "" -#: statusnet.php:208 statusnet.php:489 +#: statusnet.php:243 statusnet.php:656 msgid "Save Settings" msgstr "Spara inställningar" -#: statusnet.php:220 +#: statusnet.php:255 #, php-format msgid "Currently connected to: %s" msgstr "" -#: statusnet.php:225 +#: statusnet.php:260 msgid "" "Note: Due your privacy settings (Hide your profile " "details from unknown viewers?) the link potentially included in public " @@ -50,30 +50,30 @@ msgid "" "informing the visitor that the access to your profile has been restricted." msgstr "" -#: statusnet.php:228 +#: statusnet.php:263 msgid "Clear OAuth configuration" msgstr "" -#: statusnet.php:240 +#: statusnet.php:275 msgid "Cancel GNU Social Connection" msgstr "" -#: statusnet.php:247 +#: statusnet.php:283 msgid "Globally Available GNU Social OAuthKeys" msgstr "" -#: statusnet.php:248 +#: statusnet.php:284 msgid "" "There are preconfigured OAuth key pairs for some GNU Social servers " "available. If you are using one of them, please use these credentials. If " "not feel free to connect to any other GNU Social instance (see below)." msgstr "" -#: statusnet.php:249 +#: statusnet.php:285 msgid "Provide your own OAuth Credentials" msgstr "" -#: statusnet.php:250 +#: statusnet.php:286 msgid "" "No consumer key pair for GNU Social found. Register your Friendica Account " "as a desktop application on your GNU Social account, copy the consumer key " @@ -82,7 +82,7 @@ msgid "" " Friendica installation at your favorite GNU Social installation." msgstr "" -#: statusnet.php:251 +#: statusnet.php:287 msgid "" "To connect to your GNU Social account click the button below to get a " "security code from GNU Social which you have to copy into the input box " @@ -90,62 +90,86 @@ msgid "" "posted to GNU Social." msgstr "" -#: statusnet.php:252 +#: statusnet.php:288 msgid "Log in with GNU Social" msgstr "Logga in med GNU Social" -#: statusnet.php:253 +#: statusnet.php:289 msgid "Cancel Connection Process" msgstr "" -#: statusnet.php:254 +#: statusnet.php:290 #, php-format msgid "Current GNU Social API is: %s" msgstr "" -#: statusnet.php:271 +#: statusnet.php:307 msgid "OAuth Consumer Key" msgstr "" -#: statusnet.php:272 +#: statusnet.php:308 msgid "OAuth Consumer Secret" msgstr "" -#: statusnet.php:274 statusnet.php:469 statusnet.php:481 +#: statusnet.php:310 statusnet.php:636 statusnet.php:648 msgid "Base API Path (remember the trailing /)" msgstr "" -#: statusnet.php:275 +#: statusnet.php:311 msgid "Copy the security code from GNU Social here" msgstr "" -#: statusnet.php:277 +#: statusnet.php:313 msgid "Allow posting to GNU Social" msgstr "" -#: statusnet.php:277 +#: statusnet.php:313 msgid "" "If enabled all your public postings can be posted to the " "associated GNU Social account. You can choose to do so by default (here) or " "for every posting separately in the posting options when writing the entry." msgstr "" -#: statusnet.php:278 +#: statusnet.php:314 msgid "Post to GNU Social by default" msgstr "" -#: statusnet.php:283 +#: statusnet.php:315 +msgid "Mirror all public posts" +msgstr "" + +#: statusnet.php:316 +msgid "Automatically create contacts" +msgstr "" + +#: statusnet.php:317 +msgid "Import the remote timeline" +msgstr "" + +#: statusnet.php:318 +msgid "Disabled" +msgstr "" + +#: statusnet.php:319 +msgid "Full Timeline" +msgstr "Fullständig tidslinje" + +#: statusnet.php:320 +msgid "Only Mentions" +msgstr "Endast omnämningar" + +#: statusnet.php:326 msgid "GNU Social Import/Export/Mirror" msgstr "" -#: statusnet.php:480 +#: statusnet.php:647 msgid "Site name" msgstr "Namn på sidan" -#: statusnet.php:482 +#: statusnet.php:649 msgid "Consumer Secret" msgstr "Kundhemlighet" -#: statusnet.php:483 +#: statusnet.php:650 msgid "Consumer Key" msgstr "Kundnyckel" diff --git a/statusnet/lang/sv/strings.php b/statusnet/lang/sv/strings.php index e0a09d78..e1f41128 100644 --- a/statusnet/lang/sv/strings.php +++ b/statusnet/lang/sv/strings.php @@ -7,6 +7,8 @@ function string_plural_select_sv($n){ }} $a->strings['Save Settings'] = 'Spara inställningar'; $a->strings['Log in with GNU Social'] = 'Logga in med GNU Social'; +$a->strings['Full Timeline'] = 'Fullständig tidslinje'; +$a->strings['Only Mentions'] = 'Endast omnämningar'; $a->strings['Site name'] = 'Namn på sidan'; $a->strings['Consumer Secret'] = 'Kundhemlighet'; $a->strings['Consumer Key'] = 'Kundnyckel'; diff --git a/statusnet/statusnet.php b/statusnet/statusnet.php index f0372852..c168d612 100644 --- a/statusnet/statusnet.php +++ b/statusnet/statusnet.php @@ -266,7 +266,7 @@ function statusnet_settings(array &$data) '$request_token' => $request_token ?? null, '$account' => $account ?? null, - '$authenticate_url' => DI::baseUrl() . '/statusnet/connect', + '$authenticate_url' => DI::baseUrl()->get() . '/statusnet/connect', '$consumerkey' => ['statusnet-consumerkey', DI::l10n()->t('OAuth Consumer Key'), '', '', false, ' size="35'], '$consumersecret' => ['statusnet-consumersecret', DI::l10n()->t('OAuth Consumer Secret'), '', '', false, ' size="35'], @@ -350,7 +350,7 @@ function statusnet_post_hook(array &$b) } // Dont't post if the post doesn't belong to us. - // This is a check for group postings + // This is a check for forum postings $self = DBA::selectFirst('contact', ['id'], ['uid' => $b['uid'], 'self' => true]); if ($b['contact-id'] != $self['id']) { return; diff --git a/testdrive/lang/cs/messages.po b/testdrive/lang/cs/messages.po index 1640875d..ec29d51d 100644 --- a/testdrive/lang/cs/messages.po +++ b/testdrive/lang/cs/messages.po @@ -4,39 +4,38 @@ # # # Translators: -# Aditoo, 2018 -# michal_s , 2014 +# Michal Šupler , 2014 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: 2014-06-23 12:56+0000\n" -"Last-Translator: Aditoo, 2018\n" -"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" +"POT-Creation-Date: 2014-06-23 14:45+0200\n" +"PO-Revision-Date: 2014-07-28 18:16+0000\n" +"Last-Translator: Michal Šupler \n" +"Language-Team: Czech (http://www.transifex.com/projects/p/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" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -#: testdrive.php:64 +#: testdrive.php:67 msgid "Administrator" msgstr "Administrátor" -#: testdrive.php:89 +#: testdrive.php:94 #, php-format msgid "Your account on %s will expire in a few days." msgstr "Platnost Vašeho účtu na %s vyprší během několika dní." -#: testdrive.php:90 +#: testdrive.php:95 msgid "Your Friendica test account is about to expire." -msgstr "Váš testovací účet na Friendica brzy vyprší." +msgstr "Váš Friendica testovací účet brzy vyprší." -#: testdrive.php:91 +#: testdrive.php:96 #, php-format msgid "" "Hi %1$s,\n" "\n" -"Your test account on %2$s will expire in less than five days. We hope you enjoyed this test drive and use this opportunity to find a permanent Friendica website for your integrated social communications. A list of public sites is available at %s/siteinfo - and for more information on setting up your own Friendica server please see the Friendica project website at https://friendi.ca." -msgstr "" +"Your test account on %2$s will expire in less than five days. We hope you enjoyed this test drive and use this opportunity to find a permanent Friendica website for your integrated social communications. A list of public sites is available at http://dir.friendica.com/siteinfo - and for more information on setting up your own Friendica server please see the Friendica project website at http://friendica.com." +msgstr "Ahoj %1$s,\n\nplatnost Vašeho testovacího účtu na %2$s vyprší za méně než 5 dní. Doufáme, že jste si testovací jízdu užili a že se Vám povedlo najít trvalý Friendica server pro Vaši integrovanou sociální komunikaci. List veřejně dostupných serverů je k dispozici na http://dir.friendica.com/siteinfo - a pro více informací, jak si vytvořit svůj vlastní server, navštivte stránky projektu Friendica na adrese http://friendica.com." diff --git a/testdrive/lang/cs/strings.php b/testdrive/lang/cs/strings.php index cc68b58b..7eb1b5b0 100644 --- a/testdrive/lang/cs/strings.php +++ b/testdrive/lang/cs/strings.php @@ -3,8 +3,13 @@ if(! function_exists("string_plural_select_cs")) { function string_plural_select_cs($n){ $n = intval($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; } + if (($n==1)) { return 0; } else if (($n>=2 && $n<=4)) { return 1; } else { return 2; } }} $a->strings['Administrator'] = 'Administrátor'; $a->strings['Your account on %s will expire in a few days.'] = 'Platnost Vašeho účtu na %s vyprší během několika dní.'; -$a->strings['Your Friendica test account is about to expire.'] = 'Váš testovací účet na Friendica brzy vyprší.'; +$a->strings['Your Friendica test account is about to expire.'] = 'Váš Friendica testovací účet brzy vyprší.'; +$a->strings['Hi %1$s, + +Your test account on %2$s will expire in less than five days. We hope you enjoyed this test drive and use this opportunity to find a permanent Friendica website for your integrated social communications. A list of public sites is available at http://dir.friendica.com/siteinfo - and for more information on setting up your own Friendica server please see the Friendica project website at http://friendica.com.'] = 'Ahoj %1$s, + +platnost Vašeho testovacího účtu na %2$s vyprší za méně než 5 dní. Doufáme, že jste si testovací jízdu užili a že se Vám povedlo najít trvalý Friendica server pro Vaši integrovanou sociální komunikaci. List veřejně dostupných serverů je k dispozici na http://dir.friendica.com/siteinfo - a pro více informací, jak si vytvořit svůj vlastní server, navštivte stránky projektu Friendica na adrese http://friendica.com.'; diff --git a/testdrive/lang/de/messages.po b/testdrive/lang/de/messages.po index 8d7e7977..f91b1407 100644 --- a/testdrive/lang/de/messages.po +++ b/testdrive/lang/de/messages.po @@ -11,9 +11,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-02-01 18:15+0100\n" -"PO-Revision-Date: 2014-06-23 12:56+0000\n" -"Last-Translator: Tobias Diekershoff , 2021\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2021-03-29 05:42+0000\n" +"Last-Translator: Tobias Diekershoff \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/testdrive/lang/it/messages.po b/testdrive/lang/it/messages.po index f393766e..42a4a6ab 100644 --- a/testdrive/lang/it/messages.po +++ b/testdrive/lang/it/messages.po @@ -11,14 +11,14 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-02-01 18:15+0100\n" -"PO-Revision-Date: 2014-06-23 12:56+0000\n" -"Last-Translator: Sylke Vicious , 2021\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"PO-Revision-Date: 2021-04-19 11:11+0000\n" +"Last-Translator: Sylke Vicious \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: testdrive.php:64 msgid "Administrator" diff --git a/testdrive/lang/it/strings.php b/testdrive/lang/it/strings.php index 8faf5a06..8923cc15 100644 --- a/testdrive/lang/it/strings.php +++ b/testdrive/lang/it/strings.php @@ -3,7 +3,7 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $a->strings['Administrator'] = 'Amministratore'; $a->strings['Your account on %s will expire in a few days.'] = 'Il tuo account su %s scadrà tra pochi giorni.'; diff --git a/testdrive/testdrive.php b/testdrive/testdrive.php index 55645284..d9bc0b3b 100644 --- a/testdrive/testdrive.php +++ b/testdrive/testdrive.php @@ -59,8 +59,8 @@ function testdrive_cron($b) 'uid' => $rr['uid'], 'system_type' => 'testdrive_expire', 'source_name' => DI::l10n()->t('Administrator'), - 'source_link' => DI::baseUrl(), - 'source_photo' => DI::baseUrl() . '/images/person-80.jpg', + 'source_link' => DI::baseUrl()->get(), + 'source_photo' => DI::baseUrl()->get() . '/images/person-80.jpg', ]); DBA::update('user', ['expire_notification_sent' => DateTimeFormat::utcNow()], ['uid' => $rr['uid']]); @@ -76,7 +76,7 @@ function testdrive_enotify(array &$b) { if (!empty($b['params']) && $b['params']['type'] == Notification\Type::SYSTEM && !empty($b['params']['system_type']) && $b['params']['system_type'] === 'testdrive_expire') { - $b['itemlink'] = DI::baseUrl(); + $b['itemlink'] = DI::baseUrl()->get(); $b['epreamble'] = $b['preamble'] = DI::l10n()->t('Your account on %s will expire in a few days.', DI::config()->get('system', 'sitename')); $b['subject'] = DI::l10n()->t('Your Friendica test account is about to expire.'); $b['body'] = DI::l10n()->t("Hi %1\$s,\n\nYour test account on %2\$s will expire in less than five days. We hope you enjoyed this test drive and use this opportunity to find a permanent Friendica website for your integrated social communications. A list of public sites is available at %s/siteinfo - and for more information on setting up your own Friendica server please see the Friendica project website at https://friendi.ca.", $b['params']['to_name'], "[url=".DI::config()->get('system', 'url')."]".DI::config()->get('config', 'sitename')."[/url]", Search::getGlobalDirectory()); diff --git a/tictac/lang/cs/messages.po b/tictac/lang/cs/messages.po index cd720924..7e2725da 100644 --- a/tictac/lang/cs/messages.po +++ b/tictac/lang/cs/messages.po @@ -4,72 +4,71 @@ # # # Translators: -# Aditoo, 2018 -# michal_s , 2014 +# Michal Šupler , 2014 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: 2014-06-23 12:57+0000\n" -"Last-Translator: Aditoo, 2018\n" -"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" +"POT-Creation-Date: 2014-06-23 14:45+0200\n" +"PO-Revision-Date: 2014-07-28 18:18+0000\n" +"Last-Translator: Michal Šupler \n" +"Language-Team: Czech (http://www.transifex.com/projects/p/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" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -#: tictac.php:16 +#: tictac.php:20 msgid "Three Dimensional Tic-Tac-Toe" -msgstr "Trojrozměrné piškvorky" +msgstr "Trojrozměrné Tic-Tac-Toe" -#: tictac.php:49 +#: tictac.php:53 msgid "3D Tic-Tac-Toe" -msgstr "3D piškvorky" +msgstr "3D Tic-Tac-Toe" -#: tictac.php:54 +#: tictac.php:58 msgid "New game" msgstr "Nová hra" -#: tictac.php:55 +#: tictac.php:59 msgid "New game with handicap" msgstr "Nová hra s handicapem" -#: tictac.php:56 +#: tictac.php:60 msgid "" "Three dimensional tic-tac-toe is just like the traditional game except that " "it is played on multiple levels simultaneously. " -msgstr "Trojrozměrné piškvorky jsou podobné této tradiční hře kromě toho, že se hrají na více úrovních současně." +msgstr "Trojrozměrné tic-tac-toe je podobná této tradiční hře kromě toho, že se hraje na více úrovních současně." -#: tictac.php:57 +#: tictac.php:61 msgid "" "In this case there are three levels. You win by getting three in a row on " "any level, as well as up, down, and diagonally across the different levels." msgstr "V tomto případě existují tři úrovně. Vyhrajete tím, že dostane tři v řadě na jakékoli úrovni, stejně jako nahoru, dolů a šikmo na různých úrovních." -#: tictac.php:59 +#: tictac.php:63 msgid "" "The handicap game disables the center position on the middle level because " "the player claiming this square often has an unfair advantage." msgstr "Hra s handicapem zakáže centrální pozici na střední úrovni, protože hráč zaujímající tuto polohu má často nespravedlivou výhodu." -#: tictac.php:178 +#: tictac.php:182 msgid "You go first..." msgstr "Vy začněte ..." -#: tictac.php:183 +#: tictac.php:187 msgid "I'm going first this time..." msgstr "Tentokrát začnu já..." -#: tictac.php:189 +#: tictac.php:193 msgid "You won!" -msgstr "Vyhrál/a jste!" +msgstr "Vyhrál jste!" -#: tictac.php:195 tictac.php:220 +#: tictac.php:199 tictac.php:224 msgid "\"Cat\" game!" -msgstr "Remíza!" +msgstr "Pat hra!" -#: tictac.php:218 +#: tictac.php:222 msgid "I won!" msgstr "Vyhrál jsem!" diff --git a/tictac/lang/cs/strings.php b/tictac/lang/cs/strings.php index f895d630..f128aeda 100644 --- a/tictac/lang/cs/strings.php +++ b/tictac/lang/cs/strings.php @@ -3,17 +3,17 @@ if(! function_exists("string_plural_select_cs")) { function string_plural_select_cs($n){ $n = intval($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; } + if (($n==1)) { return 0; } else if (($n>=2 && $n<=4)) { return 1; } else { return 2; } }} -$a->strings['Three Dimensional Tic-Tac-Toe'] = 'Trojrozměrné piškvorky'; -$a->strings['3D Tic-Tac-Toe'] = '3D piškvorky'; +$a->strings['Three Dimensional Tic-Tac-Toe'] = 'Trojrozměrné Tic-Tac-Toe'; +$a->strings['3D Tic-Tac-Toe'] = '3D Tic-Tac-Toe'; $a->strings['New game'] = 'Nová hra'; $a->strings['New game with handicap'] = 'Nová hra s handicapem'; -$a->strings['Three dimensional tic-tac-toe is just like the traditional game except that it is played on multiple levels simultaneously. '] = 'Trojrozměrné piškvorky jsou podobné této tradiční hře kromě toho, že se hrají na více úrovních současně.'; +$a->strings['Three dimensional tic-tac-toe is just like the traditional game except that it is played on multiple levels simultaneously. '] = 'Trojrozměrné tic-tac-toe je podobná této tradiční hře kromě toho, že se hraje na více úrovních současně.'; $a->strings['In this case there are three levels. You win by getting three in a row on any level, as well as up, down, and diagonally across the different levels.'] = 'V tomto případě existují tři úrovně. Vyhrajete tím, že dostane tři v řadě na jakékoli úrovni, stejně jako nahoru, dolů a šikmo na různých úrovních.'; $a->strings['The handicap game disables the center position on the middle level because the player claiming this square often has an unfair advantage.'] = 'Hra s handicapem zakáže centrální pozici na střední úrovni, protože hráč zaujímající tuto polohu má často nespravedlivou výhodu.'; $a->strings['You go first...'] = 'Vy začněte ...'; $a->strings['I\'m going first this time...'] = 'Tentokrát začnu já...'; -$a->strings['You won!'] = 'Vyhrál/a jste!'; -$a->strings['"Cat" game!'] = 'Remíza!'; +$a->strings['You won!'] = 'Vyhrál jste!'; +$a->strings['"Cat" game!'] = 'Pat hra!'; $a->strings['I won!'] = 'Vyhrál jsem!'; diff --git a/tictac/lang/de/messages.po b/tictac/lang/de/messages.po index 351aaf32..da67a6f7 100644 --- a/tictac/lang/de/messages.po +++ b/tictac/lang/de/messages.po @@ -11,9 +11,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-02-01 18:15+0100\n" -"PO-Revision-Date: 2014-06-23 12:57+0000\n" -"Last-Translator: Ulf Rompe , 2019\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2019-02-11 13:44+0000\n" +"Last-Translator: Ulf Rompe \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/tictac/lang/it/messages.po b/tictac/lang/it/messages.po index e8f01e49..fc0458f1 100644 --- a/tictac/lang/it/messages.po +++ b/tictac/lang/it/messages.po @@ -9,66 +9,66 @@ 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: 2014-06-23 12:57+0000\n" -"Last-Translator: fabrixxm , 2014\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"POT-Creation-Date: 2013-02-27 05:01-0500\n" +"PO-Revision-Date: 2017-09-20 06:09+0000\n" +"Last-Translator: fabrixxm \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: tictac.php:16 +#: tictac.php:20 msgid "Three Dimensional Tic-Tac-Toe" msgstr "Tic-Tac-Toe tridimensionale" -#: tictac.php:49 +#: tictac.php:53 msgid "3D Tic-Tac-Toe" msgstr "3D Tic-Tac-Toe" -#: tictac.php:54 +#: tictac.php:58 msgid "New game" msgstr "Nuova partita" -#: tictac.php:55 +#: tictac.php:59 msgid "New game with handicap" msgstr "Nuova partita con handicap" -#: tictac.php:56 +#: tictac.php:60 msgid "" "Three dimensional tic-tac-toe is just like the traditional game except that " "it is played on multiple levels simultaneously. " msgstr "Tic-tac-toe tridimensionale è come il gioco tradizionale, solo che si gioca su livelli multipli contemporaneamente." -#: tictac.php:57 +#: tictac.php:61 msgid "" "In this case there are three levels. You win by getting three in a row on " "any level, as well as up, down, and diagonally across the different levels." msgstr "In questo caso ci sono tre livelli. Puoi vincere mettendo tre segni in fila su ogni livello, anche verso l'alto, il basso e diagonalmente anche attraverso i diversi livelli." -#: tictac.php:59 +#: tictac.php:63 msgid "" "The handicap game disables the center position on the middle level because " "the player claiming this square often has an unfair advantage." msgstr "L'handicap disabilita la casella centrale sul livello di mezzo, perchè il giocatore che si prende quella casella spesso ha un deciso vantaggio." -#: tictac.php:178 +#: tictac.php:182 msgid "You go first..." msgstr "Cominci tu..." -#: tictac.php:183 +#: tictac.php:187 msgid "I'm going first this time..." msgstr "Comincio io questa volta..." -#: tictac.php:189 +#: tictac.php:193 msgid "You won!" msgstr "Hai vinto!" -#: tictac.php:195 tictac.php:220 +#: tictac.php:199 tictac.php:224 msgid "\"Cat\" game!" msgstr "Stallo!" -#: tictac.php:218 +#: tictac.php:222 msgid "I won!" msgstr "Ho vinto!" diff --git a/tictac/lang/it/strings.php b/tictac/lang/it/strings.php index 716be3c2..10f63f57 100644 --- a/tictac/lang/it/strings.php +++ b/tictac/lang/it/strings.php @@ -3,7 +3,7 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $a->strings['Three Dimensional Tic-Tac-Toe'] = 'Tic-Tac-Toe tridimensionale'; $a->strings['3D Tic-Tac-Toe'] = '3D Tic-Tac-Toe'; diff --git a/tumblr/README.md b/tumblr/README.md index 98ff2161..57ca145a 100644 --- a/tumblr/README.md +++ b/tumblr/README.md @@ -1,7 +1,12 @@ Installation ------------ -[Register](http://www.tumblr.com/oauth/apps) an application and use (your server name)/tumblr/callback as -callback URL and (your server name)/tumblr/redirect as OAuth2 redirect URL. +[Register](http://www.tumblr.com/oauth/apps) an application and use (your server name)/addon/tumblr/callback.php as +callback URL -After the registration please enter the values for "Consumer Key" and "Consumer Secret" in the [administration](admin/addons/tumblr). \ No newline at end of file +After the registration please enter the values for "Consumer Key" and "Consumer Secret" in the [administration](admin/addons/tumblr). + +Notice +------ +This connector is using the Tumblr-OAuth-Library: +[https://groups.google.com/d/msg/tumblr-api/g6SeIBWvsnE/gnWqT9jFSlEJ](https://groups.google.com/d/msg/tumblr-api/g6SeIBWvsnE/gnWqT9jFSlEJ) diff --git a/tumblr/lang/C/messages.po b/tumblr/lang/C/messages.po index 74968015..83434406 100644 --- a/tumblr/lang/C/messages.po +++ b/tumblr/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-04-29 06:56+0000\n" +"POT-Creation-Date: 2021-11-21 19:17-0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,71 +17,54 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: tumblr.php:243 +#: tumblr.php:39 msgid "Permission denied." msgstr "" -#: tumblr.php:296 +#: tumblr.php:69 msgid "Save Settings" msgstr "" -#: tumblr.php:297 +#: tumblr.php:71 msgid "Consumer Key" msgstr "" -#: tumblr.php:298 +#: tumblr.php:72 msgid "Consumer Secret" msgstr "" -#: tumblr.php:299 -msgid "Maximum tags" +#: tumblr.php:177 +msgid "You are now authenticated to tumblr." msgstr "" -#: tumblr.php:299 -msgid "" -"Maximum number of tags that a user can follow. Enter 0 to deactivate the " -"feature." +#: tumblr.php:178 +msgid "return to the connector page" msgstr "" -#: tumblr.php:336 +#: tumblr.php:194 +msgid "Post to Tumblr" +msgstr "" + +#: tumblr.php:225 msgid "Post to page:" msgstr "" -#: tumblr.php:342 +#: tumblr.php:231 msgid "(Re-)Authenticate your tumblr page" msgstr "" -#: tumblr.php:343 +#: tumblr.php:232 msgid "You are not authenticated to tumblr" msgstr "" -#: tumblr.php:348 +#: tumblr.php:237 msgid "Enable Tumblr Post Addon" msgstr "" -#: tumblr.php:349 +#: tumblr.php:238 msgid "Post to Tumblr by default" msgstr "" -#: 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" +#: tumblr.php:244 +msgid "Tumblr Export" msgstr "" diff --git a/tumblr/lang/cs/messages.po b/tumblr/lang/cs/messages.po index 4e031be6..ebb525ff 100644 --- a/tumblr/lang/cs/messages.po +++ b/tumblr/lang/cs/messages.po @@ -4,71 +4,62 @@ # # # Translators: -# Aditoo, 2018 -# Aditoo, 2018 +# Lorem Ipsum , 2018 # michal_s , 2014 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:17-0500\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" +"POT-Creation-Date: 2013-02-27 05:01-0500\n" +"PO-Revision-Date: 2018-06-10 09:07+0000\n" +"Last-Translator: Lorem Ipsum \n" +"Language-Team: Czech (http://www.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" -#: tumblr.php:39 +#: tumblr.php:34 msgid "Permission denied." msgstr "Přístup odmítnut." -#: tumblr.php:69 -msgid "Save Settings" -msgstr "" - -#: tumblr.php:71 -msgid "Consumer Key" -msgstr "" - -#: tumblr.php:72 -msgid "Consumer Secret" -msgstr "" - -#: tumblr.php:177 +#: tumblr.php:144 msgid "You are now authenticated to tumblr." -msgstr "Nyní jste přihlášen/a k Tumblr." +msgstr "Nyní jste přihlášen k tumblr." -#: tumblr.php:178 +#: tumblr.php:145 msgid "return to the connector page" msgstr "návrat ke stránce konektor" -#: tumblr.php:194 +#: tumblr.php:158 msgid "Post to Tumblr" -msgstr "Posílat na Tumblr" +msgstr "Příspěvek na Tumbir" -#: tumblr.php:225 -msgid "Post to page:" -msgstr "Posílat na stránku:" +#: tumblr.php:185 +msgid "Tumblr Post Settings" +msgstr "Nastavení Tumblr Post" -#: tumblr.php:231 +#: tumblr.php:188 msgid "(Re-)Authenticate your tumblr page" -msgstr "(Znovu) přihlásit k Vaší stránce Tumblr" +msgstr "(Znovu) přihlásit k Vaší tumblr stránce" -#: tumblr.php:232 -msgid "You are not authenticated to tumblr" -msgstr "Nyní nejste přihlášen/a k Tumblr." - -#: tumblr.php:237 +#: tumblr.php:192 msgid "Enable Tumblr Post Addon" msgstr "Povolit doplněk Tumblr Post" -#: tumblr.php:238 +#: tumblr.php:197 msgid "Post to Tumblr by default" -msgstr "Ve výchozím stavu posílat příspěvky na Tumblr" +msgstr "Standardně posílat příspěvky na Tumbir" -#: tumblr.php:244 -msgid "Tumblr Export" -msgstr "" +#: tumblr.php:217 +msgid "Post to page:" +msgstr "Příspěvek ke stránce:" + +#: tumblr.php:228 +msgid "You are not authenticated to tumblr" +msgstr "Nyní nejste přihlášen k tumblr." + +#: tumblr.php:233 +msgid "Submit" +msgstr "Odeslat" diff --git a/tumblr/lang/cs/strings.php b/tumblr/lang/cs/strings.php index 2f5f8115..6c0a2b10 100644 --- a/tumblr/lang/cs/strings.php +++ b/tumblr/lang/cs/strings.php @@ -6,11 +6,13 @@ 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['Permission denied.'] = 'Přístup odmítnut.'; -$a->strings['You are now authenticated to tumblr.'] = 'Nyní jste přihlášen/a k Tumblr.'; +$a->strings['You are now authenticated to tumblr.'] = 'Nyní jste přihlášen k tumblr.'; $a->strings['return to the connector page'] = 'návrat ke stránce konektor'; -$a->strings['Post to Tumblr'] = 'Posílat na Tumblr'; -$a->strings['Post to page:'] = 'Posílat na stránku:'; -$a->strings['(Re-)Authenticate your tumblr page'] = '(Znovu) přihlásit k Vaší stránce Tumblr'; -$a->strings['You are not authenticated to tumblr'] = 'Nyní nejste přihlášen/a k Tumblr.'; +$a->strings['Post to Tumblr'] = 'Příspěvek na Tumbir'; +$a->strings['Tumblr Post Settings'] = 'Nastavení Tumblr Post'; +$a->strings['(Re-)Authenticate your tumblr page'] = '(Znovu) přihlásit k Vaší tumblr stránce'; $a->strings['Enable Tumblr Post Addon'] = 'Povolit doplněk Tumblr Post'; -$a->strings['Post to Tumblr by default'] = 'Ve výchozím stavu posílat příspěvky na Tumblr'; +$a->strings['Post to Tumblr by default'] = 'Standardně posílat příspěvky na Tumbir'; +$a->strings['Post to page:'] = 'Příspěvek ke stránce:'; +$a->strings['You are not authenticated to tumblr'] = 'Nyní nejste přihlášen k tumblr.'; +$a->strings['Submit'] = 'Odeslat'; diff --git a/tumblr/lang/de/messages.po b/tumblr/lang/de/messages.po index 8056174d..adeb5de1 100644 --- a/tumblr/lang/de/messages.po +++ b/tumblr/lang/de/messages.po @@ -11,10 +11,10 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:17-0500\n" -"PO-Revision-Date: 2014-06-23 12:58+0000\n" -"Last-Translator: Tobias Diekershoff , 2018,2021\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"POT-Creation-Date: 2021-02-01 18:16+0100\n" +"PO-Revision-Date: 2021-02-06 16:53+0000\n" +"Last-Translator: Tobias Diekershoff \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -25,7 +25,7 @@ msgstr "" msgid "Permission denied." msgstr "Zugriff verweigert." -#: tumblr.php:69 +#: tumblr.php:69 tumblr.php:283 msgid "Save Settings" msgstr "Einstellungen speichern" @@ -49,26 +49,26 @@ msgstr "zurück zur Connector-Seite" msgid "Post to Tumblr" msgstr "Auf Tumblr veröffentlichen" -#: tumblr.php:225 -msgid "Post to page:" -msgstr "Auf tumblr veröffentlichen" +#: tumblr.php:224 tumblr.php:228 +msgid "Tumblr Export" +msgstr "Tumblr Export" -#: tumblr.php:231 +#: tumblr.php:232 msgid "(Re-)Authenticate your tumblr page" msgstr "(Re-)Authentifizierung deiner tumblr-Seite" -#: tumblr.php:232 -msgid "You are not authenticated to tumblr" -msgstr "Du bist gegenüber tumblr nicht authentifiziert" - -#: tumblr.php:237 +#: tumblr.php:236 msgid "Enable Tumblr Post Addon" msgstr "Tumblr-Post-Addon aktivieren" -#: tumblr.php:238 +#: tumblr.php:242 msgid "Post to Tumblr by default" msgstr "Standardmäßig bei Tumblr veröffentlichen" -#: tumblr.php:244 -msgid "Tumblr Export" -msgstr "Tumblr Export" +#: tumblr.php:263 +msgid "Post to page:" +msgstr "Auf tumblr veröffentlichen" + +#: tumblr.php:277 +msgid "You are not authenticated to tumblr" +msgstr "Du bist gegenüber tumblr nicht authentifiziert" diff --git a/tumblr/lang/de/strings.php b/tumblr/lang/de/strings.php index ce43615c..a961347b 100644 --- a/tumblr/lang/de/strings.php +++ b/tumblr/lang/de/strings.php @@ -12,9 +12,9 @@ $a->strings['Consumer Secret'] = 'Consumer Secret'; $a->strings['You are now authenticated to tumblr.'] = 'Du bist nun auf tumblr authentifiziert.'; $a->strings['return to the connector page'] = 'zurück zur Connector-Seite'; $a->strings['Post to Tumblr'] = 'Auf Tumblr veröffentlichen'; -$a->strings['Post to page:'] = 'Auf tumblr veröffentlichen'; +$a->strings['Tumblr Export'] = 'Tumblr Export'; $a->strings['(Re-)Authenticate your tumblr page'] = '(Re-)Authentifizierung deiner tumblr-Seite'; -$a->strings['You are not authenticated to tumblr'] = 'Du bist gegenüber tumblr nicht authentifiziert'; $a->strings['Enable Tumblr Post Addon'] = 'Tumblr-Post-Addon aktivieren'; $a->strings['Post to Tumblr by default'] = 'Standardmäßig bei Tumblr veröffentlichen'; -$a->strings['Tumblr Export'] = 'Tumblr Export'; +$a->strings['Post to page:'] = 'Auf tumblr veröffentlichen'; +$a->strings['You are not authenticated to tumblr'] = 'Du bist gegenüber tumblr nicht authentifiziert'; diff --git a/tumblr/lang/es/messages.po b/tumblr/lang/es/messages.po index d78060c6..83f1d7be 100644 --- a/tumblr/lang/es/messages.po +++ b/tumblr/lang/es/messages.po @@ -10,81 +10,64 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \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" +"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" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: es\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: tumblr.php:243 +#: tumblr.php:39 msgid "Permission denied." msgstr "Permiso denegado." -#: tumblr.php:296 +#: tumblr.php:69 tumblr.php:283 msgid "Save Settings" msgstr "Guardar ajustes" -#: tumblr.php:297 +#: tumblr.php:71 msgid "Consumer Key" msgstr "Consumer Key" -#: tumblr.php:298 +#: tumblr.php:72 msgid "Consumer Secret" msgstr "Consumer Secret" -#: tumblr.php:299 -msgid "Maximum tags" -msgstr "" +#: tumblr.php:177 +msgid "You are now authenticated to tumblr." +msgstr "Está ahora autenticado en tumblr." -#: tumblr.php:299 -msgid "" -"Maximum number of tags that a user can follow. Enter 0 to deactivate the " -"feature." -msgstr "" +#: tumblr.php:178 +msgid "return to the connector page" +msgstr "Vuelva a la página del conector" -#: tumblr.php:336 -msgid "Post to page:" -msgstr "Publicar en página:" +#: tumblr.php:194 +msgid "Post to Tumblr" +msgstr "Publicar en Tumblr" -#: tumblr.php:342 +#: 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:343 -msgid "You are not authenticated to tumblr" -msgstr "No está autenticado en tumblr" - -#: tumblr.php:348 +#: tumblr.php:236 msgid "Enable Tumblr Post Addon" msgstr "Habilitar el complemento de publicación de Tumblr" -#: tumblr.php:349 +#: tumblr.php:242 msgid "Post to Tumblr by default" msgstr "Publique en Tumblr por defecto" -#: tumblr.php:350 -msgid "Import the remote timeline" -msgstr "" +#: tumblr.php:263 +msgid "Post to page:" +msgstr "Publicar en página:" -#: 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" +#: tumblr.php:277 +msgid "You are not authenticated to tumblr" +msgstr "No está autenticado en tumblr" diff --git a/tumblr/lang/es/strings.php b/tumblr/lang/es/strings.php index 550f6dc8..a124729b 100644 --- a/tumblr/lang/es/strings.php +++ b/tumblr/lang/es/strings.php @@ -3,15 +3,18 @@ if(! function_exists("string_plural_select_es")) { function string_plural_select_es($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $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['Post to page:'] = 'Publicar en página:'; +$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['(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 Tumblr'] = 'Publicar en Tumblr'; +$a->strings['Post to page:'] = 'Publicar en página:'; +$a->strings['You are not authenticated to tumblr'] = 'No está autenticado en tumblr'; diff --git a/tumblr/lang/fr/messages.po b/tumblr/lang/fr/messages.po index ef2f0e3c..3e9fe83d 100644 --- a/tumblr/lang/fr/messages.po +++ b/tumblr/lang/fr/messages.po @@ -5,87 +5,69 @@ # # Translators: # bob lebonche , 2021 -# Florent C., 2023 # StefOfficiel , 2015 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-04-29 06:56+0000\n" +"POT-Creation-Date: 2021-11-21 19:17-0500\n" "PO-Revision-Date: 2014-06-23 12:58+0000\n" -"Last-Translator: Florent C., 2023\n" -"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n" +"Last-Translator: bob lebonche , 2021\n" +"Language-Team: French (http://www.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:243 +#: tumblr.php:39 msgid "Permission denied." msgstr "Permission refusée." -#: tumblr.php:296 +#: tumblr.php:69 msgid "Save Settings" msgstr "Sauvegarder les paramètres" -#: tumblr.php:297 +#: tumblr.php:71 msgid "Consumer Key" msgstr "Clé utilisateur" -#: tumblr.php:298 +#: tumblr.php:72 msgid "Consumer Secret" msgstr "Secret utilisateur" -#: tumblr.php:299 -msgid "Maximum tags" -msgstr "Tags maximum" +#: tumblr.php:177 +msgid "You are now authenticated to tumblr." +msgstr "Vous êtes maintenant identifié sur Tumblr" -#: 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:178 +msgid "return to the connector page" +msgstr "Revenir à la page de connexion" -#: tumblr.php:336 +#: tumblr.php:194 +msgid "Post to Tumblr" +msgstr "Publier vers Tumblr" + +#: tumblr.php:225 msgid "Post to page:" msgstr "Publier sur la page :" -#: tumblr.php:342 +#: tumblr.php:231 msgid "(Re-)Authenticate your tumblr page" msgstr "(re)Authentifiez votre page Tumblr" -#: tumblr.php:343 +#: tumblr.php:232 msgid "You are not authenticated to tumblr" msgstr "Vous n'êtes pas identifié sur Tumblr" -#: tumblr.php:348 +#: tumblr.php:237 msgid "Enable Tumblr Post Addon" msgstr "Activez l'extension de publication Tumblr" -#: tumblr.php:349 +#: tumblr.php:238 msgid "Post to Tumblr by default" msgstr "Publier sur Tumblr par défaut" -#: 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" +#: tumblr.php:244 +msgid "Tumblr Export" +msgstr "Exporter vers Tumblr" diff --git a/tumblr/lang/fr/strings.php b/tumblr/lang/fr/strings.php index ece76c74..b3e0ec77 100644 --- a/tumblr/lang/fr/strings.php +++ b/tumblr/lang/fr/strings.php @@ -9,15 +9,12 @@ $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['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['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['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['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'; +$a->strings['Tumblr Export'] = 'Exporter vers Tumblr'; diff --git a/tumblr/lang/hu/messages.po b/tumblr/lang/hu/messages.po index 3c8eb396..c3920576 100644 --- a/tumblr/lang/hu/messages.po +++ b/tumblr/lang/hu/messages.po @@ -4,86 +4,69 @@ # # # Translators: -# Balázs Úr, 2020-2021,2023 +# Balázs Úr, 2020-2021 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-04-29 06:56+0000\n" +"POT-Creation-Date: 2021-11-21 19:17-0500\n" "PO-Revision-Date: 2014-06-23 12:58+0000\n" -"Last-Translator: Balázs Úr, 2020-2021,2023\n" -"Language-Team: Hungarian (http://app.transifex.com/Friendica/friendica/language/hu/)\n" +"Last-Translator: Balázs Úr, 2020-2021\n" +"Language-Team: Hungarian (http://www.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" -#: tumblr.php:243 +#: tumblr.php:39 msgid "Permission denied." msgstr "Engedély megtagadva." -#: tumblr.php:296 +#: tumblr.php:69 msgid "Save Settings" msgstr "Beállítások mentése" -#: tumblr.php:297 +#: tumblr.php:71 msgid "Consumer Key" msgstr "Felhasználói kulcs" -#: tumblr.php:298 +#: tumblr.php:72 msgid "Consumer Secret" msgstr "Felhasználói titok" -#: tumblr.php:299 -msgid "Maximum tags" -msgstr "Legtöbb címke" +#: tumblr.php:177 +msgid "You are now authenticated to tumblr." +msgstr "Most már hitelesítve van a Tumblr-hez." -#: tumblr.php:299 -msgid "" -"Maximum number of tags that a user can follow. Enter 0 to deactivate the " -"feature." -msgstr "A címkék legnagyobb száma, amit egy felhasználó követhet. Adjon meg 0 értéket a funkció kikapcsolásához." +#: tumblr.php:178 +msgid "return to the connector page" +msgstr "visszatérés a csatlakozó oldalára" -#: tumblr.php:336 +#: tumblr.php:194 +msgid "Post to Tumblr" +msgstr "Beküldése a Tumblr-re" + +#: tumblr.php:225 msgid "Post to page:" msgstr "Beküldés az oldalra:" -#: tumblr.php:342 +#: tumblr.php:231 msgid "(Re-)Authenticate your tumblr page" msgstr "A Tumblr-oldal (újra)hitelesítése" -#: tumblr.php:343 +#: tumblr.php:232 msgid "You are not authenticated to tumblr" msgstr "Nincs hitelesítve van a Tumblr-hez" -#: tumblr.php:348 +#: tumblr.php:237 msgid "Enable Tumblr Post Addon" msgstr "A Tumblr-beküldő bővítmény engedélyezése" -#: tumblr.php:349 +#: tumblr.php:238 msgid "Post to Tumblr by default" msgstr "Beküldés a Tumblr-re alapértelmezetten" -#: tumblr.php:350 -msgid "Import the remote timeline" -msgstr "A távoli idővonal importálása" - -#: tumblr.php:351 -msgid "Subscribed tags" -msgstr "Feliratkozott címkék" - -#: tumblr.php:351 -#, php-format -msgid "" -"Comma separated list of up to %d tags that will be imported additionally to " -"the timeline" -msgstr "Legfeljebb %d címke vesszővel elválasztott listája, amelyek szintén importálásra kerülnek az idővonalon felül" - -#: tumblr.php:357 -msgid "Tumblr Import/Export" -msgstr "Tumblr importálás és exportálás" - -#: tumblr.php:375 -msgid "Post to Tumblr" -msgstr "Beküldése a Tumblr-re" +#: tumblr.php:244 +msgid "Tumblr Export" +msgstr "Tumblr exportálás" diff --git a/tumblr/lang/hu/strings.php b/tumblr/lang/hu/strings.php index a3838b4a..cd3e3e19 100644 --- a/tumblr/lang/hu/strings.php +++ b/tumblr/lang/hu/strings.php @@ -9,15 +9,12 @@ $a->strings['Permission denied.'] = 'Engedély megtagadva.'; $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['Maximum tags'] = 'Legtöbb címke'; -$a->strings['Maximum number of tags that a user can follow. Enter 0 to deactivate the feature.'] = 'A címkék legnagyobb száma, amit egy felhasználó követhet. Adjon meg 0 értéket a funkció kikapcsolásához.'; +$a->strings['You are now authenticated to tumblr.'] = 'Most már hitelesítve van a Tumblr-hez.'; +$a->strings['return to the connector page'] = 'visszatérés a csatlakozó oldalára'; +$a->strings['Post to Tumblr'] = 'Beküldése a Tumblr-re'; $a->strings['Post to page:'] = 'Beküldés az oldalra:'; $a->strings['(Re-)Authenticate your tumblr page'] = 'A Tumblr-oldal (újra)hitelesítése'; $a->strings['You are not authenticated to tumblr'] = 'Nincs hitelesítve van a Tumblr-hez'; $a->strings['Enable Tumblr Post Addon'] = 'A Tumblr-beküldő bővítmény engedélyezése'; $a->strings['Post to Tumblr by default'] = 'Beküldés a Tumblr-re alapértelmezetten'; -$a->strings['Import the remote timeline'] = 'A távoli idővonal importálása'; -$a->strings['Subscribed tags'] = 'Feliratkozott címkék'; -$a->strings['Comma separated list of up to %d tags that will be imported additionally to the timeline'] = 'Legfeljebb %d címke vesszővel elválasztott listája, amelyek szintén importálásra kerülnek az idővonalon felül'; -$a->strings['Tumblr Import/Export'] = 'Tumblr importálás és exportálás'; -$a->strings['Post to Tumblr'] = 'Beküldése a Tumblr-re'; +$a->strings['Tumblr Export'] = 'Tumblr exportálás'; diff --git a/tumblr/lang/it/messages.po b/tumblr/lang/it/messages.po index f3d1df55..fbd17655 100644 --- a/tumblr/lang/it/messages.po +++ b/tumblr/lang/it/messages.po @@ -5,69 +5,60 @@ # # Translators: # fabrixxm , 2014-2015,2018 -# Sylke Vicious , 2021 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:17-0500\n" -"PO-Revision-Date: 2014-06-23 12:58+0000\n" -"Last-Translator: Sylke Vicious , 2021\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"POT-Creation-Date: 2013-02-27 05:01-0500\n" +"PO-Revision-Date: 2018-03-19 13:25+0000\n" +"Last-Translator: fabrixxm \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: tumblr.php:39 +#: tumblr.php:34 msgid "Permission denied." msgstr "Permesso negato." -#: tumblr.php:69 -msgid "Save Settings" -msgstr "Salva Impostazioni" - -#: tumblr.php:71 -msgid "Consumer Key" -msgstr "Consumer Key" - -#: tumblr.php:72 -msgid "Consumer Secret" -msgstr "Consumer Secret" - -#: tumblr.php:177 +#: tumblr.php:144 msgid "You are now authenticated to tumblr." msgstr "Sei autenticato su Tumblr." -#: tumblr.php:178 +#: tumblr.php:145 msgid "return to the connector page" msgstr "ritorna alla pagina del connettore" -#: tumblr.php:194 +#: tumblr.php:158 msgid "Post to Tumblr" msgstr "Invia a Tumblr" -#: tumblr.php:225 -msgid "Post to page:" -msgstr "Invia alla pagina:" +#: tumblr.php:185 +msgid "Tumblr Post Settings" +msgstr "Impostazioni di invio a Tumblr" -#: tumblr.php:231 +#: tumblr.php:188 msgid "(Re-)Authenticate your tumblr page" msgstr "(Ri)Autenticati con la tua pagina Tumblr" -#: tumblr.php:232 -msgid "You are not authenticated to tumblr" -msgstr "Non sei autenticato su Tumblr" - -#: tumblr.php:237 +#: tumblr.php:192 msgid "Enable Tumblr Post Addon" msgstr "Abilita componente aggiuntivo di invio a Tumblr" -#: tumblr.php:238 +#: tumblr.php:197 msgid "Post to Tumblr by default" msgstr "Invia sempre a Tumblr" -#: tumblr.php:244 -msgid "Tumblr Export" -msgstr "Esporta Tumblr" +#: tumblr.php:217 +msgid "Post to page:" +msgstr "Invia alla pagina:" + +#: tumblr.php:228 +msgid "You are not authenticated to tumblr" +msgstr "Non sei autenticato su Tumblr" + +#: tumblr.php:233 +msgid "Submit" +msgstr "Invia" diff --git a/tumblr/lang/it/strings.php b/tumblr/lang/it/strings.php index d4d4e257..d5075e65 100644 --- a/tumblr/lang/it/strings.php +++ b/tumblr/lang/it/strings.php @@ -3,18 +3,16 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $a->strings['Permission denied.'] = 'Permesso negato.'; -$a->strings['Save Settings'] = 'Salva Impostazioni'; -$a->strings['Consumer Key'] = 'Consumer Key'; -$a->strings['Consumer Secret'] = 'Consumer Secret'; $a->strings['You are now authenticated to tumblr.'] = 'Sei autenticato su Tumblr.'; $a->strings['return to the connector page'] = 'ritorna alla pagina del connettore'; $a->strings['Post to Tumblr'] = 'Invia a Tumblr'; -$a->strings['Post to page:'] = 'Invia alla pagina:'; +$a->strings['Tumblr Post Settings'] = 'Impostazioni di invio a Tumblr'; $a->strings['(Re-)Authenticate your tumblr page'] = '(Ri)Autenticati con la tua pagina Tumblr'; -$a->strings['You are not authenticated to tumblr'] = 'Non sei autenticato su Tumblr'; $a->strings['Enable Tumblr Post Addon'] = 'Abilita componente aggiuntivo di invio a Tumblr'; $a->strings['Post to Tumblr by default'] = 'Invia sempre a Tumblr'; -$a->strings['Tumblr Export'] = 'Esporta Tumblr'; +$a->strings['Post to page:'] = 'Invia alla pagina:'; +$a->strings['You are not authenticated to tumblr'] = 'Non sei autenticato su Tumblr'; +$a->strings['Submit'] = 'Invia'; diff --git a/tumblr/lang/nl/messages.po b/tumblr/lang/nl/messages.po index ae8e284c..f299c6f3 100644 --- a/tumblr/lang/nl/messages.po +++ b/tumblr/lang/nl/messages.po @@ -9,81 +9,56 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \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" +"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" "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:243 +#: tumblr.php:34 msgid "Permission denied." msgstr "Toegang geweigerd." -#: tumblr.php:296 -msgid "Save Settings" +#: 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" msgstr "" -#: tumblr.php:297 -msgid "Consumer Key" +#: tumblr.php:158 +msgid "Post to Tumblr" msgstr "" -#: tumblr.php:298 -msgid "Consumer Secret" +#: tumblr.php:185 +msgid "Tumblr Post Settings" msgstr "" -#: tumblr.php:299 -msgid "Maximum tags" -msgstr "" - -#: tumblr.php:299 -msgid "" -"Maximum number of tags that a user can follow. Enter 0 to deactivate the " -"feature." -msgstr "" - -#: tumblr.php:336 -msgid "Post to page:" -msgstr "Plaats op pagina:" - -#: tumblr.php:342 +#: tumblr.php:188 msgid "(Re-)Authenticate your tumblr page" msgstr "" -#: tumblr.php:343 -msgid "You are not authenticated to tumblr" -msgstr "" - -#: tumblr.php:348 +#: tumblr.php:192 msgid "Enable Tumblr Post Addon" msgstr "Tumblr Post Addon inschakelen" -#: tumblr.php:349 +#: tumblr.php:197 msgid "Post to Tumblr by default" msgstr "Plaatsen op Tumblr als standaard instellen " -#: tumblr.php:350 -msgid "Import the remote timeline" +#: tumblr.php:217 +msgid "Post to page:" +msgstr "Plaats op pagina:" + +#: tumblr.php:228 +msgid "You are not authenticated to tumblr" 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" +#: tumblr.php:233 +msgid "Submit" msgstr "" diff --git a/tumblr/lang/nl/strings.php b/tumblr/lang/nl/strings.php index 0c70f7f3..9f7f2828 100644 --- a/tumblr/lang/nl/strings.php +++ b/tumblr/lang/nl/strings.php @@ -6,6 +6,7 @@ function string_plural_select_nl($n){ return intval($n != 1); }} $a->strings['Permission denied.'] = 'Toegang geweigerd.'; -$a->strings['Post to page:'] = 'Plaats op pagina:'; +$a->strings['You are now authenticated to tumblr.'] = 'Je bent nu aangemeld bij tumblr'; $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/tumblr/library/tumblroauth.php b/tumblr/library/tumblroauth.php new file mode 100644 index 00000000..418f4c86 --- /dev/null +++ b/tumblr/library/tumblroauth.php @@ -0,0 +1,317 @@ +sha1_method = new OAuthSignatureMethod_HMAC_SHA1(); + $this->consumer = new OAuthConsumer($consumer_key, $consumer_secret); + if (!empty($oauth_token) && !empty($oauth_token_secret)) { + $this->token = new OAuthToken($oauth_token, $oauth_token_secret); + } else { + $this->token = null; + } + } + + /** + * Get a request_token from Tumblr + * + * @param callback $oauth_callback + * @return array + */ + function getRequestToken($oauth_callback = null) + { + $parameters = []; + if (!empty($oauth_callback)) { + $parameters['oauth_callback'] = $oauth_callback; + } + + $request = $this->oAuthRequest($this->requestTokenURL(), 'GET', $parameters); + $token = OAuthUtil::parse_parameters($request); + $this->token = new OAuthToken($token['oauth_token'], $token['oauth_token_secret']); + return $token; + } + + /** + * Get the authorize URL + * + * @param array $token + * @param bool $sign_in_with_tumblr + * @return string + */ + function getAuthorizeURL($token, $sign_in_with_tumblr = TRUE) + { + if (is_array($token)) { + $token = $token['oauth_token']; + } + + if (empty($sign_in_with_tumblr)) { + return $this->authorizeURL() . "?oauth_token={$token}"; + } else { + return $this->authenticateURL() . "?oauth_token={$token}"; + } + } + + /** + * Exchange request token and secret for an access token and + * secret, to sign API calls. + * + * @param bool $oauth_verifier + * @return array ("oauth_token" => "the-access-token", + * "oauth_token_secret" => "the-access-secret", + * "user_id" => "9436992", + * "screen_name" => "abraham") + */ + function getAccessToken($oauth_verifier = FALSE) + { + $parameters = []; + if (!empty($oauth_verifier)) { + $parameters['oauth_verifier'] = $oauth_verifier; + } + + $request = $this->oAuthRequest($this->accessTokenURL(), 'GET', $parameters); + $token = OAuthUtil::parse_parameters($request); + $this->token = new OAuthToken($token['oauth_token'], $token['oauth_token_secret']); + + return $token; + } + + /** + * One time exchange of username and password for access token and secret. + * + * @param string $username + * @param string $password + * @return array ("oauth_token" => "the-access-token", + * "oauth_token_secret" => "the-access-secret", + * "user_id" => "9436992", + * "screen_name" => "abraham", + * "x_auth_expires" => "0") + */ + function getXAuthToken($username, $password) + { + $parameters = []; + $parameters['x_auth_username'] = $username; + $parameters['x_auth_password'] = $password; + $parameters['x_auth_mode'] = 'client_auth'; + $request = $this->oAuthRequest($this->accessTokenURL(), 'POST', $parameters); + $token = OAuthUtil::parse_parameters($request); + $this->token = new OAuthToken($token['oauth_token'], $token['oauth_token_secret']); + + return $token; + } + + /** + * GET wrapper for oAuthRequest. + * + * @param string $url + * @param array $parameters + * @return mixed|string + */ + function get($url, $parameters = []) + { + $response = $this->oAuthRequest($url, 'GET', $parameters); + if ($this->format === 'json' && $this->decode_json) { + return json_decode($response); + } + + return $response; + } + + /** + * POST wrapper for oAuthRequest. + * + * @param string $url + * @param array $parameters + * @return mixed|string + */ + function post($url, $parameters = []) + { + $response = $this->oAuthRequest($url, 'POST', $parameters); + if ($this->format === 'json' && $this->decode_json) { + return json_decode($response); + } + + return $response; + } + + /** + * DELETE wrapper for oAuthReqeust. + * + * @param string $url + * @param array $parameters + * @return mixed|string + */ + function delete($url, $parameters = []) + { + $response = $this->oAuthRequest($url, 'DELETE', $parameters); + if ($this->format === 'json' && $this->decode_json) { + return json_decode($response); + } + + return $response; + } + + /** + * Format and sign an OAuth / API request + * + * @param string $url + * @param string $method + * @param array $parameters + * @return mixed|string + */ + function oAuthRequest($url, $method, $parameters) + { + if (strrpos($url, 'https://') !== 0 && strrpos($url, 'http://') !== 0) { + $url = "{$this->host}{$url}"; + } + + $request = OAuthRequest::from_consumer_and_token($this->consumer, $method, $url, $parameters, $this->token); + $request->sign_request($this->sha1_method, $this->consumer, $this->token); + switch ($method) { + case 'GET': + return $this->http($request->to_url(), 'GET'); + default: + return $this->http($request->get_normalized_http_url(), $method, $request->to_postdata()); + } + } + + /** + * Make an HTTP request + * + * @param string $url + * @param string $method + * @param mixed $postfields + * @return string API results + */ + function http($url, $method, $postfields = null) + { + $this->http_info = []; + $ci = curl_init(); + /* Curl settings */ + curl_setopt($ci, CURLOPT_USERAGENT, $this->useragent); + curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, $this->connecttimeout); + curl_setopt($ci, CURLOPT_TIMEOUT, $this->timeout); + curl_setopt($ci, CURLOPT_RETURNTRANSFER, TRUE); + curl_setopt($ci, CURLOPT_HTTPHEADER, array('Expect:')); + curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, $this->ssl_verifypeer); + curl_setopt($ci, CURLOPT_HEADERFUNCTION, array($this, 'getHeader')); + curl_setopt($ci, CURLOPT_HEADER, FALSE); + + switch ($method) { + case 'POST': + curl_setopt($ci, CURLOPT_POST, TRUE); + if (!empty($postfields)) { + curl_setopt($ci, CURLOPT_POSTFIELDS, $postfields); + } + break; + case 'DELETE': + curl_setopt($ci, CURLOPT_CUSTOMREQUEST, 'DELETE'); + if (!empty($postfields)) { + $url = "{$url}?{$postfields}"; + } + } + + curl_setopt($ci, CURLOPT_URL, $url); + $response = curl_exec($ci); + $this->http_code = curl_getinfo($ci, CURLINFO_HTTP_CODE); + $this->http_info = array_merge($this->http_info, curl_getinfo($ci)); + $this->url = $url; + curl_close($ci); + + return $response; + } + + /** + * Get the header info to store. + * + * @param resource $ch + * @param string $header + * @return int + */ + function getHeader($ch, $header) + { + $i = strpos($header, ':'); + if (!empty($i)) { + $key = str_replace('-', '_', strtolower(substr($header, 0, $i))); + $value = trim(substr($header, $i + 2)); + $this->http_header[$key] = $value; + } + + return strlen($header); + } +} diff --git a/tumblr/templates/admin.tpl b/tumblr/templates/admin.tpl index f38844a2..b361f182 100644 --- a/tumblr/templates/admin.tpl +++ b/tumblr/templates/admin.tpl @@ -1,4 +1,3 @@ {{include file="field_input.tpl" field=$consumer_key}} {{include file="field_input.tpl" field=$consumer_secret}} -{{include file="field_input.tpl" field=$max_tags}}
diff --git a/tumblr/templates/connector_settings.tpl b/tumblr/templates/connector_settings.tpl index 435059e6..d28fab9d 100644 --- a/tumblr/templates/connector_settings.tpl +++ b/tumblr/templates/connector_settings.tpl @@ -2,8 +2,6 @@ {{include file="field_checkbox.tpl" field=$enable}} {{include file="field_checkbox.tpl" field=$bydefault}} -{{include file="field_checkbox.tpl" field=$import}} -{{include file="field_input.tpl" field=$tags}} {{if $page_select}} {{include file="field_select.tpl" field=$page_select}} diff --git a/tumblr/tumblr.php b/tumblr/tumblr.php index 4d5368b8..6cf47fbe 100644 --- a/tumblr/tumblr.php +++ b/tumblr/tumblr.php @@ -7,230 +7,26 @@ * Author: Michael Vogel */ -use Friendica\Content\PageInfo; +require_once __DIR__ . DIRECTORY_SEPARATOR . 'library' . DIRECTORY_SEPARATOR . 'tumblroauth.php'; + +use Friendica\App; use Friendica\Content\Text\BBCode; -use Friendica\Content\Text\HTML; -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; -use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\DI; -use Friendica\Model\Contact; -use Friendica\Model\Item; -use Friendica\Model\Photo; use Friendica\Model\Post; use Friendica\Model\Tag; -use Friendica\Network\HTTPClient\Capability\ICanHandleHttpResponses; -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; -use GuzzleHttp\HandlerStack; -use GuzzleHttp\Subscriber\Oauth\Oauth1; - -define('TUMBLR_DEFAULT_POLL_INTERVAL', 10); // given in minutes -define('TUMBLR_DEFAULT_MAXIMUM_TAGS', 10); function tumblr_install() { - Hook::register('load_config', __FILE__, 'tumblr_load_config'); - Hook::register('hook_fork', __FILE__, 'tumblr_hook_fork'); - Hook::register('post_local', __FILE__, 'tumblr_post_local'); - Hook::register('notifier_normal', __FILE__, 'tumblr_send'); - Hook::register('jot_networks', __FILE__, 'tumblr_jot_nets'); - Hook::register('connector_settings', __FILE__, 'tumblr_settings'); - Hook::register('connector_settings_post', __FILE__, 'tumblr_settings_post'); - Hook::register('cron', __FILE__, 'tumblr_cron'); - Hook::register('support_follow', __FILE__, 'tumblr_support_follow'); - Hook::register('support_probe', __FILE__, 'tumblr_support_probe'); - Hook::register('follow', __FILE__, 'tumblr_follow'); - Hook::register('unfollow', __FILE__, 'tumblr_unfollow'); - Hook::register('block', __FILE__, 'tumblr_block'); - Hook::register('unblock', __FILE__, 'tumblr_unblock'); - 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'); -} - -function tumblr_load_config(ConfigFileManager $loader) -{ - DI::app()->getConfigCache()->load($loader->loadAddonConfig('tumblr'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); -} - -function tumblr_check_item_notification(array &$notification_data) -{ - if (!tumblr_enabled_for_user($notification_data['uid'])) { - return; - } - - $page = tumblr_get_page($notification_data['uid']); - if (empty($page)) { - return; - } - - $own_user = Contact::selectFirst(['url', 'alias'], ['network' => Protocol::TUMBLR, 'uid' => [0, $notification_data['uid']], 'poll' => 'tumblr::' . $page]); - if ($own_user) { - $notification_data['profiles'][] = $own_user['url']; - $notification_data['profiles'][] = $own_user['alias']; - } -} - -function tumblr_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::TUMBLR])) { - return; - } - - $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'])) { - $hookData['result'] = []; - } -} - -function tumblr_item_by_link(array &$hookData) -{ - // Don't overwrite an existing result - if (isset($hookData['item_id'])) { - return; - } - - if (!tumblr_enabled_for_user($hookData['uid'])) { - return; - } - - if (!preg_match('#^https?://www\.tumblr.com/blog/view/(.+)/(\d+).*#', $hookData['uri'], $matches) && !preg_match('#^https?://www\.tumblr.com/(.+)/(\d+).*#', $hookData['uri'], $matches)) { - return; - } - - 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]]); - return []; - } - - 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); - } -} - -function tumblr_support_follow(array &$data) -{ - if ($data['protocol'] == Protocol::TUMBLR) { - $data['result'] = true; - } -} - -function tumblr_support_probe(array &$data) -{ - if ($data['protocol'] == Protocol::TUMBLR) { - $data['result'] = true; - } -} - -function tumblr_follow(array &$hook_data) -{ - $uid = DI::userSession()->getLocalUserId(); - - if (!tumblr_enabled_for_user($uid)) { - return; - } - - 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']]); - 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']]); - } else { - Logger::notice('Following failed', ['meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'url' => $fields['url']]); - } -} - -function tumblr_unfollow(array &$hook_data) -{ - if (!tumblr_enabled_for_user($hook_data['uid'])) { - return; - } - - if (!tumblr_get_contact_uuid($hook_data['contact'])) { - return; - } - $result = tumblr_post($hook_data['uid'], 'user/unfollow', ['url' => $hook_data['contact']['url']]); - $hook_data['result'] = ($result->meta->status <= 399); -} - -function tumblr_block(array &$hook_data) -{ - if (!tumblr_enabled_for_user($hook_data['uid'])) { - return; - } - - $uuid = tumblr_get_contact_uuid($hook_data['contact']); - if (!$uuid) { - return; - } - - $result = tumblr_post($hook_data['uid'], 'blog/' . tumblr_get_page($hook_data['uid']) . '/blocks', ['blocked_tumblelog' => $uuid]); - $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']); - } - } -} - -function tumblr_unblock(array &$hook_data) -{ - if (!tumblr_enabled_for_user($hook_data['uid'])) { - return; - } - - $uuid = tumblr_get_contact_uuid($hook_data['contact']); - if (!$uuid) { - return; - } - - $result = tumblr_delete($hook_data['uid'], 'blog/' . tumblr_get_page($hook_data['uid']) . '/blocks', ['blocked_tumblelog' => $uuid]); - $hook_data['result'] = ($result->meta->status <= 399); -} - -function tumblr_get_contact_uuid(array $contact): string -{ - if (($contact['network'] != Protocol::TUMBLR) || (substr($contact['poll'], 0, 8) != 'tumblr::')) { - return ''; - } - return substr($contact['poll'], 8); + Hook::register('hook_fork', 'addon/tumblr/tumblr.php', 'tumblr_hook_fork'); + Hook::register('post_local', 'addon/tumblr/tumblr.php', 'tumblr_post_local'); + Hook::register('notifier_normal', 'addon/tumblr/tumblr.php', 'tumblr_send'); + Hook::register('jot_networks', 'addon/tumblr/tumblr.php', 'tumblr_jot_nets'); + Hook::register('connector_settings', 'addon/tumblr/tumblr.php', 'tumblr_settings'); + Hook::register('connector_settings_post', 'addon/tumblr/tumblr.php', 'tumblr_settings_post'); } /** @@ -238,70 +34,45 @@ 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() { if (!DI::userSession()->getLocalUserId()) { DI::sysmsg()->addNotice(DI::l10n()->t('Permission denied.')); - return; + return ''; } - switch (DI::args()->getArgv()[1] ?? '') { - case 'connect': - tumblr_connect(); - break; + if (isset(DI::args()->getArgv()[1])) { + switch (DI::args()->getArgv()[1]) { + case "connect": + $o = tumblr_connect(); + break; - case 'redirect': - tumblr_redirect(); - break; - } - DI::baseUrl()->redirect('settings/connectors/tumblr'); -} + case "callback": + $o = tumblr_callback(); + break; -function tumblr_redirect() -{ - if (($_REQUEST['state'] ?? '') != DI::session()->get('oauth_state')) { - return; + default: + $o = print_r(DI::args()->getArgv(), true); + break; + } + } else { + $o = tumblr_connect(); } - tumblr_get_token(DI::userSession()->getLocalUserId(), $_REQUEST['code'] ?? ''); -} - -function tumblr_connect() -{ - // Define the needed keys - $consumer_key = DI::config()->get('tumblr', 'consumer_key'); - $consumer_secret = DI::config()->get('tumblr', 'consumer_secret'); - - if (empty($consumer_key) || empty($consumer_secret)) { - return; - } - - $state = base64_encode(random_bytes(20)); - DI::session()->set('oauth_state', $state); - - $parameters = [ - 'client_id' => $consumer_key, - 'response_type' => 'code', - 'scope' => 'basic write offline_access', - 'state' => $state - ]; - - System::externalRedirect('https://www.tumblr.com/oauth2/authorize?' . http_build_query($parameters)); + return $o; } function tumblr_addon_admin(string &$o) { - $t = Renderer::getMarkupTemplate('admin.tpl', 'addon/tumblr/'); + $t = Renderer::getMarkupTemplate( "admin.tpl", "addon/tumblr/" ); $o = Renderer::replaceMacros($t, [ '$submit' => DI::l10n()->t('Save Settings'), - '$consumer_key' => ['consumer_key', DI::l10n()->t('Consumer Key'), DI::config()->get('tumblr', 'consumer_key'), ''], - '$consumer_secret' => ['consumer_secret', DI::l10n()->t('Consumer Secret'), DI::config()->get('tumblr', 'consumer_secret'), ''], - '$max_tags' => ['max_tags', DI::l10n()->t('Maximum tags'), DI::config()->get('tumblr', 'max_tags') ?? TUMBLR_DEFAULT_MAXIMUM_TAGS, DI::l10n()->t('Maximum number of tags that a user can follow. Enter 0 to deactivate the feature.')], + // name, label, value, help, [extra values] + '$consumer_key' => ['consumer_key', DI::l10n()->t('Consumer Key'), DI::config()->get('tumblr', 'consumer_key' ), ''], + '$consumer_secret' => ['consumer_secret', DI::l10n()->t('Consumer Secret'), DI::config()->get('tumblr', 'consumer_secret' ), ''], ]); } @@ -309,7 +80,122 @@ function tumblr_addon_admin_post() { DI::config()->set('tumblr', 'consumer_key', trim($_POST['consumer_key'] ?? '')); DI::config()->set('tumblr', 'consumer_secret', trim($_POST['consumer_secret'] ?? '')); - DI::config()->set('tumblr', 'max_tags', max(0, intval($_POST['max_tags'] ?? ''))); +} + +function tumblr_connect() +{ + // Start a session. This is necessary to hold on to a few keys the callback script will also need + session_start(); + + // Include the TumblrOAuth library + //require_once('addon/tumblr/tumblroauth/tumblroauth.php'); + + // Define the needed keys + $consumer_key = DI::config()->get('tumblr', 'consumer_key'); + $consumer_secret = DI::config()->get('tumblr', 'consumer_secret'); + + // The callback URL is the script that gets called after the user authenticates with tumblr + // In this example, it would be the included callback.php + $callback_url = DI::baseUrl()->get() . '/tumblr/callback'; + + // Let's begin. First we need a Request Token. The request token is required to send the user + // to Tumblr's login page. + + // Create a new instance of the TumblrOAuth library. For this step, all we need to give the library is our + // Consumer Key and Consumer Secret + $tum_oauth = new TumblrOAuth($consumer_key, $consumer_secret); + + // Ask Tumblr for a Request Token. Specify the Callback URL here too (although this should be optional) + $request_token = $tum_oauth->getRequestToken($callback_url); + + // Store the request token and Request Token Secret as out callback.php script will need this + $_SESSION['request_token'] = $token = $request_token['oauth_token']; + $_SESSION['request_token_secret'] = $request_token['oauth_token_secret']; + + // Check the HTTP Code. It should be a 200 (OK), if it's anything else then something didn't work. + switch ($tum_oauth->http_code) { + case 200: + // Ask Tumblr to give us a special address to their login page + $url = $tum_oauth->getAuthorizeURL($token); + + // Redirect the user to the login URL given to us by Tumblr + header('Location: ' . $url); + + /* + * That's it for our side. The user is sent to a Tumblr Login page and + * asked to authroize our app. After that, Tumblr sends the user back to + * our Callback URL (callback.php) along with some information we need to get + * an access token. + */ + break; + + default: + // Give an error message + $o = 'Could not connect to Tumblr. Refresh the page or try again later.'; + } + + return $o; +} + +function tumblr_callback() +{ + // Start a session, load the library + session_start(); + //require_once('addon/tumblr/tumblroauth/tumblroauth.php'); + + // Define the needed keys + $consumer_key = DI::config()->get('tumblr', 'consumer_key'); + $consumer_secret = DI::config()->get('tumblr', 'consumer_secret'); + + // Once the user approves your app at Tumblr, they are sent back to this script. + // This script is passed two parameters in the URL, oauth_token (our Request Token) + // and oauth_verifier (Key that we need to get Access Token). + // We'll also need out Request Token Secret, which we stored in a session. + + // Create instance of TumblrOAuth. + // It'll need our Consumer Key and Secret as well as our Request Token and Secret + $tum_oauth = new TumblrOAuth($consumer_key, $consumer_secret, $_SESSION['request_token'], $_SESSION['request_token_secret']); + + // Ok, let's get an Access Token. We'll need to pass along our oauth_verifier which was given to us in the URL. + $access_token = $tum_oauth->getAccessToken($_REQUEST['oauth_verifier']); + + // We're done with the Request Token and Secret so let's remove those. + unset($_SESSION['request_token']); + unset($_SESSION['request_token_secret']); + + // Make sure nothing went wrong. + if (200 == $tum_oauth->http_code) { + // good to go + } else { + return 'Unable to authenticate'; + } + + // What's next? Now that we have an Access Token and Secret, we can make an API call. + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'tumblr', 'oauth_token', $access_token['oauth_token']); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'tumblr', 'oauth_token_secret', $access_token['oauth_token_secret']); + + $o = DI::l10n()->t("You are now authenticated to tumblr."); + $o .= '
' . DI::l10n()->t("return to the connector page") . ''; + + return $o; +} + +function tumblr_jot_nets(array &$jotnets_fields) +{ + if (!DI::userSession()->getLocalUserId()) { + return; + } + + if (DI::pConfig()->get(DI::userSession()->getLocalUserId(),'tumblr','post')) { + $jotnets_fields[] = [ + 'type' => 'checkbox', + 'field' => [ + 'tumblr_enable', + DI::l10n()->t('Post to Tumblr'), + DI::pConfig()->get(DI::userSession()->getLocalUserId(),'tumblr','post_by_default') + ] + ]; + } } function tumblr_settings(array &$data) @@ -318,27 +204,25 @@ function tumblr_settings(array &$data) return; } - $enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'tumblr', 'post') ?? false; - $def_enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'tumblr', 'post_by_default') ?? false; - $import = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'tumblr', 'import') ?? false; - $tags = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'tumblr', 'tags') ?? []; + $enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'tumblr', 'post', false); + $def_enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'tumblr', 'post_by_default', false); - $max_tags = DI::config()->get('tumblr', 'max_tags') ?? TUMBLR_DEFAULT_MAXIMUM_TAGS; + $oauth_token = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'tumblr', 'oauth_token'); + $oauth_token_secret = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'tumblr', 'oauth_token_secret'); - $tags_str = implode(', ', $tags); - $cachekey = 'tumblr-blogs-' . DI::userSession()->getLocalUserId(); - $blogs = DI::cache()->get($cachekey); - if (empty($blogs)) { - $blogs = tumblr_get_blogs(DI::userSession()->getLocalUserId()); - if (!empty($blogs)) { - DI::cache()->set($cachekey, $blogs, Duration::HALF_HOUR); - } - } + if ($oauth_token && $oauth_token_secret) { + $page = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'tumblr', 'page'); + $consumer_key = DI::config()->get('tumblr', 'consumer_key'); + $consumer_secret = DI::config()->get('tumblr', 'consumer_secret'); - if (!empty($blogs)) { - $page = tumblr_get_page(DI::userSession()->getLocalUserId(), $blogs); + $tum_oauth = new TumblrOAuth($consumer_key, $consumer_secret, $oauth_token, $oauth_token_secret); + $userinfo = $tum_oauth->get('user/info'); - $page_select = ['tumblr_page', DI::l10n()->t('Post to page:'), $page, '', $blogs]; + $blogs = array_map(function ($blog) { + return substr(str_replace(["http://", "https://"], ["", ""], $blog->url), 0, -1); + }, $userinfo->response->user->blogs); + + $page_select = ['tumblr-page', DI::l10n()->t('Post to page:'), $page, '', $blogs]; } $t = Renderer::getMarkupTemplate('connector_settings.tpl', 'addon/tumblr/'); @@ -348,119 +232,31 @@ function tumblr_settings(array &$data) 'noconnect' => DI::l10n()->t('You are not authenticated to tumblr'), ], - '$authenticate_url' => DI::baseUrl() . '/tumblr/connect', + '$authenticate_url' => DI::baseUrl()->get() . '/tumblr/connect', '$enable' => ['tumblr', DI::l10n()->t('Enable Tumblr Post Addon'), $enabled], '$bydefault' => ['tumblr_bydefault', DI::l10n()->t('Post to Tumblr by default'), $def_enabled], - '$import' => ['tumblr_import', DI::l10n()->t('Import the remote timeline'), $import], - '$tags' => ['tags', DI::l10n()->t('Subscribed tags'), $tags_str, DI::l10n()->t('Comma separated list of up to %d tags that will be imported additionally to the timeline', $max_tags)], '$page_select' => $page_select ?? '', ]); $data = [ 'connector' => 'tumblr', - 'title' => DI::l10n()->t('Tumblr Import/Export'), + 'title' => DI::l10n()->t('Tumblr Export'), 'image' => 'images/tumblr.png', 'enabled' => $enabled, 'html' => $html, ]; } -function tumblr_jot_nets(array &$jotnets_fields) -{ - if (!DI::userSession()->getLocalUserId()) { - return; - } - - if (DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'tumblr', 'post')) { - $jotnets_fields[] = [ - 'type' => 'checkbox', - 'field' => [ - 'tumblr_enable', - DI::l10n()->t('Post to Tumblr'), - DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'tumblr', 'post_by_default') - ] - ]; - } -} - function tumblr_settings_post(array &$b) { if (!empty($_POST['tumblr-submit'])) { DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'tumblr', 'post', intval($_POST['tumblr'])); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'tumblr', 'page', $_POST['tumblr_page']); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'tumblr', 'post_by_default', intval($_POST['tumblr_bydefault'])); - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'tumblr', 'import', intval($_POST['tumblr_import'])); - - $max_tags = DI::config()->get('tumblr', 'max_tags') ?? TUMBLR_DEFAULT_MAXIMUM_TAGS; - $tags = []; - foreach (explode(',', $_POST['tags']) as $tag) { - if (count($tags) < $max_tags) { - $tags[] = trim($tag, ' #'); - } - } - - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'tumblr', 'tags', $tags); } } -function tumblr_cron() -{ - $last = (int)DI::keyValue()->get('tumblr_last_poll'); - - $poll_interval = intval(DI::config()->get('tumblr', 'poll_interval')); - if (!$poll_interval) { - $poll_interval = TUMBLR_DEFAULT_POLL_INTERVAL; - } - - if ($last) { - $next = $last + ($poll_interval * 60); - if ($next > time()) { - Logger::notice('poll interval not reached'); - return; - } - } - Logger::notice('cron_start'); - - $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' => 'tumblr', 'k' => 'import', 'v' => true]); - 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']]); - continue; - } - } - - 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']]); - } - - $last_clean = DI::keyValue()->get('tumblr_last_clean'); - if (empty($last_clean) || ($last_clean + 86400 < time())) { - 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'); - } - - Logger::notice('cron_end'); - - DI::keyValue()->set('tumblr_last_poll', time()); -} - function tumblr_hook_fork(array &$b) { if ($b['name'] != 'notifier_normal') { @@ -469,22 +265,8 @@ function tumblr_hook_fork(array &$b) $post = $b['data']; - // Editing is not supported by the addon - if (($post['created'] !== $post['edited']) && !$post['deleted']) { - DI::logger()->info('Editing is not supported by the addon'); - $b['execute'] = false; - return; - } - - 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])) { - 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']]); + if ($post['deleted'] || $post['private'] || ($post['created'] !== $post['edited']) || + !strstr($post['postopts'] ?? '', 'tumblr') || ($post['parent'] != $post['id'])) { $b['execute'] = false; return; } @@ -492,6 +274,8 @@ function tumblr_hook_fork(array &$b) function tumblr_post_local(array &$b) { + // This can probably be changed to allow editing by pointing to a different API endpoint + if ($b['edit']) { return; } @@ -505,9 +289,9 @@ function tumblr_post_local(array &$b) } $tmbl_post = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'tumblr', 'post')); + $tmbl_enable = (($tmbl_post && !empty($_REQUEST['tumblr_enable'])) ? intval($_REQUEST['tumblr_enable']) : 0); - // if API is used, default to the chosen settings if ($b['api_source'] && intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'tumblr', 'post_by_default'))) { $tmbl_enable = 1; } @@ -523,965 +307,138 @@ function tumblr_post_local(array &$b) $b['postopts'] .= 'tumblr'; } -function tumblr_send(array &$b) -{ - if (($b['created'] !== $b['edited']) && !$b['deleted']) { + + + +function tumblr_send(array &$b) { + + if ($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited'])) { return; } - if ($b['gravity'] != Item::GRAVITY_PARENT) { - Logger::debug('Got comment', ['item' => $b]); + if (! strstr($b['postopts'],'tumblr')) { + return; + } - $parent = tumblr_get_post_from_uri($b['thr-parent']); - if (empty($parent)) { - Logger::notice('No tumblr post', ['thr-parent' => $b['thr-parent']]); - return; + if ($b['parent'] != $b['id']) { + return; + } + + // Dont't post if the post doesn't belong to us. + // This is a check for forum postings + $self = DBA::selectFirst('contact', ['id'], ['uid' => $b['uid'], 'self' => true]); + if ($b['contact-id'] != $self['id']) { + return; + } + + $b['body'] = Post\Media::addAttachmentsToBody($b['uri-id'], DI::contentItem()->addSharedPost($b)); + + $oauth_token = DI::pConfig()->get($b['uid'], "tumblr", "oauth_token"); + $oauth_token_secret = DI::pConfig()->get($b['uid'], "tumblr", "oauth_token_secret"); + $page = DI::pConfig()->get($b['uid'], "tumblr", "page"); + $tmbl_blog = 'blog/' . $page . '/post'; + + if ($oauth_token && $oauth_token_secret && $tmbl_blog) { + $tags = Tag::getByURIId($b['uri-id']); + + $tag_arr = []; + + foreach($tags as $tag) { + $tag_arr[] = $tag['name']; } - Logger::debug('Parent found', ['parent' => $parent]); + if (count($tag_arr)) { + $tags = implode(',', $tag_arr); + } - $page = tumblr_get_page($b['uid']); + $title = trim($b['title']); - if ($b['gravity'] == Item::GRAVITY_COMMENT) { - Logger::notice('Commenting is not supported (yet)'); + $siteinfo = BBCode::getAttachedData($b["body"]); + + $params = [ + 'state' => 'published', + 'tags' => $tags, + 'tweet' => 'off', + 'format' => 'html', + ]; + + if (!isset($siteinfo["type"])) { + $siteinfo["type"] = ""; + } + + if (($title == "") && isset($siteinfo["title"])) { + $title = $siteinfo["title"]; + } + + if (isset($siteinfo["text"])) { + $body = $siteinfo["text"]; } else { - if (($b['verb'] == Activity::LIKE) && !$b['deleted']) { - $params = ['id' => $parent['id'], 'reblog_key' => $parent['reblog_key']]; - $result = tumblr_post($b['uid'], 'user/like', $params); - } elseif (($b['verb'] == Activity::LIKE) && $b['deleted']) { - $params = ['id' => $parent['id'], 'reblog_key' => $parent['reblog_key']]; - $result = tumblr_post($b['uid'], 'user/unlike', $params); - } elseif (($b['verb'] == Activity::ANNOUNCE) && !$b['deleted']) { - $params = ['id' => $parent['id'], 'reblog_key' => $parent['reblog_key']]; - $result = tumblr_post($b['uid'], 'blog/' . $page . '/post/reblog', $params); - } elseif (($b['verb'] == Activity::ANNOUNCE) && $b['deleted']) { - $announce = tumblr_get_post_from_uri($b['extid']); - if (empty($announce)) { - return; + $body = BBCode::removeShareInformation($b["body"]); + } + + switch ($siteinfo["type"]) { + case "photo": + $params['type'] = "photo"; + $params['caption'] = BBCode::convertForUriId($b['uri-id'], $body, BBCode::CONNECTORS);; + + if (isset($siteinfo["url"])) { + $params['link'] = $siteinfo["url"]; } - $params = ['id' => $announce['id']]; - $result = tumblr_post($b['uid'], 'blog/' . $page . '/post/delete', $params); - } else { - // Unsupported activity - return; - } - 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']]); - } - } else { - Logger::notice('Error while performing activity', ['verb' => $b['verb'], 'deleted' => $b['deleted'], 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]); - } - } - return; - } elseif ($b['private'] || !strstr($b['postopts'], 'tumblr')) { - return; - } - - if (!tumblr_send_npf($b)) { - tumblr_send_legacy($b); - } -} - -function tumblr_send_legacy(array $b) -{ - $b['body'] = BBCode::removeAttachment($b['body']); - - $title = trim($b['title']); - - $media = Post\Media::getByURIId($b['uri-id'], [Post\Media::HTML, Post\Media::AUDIO, Post\Media::VIDEO, Post\Media::IMAGE]); - - $photo = array_search(Post\Media::IMAGE, array_column($media, 'type')); - $link = array_search(Post\Media::HTML, array_column($media, 'type')); - $audio = array_search(Post\Media::AUDIO, array_column($media, 'type')); - $video = array_search(Post\Media::VIDEO, array_column($media, 'type')); - - $params = [ - 'state' => 'published', - 'tags' => implode(',', array_column(Tag::getByURIId($b['uri-id']), 'name')), - 'tweet' => 'off', - 'format' => 'html', - ]; - - $body = BBCode::removeShareInformation($b['body']); - $body = Post\Media::removeFromEndOfBody($body); - - if ($photo !== false) { - $params['type'] = 'photo'; - $params['caption'] = BBCode::convertForUriId($b['uri-id'], $body, BBCode::CONNECTORS); - $params['data'] = []; - foreach ($media as $photo) { - if ($photo['type'] == Post\Media::IMAGE) { - if (Network::isLocalLink($photo['url']) && ($data = Photo::getResourceData($photo['url']))) { - $photo = Photo::selectFirst([], ["`resource-id` = ? AND `scale` > ?", $data['guid'], 0]); - if (!empty($photo)) { - $params['data'][] = Photo::getImageDataForPhoto($photo); - } - } - } - } - } elseif ($link !== false) { - $params['type'] = 'link'; - $params['title'] = $media[$link]['name']; - $params['url'] = $media[$link]['url']; - $params['description'] = BBCode::convertForUriId($b['uri-id'], $body, BBCode::CONNECTORS); - - if (!empty($media[$link]['preview'])) { - $params['thumbnail'] = $media[$link]['preview']; - } - if (!empty($media[$link]['description'])) { - $params['excerpt'] = $media[$link]['description']; - } - if (!empty($media[$link]['author-name'])) { - $params['author'] = $media[$link]['author-name']; - } - } elseif ($audio !== false) { - $params['type'] = 'audio'; - $params['external_url'] = $media[$audio]['url']; - $params['caption'] = BBCode::convertForUriId($b['uri-id'], $body, BBCode::CONNECTORS); - } elseif ($video !== false) { - $params['type'] = 'video'; - $params['embed'] = $media[$video]['url']; - $params['caption'] = BBCode::convertForUriId($b['uri-id'], $body, BBCode::CONNECTORS); - } else { - $params['type'] = 'text'; - $params['title'] = $title; - $params['body'] = BBCode::convertForUriId($b['uri-id'], $b['body'], BBCode::CONNECTORS); - } - - if (isset($params['caption']) && (trim($title) != '')) { - $params['caption'] = '

' . $title . '

' . - '

' . $params['caption'] . '

'; - } - - $page = tumblr_get_page($b['uid']); - - $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]); - } else { - Logger::notice('Error posting blog (legacy)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]); - } -} - -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']]); - // "true" is returned, since the legacy function will fail as well. - return true; - } - - $post['body'] = Post\Media::addAttachmentsToBody($post['uri-id'], $post['body']); - if (!empty($post['title'])) { - $post['body'] = '[h1]' . $post['title'] . "[/h1]\n" . $post['body']; - } - - $params = [ - 'content' => NPF::fromBBCode($post['body'], $post['uri-id']), - 'state' => 'published', - 'date' => DateTimeFormat::utc($post['created'], DateTimeFormat::ATOM), - 'tags' => implode(',', array_column(Tag::getByURIId($post['uri-id']), 'name')), - 'is_private' => false, - 'interactability_reblog' => 'everyone' - ]; - - $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]); - return true; - } else { - Logger::notice('Error posting blog (NPF)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]); - return false; - } -} - -function tumblr_get_post_from_uri(string $uri): array -{ - $parts = explode(':', $uri); - if (($parts[0] != 'tumblr') || empty($parts[2])) { - return []; - } - - $post['id'] = $parts[2]; - $post['reblog_key'] = $parts[3] ?? ''; - - $post['reblog_key'] = str_replace('@t', '', $post['reblog_key']); // Temp - return $post; -} - -/** - * Fetch posts for user defined hashtags for the given user - * - * @param int $uid - * @param int $last_poll - * @return void - */ -function tumblr_fetch_tags(int $uid, int $last_poll) -{ - if (!DI::config()->get('tumblr', 'max_tags') ?? TUMBLR_DEFAULT_MAXIMUM_TAGS) { - return; - } - - 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, $last_poll); - 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]); - } - } - } -} - -/** - * Fetch the dashboard (timeline) for the given user - * - * @param int $uid - * @param int $last_poll - * @return void - */ -function tumblr_fetch_dashboard(int $uid, int $last_poll) -{ - $parameters = ['reblog_info' => false, 'notes_info' => false, 'npf' => false]; - - $last = DI::pConfig()->get($uid, 'tumblr', 'last_id'); - if (!empty($last)) { - $parameters['since_id'] = $last; - } - - $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]); - return []; - } - - if (empty($dashboard->response->posts)) { - return; - } - - foreach (array_reverse($dashboard->response->posts) as $post) { - if ($post->id > $last) { - $last = $post->id; - } - - 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); - - DI::pConfig()->set($uid, 'tumblr', 'last_id', $last); - } -} - -function tumblr_process_post(stdClass $post, int $uid, int $post_reason, int $last_poll = 0): int -{ - $uri = 'tumblr::' . $post->id_string . ':' . $post->reblog_key; - - if (Post::exists(['uri' => $uri, 'uid' => $uid]) || ($post->blog->uuid == tumblr_get_page($uid))) { - return 0; - } - - $item = tumblr_get_header($post, $uri, $uid); - - $item = tumblr_get_content($item, $post); - - $item['post-reason'] = $post_reason; - - if (!empty($post->followed)) { - $item['post-reason'] = Item::PR_FOLLOWER; - } - - 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]); - - if (!empty($post->tags)) { - foreach ($post->tags as $tag) { - Tag::store($stored['uri-id'], Tag::HASHTAG, $tag); - } - } - } - return $id; -} - -/** - * Sets the initial data for the item array - * - * @param stdClass $post - * @param string $uri - * @param integer $uid - * @return array - */ -function tumblr_get_header(stdClass $post, string $uri, int $uid): array -{ - $contact = tumblr_get_contact($post->blog, $uid); - $item = [ - 'network' => Protocol::TUMBLR, - 'uid' => $uid, - 'wall' => false, - 'uri' => $uri, - 'private' => Item::UNLISTED, - 'verb' => Activity::POST, - 'contact-id' => $contact['id'], - 'author-name' => $contact['name'], - 'author-link' => $contact['url'], - 'author-avatar' => $contact['avatar'], - 'plink' => $post->post_url, - 'created' => date(DateTimeFormat::MYSQL, $post->timestamp) - ]; - - $item['owner-name'] = $item['author-name']; - $item['owner-link'] = $item['author-link']; - $item['owner-avatar'] = $item['author-avatar']; - - return $item; -} - -/** - * Set the body according the given content type - * - * @param array $item - * @param stdClass $post - * @return array - */ -function tumblr_get_content(array $item, stdClass $post): array -{ - switch ($post->type) { - case 'text': - $item['title'] = $post->title; - $item['body'] = HTML::toBBCode(tumblr_add_npf_data($post->body, $post->post_url)); - break; - - case 'quote': - if (empty($post->text)) { - $body = HTML::toBBCode($post->text) . "\n"; - } else { - $body = ''; - } - if (!empty($post->source_title) && !empty($post->source_url)) { - $body .= '[url=' . $post->source_url . ']' . $post->source_title . "[/url]:\n"; - } elseif (!empty($post->source_title)) { - $body .= $post->source_title . ":\n"; - } - $body .= '[quote]' . HTML::toBBCode($post->source) . '[/quote]'; - $item['body'] = $body; - break; - - case 'link': - $item['body'] = HTML::toBBCode($post->description) . "\n" . PageInfo::getFooterFromUrl($post->url); - break; - - case 'answer': - if (!empty($post->asking_name) && !empty($post->asking_url)) { - $body = '[url=' . $post->asking_url . ']' . $post->asking_name . "[/url]:\n"; - } elseif (!empty($post->asking_name)) { - $body = $post->asking_name . ":\n"; - } else { - $body = ''; - } - $body .= '[quote]' . HTML::toBBCode($post->question) . "[/quote]\n" . HTML::toBBCode($post->answer); - $item['body'] = $body; - break; - - case 'video': - $item['body'] = HTML::toBBCode($post->caption); - if (!empty($post->video_url)) { - $item['body'] .= "\n[video]" . $post->video_url . "[/video]\n"; - } elseif (!empty($post->thumbnail_url)) { - $item['body'] .= "\n[url=" . $post->permalink_url . "][img]" . $post->thumbnail_url . "[/img][/url]\n"; - } elseif (!empty($post->permalink_url)) { - $item['body'] .= "\n[url]" . $post->permalink_url . "[/url]\n"; - } elseif (!empty($post->source_url) && !empty($post->source_title)) { - $item['body'] .= "\n[url=" . $post->source_url . "]" . $post->source_title . "[/url]\n"; - } elseif (!empty($post->source_url)) { - $item['body'] .= "\n[url]" . $post->source_url . "[/url]\n"; - } - break; - - case 'audio': - $item['body'] = HTML::toBBCode($post->caption); - if (!empty($post->source_url) && !empty($post->source_title)) { - $item['body'] .= "\n[url=" . $post->source_url . "]" . $post->source_title . "[/url]\n"; - } elseif (!empty($post->source_url)) { - $item['body'] .= "\n[url]" . $post->source_url . "[/url]\n"; - } - break; - - case 'photo': - $item['body'] = HTML::toBBCode($post->caption); - foreach ($post->photos as $photo) { - if (!empty($photo->original_size)) { - $item['body'] .= "\n[img]" . $photo->original_size->url . "[/img]"; - } elseif (!empty($photo->alt_sizes)) { - $item['body'] .= "\n[img]" . $photo->alt_sizes[0]->url . "[/img]"; - } - } - break; - - case 'chat': - $item['title'] = $post->title; - $item['body'] = "\n[ul]"; - foreach ($post->dialogue as $line) { - $item['body'] .= "\n[li]" . $line->label . " " . $line->phrase . "[/li]"; - } - $item['body'] .= "[/ul]\n"; - break; - } - return $item; -} - -function tumblr_add_npf_data(string $html, string $plink): string -{ - $doc = new DOMDocument(); - - $doc->formatOutput = true; - @$doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8')); - $xpath = new DomXPath($doc); - $list = $xpath->query('//p[@class="npf_link"]'); - foreach ($list as $node) { - $data = tumblr_get_npf_data($node); - if (empty($data)) { - continue; - } - - tumblr_replace_with_npf($doc, $node, tumblr_get_type_replacement($data, $plink)); - } - - $list = $xpath->query('//div[@data-npf]'); - foreach ($list as $node) { - $data = tumblr_get_npf_data($node); - if (empty($data)) { - continue; - } - - tumblr_replace_with_npf($doc, $node, tumblr_get_type_replacement($data, $plink)); - } - - $list = $xpath->query('//figure[@data-provider="youtube"]'); - foreach ($list as $node) { - $attributes = tumblr_get_attributes($node); - if (empty($attributes['data-url'])) { - continue; - } - tumblr_replace_with_npf($doc, $node, '[youtube]' . $attributes['data-url'] . '[/youtube]'); - } - - $list = $xpath->query('//figure[@data-npf]'); - foreach ($list as $node) { - $data = tumblr_get_npf_data($node); - if (empty($data)) { - continue; - } - tumblr_replace_with_npf($doc, $node, tumblr_get_type_replacement($data, $plink)); - } - - return $doc->saveHTML(); -} - -function tumblr_replace_with_npf(DOMDocument $doc, DOMNode $node, string $replacement) -{ - if (empty($replacement)) { - return; - } - $replace = $doc->createTextNode($replacement); - $node->parentNode->insertBefore($replace, $node); - $node->parentNode->removeChild($node); -} - -function tumblr_get_npf_data(DOMNode $node): array -{ - $attributes = tumblr_get_attributes($node); - if (empty($attributes['data-npf'])) { - return []; - } - - return json_decode($attributes['data-npf'], true); -} - -function tumblr_get_attributes($node): array -{ - if (empty($node->attributes)) { - return []; - } - - $attributes = []; - foreach ($node->attributes as $key => $attribute) { - $attributes[$key] = trim($attribute->value); - } - return $attributes; -} - -function tumblr_get_type_replacement(array $data, string $plink): string -{ - switch ($data['type']) { - case 'poll': - $body = '[p][url=' . $plink . ']' . $data['question'] . '[/url][/p][ul]'; - foreach ($data['answers'] as $answer) { - $body .= '[li]' . $answer['answer_text'] . '[/li]'; - } - $body .= '[/ul]'; - break; - - case 'link': - $body = PageInfo::getFooterFromUrl(str_replace('https://href.li/?', '', $data['url'])); - break; - - case 'video': - if (!empty($data['url']) && ($data['provider'] == 'tumblr')) { - $body = '[video]' . $data['url'] . '[/video]'; + $params['source'] = $siteinfo["image"]; break; - } - default: - Logger::notice('Unknown type', ['type' => $data['type'], 'data' => $data, 'plink' => $plink]); - $body = ''; - } + case "link": + $params['type'] = "link"; + $params['title'] = $title; + $params['url'] = $siteinfo["url"]; + $params['description'] = BBCode::convertForUriId($b['uri-id'], $body, BBCode::CONNECTORS); + break; - return $body; -} + case "audio": + $params['type'] = "audio"; + $params['external_url'] = $siteinfo["url"]; + $params['caption'] = BBCode::convertForUriId($b['uri-id'], $body, BBCode::CONNECTORS); + break; -/** - * Get a contact array for the given blog - * - * @param stdClass $blog - * @param integer $uid - * @return array - */ -function tumblr_get_contact(stdClass $blog, int $uid): array -{ - $condition = ['network' => Protocol::TUMBLR, 'uid' => 0, 'poll' => 'tumblr::' . $blog->uuid]; - $contact = Contact::selectFirst(['id', 'updated'], $condition); + case "video": + $params['type'] = "video"; + $params['embed'] = $siteinfo["url"]; + $params['caption'] = BBCode::convertForUriId($b['uri-id'], $body, BBCode::CONNECTORS); + break; - $update = empty($contact) || $contact['updated'] < DateTimeFormat::utc('now -24 hours'); - - $public_fields = $fields = tumblr_get_contact_fields($blog, $uid, $update); - - $avatar = $fields['avatar'] ?? ''; - unset($fields['avatar']); - unset($public_fields['avatar']); - - $public_fields['uid'] = 0; - $public_fields['rel'] = Contact::NOTHING; - - if (empty($contact)) { - $cid = Contact::insert($public_fields); - } else { - $cid = $contact['id']; - Contact::update($public_fields, ['id' => $cid], true); - } - - if ($uid != 0) { - $condition = ['network' => Protocol::TUMBLR, 'uid' => $uid, 'poll' => 'tumblr::' . $blog->uuid]; - - $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; + default: + $params['type'] = "text"; + $params['title'] = $title; + $params['body'] = BBCode::convertForUriId($b['uri-id'], $b['body'], BBCode::CONNECTORS); + break; } - } - if (($uid != 0) && ($fields['rel'] != Contact::NOTHING)) { - if (empty($contact)) { - $cid = Contact::insert($fields); + if (isset($params['caption']) && (trim($title) != "")) { + $params['caption'] = '

'.$title."

". + "

".$params['caption']."

"; + } + + if (empty($params['caption']) && !empty($siteinfo["description"])) { + $params['caption'] = BBCode::convertForUriId($b['uri-id'], "[quote]" . $siteinfo["description"] . "[/quote]", BBCode::CONNECTORS); + } + + $consumer_key = DI::config()->get('tumblr','consumer_key'); + $consumer_secret = DI::config()->get('tumblr','consumer_secret'); + + $tum_oauth = new TumblrOAuth($consumer_key, $consumer_secret, $oauth_token, $oauth_token_secret); + + // Make an API call with the TumblrOAuth instance. + $x = $tum_oauth->post($tmbl_blog,$params); + $ret_code = $tum_oauth->http_code; + + //print_r($params); + if ($ret_code == 201) { + Logger::notice('tumblr_send: success'); + } elseif ($ret_code == 403) { + Logger::notice('tumblr_send: authentication failure'); } else { - $cid = $contact['id']; - Contact::update($fields, ['id' => $cid], true); + Logger::notice('tumblr_send: general error', ['error' => $x]); } - 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($avatar)) { - Contact::updateAvatar($cid, $avatar); - } - - return Contact::getById($cid); -} - -function tumblr_get_contact_fields(stdClass $blog, int $uid, bool $update): array -{ - $baseurl = 'https://tumblr.com'; - $url = $baseurl . '/' . $blog->name; - - $fields = [ - 'uid' => $uid, - 'network' => Protocol::TUMBLR, - 'poll' => 'tumblr::' . $blog->uuid, - 'baseurl' => $baseurl, - 'priority' => 1, - 'writable' => true, - 'blocked' => false, - 'readonly' => false, - 'pending' => false, - 'url' => $url, - 'nurl' => Strings::normaliseLink($url), - 'alias' => $blog->url, - 'name' => $blog->title ?: $blog->name, - 'nick' => $blog->name, - 'addr' => $blog->name . '@tumblr.com', - 'about' => HTML::toBBCode($blog->description), - 'updated' => date(DateTimeFormat::MYSQL, $blog->updated) - ]; - - if (!$update) { - 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]); - return $fields; - } - - $avatar = $info->response->blog->avatar; - if (!empty($avatar)) { - $fields['avatar'] = $avatar[0]->url; - } - - if ($info->response->blog->followed && $info->response->blog->subscribed) { - $fields['rel'] = Contact::FRIEND; - } elseif ($info->response->blog->followed && !$info->response->blog->subscribed) { - $fields['rel'] = Contact::SHARING; - } elseif (!$info->response->blog->followed && $info->response->blog->subscribed) { - $fields['rel'] = Contact::FOLLOWER; - } else { - $fields['rel'] = Contact::NOTHING; - } - - $fields['header'] = $info->response->blog->theme->header_image_focused; - - Logger::debug('Got updated contact fields', ['uid' => $uid, 'url' => $fields['url']]); - return $fields; -} - -/** - * Get the default page for posting. Detects the value if not provided or has got a bad value. - * - * @param integer $uid - * @param array $blogs - * @return string - */ -function tumblr_get_page(int $uid, array $blogs = []): string -{ - $page = DI::pConfig()->get($uid, 'tumblr', 'page'); - - if (!empty($page) && (strpos($page, '/') === false)) { - return $page; - } - - if (empty($blogs)) { - $blogs = tumblr_get_blogs($uid); - } - - if (!empty($blogs)) { - $page = array_key_first($blogs); - DI::pConfig()->set($uid, 'tumblr', 'page', $page); - return $page; - } - - return ''; -} - -/** - * Get an array of blogs for the given user - * - * @param integer $uid - * @return array - */ -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]); - return []; - } - - $blogs = []; - foreach ($userinfo->response->user->blogs as $blog) { - $blogs[$blog->uuid] = $blog->name; - } - return $blogs; -} - -function tumblr_enabled_for_user(int $uid) -{ - return !empty($uid) && !empty(DI::pConfig()->get($uid, 'tumblr', 'access_token')) && - !empty(DI::pConfig()->get($uid, 'tumblr', 'refresh_token')) && - !empty(DI::config()->get('tumblr', 'consumer_key')) && - !empty(DI::config()->get('tumblr', 'consumer_secret')); -} - -/** - * 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, int $uid): ?array -{ - 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); - } catch (\Exception $e) { - return null; - } - $html = $curlResult->getBody(); - if (empty($html)) { - return null; - } - $doc = new DOMDocument(); - @$doc->loadHTML($html); - $xpath = new DomXPath($doc); - $body = $xpath->query('body'); - $attributes = tumblr_get_attributes($body->item(0)); - $blog = $attributes['data-urlencoded-name'] ?? ''; - } else { - $blogs = explode('/', $matches[1]); - $blog = $blogs[0] ?? ''; - } - - if (empty($blog)) { - return null; - } - - 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]); - return null; - } else { - Logger::debug('Got data', ['blog' => $blog, 'meta' => $info->meta]); - } - - $baseurl = 'https://tumblr.com'; - $url = $baseurl . '/' . $info->response->blog->name; - - return [ - 'url' => $url, - 'nurl' => Strings::normaliseLink($url), - 'addr' => $info->response->blog->name . '@tumblr.com', - 'alias' => $info->response->blog->url, - 'batch' => '', - 'notify' => '', - 'poll' => 'tumblr::' . $info->response->blog->uuid, - 'poco' => '', - 'name' => $info->response->blog->title ?: $info->response->blog->name, - 'nick' => $info->response->blog->name, - 'network' => Protocol::TUMBLR, - 'baseurl' => $baseurl, - 'pubkey' => '', - 'priority' => 0, - '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, - ]; -} - -/** - * Perform an OAuth2 GET request - * - * @param integer $uid - * @param string $url - * @param array $parameters - * @return stdClass - */ -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); - } - - 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); -} - -/** - * Perform an OAuth2 POST request - * - * @param integer $uid - * @param string $url - * @param array $parameters - * @return stdClass - */ -function tumblr_post(int $uid, string $url, array $parameters): stdClass -{ - $url = 'https://api.tumblr.com/v2/' . $url; - - $curlResult = DI::httpClient()->post($url, $parameters, ['Authorization' => ['Bearer ' . tumblr_get_token($uid)]]); - return tumblr_format_result($curlResult); -} - -/** - * Perform an OAuth2 DELETE request - * - * @param integer $uid - * @param string $url - * @param array $parameters - * @return stdClass - */ -function tumblr_delete(int $uid, string $url, array $parameters): stdClass -{ - $url = 'https://api.tumblr.com/v2/' . $url; - - $opts = [ - HttpClientOptions::HEADERS => ['Authorization' => ['Bearer ' . tumblr_get_token($uid)]], - HttpClientOptions::FORM_PARAMS => $parameters - ]; - - $curlResult = DI::httpClient()->request('delete', $url, $opts); - return tumblr_format_result($curlResult); -} - -/** - * Format the get/post result value - * - * @param ICanHandleHttpResponses $curlResult - * @return stdClass - */ -function tumblr_format_result(ICanHandleHttpResponses $curlResult): stdClass -{ - $result = json_decode($curlResult->getBody()); - if (empty($result) || empty($result->meta)) { - $result = new stdClass; - $result->meta = new stdClass; - $result->meta->status = 500; - $result->meta->msg = ''; - $result->response = []; - $result->errors = []; - } - return $result; -} - -/** - * Fetch the OAuth token, update it if needed - * - * @param integer $uid - * @param string $code - * @return string - */ -function tumblr_get_token(int $uid, string $code = ''): string -{ - $access_token = DI::pConfig()->get($uid, 'tumblr', 'access_token'); - $expires_at = DI::pConfig()->get($uid, 'tumblr', 'expires_at'); - $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)]); - return $access_token; - } - - $consumer_key = DI::config()->get('tumblr', 'consumer_key'); - $consumer_secret = DI::config()->get('tumblr', 'consumer_secret'); - - $parameters = ['client_id' => $consumer_key, 'client_secret' => $consumer_secret]; - - 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]); - return ''; - } - $expires_at = time() + $result->expires_in; - Logger::debug('Updated token from OAuth1 to OAuth2', ['uid' => $uid, 'expires_at' => date('c', $expires_at)]); - } else { - if (!empty($code)) { - $parameters['code'] = $code; - $parameters['grant_type'] = 'authorization_code'; - } else { - $parameters['refresh_token'] = $refresh_token; - $parameters['grant_type'] = 'refresh_token'; - } - - $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]); - return ''; - } - - $result = json_decode($curlResult->getBody()); - if (empty($result)) { - 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::pConfig()->set($uid, 'tumblr', 'access_token', $result->access_token); - DI::pConfig()->set($uid, 'tumblr', 'expires_at', $expires_at); - DI::pConfig()->set($uid, 'tumblr', 'refresh_token', $result->refresh_token); - - return $result->access_token; -} - -/** - * Create an OAuth2 token out of an OAuth1 token - * - * @param int $uid - * @return stdClass - */ -function tumblr_exchange_token(int $uid): stdClass -{ - $oauth_token = DI::pConfig()->get($uid, 'tumblr', 'oauth_token'); - $oauth_token_secret = DI::pConfig()->get($uid, 'tumblr', 'oauth_token_secret'); - - $consumer_key = DI::config()->get('tumblr', 'consumer_key'); - $consumer_secret = DI::config()->get('tumblr', 'consumer_secret'); - - $stack = HandlerStack::create(); - - $middleware = new Oauth1([ - 'consumer_key' => $consumer_key, - 'consumer_secret' => $consumer_secret, - 'token' => $oauth_token, - 'token_secret' => $oauth_token_secret - ]); - - $stack->push($middleware); - - try { - $client = new Client([ - 'base_uri' => 'https://api.tumblr.com/v2/', - 'handler' => $stack - ]); - - $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()]); - return new stdClass; } } diff --git a/twitter/README.md b/twitter/README.md index 038bf1ca..7e0fabc5 100644 --- a/twitter/README.md +++ b/twitter/README.md @@ -3,14 +3,44 @@ Twitter Addon Main authors Tobias Diekershoff, Michael Vogel and Hypolite Petovan. -This is a uni-directional posting connector addon that allows each user to crosspost their Friendica public posts to Twitter. +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. ## Installation -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. +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". ## License -The _Twitter Connector_ is licensed under the [3-clause BSD license][1] see the LICENSE file in the addons directory. +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 [1]: http://opensource.org/licenses/BSD-3-Clause +[2]: https://github.com/abraham/twitteroauth diff --git a/twitter/composer.json b/twitter/composer.json new file mode 100644 index 00000000..75090195 --- /dev/null +++ b/twitter/composer.json @@ -0,0 +1,32 @@ +{ + "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 new file mode 100644 index 00000000..80583397 --- /dev/null +++ b/twitter/composer.lock @@ -0,0 +1,328 @@ +{ + "_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 new file mode 100644 index 00000000..8895814d --- /dev/null +++ b/twitter/config/twitter.config.php @@ -0,0 +1,16 @@ + [ + // 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 366d6c8f..43d00fc1 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-16 03:27+0000\n" +"POT-Creation-Date: 2022-11-13 10:15+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,62 +17,143 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: twitter.php:84 +#: twitter.php:216 msgid "Post to Twitter" msgstr "" -#: twitter.php:123 -msgid "No status." +#: twitter.php:263 +msgid "" +"You submitted an empty PIN, please Sign In with Twitter again to get a new " +"one." msgstr "" -#: twitter.php:129 +#: twitter.php:330 +msgid "" +"No consumer key pair for Twitter found. Please contact your site " +"administrator." +msgstr "" + +#: 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 "" + +#: twitter.php:344 +msgid "Log in with Twitter" +msgstr "" + +#: twitter.php:346 +msgid "Copy the PIN from Twitter here" +msgstr "" + +#: twitter.php:354 twitter.php:399 +msgid "An error occured: " +msgstr "" + +#: twitter.php:368 +#, php-format +msgid "" +"Currently connected to: %1$s" +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 "" + +#: twitter.php:381 +msgid "Invalid Twitter info" +msgstr "" + +#: twitter.php:382 +msgid "Disconnect" +msgstr "" + +#: twitter.php:387 msgid "Allow posting to Twitter" msgstr "" -#: twitter.php:129 +#: twitter.php:387 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:130 +#: twitter.php:388 msgid "Send public postings to Twitter by default" msgstr "" -#: twitter.php:131 -msgid "API Key" +#: twitter.php:389 +msgid "Use threads instead of truncating the content" msgstr "" -#: twitter.php:132 -msgid "API Secret" +#: twitter.php:390 +msgid "Mirror all posts from twitter that are no replies" msgstr "" -#: twitter.php:133 -msgid "Access Token" +#: twitter.php:391 +msgid "Import the remote timeline" msgstr "" -#: twitter.php:134 -msgid "Access Secret" +#: twitter.php:392 +msgid "Automatically create contacts" msgstr "" -#: twitter.php:135 +#: twitter.php:392 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." +"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 "" -#: twitter.php:136 -msgid "Last Status Summary" +#: twitter.php:393 +msgid "Follow in fediverse" msgstr "" -#: twitter.php:137 -msgid "Last Status Content" +#: 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 "" -#: twitter.php:142 -msgid "Twitter Export" +#: twitter.php:406 +msgid "Twitter Import/Export/Mirror" +msgstr "" + +#: twitter.php:558 +msgid "" +"Please connect a Twitter account in your Social Network settings to import " +"Twitter posts." +msgstr "" + +#: twitter.php:565 +msgid "Twitter post not found." +msgstr "" + +#: twitter.php:965 +msgid "Save Settings" +msgstr "" + +#: twitter.php:967 +msgid "Consumer key" +msgstr "" + +#: twitter.php:968 +msgid "Consumer secret" +msgstr "" + +#: twitter.php:1167 +#, php-format +msgid "%s on Twitter" msgstr "" diff --git a/twitter/lang/ar/messages.po b/twitter/lang/ar/messages.po index e12139c6..0c1b26ae 100644 --- a/twitter/lang/ar/messages.po +++ b/twitter/lang/ar/messages.po @@ -9,72 +9,121 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \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" +"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" "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:84 +#: twitter.php:224 msgid "Post to Twitter" msgstr "" -#: twitter.php:123 -msgid "No status." +#: twitter.php:269 +msgid "" +"You submitted an empty PIN, please Sign In with Twitter again to get a new " +"one." msgstr "" -#: twitter.php:129 +#: 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 msgid "Allow posting to Twitter" msgstr "" -#: twitter.php:129 +#: twitter.php:397 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:130 +#: 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 msgid "Send public postings to Twitter by default" msgstr "" -#: twitter.php:131 -msgid "API Key" +#: twitter.php:406 +msgid "Mirror all posts from twitter that are no replies" msgstr "" -#: twitter.php:132 -msgid "API Secret" +#: twitter.php:409 +msgid "Import the remote timeline" msgstr "" -#: twitter.php:133 -msgid "Access Token" +#: twitter.php:412 +msgid "Automatically create contacts" msgstr "" -#: twitter.php:134 -msgid "Access Secret" -msgstr "" - -#: twitter.php:135 +#: twitter.php:412 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." +"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 "" -#: twitter.php:136 -msgid "Last Status Summary" +#: twitter.php:805 +msgid "Consumer key" msgstr "" -#: twitter.php:137 -msgid "Last Status Content" +#: twitter.php:806 +msgid "Consumer secret" msgstr "" -#: twitter.php:142 -msgid "Twitter Export" +#: twitter.php:1002 +#, php-format +msgid "%s on Twitter" msgstr "" diff --git a/twitter/lang/ar/strings.php b/twitter/lang/ar/strings.php index eea34dd6..285ad303 100644 --- a/twitter/lang/ar/strings.php +++ b/twitter/lang/ar/strings.php @@ -5,3 +5,4 @@ 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 3e9d27d5..68586a7e 100644 --- a/twitter/lang/cs/messages.po +++ b/twitter/lang/cs/messages.po @@ -11,72 +11,126 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \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" +"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" "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:84 +#: twitter.php:195 msgid "Post to Twitter" msgstr "Poslat příspěvek na Twitter" -#: twitter.php:123 -msgid "No status." -msgstr "" +#: 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:129 +#: 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 msgid "Allow posting to Twitter" msgstr "Povolit odesílání na Twitter" -#: twitter.php:129 +#: twitter.php:347 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:130 +#: 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 msgid "Send public postings to Twitter by default" msgstr "Defaultně zasílat veřejné komentáře na Twitter" -#: twitter.php:131 -msgid "API Key" -msgstr "" +#: 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:132 -msgid "API Secret" -msgstr "" +#: twitter.php:359 +msgid "Import the remote timeline" +msgstr "Importovat vzdálenou časovou osu" -#: twitter.php:133 -msgid "Access Token" -msgstr "" +#: twitter.php:362 +msgid "Automatically create contacts" +msgstr "Automaticky vytvořit kontakty" -#: twitter.php:134 -msgid "Access Secret" -msgstr "" - -#: twitter.php:135 +#: twitter.php:362 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 "" +"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ří." -#: twitter.php:136 -msgid "Last Status Summary" -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:137 -msgid "Last Status Content" -msgstr "" +#: twitter.php:628 +msgid "Settings updated." +msgstr "Nastavení aktualizováno." -#: twitter.php:142 -msgid "Twitter Export" -msgstr "" +#: twitter.php:638 +msgid "Consumer key" +msgstr "Consumer key" + +#: twitter.php:639 +msgid "Consumer secret" +msgstr "Consumer secret" diff --git a/twitter/lang/cs/strings.php b/twitter/lang/cs/strings.php index da68673d..59a584ce 100644 --- a/twitter/lang/cs/strings.php +++ b/twitter/lang/cs/strings.php @@ -6,6 +6,25 @@ 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 a38392a2..855293a4 100644 --- a/twitter/lang/de/messages.po +++ b/twitter/lang/de/messages.po @@ -4,7 +4,6 @@ # # # Translators: -# Raroun, 2023 # Till Mohr , 2021 # Tobias Diekershoff , 2014-2015 # Tobias Diekershoff , 2018,2020-2022 @@ -13,72 +12,153 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-08-16 03:27+0000\n" +"POT-Creation-Date: 2022-11-13 10:15+0000\n" "PO-Revision-Date: 2014-06-23 12:58+0000\n" -"Last-Translator: Raroun, 2023\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"Last-Translator: Tobias Diekershoff , 2018,2020-2022\n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: twitter.php:84 +#: twitter.php:216 msgid "Post to Twitter" msgstr "Auf Twitter veröffentlichen" -#: twitter.php:123 -msgid "No status." -msgstr "Kein Status." +#: 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:129 +#: 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 msgid "Allow posting to Twitter" msgstr "Veröffentlichung bei Twitter erlauben" -#: twitter.php:129 +#: twitter.php:387 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:130 +#: twitter.php:388 msgid "Send public postings to Twitter by default" msgstr "Veröffentliche öffentliche Beiträge standardmäßig bei Twitter" -#: twitter.php:131 -msgid "API Key" -msgstr "API Key" +#: twitter.php:389 +msgid "Use threads instead of truncating the content" +msgstr "Verwende Threads anstelle den Inhalt zu kürzen" -#: twitter.php:132 -msgid "API Secret" -msgstr "API Secret" +#: 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:133 -msgid "Access Token" -msgstr "Access Token" +#: twitter.php:391 +msgid "Import the remote timeline" +msgstr "Importiere die Remote-Zeitleiste" -#: twitter.php:134 -msgid "Access Secret" -msgstr "Access Secret" +#: twitter.php:392 +msgid "Automatically create contacts" +msgstr "Automatisch Kontakte anlegen" -#: twitter.php:135 +#: twitter.php:392 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 "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." +"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." -#: twitter.php:136 -msgid "Last Status Summary" -msgstr "Zusammenfassung des letzten Status" +#: twitter.php:393 +msgid "Follow in fediverse" +msgstr "Im Fediverse folgen" -#: twitter.php:137 -msgid "Last Status Content" -msgstr "Inhalt 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:142 -msgid "Twitter Export" -msgstr "Twitter Export" +#: 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" diff --git a/twitter/lang/de/strings.php b/twitter/lang/de/strings.php index 4079ddfe..f465aab2 100644 --- a/twitter/lang/de/strings.php +++ b/twitter/lang/de/strings.php @@ -6,15 +6,30 @@ function string_plural_select_de($n){ return intval($n != 1); }} $a->strings['Post to Twitter'] = 'Auf Twitter veröffentlichen'; -$a->strings['No status.'] = 'Kein Status.'; +$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['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['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'; +$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'; diff --git a/twitter/lang/es/messages.po b/twitter/lang/es/messages.po index f479b846..6673ef0a 100644 --- a/twitter/lang/es/messages.po +++ b/twitter/lang/es/messages.po @@ -11,72 +11,123 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \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" +"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" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: es\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: twitter.php:84 +#: twitter.php:189 msgid "Post to Twitter" msgstr "Entrada para Twitter" -#: twitter.php:123 -msgid "No status." -msgstr "" +#: 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:129 +#: 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 msgid "Allow posting to Twitter" msgstr "Permitir publicar en Twitter" -#: twitter.php:129 +#: twitter.php:359 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:130 +#: 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 msgid "Send public postings to Twitter by default" msgstr "Enviar publicaciones públicas a Twitter por defecto" -#: twitter.php:131 -msgid "API Key" -msgstr "" +#: 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:132 -msgid "API Secret" -msgstr "" +#: twitter.php:371 +msgid "Import the remote timeline" +msgstr "Importar la línea de tiempo remota" -#: twitter.php:133 -msgid "Access Token" -msgstr "" +#: twitter.php:374 +msgid "Automatically create contacts" +msgstr "Crea contactos automáticamente" -#: twitter.php:134 -msgid "Access Secret" -msgstr "" - -#: twitter.php:135 +#: twitter.php:374 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 "" +"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." -#: twitter.php:136 -msgid "Last Status Summary" -msgstr "" +#: twitter.php:770 +msgid "Consumer key" +msgstr "Clave de consumidor" -#: twitter.php:137 -msgid "Last Status Content" -msgstr "" +#: twitter.php:771 +msgid "Consumer secret" +msgstr "Secreto de consumidor" -#: twitter.php:142 -msgid "Twitter Export" -msgstr "" +#: twitter.php:967 +#, php-format +msgid "%s on Twitter" +msgstr "%s en Twitter" diff --git a/twitter/lang/es/strings.php b/twitter/lang/es/strings.php index 368c871c..1aa0cd14 100644 --- a/twitter/lang/es/strings.php +++ b/twitter/lang/es/strings.php @@ -3,9 +3,27 @@ if(! function_exists("string_plural_select_es")) { function string_plural_select_es($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $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 b510d6d8..f6afa0a6 100644 --- a/twitter/lang/fr/messages.po +++ b/twitter/lang/fr/messages.po @@ -4,7 +4,6 @@ # # # Translators: -# Florent C., 2023 # Nicolas Derive, 2022 # ea1cd8241cb389ffb6f92bc6891eff5d_dc12308 <70dced5587d47e18d88f9298024d96f8_93383>, 2015 # StefOfficiel , 2015 @@ -12,72 +11,153 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-08-16 03:27+0000\n" +"POT-Creation-Date: 2022-11-13 10:15+0000\n" "PO-Revision-Date: 2014-06-23 12:58+0000\n" -"Last-Translator: Florent C., 2023\n" -"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n" +"Last-Translator: Nicolas Derive, 2022\n" +"Language-Team: French (http://www.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:84 +#: twitter.php:216 msgid "Post to Twitter" msgstr "Publier sur Twitter" -#: twitter.php:123 -msgid "No status." -msgstr "Aucun statut" +#: 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:129 +#: 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 msgid "Allow posting to Twitter" msgstr "Autoriser la publication sur Twitter" -#: twitter.php:129 +#: twitter.php:387 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:130 +#: twitter.php:388 msgid "Send public postings to Twitter by default" msgstr "Envoyer par défaut les publications publiques sur Twitter" -#: twitter.php:131 -msgid "API Key" -msgstr "Clé API" +#: 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:132 -msgid "API Secret" -msgstr "Secret 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:133 -msgid "Access Token" -msgstr "Token Accès" +#: twitter.php:391 +msgid "Import the remote timeline" +msgstr "Importer la Timeline distante" -#: twitter.php:134 -msgid "Access Secret" -msgstr "Secret Accès" +#: twitter.php:392 +msgid "Automatically create contacts" +msgstr "Créer automatiquement les contacts" -#: twitter.php:135 +#: twitter.php:392 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 "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." +"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." -#: twitter.php:136 -msgid "Last Status Summary" -msgstr "Résumé du dernier statut" +#: twitter.php:393 +msgid "Follow in fediverse" +msgstr "Suivre dans le fediverse" -#: twitter.php:137 -msgid "Last Status Content" -msgstr "Contenu 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:142 -msgid "Twitter Export" -msgstr "Export Twitter" +#: 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" diff --git a/twitter/lang/fr/strings.php b/twitter/lang/fr/strings.php index d75116e9..ff46a386 100644 --- a/twitter/lang/fr/strings.php +++ b/twitter/lang/fr/strings.php @@ -6,15 +6,30 @@ 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['No status.'] = 'Aucun statut'; +$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['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['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'; +$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'; diff --git a/twitter/lang/hu/messages.po b/twitter/lang/hu/messages.po index a42e3327..7ff28101 100644 --- a/twitter/lang/hu/messages.po +++ b/twitter/lang/hu/messages.po @@ -4,77 +4,158 @@ # # # Translators: -# Balázs Úr, 2020-2023 +# Balázs Úr, 2020-2022 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-08-16 03:27+0000\n" +"POT-Creation-Date: 2022-11-13 10:15+0000\n" "PO-Revision-Date: 2014-06-23 12:58+0000\n" -"Last-Translator: Balázs Úr, 2020-2023\n" -"Language-Team: Hungarian (http://app.transifex.com/Friendica/friendica/language/hu/)\n" +"Last-Translator: Balázs Úr, 2020-2022\n" +"Language-Team: Hungarian (http://www.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:84 +#: twitter.php:216 msgid "Post to Twitter" msgstr "Beküldés a Twitterre" -#: twitter.php:123 -msgid "No status." -msgstr "Nincs állapot." +#: 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:129 +#: 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 msgid "Allow posting to Twitter" msgstr "Beküldés engedélyezése a Twitterre" -#: twitter.php:129 +#: twitter.php:387 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:130 +#: twitter.php:388 msgid "Send public postings to Twitter by default" msgstr "Nyilvános beküldések küldése a Twitterre alapértelmezetten" -#: twitter.php:131 -msgid "API Key" -msgstr "API-kulcs" +#: twitter.php:389 +msgid "Use threads instead of truncating the content" +msgstr "Szálak használata a tartalom csonkítása helyett" -#: twitter.php:132 -msgid "API Secret" -msgstr "API-titok" +#: 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:133 -msgid "Access Token" -msgstr "Hozzáférési token" +#: twitter.php:391 +msgid "Import the remote timeline" +msgstr "A távoli idővonal importálása" -#: twitter.php:134 -msgid "Access Secret" -msgstr "Hozzáférési titok" +#: twitter.php:392 +msgid "Automatically create contacts" +msgstr "Partnerek automatikus létrehozása" -#: twitter.php:135 +#: twitter.php:392 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 "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." +"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." -#: twitter.php:136 -msgid "Last Status Summary" -msgstr "Utolsó állapot összegzése" +#: twitter.php:393 +msgid "Follow in fediverse" +msgstr "Követés a födiverzumban" -#: twitter.php:137 -msgid "Last Status Content" -msgstr "Utolsó állapot tartalma" +#: 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:142 -msgid "Twitter Export" -msgstr "Twitter exportálás" +#: 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" diff --git a/twitter/lang/hu/strings.php b/twitter/lang/hu/strings.php index 8e2a5084..552ebb3e 100644 --- a/twitter/lang/hu/strings.php +++ b/twitter/lang/hu/strings.php @@ -6,15 +6,30 @@ function string_plural_select_hu($n){ return intval($n != 1); }} $a->strings['Post to Twitter'] = 'Beküldés a Twitterre'; -$a->strings['No status.'] = 'Nincs állapot.'; +$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['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['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'; +$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'; diff --git a/twitter/lang/it/messages.po b/twitter/lang/it/messages.po index dfb7adb2..a199980c 100644 --- a/twitter/lang/it/messages.po +++ b/twitter/lang/it/messages.po @@ -10,72 +10,123 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \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" +"POT-Creation-Date: 2020-10-23 02:00-0400\n" +"PO-Revision-Date: 2020-11-20 16:52+0000\n" +"Last-Translator: Sylke Vicious \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: twitter.php:84 +#: twitter.php:189 msgid "Post to Twitter" msgstr "Invia a Twitter" -#: twitter.php:123 -msgid "No status." -msgstr "" +#: twitter.php:234 +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:129 +#: twitter.php:291 twitter.php:295 +msgid "Twitter Import/Export/Mirror" +msgstr "Importa/Esporta/Clona Twitter" + +#: twitter.php:302 +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: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 "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:315 +msgid "Log in with Twitter" +msgstr "Accedi con Twitter" + +#: twitter.php:317 +msgid "Copy the PIN from Twitter here" +msgstr "Copia il PIN da Twitter qui" + +#: twitter.php:322 twitter.php:377 twitter.php:757 +msgid "Save Settings" +msgstr "Salva Impostazioni" + +#: twitter.php:324 twitter.php:379 +msgid "An error occured: " +msgstr "Si è verificato un errore:" + +#: twitter.php:341 +msgid "Currently connected to: " +msgstr "Al momento connesso con:" + +#: twitter.php:342 twitter.php:352 +msgid "Disconnect" +msgstr "Disconnetti" + +#: twitter.php:359 msgid "Allow posting to Twitter" msgstr "Permetti l'invio a Twitter" -#: twitter.php:129 +#: twitter.php:359 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:130 +#: 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: 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:365 msgid "Send public postings to Twitter by default" msgstr "Invia sempre i messaggi pubblici a Twitter" -#: twitter.php:131 -msgid "API Key" -msgstr "" +#: twitter.php:368 +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:371 +msgid "Import the remote timeline" +msgstr "Importa la timeline remota" -#: twitter.php:133 -msgid "Access Token" -msgstr "" +#: twitter.php:374 +msgid "Automatically create contacts" +msgstr "Crea automaticamente i contatti" -#: twitter.php:134 -msgid "Access Secret" -msgstr "" - -#: twitter.php:135 +#: twitter.php:374 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 "" +"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 "Questo creerà automaticamente un contatto in Friendica appena ricevi un messaggio da un tuo contatto sulla rete Twitter. Se non abiliti questa opzione, dovrai aggiungere a mano in Friendica i contatti Twitter da cui vuoi ricevere i messaggi. Se abilitato, però, non potrai semplicemente rimuovere un contatto Twitter dal tuo elenco contatti su Friendica, dato che questo sarà ricreato la prossima volta che invierà un messaggio." -#: twitter.php:136 -msgid "Last Status Summary" -msgstr "" +#: twitter.php:759 +msgid "Consumer key" +msgstr "Consumer key" -#: twitter.php:137 -msgid "Last Status Content" -msgstr "" +#: twitter.php:760 +msgid "Consumer secret" +msgstr "Consumer secret" -#: twitter.php:142 -msgid "Twitter Export" -msgstr "" +#: twitter.php:945 +#, 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 f744c242..e4797a7e 100644 --- a/twitter/lang/it/strings.php +++ b/twitter/lang/it/strings.php @@ -3,9 +3,27 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $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['Twitter Import/Export/Mirror'] = 'Importa/Esporta/Clona Twitter'; +$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['Save Settings'] = 'Salva Impostazioni'; +$a->strings['An error occured: '] = 'Si è verificato un errore:'; +$a->strings['Currently connected to: '] = 'Al momento connesso con:'; +$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['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['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['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.'] = 'Questo creerà automaticamente un contatto in Friendica appena ricevi un messaggio da un tuo contatto sulla rete Twitter. Se non abiliti questa opzione, dovrai aggiungere a mano in Friendica i contatti Twitter da cui vuoi ricevere i messaggi. Se abilitato, però, non potrai semplicemente rimuovere un contatto Twitter dal tuo elenco contatti su Friendica, dato che questo sarà ricreato la prossima volta che invierà un messaggio.'; +$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 f65c86c1..bc0d4360 100644 --- a/twitter/lang/ja/messages.po +++ b/twitter/lang/ja/messages.po @@ -4,77 +4,128 @@ # # # Translators: -# daingewuvzeevisiddfddd, 2021 +# XMPPはいいぞ, 2021 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \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" +"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" "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:84 +#: twitter.php:189 msgid "Post to Twitter" msgstr "Twitterに投稿" -#: twitter.php:123 -msgid "No status." -msgstr "" +#: 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:129 +#: 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 msgid "Allow posting to Twitter" msgstr "Twitterへの投稿を許可する" -#: twitter.php:129 +#: twitter.php:359 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:130 +#: 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 msgid "Send public postings to Twitter by default" msgstr "デフォルトでTwitterに一般公開投稿を送信する" -#: twitter.php:131 -msgid "API Key" -msgstr "" +#: twitter.php:368 +msgid "Mirror all posts from twitter that are no replies" +msgstr "返信がないTwitterのすべての投稿をミラーリングする" -#: twitter.php:132 -msgid "API Secret" -msgstr "" +#: twitter.php:371 +msgid "Import the remote timeline" +msgstr "リモートタイムラインをインポートする" -#: twitter.php:133 -msgid "Access Token" -msgstr "" +#: twitter.php:374 +msgid "Automatically create contacts" +msgstr "連絡先を自動的に作成する" -#: twitter.php:134 -msgid "Access Secret" -msgstr "" - -#: twitter.php:135 +#: twitter.php:374 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 "" +"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:136 -msgid "Last Status Summary" -msgstr "" +#: twitter.php:770 +msgid "Consumer key" +msgstr "コンシューマ キー" -#: twitter.php:137 -msgid "Last Status Content" -msgstr "" +#: twitter.php:771 +msgid "Consumer secret" +msgstr "コンシューマ シークレット" -#: twitter.php:142 -msgid "Twitter Export" +#: twitter.php:967 +#, php-format +msgid "%s on Twitter" msgstr "" diff --git a/twitter/lang/ja/strings.php b/twitter/lang/ja/strings.php index 9fda4106..935058fb 100644 --- a/twitter/lang/ja/strings.php +++ b/twitter/lang/ja/strings.php @@ -6,6 +6,23 @@ 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 d1f397ae..b0af4dc9 100644 --- a/twitter/lang/nl/messages.po +++ b/twitter/lang/nl/messages.po @@ -9,72 +9,126 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \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" +"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" "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:84 +#: twitter.php:195 msgid "Post to Twitter" msgstr "Plaatsen op Twitter" -#: twitter.php:123 -msgid "No status." +#: twitter.php:236 +msgid "" +"You submitted an empty PIN, please Sign In with Twitter again to get a new " +"one." msgstr "" -#: twitter.php:129 +#: 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 msgid "Allow posting to Twitter" msgstr "Plaatsen op Twitter toestaan" -#: twitter.php:129 +#: twitter.php:347 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:130 +#: 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 msgid "Send public postings to Twitter by default" msgstr "Verzend publieke berichten naar Twitter als standaard instellen " -#: twitter.php:131 -msgid "API Key" +#: twitter.php:356 +msgid "Mirror all posts from twitter that are no replies" msgstr "" -#: twitter.php:132 -msgid "API Secret" +#: twitter.php:359 +msgid "Import the remote timeline" msgstr "" -#: twitter.php:133 -msgid "Access Token" +#: twitter.php:362 +msgid "Automatically create contacts" msgstr "" -#: twitter.php:134 -msgid "Access Secret" -msgstr "" - -#: twitter.php:135 +#: twitter.php:362 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." +"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.php:136 -msgid "Last Status Summary" +#: twitter.php:614 +msgid "Twitter post failed. Queued for retry." msgstr "" -#: twitter.php:137 -msgid "Last Status Content" +#: twitter.php:628 +msgid "Settings updated." +msgstr "Instellingen opgeslagen" + +#: twitter.php:638 +msgid "Consumer key" msgstr "" -#: twitter.php:142 -msgid "Twitter Export" +#: twitter.php:639 +msgid "Consumer secret" msgstr "" diff --git a/twitter/lang/nl/strings.php b/twitter/lang/nl/strings.php index 41c44f25..60a1d4ab 100644 --- a/twitter/lang/nl/strings.php +++ b/twitter/lang/nl/strings.php @@ -6,5 +6,9 @@ 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 11aaef7c..adf3809c 100644 --- a/twitter/lang/pl/messages.po +++ b/twitter/lang/pl/messages.po @@ -10,72 +10,153 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-08-16 03:27+0000\n" +"POT-Creation-Date: 2022-11-13 10:15+0000\n" "PO-Revision-Date: 2014-06-23 12:58+0000\n" "Last-Translator: Piotr Strębski , 2022\n" -"Language-Team: Polish (http://app.transifex.com/Friendica/friendica/language/pl/)\n" +"Language-Team: Polish (http://www.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:84 +#: twitter.php:216 msgid "Post to Twitter" msgstr "Opublikuj na Twitterze" -#: twitter.php:123 -msgid "No status." -msgstr "" +#: 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:129 +#: 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 msgid "Allow posting to Twitter" msgstr "Zezwalaj na publikowanie na Twitterze" -#: twitter.php:129 +#: twitter.php:387 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:130 +#: twitter.php:388 msgid "Send public postings to Twitter by default" msgstr "Wyślij domyślnie komentarze publiczne do Twitter" -#: twitter.php:131 -msgid "API Key" -msgstr "" +#: twitter.php:389 +msgid "Use threads instead of truncating the content" +msgstr "Używaj wątków zamiast obcinania treści" -#: twitter.php:132 -msgid "API Secret" -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:133 -msgid "Access Token" -msgstr "" +#: twitter.php:391 +msgid "Import the remote timeline" +msgstr "Zaimportuj zdalną oś czasu" -#: twitter.php:134 -msgid "Access Secret" -msgstr "" +#: twitter.php:392 +msgid "Automatically create contacts" +msgstr "Automatycznie twórz kontakty" -#: twitter.php:135 +#: twitter.php:392 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 "" +"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." -#: twitter.php:136 -msgid "Last Status Summary" -msgstr "" +#: twitter.php:393 +msgid "Follow in fediverse" +msgstr "Śledź w fediverse" -#: twitter.php:137 -msgid "Last Status Content" -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:142 -msgid "Twitter Export" -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" diff --git a/twitter/lang/pl/strings.php b/twitter/lang/pl/strings.php index d160fa3b..3d44c3e5 100644 --- a/twitter/lang/pl/strings.php +++ b/twitter/lang/pl/strings.php @@ -6,6 +6,30 @@ 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 d6b4b442..911b2e08 100644 --- a/twitter/lang/ru/messages.po +++ b/twitter/lang/ru/messages.po @@ -9,72 +9,115 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \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" +"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" "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:84 +#: twitter.php:77 msgid "Post to Twitter" msgstr "Отправить в Twitter" -#: twitter.php:123 -msgid "No status." -msgstr "" - #: twitter.php:129 -msgid "Allow posting to Twitter" -msgstr "Разрешить отправку сообщений на Twitter" +msgid "Twitter settings updated." +msgstr "Настройки Twitter обновлены." -#: twitter.php:129 +#: 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 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:130 +#: 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 msgid "Send public postings to Twitter by default" msgstr "Отправлять сообщения для всех в Twitter по умолчанию" -#: twitter.php:131 -msgid "API Key" -msgstr "" +#: twitter.php:213 +msgid "Mirror all posts from twitter that are no replies or retweets" +msgstr "Получать посты с Twitter у которых нет ответов и ретвитов" -#: twitter.php:132 -msgid "API Secret" -msgstr "" +#: twitter.php:217 +msgid "Shortening method that optimizes the tweet" +msgstr "Метод сокращения ссылок для оптимизации твита" -#: twitter.php:133 -msgid "Access Token" -msgstr "" +#: twitter.php:221 +msgid "Send linked #-tags and @-names to Twitter" +msgstr "Отправлять #-теги и @-имена в Twitter ссылками" -#: twitter.php:134 -msgid "Access Secret" -msgstr "" +#: twitter.php:226 +msgid "Clear OAuth configuration" +msgstr "Удалить конфигурацию OAuth" -#: twitter.php:135 +#: 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 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 "" +"set this to avoid mirroring postings from ~friendica back to ~friendica" +msgstr "установите это для избежания отправки сообщений из Friendica обратно в Friendica" diff --git a/twitter/lang/ru/strings.php b/twitter/lang/ru/strings.php index 94582c11..237d68bb 100644 --- a/twitter/lang/ru/strings.php +++ b/twitter/lang/ru/strings.php @@ -6,6 +6,24 @@ 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['Allow posting 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['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 df5c8ac1..ccbfe7a7 100644 --- a/twitter/lang/sv/messages.po +++ b/twitter/lang/sv/messages.po @@ -10,72 +10,138 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \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" +"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" "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:84 +#: twitter.php:213 msgid "Post to Twitter" msgstr "" -#: twitter.php:123 -msgid "No status." +#: twitter.php:258 +msgid "" +"You submitted an empty PIN, please Sign In with Twitter again to get a new " +"one." msgstr "" -#: twitter.php:129 +#: 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 msgid "Allow posting to Twitter" msgstr "" -#: twitter.php:129 +#: twitter.php:378 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:130 +#: twitter.php:379 msgid "Send public postings to Twitter by default" msgstr "" -#: twitter.php:131 -msgid "API Key" +#: twitter.php:380 +msgid "Mirror all posts from twitter that are no replies" msgstr "" -#: twitter.php:132 -msgid "API Secret" +#: twitter.php:381 +msgid "Import the remote timeline" msgstr "" -#: twitter.php:133 -msgid "Access Token" +#: twitter.php:382 +msgid "Automatically create contacts" msgstr "" -#: twitter.php:134 -msgid "Access Secret" -msgstr "" - -#: twitter.php:135 +#: twitter.php:382 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." +"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 "" -#: twitter.php:136 -msgid "Last Status Summary" +#: twitter.php:395 +msgid "Twitter Import/Export/Mirror" msgstr "" -#: twitter.php:137 -msgid "Last Status Content" +#: twitter.php:547 +msgid "" +"Please connect a Twitter account in your Social Network settings to import " +"Twitter posts." msgstr "" -#: twitter.php:142 -msgid "Twitter Export" +#: 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" msgstr "" diff --git a/twitter/lang/sv/strings.php b/twitter/lang/sv/strings.php index 72e9772f..13200174 100644 --- a/twitter/lang/sv/strings.php +++ b/twitter/lang/sv/strings.php @@ -5,3 +5,7 @@ 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'; diff --git a/twitter/lighter.png b/twitter/lighter.png new file mode 100644 index 00000000..297bb034 Binary files /dev/null and b/twitter/lighter.png differ diff --git a/twitter/templates/admin.tpl b/twitter/templates/admin.tpl new file mode 100644 index 00000000..d598e888 --- /dev/null +++ b/twitter/templates/admin.tpl @@ -0,0 +1,4 @@ +{{include file="field_input.tpl" field=$consumerkey}} +{{include file="field_input.tpl" field=$consumersecret}} + +
diff --git a/twitter/templates/connector_settings.tpl b/twitter/templates/connector_settings.tpl index 251093de..5d0061d1 100644 --- a/twitter/templates/connector_settings.tpl +++ b/twitter/templates/connector_settings.tpl @@ -1,9 +1,25 @@ +
+{{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}} -

{{$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}} -{{include file="field_input.tpl" field=$status_title}} -{{include file="field_textarea.tpl" field=$status}} \ No newline at end of file +{{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}} diff --git a/twitter/twitter.css b/twitter/twitter.css new file mode 100644 index 00000000..480ce28d --- /dev/null +++ b/twitter/twitter.css @@ -0,0 +1,12 @@ + + +#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 b01345b7..d7cce96a 100644 --- a/twitter/twitter.php +++ b/twitter/twitter.php @@ -1,14 +1,13 @@ * Author: Michael Vogel * Maintainer: Hypolite Petovan - * Maintainer: Michael Vogel * - * Copyright (c) 2011-2023 Tobias Diekershoff, Michael Vogel, Hypolite Petovan + * Copyright (c) 2011-2013 Tobias Diekershoff, Michael Vogel, Hypolite Petovan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,42 +33,178 @@ * 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\Group; 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\Object\Image; -use GuzzleHttp\Client; -use GuzzleHttp\Exception\RequestException; -use GuzzleHttp\HandlerStack; -use GuzzleHttp\Subscriber\Oauth\Oauth1; +use Friendica\Util\DateTimeFormat; +use Friendica\Util\Images; +use Friendica\Util\Strings; -const TWITTER_IMAGE_SIZE = [2000000, 1000000, 500000, 100000, 50000]; +require_once __DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'; + +define('TWITTER_DEFAULT_POLL_INTERVAL', 5); // given in minutes function twitter_install() { - Hook::register('load_config', __FILE__, 'twitter_load_config'); - Hook::register('connector_settings', __FILE__, 'twitter_settings'); + // 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'); - 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'); + 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()) { @@ -88,30 +223,75 @@ function twitter_jot_nets(array &$jotnets_fields) } } + function twitter_settings_post() { - if (!DI::userSession()->getLocalUserId() || empty($_POST['twitter-submit'])) { + 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'])) { 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'); + 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.')); + } - 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']); + $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 ( - 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()); + if (!intval($_POST['twitter-mirror'])) { + DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'twitter', 'lastid'); + } + } } } @@ -121,41 +301,116 @@ function twitter_settings(array &$data) return; } - $enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'post') ?? false; - $def_enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'post_by_default') ?? false; + $user = User::getById(DI::userSession()->getLocalUserId()); - $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::page()->registerStylesheet(__DIR__ . '/twitter.css', 'all'); - $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']); + /* * * + * 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 { - $status_title = DI::l10n()->t('No status.'); - } - $status_content = $last_status['content'] ?? ''; + // 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']); - $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.'), - '$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'], - ]); + $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() . '

'; + } + } + } $data = [ 'connector' => 'twitter', - 'title' => DI::l10n()->t('Twitter Export'), + 'title' => DI::l10n()->t('Twitter Import/Export/Mirror'), 'enabled' => $enabled, 'image' => 'images/twitter.png', 'html' => $html, + 'submit' => $submit ?? null, ]; } @@ -169,31 +424,64 @@ 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) - ) { + // 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'); $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; } - 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); + $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 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 = true; + $twitter_enable = 1; } if (!$twitter_enable) { @@ -207,98 +495,393 @@ 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); + } +} + +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['gravity'] != Item::GRAVITY_PARENT) || !strstr($b['postopts'], 'twitter') || $b['private'] || $b['deleted'] || ($b['created'] !== $b['edited'])) { + 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']))) { 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 forum 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'); - $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'); + $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'); - if (empty($api_key) || empty($api_secret) || empty($access_token) || empty($access_secret)) { - Logger::info('Missing keys, secrets or tokens.'); - return; - } + if ($ckey && $csecret && $otoken && $osecret) { + Logger::info('We have customer key and oauth stuff, going to send.'); - $msgarr = Plaintext::getPost($b, 280, true, BBCode::TWITTER); - 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'] ?? []]); - - $retrial = Worker::getRetrial(); - if ($retrial > 4) { + // If it's a repeated message from twitter then do a native retweet and exit + if (twitter_is_retweet($b['uid'], $b['body'])) { return; } - foreach ($msgarr['images'] ?? [] as $image) { - if (count($media_ids) == 4) { - continue; + + Codebird::setConsumerKey($ckey, $csecret); + $cb = Codebird::getInstance(); + $cb->setToken($otoken, $osecret); + + $connection = new TwitterOAuth($ckey, $csecret, $otoken, $osecret); + + // 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); } + ); + + $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[] = twitter_upload_image($b['uid'], $image, $retrial); - } catch (RequestException $exception) { - Logger::warning('Error while uploading image', ['image' => $image, 'code' => $exception->getCode(), 'message' => $exception->getMessage()]); + $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()]); + } + } + + 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()]); + } + } + + 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::config()->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(); - return; + } 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::config()->set('twitter', 'application_name', strip_tags($application_name)); } } } - - $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 (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; - } - - $in_reply_to_tweet_id = $id; - $media_ids = []; - } } -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, int $retrial) +function twitter_upload_image($connection, $cb, array $image, array $item) { if (!empty($image['id'])) { $photo = Photo::selectFirst([], ['id' => $image['id']]); @@ -306,110 +889,1606 @@ function twitter_upload_image(int $uid, array $image, int $retrial) $photo = Photo::createPhotoForExternalResource($image['url']); } - $picturedata = Photo::getImageForPhoto($photo); + $tempfile = tempnam(System::getTempPath(), 'cache'); + file_put_contents($tempfile, Photo::getImageForPhoto($photo)); - $picture = new Image($picturedata, $photo['type']); - $height = $picture->getHeight(); - $width = $picture->getWidth(); - $size = strlen($picturedata); + Logger::info('Uploading', ['id' => $item['id'], 'image' => $image]); + $media = $connection->upload('media/upload', ['media' => $tempfile]); - $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, '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]); + unlink($tempfile); 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, 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]); + $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]); } } else { - Logger::error('Failed upload', ['uid' => $uid, 'size' => strlen($picturedata), 'image' => $image['url'], 'return' => $media]); + Logger::error('Failed upload', ['id' => $item['id'], 'image' => $image['url'], 'return' => $media]); throw new Exception('Failed upload of ' . $image['url']); } return $media_id; } -function twitter_post(int $uid, string $url, string $type, array $data): stdClass +function twitter_delete_item(array $item) { - $stack = HandlerStack::create(); + if (!$item['deleted']) { + return; + } - $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'), - ]); + if ($item['parent'] != $item['id']) { + Logger::debug('Deleting comment/announce', ['item' => $item]); - $stack->push($middleware); + // 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; + } - $client = new Client([ - 'handler' => $stack - ]); + $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; + } - $response = $client->post($url, ['auth' => 'oauth', $type => $data]); - $body = $response->getBody()->getContents(); + Logger::debug('Parent found', ['parent' => $thr_parent]); + } else { + if (!strstr($item['extid'], 'twitter')) { + DI::logger()->info('Not a Twitter post', ['extid' => $item['extid']]); + return; + } - $status = [ - 'code' => $response->getStatusCode(), - 'reason' => $response->getReasonPhrase(), - 'content' => $body - ]; + // Don't delete if the post doesn't belong to us. + // This is a check for forum 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; + } + } - DI::pConfig()->set($uid, 'twitter', 'last_status', $status); + /** + * @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; + } - $content = json_decode($body) ?? new stdClass; - Logger::debug('Success', ['content' => $content]); - return $content; -} + 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; + } -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]); + 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'), ''], + ]); +} + +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()->get() . '/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::config()->get('twitter', 'application_name'); + + if ($application_name == '') { + $application_name = DI::baseUrl()->getHostname(); + } + + $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(); + + Group::addMember(User::getDefaultGroup($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()->get() . '/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::config()->get('twitter', 'application_name'); + + if ($application_name == '') { + $application_name = DI::baseUrl()->getHostname(); + } + + $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']; +} diff --git a/twitter/twitter_sync.php b/twitter/twitter_sync.php new file mode 100644 index 00000000..073793e2 --- /dev/null +++ b/twitter/twitter_sync.php @@ -0,0 +1,31 @@ +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 new file mode 100644 index 00000000..e064c4e0 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/.github/dependabot.yml @@ -0,0 +1,14 @@ +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 new file mode 100644 index 00000000..6b718cd8 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/.github/workflows/lint.yaml @@ -0,0 +1,12 @@ +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 new file mode 100644 index 00000000..78af4a8f --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/.github/workflows/test.yaml @@ -0,0 +1,18 @@ +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 new file mode 100644 index 00000000..f018d18a --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/.gitignore @@ -0,0 +1,5 @@ +.DS_Store +vendor +env +*.cache +node_modules diff --git a/twitter/vendor/abraham/twitteroauth/.prettierignore b/twitter/vendor/abraham/twitteroauth/.prettierignore new file mode 100644 index 00000000..fb96e452 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/.prettierignore @@ -0,0 +1,3 @@ +vendor +composer.lock +tests/fixtures diff --git a/twitter/vendor/abraham/twitteroauth/.prettierrc.json b/twitter/vendor/abraham/twitteroauth/.prettierrc.json new file mode 100644 index 00000000..cf18896b --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "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 new file mode 100644 index 00000000..80b42390 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# 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 new file mode 100644 index 00000000..d941b2c9 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/CONTRIBUTING.md @@ -0,0 +1,21 @@ +# 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 new file mode 100644 index 00000000..3a631e0c --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/LICENSE.md @@ -0,0 +1,22 @@ +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 new file mode 100644 index 00000000..5afe95f0 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/README.md @@ -0,0 +1,11 @@ +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 new file mode 100644 index 00000000..33797545 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/autoload.php @@ -0,0 +1,35 @@ +=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 new file mode 100644 index 00000000..daafae0c --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/package-lock.json @@ -0,0 +1,511 @@ +{ + "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 new file mode 100644 index 00000000..81746e3d --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/package.json @@ -0,0 +1,44 @@ +{ + "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 new file mode 100644 index 00000000..ef45e75a --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/phpmd.xml @@ -0,0 +1,15 @@ + + + Keep TwitterOAuth source code clean. + + + + + + + + diff --git a/twitter/vendor/abraham/twitteroauth/phpunit.xml b/twitter/vendor/abraham/twitteroauth/phpunit.xml new file mode 100644 index 00000000..d882f5bd --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/phpunit.xml @@ -0,0 +1,18 @@ + + + + + + ./tests/ + + + + + + + diff --git a/twitter/vendor/abraham/twitteroauth/src/Config.php b/twitter/vendor/abraham/twitteroauth/src/Config.php new file mode 100644 index 00000000..ab7ee2e4 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/src/Config.php @@ -0,0 +1,109 @@ + + */ +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 new file mode 100644 index 00000000..3f3797a0 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/src/Consumer.php @@ -0,0 +1,43 @@ +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 new file mode 100644 index 00000000..922b2cf0 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/src/HmacSha1.php @@ -0,0 +1,46 @@ +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 new file mode 100644 index 00000000..c3e1dc17 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/src/Request.php @@ -0,0 +1,289 @@ +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 new file mode 100644 index 00000000..1d5af5f0 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/src/Response.php @@ -0,0 +1,109 @@ + + */ +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 new file mode 100644 index 00000000..9d726e8b --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/src/SignatureMethod.php @@ -0,0 +1,78 @@ +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 new file mode 100644 index 00000000..2e87aad7 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/src/Token.php @@ -0,0 +1,43 @@ +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 new file mode 100644 index 00000000..9303d3da --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/src/TwitterOAuth.php @@ -0,0 +1,727 @@ + + */ +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 new file mode 100644 index 00000000..03b8e3e9 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/src/TwitterOAuthException.php @@ -0,0 +1,12 @@ + + */ +class TwitterOAuthException extends \Exception +{ +} diff --git a/twitter/vendor/abraham/twitteroauth/src/Util.php b/twitter/vendor/abraham/twitteroauth/src/Util.php new file mode 100644 index 00000000..b1c09a95 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/src/Util.php @@ -0,0 +1,122 @@ + 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 new file mode 100644 index 00000000..989f3406 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/src/Util/JsonDecoder.php @@ -0,0 +1,29 @@ + + */ +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 new file mode 100644 index 00000000..b390620e --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/AbstractSignatureMethodTest.php @@ -0,0 +1,60 @@ +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 new file mode 100644 index 00000000..18a1de01 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/ConsumerTest.php @@ -0,0 +1,23 @@ +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 new file mode 100644 index 00000000..cd7887ed --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/HmacSha1Test.php @@ -0,0 +1,47 @@ +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 new file mode 100644 index 00000000..1863676e --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/TokenTest.php @@ -0,0 +1,38 @@ +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 new file mode 100644 index 00000000..00244e1f --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/TwitterOAuthTest.php @@ -0,0 +1,397 @@ +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 new file mode 100644 index 00000000..dc6fa970 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/Util/JsonDecoderTest.php @@ -0,0 +1,54 @@ +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 new file mode 100644 index 00000000..23653e04 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/bootstrap.php @@ -0,0 +1,10 @@ +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 new file mode 100644 index 00000000..b592bc87 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testDeleteDirectMessagesEventsDestroy.json @@ -0,0 +1,40 @@ +[{ + "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 new file mode 100644 index 00000000..f18db6b3 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testGetAccountVerifyCredentials.json @@ -0,0 +1,46 @@ +[{ + "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 new file mode 100644 index 00000000..ba77e882 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testGetSearchTweets.json @@ -0,0 +1,46 @@ +[{ + "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 new file mode 100644 index 00000000..0a6471cd --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testGetSearchTweetsWithMaxId.json @@ -0,0 +1,46 @@ +[{ + "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 new file mode 100644 index 00000000..3e9c9680 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testGetStatusesMentionsTimeline.json @@ -0,0 +1,49 @@ +[{ + "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 new file mode 100644 index 00000000..6ca9d38b --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testLastResult.json @@ -0,0 +1,46 @@ +[{ + "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 new file mode 100644 index 00000000..67c47775 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauth2BearerToken.json @@ -0,0 +1,49 @@ +[{ + "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 new file mode 100644 index 00000000..82331b59 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauth2Token.json @@ -0,0 +1,46 @@ +[{ + "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 new file mode 100644 index 00000000..f112d7a5 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauth2TokenInvalidate.json @@ -0,0 +1,46 @@ +[{ + "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 new file mode 100644 index 00000000..791d8387 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauthAccessTokenTokenException.json @@ -0,0 +1,45 @@ +[{ + "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 new file mode 100644 index 00000000..47969285 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauthRequestToken.json @@ -0,0 +1,44 @@ +[{ + "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 new file mode 100644 index 00000000..1b91f186 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauthRequestTokenException.json @@ -0,0 +1,43 @@ +[{ + "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 new file mode 100644 index 00000000..eb71ec87 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostDirectMessagesEventsNew.json @@ -0,0 +1,46 @@ +[{ + "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 new file mode 100644 index 00000000..a303a6d6 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostFavoritesCreate.json @@ -0,0 +1,45 @@ +[{ + "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 new file mode 100644 index 00000000..0d0c8785 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostFavoritesDestroy.json @@ -0,0 +1,45 @@ +[{ + "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 new file mode 100644 index 00000000..0637a088 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusUpdateWithInvalidMediaThrowsException.json @@ -0,0 +1 @@ +[] \ 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 new file mode 100644 index 00000000..577c6d51 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusesDestroy.json @@ -0,0 +1,43 @@ +[{ + "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 new file mode 100644 index 00000000..156e1ba0 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusesUpdateUtf8.json @@ -0,0 +1,45 @@ +[{ + "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 new file mode 100644 index 00000000..97867ada --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusesUpdateWithMedia.json @@ -0,0 +1,134 @@ +[{ + "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 new file mode 100644 index 00000000..ce538a2d --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusesUpdateWithMediaChunked.json @@ -0,0 +1,2392 @@ +[{ + "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": "command=APPEND&media_data=%2Ft2vhfWOerfIY22EHX5DMlPC1hyWaPi4szL5nWUqN%2B%2F8EmjuQWX%2BTUZuVRn%2F0ypMS%2B52a3rrB8XwMbC3QFsw5M%2FiSEVRgQHNcLX9W1xXd8NweikwF4JC1YJ%2Bp5LI0Tr5PJX4vUElmtkxtx8FBU2E%2Bgc%2BC5xJdWrq%2Fil65a1XRL0X%2FXF8kua%2Fl4d3hQPxECF6NCbv%2BOOP5S2SREDL%2FvYIY%2Bz4qSpBfQR8uGIVX6fbf5fJV%2FfmMXJ8%2BCITDvuzv9ShZf3ckImrZAPblwv9yr%2B9z%2F%2BQlT46qmNcJ3qb6p6glK8YjAQveQSiA%2BtvglJezOyj965OWm%2FNSLg%2F5WZdgpPtPbv7LRx619Yqiv1b0rVFVrpVurS7fIQhkGObPL%2Buognx%2F1zwtS%2F6k63EnPn0EjIaXXU3NZDcjL3BEZkCzGn22aT1V8v7q5o2yfnyQRRpp54frlmyjRrorVyz3%2FBJdx%2FtzX0KfFSrxKtl9i%2BEfja9l%2Fa%2F6tXWDxFtVy%2BSv5fXXZnN%2Br7W4bPtKrU%2F%2FbqrlXWqjq13W9cERI21%2FnfL7r5ST53qrilUEXU46%2FVYuSCTxpjF9CfYrDuN9K%2BK19e2%2BvfW9dWvr1rB14sNLkgKIEdSY377ut3CyZeTyUVK91H2%2BkTMY5za1ya2tcM1i%2BuX1ar4AAAFuEGaAQBKBX%2Bhd6L%2F%2FQj6lYv1ixH9Kx86kT%2F9cupavwRXfftX%2FVljMV5fCKv9f%2F%2Fq%2F%2FambJ9f%2FeEMvz%2FvmHfnf1q%2BL6SrXVDte7q9Pgk50hrMlF%2F8unXoj%2BpeGZ0vfeKldX8YsGOfF3phDr1ZhLr69etz9ep3rh3%2BtSdr3Rv0rJPUoYVhrMIXqWdZ6vk9%2F6Nul2evtGGSxWAsfibhtWvojZsNw1qK80omXykyOerXEq1ULZPn%2F%2BbHZcOiKOW9erB3%2BuUlSuxymILBetXfat8TXE%2FrlKT3LXoL0t93UNOL2%2Ft3BFJEbl%2FZ2qUFRPxPfy47Fffq%2Fur%2Frnx2j9jt5V6t2ssV1SLL9SJ3VMvzvqWviFZVq5jFfr4lYv1iu0SLvFd1y%2Bix%2B%2FnVmEuv1ZdMrv1i%2FXq9WMJLc2v3636b9aq%2B15viVYq8V1YJI9%2BhsDNAePJ6deSBIPzx%2F9%2FrF3Ta1b5u8corg3Rv%2Bt3eOy5J6gnV%2B1i7V74quZdVffQiveFd89WiP2hOXeT4r84hbpv9v1devfJEf7f9XPS361SjCKVhb%2BTy%2FwTTT5qeXYZKwGU3McFrLIhoZ0H77C88DU2AisIE2Y%2FNTGav2tapovvvtSA6aYd2%2FWsct64tT10yt%2BtVf6vQzdONXopwjZMFC99izBPyjr0nHdIfrqz19VRmMfq2T7fd3Ecr32f2RWt%2FTvsWKVxs%2Fb5x0xop%2BA9herPtXw%2BpCFhXsN546t58%2Fen8cuKS%2B1SivXqqq1Y%2B0V30sx197%2BuS2Prrvvd4g3GHZTVq7fCegnadiKk7fKW0eOrNzWPmUnpl%2BF6VKuqjZrEwm8h%2BTx%2Fwt0DDcJbavdiUk97Hf275PHky8n3756s0Q1K%2F2sGvoEXH335x9Tp%2BvXBD38RLTrqhWf%2FWXpAku88MvJQjKl9dfZiy17vyfH%2Fk9dd1cbDJSHtVNsqpl%2By06f6v9AusONmzdEGnB%2FTrdP3BDHYzkYXGyefrWnsEfH5WVuUPWDYcmO61bVtY%2BqDZl2r8%2FatXrX6y6foju7V%2Bm7%2FXr%2F29P%2BCN9slgccCh2Jt0rdM4Q1eTgdtapPfV%2FsEgm2iK%2FXf5TFwpBZbW%2B%2BYQFdrbJ5XpUr7a6J9f%2FaxX61J6u%2FWv1tXqySmva%2BlhHp6fdBwn%2FWVP17BKQ%2F2BUBsZMY2%2F3%2BixzJ8u6qCWHMtZ0YLMaVpB8snn%2F%2B%2B7%2B8nz%2B5t5B67zRsdHYYrsEmTfv16X1SonrrtWr1f391z%2Fonwojr1l3XotavBHbzSfU%2BCQ9E7p8nv%2Fs3L%2FhrapOkJq%2F3aJjbvZVrdhIhI6ATTZL17K7OVn6wfEyLEYlYq3Wplq71S4jVhX3pL1w8sEvG91nIcfGZPbz8NY2KtPUOKd9v%2Fk8vdn0d%2B3JuT%2B%2F%2FwoUjN2cabm9u23NRnVl%2B9DMaK2tJ8FpC06Hfl2E46QnnGpeHtUGu4qfRMvy7nzr6BGdrVx8hG39gh5csTXN5j7uvXD9X968EYjdp%2FX9cK8IFtVKK3vo5f%2FVZVqErWlnxfqz8936Z%2FRNvQXsEDlSTKVJ%2FDPK%2F%2FBgJGVv7okr%2BaiajtmIeH%2BGiNWqQWlf6XWWk7X612CgrakI6oe9ZaNl7qw7%2Fouvf9Yqur5JX9UWv11%2BsavIInxFq5bBEdhyVar8EekL8ZXhUir6Sqipnl9b4cx43eL5dpV4ZLNu7%2BW2pPX9VYInz%2FijWzggCvDel2q1cEM9Hfnlk%2FS%2FXfrb%2F%2FBEdSfSBs0tPtW%2FRNwkwjVbovfq%2Fv0R%2BpwfSy6rL%2F7s3M9eCQtKnKvXP%2BtSeCOm1YNjeuzY3K1v6%2B66%2F%2FViVfo%2FrHav4S45UN%2BWvRZef3PKhDfr36t%2BXnh%2Bsv0fWvZrL%2F%2BvYSUvznb%2FHZvD9V79Eu%2FEE58xDTf%2B9%2F9ykHafo9dFq9itP6v31K36vXouJ81dLl%2BiQ%2F16Yv0Sv%2BiwjJ7da%2FMjP3JLWqOy%2FBEKvLLfAAABd5BmgGAagV%2FoW36sVa5qvEa%2Bbv77Wv6opa%2BPu%2B1Y7%2BJqi%2Fk7WsRiurpa6JWv%2FdX8IpayeP%2Fk8%2F%2F%2FtctfS1drVetfrVetdH9q%2FRvxWOxWLbHeO7Wu1u91IoKiVtsqYOY74ZH%2BiStl%2FPM0KnwUeuFRzdA27GT9J9sLdNIEjQFzPaiYyNIlRGthX%2FCikTCSpv9U9u4rrV8d26%2Bl5a1Wv1SJDOmUVkzR0t0MWlW1ahCp21gitICIS4Pw1GQAGjYl6%2BRQQ19QjjZdJY60Np3F2fogM6YcGpVggTfTlSt6YFvh52DS37tYMnrt9B24FzRZHhqjRHQaadJiIhWpgwlp6FboUtKrWsJLXo%2F1%2FJJqtKt9qmBhIl%2FU%2F%2B1%2Bfq0t91WqRfVn6FVS71irrXaYJhbpaK97uwzH3l7TfJpldLat817rLvFKb77q1TnyKRPVY7tSLVVhLr97fVW%2FWvmVv1sdN3ilq1y6VW%2FWNiPtW6qX2iN2rPurVu5fVuutPHSzPMn7%2F991Tfq17q0l8xHf6lxjNMzrsE0e09GqHTrsN8z3UhuNxf1eOV3Mdu%2Faufr1Dsv9%2Buu%2B7HdjJ5%2F1Uqv8q565u1qr5Vd3%2BtYz9%2BrF2CTn3V2ci3Tf9rhc8w7yr1a4TiRC0IV1dX332CEo4DwVw%2Fvw77BHzCoZZpzOw%2FbMhfZjY5sqHVODdNG0rq%2F9cP1ilwh%2FRGr1afmvmVu%2B6ut%2B9vrB%2BsX6pVs5VGMf%2FOCbeWd0sHfYT4pxgx59oF7dAh0o8BUPgj2cbJGuUM42X48kv3Fj%2BEJhuQhFVewUykp7ayUzkNKKvWLv9axX8qsTX%2BrfrXKrHNq3xPa12rXYYuyahnVPraGYf%2FY6Y2giGmmo5mVnQWPt7Tu%2BzkUNpr%2F%2FwVFppdtdp0y%2BuHYZu%2BrZUUyv9hjd2CjBGkilc18cH1sHWOnwR3MaC7d6v3LuYfYX7N%2B5ulxVa19V6vVq1epxSqfCVK0zttBPn4e%2B%2BxdEgN0sM38qpPX%2FDtiKcuPwtbMcSZxkeUA19LGJq58EcySqxfu7XtayfvfhfOo7uh7%2FK62cQOxF2%2Bhxt9vSp7DMo7Ugwu%2FHini2FcInv%2BVF1ZSFglxKYTznS%2Fp3Bfb0xyzQe2o9C%2Bn9Pgq3jEpzEmVzx9dlnuu%2FiP1f9W756vtamHafpLqwSExz1BpB32bYpvsROY1cjkn6oSx2jW7rwRavM3YIt2r6l9X%2Fq1E9r1SBJfSru%2FVMDuJ9bY79RPz%2F9wSXe%2BCd9gisRkC8F%2BYj5Mk%2BdXwS0rRMF2HoHl2777Ld%2F6Kxu8TKLkhd799ouXZSThAMeN1X5Pn%2FNaS9rXZ7btt%2B%2FVq%2F9a7WdXrl33J6xrJ4k%2Fq5%2BTK%2BVhE%2Ber3vZrzSfr0Vu0Tb9dXcifKSQvc3zdIrfrV%2BSk%2F9a0%2BCLu3P%2BC24r2b8Cj1%2FNH0L%2Fz1QY7r%2FVmJmYv0Jw%2FDdrfVs8W2pP%2BiSyff%2BKjWjBg06TryeWn4TmxgcLG6tKT7%2F9N4Lp%2FGDbvpsLvDnlxXpr%2FwWdzNGhk3r2bwwHfsElEc%2BgP0i%2BaUMF%2Fa2sVyQrfosX0utfrB3l%2FX5PYjNQ2fRW%2FLY6%2Fm8sF5Nq%2B1wQfgo2MmeaeD8mtU%2FslBMaCf6PX54pcjJv4TNoeENr%2BjMfk3kD78EZabNOatf0Iqk%2Fp8FAnNHx0YmvCghcxx6JF032i2r1avVvCOvRmr1d%2B8n35S8v%2BbRoGeH1yRS%2Fv%2F4Ic27fomW98svd%2F0fDL7r4JZQQFBXZbuKtT19W3%2FIZ5BdAP6xfsrvm9FqvBGaRRY5dorbxXWxVq43UjLC%2FL5MyrO8mRe4I7ZUXO%2FLoa%2Fr3Yq99jYb7XLL%2B14JMyVnAqsv1%2BiOVurn5CZs3vzeIKzOY7T6sF2tS07fmyU9rXiqK1UUr9d3u3ye%2F0I%2FgjpLte5q195fRouyHjH%2F92Zpp6Nr3eO0sMduZOe%2FQivf396WPCIqhLyjs5Grv4hEhfovfopAfo2qvv9Fue6sUvNVv1aq%2Bk6bu%2Ba9V1%2FcN4EAABsaWJmYWFjIDEuMjgAAAI8KSCUKDcLDQLIQzBQjCQZhIIjMLKzi98uMnN5NZXGSi1Xu9yWhOhy%2F9I%2B34P0PmLx8u%2FZm%2FP%2Bj6u8ZbOXlDvo37N%2BvD49lQez69XyroN%2FKe%2BeOyRnnzo%2FHkfz%2BlpfrNZ7pUP%2FM%2FlH3%2FUN37J0TSH7bQH9vpGCgIPf1JCKQkt8wly%2FbdT%2BJqH%2F%2Fj1UdSpTLfyDAge%2FD6zE%2F%2FwAHo8GIKN8qCm3xeMsoMTlVQUp%2BzTUEcX%2FObv%2B2lI6YDNXfaHgtp%2F%2FYARt13exP8NV1kN%2BMO5JuoYG3f%2BbRpKQpzht5wcxn1fxkAcBJBSULDQbEQLIQLCQLBQ7BcKhIIlUU1zkrLyJUkSoy6lZchI6D4Fp4HoT85xrmWqH2L3Y%2BPC79c%2F5%2FL567dnuzr%2FXPpfy8vaMmoabLu4ZcKOFAUYSWFwVPw3xBQyxpO4w5bCUKRJOhNch7sApcsBHmwraTORr7d2LoNQltf7R0C0toXv%2Bf3UeluE4tTrrflXtwwm2FwCf16RDNj57e7LYcvQ5XgEge%2FjTASmExmaF8MZ8PqFlkvsaIT11FXHbZzuc2hDYlgqtGEo5%2FNStxWLfnr%2BbA%2FZ1ZskIg4ABJhSMSEYKBYKBgLHQbBQqjQTBcKhEShEY1tnN3zJVReWvJFBktYmh%2Fj%2Fi%2FntGfn%2BF5r%2F466f42Dwn4eqeXIPRVXoysocf966eztTqjmKTf3VJb833nlfKvxvMPwvHecowjEnQfkz0vnVAJ%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%2FZBKeWu77eHYBn35gX2C4qtgte0pSherZJS8v%2BPi7cWw7rJ2sU%2B4rAcASQUmCgjEgWIgmDAWOg2CgWCgVCwUCwlCQjCIzC%2Bvy1ylbvXeqqXuaVk1OZeyXV1J0C6fw%2FkH8H83%2F6Nu3U%2B95ez%2BF%2FWOq%2F3z147Va18HLtzTRTLzjhL0Ojqlsp6TTD%2FC6tNcwVreiPqt5Xpb9L%2BatMfApfmH1v5N%2FaKavSF7UjC%2FP%2FWvigNDAOkVGyHX18w%2FApeKVgEjwr%2BOolg%2BPZZCBJhY0LvV2cMFcjX3HNvm%2FOlJ5QKiZxCk7NBXJyZ3AA5lQiJ%2BqmSn3Pg8ZRN4%2B1%2FgZeSqgbzcH66pfjLWccf91ruXf4P8VVfK%2Fld1Z%2F0mkBwAAAFvUGaAgCKBXRfr9CYvn%2FV%2FjK5v%2B%2B4mir9eu1udFZPz7%2F179W9vvv9YuSRa%2BLWLlr%2BjPie8UT8%2FfT3xvffaIb9rL1BJ47hx9c%2FRP4JMaQrDmta4IuWgZZ05l%2FrW%2FV8JLX66tc0lCM3JeqxX6t2vfE%2Ffd%2BCUtAJo7FK1VUQN8Zf5K%2FXOnuaPFz3fLDOttE7tYP3Pfl9X9XdyUX8J%2FE9E9q4VqzHLb4mX1Y6Why%2B%2FVvkr167VpL707QIa7Jx9e%2FV%2B173Xsct8VuT16ifXX1fdXjuVK9SpXqVMQv6v%2F9K%2Fa92tU7%2B1y7VyrLe9a9qW7xS4onv9SpUhNjsV9fr3axXaxV6uxi3r179f9EZPP%2F9CV6hyz8q17J9f5%2Bo7Odtf8lBRq5vi8d%2FH69XSnT9X7U9%2BpU77XsU7xSuhyl%2Fu1l6Lvl%2B8Uqr179WVuv2IWTUEnjvhSnqilTFenxZLDbaj6Hh%2FdZGb9exSu%2FV5LvQn5bL%2F%2FyxISWqf%2BtXBRy4y3Y2C3H09IaZLvONKWQ1o62j9B%2FdYv8q4Zf38N5s%2FvjzfFp%2FBJYHJL1%2BrD66m3Xqte7r65e1er7V5PV6euG8sGC1bbNKgvVkpJX%2BCOh35Zf%2FcExRxC%2BlOMG34JZyQcJr0GrjugLh%2BzGbPn5c8tealKY%2Fks2dr7s9Vh8TJd30q1it%2F1B3forv1Z3VrLb4LeEzDNWgh4NLXL8RQSSdBSIW%2FjyZUYYdhJ60R4m1QZe73tU%2ForheG92VfcgyUxq%2BEYzl8n8dMFZf%2FrL8xHfy%2FgiOckZyUufmIte%2F179a%2FV69a7Uwq9XY7u6MWM77WXdetSrXBRjQQEYNwJgQBXYXe4b3sa%2Bydml8UUZbIAuyX%2BGKBs2Ry%2B4QPj1NLG0H%2FKS7ofwQyigZbkQEAfL8tta%2FRX%2FRJSeKsyGMyVb15NlPly5I1KcJdzyWtd165V9Cll9DKvw%2BN561rHTxWiAr%2Baqy%2Bv4KbNuQojCdT%2FQHNHc7BEeVimO35DXp%2FDNMtPKZS7f15MoYDSeqsfl6q7BDxgICizARuvdr1WvK9q9ClLm1qbwnonxmv7XXY4zKWEzGt5Tq8JUExvDA3Z9%2BGz5DLS%2BcYURkbzfwzKbPbB01Gz6ZX16LN%2BKIQVk%2FkxeGtiHLmsvLH9etdrVXXrl32r%2Bxay%2FWKr%2BbFLRPfXevQp9%2FaGsV4LCFywm1aSJ%2BXNV5IRcL4ePmPgj5wgCyTVZj7lQ7BIRu2wE42G5pYaAl%2BNO5hjuzEG8vq0eDvT5jY7pr2XGy%2Fzt%2BSiq1JVa1%2Br%2FrnvX8K42Di69i4g8AKGvoEHUXI0F8Xjowvy5v6BHIIKZQQGc7sPWnoLkgNrqhebj7U1uwqUqmf4cQ0vUMuo30K37u3eAAbR9X5CB9Wv%2FBdbGKEN9EX5RfsmbEasNn1SWs0PXhKhHAAClCN%2F8J7RBRSKhYMg0H92%2FxtgrRxAbTZov1pdtqLD7rP0ZBrarh5gwMYnGb9avEZKJRKqQvqkL6mvgu7TohvzxV%2F2r6v77NXGBkXq9E9r%2BjXJLk%2Fe%2BqVXqr1a%2FmPjQ8GpezPGQpPYXgoLQjUppx0U%2F1xPujd%2BXLT%2BU7UZhf6kb9SLL9X%2B637r7J5f4JyBq123Vwzi6E78T4%2BCEZKg8H%2FPX%2BP7%2Bcq%2Fu1snlvvd5Ns4xeYyfq%2FkItLf4Tu%2FmMt7BCe9WC3V%2FwXmxqLDtPnfdk%2BvX8hcl79bf9E8%2FXKVp%2BX0%2FcRTOS8r%2FwQmZXag77rVFYP1w9zdWdPruM6tfhg0ue01h9gJI3x9iyzbemkUhl%2F11rurvybqVeT%2Bv8Oat19ttasQQbZVctEkDPfXn5e5vBCW3Kt%2FuIu%2FBDu969Fl5KJF6%2Buv68I6VrcuMbtyL4ZIletDTJnk3Qmx%2BCTu7mqtcPhPuTJBGIMWfYS%2BpOX6luje7QlpKltXrXCat%2Bjfr0dq8End3PC%2F9Spwvk8Vv7v9T8%2B1KDklaYV2X%2F%2Bn%2FgAAAEM0GaAoCqBXPVjImRK9WP16T175LtXJfVu17J%2Bf%2F65zte%2FV%2BdY10V0NotfrcktE6XlV3cnLV9qyvWKrUhfqxXF47L2C9aqXFeK66Vj4pXcH9etVL8TVrWMVfmO5U77r1pa4tcu%2FwRlZ39RPb9QQxZmwpBaQYO%2FwQT6j6BsMZqaZ7r80a%2FRNnYZ2kq%2BjRFxSPkg536rW%2F6vzq9DiXdileEu%2F%2B2%2BWrV5bk9Xq6f3fgj5LSZr1VhuhStfWu8nz%2F45RXXKr1d%2Br%2Fq7FZc9L3dClv1lVE0M7q4vf658QtXXknECc1mFfRMvF%2FrLHeXRP61%2BuVerHdXVq5V9q430v6uSeCLu%2BX6yov%2F9Cvv5VqQdlz%2F6v38SrrTP%2FJ%2Brfq%2FeKX9X6v1OitWvY5bEwr7V%2B1gv1rFLc%2FWuqHLeJ9er1eamwl19vlerq%2F5vJn1ZXrlVyUq1%2BrOfFE0KJrlqWvVqHdv1f9X%2Bbunuqu7PWPamGYv%2BsX4I7e7fqxfrl3V9q42r9rlXS9EdK8nq9WbqsZmp3Wi9k%2Bf4k3c50qfC05DT1aMIKhJ6%2Fe%2F%2FBRdtrcl7%2FgkqnYbvzE2a7%2FPVYyNH%2F6t%2BLLUqTejon3%2FonVfcvr36%2Bfq6qle7%2FWK%2FQzvzjV%2BToqH89Tik0Skf%2BCEvNsH5LEtteHY5nwFYCYM89SZlTKjGyD%2Bien1YJ9aUV%2FV56%2BNoVOll%2F7w1QGc0goSlPjpCb%2F%2BYnGhpL6uPq5dE9q%2FPq%2BrivBDsOVQ3Zua2A%2Fk7RRivOdfMrLlkXzmXzWcIA%2Fy5dyWCTyU1Y7lT9ev1iq%2FYu5a9feha9WWrV69l%2F7wR3fyq685FWQqYYP%2FXEFchPX%2FYk1OvORfNbaFVhnnNP0tzTQX7DNGNr3%2FwzYl6v3WEKxV6y76q1V5%2FVyUvk%2Fr%2FtU2Tz%2Fyldf6I5%2BsF%2BESSiApI2jlgWH1f5zqsdEHS%2BnxJt3prEDv1WvUX%2F9FevXL8la5ff9fdqdP1PSeuq89TjhIony%2FZ7Ql3z%2F6s5SFKxdD93fmNkakrX0novcXXoneK1yf%2FotSk9l%2FRGCW%2F7hOkn7vs0YlNJf6%2Bq5rr0JYfC%2BblDBzLzo7sppHf%2FOZftxkufns%2BjdRN%2FzUB2CGAfl4ISnsggNHvUSQzWkR65T0mRUXoEfSSwr1evV%2BperCle%2Bb8klpbb9%2BH7oualx%2FFKOqSoSf%2FFZWNcaRPi%2FjkUtf%2BCbRsamFtN4v0TL9dbvXDJ%2B%2F%2F6K4%2BCS3kGmFa4Ib5RXv2YggN%2FwlIPSZd%2F6L4H1MVbVeiN3Uv69Vq93Ivcuhlp77r30IYZS%2F39erkvokvdWa3UEXGW7gcN1clyWj9jlEDldF1pVn6l16vXtpf%2BjOq5PR9dqx%2BCTR1l3%2BCHqvVavXgize%2Fd1vy1P%2BvJ3wR2qte61rvtXu%2F1lqkhHb6%2FSF9f1Y%2FV5LWOViM3q%2FuCLLDfb6N1QAAAQDQZoDAMoFf6Ex%2F1yxni%2FWK%2BW7V%2FlkgQf%2F%2F1f6%2F%2F%2F%2B%2F1f6%2FVj7VId7avvJ%2B1%2F%2BvjtFY61bnVogQtc0t8CHk9P%2FVFfyeXwIWiP2rHcmFderVdWrviq5V6uKXX69Xr2IJSfr1dL3d%2BuH7KkVtNYdZ5imWRz%2F156%2BOonQypKfDdHDqElSf8bmhjTk%2Bif9v%2FJIKRHe2vYSV19v%2BLu1eJ5ataibBdfPHI3t3YbWK7m6XKp%2FCdcu%2B5uLxC%2Fr6S1r9e%2FX1esV%2Bevuyf89Uzb%2Bv%2FXpoM7wU69Wd16kT4mT17uh3y%2FWYb7VirWVXVnr8YM2W%2F7rpXurT%2FdSyeu%2Fcly%2BuX6uVp%2Fqd4dnr9RV9%2Fr365f9rLu75Ve7qiFe7XUvS9a4nq%2B6L9P4W6NUn9ke8qK7Y0NGNbQLXqxXrF%2BtXX2rF6r3Wr1XW1Ejv6r%2FWD9eqzeHUhv1c%2FPco7v%2FwRXptuZPP%2F%2FWu3lgwP2qdbPcZkgYifP32TjdXgQlBHWaEpda9CfoteteYjcZBU%2FhK%2BwCRq5gwHYI7Es4YD1erd9rFXn6%2FmoUl8FtJBv0GOhAvfouFWial3XvtWrVWVtr3yd9VerO5PVgvRTlXlIm1%2FJ0Mv%2BEtDe8qT8EZc%2F1%2BCckiixyr%2BpLBDzXKvXv1yqtWrkuVRfc8vLfq0nicvod7P5Z3NsD%2FFcYLj7cogO%2Fwsd9ktakExxuKioL16NBfn5UORhP%2FgkpMHNXv1g%3D&media_id=1254206535166763008&segment_index=3" + }, + "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": "command=APPEND&media_data=L8MbIiX2k1ohoWDf7r67WKrx3LeEc2mr3dXXrh3IX1%2FcajIHeXy%2FdUy287%2F5a1vz%2BxyBmU%2FrzWEOkPr1avmL%2F%2FN6L0nrPXs1Nfzd1Lfd%2BeqRwwYxG%2Fuyff%2B7Gg46Y%2BisXTS3J61Xqz9ar1cfDGsmapqkXf0X%2FXZOZuyWbHbfgiKlav%2BKy7Gjhcx7%2FWCrDfjpjpw8wNV8vgvIZSlvQ6%2BMFB6a8FtUXqh5VCT%2BJyV169J6Ky%2FRur16vOVfQEkmcX%2Bvfr36t%2BFb2t7NUAySaspnJ156oJI6bof9X7JWv5o%2Fj%2B2c4Tf%2BC2um2dmzOn6M5%2Bu%2F5ZqEg%2BvFlzpXq33MmT%2FRsq9F6rv16vZJae%2B6s2an9Fb82616wcqmSnf2jQfkE1S%2FVx8Eld6r0Rju%2FRGdrlXoXGK85lmkrxr936sI6Vn1euHrVrvJYJKOat2T79c248ISB%2FBGRdOq9e%2FP69pv%2FhquvpxhODISol%2Brr1YLwRW26xbdSc9Nvn%2FP25Mbf%2FWXaxdrX4ZzpJUj%2FN85pDv36K%2FL3eJCFeuv1yr1qnejVfm2bTtOT32iveXt%2F6Ra%2FRsu6J9%2Bubs3q%2BtVw81ampUV%2B%2F1l2pgddK6VvpYuiVTyS68u%2FVxoVW%2F4Ie7vccTjvVeuVa%2B7MfH%2FqzAAAAOyQZoDgOoFfdcV%2FQhcRFq7Vz9cq9a%2BNkvuVvCVE8f%2B6iXf%2BrKtX%2FVzvtek9XehC9J6snteuUEfcsWq%2F1hjat9fS9cwnjifVeEv3%2B6tdl2r9zeuXf69fr2O1l%2BCTdO5fgkmtPcqwnVLKNMNfwQyDFLa4fXv16%2FVv1bHLjFYJv6sV698R1L3a98tevS%2BvVatjucH6uv0O1RfJ%2F%2FBCPGX1tI3FHasdr1DufXa9Vq8l%2Fq9eteqyltdd36soUuKW%2BJmu7XqtY1cV3%2Bu9XdqxXq9esXcwS%2FWX8lE%2FhO%2BzQMtv%2FBJeyz9q%2F6uXfLJa276VdWX4R%2F%2FWv1M2nl7VpuVX%2FRMu5N%2F0fPI7ia4lE7FcVcnrFXrh%2Btd36xV6vXrKvHSjBHwoTQ7etpfwzGhp%2BvvjT4%2FN1WrwjJnlz3Pn1d%2BsFcvMXJa9Vq%2FCPc%2Fq%2Fzd%2Fq1Utt8EXLnVW9K%2F17fqJKeyEvbGiFsmeylHjMv%2FqQyNgnkv5KvxVeluM9F6vBfs7ysa%2Fbn1eCchsYDRTpD55fiY4hfPCwO%2FBEUhBDMM5%2BXYamy%2FsukK%2F%2FBbyyYeUSI3vzEVbPqCPsb12FTktALQR81GSghMZat%2B%2B0SprVl2td%2BEMl5Pb%2B7x39XC9F1XmIlGwLt%2BisUX9bxE0yFpCCme%2F8Et9vRUBHS1iDs7ZHSlDD3PXw8ntcaBb3Lnr5TEucny%2Fqr%2Fq%2Fasdr1XV%2FrUZ4c2j7r4%2BPXyIvklDAW%2F64frVeaxr7p70rHf4JJ%2F7mT598t7uX16%2FXKrXMl9alFLJaJF33%2BXTnSF85V%2FSJ5PffyWmkD9UTX4JBKW7F%2BEiSGpbtUvi5IfLiA99rBd36tfE%2Fq1k%2BP%2BS%2Fz1%2BZluyerVdeCLIvsCWCSSNly7v1c%2FWuw35dX3tkQHFZc%2BrlXVnrGff6ve7zeew9DV234IaTHb%2Bfrl%2BCEqZGeLsEPNL36J34JJE9KKvRHK851Lmn6vJ7f4i5A2gFj4RDS8B%2F3JX9%2FrF%2Bid4jEXLat3Vvx8FiriPR31eYj2X58rEbjRCgf%2FCetJjkINeizdlM969avyn2n%2BrF%2Bsddr361k%2FP%2B%2FQjr9F6%2FCxTx90VfOGAsEPlx9qZqu%2FVj8t7lIP1b8pocQvr77k8tprVZBMnS%2Fl3uulbuX1hVqspPDIiOkHQxSb9oyccv%2FvfnK9Y4aPyXl%2B%2FxPna3ug1aI5Gei%2Fib7q%2F1gonvv5CaN3aspfaPKT1r9f1as7rzCI9p%2Fr0to7S%2BrdXd%2Bit30l6rXderD65fqYsnj7%2F1Lc8AEkVIwoNgoFhoFioGAsJBsFBMFBMFAsNQoEwoEhiE1jM68ZcUVdS6lVcqlC4hwPzn5znH%2BUuWsi356vS%2F9PazbyfiuFG8v1t8Ks%2FJfg31Lh434lkL%2BLrrBpTddvblmg%2BWt0P%2BBxrSlf5f86qmqGijionVYn%2B59U7M3qcetoLJNoGtVXle0veAttUd3s%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%2Bn5Ya9GkU0xFvOkWjCSXi7FLAsn2Zlp5GOctEPADgASIUkEwUIw0CzkGQXCgWGgSEIVCImarJmJkUiYXN2tmuZM4pdV0O71U2797r3SP9Go5c6G2ci%2FqmGq9dffwXTrer7zyrvmaiirkkJdJvEpsU4rJ3d3FDQ%2FGXOsxoo%2F4A1zSHJ%2BAIGuk9t9B4pzaqK7PnNepFOHf93%2Fuby%2BaV6e751Mwdv8QO096drUmnUa8JxZx6%2BE79tQghrDrn9f7X73%2FVAGmpiYO%2FDJyhbvJkBla3IbmqnCEaOWoL681CVggQzaxwpbIFU6DUQqT0t0ot53DqVWJfv6N9XbiNrvVo6rS4zT%2B%2BX1A4ASQUjCgVCg2CgWGgoCwYCxkCwkIoUCwlCQTCQRCQRE2tWceLq8BKXS0qpkVqUjofnfqb4%2FlNm%2F0J1f0vXO3n91%2FxP7tzD6Z80h1cw%2FuOiXpJnQim7Sh%2Bx5MYl8BlpH76sVBLy83pZtap1Tk3ia72qgc4ccQNrVMTa3uMbA5zxXLQ0B69voFXoLx6LsNzV%2Fl59nM0O1r9xxWPlvHyz6sqjCeHC3pv13sBagBWtcEtBmS06k%2BQGT1OY08lvqDf1dMI7%2Fdh3aEIbelbXEuOjZHE%2BqzsWaOcGvDJ9sUgY8g2ciiU9360t%2Fb8wOABJBSQbCQTCQLCQMBYSBYSBYSBYKFYKBYKhQJBQIhIZhTaYpffVYqwlXUmJSpcqpfA5Boj55yTYf8D%2BX4zd5fqfZL0lku4l9u%2BuSPEwbe2Mn0mny1RrUdvhLVjZGOuk%2FtP1G8l%2B7lK5XW7a5wbRH8GiBcbQmC0ZZyETdfz0H1J321nvmDZ%2F0yePZPX1zzAEErDrvxhkZon88gBzO2Gp31S1AAPp2kxbc8nieBIgHyAJokJpLmuFxXicev3cHsF2cP28Heh7Lpj%2BD6UX2UVR6MfKSca3YW8igf8phcpYkPbjGxhjskRVo%2Bp7YOAAAAGQUGaBAEKBX%2BhMX6xfq1evYjrk%2F%2F%2BVWKvteq16Uv%2FT1698T9dq5%2F3%2BrZPn%2FWL7%2FXu%2Fpe9%2B1b4ihXV%2Fr0XkyXX45ec%2FVrvuStesUr%2BKk9YtcV9r0wpfyc9EB%2FElGmVA9mzmY%2FZBpo%2Fv8nmh9WP1yr1T1cm69jl1jlvVS9Xq6a5aqvvtWBbV2X%2FX77Xq9U8lGd%2FSxWKV%2Fqmm9Xku7Xrte%2FXLuS64j9e5174xcqmf9eu79a%2FViW5hXp%2Fv9dSeCPkY5u8core7%2BL%2Bf9Wq%2Fb%2FUtIKWrv1yr1ZQgnnv1erXENop2rzGiVTQCfrFPatLc19zXV35yrsEG96%2F6kB%2B8p2Pr9Y5%2Br9rU9cR6yxXUK9qT2MV3ta4vVIiGmZlLCDPhiEgwPFth54aIZjVaJgwCFcJf8ElB2BlzL8K83aaoSpV5Q6dFKNvyEzRbfrX4jzTw4hCZMVq%2B66XpelesI79F6%2FXKvNCVy8jAMLNuJPxRGBZQ%2BVQHUQugfl%2FvwTZTdTCUfl%2Bcq%2BmmteCTYcN1IvwSaHeL9SX4IyI5flXgjPtNMb9SkfR%2FBP5%2FP8ov1rylqO%2FaWxdJXambm1f1XUlrUlqRY%2BEZwQUMoqwAAY3cZt%2FjghJPT7yFRsju%2FktPhjPG1ugfzEqOzkKX%2F7WL7EyHQ9uXWv2QqV2Hf4JyYKRRY52HK9XfrOfgizDsng9XnIx74Io8y%2FKq1Sgt65KtZfJ7LN2ry%2BNsdXCRy%2B%2BUDLti2QSoDgkfT9vvAonD0y8qX%2BNmmHoaBI5qSnx1sDdIi10%2F%2F3xCA%2BZip5oEQIMX%2FFXmlYGPickZWpjYvPQMSCAr11hI%2BGCyvnig7ekb%2Bv3qra6BFJjjMylzlBXwoyq7u8cNnTn5b0sqSrL0g6hoyVK9VrV3fNV%2FEz%2BsGvsYTjQIDM%2Bre8fNhp8a65Pj9QSltBFCAdcMH0bC66LLkZOHX2CEweRKHR4PyyJMwIAr2Vp0969LXd7sF8foCj5cO%2F25%2F%2BjkRn8QS%2BL5EKP%2BaePr1CexTXPL%2BDDxmUUVGI7r4dTuOBa9VrcurlUslrrtZVichf%2FLlVqK3jWV9PYSJl76tbBKXHDYwKAdxgFXx%2FYog5c8cGDXGPspeF02XrNxwYuvVz8EcvoeErogpu3b7cJjUBFYhpP4htCBngAByiH4uwZUVDaGGdBX4sxzEkFSGr9q5OvwueNLaGAyr6%2BWIe4%2FziMhjLToIkNV30TrRO7n9FahSv9e1agh1bv6qxr9WHxV381Mnt7%2FYgkNyY3wkxcrl%2F7x%2FlyPDo%2Fbar%2Ff0C7iOUxkZY0qnnr85bHxo1rq%2FJrbXhvV9TYeNn%2B%2FwS7GyIhLQNC%2BL8KXqEDbR5QI%2FPbfvW6%2FL%2FXi%2BTERs%2F5j5gyRjYLCJln%2Bh0Cmtg1sdV5K0Ez%2B%2BgR4fBQcNL69xMgfxoQLud883qeql4X91f%2F3Qh6SsvL%2BCgrUMTMlJqO89fi6CHmhg%2FnGho0fCOCDTVPuQDpLtT%2BCHlxKnHKL6%2Fgw7aucxZUDVNCQz0%2F4I%2BH3GqSB1C%2BVmVmtfaptfL%2FL4nmY1tpfgvyHH6Gqqt2OWF%2FlOWl%2FwYcETSfedId6evnijj5n8ho0JxG739hTlQa4ctxjLpukozpedjbelhjoaoBxzbiCuP%2F%2Fk%2B%2B%2FLzkhpotq99KW9P8FeWN9prd%2B9LJ91rmIrO%2Fql0qE6ul%2BRW6T6V69X1r%2B4ITDfvv%2BLz3loXJB74RjBjdzR3JcJaLrB32l%2FEzMv8sjUi%2BXpv8pWNBEpyffr79b8EXaGWsta5yLjev%2FxcpBfPWVIEDujZzr%2B4c5f1YUOoIr5f34o2lMNNNulJ7vriO4YJM3fk918nfeJlPidJLff9X71uorzeIFifNs6rv9eu%2F179Xkh7k1ITCNl0pfX8hN06%2F1%2BY%2BO%2Bpov695fvq3kl%2FJvMIH4vxrDG3vrIQuWnl%2FvqvEYaT1FMXjNAR88n6v6s2%2B9x%2F3W%2BE%2BHlWW%2BPg%2BZe7V0tSv7XXq97T9HbHdOC9Y0q10VLzoxKt6yfUE0%2BEJb3serJbvJ596gh5JWNe69r%2Bk6nOo29av%2FwQ2DJFv1d%2FKrVurv979WPMk%2BXPw%2Fpvgl8ZaNtJ01%2BWfH%2Bqwv0fuWapXv1i7WWon8K7v39eftFOlL%2F9E6s28vX0iS%2FWLzEr3H1%2BoAAADb0GaBIEqBXd9EoXl%2F0IfN3iN99rF%2BrF%2Bvdz3P6tWG626JVz%2F16r5lMNfH4hZPXpdV7u%2FVyvXyrr16h36hSxHrVerSevr9X%2FWv1r9YRXgh2o5Zb8ENmlIcy%2FfSS%2BuH6xiW197S5VdWrl%2BrdXxf66r1aUR2X479eq1qayeTGO7Vk3aufE%2FG3av38QrfJ%2Bsv11d16uSerpqlcmte%2FWv1btarlv1arVvHav9XP1c%2FVq9XP179XP1csVqh35Hta%2FV1%2BsX6xV6sS3LjK9fr89ZJa9XX658d5mvi%2B63N48hL1c1X9hmbeqJlGe8m1WqxfrF46rPIW8mqlf9eoUr7XMfrVXFeCTH3VoUvwUV7f%2FJNgKJn8N81FYfpHtX2uH6xlerEn8X2rXjter1d2rV6vV%2FrX5vG2r89fH9PR%2FWvz1pE%2F78%2FKZIONRp10%2F%2BC2imH0DZJWPD89clmMmNRucgP4JKkGDv%2BCTbtuPNJe%2Fkr1qmfXq0nr362SX%2BesyQZh%2F16JF33l9%2F7L%2F335zuffr69%2B6JF%2BvvSktTt9L12vdr1E%2Bv%2BT16T1YfPX7REM%2FBeVhZ6ZPwuVx3T9eiaon7156%2BdaG6edvovzsxNk%2B%2B17un7q4J6tdXLd1avXNRPz15fNkbX7vHxQf5vHqfBDIYsex2jsbnyGXfb6uvNRJseX9%2FWXrJ4KK30V3%2FWLqWququ%2BYvh1eq5%2FWKr%2FMR9KX%2F3RYbJ%2B%2F%2BT8%2F5PDm1JnUpas%2FXujd69FctX%2Fo1ZP736u%2FXq9e79r24lP3cl5PL%2FkuT0V5LvXJ7%2F9cljlFcVXd914SpPQDk5AlWk%2FXnrHMZ%2F65V5aHVJXXomW9evdAdJJu%2BQVv5Zr77vf3%2FPWa6fr1qrv1iv0JSg%2FQh6sxcqhJX797frEGXuFGXcriVaS7vuTwrMZa5zLcr7CG0oohgNWeuSi%2BvWC3fXq%2F61%2BtflI6Lq9csn5%2BSCEqa7G75bRWO1S991fi%2F0tXqCLu%2BX6JqvJSHAgn3t9Ey171d%2Biy3V%2FRNOXt7%2Fv69%2B%2F5SEvdXLxNeit2vfrF%2BsX6KVvH7tcq9a7RMPfJ9f9eCOgRo0q17hfoMrE%2BIvpcWVX79ZSeixfq71WuW1v7%2FOIWnLT99qQXwzhKev61jder%2Fq%2FD9%2BS9%2F11Xq%2FKsHS3apwXkLupNURpIIcnt%2FXfiK4dujf2jOd4AAABQ5BmgUBSgV6%2FQvL9cvlxGakR1fxK9jOlW16qL%2F%2F%2FVvk%2F%2F%2FXvtfH1%2F2r%2Fq74v%2F4r9Zfr3X7Xa27Vz%2FtWPl%2BWr%2FV%2B%2FhBa7%2FV3xOK8YqUa%2BI%2Bb5j1%2FDzDe91Z0yu%2BYEfdtnTAjmnOTvjuVK6X%2FdDt7y%2BtfSy%2FUyXT1fa5V6mTtW%2FWqHeVX1UX1%2FV68NeXGH0Y6bWm%2Fq5pXBfxws8dxEoLLXGTOS7Tv%2B17tWdq8grdSqZO%2F6tYuta7vif1rGL67%2FVsnn%2Fzeqf8EPkRpMPgljNj97QukP1l%2FJa67%2B1fvvvotX%2Blersd3Sl%2F%2Fq%2F1qy%2F%2FCK1Xqxfozlo7oVy8%2FdXXSLFXJ3YxcXdX%2Bsv1Ol%2Bru%2Bia9Y5Vq9cTLyL4917uq%2Fu7kouWif1jHcnm6BjLX6K%2FerwiSJVM6kdHRcCA5RCwlTjSeR%2BJkXY%2FB6RYL1yqkVwstcuk65ula%2BdWqX9e7WKT16XwUbIqJbRvXcfBLh5Z2vita%2FBNGAqemWDT%2FlVibUXdfwTY0cLmI5c8z9e%2BLXq9dfJFXVrqvX3dXVEq369Xm2aMehGwUTiA6Q6Nc1fVWCTjxwdJh8FpUd%2BpgQL5f1lwRSEpz8pfghMJc8W9ck1NgviuXLN2etcXKRKNXOMFn%2Fk6Ai4tnl9e7666VuromX0Xv1ZJ66%2FFUbBmGLMMGOGIuwxJ8eREcEA4Rftr8KAoVcy9IpLN%2FYL%2BRl3wnJaopnL%2FxJRjHXevf4Io9Hshoffghh2eQiZuQwDWpjBrXE%2BGYcke6%2FPXgioEPyvF%2BIri5890DNOg9gqm1qg8uoPbyhgYu4nb61ax36bxfVFRhKxC%2FhMmYs%2B2v0eD8EVHL6k6DgMDoesnv%2F%2FhXYQyLh0EJTGgGcvlCAkEBXq85F%2FHrnJ%2FX%2F2CTIoZbH5JL6fqrlE%2FdfJRonIc%2BCrGn5%2FJZaQ%2BD98hElv1t2vXy3wguXTfr12rc2r8XdggtRmIKBcfNmrKPEELhirz4w%2F2E4fgKOAGQIB2thOqGwg5EDQw1v%2FVztHY33mNQj%2F2XGmSW7UUVerl%2BrV56%2BeF6l57vubie6i7vvvb2CU2HEuDvu%2Ffd%2BCQ%2BgjrsNksHaKQV4Iyo6TNj9kybVkhDnsnaJoFsOQ6%2FfU6VY4i%2Fte%2FLxk3b%2BuTwvq1evV76RZS3%2BEDTtIl2AkOHNxHyE69X3Xo9Zf%2FscSWHZz5q3ui%2F%2FN3%2BrD56oE3Dtyv%2BK8dHC%2FaXkz0%2Fq364%2F1rL%2F%2FXq%2F61yrlXqx%2Br1pZPz9Vrv8FBXvXdzfE6uKda8UY2tFQUGVDF%2FJQSsffeX109FhMv%2BtivGkxc2nta7BDGIj7Pz1LDGDHrzEQcZEB%2FhOyo1RF9A9voZmV4Tykras6cv%2BT%2FkzCE%2F0T0vqpLnur7Bd3HWR87m%2FxO7uYlpLvv8k5icYOe%2F17vu7V3ffffffV1aIv9JHmKzVevV79e%2FVuxGzu9%2B5PRGL8ERYzv%2FadV6%2FFmzCqvvvtHYbDU9Etx7MtUHH8EW0jRd%2BCQx9pW7LvdX2rZPj%2FdKXu1VkE3Nnur%2BJr0TpPWCukWXffaEHbtltnfRb7BDlUZb9UwfCW1aen33t7JhFs1r2G4%2FSFvKSeS%2FWvfZCRwYS%2B%2B%2B1ersv%2Fei9tvCZCKSs7v9fhSvR7cJ8hEQl8mPtH%2BQhTHff72N6erhmxoNNvD89Za%2FctP8QU0POkQJ4gP1xEt6d%2B%2B%2FwSCHa9d1V%2Brnqj1IK%2Fll6XLvye%2F1wu8nv%2F36LkqFXV1AAAADIkGaBYFqBX%2BhLzc2I8R4jlwQ%2B%2F%2F%2BBN77%2F7%2F%2F%2F4J%2B%2BDlX%2FXL6%2B17tWPr%2F9avm7k9cr9Xsd4vBBWtcT8dqdtXS5beTz7tT2OW53QS6p%2F36K5jn06%2Bvfa9E%2BiRVavE%2BsX6uF6uVfa1Qrq1f6V6FE45bkl9rKXVe7vnxy%2B7r1dNZMegv9S1%2Brlf1Vd%2FXr367PVcrvtcK9ZiK5aL%2Bt5J1%2FuXF1Yu1i%2FWr9Xu5hCpL1mL9axS%2Fq%2BKWW69Ypr%2FWr9ZY7p2X1armua0WVJ%2BW4m5L%2FRHKv9cpPXKT1l%2BrBetWn1132udJasVP6SuqerVu5bXq9Wr1erV5PV%2F1i%2FVv1r8ORkaFD6uMiRtGD%2FxOej5SL%2F1SH75iSf1btxZ0kl6xSX569dyWrletirWq9Fr3V6V%2F4ITc31%2BsVXk%2FP%2BT1funvrl0X%2BsrvnWuWS7v9Fy37qRLif1Z3XrLsJcbCvAFu68JW6dPdK%2B27irabo46y%2B69RcJKJq5LVLt%2BrqG5m%2Fk9%2F%2Br%2FV%2Fzc0P3tVfuj3L5o8Lge0XwR8ZbMyRNNJ692rdq0to2XYJCuj2fln8oQB7FknhLKyerDV9NfjM0RffoqcH4Jiu%2FmrTfojvwS10sZdtIvrL8uSDCbm%2F179Wm5u5nvrDBPJh1az%2FPX7GZG3d9%2Fq3asdorn6JrtYL8pOOmNspYcnqm7777XrvV9cTdrlXrFRPb%2F3v9vO98lhOm9hzN5PL%2F7WLJ4%2FqHC42ygNfhxLj0Xz3XqVP7tmSr%2FhjHQQH0Z26%2FQCceifl2iAioCZs1d37ndvv9Hiq4iia9Xk8ht0hN997NvsOHW1X5qUt%2Fsy5qbluT0f5J6t4v%2Btbx%2FU1P5yKPnCf%2B%2F1i17otdnqPzcNlf971dE1fgiLDiBueBuPm0hsKf8N6O9ynn%2F%2FIbHwgRT5WyntHr0Z5L%2FYu616td47Zlrnq1l3XhIRKEAUe0%2F9lNugt%2Bt%2Btaf0%2Fk%2Bf8msIvObRsr9ek81qQkjV5P78khWO9eCMjS7fo9QiT99cmtfghk%2F1dz%2BtSeCYjWTN3Ynv9Hb9aktTt3%2BrPyV3Xq8nuNsouLgpWLxXsEVz5tcBJhSQKhQLBQLBQLBQLBgLFQLDQTBUKFUKBYKCIKBIYiY1zMhKqpJUySC63bJWpkX5HEXo%2B4aV%2BJN1%2F8TwL55H8a2sA7VJEzbn1Xcd1Pi2jYfv%2Bkujv0gWV37r9vXYFr6N8sWn73BfrXxD4KHxDxFqjdHfMnRXD3foNwZ7UO%2FS%2Br8exUhWOdr3doX74j9PjPyXSugJ%2BArbWjmVxxz57vnmTu6mB%2Bo%2Fo5LAUygFt3FlVAzS234x2518f30Z78VSf8dd%2F0e5J%2FZ6bixpBDgcsJFqpYjt8n1pD131WZRUwaCPRMGeG9Tngv45TBwBJhSQjBQLBQTEgLFQLCQzBUKBYMBQJCMJDMKd9O64cy6KLzQJSYVpeL0PyfyH%2F4fNfAvqten4z9224%2BfO7GdfcBdVIq71Nta93w4trln6vB5cvoVMm%2BXkMH8R3PxTfnedU22hVYxw%2FHb11fsqD%2Bz0ueqsh%2Fws%2BTE%2B7R5h6VDz5Un9%2BrU4oe1YLvqDI4BVaa%2B1MIShXw6cRBn0dx0Gl02vU%2BeY1EZZr2Vwh5aGB9o0IFkAU4h%2BDTOXvr6%2F5F%2Bm8RuBjSezjIKF%2Fe80JkS60p%2BThzL003MVPgavT2LG4LLUeJaLULwYvYA4ASQUkIwUCYlCwYCgWLAWCgmCgVChVCgmCoSIITCIXNazr1cyuN7hJqskqSqKS5lrscT2%2F9xqT3l4%2F639N8VHn07n2ui9bX6dhdc%3D&media_id=1254206535166763008&segment_index=4" + }, + "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%2Bz2o5cmIHdzXPoi85iLa5EV7i5aqbi9WoRrF2k746mbWGE81d7tKEhA5FIa2OWJlT63wA4ABHBSUKHMKBYKBYsBYaBYKMIIhUJCELvnWXk545ilZprdzEupWXktVyuA7th%2FIcPuG4fcf9n6j4NjHSPkOqdxrfNprL1Tca3%2F3Cpt%2FH%2BGCs%2BuCsevS0kpT%2FQEuS%2FyS0V%2F7dJexTOKUnoTsP5nu2%2F9G%2BA%2Bl2q%2FS3%2BTdIridcViV8Hprs9IG9zr6%2BFfLuZe7yp7NiOBtww6yZ7J7jHX6Tjlwuen2m0ezjeB7p7MQyYQ%2Fl2V5Jc9U540ZoKCRfmHa0o9HTvdfLm4NkxmQUYpVZ8JTRh8sVEKeu4OAAAAC5UGaBgGKBXXoTF%2BrlcRQj7WrEbMT6sT1LFk9f%2Bp6tXmHL6uLkuulioVuf1b9Wfrr9WXa1Xqwjv17r1X%2Buv1lL61JavXE9Snbtel9SC%2FPXJjfmFfz86t%2Buu1T2KWtrqXL1Vq9esYvKauT0Z5fOJX2ipWsl30rFerF39K3XVr36yv1gr11CHS9Xq5V1atd47kq9ekHLwktWKFL2uFXIOWx%2BuYr1buKxea1ik9XktXJPWvwR9jDSElD%2FXXay7v1il9dS2rq9X%2FWKrV%2FG5%2FWv1e7rwRyHDwQKg3O79S36w79fVa9d9oj1%2FcI26677iLvFZMIb5qu%2FRakvvsNd0S2Y9tEk%2F8nrLuvV%2FykSMQffaPn%2FOR7Q3Nf%2Fr1Xf169dyWtd%2BqvJauNqw%2Bi4V7ItldorC78n79b0l%2FDMoZZRqOX0IQhAO%2FCMd72COPI6aRB7JdeiV%2FLIXLly2rHZ%2FWz4g2I%2F%2BWcef%2BErovme%2FXq9WP1PfrlJ6s%2FPVumMd69ev%2F1dfE%2Fr13Jk16lB%2BiMPsraX9e7MS5W5%2FNe%2BX%2F3Ql%2FzkXzeiqwzRXqhrHCH%2F3PjDsFsEm967Vjteq69a%2FUwPfvFL%2BtfrV3NZuWvfYJL7VfhrneWkv491JeeqVTqf%2BpgXf6sF56vq1%2FzkX5LYoi%2FJ8nE%2FN2Qr6S9FYqykd%2BpXrxGcxa%2FMuS%2F2UdBV%2BvRO%2FWDtWV57jLpxr9%2Fgipvy%2FE5Blet%2Fnr5rD%2BDWC%2BrD6KdPF0SX69fcnEzeblpfmo0Zg%2Fr1MV%2BaaVBnIrz1VNGvkv8k2fYIbKjPXLRe5cuhK2WVOyPIREcTKu8xmtfk44Ze0WXZda166%2FXDv8l7nx%2BrBerFeGo1n7548DR7LD%2FgipJeEnlI9H3frh3EPw77Ymr1d3332iGT8tgdxqLtEq7rydhCHNxV%2BEdYmj9EF%2F31c%2FXq17v0TpL%2BLk9HRQbu717ROm9WxX%2BrXRNevVdZkisV6J36KKr9Sgov%2F64T%2BiQSL9GwwAAA3dBmgaBqgV%2FoTGon1%2Fx3F%2F%2F9%2FJ%2F%2BuX6s%2BO%2Fq1v2rF%2BrH6KdL9E6X1r4tekvELJ698UXg7EvIK%2BKV%2F%2Fm6ZXdgjjLy%2Byr%2BJq8ct69WO%2B1rJ7f%2BO%2BXdl%2F%2BrtYpPV69Xv1Y%2FZS18vl%2B3%2BDDCB5uNEkTdycaGis%2Fr1Y%2FBTDSKl607vN4RmNKvoQ%2BT6%2F8UiiuKJ%2BJ%2BO7vpdX6tJzfq0Rdevfqyb18F6npC%2Fv9evc%2BKV%2Fr79ev1lV1xK9d0X5v69XT%2BhDIir9CWP1yv16S5LXr9YpLXoj1wmnn42vXcv1yiN1aX1xbeJ77BPpqnBXpFSJtj9x9M%2F8qykvnXv1I0nr3ff6t2tV69XN%2BvTX%2Br34I9bbj6sfghnhoFAqXqx%2BG8rBRu18cu%2F3%2BrKr8jXvdalFd8v65SetX6v%2BsUnmsrbrwS3vJXt%2BpFjdeuVeuUg7NQzTWtl3NUrn69%2BuX61frLJ%2Ff%2F4XyexES3qdOYMjxK%2BX%2BvG%2BOokv5nt1h%2BH5RECX7Eab7v8J3mDOx1u%2BvBJ4ZwK%2F4aK5MslIEGPDxch%2F4ISNJeWX%2FWVbTerdyWvX69NYvSe9kjk%2Fv8EdyU67kX0Ln996ezFl%2FshLFMu%2FXD8m9JP%2Frr9YT8EUPzHgKmktWq5PWPFe9gKJsW%2BWYAG%2F4TmIWuGuK7%2FPWRluL5f%2BsNHhrdnVgihea%2FXsyp%2Frv8Xe%2B2%2F58X2o2lf1Y%2FPX8M6jVk7lNfX6a%2FdWP179e7v1c%2FV7teuzEb32i4VfcnukUxYH%2FdA23a3%2BiufolX5uyJvwR%2BN4YfVysTu5rn8%2FX7c9Pl2Cn%2Fz4P3kfv9S78%2FXTHCV%2F0VivEkTnSVoqpekkL%2Ff9%2FuS%2BW1a%2FXpfNSXITw%2FeS7u239rl25YPr1Yb7LMxHkx%2Fc5jf8l5lNWcq0x5Ogf7lub1b3n9E7tWNT%2F65V6mb8l9P6JB%2BhaZ7RHfl4%2BPg0OTz6%2Brr0TKI9HavV69eu5F11YJuwjzHIaqLPTv7DVp2Ph89IyCDolaIwdkLoa%2Fdl%2F%2BrWT6%2F%2F0aW%2Ff9cOzacs9%2FhwSxvxT2n%2F8NRlp6kNUyVt%2F8whUDvu5KT0eD9Zdr37JPn9k0mj%2BCE%2Byfu0SVX29kbdt%2FfuajYMtMT6K83ouWvCPs9W21%2B7Vy77MIdHr17uJtCYpLu%2BE5sI%2B%2B7tTNV%2Fq4%2Bsv1gu%2B1rv9dfrB2jPKK%2B%2F0X3673AAAA0ZBmgcBygV9oW0b61%2Bt%2F1Ylwj77V%2F%2F1cf7%2F7%2F%2F6L777v1qbpWS%2B%2BqxSpLz1xyLH5fVxdhCe3w23drnJY2q%2F1bHE3r1rtcJfWKI9cv1i%2FXu%2FpXP1ahRP57%2Fluq8OVX18ypabuifXr6v%2BLVzi1LYSUuL9v%2Br36v3d%2FrFJdDFLjl8TXrNXq1esU19q7u%2Blfv4lXOi6vFb7WLo2rV1XV%2Fq9WrlctO4nuL%2F5Lr7rCnv4tXl9Eikf8notX63r1evVz8IbBS0yr2jEGi2Sc%2BnT%2Bsr%2BuL6KV2OUVvit%2FS12rJLricdvEyQpZvXMfq5fr1WimFRPH%2FMIt330t9z0TXJXG%2F9NV93xMlrV3XhMo43fxsuH%2BiONy%2FPd2i92r%2FN89WrV6vVEq36vdk7MpeT7%2F%2F1v%2BL06bHbZ%2FPVBqRDV78J2CntykKTB9idI4WvmMTJPi7DLQoICwQEoLa2fwjMSYM08wvpMGwimkbCewhaxgsh4v9T73RU%2BrO1Tr66l%2BvV77VpL5ZPF92fJDd%2Br0X%2FX7coIFWF%2B%2BqbvsEukclmzYWvz1DelS%2FvOruu5r%2FWv1SJF%2Bv68EO604q68J%2BMvthJNfrX4me%2ByuO3Unz1Romjy9er%2FhqzdopF5e1pDT6%2F2TlzbKYkjZHHqlwvecxYVJ6%2B2OPX%2FIRHJG%2B%2B5LV6ridur7kta%2B5fRYrsM6h%2FAiEvlNR4st%2Fvf6a1%2FW6u%2FRHpS9eivfqy7c4ICYQmDBVxVfZjTGK79au%2B%2F0Vn56n1gq%2F9Zfq5Ype1et1y8Rr67ivBJscroqv9cFB2s5dy3XnrHyLco%2B%2FVXr1qT%2B%2FmV5vRa%2FPi8eMftkfdF%2F1yWb6a9Yrv9Fiu0bKvCfNjBp27u%2FfNk29c36LKW0Rn6xR3oS7urv1i7lwgIBJy%2FYcIJE132rJvV68hN0f3y5%2BrL9FK36xn6xVfe%2FVk0ZafFzmi13oruvVu0WDvvlRtV6Ewfq%2F6vLclzeXKkR%2Fw1ZFX18rLnNe%2BxN9j0kvq78OYwMJLVqkcYP%2FRsp9e%2FVdoq0erteiPBCSWn35N3%2FUxV69l%2F3y1zZ9F7W%2BTIK2ierzWjOF6vfSO6tL1VwrXq9ZV61Vq6vWC%2FV693v3dzXVq3KCKYju%2F6NX5OfDnYAAADZ0GaB4HqBXfoSwfE4hYm4u%2B1m7q5aNk9WYon9arjcQtCOwkTX6L%2Bt%2F1v%2BsV2r92O6LluxxODvta%2BNV6tX7WOUOW%2BO%2FfrVesq9axS9990KWr%2FOVUGN6%2BNo0Vas9j7Ub6iVh%2BPRv6Ml5n3r7GhmRKDZsXlYYfjrTq0TLtX7rBFvjb9X%2FVjp%2FVXlEL8R3dyWrgnnIvkjf9FbtYu%2B8d3Kq8FesEv2rHZcYP1l%2BtdV%2BuVXfq%2FasV65QhvL6s%2FV6roUt%2BuX6uVavd1a1frF%2Br7uJV7ojv9X%2FVndTCXLLhHQpauvWCxC9yWrH6w%2F0WHV9zWiRX0r1tSWvRPLJa3qwQ85BY4PwSZB5%2B5%2BuHasVdbEr9NavNf0spLWKrXD9Wqq7WX693%2BE5aXobod%2BI2qeYmULS%2B%2F76r8%2FLjrGP%2Fr1e%2FPm6vy7tU71rlV9E1cl%2Fr369%2Bi9Xohxdmp1%2FJ0xgAZ8tb9rr9dd93at2CEsOQ0uzG7%2FZMl%2Fr0nq8nN3Lc3hmqRR2ga%2FMxPVX%2Bsu%2B6T9X%2BsL8ENb8KW%2BvSXFcv6tXojSeXJD33V%2FouHd%2Bsrurr16a1%2BXa93fq0l%2FrqvBLMIDsnQG1MD9a7r2TQjUV3faE8i%2BQhx69X3%2Brj67hXVybr0TZ7Ef%2F%2F%2FrK7RMK9Fc7RXK8TtWwhcnPgJpJ4lDO7%2FQmKvBJUrHl3%2BevjJj%2Fw5e9nynibf4JOWHXute3frV3J4IqruFaK52HJ8fr8u0tyXS9oO6GUQHtt2V6htNPq%2FVeQkNXTWsfBCVjLPvfo0VeTtkCAuwnsDVO8rO69XHVHSoX6u7q0IYr1ZXmLxwIP8IUOPm%2BJ7FHodb%2FN2RLfrF%2BsVF%2B68J8rGxmprznX6nIv%2FwYUCm9KeLsfKMEMyGU3D0vr7ijJbVjXsEMbSfK1knuNhuh0BfrV%2BCTNe7vur%2FRcX6tJa9JZjSsb9Fy77Xv3HGv95Ph%2FwS73rK7lu%2BvXE%2FXv178FpNkcXYYqt5Pct%2FdWQ89Pa9pfJuk79a%2BFZO1bJ%2B%2F%2F66ktGfu%2FRXd%2FnuVtr%2B6X2L0Ru7FFtJNPvfvxRMrF2P%2B5abJXN78zH0VpX%2Ft%2BX1eb1sNj9070Bst0jei1%2BuXxKur0av0R5dV19IT30rKq%2FVhtcv1fFfCdevX6v2r%2Fr1%2BTNt1f692uVeiN%2BuEl16K%2F6tcABLBSQbBQrDQMBYbhYaBIKDIShQSiQKhIIjMTrbd1rxddb2vdrzVVK1U3CrJHA4lpfTOtNGb58m0v8ot19dJ5G%2FJuNjL3SUnyJv4aOi0f%2F1ns4P4kULnRmNMfbgoFVa%2FWcULPw%2Fyv6eztvt3riBvU0OjPtBkKnrMdn9Zl52Hj6uXczvpO2ze%2FTunbAy1T4xbz3zPUqstRkDSf0s%2BUfH20jtdvTfdanHUu%2Ft1Lienoy9K3nNK6uv2fLDguGJQvDpJTsKi5QxnZ%2FCbavglScpeWxufAnh0LEZ6%2FswcABIhSULBQJhQKhYSCYcBYKBYSBYiEYKCULCQJCQJCMStrZx73E3Wt2vJCrm4Ui6t0HmO34b%2Bg3b1E3X6%2F1X8p4RNJHHnf82nop61cM81HLRnw3d8bSpu%2FlOTas%2B5fWfBZQe2rERHgyVzoPBRZUc07gzpiAvSOvPc2%2FQLOvj6Vkl1GfCIafYUEQ2az8OZvAEV90ORWbBzt6i%2F2aX1UPiXAHLoqInl0c%2FQYMarUqEe7wCgjpFrHwKCALvAQ7q3nfH8th4eGrxqwPWofo%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%2BMgSlfCbTZZTxjtPq3hHXuAR7mrt3Fjtzl2wAX4LuIsoNBe9Fu%2F6Xub1JBiSqYCaXqqTnImtCQ9LjuttTPeexffBzO47%2BuqLJ%2F5T77W3HR1AC4L65rr7D8qnnCriU4CQb9Uxzd75d9QRIj3ArUA9Pf9CYK%2BdbiUejXN04euZmMb7rGSLQmNw1aeV66s66fBIROtkvc2AcBJBSMKhYSDYSDYMBYKBYaCYKhRDBQLBUIhUJBERhbTJVb87UpLySVSRhiXYeR%2Bd%2BQt58eb66%2FdJ4b5Plf3L7tuH2pn33Z0cw9tO6j4DpeNc6RIpbVXYO9i%2BQIfHk2nk2XUpgKHaOzi72pg7X1RP4H5YOjLeiFs93YWU%2Fk9RrJBULDKUfBfgbp9DULGN7agxBB%2Fx791z5X8JvPnBRr%2FlAgkcoWTtRgrJw%2BkfzOkMuLfUNO9H1ho0EWWITQVEAE%2FVfwsi6dfJSODrdo0vdmVr3GlXvcKoJkIJ9llRW3Bhi%2FJG89byAOAAACskGaCAIKBX2hb1eX%2F%2B%2Baub%2F9e%2Fr1%2BCcis%2FXv1b%2BvVvi%2F1Yf5%2B%2F1c7%2BRWP%2F0UsUvWrjquzu%2FRsO6pa%2Fv55b7%2BX5Vb%2FpVYfXq0I%2BM5V7qVuRFl0QvVapnHLZV%2FGVeOX1%2Buv1y7%2FXt%2F9r13Jalqu17rLvqVjn5EqVW%2FX3atd9qkWibGLqhy2r1yrmi7yfn7dju0lqxIK%2B%2Br9W%2FVktq1CFkvFL3QhYmWa67VvruJnq16%2FV69eu178JSz9jOxl%2FFL3L6sl4j4mS5MFWS%2B%2B4rpXqe9Vl5P6uFzfPNzTWa8cJH9cPz%2B%2BOl3Qq78XSSYact6uae7Xr5Kv9av1yq8Q9%2BrUT5%2F%2B%2Fz4qO7%2F8m6161Xq9XfqWutaiH8T%2BrV69JxNeuX5ZhQcGXa9ZTeGt7qzN%2F%2Fr34c6sb80ikH%2FnK8mDRqwZVEn9oh1S2vdS9%2BvdJ2r%2FL8nSTYrd%2FnuPVun9YJL%2FRWr1w%2FEZWED2Oja%2BiPfkq%2BX17%2F9e6118QrR%2FvMMZ7%2Bc6x7DF%2BW%2F0I6W5N16J9e7v0Wr8pt3%2BiuD3%2BTRufF4JComnZ1V3cly3XonXaLqvKIXSXosq89UBOiHD1%2B1avWCrl8EhA9Fq%2F12iyr1ir1SL61%2Bs3eKxXyau%2FV5b%2FRUr%2BCLpNd2Um7lu%2FRc2%2FovVpX3d1deiMfgjLuNnE7S7%2BXLdWjVVzerl3JaEpV9UofOZVpmGD4xc%2Br%2For99q1etUTzX%2Bew3Qk2SbU0COZfn%2FWLsE8YiIB6N9ct%2FYIt6cEtqw2CO%2B1l3dguoziA9aRnRV9q9Dtn1V%2Fq%2B3urRIq8%2FCkOGaD%2F33V1Z6%2FlNGpd673f5Js0E%2FCXRFILMZb%2F9%2BMBBlPJ61Jjc2J%2Fr12j1Vo0V3%2BpQV7K975u%2B1bon9ek8EZue2C8uyu7R2WX%2FX74J%2BqaqpVPV6tLfdXJ6JlV93AAAA0hBmgiCKgVyiOvQlpLu5Kp%2FWr3Vu1znfV%2FydXXrFVzM%2BhHJdeuXderherB2vdyersc9u6tFY6pBHfokXS1eIJr1rFK%2Fycmv85V88rJJeez7MesL77DeZKVDANz8ZgLBFv4bjenQriS36jrFHYRbqddcBEDEnS6ibl9ar0Sv1YDMKbtYqFYr7qyrVz6XX6lq9fkK2vXBPXrlL6t9q03r1%2BuUT61%2BrV6xT8%2FxNDsV93k%2Bv%2BvXKf1ZXEy%2BtSeLk3yq7%2FVi%2FWpL7%2FXrur%2FWpeLl6V%2F1q%2FWVeCeXKPLfYr1y%2FBNrJ0cG%2Bp7XKTVbHxclrt3Lawd%2FNV15ctGva5fkqu%2FcYLr%2Fydt9rBvfBDsnxdmluv5MenWFS%2BevjPfJPFDsuDFK9eu1q%2FJ3aVgntJ44zaIPl%2BCHz%2BX6yrzdmX%2FBDVnmCKdqbzsU7nr%2BHKV9gtKfDz6h66%2F%2F%2BiS7BFY8PWLpCfH%2F2rR%2Fm3Tv11%2BWQxJhJ%2F3NhkSC99ouH5CXvtcv1qvUhTeuu7n%2FXozwYSsB2qegOEbFR%2BGojCv%2FuXWBj59rxFgJgZxAbLT2X%2Bnz6lXbS%2BS69Yr9cO1qSEe1f9a%2FWv1quaqea1l%2BYiHNteUuNHnXmJKy1H8O9EaCLNcbPrLp0%2F35Cyv%2FkjMWevRWdmNYZJ%2B%2B32b%2FVyvWYH9ZXd3W%2FvXq5FWQydN%2FhIs0So1M5wi4W4t37FnmlzyY4ApPF%2FycZANcAB%2BUymRMv4JDw8ku7j4I8OcxQNibEZ%2FVh9Wr1i%2FCe793XiCS99uVir7F4cXSfHMx%2BYre%2FwQ93rv8EOmjd6spNJd%2FnqmOjQOE6H%2Fy0S8v%2F3%2BbQ7%2FJlzVxPoupSeu%2B9X%2BiOlur%2FXC3d1aO5XgkMUZTb9J7yfJ4KCrJOlSsiPV5vITL%2Fzc1KJ5%2F9ej9t92G217%2FgiI9%2Bvz1boRKeief%2FzghKP%2F%2FX69%2BEjSTGZXLT3%2BivIX%2B%2FMR3y%2Bjv2vWO%2FXfdXfnqjTSb%2F7u%2FL910ELa7Vu9EX7EWTGR%2FkX%2FDXZmNL7DGH8UQYXy0BzQI5PrBVd%2Fm%2FGDx1SiBGPRdE%2BJ8hX0ietS4R8J3dsyiKu7p%2B6u%2B7v9FevXpPBGISPnK%2FVpfQlmEtNX%2F%2Blfqnl7Vrub1gly%2B5oAAAAJ2QZoJAkoFc9zehL%2Fr0%2FE%2FS1%2F%2Busnp%2F%2F%2F%2Fq%2FQh98Gvapl6%2F%2F%2BJ7%2BWT1qvXrHfp7WKqZa7WztXX61XrrFdXXKrPeT1rL%2F%2FLRPdXJ6wdgiKMF88OeB6J8%2F5I6y40Pf5o830%2F9WC%2BrRIrFcl%2FrKN9ZSXL66vWqK7uBVm4ntXXfxNjuRp8I4j%2B6om76pOXue64ntXIv16Xa%2FVlRc9zerFerna980lrMS%2BsHy1d7rXdYZzXKKWW%2Bif171X1erD69V9z%2BsVVK3X3dUX6v2vT%2Bvfnr6BDFf2rblzS3y8T2upKJ1cV2vSer1a13J6LL3WKS%2F17ff%2BCamwSd9Yv0RyvVn6x36t3VrftYJN1q6STiYq%2F11V991ct3LXrFN6vEYT356sx0rLxj69HhpLku7%2BWS%2B6l7r0Z4wv9%2BEiPlyPD75fKXdkr7r33KwvN1MIDuIuvWKV783l8tNkInt7OVfw6m4h%2FVivLzqJbWK%2FIRvMV%2FOdgfW%2F%2Fonyb1qubxuX1yq4i%2B%2B5PLo3rzXv%2Bryej9folfr94rdrFLa9XqmPwzdFdTkI01%2Fk9au%2B79EZ%2BhbH4bod6Q%2BmWix7ktYJfRk74uiy1qvp36vUtPyVYmvJ7%2F5smX2uXZ7I0ROP%2Fz1JQ6igX7ov6%2FVrg4fcogKfuvRPEvgh3S7ivpFn%2FV7usTVv1cCvBHkOU5a%2FPVNEPPX%2F4J73u94P1Z%2BeqESD%2F%2FNzUVetS3ev5RRbkI2%2Fffko%2Fr9FYp%2BqvJDx1X%2BvV6sfvJe7k9TJ%2BuOrd39%2Fq%2FdF%2F%2FZEkt%2BG9J6%2BXE6XwR8uIJyvDlaRBAfFZd%2BS6vus2nvosv1apC167XvJk9aq%2F0R5PWv1qT16oAAACw0GaCYJqBX%2BhMbV8Xc3q%2F6vJc11yV6p0TQm%2FXu4%3D&media_id=1254206535166763008&segment_index=5" + }, + "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%2FVKtRHrFCLyN%2Fy7Op5ll9Wn85V0y75PDWVjUeQf9XT3Vkev61a%2Bwnmg1rQ79crvuvV6%2F575MVyej6%2FRJU%2FWvXVXXq9%2BCTjqDdN5NbLcnrqSlV4n1vN6wTXT61ym89fDKWFBa7JZ6v1r3Wu%2F1iqCH9aiPPWW7X7WCXyx8IN9OvLbtsi7hk5VF6%2Fj%2BVfz%2FAwxQ3OJf9Gc%2FXpPXKSr6%2FRXr1q7JVd3%2BCS79TWev4ZT2v56p4YTsP%2BrNX99okvz36GX%2BrRYTsvRvslM4wf5jD78%2BvRcL9Gguzi2l3T%2Ff5BGaFrrR3odtd3e3L7yV359fkq8NX%2BCQ0cnfKrn8sl%2F6I1%2Bz7vfvJdwzfo7RXmMtf1wr1Yq69HbtE1W4Ip8OY%2Ffo2pfVz4lCasVitWuu8d6v179XBrjfXLy1eSAAAAMSQZoKgqoFd3XoW5Xr3cl%2FEdE%2Fq0nrXf6xX6u7q%2F1avVz3Vz9T1erndesXevif1Z%2BtfrUnrFXE3avXrFfq78N81EM9x0fFUTP7V13V1xN%2Bvd99LVqx7r1euFeuVevRPrlfq4VEzev3BLfrVeuX61%2BvRvrHTeSwiU%2FrDK5Vyea1y%2FXom%2B1b9X7Xojln6XomiV7qV7tWV61VMsX6xVRNBLqn%2FfSsfoj1d3fEy4Z%2BlJzS5P6K0nq3Vd2O5BN%2BvVd%2BCaxR9M%2FJRHjP1Z%2BsFUt%2Bu0%2Fq6b0Rp%2FXoiwR92nCy%2F1aM9Wk9cpBHfmLpFor%2FVqtcu3K08t%2B95bJ65Xst0quk4qf167%2FWqv8STj9Bkbd93L6LKX1ir1b9eu69EqL9ly%2F8EnIYj0dqvV1%2BbMvLF3%2BiOO%2F5NVl9Ypuaa1eI8h44Djv5iI1Mx%2FNQ5WK8lOkqGrLQGb1l%2F9b8uQxsf1Yk9Yr4u%2FV5PWp%2FBDTpoE78vL%2F0R68sxi%2BXwnRs3pzKf0Jf8Saily999kjJs%2F82wY2ZuBAXzRhPb41ZPRTSp%2BJjoAA7yCYJh9Fgo08PScMrw3yQRLhxPJ%2Fl%2BGd8u8v%2BtfiCZWL3rei%2Bv2CrdNKXDweEAgopxmxBwrwmVuhpoch%2F8tgjIZBL4k1uZgrLhCgOH8NHQWaK%2BHdhz2iVHWpE%2FR2S3%2BcjPvGyHk8mPGnr112KjBto9Ew3f9y87evCRCR9aXzFoCnY%2BQg0mPkL9foSmW5r%2FWUnrlEeiP%2Brn61Xgj5ZMosv7%2Brn4I8n%2B%2FMQn69CX77rwR8eKpSZVXsxuw1ovr6%2FmzZq9X1aO1bq1YRdern69J4IzVrqWznyjIvqCrYL1ff6EOPgiEx0FXpvwUSw%2B6Hl%2BrfkNYpaL0UoJb%2FFF2iKnyoPzTMe2%2B%2FVq1WpLWUR6J1%2Bia%2FMW3b2EicbHRJ%2F%2BSOkSrr3z0q%2B%2FwXct2d7WX%2Fb61J03%2B8zH9F67Vq4n9FPelz16uCejd%2Brh26Tf8295fv8ExT%2Fulxd%2Fq36xSevT%2BhHd1aEt8VV9r3d2vd169frFJ6KYEVdejPv1RqqAAACIkGaCwLKBXKjr5unnv4v%2F5P0JftW%2F7%2FUwP%2B%2F%2F%2Fv6%2B%2Fk7Vzv%2F5f1qr77Vy6axS9yCl6Ze75m%2BZW%2F6b5lc6ZWX69YSWu%2F369Ypbvvvp1aQV9KtWO%2BY%2FWq9FmKd56%2FSNT2QlqQb%2BsF8ZLtLf9WSWr1dE%2B%2F%2F4jpfCeSnr11Jfl36JL3p30K79HYEHbnSvWL9XiLr1r9XjZ1ahSuIu7q1i%2BI6bTx98XIEvL0%2FN7mYS3L32su5fV0nq365fqxNc3r3fd%2BvfmI2n%2FVu%2B5P%2BRFeuMifWL9fdES%2BpUr0Ryrk9Zd361WGM3y3OIXuvXquS%2FyFLCwPua5pl7u5vXqGZby7WqtXPwRdX6%2FU9L6JVWit2CK9%2B1%2BiSnmWqoq5vR8K88xfOMI2h8l%2FnIsptqfJ61%2BveWuVYQ10vQj56s6lRf9kfdXfosVeTqOBYd1696r3KvRIriPVleQnGgXxFzwvN6L36%2B%2FXv16T11J4IsZHb5d%2FrF%2BiQforfqx2jsF6NF3frqb1lP69N6nTu%2FWCrdtcnr0tzWfFG%2FTv%2F1y%2FRS1ejd%2BvRNyeuEt9z%2Bi%2Bk9er0SKW6j79HetV7wj7iPJvTEesYk92Bk33L4I%2FL3qNIatfo7%2FrVyyXXkJPd14IpRBtWTetS2TmGKZPV03reqLV7n7RXrJWCgl3DX9X%2BvXaIw3%2BScQFKzdrBk%2BK%2Fq9mGslxHrWOZU3d8KStXq8RQur%2Fq%2F6y7kuvUzfrBEbrFJAAAAntBmguC6gV%2FSExfHq5%2BrDwp%2FII0i3%2Bvd1f61%2BrVdesUnq9%2BqYq0Xu%2B5B0mb9Xd36sv1qKv8u0t%2BrSivtWY7du1Yr1iu6Hfq9Yprr1fT81yWrHnqz9W91sT%2Br%2FrXasTetX612r16ululbct%2B61d1RfavXq8vqZ8R65frl%2Bt5PWV2tfrXhqtVtS9LXfa1%2BsXKqUdrXfauVcnrFNuspPLVUB16ue6udySqy%2Bftaqfvvg%2F%2FV%2BnXrvELKKJq6fxKLB3NaJFV9rLvxVeviOmXsd2P1rp6vFcghb9a7V69Zfgh8tY4%2BaWnSX179WLn%2FV69X8J%2B%2FiLtakuIFLXq1%2BWui%2Br15Lo9XJ5OZt%2BuH61WsvJivL%2FJ69XrKS1yonn%2F361L65fidgY%2FOb%2F97fLInN%2F1YL1ftYv1bv9cq9f1Cn2reXL69NYSvpXYbfwRd22BPfHwgTEevfnqzW%2Fv1fgh%2Fkn7v1btWiPPXyjBQCbbErJ1wnFLXNdyer3a9Fecike9Lyeisk92pjH8EVVvKvPU8L%2FJi6tLderER69d369Xmlz7ibXu7%2B8ft%2FxXvR1%2BWwKel%2BrEtxF18vq%2Fqu0tkulcvhve6sCD6L4f%2FwzbjIHXl%2BcEAYyCCf1a%2FJR5qfUpS%2Btfl81CXPa651aW2Xd161L5DS%2FJaO6t0SCW1i%2FRXteWP1blOJ70v0aUnghO2TP8t1692vX77ub1l2K5fOk0XwzY9Vxo%2F7caIOxd2%2B2%2F4Yk%2FnYoaxrD%2F7rwW5DGh5aenub2Td1clo8VXUtesXd3J4IjVQ%2Fdnr460dPL9%2Fyeiv%2Br%2FrLuvQiU0tsFfFRae5fPqf3%2B01FK53k8v4n9cJifv%2F3EWie%2FVrgEeVJQoMgoJhIGAoFjohQoNgqMgiV3uS98eKk2NY1l5apVXWRcXU0ObU25bH7640m%2FPhRyhelWDof9Fll8LtmdPu%2Fy2qWZPomphVrZJ%2FpEiDrKTsNI7D9yuAAS1ZxrX3bpoqB8f9ty66udI8o%2Bmo%2FL3a0QsT1Jblf%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%2BjcNkpXtof13KxVQVXupZlh2bgvvV6h2RgDN3AcBJhSIahIKhgRhQLDQLDQLCQJBMJBQJCERBEJBMIob6765n7ffu62LvLnGBRS8kvemh5%2F3K693I14%2FHX%2FxefHyqjRQm3L8qXx%2F4r3TXvRz43J1DH%2BBCVtR%2BRff%2BTA530TaZ43r8PLSzS6zH8vAiuvy%2B2LiYYRKGDOr5d%2F1ku2pvbg9qZJQuVLrRR%2FjJ%2FhbS1Gj9h3YsstZdebxf%2B5lfCv75lkqUSsYFUrp0SUXomgjZCQzyqDgASBUjCgVCg4EgmE4WGgWFATCQUCQlCYSCYRCYUCITCITCJWzc37%2BcTL3opq5klUy6upKWsf4O4dvp8n5%2Bns%2BrB%2BofwF7KmGE1x8XmHy7x3dUkNvNJefHTsWIdSr1aO2himEvyLxzdSW%2FGsv4w1YSNXUVmgl1DJ3USvD9jT%2FPuszMRCEd8%2BwtJGf%2F%2BUfGcfUQNLDD2TruVLuFXF1LaXRNQ96TyU0SgLrZbO5b3RQUAvg1v2kUkMsF1f2lcHAAAAHoQZoMAwoFfaFt3dq18va5f36vVyerHcl30vj7Xv1SL6sVBDxas%2FVu17L%2F%2FVq%2FasSf1fq9%2BuV%2Bt%2Fzc2Nr1evV1eu9Dux2tS4b%2Fr363rBHV%2B7vGcqfrV%2BvV6y%2FVyS%2F1ck9cJh27drKrWt%2BCqryF%2F%2Fq%2B%2B5rkVN0Tz%2Fjon1d9KzopXqiOG5JLtWq5bk9WrmXCr5%2B5Lkn77Vi%2F6lYq%2B1Yq%2F1ir167r11Vr0136JF%2BrVfd4vV91j8RVP65TK%2Brn9cq0v1vL6uS%2BvT3d%2FrldrrvL%2F7hOq%2BXxdxwrq5PZXay%2Bid%2Brl0Rc92teTLcV5OSslyX%2BivPfa1J9esqutV6cv3%2B7HTY172EQfWkResEnsg00fU8Ta9f3fc%2FvnXl9cJHfXrlfqxFVxvuNHD68RbQZAgDQk2pLd14ajQ%2BDF1tplW%2Fd3NPLhWtQ7ffa158nq99IsUvq5Pa1frL9EyrxWgmRD4aRfz78szFjq%2F1i%2FR%2F%2FaJc5Vrj1qS%2F1e%2FRcb9Xm9GlP6sS3%2BvXd%2B%2BjHWT9Hl2Xuq9Xl17VyX0aV%2Bixd1f55G%2BVNZEjuS6uT1b9Wv1a7hH1qN9er1fFP%2Br169XrlXorfrF2sFF%2F%2FkuTz1KKCw%2FyWtd8%2Fask9CuiNULZXS1XqYUvrF3VyetWT7%2F%2F0Z54IKSAAAAHmQZoMgyoFdehLnUqYPOuUtyXVyWvRFr3atXq12i13YhetErJ8f%2FS1yzXQ5b161J6sq1er%2FVv1a7VyrXuiVixz3JbqpWlGK%2FdV%2BvV5yt870cpol%2FojBevfr1Dv36tjv1erXatE8R%2BsUnr1br0%2Fq4fr7vx1Wq1LSX3J6urVeiLiLk6Xtvr1erF3ad176Xqte9V7f%2F6sfrHLohYu16xy6x379WuYiribWdJ69Vr19K3atEXJ63r0XUvolVquVX%2Buov1iv1IlitsX59c5IZ7161drqX1qL9XknrzWpGBiGP5NJ7u%2BJmhGT1r9el9Y36xRvrF3XrlXrF%2BryevfNfqkWWS%2FWb1l%2Bbdf1ZfkzL%2F1evVxv8JUtKlSIKUVluUv%2FWr9xnrB3EeW1WfH%2F19fEdq0bd%2BvX6JLvuYv%2F83N2i12rl%2BvRhf4v69dX6J3aLKvWKT1lJ6tL0vVct%2FrhXrhL65frBEWImS272P80h9BMfffL7r3TSXJavP63%2FPUxWb%2FfrUTZN0q9cae69Xv0VpLXpvRGVdeimF2iVLdeiV3N5xNQ5NX%2F7Wu1erov%2F83rK%2FKIWtej6v1qKtkZapes91dXV1132j9fqw%2BiMCetSesV3%2BsozVFbuqvwR9Vq%2Bl79XHTq4l3HRFrf8EWX73AAAAB8UGaDQNKBX%2BhLH6pE%2FV79enuO9ektF7T%2F6vU6JKvWCX18r179eu%2Fdfdy2rP1a7Xq9WKvFLXq%2BKX9WdrFJ692pbHKm36nSvXviZvRWJbu%2F0Tqy%2B17wh%2FXpLV%2F16Spcrvv9cpatfEyl9%2FftX%2FXquSerXr9e6JV7tXC9axSxfrUlyVdH9Ciud%2B0rJalc7mtYpPWrFLEXFbVerdq3d3ehC1FTrVXfrCKua1gkHdz9a%2BIkvtbEtxfr36wX692rgtydLqtVim6WPd9rlS3z18xsaaP9Wl8lJTy16132aSlb6WV%2BvVxEt%2FrUl936sV6JlJ6LlJasC33fr6TP9qT1yiLmvL%2F3rXf6sPuVI%2BfH5PV1%2BsXcXaLLubykyDBV%2BsMEz%2FHfPrdXm9XV61N67B%2BidJ7Kre%2FRe7Ru7vy9NL4I%2BPvr%2BCbVzr0t%2Fo%2BUnojTetVZ6%2BW2vclqZu5bv16a5C%2Fv6um9YJb7r1qru7t29fgjLzYxEeiSx0sqV6I36tXojklxPr01orn4ISxoFLwS%2BiPXorV67VcX73tr1d333JYI%2FNXN%2Bev2j6%2BW%2B%2FwRQ0hOP6l93v%2Bvd36uXoT4rdrV%2BYQS%2Brn9HwiN57sVuuT1RdfrLFLXrLtZVf6NURd3ZfJ%2FWp%2FWsU7odLq7V8V1ffftRG3EbrX61Xr79WuAAAB50GaDYNqBX3XoTl%2BsV8y93iOa4v16vXpLVhnqiqGfqJ5f9388%2FEV66lub1TNXFWrV6x69WO1lXL%2BsXxMV61UuOW%2FUux9K8tq%2Ffd8T3dE1desruIuhS16vQrFb9aq5JVZ3Pzfq9etRPs1UkiCuf0d7tar1qslcqFf65d3zfN%2BryerH6xd%2FSvXEfrURcb65V6uH69%2BsHfn%2FklZtsf1Too7lqtZdrr3WpKq9erVWq4hf%2BX%2Bsv1KD9cv3bbXX5eNNGrk4jtZpvVqi5xyyqq6EL2td1693Nf5aJgKu7te7UqTSq54%2F71fqsq9Wv1ijbU6d369frL9e%2FV71Xu16W577nuvJjQSdfyW0s86xX692vV691L0Zfd%2BrE3rhfq0vrXa5fr361drFVzesprr1lV14IdaWv3rJBevfqwNff6vLf5rJd3Nf7KluW68L82UDh%2BIM19CLsqH5yKnLT7vu8Rv69XJbV5r%2FWKX3pkJWX0SCS6J5f8v16tGeup%2FWp%2FRWMn5%2FkLl8t99q1WrVa9EecQsfiWvyecq%2FjiDdgk5c9V1ffdeSGF%2FD9e5day35terXLLaLrtWku09gk42v5Xq5Vr0b6I04pFEP31aVu7u5%2FXH%2B5P%2B663%2Bvfr3y%2Fr36IdJNZhSz51k9v%2BJubLq54ABKpn%2BTCZImKoyJE4iszrgR4l4mepvoMvEPmnzWHhkk5727Poo1sxGPNR1gbQKBCZ9IjJNmv8I%2BpC3dhrt2TWjcvsb0UZoVAA8oT1aEqnIu8Hg1De%2BpvmeF7ESx4G46hMeLx1uK8isCYG8uahka9zFUaA%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%2BioOABJhSUKBIKCULBgLBQKhQLBQrBQKhQJCQJhIZhUJiEJhExlSp%2BnXW8Iuqrjd3kuqlKvW4uug4%2BRn416XEmtP%2FZcePS9uuTaIZPXGuf%2FTxvN6CJvcfZ5%2Fwg6gVaf%2Bdpoz9UFwSh3a5AXGZHyE3Xlch5tl3XlIOdGHKXWBNUlx1e0pmLD9IJ%2BUq1u1DIJYMJH9P9icmvyenmbVpSuWzZf590rHBK2mipVMTUnq3t4QWWnKKxLhNy2AcBIhSQKhQJBQKhYMCQbBQShQShgKhQhBEJBUJBUIhMIhUIlMLlVXX5%2FHn7TKmtw131laUKSwnkcFxbt7dV2C5Q%2F76Vtxfatm8fWhP9L9R%2FYv%2B%2BXfhhN%2BF9D49W1XP7TRCUsAvsg4tV6IMPwtt8XAAQe0l7sF%2BjvYTr%2BYv9Moy2CWcoR9bqEuKV2ejiEtYXiFN0J5MmPn9zNqcG8rlfb8UoeIup5OCwi6iNkYpUKr1ora1zs3yIa7wIEinUQt7EHAAAAfZBmg4DigV1aE13XFVTYj%2BJrkv1rtXiPV7v9ar1r9X%2FVhut1YU6or1aJqb17tXV0sX61Ypf1ftXRHqx8RXq6r%2BKV69WL9coi%2B5fWpfVh9cJPVyh37n7W%2FeKW7v1YCOa%2FWokn17%2F6sDevd1d%2BrRd9%2Fqx3Ls02I1Rterr2v1qIuvXpZ69ZV6zFLub9e7kuT1OnuvXxCs%2FV7HL9Xr3y%2Fr0ornu%2FU4JvU6q9Zdq36tJ65XcnrlN6t9q4%2Buq9481%2Fy%2BaS8TnlyBAFHr1w%2FXq9anqv1lXrckuhRNcvf61%2Ba21%2FXC%2FV5fXpOIk9a%2BWrkv9T1X2rv1i7jrr1Kl7rFVq%2FDd33FeuVXXlo2drd%2BrTWTmnEevd9qz4nbxva5V6vF%2Bsvz19561f6kuzaqbk81KzSEUQrdrXOrO%2B%2B1i%2FU6RF36JUlxUzT2sVaotT%2BtTetV7z%2FXoRUnoWw%2BC3jRlDsI01bblXkqypCp5PNUs%2FaIyvRY6W5PJYI4rT%2BW1t%2FLfZEuf1qX1ik4iX0aCS79e%2FBIUhizRM9SeiV%2BhbJfBCbVamsupc16K9er%2Bl1q1ar1bETeCMiovKO9ZS%2Biy7k9WP1fv1v1l2vdy3XrVXVokFWiRR3FYrrtCe9i6qnu%2FZNUjE91%2F756J6f9eiNFaxPoT1%2BsV%2BrDf6ylu%2BZe1%2F%2Bt5IAAAB40GaDoOqBXRPL%2FuqqJ7QnuVe%2Bu%2F%2Fv%2Fv5u%2F%2F%2F%2F%2F1rv%2F%2F9Yv%2Ftb%2Fq%2F%2Ff%2Bv0V%2B1d8ardrVeidfN2tdFfa1d4r%2Bauj63m3%2B0tIO%2FpYq2letpd39VrViuvVuta6%2B1rtFdJxEv1yV6Jl%2Bp0xSy2air3f90K%2B1TratLder%2Fq4Xr0hf%2FXELGeuv1bsEe1XCaqb1eKu%2FWUnS9P9CiZ7%2FVq9ffr1evfN3J61N6tJa5d%2FPVr1bXyX0tfSsrpXdr1jv8qVXk9Xr%2F1dXqwfrX64d%2Fr0v3a92uqte7i7Xr%2B7%2FWSgK%2BbmXrpP17yatcpL%2FVrvte5r2u1r9Wq5bv6i69em9e%2Ba%2FXq9WR3onVcsq95hCLrta7WpM9X%2BW%2FXv1yl9TFV%2FrqT1burn9ariO17i%2B%2F1er5e6ue%2B69F6W5PCdmqenMPL0bpRS%2BK8stxllvQ2E7r11J6yivr1y7Vv0XvSirQjCvR5X66lvL9fxOXfq09%2Fr0t5f3%2BvXK%2FWK7KTJk3oT3aI5%2BtV6w1XXrqf0Rpbv0Ut3E3XrlLtIvfS6k1ktam9Ejq9Yr9WI663RWC9XqWT1blp2ktSeevh5dB%2FurV35Mn5Pbv1ghH1axXy3PfS6k8hEj0sG%2FJvc9xfr3F0O7X6%2Bnvy6J%2Bf%2F6O1XVxWWrSQAAAAfhBmg8DygV9oS%2F6pV9e%2FXqtel9exnqrXqteq16vVv17v6Xrur7Xv1avXu179F8%2BK7q7tE9ivq6577VlXfgkotZZPu%2Fy5aaHL7uvXsV9q1T4okVxW79WK4mvU4UvEXzV6uVauPq1WrX692uY%2FXu%2B69W%2BJ%2Bl7269e7%2BWLtfVa1Nc1q0ndCup16%2FVwbiO1a7v1Y%2FVif1aba%2BKv18VVJghr1c33frXaxSX%2Brkvq1XWT9KyrUrfPfF93a5%2F1arsR3fau7XKS6vv9al2p%2FWu1sF61N61%2BrldK%2Fd2rD5tppr6IwL6lsVKQi%2FXpLWDuS79akvuvV%2FiVeTzUn9zery2t7ua1lJd%2BtV0ixRt17MSmid369%2Btfq9XLc3myw%2FouHf5CWmZjF3XnKqEPmrL%2Fd%2BfqdQ2QhcZ8kP%2Fq1XJOrEbdXXlJsnd%2Fr0t16veEMnq6MtZTXL613XvzUXrUTdX%2Bi9Xr1%2BvTX%2BiuPkEUk%2B4n3o3hD0WLu%2FKTkzaxdq53Fr7%2FJHadA6vm6hXi5Lv0V%2F1e7RsJLl8pZn%2F1ckv8lhPcty32YuqkvybbXN6IyX1wiPLpTUP6K3d%2BtS1rBdUnqzvv8EXkeyrNVNAk16J0I1K2OZfT2p79em9E6%2FRe7WFfq95MSK3fqYX6vl%2F11fXpL366r16JtSrH0UqfqVJuaT0bpIAAAAHZQZoPg%2BoFd32heVCPEf63%2FW9VX619Lfur%2FW9XV16183fR%2B7Bv76Ee%2F1rv9SdJ61V5Pqv%2B%2F1qvWsJLXs%2F81%2BtpfRG7u7v6R6yfP91gj9VVK6rsUvdF%2F%2Fu5BX%2BiQUTx%2FL069qw33c%2FL2vdq5Wqviu8CiEeuQUriP6et1eX0TVeiv%2B9pZZ75JLu5r7l9WO%2B5fe6T95KOV6ppvXCvWrlVyvWKrWL9e77r1r9dVuu9erkRT3X9q51S%2BrS2uXf6vcWuXcipuS72rwlXKuWW4m5bWq89aUeJP7%2FJurXz6kg%2F8v%2FvXhmckY17Bt1b9erpf7%2BOV1CuW1i%2FWKYR9164T%2BiRVfckWi19LKbNrDGS7ur%2FXL8EXDUKXTpXfrBXmx4EB0iWuX6xfrK%2FXKoRV%2F1rl%2Bf9ek5sVxFzXVxEjXat0R%2Bvrpv1q%2FXvdEaW%2B5bk9Fc%2FVyK3X3zL3uvX6vG3V9yXFd3uvUX%2F9aq6u7Vpbqw4dJuyuP3NIIfZfr%2Bb0IerRXl9cu79Yo316uWvXruMuXz%2BsMuyR8nq8nq5Noytfy%2Bi1XrOTXfojIv1qa5xXXrhXrKW1lJ6sRfozk%2Fo73JRFxN36KZ4zrXa5RoqRPL33V1f6K0noj%2FouKJwn%2BasfrF%2B5IAAAAHCQZoQBAoFf6FtdyX%2Brfrlfr3fRHa18tVfOr%2F%2FrX69%2Bvd9VRfa13wyvcqsdrX%2F67FepG%2FXu6vunvqyrXLtWk5V79avX5KpPpWq%2F176Xqw57od3dz32uVDuZsR3eO4pq9EYv1fvd9X%2BtSV1ctSKRK4pXmL%2FxH%2BtYxfS2vTeevxEYOX1ZXSxXxCxnUrTerv16%2FXK%2FXpbiYtXoUvP9q1T8TRPr%2FqBHm9Yui%2BkUyd%2FrXd33fq7u%2FXqte7Wpb%2FVixXXq3a1%2Br%2Fr7tXku%2Bf4n9WKtfH6JqJza5qq7k5JMmJ1u5fVwK67x36S%2BWTVW%2FVqur7k9F3q7uS1a7Xu1wlwnXpvV3d3Nc9161JPw%2F8mX%2F%2BEfJrMYm9E6b1yrHe1yl2pbi7q7uvOVT7Ka%2BI%2Bpu77l1Xouz1s3JTyX3EU8lzesolZObkFCv3H71d6ojy3RPP%2F7ryaCGxeZb7RWjpYn1b9Y0RcniZqfYIZTfgh3oqsv%2Bborv0Tv2RbV3XvmYZlj%2B0cqppalVyI9EOnderknsvJD6t%2BrfoQ1XEXWSjuXPRPX%2F%2FWDuW1dL6uRVz3LUvRnrU1%2B8LE%2BP%2BS8nl%2Fop6X1ysv%2F6M3PL65fq8kAAABqkGaEIQqBXfoSx%2BtX0rYjv1b9e6b9W%2Flur%2FV%2Bqrqrr7%2FWvLVzv%2F6X5P6ul9Xr7v9Yr9Xfgk0dWfgk1ZZe6v%2BvyqfHfu17tYqFderfqyamu1Y6pBy%2B7Xv1wu79WCuS1Y7V%2BiV67XCsKav9al5uua1aLvtX77uGqxT%2FrVX%2BtXavyxApf1qJ9Xq69cq%2FyVf9Xx3nfL%2BsV%2BrE%2FJdrXRH624IZLV6v3V4jiO%2B1YbxXL6xfr7uW69Fxkdcf6I12vsnz%2Bt2sU3qyeCSvaV6qq5rWq9W%2FUgJrv1f82zqItdd8T3JRN%2Bpkq%2B7uM9YpPWv1ivFZLXKPu%2FVy7r1lfqzusLe16p%2Fdaq1ik9X%2B1f1RHiPQmXc1%2FojE%2F3iK34zWVWrsc7shDzVvE%2Btfqx%2Brf1hHfr25%2Ba79X%2FVie4r1qW1eS5bJd9X%2B9pZr7iC%2F68QKXlXoj0XKIu7l9X7BJzbb9Gc%2FV1%2Bi6n9XiPWYibXpvRWO4r1btyz996FN%2Bjt2vS2sHcV6udwg%2F5ri%2FRIJl%2F%2BhMvfy79GaIxPyaL%2F8I161J6L0kURfq9euWXwp%2Fn9esVjvbXpIAAAAcRBmhEESgVycvy1eIiVXrG77q64tYv9fCXf9%2BtVauVOr1xPv9f5f%2F0Xv1i9tZSfXol5PVpLxS%2BhVr%2FtZZPnr5LVy%2FWu4j1ykuYUsnq5L6s7k5MVvHK%2Fctevq9YJuWS5BSxXq0t%2Fq52sXyfSu%2BWx3Knc3q1%2BtWI3JdaLL69V3%2F2vXff6sq1%2BHxdc369XEy%2Bvd9q36sV6J3693dovVyrl%2FXr1YNB2K69fgvq36133%2BrTerFesu5PWVetfrKvWr7qCFW%2FUtV%2Fqev16sI%2B1y6ah3OkR69fomUnoteq69lXqmv1ZXJ18QR6r6rmp%2F1miH63cTa1P6tNa%2BQl693JXVq3616HLFr%2BX1ZE3%2BeoZvp9r1d%2BiRVd3L8lF1xd%2BjtE3Xo3R%2F5Pb%2F6SvRfP11%2Buo%2Fy0nxXq52rF%2FJ66ibXu5bVzXVnO%2F5VUaJIu6FdXXJKK3foQ1X3J6xd5PvfuvRYoz16qaFfRMpPJslr0Xu%2B7u9UIykiq6X9C3kx%2BJ9XTXXq8Z6vNc3o1Sk8f%2BJ89fbPdhJes3mEKMrU4Ypf0Pbwjm9a%2FVpbk9TpJ69frFEetfq0trliu7rn11r03nr6tp%2FnKqO2eP%2Bq1iPRKkgAAAAbVBmhGEagV36EuX69XN%2BvdOsWT8%2F6Ed0I9FL3%2Ffav%2F%2F2re32vd9r30p79Zf9%2Fa19dfKiymGSL36s%2B%2B%2B5vWXzK67%2BbplcaZdx5Jb7XLtXq1ZJcuqtQpa6VyvXru%2FNd%2F6xV6tX9r1XJ6viuvVr9e%2FXq9WoQv6vYhXU69F9VyK1R%2Fclr3a9hLv%2FWcZ%2BiB3yiaf9W%2BI%2BapvurujlPV60oH9e7Xq5a9Zfq3dTfa%2Bu6teui%2F1wsct%2BqUv%2F6nBjlf363q%2B%2F1arrpYrv9YL9elvvq77WUk69eSvulu%2F1r9Yv1ab1MlevV5Z2Pv9Z1XfrVUivJWuV3VV%2BpQV69IIJm9EavR3%2FVy7%2FRul%2BedF6rr1eS4z347kTybSkv6Jq%2F%2FRZSy169fE0j4QubutEWr6Xu1f5pPVo%2Fyd2vl6v9eiPWXly2rO%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%2FLVKtPnrJzRIZLQfVjzGz3%2FKUVLh5iYXqAJj7lB3R%2Fm40ASpofee8G5K5%2BNaV24XFyAEJwuN%2BqacLJCEaEioYE53hIHVMHAASgUiCoSKwkGwkCoWDISCYUGQlCYlCYhCYRQZkp83rdMkZ%2BOeO6J14cZfPASaHZ1t%2Fl47dNm7g%2FKOc8i4j9RluLdJq7V%2Fotfj61A%2FV4fk8wxd3Zl%2F6qggvpAvkGFt22z4t%2BtZj%2BRt0Wyfrzo2wB34a%2BFK%2Fkr4ezYlPcOuDY4vM2rOE%2FWf4qkwftl2Dae5v8X6EKlFV7VKRvAFAjUQyEoXmILa4gTuDgBKBSQRBQJBQKhYShQShQLBUNBkJBQJBUKCUhhELhEKhFDv9%2FW63838d0V1vf0vnczqd3rczUUk6HFery9n0cVfKnRtJ0If7U%2F%2F3T5%2BX%2BT7bgmpI98EDa7nf5Py8QOnTzevljQfttvwAj2W%2Fkrhy97mK9cHVlpp4Q6ABT3EKsYVOe9Tux2o70PSYjFF0CsTfoePtIagZ%2FnYOY89u%2B2UkUhtjTeG7ECpHgthJpC6E0VXNUHmAcBJBSUJBQJBUJCYShYKBYMBYKhkSiIKiQRiUQhQJiFDvXOt79Xx3RevXHV%2BfmleXd3uSVV1dewd%2Bzweji3Z7%2BPUjyHLjR9z7xFv6pWiNBvfA7%2BPSXX3n9G7ybkK7efhoOibyy9zK7c2l11x4RaM8DlH2u%2FXN%2FVWSTXJffhZlWbpbHGoVIVJ8C9OiV3eq%2F6D7rzAuz4BP5wbL2jjFEVsJJYXwRmIhapaYqFLlL3OAjngDgAAAGMQZoSBIoFcvFd9ffwn%2F%2F8mIiXJTfq%2Fa1092rdFrF0IXa903VL6Ky%2FRKqnq1fFLXJ%2BsUvq%2FzrUt9rqh2%2F%2Bi6tWO1%2BFdiiW3cnav%2Bv7%2Fo6p5fXv1furPX8f1yCvuT1y7oct8V%2Fr3JXdCCS5uP9WH1iqqQUv65VclqyNuIs5l8uHnvlm9Hc%2BIXsdpC2%2BJm9cq9Y3axdESXLd3VyT9S1W6kBJOtSDv1%2BrknrF8T%2BrrzVpUJ5oqW8m7VjtYviZfV%2F1cbu%2F16W7vz6J7f92tX6v%2Bvd1cnrUTd3CMvqtTesUV6NUXj%2FujvD9Ss91y7WVerlesq9ehP1Y7Vy%2FLzggFperVXWqu%2B%2B16xS%2Fq8twtzRfouX6I6JtWPzlb%2B5pBS0apfV6urluie9%2Fwv6LhJ6M6S5Ll9C2O6uKuZeJrUVfaJV3La9%2BhDzr6Qkt%2Brwh6ysnl9eT0%2F%2F1c77jLrsw5MG34kQ7A1NX1X6H9d169dr3f6NBV36F1FeQIVeX%2BhvX6vfq%2BK%2F1gr167k9FavRGAjlkv9XuAAABj0GaEoSqBX%2BhLxHrXcvq8%2FrX6v3%2BpKvWv1rtTd3L61J61%2Br1avVq6rWpfWu11%2BuUnrUvq%2Fff6pw2tUOy4lcd07d%2Fqx%2Bt64la7W%2BO%2FfrXa1%2BtX0tfrVer9ye6rrJWvVau1qulrtaxTusXq%2F1e%2BlbuXi%2FVa91qX0MYFvu%2FQ1ixXXq75vpau11P61Xq8tNE%2Brz2r4rX6u%2FVl6rFJ6xdrU%2Frjk0J%2FRqr0evdYpIuvXro%2B7kupCe1yku18TV361frq%2FXpLXv1avWu1ZXS9N6ufq1%2Bsru7r1g%2FVknrFXr3urT3dyXXq%2F6v3Xq83rUT69%2Burwjk6Wq9eu69XV6xQp66vJk9ZS7wvF1uvVa1%2Brd1VWqvFevfomEX6L0tNXq6%2FWv1aW4Su%2BJjLhsv17yXLZvNi8ndy%2BuUnrhHbr3xP61J6yu%2F0V4q0au%2B%2F1q77jLvlR6r179ZV6uRPqzvvuT1y%2FBXvPV6tprqI9ddy4nL6wTeiMu5Ljn0nforT%2BtSX3V%2FolXclx2qK2O3hzE9f%2B%2FWpL9e4ypakgAAAYhBmhMEygV9y8b83%2Ffy2I%2FpCXJOJ%2F%2Bv%2F%2B%2F%2F1Y%2FWL%2F37%2F%2F%2F7Wv1r9FeW%2B%2Bielk9EqTdW%2FWVcyt%2BuXzX%2F62u1m7VgvXoi%2Bi%2Fm%2FXsd26I76Jr1f9eltYJfr1f9WO1yq1r9e7iKImub0ZztGeT0LfuSeSvvFeOl5oj1lV16pF9Xn9ek9CHVveXXJ19o7HxXclyWrV65yXDHuItXK%2F5V6a18l4nFdevTesX65S%2Buoi5IL%2BTu%2FaV%2Fif16S16rn9WCurWL9dSXWn8sSv16IuJuJ7m5Il19XE%2Bevso97EesFfxdcRl%2F%2Fv17lki4%2F1qIpKtWd1krFNcVc%2Frcm9X%2F%2BZZSS91a5RG8I2vWK5aJVvJWVF%2F116T1ZzozV6P6FuTpFauSd7rF%2BsF%2BiZRdfcTcVd2izFp67k99VN0bWWaua0cdqtTpP6N1evVf69fordq35%2FvtptshXk1WXSkuX0bu11H%2Ba7PN5hxolwvLAf0E3ktejL7iLRSpXqcE64%2Fv1bvo6vRLYr%2FXCN9HKkVaN3atcAAAAdZBmhOE6gV2X%2FrktCevjvn%2F%2BEe%2F1jfX%2F6t1r30v%2B%2F17v%2F9dd%2Fr3lr3as5%2B%2F17ta77X79a%2FXL9e%2FXq9avpWVwj0182T1%2FmXvm1%2F6N381jn9%2BuFX39q%2FcmSvX61EX81Vd%2Fr31%2BrV64X6sFa%2BHdex3nonj%2F9rX2veT9q9esV%2BrfrUTWve38n6vGbxA7%2FV6ylFLFcXVEq5L69d%2FEXOspMud8Xq%2F6xdrlJ61Xq92sUt361cvPd3quX6y%2FXsd25a9Yv1f5auW1qvRZRVompu%2FuvWK%2FWoj1f9YpPRK%2FWr9FlLIYtVdUy1Xat8R3N6tV%2FrUIerXfyebQp%2B79altWQl6NLu8v7R4vnrEfi6Sbx3lnpy3N6wfrl%2Brn%2F6u%2BX5e6v4v41ehHydUZy%2F9a1d933emrzckL88lcvr0twrDXJieoP%2Bb1eJ829NWWnT%2FWsn9tfF9o9VTfaEOlFPO%2FeTySMfauV56%2FH76eru0JY7MbbTGz%2For%2Fr1arX61EejZd1fdXXojuyjW9do0XcQ%2B9SCgmL%2F4aOCgdwsqJNGdgwgapG%2FQRerjL7m9e9%2F0XKie8vXXoZqy%2B760th%2FIIJEt%2F0E6q69XKtW6Kv11fq8nrF%2BGcl6%2Bc0e1%2FrURy%2BWuV%2BtSQAEiFJQoEgoEgoFQsJQsRAqGQ0FQoEguFBOEgqFAmEQqIUvE8%2BOPnxqVUqTLudd5eea51PGmkqHQc%2BO%2Fnyfvvzt56Novr09J11svqdU%2BJfXtHY%2FuL1e0vo%2FlXTzMwQ%2BIV6Of6vOrrKCI8umb4%2FQQQx61rQHjnLU4tTq%2BqemgyQcIivcUN2WLzq%2F%2Fzud7AN7bOc7JAD47jqcLxcdcgHpz4jw%2FLJNChT5xHddxuWTUnHD3iEXAzIP1vECRuTp0A4ABIhSQZBQKhYqBYMBYKhkMBURBUKCgJBUKBUJhULBUQnHcrPl7cysnHfxmfXvV55zd3zly4ur0OKcj1t%2FOiuN%2Fn65vJUOiznI3NPsL4%2Fm2DWjBuukd8eVr4no%3D&media_id=1254206535166763008&segment_index=7" + }, + "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": "command=APPEND&media_data=h4Q7PBkOg6O71%2FVqOgfRa17vA5vtVaDj31F%2FS9VcYnJCeAPQuxnSglhs7k8L9yKyd%2FFMzx8fjuRUCX43aprLg6IL%2F2%2FVvdxzGC1wYgTBal%2FeIdV8LXwvwlXqPQBxkKJWUkTXgveZqss%2FA6sMSeAKr3cUq22AcAEoFJQoJQoJhoFiuKQqIgqFAqIQkJQuFSCdz52nfz7U5urePrM%2Bu1TrtnnvK1wqR0HLutscOe8Us389HgPLWXlx63OstkmVlHZadm1HjQVr%2F%2F%2F6PobHdw%2BvGPVfLpLJzue%2FxL3N7sVHPGR2L92i8M49We%2FJnsOI8%2BBjg%2B8J4NeztdA4wEuwLlKEgrpF%2FHx8SbrXFzzJyTD%2BOgmN3ycL7yuS%2FiSPOQ4SBCgJYeVIGIdixRkjcjAEGf%2BQDgEoFJRIEwkFBMNAsRQyJwoEguFBKEwqEwqIwqMTueGvD8%2B071tL8eTz3eNK3xnNa4SVOA6%2B9wH6z%2Bdh%2F10%2Bvwk4Hvv1JZl8qB%2BsuuyRjo58XLwaiv0D8yiXEzHrRW5fUX9kPse6rMhQ%2FWL63ajzrWkvhv2P17VyTC%2BIceEcEFdL3sWJXQ4usbdmxQiQ8d7%2F%2F8JV9reZODuLyg7ne5VDlChznr6R3AboxkRwUHJGKEFEZJkkpiE5i0yqzADgASQUkCoiEgoCwUEwUCwlDQZCgVCQVEgSCgVEgTEQUCoXCJnvpWt%2FP6%2B%2BL507%2BLzz3rmr1txnNauVdXocq6zn7%2FTt9Zj7%2FjJt3Nv4fzsN9k%2FGy%2BXZRYXOi%2BzzDxDdq%2F1mrLPWy74OvwnsGN3xx148iO5JxDpir6GHO2nV5B7%2BfHXWhdqOMXNcDha5qyJxuNnpybP2WFydV4MnX91TNEMMSlGeqDGykd9nAy9%2FtFAxV5IAUS64w1DBvSlXLILIzUVd0gVXBwEmFJDMNAsFAsGAsKQ2FRIFgqFAsFAkFAqEQmJRGETPGuuZ373xtVXnXfV%2BffVVXG%2BG6XFROBxDVPj9Ru%2B8J2b8eU%2BsBq9VH1XScpdKD5jTr%2BNFFtnRdm5%2BzcBABChdHrnPX46ksqbIF%2BqVTIfayh8bD%2FAy8OC0hMLaxL37cqvB3jHymxDE9I1erVjONBJR9c3v2qcaqEXhanFsd6WJKD6U5do9cCC8%2FoS3SrUKPy%2B5EVXfdOsyMM6VJJ7lhJChOL9yAz2BwAEgFIwsFAkFBMRAsKAsFwwJQoFQwFQoJgmIREFwqExCZ86vHPq%2BsbrW7ly%2B7pXEusVoE6H5ncX4v59E5MWjl9fdQ%2Bv%2BHtF1Wv8cLreIvbbNf%2BrWek%2BxkaU3SbsgTEJVHu%2BzX8TsnM9fqOULh4GDC4LVf0afjH0z9QA%2FC%2Bv%2FpFENeypbLwJbZE8h5Tx6I7hbS8ttksK87eM4Q%2BACDM%2ByuFUrJbtsl%2BbnBUIHTxHMv%2FOYibwZT1aoJzjVWDtgWuGaELJyv1kG7YvIfUBwAAABvkGaFAUKBX%2BhbyevVcnSv1y%2BsElrFTOl7tYvtS1zq0nrSH6lSrWN333dF%2Fqye6tdXaI9%2BvUT0%2F79Fb9WOiZLWXd0v6uX69JdZdX3J6M0vorja5V6%2FOpYu7uhy4oQuf0Rr0SvRcpBS30r3VXrKhy5TerT%2BrEtq1esUs%2Furkvr1esX69d%2Fr365fr2K%2B69ZXcT69L6tJfat%2Bsu1btai7icuvWLX9Wvfr0vrXd3XqxPdXNcuI2rWXav165e1arr1wjriMRxS99q36tJ6u%2FWv1ijPRultHMD9Yv1yq5bUyfqb3pQj6NlLdXL6P3qrx%2FrKvRqjoIa9FlJxM1w5clorfop0k9E6FPXpifP8TL69l%2FdeJ9eq3Tz%2FaJBGYlnHgpS7NBL9YiK%2Fn9lglS%2F6EeXRP66k9XkuW4%2FIq1MM5eRe0QJ3Z36M%2F2vdq%2FxZqr%2FWOTWjMu5vQlirkf9vWwSDsmKwfaE9rvkx9F6%2FXDz4T1%2F90Ic%2FLNhbkxv%2Bi%2F%2BEwYixBcgdRqG1ADUF1LWPaa3%2FQ%2BpLk9Fcv1aNtcvpSgrdcqd9S97yz9cO4VCku1ZqEsFHbHMd7%2BR4rWr64vqQR1d3clxdyX3UAAAFzEGaFIUqBX3S%2BarmJ9%2F98QhNfrn%2F6Jr1iq6tWv16vXvLueuK8FjRcpPRKq79XVzL1c1d93N%2Forvf3963WCpV1jv0nrnq5fRK%2BatVir1qT%2Bn6vfW9khlpvy%2B%2FZP7JLkmfLZnJTkl4JoQYPtfwh71shtF0twrRa6lrHL7uTYux368n9e%2FXL4iYYt5e%2FzmY%2BY0Xcmv3%2BrjyI8XdVX6y9q%2FWKW4znl%2F17rl7rVcvVcOVeq69X%2Blyq6l7r1r4nvuhT3atXrPl%2F%2Fsv%2Fd165SXXrX61Qr%2FVKiWvdq0vq0m6xSer%2FV%2BKFSLyKYPlM5H2W3ql9C8qxFcx7q%2FOvyT1bx%2Be5vVq8puIWJPuT%2B%2FRzN%2BETEwdqcue0DFsq2rEx2oPWLmJWD5izN%2BWhbpea90T1er4r%2FXruvVr9Wv1b13u17W9vv1crxxM%2BHxmcks9lpF%2BxlKyzb%2BGbK8eLOGk%2FLGX17hivLpHmjtwgO2DX6ZNZtaf5WJIYlKkHG5g3kUbCX0LyrVWK9dRFyy9%2BeixUX73aKMsly%2BdNeeqWOj6%2F4ogdnqUZwDVt6Al%2BXXWX69sg3TOoRf%2B8EgihRwQHqfkRagianmQv7%2FglK2%2FBNXc378nISKP9QyRA4ZaDYNWztmf%2F0JfuvXV8slolXaP6t0KaTaG6qqqqqLokzUkx4zVxvCFvr%2FQISVUn6l7%2FkLqjvTxBXaAjazPNZTyj%2BkC%2By%2FV9iiWKDsvDtM0XoEpzNJTgppbgC5017YJZ7ltHNiUNOr72ZShcMxB65fX7XDWTkvOYlIPLfJYPiXf3R4v1avXv179e%2FWLq%2FXv16XdG6TxRFIlLR4PwR6Hf%2Bh7LbZ9zJwbpZHaA3X7tDe%2FBIbKw8GX%2B1xO9zUp39%2FkuYj1rvuUg%2FvtH76DggmI5bX7cRRez3PmyvLj%2FRXX6y%2FXv17u7XviIjar2YggjI1HF6El6VL0346Ml5Gri1%2F7%2B8vrfiCuWxWe4a46ZIHTJfCZMPsVlDkX%2FBMN0btaXZfrzoEQoZiP%2BZfa9fy3Iv3rYTkzUfLLoZCUvrauGy4y0P6%2FTGs4HL9Ky2f38I7DT4r1aTU3d%2BT6%2Bn%2F%2BUQbJMy%2F6%2F5sv%2Ff4JBZZKBBvGX5%2Fz2vwUEyeb6cUi9P06XqK8dH0E%2BLwasQGgTX7KIGBEBi%2FpcupX4eE582RDt40XnX8Js%2Fr9ZFhWHp6oD6VOv3J6%2FRe4yyFFb9SueubU%2Fq%2Fb5OpMrVxFRe6i%2F28v3%2BzQ4kx5fX9ddiS4c7GSQQm7sNMddfKKxsTsWURKpMf4iRDQr%2B%2FtDFz%2Fd2Rn%2F9dZfrrCRAO8qq7bwQeaV%2Fu7hyw%2FL9O6gs2b4w141tN%2BTJZf%2FUJW518MKWHM6%2B9fX2yNUcnXkzUdV6vbDPFmlvKNf%2F8v3s6KUetQN2N32qRrCtEMnfcu9eiMsv%2FaivDsNGzcwz%2BoIYybY%2BNg4svru0ErgieuddTHVu%2BqLGR83V66v5dnZi3VavCluzsnMFyrGY6ru5WINumCcxmJPHEHRe1pVvbzHxsY%2Bu3p%2FZhWPyoa132xPsTvBGJYvepOnbKJox%2F3X5SrNzU4bCfhTXItd991dl%2F1Uwg1P82Pgq%2FpF9sn6YKSizmX8%2BOba3Py6R8tJ7MU9tO%2BbcMv1H%2FkINRH%2Fgi5MXMJf%2FUEVFSSi3qqIzsgvA7WW%2FhMiksv5c5o3d6dQkbmwJWgUaGCw%2BnxFgmplmBoMUfV2uiTbpZPa3%2Fk%2FUER1rrfoI%2Fq%2F6uV6LWKVmrrb%2FBDq9vX8OCI80evqb9e4KtX5qUktjX4kpMj93J9%2Bpi9fX8hi3sIYLTrl8n2xWfGsmN%2FRCeTLhiCQjdJJk8fEsnJ7fk34uq%2FL%2FgjJiHHdk81979D3O5J69a7rWReqJ2X%2FrDE20mebLnyojjLbSvwQkZXuJf7WiHzQF5f692qpE9Fi%2FV3l01X4S9QTIvFEacS9Yjjwpaq1UTZgcUGvKEoVdnT%2BvRHx3uD%2BvSr9xHPX8nq%2FdZMnS9ty%2B6gAAAHtEGaFQVKBX3%2Bhbn6vjO36uVxv%2FxS18%2Fat8mIz000nrEq3%2Btd169l%2F%2BG174RV%2Bjlj1x6uPr79Uzl%2F%2B1c7Vzv9X%2Fkqrl%2BKVqrkte9iaxPxfX3ub6xLMbbNLCX2WNvNpH9bHT%2BlvFdev03rUtNVffSr2gXE%2BtEvy9hOYYpNgBC69XH%2Fs5L%2BGiaBjRdKkXf7NsEeCT5uE4q0PgjhI09cz1paYNZ7n5nsJSe80j1V1RFLhDsUtevqpavua5BS3aGMEllWrR37P75knLD6PleWr1xHxGK6217u%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%2FkITbsNl6Y8M7fwifZznde3kDBOVjG%2FKvZMfksgQCH6PXU9fDiK51x3v%2Fb4Vepyr519kbvvtWLwWDOvml9%2Br3cilN7HitVpzkl4wCpYuFSiMoBqKYnn1H5qgez%2Fk1ZsZBDYtk3hf1%2Fbmosr32Lii8zFjbGEGxGNFoHq4WxOWDKu1p0aIC4wdy2%2FLFEfi1kvl8rXckH9P8XLB9N%2FUEqLFLkx8%2BFUeUGBSTK%2BcZaTHAtKgUa84Y8K2HkVrk%2B%2Fqlb3Woi0XVXeajtxurW03eT%2BJ7cEIQz%2FhznKuNIkA%2F96FKX7MWgxkQSj%2Bjvo6BeI4RKwP42JWvjJ4jX3PpdL%2BQdjFO52XiF0OUgJwjjJCoJUX7wZy4bDlgOgYankRdsPxdH9hAVy%2BPoMzuBrmxc%2Bv4XFhqfJInm%2FADM1udfr7j0YJKhnn7uw7jCTCxXS7o%2FlL3qr6C5tq2D9gbFS1xV7s8%2BfzXCg%2B63yeTL7kFMBwJm8UfRpU7sGFhvU4YLsCqWeG5c%2F196rayfXe4dOwMDfBI%2BLZ3d4vEGvc%2F%2FYZ6IEr5en9fCbl62F97tshijw6WmgewndZ%2FfDZazHsOWB5MMK0wSYWTP5PbS10%2BK%2BZhu%2FqQypB08n3s%2BupMjBFmp5atwTFwMaqvQgTHqOwr7OL7%2BBLqHB8%2BL9XVF%2FsRqbF9OWjUOEeZd1uE97XJCrwlhPYOlsJZ4IL7rMf7%2BkYqzjHJ8fVlyc%2Bf17L91%2BnsUTKxXeT9r9C3MnxvqPI8dz7J8%2FG5bWZPf2qKa5R%2Bl8pA6hZfsIWtOjFPKw3qiR3CT%2BNoOzS5yxEsOCJSeNaSegjKq6VEvRwjp2cwlar1RHv0Xu%2B%2F16fxIpvW2NgDOT513ZRmI%2F8tnPdeiu%2FXCnaZyQYdwHh%2FJ%2BGXlaxcmci4VxXBA%2FR0QXjmV9MrI4X96dkL3LlTShE1xwL5Vy1NgIVcs3vQznp4OvJPwqNLxEsDZFkHikdanr7R96MnieNNrXXXL85s9b77sV1d%2Bhb17EQIt5%2B0V%2BvT12QnCVurTkyEHSyXkL%2BaIq3xh%2Fkjj%2BxWfCUwf0Cr70Eq4VV4ntzE9eGiNGTqq%2Fy1NTv1N0xA58EeXgftW45%2BhrU%2FVW%2FVjhjW9esElrKYv9qrNmo1L%2FeoKKmIO0yrW%2BsIbvPn4LNLa6RdfuGxo9lL61%2BX63vfxCKVKv359KkJs6%2BQg4hBXxW%2FEueYhoae9YyOQKrL%2BPc2nzwEuCoRxzmVAJQ5hF2lvHa1VEy3XrKsn9ek%2FufaRa824AAAAZ2QZoVhWoFfffdWhPVa91L3cvSufOsbte%2FXu%2F%2B1bvvvpV7oxXOk%2F6J7V3at2vdHdCKL3e2ENSqr0TKS1%2Fjibfq1X3V1%2FyVN6tm7VnHojH1%2BiSr0J79Wk9er167Xv1lXq36%2FYxfdq2O%2BH2vYhe5By%2FFxzIj8Wf01lSf8mTS%2FRffEr3P0SvyT1%2BL%2BqubVWoYvv17ter1y9CqtWqrtCOl21bL5XXuCZpio3g3J%2Bf92hPd1hCrVa9%2Bqb9W7WUnr3a9ilkFLVqx8T2rY5b5Pf77wnXrhLrl%2FVrT%2Fawfq1cI3xP6tXrFL69Vr3eK%2B6v4mrXq1YzBjUJvdf0EffPl%2F77tE6rXu%2F1ZV1deuu1f9ZXctrl%2BrLwh3CZvjK9T18v2tKxh1%2Bk%2BhvfNYrq1b5VSJ0TwSfxMbfaK42YVJiDblR7gjJWLwcXIvUpYzQoY%2B%2B0dlcR3Lavdq5ivuQUs2ahpgOuX33k%2BF%2BtnjwozE%2FJhOrIatqVTlQlu9auINmvtp9%2FydykckGIrDgy3NvNTlpzjUBXP%2F5PLVLCVg2gwvOSpmPTCHqqchH34gF56Fdbo%2BV%2BvVavx%2FqtqFKK%2Fq5cvgQtF%2Fz177FmzUooacnsEhDn2frvvvswmnGhMyeGT4TIzWcgz4OtaCqX3u5eNpj%2BL8n3KSrJyFYMJlWTAfLEUs5j%2BtAyUobUEpMdauJUOVghXfz3PyyejwfrF4Srf0%2FJqFukNpCxCpLRx73ldV9kOyKID7CXA1mzKxuDrcmW6iOZthMjSXXKkb2QstOjvvsE%2B7xpBo3QpeSWnT%2FBDYOMvT1RPlfyEWOQMbycEMe8LtAXQTiT4%2FoEt37htmsBxekCHjHmEnd1ujv%2BuXutfqa%2FWtP1a1%2BtSa1ivdWMFFDIyICx3kzjIiNWAruZODIy2uaxMpyBBrfW%2Bma1r6jR1gtLkJlGDNTi7DfDDlavVl%2ByCYdbs9l1k8fS%2FITc973UhMpdqhXF11YMfI60Y2qsMlaa1%2BmXUjPtT2HBFqDG9B%2FQxBaHhvru5xS93dbSElSr6wkM8bI3fopIQUfGFAkrkpiHWBLW50MvWyKREbeit%2Fq5%2BzH0nXginIlv2ZPnfwXEuzL0KMJn13u3BFIwTF3a%2BjSwPnJ79U4IigieWEnAcWXYJI%2BFCjX%2BFI0dedN8l16LVWr8Wj1z6NbTeQZQcXk%2BJfw5jM3FWPqraBDAkP6NsJ2O8gQB07rvRJSu7Ra7%2FDXj8pTpj3q6wOiR5G9b%2Bw3Gxr2HO39gjTMu3HbR0QRxwxv8LicET1wpHYiez5%2BvDs8G%2BMTW%2Byirvk8tf5%2B8dF%2FlZP6v5MmT%2FV6NfJR9dk7iutyfJ29hcVX3uTOuHVK%2F5PHXyeX6ylYFHLnJ8L%2BYxwwFwwIkPrk%2BuTiRRY0NCqMRjSa%2FwmeTw6Lf4WnEGFIkvnhOD6B3EL%2FRH%2FDuOpn1Bx0XoDJUBoYD7tgXiZWZUP33z%2BT8%2FcOEiGGo4RfKo%2B97CnBv9Fw3denZZXX6VH9gxbLLJ%2B%2B22WhgmbyRXh9JX5WR7WTyvJURRzkJgWtTnAdHgm5p2CDMd0PCzso3aDVyP1gn9dV64c%2FPM7oghgsMt2bLZo71XispXtIz5dv1orGq8L7phZaOcaArVEyoTyeEe3x82XgjdXM6qXuMtxuTvvdKq1uegTke8%2F%2BGomxQ3d3ntlc02C41v4RMF6Xd9mpDcQ%2FYkjHzEEOptf3y8nk8CJL%2B%2B%2B9OhHLtrk9DW77q1ivdmxmVAdTKpIeSaP7DfHggTivHnVF%2BwTQ4sn3a2OwUFykR5fKw%2Ffa5atXK7L%2F1fL67%2B7Xe7ehbHFlYtdJUX3Tar17yeH6ixQ8tXBrZfpd%2B9lOGcQ5r7R997C%2FaXm4H3zcykPNST1RXy5PH6iKx2I9H1VWvSBYImppbtNabX4I7KkOMkll%2Fev7BMWld90%2F4JM%2FEObFeEd7Hk%2Fg30k%2FLrwiTkgJftE9A2vUhpqfLon9r%2Bt3p7qivwzs8X1Z5sGvU1W6IpW9wWd3E808C0gBqVACAuRv8wfNe%2BFQDxVBPerv3vHf%2F6q9D3uS6WuEP1i%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": "command=APPEND&media_data=axfeT3%2F%2B6icn563VdQqhT8StdrKrueief%2F2hbVayrier9a77Xu%2FpXr1fpe1epHWu1caJpif2cy%2BzJCnifNPg%2BVIHkVQg1%2FpPfFfyffniekvKRpo%2BdlEWz6tCW%2FWsUt3ilFbFbk5bonpe6u6v1fvu1l0hTjuCQ%2BEexb8NfDYIYmSfcfQlrtEa4o%2F9Zd9rX6vNfeIWr6WvVyvV6tWP1lJCDIZLvrRe%2FQt%2B7gxqNV3dWvdX6tXrF3Xr1%2Bpk%2FXKf%2F1YvaGBCckCwrYTBH5cdJB7WmCrSeaMU4jLw%2FVZfQ9jV8lN2vfr2KxWUctpPV5MK%2BiLve%2BYmPELe4RFLBQy70Z39esn9WpPaH5cq9PutSeuHf6ykter1e%2FU3S5Hk9yu%2FBQKrWbMhcRjDh1DOQXfgPPxv%2FLKlVePtTdqdjvcnu1%2BJgIFdGt%2Fvq00qv1YyfPrjMZQpyoWNaD46FlG9xdQrNFBJEJhZaG08ogJs%2FfoX2i6k9ek6kJ9%2F%2B3%2F1eS5PXL9Wonv7uHOejrow3w%2B9yFDBuNeYRLwd4GLbwgcqZ%2B98N354N%2BM%2FfEH9bNqP4IbuKxXrJ%2FfREHr3Uq0740vB1JAfGSH3c%2BstwUnMQQvDPzkkWn5N9vpxEwtnwwIEGr9tN9%2Bx5HjjLHWgO20RCmR8MYa8nlf0CrVegv3%2FDdpPxTNPp8NapAoj5CKdo9u3eFvIiIUQa8q9UeiDMSagPCCdUk%2FqhPV6vVL2rur9fd9X3JhKjxcSCQY4rFYWcq8hQt3cV6FW0OY%2F5ihapqILjIK%2F0Y%2F%2BFYn%2F1C5GKAg8lOIr5aCRQsvFijmrqPfL%2F%2BGJmMM8Hzr2BXTowUJGizqSq%2B0Rx%2FH0JcUrTKfPJ70TuCAiQ4ysg9mclKgNQcZS3h5dAU6W%2Fw9SzUaRI%2BbGbLptwNpqzHl%2FWxwT27RBf03EwRkHRJDPmbZ65IXGSP0Dyj4dTtdw0UbL89H%2FlhlSqcf9wrOOmxhOL8eIikulhm1P%2FZydaBN731Nz1id5MuK1X3UKP31d%2F5PezlGxbBBd3DY1RwqlhHxhrpL0sIGpmMI2qaSj%2F8EJHFZbxV4XOgCGeZoLYCB3GMWQ21iZO1FFQhgORlVcv%2FuCDlBAEoIAmHhsL%2FATRgtNUvKzxBn8MCqir%2FJ69bYajcr6%2FhlFSf%2FQWpj%2BXTfXB3h9SqnViuCU49IoypQGkny8dLrL89RKW7j7P3a5PbvwqIjpkwfmLVxoEpTp5%2F%2FPX5La%2Fhrg1%2FFHZKc0B%2Fy%2FDU%2Fl9hnlwZB9EVH5mnj8yCF2wy2Evp65xL%2FeIDUXN3XojyfNLeL%2BRh4RWupnzkoaSf1x%2FQtU2USh4jKXV9%2FQWvIDSvL45PQJGeqGyUSgZIBfL9bdBrjLWAuttxsWP1%2BGzkhZZWaDArqeIUmT%2B6yfbBJuGhgg%2B9Zf29Qtl%2ByNn1ZxLp1vV9hW9AikctPRxfb9Sm7Q37V7nPX9I9ye%2Fu4cEHzJJMPzkI861L1rfC3LRjqypg8Ee7cfZdp%2FOdP8tzqLvvFfs93NfPw1ErXk8n7X4XFV8a3AbAhs7MG6A5fCLPyI4%2BN4gPcK0K7GGa8aE5%2BCrash%2F%2Fw2JYDgdoHlUKdazQfEF%2FvZW99Kcy8EexvfIMJ7k%2FlopMK9GXkr6o7mo8e2Iv%2F2nFFezbCZ6TUVvYVlWS4361R8M2EKNsL6YgtMr%2FXuDAlbG7lUXqud%2F17%2B5I1p%2FJGu%2F8K%2BXAhw3h%2FhYPtqxJ1NpAw8tDjDIYolx8EDGtlhftpwmV95M%2BkXgdvLEfV3lyVItavIInCU2fDcH%2BQdPAi4Ro5aMiiv%2Fha5f8EnzfqVMlc%2BpPdAv9HIsGuJD%2FXpAjPh%2BLBeG%2Bs0czwa%2FTf59FKJjHvrDQhLT5LEPesgVSmLjIz9tZjl2OkhmtaV03wuES0hAqypJUhPuAXrCZr60GDRWEoYwiT7%2B8UTbSfKS7eT936V8v9eItGCPkLsh6%2FV%2B5uI8%2BTTBEXd8Nfidy5tP6XiPmxnVVXVfSXeT9RPoKmg%2FoWl0DcHKWUe1iVzCkOX4Pl%2FrbCvX6enfBwlct9f9PRMOQQ%2FHKZA%2BPdnBHxIcjCJ%2B8nr%2FR6xq5h%2FJ9yekGhIJWpZ7xqHzf0iFZ8n1W%2BFrB1Ag%2FlygO%2B3Hvbl5Pb9QWmaafYcORaeG%2FzYnDpvFkh6EFdxnSpvXXVk%2FP8cRtJXCf68%2B9demSbP8krDlY%2Fh8r0CeNvj0Dov4j6DbgNynY%2BiBsaXKgXS6d39Bfv7%2FRuk%2F3V7u8iqIuyalv3l9PkwQUaChKxNvHUyNMpL5gXX6hMxKlum5EgJNAYFtui%2FZQ%2Fh1E%2BJFxneIlMuabWXsBsxAJSaDLlvX%2BT2nvoEFCiTW%2FDjHlGwY6WG2TRmNxIvx20UFlaeFrWT8%2FND963eewb%2FLBKf2Y9AVbOPtfituTH4Qjd%2FwR9XVsKN%2FwQ3o5mX%2FDZN31j6ev%2FbQ1tFuzY7J25WC00IaZ2rLft3QgiJ3jpDZxnl7CsiJd%2BlMrKWnKS2XdDyfVGFXbljxGO%2FDPh4jaeQQHPGVXaFX%2FQj4gp3jqvzxEl1Oiv0V2tSLvC4rHROQscFwOBrGBkun%2BX%2F2wQ29PXYZKELDD%2FAuYnRsRWw2iwNpuqwsO4zsN6Qy2aK%2F%2FBC6eI%2BpOuvc6hk5XNtK6%2BPmjanynND%2Fbjk73y%2Bf5fZiZIZPu98guEIods816jOgvmcee6SI3lpRkYsCk9pZfRCDaE8FhsEI0Z7x8PRkfH8LkxtSaiKCWki%2Bgxxl00qBIIPUmpf8aJ3ZOgOECxvT19%2Bo4s26N%2B3SxhnzI74rPmVXqY5e6Nr1gt1OQx7RrX%2F0CWZ59RhiHylHzEHe2pYTGnwQbZluNaaDdnGPN9WPpEz31U6h%2FTQ5ecyieP0dThvLOxfwEHqb2Kvsbp%2B%2BtXfgmLn9u92rSBhonXSdfzLADR%2Fk%2BPozMv%2FdCiybL5ffJC6HraNv3IIwW0694mTy5fEuz0hV5%2FaMQ%2FOVxH%2BpSzYx78Ld4pD3pcYq614aMCiPeL8OA9B4PnOHjQpfQL76xGAHs1Zi40v%2FnQ1qnr19fr1T1urUzS%2BgqQMZZmdV%2B%2BMS4%2F8RaZJJarL%2F7ufLs9z%2FvsTZjLt%2BDC9u03R%2BP%2BMcRDdXr069Yq38Vr0fW8t75WMdLzOUmbMvrEhVhNkJevIw%2F6qq3TA0wYw6xM2g0Pil7cvpzdegi9Xdrl%2BvSeitWWrAnq3dcmTx%2F64m%2Flba%2BWQVC%2Fun4fOKEemE506VmvgAAAKKEGaFoWqBX%2Bhb3zdPJdXV%2FrLuvXr9cu1jK3Xv1y%2FVzvxnq%2FXsnz%2F99fa1k%2B%2F%2F9UtBJXi9P2IJkn7Xu%2B%2B17terF116Fgo5iRjWXLfrF7OvUvCRA4IaOYsMSv%2F%2B%2B1zLH3TJfDxhhMseWldjnhlOOuqD2WDaeFl%2FWFvjo1zq5Ca9XP1K3WvV2vUOVeR7Vqtdd%2FSxVa37%2FV3ffffP3aBQt%2FoEIg9rY7Qq30ZBny2ozLvjWaro%2FkQVxCSj4PRjXd8Nzo%2F76GsFhLoqSU3wXJSaUK8IxeAJQblkQy71YFh%2BsS6Chfidq%2FG4dumrPCHQ8eyNfjpHWZxx%2FXU2PtPfbY7ltyDTQa0ngNSlsGj7CKCAHe0m4fR%2Bqi1yxX%2Bvdr0lrlVq8uq55bV6u6IpVxBzL4P9Ma4SRi4blBN%2F4QUuR8u6YVy%2F1BVqonx5ePL0ZcyI6l8mixgpHAMl8agVSzifDQrj2fhO95O1hcjghukE%2B3mtzXfo%2F9f%2Fr3hffS9XrFPdeuV3d%2FMtX6165flmU3nOIXz63%2Bz2m025dLvd8loWkXde4JVfnkv9X7X5d3613%2BtfS1J9WsX61TyoWYaOAosuiHZP0zIB2wO%2FQdAwd3EjGDgbANRHxKCLvb25sJn7y2kN2qwVN%2BNnGBzAbn1AJAxPBSxnq6HeGiAyBqm2GX%2F5fazkxPNcuPmQApTPWQjjx2T74%2F8np%2B%2B1%2BrklQ3C7k9eiPWK6av7WvoWTaGYu2xssmXzeysUKJtOTvA3I2T1E6zJispL%2BrYhusTDfwbfR83ofMV%2Fat1LGu1ruJ9WSbqw7WXxab1BAKtgXYEsw6HmTmVMF2zPMEvWn%2Fwycwg31ZiO%2F1ZGEI2Nj7BoFLLRlyTx9%2FfqMJe93d2dKVSs80TLQbhFq0z4GvVDNVoSyvUUXTSeuqpO1ldyXIMf0imzFDhnYMaQUJceepkxd18n6v2HPLFLzHhQoHZgVuD3mZfTVcEOK%2BLL%2Ft4XvGhhcymWZwgoPqz1GURrPrXDQmab9Y0bTw%2Frc0RLbRhoGoavuBf2IPe%2FwS%2BTKJGOGSf8nCLBM%2FhoQWbD31GkQ3wymkgZ6ijs6cGa%2BDGZee2e1%2BwggxY3jECEH94mbBsGVzWyF916PV334nfq%2BO%2BX613VasbQIw0JD8dqcmTgafDIIB4q93u7vAWUOWn%2BMK8UYhzdmEiPGkr26%2BvZj7rd4e0BxozpOCA5w3A%2BgUcpbwSqh%2BuPtykHk40gIzzwPyIqVKOETWVNQd%2Bl%2FL9VuH%2B3vnsV7QP2MHXTDM7H%2FU0ihsTP9%2FpxoEC%2FYLyl%2B9xW9%2Fm0rEZGr4JyEoQ1WCB5d%2Bs52%2FkH4fs4WYxhq%2Blwvo8fTQj5Pq7EM%2BNnDlm%2Fe%2B%2BHssVaI%2BCMjGUgio7y35YY4rFeMytcpkZZ%2F8EpT0H2%2FqPEE0OdP7c%2BFaamewkTGUBsIxKYxB23%2Fs5FNo4b6m573RypJ2sV%2BsHBGr%2FrKrRe%2BN9LfxfRPy75A0CMKDr3FGKDFGKOcgot%2Be56YVigxQGJcfgOh5fUPuZlDOfxDhoSwhkFrQNfhuTb61cb5QU7geG0Jw5VY7CIoQ4GfQJ26nrciz9f5Pd31BISifBp8OlSMCghwzI57CFd3r8oQIwb15Pb263akLe8nhqrQKhDvxuZEh60w4e5MptXj73UEInyTO%2FETwG0xaQX%2F%2FiBA%2Bf%2BkjL6B%2FDs9Y%2FZTaDfCQlTc%2FGauPfpD6BD7VozmxT%2FU6MezTvVpBWOsm5DYZz2Pka%2B2P495NO8q%2Fn39CXV6wVBDear%2BX5devV6vuworL9f9L%2BHhkEe9%2BbeZOX8Ej6ftAugNSqGjDVDmulL7%2Fgh4KcuzuKKz1bGTNJEvr%2BvVnHAwFNDB%2FiF7PXgh2yf%2FaE3bx3zc9L11AnqpBAfQpV5f8qxfqx7%2F%2B4vCXB41pPJ6vQS3%2BFuwQ%2FjbOn%2BG7f7VH6K8%2BSuE2hXQh35Ah7EeTva0KLdYb1mYUZfbIf%2B2CMSgDCZgrH27KUMmBrmPQcMBLn1aCarp%2FeyOrm7yeX3%2B6W3p856%2FaQRadw30br%2BTDkGv3e%2FuFyPG0GVdcq9CV5fG4BwiQpJGynSShZPf3wyaYMDaX7MqiPuLmgu2v3DUJ9hDUU1hpxm4H%2Fw5zmLNf7QdiifnKvjBVuM5AadZ8v1xEn6colH7zn%2FQrr2w15usN27%2F13gg5IR02acROoFw0nqX48OSCWCxcar6BR4h0iDAhNzBAl50%2B%2B8N82K%2FDvZf3eYuH1yBXSZ0d%2FwoIqZjzc5iT0UaTGjkxxfhuHFM7r8wudR5UbviCGo3adn%2BPPKdQd%2BKdcIVF1n5P781F78Fx322DLj9fizcF1PcoCpGdC%2FM0v1VklMdi3AmGgX8NCxlsoPac%2Fh1nP8MxCaGwp%2BvoxPWpErW5fVudFjEmTJ6t%2BsVesF%2Brn4Jd2V34uffVgqEWBi4mPxD2edzb7L%2Ffrr8pyqJk2OT98QKsFwhtZQwEVv63re%2FwTljVIe5MVSY%2FfgwOhSQ%2BC2nISI583DSL0V%2FhnhBh7dr6kx%2FeT2%2FohgJ39Ln%2F%2BE4bqJLD9y%2FTtIpKEMZexXISmmpqbKffL9u%2BMI%2F%2B8JzrN1gMiqhUv3Z49XF8m%2FQ%2BORJC%2B8CL8pw9vzAY%2Bml3%2BOmFISrX97a0zMgvc6%2FG86%2BggXbkHXhaJ0YEjZ%2Bc%2Fvr%2FhsaO4blQI3eaIvam3%2FmKq%2Fyyfr0bpvU4VerUTwJ90IjAnQL76PkhrqVR%2FzTQjucy%2F3uCyksSmtJXv7fSiSkloCcIeir5T18DdwGLvj%2FL%2F%2BKyTS3LiI1epvhvmb3NDW0NzX8n9%2Bps3f%2BFt6G3KY5VMx3GCL116UT%2FBJw5icvk9qb7BESCLkz4pGk5k%2FLn6EEQ0wrq6Nk6TVqZ3bvJ%2FRcahEUPu77e6eYzUQXjyvbu7u%2BO%2B5Pcx7lwhdIubu7u27fUdDSe7whq7WY3kr949ej4TW%2FvyzVX%2BXdV5YssdkM3Ocfl%2FVofF0p8LTEOBx6vDQiT0du%2B6h9cr8wgtP8VxoTlDwlxV5Iv1378KePmLQe%2BZd1bqcVHdthL%2F3uPe%2F8EZbSNFkpRftf%2FZaZktF9GY7%2FDFpVoh%2F3WkRI1X68Qe1LmGsGV%2FujQgZpj6U9E7X5DZWGAvk2WfqJHs%2F3vsmWkmfBDJi0u%2FETY0kuq%2FFawN%2FgLyklJ%2FXLyhETVhsnFb3eK6ishAjWoThu7v3FdQTE0OtPiXBDTtlyJeitPdRNeCIx7n6vD5T%2FQ6DhzLTqNeb4%2FC%2BlX2COlu5%2Bew%2Bjjh6SFrb4I%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%2FWX9WxcWfV4Ktlg737tXDRhmI%2BromGPf%2FKewbLrEcX33QqB%2B%2B%2BWiXX2CSHZqdBlJxj8pcmLd5%2Bv4djxS4en6GKvkq8hN3SpMEXit9fYug8%2F40XUnvL%2BG4cXG%2Bmo1%2BxQwnduTp62bl4YJMewSHd1sZPNf%2B%2BwX52NjoERdfjg%2BRUVPeTw%2FiSBBW%2FtsVCpyxZTYH8RPPHa%2BhsJoRg9jyTf3p8E4tqFn1mNv%2Ft4Lni31hgxyVmAMeuTXX2qkzMQW551anCASIvl%2B%2FJEmfRlkhT44otpm3thcSUaMS49jr5KDEr%2ByXu%2FDYnFcRQzk9P%2Ba%2Bfc3Ya1gQEH3K9fh1OH5PruskxC8aBJp5A2VWGeEJ3ERH8ntu%2F32Ykq1%2Fh46cYplBAUupb1H7EFR%2F1gmsLAy2KFxv93o7IYKvNzOIfhPjC9M39gg0oR8LUD7LGtj3z4XCtyzCVQOFa0y3IaH2XzkVaRgP%2F7BPwEj9zO7QEe9PrTzbttcrTKPi19jyWhT6avk2Q1YtGugHqUoNYD3nLRuXyetcfAdU%2Bezntg78AZp03DfS6%2FCfTdU27%2FKfF6egwWLVECnqdCz4xCs86h6dHDOrk8%2Be8FA06G2zs5cpk1nX4Ra1UqJF%2BrfrKrlVvdKPJu4xKjhJMx%2BK8C2JsM2pjKkcKcdJb7JGqTqt78KlqyWNUsYM0Op9E1Fr990FOdqH4%2FVva8dM84tlfVl%2Fq8Ru%2BVi%2FaHGRLw6FwpGN41RS%2FJL44xEf3HKsaMajdXzpBTS2l%2BX7i2SQRFb%2B760Jwoe7u98If49NqjrfIyhC5MKzGW3B%2BxlxLr1GUoGNiY22OtBMdTjKZnUXwdGgq1T9BPMXNQRw4594dCIuJNBJykJ4PMmYdzoSL1S8U8TwX6Fiyy407Np61y8bk%2FF91notTX%2BQ2TGaVWHM4gMeB%2FW1Gzz9fZc3MrDLfvsEZXtbDf65b7wQlB7p6rUERuc0WiKnJ7iN7av%2BcjnJoRedfc6kFxodf5UEc%2BbWcQcs%2FoEJMtNaZFCJjdDWQghBO6%2BVGy0n4fZJ75JX%2BUgiPRBKrfm6P6iLpLsOzCpXhii%2B%2B8kQhBDzgnkmGw2HcO5fqCri4nmJ4bBHDuffhGkSFRBwU8TxdmS2Sl%2F9HCInPtuJeu7y%2Bi%2FKP9UOIfNiTM%2BmMnyOrNE8esWPVE%2F13ZhEbpncb4IxZxpm18HdP2%2BSRIK1J5ZLNEYyRP5I8kQTdn0CHfS%2F75rg686DGESyYTOnFTQa%2FhUTnUXaTMLLDHmvy332OEFltGObSVqtcFHB1U6RiUVZZCO6f4Uu3J8S2%2BKMQOYUcuvsIdtaijcXF0v0LeWhGb1er%2FVx9EYy%2F%2BoLvNirsKbxdWvSWT4%2F%2Fw%2Fvfd61jK5ahxNLgenohaAcX7Vb3j15X7glMfHwb4hIxXSP%2Fb6LH%2F2YOa61l5M%2FhEkH2aYHOP3G5y3%2BMFDKlzh39iZwMb5%2BamjJ%2BhAYMGConl8RETjAwEBZnNnJnL5sgaHCQEOCgoPLO81LpLr0Nr9a%2FXpPRZV6phN6IwEct3WaQUFHgcPgo%2F5LgqH8XH5PfG8MyGnwb50YAAAyvQZoXheoFf6Ft%2BrVasdq5%2BvyX16uI%2BXvv5Vaulf7WKvXr9XO1Z%2BrlT1d%2BpLteq1yq69al9a%2Blt0q19LXz%2Frl%2Buz21MmEtSoXen%2FCAgxuO44SQ03L8VYmZDjSD8%2Ffr8zjhXskiaxFQaZFW4TGNQtlpNRcEhC0HB3%2Fu%2BEtDXrAg65FYq1r9dYpcV4rfxXa1%2BrF2tScQtfrX0tXf612tbQWwmL8eJDgzBI9MgUXUzN9Imp1340oLN0TLP2DqvcuWNYs%2BCCyjTPy4YjuONRu5Yy%2FkNGry%2Bcao2FyAg1seOsgWI7qC2YkwlkqEBGQ26T9Bg8%2B16SsYP9E0Pfl%2B8OsFKDHwGKtk7OQPCTeM5QfFG1HuT8Y%2BtcpYes7hwaLe8HYkSxhlzv%2BLd4eQJ0c%2BcWQFyrbWmcCi%2FbT%2B1510yPX%2FxP0tVfa3dS2Mc7%2BoJcm%2FrV16sfrF3LdWrWT17y%2F0Kc%2BgQkWdz9XNYVQhAkkwGUR%2BPr4gaUXUUxdXF1Jvi%2B4uLpB0jGUNVk1NONsVfCsKWlFxdnLJnxcXxcvUXUaUMVeJqCaJHHenukPUEN94Oq6W2%2F39yctSoTXdctWpE%2FVupayfn%2FJ%2FfzdX5hi1%2FJP%2FrGCIZZ3f5Wcik0xn%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%2FTQYYfeMaChPEBbLrQvVgpJb6bZ7%2FgqKHU88rhnAp%2Fzf0YC%2FQr5GQ7r3P4P0aX4sTe%2B75w0aeigdtMpmjK%2BZf7tsOnCdrvGWnb%2Fvyi2VeXHsTsdiP5rFvGW6O8nx27hXRoyG3hq3HX7DDafP%2FCogJJ9GNc9v6%2FWPxPk%2FFJ7DMVpvHzV6FaJPrYyr1PhrYOemEK7JFC0%2F2GuayEVH2aBnf%2F8K2bNR46Sxks9wP9GyL%2F2cSv8Yv69Xk9eiH%2Br5fX6%2FIMd%2B8SpVTr2hD%2FQ04Ifp0oxd0zQiZlVmGBhvgheXvu3FRJoi39%2Fh0oeafBr5w%2FzWSHWzcv6jIz01QxHC5puYh5Pn%2FDVBSkyB5WGUzjKX%2FTBCUowQWwZ%2F2ZbelkO6v%2BYzSCHUw%2Bn1w7RNd82GzrXHAxiBRx2caa%2BXlDdqaiNfykjbaVpHufwifZmkOzlb%2B2Ge06hwQYxSLe4m2PmsbV6QpjP56%2FqRG7P%2FyFtFSFXEX2iv%2BuX6%2B5BHvn08IeQR9nGMDK2oowJD%2Fh4ofQkqCUjEsatcw7FUfW5vbB6NMZ96f1rZS8ZEL6QOGx8QHU4gJFDA6C%2B7r1Ct41hPd7PdS4ITP92T6gkPbNbkrH5d5aXeFY6FmpWRr5W%2BhSRWlNA%2FNf0qoXJk8OpIQgfbTKtUEPxzJzCIy0i9OEeT3qrt30pPb9ScsMn7%2BoIpCZhi39k%2B8mnD9FYQzJ3FYdQ36g3pCD%2BZynCAyqQkdf%2FDBV4Pca07P8HdF9ns%2FgjbH7XiLqXv4n4r339WvzytmTv0v%2FwUGNkmMCsGaKoLXaug2VBvARCDhlFyDy89NQgeHa09VeidoplDZSh%2BHYuB1wxbX%2F2YuMnj%2BYvL7nwRCGt8FU%2FZBShMRwTyfijlJgnKmJYT4WH495C%2B3oLi2HDK%2FjDCr07PBWwl4SHg0%2FXqCA3GWo6y0k%2FxAhqMShn6xgwKu4UO7341tdtTq%2Fl9O6SDZkvRmLejB%2FX7cZ%2F3yYXEjz67xovn1%2BImvWHprHyFju7l%2BM03%2FYz1Dx08bPTD%2BindwEJqRXkeqhOovvaFfXfdCt3Fc1OXyd3Hau4uL8W%2FcRvSRv1%2BGTZuKM4cIOWCOGGO6pDB79vau1pKUpWL6dsOEDSLg9QCr6qx%2BbuNiP6J%2Fd7kwxI2tERbqFRJE0K%2Ff4K8uRcbedR%2B5r7n%2F9%2BmiHnyfH1gggmHhw0OoJWfuryqede8gYQxl2bBv9hwk0Pqa2nYJtvLfk%2BuuwxH%2FGvGK%2B4Ss0eFNC2UkjL0h5nRWGKYaU8YPyqPXSCPXmcf%2BT97uwuRMvp04TP7e22764W%2F%2F1%2BM1wnlZ6xK8knZEoBiLkDKg43IZvdzbfaWvN7tvFKpKH7EJrovfzqr7cf1MQcSzN8q%2FkzF%2BJvMtO7Y%2BKj1pJh7lWao2dUUhNG25UyGt9nbY8pYc5Vb369oMTppnNUIXp8Zb5DX%2FQKEnDCUv%2ByqLG4UMVF%2B1Lf7u%2B%2B6rkW9q%2B9UkZ%2FL7rzUtqT%2B1tILxhsdmzJvr5gi5ZLCy%2BC7W7BMfHTKDL5FWmCe7goxmSmTKCOv2g3Zvp15Tg08saT4ICyJX90NYZflHlzSjbf%2FUbNroHvOan8AkrrqxWJzxrSxVnNrMgjyfPfm1o%2BkCnDZI441pMX4%2BttNnTzFvtMURiHTMnwevvnBGLPD4lVpKIPM8BLtwFLnjZnX8B%2B9jfkCJnHU1AxXVO4uNlm90x4fPocZjoUthCSqcwUv4itZ28wXfZZ%2FP5f0cvH24XM%2Bd3ZxuU0jezIoQLDbplw3L9bML%2Fdabn2%2FWixIyhxhVz5V9u7ur%2FY7OO3rSMsuI6bsf8JH8Tw9ftDfuCsImnILNVl%2F2JQnT4s620a0ib4u7R24Wlr067V5Lon6X%2BKFPOGA48Cp6aS%2BxpQTl70v5aU0EqeXLNnzjqaJOtcEfPnq3FF0zVejRpLlc%2FP5Pz9%2FUKk5toYrLTXwpBTi0HJ7LVKEeW6V9mk9m4cJnyuMMyI2Nn19BIXQwhuR7itjavKsfTq3kIS43byFg93EyMBdxZHu8Haj30gibZjoaQa1xn0bCF%2By%2Ftdodx4hG%2Bn15o71gsdvW%2FcxGn6EYbOCFvlb%2BwS4NR1RG6t9RMF8BCeM9v8EpFayXqajb%2FNVeX%2B1UI6VohBXTS%2BijDkzt1L45Vu7e%2FphHdd6Grp7%2BLCXL3FbdqtjUwUEVOm3jfuit%2BXsQVPaJb%2Bin102LLd33S%2BWZItOrExXTbu1qfNfet7NuXOTxqnLBETlxvw0WVimuqT2X99qCjxvOCNodI%2FD8QIuGWm8CrHce8RSJ4Kv9yxHplL482uvqEY%2F40tfGCwvGeQkGRlvWYgxAs8mSTNnP2sQbNH%2FPyL4oxSlol3hEpyF4ZZbrrBFV%2Ft7bW%2BkmZov62Jx3cV7viHAf5X7q%2F9D803qdL9e%2BTuQnrq15PX6pmxDbL1v7DFqktMO%2FtfRjaL6%2FBDxW24%2BCYp%2F2l4P3CqZXs%2BK%2FrFef4lgiLDT3LjJ8GhET%2Fr%2BcYqVIm%2FiwtGffw19qfW42ibb9kBEbFVy1jFguIs4GM%2BGsB9onkUleHjCTlp6e6xO%2FQ%2B%2Fav%2Buu6y6tXqVXv179X9SWYjuy%2F%2F%2Bc1b3xF5O4O83VcSQY4hzqNBHcSw9YXOLaNFgBJBSUKBYKDYMBUKBY9BQLCQLBQbBcLBgLBcLBcKhEphcep1zv3%2B%2FNStyTOIzVZFKq84kVJ5D4ca5RqnW%2F5ijYn5r5%2FdB29tvXPRKfo5%2FPybu1E489m3UOclvr4fEgGgDwPqiuA2GVFtAOPOa%2F%2BH%2Bq%2F3aLvIAhrtIfh90CPw3ZAd3fvuXAfud2OevETCBhrbuhy7trwmtKWls0Igv2hUtIJRXqQUJawZfSLO6BdB7CUconVGU4bklB94R8m27PdDs7o5GofgTSgoIGfeD6O%2BotwuV2evBYVWe2iceXsUlVle%2BsYsmJBmlsz0mtOlerty20f1jmKJR72wDgASAUlCYWEgVCwaCyYCwkKoWCgWFAWDAXCoSEIzCwqs9%2FbITJl3UKSqopNQ1XsHs%2FWT7uY7a9824TwuSecwz1ZlowwbZ3%2FL3F1tVVu7KvPhBR2%2FzcKzTrBHOow09ZlLXL0L5Yvv%2Bo8DQvL%2Bx2YkFfBjfFtHc9ofm17Mzq%2FU7Z8AFru9HJiM3p%2Fe%2Bi%2Brzds6VZM77ECUJwv8AtWhL2ykQMCHfqeBE0BocFnWG%2BnXvpGgeSYNWrqEOa8CDn61voOiqIqHOumGJOxX1Gyc%2FG8H0PnAKP84pT3dJVEUhMU54HiK6J4RS2sPZfolPHaMu%2BK9rK9r%2F0ecDgARYUjCwUCwUCwUDAUCwUCykCwUCwUEwYCwYCwYC4iCIUCQRE%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%2F3A1ujqcpPDGu2tCy8g8lbXwpYHu42Kz4jYFFOLYd6She7mXMoPZXxACc5XucC9OHfec39ljP3ksz%2BgJjNRynIQA2ri9fZ3Yjy4JX%2BUziXlQPyPRXr9TwtxW0zSoWkKQawFrZ6hmqA6j3JV8%2BX6I7PmyFzTbabpvIwc%2Bvf9mVPBj8BmT8qBX3YEYTqP3KX%2FF9DvbPMBwEkFJAsFBGFhQFhwKhMGAsNAsQwqFAqFBqFwiIgiRN%2B3jnr8%2FftvTnrdyoElRVVxGWnQ5JyL9z%2BI%2FUa6i%2FSvOq0%2FihO%2Bqcygf29LE3zoiRvcebQ82Fr3L7KffASlPZdFdO3oyhT9B5sHGvS%2FFejzOQBS8vqubgUlw8u%2BhaDSRNvzMwOW9K%2F193pffzweXPluh0cTHpV9npR51yxm4DznftMZG3IfFlXH1HusWfGt3y%2Faq96zcu672tdesF8mep4cOPp9XWFyZJlPOaHRTlog%2BZgsaEGJMzs0pxUrN52xtMe0SvL%2BmgHAAAJiEGaGAYKBXV1V1oS7uvVv1r4nq%2B%2F%2Frv%2Fv%2Fv9X%2F%2F%2F%2F%2FVKvau7%2F9%2F%2FrrWq9FrtUq%2BtSUT8T%2BiO%2BL%2Bqm%2FpXrl6dWc%2FS3hoYFxHL3HjoNyrKJw4qvrBgKlDBAqxhLW2EShJkSW3JlSTz60Xf8BWHFL24l9C4q9aktXkwQbu6I%2BahXVJ0R8nOscoUvN%2BF3wKxpxi%2BzMZL%2BT1sa8TBJGzV3Kl%2BKh%2FmPHwxyoVZFS2TyR83Hn0%2B5NIla6xImQFhF%2FnY6zR8fQMH9B%2FQHVOlYE9GEkLO2ZfPw%2Bw3BRw1dUmrypIjTFmIvn8GKGlFAGfhcVlVEnIj39yj5qsb%2BG8kEQHhwhAVEHDIWup3jaEKpVP61wSFwWvhZMZbXhMgKNxfHqhPapg7oX317r3JdS9VfRmO%2FcP47zleidVzP%2B%2FX%2FyL1qx41Cq1SSDS6rzVVWq5gKGPS3Gf0pzE%2FEdJufWpP3PxU1GDSorfwgYbHi5eIDy8vdguXlNKZnkXpCSQOtZNFv5h6Cvr1Qa66UeBgegHKHhtGKgNHgb4ZsbC8SkgsVmbAdsdAUzvFM7xGYr%2FTRt%2FgVkGWm4Dvd%2B7vfDzOb5%2F%2F%2FBygYiCYWmmyhFcwK5m2VR3MtJY6X6rUjoq75K5v174SXLHYrn%2FXLaaoIhi19vBvlF9tTKaxB1x0eIFu7u7u9R0BUhURJnu6%2B0fejwre7vd18pk%2B%2BA5Ti1EGoN1%2FN37%2Fk9WfS5ScbeqsVfRK9Jy169ilr1cK%2FianXzfODA4UHQJg9%2BMQpsK2xLeGwY0qpZ6XRhlVom%2FUoee5hvLQQG4V4oGBDzTL%2Fw2BFPpN4K%2F9kBgECbBozNVQ96G9V5X2sGj4qxkSNM7%2FjEKQyXlU%2F7rRuC2i%2FL9%2FJQ5DcXhn%2Bve9WvVqsv1a7luq11ZPn8nwtMbPR%2BIlF4bnW6fiIJxkxrFzKF3bxKlEiHKNlIBP4iMBspwMjrKVgcpyiicUT1VaCPq9Y8T69N69%2BrSxKlvSFiuVjlyv1dv1GHkQR3yLI6neQgup095f9cITZgrx4IhTbmgU7vR%2FUYY%2Bbu0ZxfE8MZxxe9RTGEm2L9N2MGNGuhGpNjYaObxERqNpf1LJE%2Bup%2BaALVrckXiRORCe616XtWl9Xx3aIu37izcd9xj6CX1313HddZPp38QZtcn%2Fw%2BNEcMTXWmem79dsxqP%2FnqcKmRaf3O4aNntDYGBUFudJtP%2FUn0iZ1y%2B%2Fuawee79wjpEIYs0m2miXDv6eiSGtl%2BS7urR8pcGw8xbtaQNwgoY3gmMkCgduK3igMMg8IpFXxheL5qExUv1f4XoGUibX4IpbCdgqCVuKg2Ufx%2FwVUF46D3UKBK3ddXmX9yF%2BMP6SreGj%2FR5weo2rMq%2FbaSHhEYYpS9VaZ3hi2QpULps%2FzRyv84gwzFNdaiobWMvy%2BlGRAa3w%2F4SuTnoRFgf8T6abklCJo5bFY4b%2F6mvP%2FxZBqTVIKPL3%2BphfgiLV%2Fb%2FBFyXw9TkUppFLDyaovTcnp90KXw%2BQUWta34bCe8cgsESClXwHlglquq%2Fax5AutYoEYTEApJdWbvAXNu558fiew4KYVigDFAGoP0PoB3Gtdz%2FoonZko5gycl0f71%2BQaYNLjQgHQL4aJkU0up%2B%2FKsQcNL%2B%2FGAgT%2BGixdhDSy%2BG4klga2V9KGTHxvqsfGTmRRT6xV6KZeZd%2F4JTjRH997vyWRY%2FxBoIG8y0G31%2F5MoSjYgMv%2FXEbUvJXo7fq%2Fk%2B5hGqrBJIR38B1Egpu73fe7p11G21D6mLriAhts9%2FxXjQkuqyKE%2Fv0hJUKA81wHAOkd43H8v69GnMTBe%2Fxd3u%2B%2FyC43O%2F6Mw%2BLmsuZccUYrL4bLyTXB%2FhM%2F4I%2FCRhvxb9XPyG3a%2BrA3FfHfGfEV6PVX3XDHguNryfhAQKd93%2Fis5yU2H0SZvSO31unLI%2FXk7T9xBy4K7PggYW%2FP7u%2F8E%2BhysSqN68FWYYJySoeDIPM3xmhPXLL%2Fj2GYY7ojOV91%2FDex%2FwvDUq6B991cwyxMH%2F%2BCvWNxpaPzpvp18OTYwFqegWghW2EP%2FF%2BS9IdCBTcX89%2BivXrUrlpGfu%2FDE0aWQ1bU4myDSXZgmBIzqK0rkDXh9F3It46P314KD2qoalEdz8MlPK1Z%2FhXc%2BHBBWJUlfHBP8kH5BkdaeX8d8KnjuzUv3Y2iMExW%2FR0i%2B985exP%2F%2F9nbYmRAwPxZqIAMm31gCsKy1iovpWVkmZxKX%2FxEMGayAgWlt5N%2F4RobHf%2FkEsZx%2F%2BCKUxlY1p%2BX5L7rW%2FR2P16yfvyYaMWm3rDSItC%2F%2BJ5%2FeY7fhfH4BaxGkrreV%2F%2Fh07M9hhE47U%2BFP6j9%2F%2F%2FDNrUMgG6%2BMmyFyeCsRlzH4z6R8aQcqWQrh41lPKtAli0fVABLPqURnXpsWmSwHZEshWoNAU0LWwpl%2F5fLPR7GbgsXyWPaZwACtrozGXVmEwmvTxRST5%2FsP%2BL%2F%2FbHrvyX%2FED8ZZAO%2F6A7ksm%2BTWo6r%2Fd5awwv4K%2BElPJKSPqqwPX4lwvv%2BCsuPDPpQT%2Baoyw7NUJuXdfHby%2FDYvAsrp5Voiv4Ta8uSi5OLxT36txcvnMrBR8SKiX5fBIVWodlNMPl8s%2Fr34Vyr1P27qwzQPWdMtPozmvaEjSqLe6X5jY%2Fdeo%2BQR2QEr0ldL9bWOIH7n64NrUAprAm9bqWOTIq33oPWcjjMReWy3uM%2Buk1QulVQzZWhOEN3baCzjjbRL384QKhim57LuIWH3G1l%2FJvHY3xA%2Fv5f4awD8n13rhzktJc%2Bl37%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%2BaPiI4L8FBGIQ5C4oPJ3fgk6r35yrU2%2F61oKwhPUdxGM8VnIKhzA1pr%2F2jkWPprTI%2FuWeS69CdSZuvBuF9eCdgsHZsNglw%2Bb8qUU3NIXYfOEqvEPEuPOXwMIIQUhtggKHhtenpBMe6wqqS5CUat%2Bb2E493fLZqjxsRcajP%2FlQJYoYWPBTJeNUFKC0Az34aGwwh3HrjPf%2FD5OGYfF6BQ2hu%2BGe3zGnFpLgKHE6bIPpViXT42Mii4DvKFWCCTjf04Y9XoZYdTZ64zjjmMjoIWTy%2FwyUcLcnwsASshQVZHoMHoUVJ%2FO%2FsaSdJEPbUlVy8rdHhHjwqqWqtiVdsLKY3e2WT%2ByE6Me95PapE2wSGUDvIEnqWaXw6VhmAzbWe9zn3dzii76zh0f%2FZI0Er0%2FhU0sd22fUxk2%2Fy%2F%2FYVqchMRiy%2BOAkuyMjXv63UPTh8RI0OmIjEc98l%2BH40%2BfTrTcNbkuJY29aHi%2FlglpQdiIOxGVlfW5eb0fD9eq6ta5Vq%2F4ApYHbwNoIiGaPnWJdGET51sgHwQELGUIFKTIBFCKmcAflNkxQPB%2BHzgTj7Kv85dZufMXC2%2FpZ%2Fqf8h5CCteCAsCSkDAY4eKBf8L5ThQW8iTGhAHWGOgtVo22zU5fX8OFXWX%2FqF0o%2FpBUSifz5df0UBG7aVbmEFs2LfxueFzw4ecFhEoWAZjTqcducHB6kqhpXea%2F8SbF5enye3b4aK8DqsT%2F%2BxJWtXnY%2FWWkJ9XNgQb%2BoITlIpm24PUMCNUN8dir%2FGR4lcy6Z6UfDsSR4wWYWeO0qXBJ6Yeb3gRA8HRwg14rEcS%2Fw7LAMGlKKAZwfqZSAqDEc86i46OdQJD5f%2BsOlgLDl07xeqDvzRL4JDflvkHj9P1pAhIPCc%2F2l77DUk%2BJ0UMxfFpn%2F0wSnCnc7szivl%2B717DZSRzUZV6Gg5JjBs%2BCEj2P34X7EWRWMGnTJerMgnEr%2FyQs9JulHW5dl2hpse9Ehhit%2Fuwvy5WYQEZH8%2B%2FqalNGqp%2BLBZHo9NDBU5Pg2hGO7RgxXubVaD9hjeCmCxwMNuEfso4mQgL3EFyZHYYcn1SzXww4J%2FPpKnMn75ev7z%2F16r4Xv0Xq0L7RayekI%2B%2Fe%2FVit34NgyCIW73%2Fr1DRuXrMeQ3hLn7j%2FCxmHbm4vJYLYWIr1b1A%2BMsNQMSAo0FXqHy8jAY3v4r0BaqQTPcf6bVZRIbhiLSYfwID5cMyV%2F2suCQp0sZOH36Kd5k%2BeqcPCHv580Mq0cTUI6Uc7xpMfDBQ0pmjWEfsXeo%2BbmqGusqzw0FfvqcL6Eb69BUghrGGVM7OwQH5k950mMZ60G44If9iCxnMO%2FPJ9Sa4XPjsZVTOYxsK66jEUyxwjDG%2BpPJdLRO%2BwRiAN9oNWeD2Iqxr41k%2FLrcLiY0y3CJw6h93zC4w9fc2VhqgOba%2Bgnglg04PvXPnr%2FTxIRkgjk2I%2BPR3%2FWVE8a%2FJ1XPt%2FJ7a9aWnBVbF9N%2FHSHtxO%2B3DxqRFgewMBCLuWAbvL1ECTvmiB6wQdpHgi2p79rTnlFsaPeC%2Fq3LhfdDjwPBzdw%2BM8qgSvBE2v1PTJEUVdgp1MrF7loPHAupEs8iDHSUrAoPttFMaE754OHTsRU9hnwDTSCAlK547d%2BczXz3hfk%2BP2jkX0Ny09heMCRixqEjxnDaGA6lqwUbS5bnX%2BHCUjSUi4FTjnh5fJ%2FUXAzQ3Bg%2FB3ZxMgyerz8womNwBlRc5GV%2FTONnXlt%2F8n2gmCsFxg2mNJKaxtSjMmgdeBghWqJdQlHTk8otMHgPCUAVKFysPiwZY7%2FTtPfuMv5x0RWi7TJgF0WMwG0zhfPCLMiG4ep8vNN7vd85t%2FBrrbecTnEXbL%2BnjAiMP4HV4SW%2Bvpxdg%2Bmtxw2G9EyRK3o2T9Jzqw9HGmsSFNvpmGITEPeb3EEwgK6MAO2Inp7k2h6q%2F6eg%2F4wOnB9R5KeaJ0lw1Oc7BA0t%2B%2Fye%2FsuUXyQNmWi%2F%2FrF6rUn%2FrFU2r831e%2Fr7%2BpjFp5Pv7UEFAoyyUD48N077%2BzzxgZHImieQZHpqnS4snj%2FYY0DL9hZIMlSsDj4KpIjjeGH99UC%2FUEzDcVU%2FMZcECKDVAzp4k%2FKVv%2BwtGsu9BhRgXPWH8v7Q6Z9E%2BPrGlu%2BBMJJWPeGhlogfkPal%2BGpwUEXQk91%2FDfMwuyskt1qlJcucp4z%2BHPBH7vv8eK8eGUM52CvL2NeeG77du2Lu6wuR4EdRaHut8I%2FpJCsnpXcuT9fkUxcOoTN%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%2BZL8Epz%2F1Q0P3u6uV6Be1e%2Bv0Ut5ay%2FECjjEhLNNL6X4Rniaj5jIWFl3%2F%2Bh1MuXWeIxlgbnSKXEViUHiCDW4xWFgPg%2FAlOcH%2B8WVkbpe%2FO8IGHsRJhUtfGcqDzT%2BEUEaktFapUQrT%2BiuHciy5lbyVaXCPyeVE1V7cOlp4MiAsFECmSHiR%2BAAAQREGaGoaqBXVoS5J6t33fEa%2BN%2BN%2F%2FX3%2F%2F%2FfT9N%2F%2BrVxX3%2BqUP%2F%2F9r4%2BE%2BAkAm%2FV3xv6xX6tVq1X2vd1Uvfr0i1AmBEMCFTJiB8egWkJ%2BuIOzLtP%2BBSCI3Ua9quoIWXrqaIjCJY8R%2BE24r7gtEBzgCV%2BKJfNrYpTiFI3n0id9RyOVum%2FDHlzlwDDwHzwRX2A6I8vHvh5hS%2FhjjTXy8GzyAzoxzJuB7fZr%2BB1LuCQKBwmWkDsgqbxUalXjn5aeL%2FQljolXO641ex3TBFL%2BvqJ%2FV%2FfrFVEK36v%2Br1a9%2BsVX2sVX8UCfTjtJW6W98wLsgjqGCuK62sevtNEzLRQyqGLd1C4fhRFMFcFBhjY7RMJSISxBfhqkiJmHBoFYGOrDRkgQBPBRQyXL%2BoXsZo2x8whg6DXV%2BGo4%2FBjUPbowRRi%2FL%2Bsd8JSAIEqvn5xWht3yfsWEGDgEYDXEgg7CBvitBd8BwN6h2XOlUUE%2FL8zPqUxGYhuOo91UvjiTARxYEcWHybbtqMRFnOYnQHvG4vm1rbk%2BgsEA8CICG8bxdXWhi3iAmgYtZBvaOVX%2BvVKT0wgaMjgU4goPt1n2KrXDFQowGsYCksY%2Fbj%2Fs%2BHz2NZg2B2nhALkIEFndFEAFieEUAcnE%2FoXVX2vcyY56bvuJtYu1qqvnvHhM4gVTpRLO78Lsv8DiGQqZGDN7j1gH0vEKQi0IOg00nPHQY8nvFiQenBVOHDhwHXZarwur3eA6R3lQFkLhoorJgFdzvtpX5IVnj%2B3zXCBOYwQSFKKsbih8PcIWzGhA%2Fl%2BaI%2FCCgYw0AMMwP0YyLWNyg7a%2FX5yhUoJ%2FDDCTnwdzY%2Fk3lpOpHciif3%2FW%2Fz993wl5QlvGwEAMC4SEAPA7tan%2B3eBjC73hT3uBiPBsBTET3jymq10yVleHhpxYREzBCZjB%2BCQfwOh%2FviKkJyvl%2Bv1eT1iu1iqqr%2FWCr7V7%2BlgIgJAfAwFAlAPwq6sZgAI%2FqtyKKDU1HZzUGlOogJxhdX4%2BsGgrGE8bmCtkEH33p6sUkqanv1RZf4Q5fm%2F%2FQV6t175bHcuO5PXf5fl%2BVe%2FVv17uq8Z%2Bny96jBQYGY5qF8O5mmgTKqeSrGu2XfvBKUGUpS3B8nVQGOQ%2Fkq%2Fzwh6iMdTFrEe%2FU0j8jO6tCYp9bHfq5l6Qd8O16xHLeT80jkBCBEDg4KcmUBryIFQP%2FIHp%2Fx%2F027k7i8L8kuAYmFloLoC%2BaiK7a%2BX39QeP1BYmZdoFmnV%2BGxAMwXW45yfLTuFD2KlZxuPD7oLbFLW1LLN76CqUUIPTfWCQuHog7BOQe2nb7AfDpF4gkeKyuJ9f8MpR6sslIZxPf%2BGz60idfz8Ox16ggFJA7UfQGMSuxLALPJdTdr8uTXSW4JtnL41GgxbICVSFE2lKKJrE%2BLrfq74%2B7schNr9a%2FWK%2FDmkbB2ov8Z%2FaUjQXNlw5BpxwZFyWOo%2F0lWCDA7iVTuUS8KfWxoJ7ZuwZrQQR2G%2Bk5CArSjcOSef7Ydk3E8vcqv3rUBUtGPmjuf9LrMDpIPGO40FQViAwEwvHVmYfYEEnJIlYdTTEzQtf9BTfUmKHwZ%2Br37hYaeZMePyziOJHtz047%2F%2BIhufVxHoU8uaO4d%2FiDMv%2BNx3xG%2BixtHTP%2B4T0%2BAkK8nKCAIO%2BM0q%2FlX2CiWZs5iCmKx%2Fko%2FCM12YkqvE7uLSVbuEKUc2CdtIq2R8isbn0rCP817fPW8no8v1r%2B8CwH%2FApB%2FWAqpjI3eAikY%2B7xDgOrFLfKTVOT4LKTwX6Axw3Y%2BF5EnBLe5hHrcvQ%2Fk8f0w5AduLoVqgcmhAVWAv9YNYSbDYbDLVVwlfC5A4hfV9Le4PtvVnDATNwPPwmEycKx%2F%2Fhn94IAhlJktuLiQa0HOBtg8QH%2BGzoOaiTSK9afDcSz2b6ewQWGCdo788DWMNqloupaFN7WOENtegyIwlrfPVXqH7SCM%2BCOTNIcU%2Fw66B%2B8pOO%2Bk3cM5VGk%2FUz0fvyoa7nYugOT990gxoiMwtgUWKv6Yxc%2BCggYSO7lzMTZ4eSL6jdNd5pGT80llHFG2VXISByvlvjBd9bdOrGyzEMdBV24egi9MZy5pxVCHsHd4cU8VyF7GY1leT%2B1auSa6%2BuTeLIB5BGEBSrvq7zZwegrBXVd3zY7uyrJVWCcPgoBYNrXlwEx%2B5gclgSESc%2F8eD3rgW61hvjoFX%2FSERdBcmpQoRuLDKawuNKyCFsWO77D40N4YSwf2HCSjRBo04zkrbRhgTe33PUaRIu4lyfv%2BCDaMMXD8wx3IbZv7OrzIlIlbtxI3qPyfSbXiCjOVITtP%2FUz6lGC%2Fv7DBIV4TKNQ%2FhsPAOHhxx9NM0%2B%2BRdaWF%2BiUx%2FFfSg6vT%2Fq2gsUfVJlQOVSZqEF9bRHf%2F80%2Be%2Fx5o%2Bn33rJk12q23HZk%2FrRir428vMGA69v0r6bDNa0FP9tqyW4KQR6V%2F9nr%2BE31T9M9TGlKR%2F9znTv4ftvH0Lwtr1arqlu%2Fl3%2F8mvAxgiJaVResBDh0Bch4QRqLi9VF5PMaAqi8HwIfxogN0lmYBZL2G45CQYxgQJ2gGZQABAGJoAqycyiPg86gM8H1AlOwsjZ8Wr4WKAT1%2Fp%2Bq%2FHuQl1Szf37QGBcGCGZzFPoYTsSX%2FBPxsuFe%2FNv4snvp%2BHSyjBgVSuV%2FX5UDN1h7DMVPggkxdp5ZrX4eE7vGcd0UVrBSasF%2FwwZ31QMdw3GeEL%2FneGVH6jdmZG4IOPAMvEcNQxdsHsMzJGx9hLv8v3fWzb0672IJ7P9giOFlXxyyhyl%2F%2FZy0a70mg4ZbsGmH7Dgl1b9v7%2FPXxF8j%2Bm8X%2BIkhWqkXq1V5F%2FWAkB%2B7BmCoghJLtrCtT4xJNAGJa754SpqRmsX4gRK1ntRg%2BOj6KrYLTqL1xpSHouVS8LZGhxbI1Xo1%2Blv72Z0toFc72MwVbrwC7%2FF1t2d1gNnPSDdgOAPf7UZQGqO%2FfB%2FzkP9fnM9eJCApQv1Hr%2FHSuwhvTwqWa4aexVSOZZR02e8c%2Fv7dxjyvcE5b3qYnQ4MvrXq2vUEMxGkpy%2FDhDqJ1AVVfZR%2FCEZZYWzHzUye5X7hsiOHmAnCC6kdtm0QQTDM%2FDG84gI6Ijgqo5ggCTfl%2FJTwQQkv%2BsY%2FJw5aQ4BR%2FcRbu62PFhMeEP80LWyfqGOOjEWygj8Chn3DSlxpNa1EX4vhWCr%2BT9XvL%2FAQzl9a%2BIu7vtFa75LmkeXqjPeDgLotanbBEScMDdm%2B8UIvPSlEbk%2FXt7El8nsHRhG4w9CWyn1wzLJ%2F%2FBQXN40JdAZFbHD9a3zlX%2BOYr8FAgVw2ktwb0GNaI62eWvw2UIhImL8PUxKOG1k%2FSeGSDjKLQ9D2Fz8cox5I8bQoell%2FkwQ8sOzcrYeEzsWCjlEBnu5RFacFseVgmKGNz%2BCAnDy7hg8GEuLvyhI1fM%2FXv5lP5PZt6JBGbKdG4whpDnK1%2BCc480IzLfAjbx2Ve3Ensy%2FhbhtnXrsHVN9fAPorecAsMq54lXmwhq6tFqieUiVelyT1PWazb%2B9YOAy4vL%2Fd67wzaXVHHTP%2B0i%2FwqSH3S1IESYkaopB4DtOsNL8ei%2FYaoG1fWEOldOC%2B3ULUA40Lr5vVofqDZ%2F3BJHwVcU7gRy9%2BvcheVjS%2BCcjhpKS5eb29nuFT1goPWff8eB48HcoHd416J%2FW6ghuQP7S83OflJe8n7DFN2EYJKWbzih0h0xlIfBPao7DJMKV1DctB%2BG5fn7qxdQUo9XSq72QZk%2Bf8b2Rl2BbAxACGUZGy5yVkPJ%2Fi1FYVIaBY7yl%2ByLOl2DwJb4ArYoY1tjDp65OUcOXyBNlYRNCgg3%2Fh4JW7SAXnKjECB66TBgatAdj956oJQUA6fzGszKKGXIy29p13bKAoMFt0orDEK5DNfrz%2BhhHNJHsaL%2B2djpZ5B5UUjJDF81WW7HwVEsOT3K7VkH2DQYAhlJMPvk7jpGRAXGK1B4JTtiMN1fc5xIYoxNBySqfgMuVq8oevoEMEST4TVpgjG4cy7cd3wndyUk2%2F5DbpJ%2BkNvvCRxYW0ZjNfhI7kUstMON0rEBfJ6%2FpBn7IZH1Qalw9Aggt%2FbgHXl8mtMEHBrn8sWEuOD4MaX1lmUxrSaGpuv0ELCTq2%2BiYLsN%2Bk%2Fa%2FC5cVu6sgk2zM5FbrS%2F%2B%2FwX7vk%3D&media_id=1254206535166763008&segment_index=12" + }, + "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%2FJG39ndMuIdUwmos1lBbwb3McRch4VpDBmUDuSpBVROZvN%2FP%2FvGFwgQE0N0zGaYADfHkCHKYdh1nsDY07l7l%2FQvqlr6j6e%2F6mLu%2Bf2xBs%2Bbvyfn%2BIly58x3TXvJ%2F4fmZpyz0TZcT%2Fj0VseJdd%2FUC3DS4O%2B%2FZPiq89RjT%2FuJ7qPovhU704TJwFJImS56%2FcEFGDtTUhrHfdpL9It1eYJaUxHJEV1ghjSglNisHjpD5GFh0UO6GPYREEU5DcnQ954aB4jVRiZFG6%2F%2Bh3kVZRpKxZJcG%2BG%2FIe8iOkv69BOquh3evvv1%2BW9V7wvrwSxlor6SfB258a%2Bu6h%2FhnkeoXkjeCneoggIsI%2BvKLL%2BBkC3kC20bzLVfXVV4d13S5U8H%2FbzfMGKEvgAABECQZobBsoFdXXoS9XQjZu1a%2BJ9%2F1LZf19FY7%2F%2Bl7%2Fr%2F%2BKV3Ca931qx2iRu%2B%2B%2F%2FBVRX7XtWCv3XojfrVWvV6933VFqmuRvEhDJ99AmFgmGhgQqIT1brLjMAf7td51y0XNQuYAjw4L1qq1HM1x7v%2BFihvxAffLjaxfwRDPtDdeCIKacEgwWMxnSq7npwIgW8Zvl7l9C%2BkvonpZBX3M%2FRQuKUZsKcLCnCwp7jMsLzQryCwpfnWrPk2OzFDUUMsDPDgoGWBjaGCuFSjcUY4qvxpG29c5YZYYoYoYoYoYoYoY4kQNRL55nh4fR%2FiWN81AIXujL%2F%2FimJ4KGWGoOrBQywMaUMFRmrb%2BsaLB2KBATQMIHl4MB%2FhZP4s2cCzJ1iGlfvb%2BvHd%2FL8QHhAEFg5Y3qVfjvmIK9OmrtJLkJFWbb80kyZ9sFkfaPgNqHQH58pmN4ctznC23yjSh2C6RpUMe8xDR30stvbu8DEFK98DVv1X%2BCnu5o%2B7u7Hy%2FE4r6snnVdyQZFd%2FSFxfr0nStEbV%2Br5fYoCCWGIYOIAWATBkpfg1cv8BLjQ0RImYgEiEASoeC0LBneOg9EAmeEFUNIH6AzMd9CgPuHElEDQMl%2FxYeIKcZM65dNQGl4OHCoFaEoACpGduyOybjdFMPrYZqgBJOTC9mZMzY17zfDvYaiTOlu%2FtRk%2FAS48bh6x7iw%2FgY5S3M6o%2BvxDVny%2BAhBMvngWABGEABFhPWyVcWB4QA%2ByssH4UX6Ey9qXia9Wk9e%2FVw%2FVz9eq1lJ6lu1e%2BZXr17WCYCEWPGO9%2B73vMeub%2BHQ7d9QDTWYfn%2FCtBIYijEIy4HcL87CB8P89hHqHOgQOQgPQ76B3l8fYD%2FP85wiSIJZmD8hD%2BHTPvr0dysCKNn9exy7V69V365VS%2Fr1T16xc%2FPe69l%2BULBPDoSCg6UlBkeAFCQm7d54qv1Mqq2jIL8CQ5lwCyGqVUAfTqy%2BwiFwSAtKkMI7nNjHqm8ziLGA0CzuUgAd6GQS5PhxZoq7o6H%2FjtUt%2BgnFJfa97r1WupL7v1fqkHfry%2FBWJBQbLAAOEsa%2Fbplcdm8D%2F83FLyy8FGYp6U7Q1z2hwSlbQStoN83zxvyFf2isVRF5dUt%2BhL3dX1S%2BrV6v%2BvV63txmAQUDcCAwoxRijFHifTAQ2RmZCqApEjMCGrQHrCjCfBzcyAPmapVZGIOSy%2BT9Ajh4FCASgJgJQfD5sGN6tkpSwGlSC2Yjq8CPly9CDl5TV554Yut%2BSNEkyaSvs39kxSD9H%2FyDc1w%2BHwuQFQbrh%2B8xfTbPf3ClM62gPkXfg7%2F3w41P4i5jYzbn6xZPcs1cFhAq3Nvh3ya%2FlC5cBGZ%2F320M43W8bCbDsToamF5ZfgY8MH9jbVLni%2BktfLp%2FnQnpCfn%2FLuvVc9q3ffzVqbxto5UFyZBcxKgoAvOm1FyaBH%2F439oPeWDa0qJHHBnKG9mEGUELQVSIZNaYl%2FZ%2FGzjiMDkWdGs6V2vNC9z3Yetx5O9J9lDwojkrgCvrPqkA8fMABfGDTw9xr2DD%2BfYdSC7vj%2Fl9z1wTDZSmX9KBxnR7L694JSh9gbF1M1XsGdxr1BEI44c5epPqmtE9jsP%2Bn7MRoGkDuScQZhAzGJU45LZf5Q5MRs2aUc1R4ui7QRjPCcF%2FMbBvCBHvX%2BEPDfl8CmFVg4F41DUd%2FRqx2uUvq3a98TXq3ay7rASQfF8Tyu95hwCCCPsR8V%2BXqbO5iYgcHwQHtB3w0hsFmR9n6s8cDfYT0%2BX6DhRGSXzr0hsw8yt8eP%2BOjXw7wiI8IhwbSiO0MOP4T8lT8v6%2BN6IdNgBa%2Fi8wT%2F%2Bqt%2FyH%2Bym5HpN9vT61%2FIvgLLk6%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%2FkgkwKPXJ99aZUETWEes40cGnXmc8ory1rqPPI%2BU3gK5oT86tmbBTiYi6AsEWFlULduDu%2FTvvIymBLWk%2BfiCeUmxLtq%2BXN0X0OnxITxZLCh3Q0fDuF9r8%2FL4deWoTJcXNiRM6%2FFyza2miWw1L%2BShCYKbvy0ep3lpz0h53ixjJnqb2TJNdaPiIO2H8XzfzhPiqVI2Hy%2BNCZRDpJGvuh7eqv2r161XrlJ5KQwGD%2FYVN3eGWWbTsPh33l%2Ft3BZw1%2By0Epiz7Sc%2BZ9fh85yXbGmulFjQO5ctWjoUb6%2F9Aq5fkTLCjfac3t4Wsbpumx3X3ar8%2BXx4Se1R%2BE9oxj8uV3hzN2fk4%2BznKBuai8%2FfHRtmWmMi4E6v9BEmkkT0O7v7X4gg9CQRuO6XhXteGGoW28lIf6loh%2FqNtEKtr5fciKzQjJZNfeSIS1JGWqz5yRMDDn35r%2BovjJEFuerVb%2BbqxpQUdBBf7Xe3MnoCkIoUspKMS52tuPu6RrSnA8Vji3%2B4U2xWDfll1ce%2BTHUJxUsa3F1vwkhZBWD3jlg3ijb7MHcRwV8%2BYo719T0%2FyWhvdr1ei5drFXapwk%2Bf%2BifX%2BiMOp7nz63%2FBERnaeu6Xf%2BN0Rc732N7tVKMMbQp%2F5yqmVKKv%2F4IYQLxr8Xivm91n%2BT65fL3JQiLL4i4m4IJiKWWn3PVZ9SoW0fZP0YYUYPiXLuWnJ8DDAXwRoIDILq9pz3vk8y3BcHASsKCoWV6MARjp55My6I5vqkAxRxH5B0WA6Fgngng4hYUQXpi9oL9IK%2B1bvuXrlkuvBDH2X2Lwnn4nvQoIIIcmZ0y%2BBkDgNiyzsLJ4WHLMSED6qkutdAwF0QCMKrqzAEeFJgqEwoEwsGAsJAsOAstAsVAsJAkFAkMwsSk99a5jd3vjfDKiKTKuuEHAPp73675n%2BfLiHS%2Fr0%2Bbf8wf3S%2BizVzoLCv%2Bi%2FC6RHVRuP4%2BuUdXt0d6cqNU3hhPzq%2Bt%2F8VVUIYlKm%2B1rD%2BlM%2FLdZuGmvWMVxpmffLKsONUi9VNlbc63rkHXCukskJEiz9jlpxGzqSLyp13qJjC31dwEwWFJV7JAFZu%2BwSp4vMCWNQd4PJdozutQ%2Fw%2FKi0%2FyX7Z8SGfbIo%2FJ4uICvgsDRd23ckNhTXUfO8gPBjOsQ7y8loOXSIOt3fbx63EKeGDqeWAaiOvqWs%2BFLDjpQC3%2FGtS4OAEaFJBsSAsNAsGAsOAs6AsFwmFAkMwu2t%2B3zjjOPBqpUk3dRRiTiYq%2BB8B%2F%2F%2F1eTr7Bw2%2BxviF5buU%2B7%2FPTJ%2FQ%2B%2B2Z4SvM%2BC38fDfSHbNY%2Fd6WL0JIW4A7I%2FXzn1UYLVa4NX2dFFrftPVXZz7LVsHlPbTdTNoG%2BC4BJTelOpa56ipaDgNRlVeo2M4%2FK%2B0kGZjemo5LMdV8YStKUp7ABdtcGB4WvdvrLgPv2vhZQvOi1E35xT6zDCa2eySrleNaHdAymm4qEQQB6FN0g7Pm%2F5XOIoHdIPMeKX%2FA1ZKqKa9zOezEKdj23tiPj1I4MEa1P1pGJKZwaZ00pwsEeRuQWfUXrA4ABIhSQzBgLEoLKQTCQTBQLCUKBIIhIQhMLJre%2BPfWu%2FPiVLF1VSMuqL1ll8D%2FR%2F%2B%2Fr36XRn%2Fthya0ejj1nlo7fZ6%2BEnnDdzPZ7vNhPt8MfZnt02bFyq4T8ZL7g8%2F2omvm2uT2onLvN5hitj0WHpC7M%2FeuAF7vybTmpSH0rc9ChRssOKhBp6mqZ6cn9M87H6ew0fv39U19sHFLdT%2FhOss0xIVhiAqu00QqZZ9MCiPzTXnJumO8prL6rdDXzA0zuBvVSWc5xqHJDx9M9l2dkq7%2Bxrwr7Tqviq8IRKylj118mjLU24knoKtPyFggnOee6ykoUt2HtQcABHBSQLBMKBULBQMCQLBoMBYMCYUBYSBYSEYiBYLhIQhIIhMLeXVVzxSpWXmprKJVRN3l8YlXofONUfo%2F6x9q%2Fl8uh7btjfUi%2BOqXWwQQUnXWbo9q6N8i30ljnjZ0Fx%2F9FcteWh%2BTqCIsGawJb7rudrFsH3zRnJvzPXeojJnJbELhqV%2Fb3%2F878i5Pvn8kn%2B0X%2Fuupfvw7r9H%2BVhiW%2Fxfkv1spMgPxqhr5zR69uvzERpzryVRCsgjRhGIlE4WX06Rievhyne15aRQE1%2F3rdY%2FZvtHR%2B3svmsABELpyYPEfR9jNanUaNZmUU1ZN55ioB%2B3V3giyZ0Yaek3a2Uy3zAsa5Ls1k%2F6jLzQcBGhSYSBMKDYMBYUhYcBZiBYKBYhBQRBUJhdmcc4ulVeRJKvF03dXjhKk4G09T%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%2Bs1gnl5HpvqDrvFVez%2BKEtsAJUjdKHTNvCYSBhwJP51v%2FaaE8LPL7PUbeCsPAr8Vgz%2B6moG%2B7iWzPgnDwfLiBo%2B8Q957kWA14epWU4ykQ0K5R0Wpmu%2F11%2BuXc11dRKtdWtyRQytYp8v%2Fyq%2FhEweg2vZPdxJO7vmAqxVr%2FBZBUQVit3e3ctq%2FcBiUJvzu%2BUK%2FjXn%2BbGxyzS3IGagfh%2FMDlBgZYWIagxsUjVFr6EUc9IiuCHwIKGW1UUbxUTlwgrgYcgOZ7NEkz1iBMzD4fy0CyqWBnQePj0sq0vGZZTy%2BCcPBe93d3dbB6h5B1wq%2B6EtJ61jl9V1yVd4rfNXq5Ja6q%2FhD4o9YUy%2F8v3f5fLgQsnXWFBCr3QnVVVCkX98HaE97qULgEgHO%2Fl%2BWT16uI9%2Blr1qSiZ%2FV%2B6vvr5cvxAkUQwTgqCEGN6CPIJJOn%2B9j2SrNQjUnPatKfQ9zBLKG1fZfYyQL8Z20CUa%2BoDGc5b52u7vjsS%2BsX5PQRq7l9a4Ie74mW8QtetfESE8%2FyfA5BYojcDtvBv0wiIDuCoex0Ew9h2qMjMFnqy6k%2Bc5vdQQ29fu5fQRs%2FV%2B79e6pdCaHLapV1L61%2Br%2Fq2pXyfxa6e9pwjE6AjGUei5l8DrwUdmPsCF1KZ7EH4khRtEOdL2jI36Zxa4tylw7gqgpfwosXCBoS%2F%2BeCZ7aT%2B4ngTqpvQfkshLjTULC%2FMoa5m4%2B5fU5qm%2Fk9Ca%2BLltXvCu7XUnrFfq9XIX9dvVqCIIQnkkb3KHb0jxw3NXx5o%2BGJ6iZJfUKlBx6l3IuUZYSIdL%2Fycyb%2F1qkCUQqUkq2j5PpaSGixy9x%2FT7REB7vMnak2pET5aprUNHwpPJmjwHYb%2FUY1irxSAtLUNWD46GgUz%2BLkgF5C92Dr8syvcJbTENf2EcQFtfgw6lqqj9opaD4nvXo9dyUStdrl2uV%2BvTYCARiYuJ5eLgdmUj6t8oHYbvBuHQXA3FVVV2wDb6HXT8ExcScMICAkXkCN23H%2BKvCWwiJK9E9vgu5crZS36L78MFS1J8X30kcuy%2Fu6hIxInp8MjLS%2Fl3jYEd7mNTKzfTcArMLRscwGag2g%2FyEpSagQsqR%2FLF9rqOy4UEAqF1JofQ3zpf099FiyQN1hb%2Bfr3L2mrtIceED3S7CTh%2BljQ7PbIQPsF%2FnGfmy%2F3dovVHq%2FBP7q3a%2B6Zel9dcA%2FwKBu70gSYCGA5i4uLrVZcpBKFgM4LAkKeq2q%2BYzOZ7A75NH9eXEuIcHSVu7f6wdhMHoYDsSA4KM%2BZ%2BKZ%2BDAKHcwIkHAQjnsj9YA229B7k%2FbLlFgehgRB0%2BBcsJZ47x4LwUaQ%2F7OLg%2FGh8EdHOB7XX6Jl%2Biwm%2BsOGxA4K1NOZb6WlkPQnDSmW%2F9nqNEuL%2FW3hUkMgJRmBP5NpxL48l09Pq5%2FkXchX0H8RUt5MkfE20dA974KZSC4zEXnwIV0W%2Bwk%2FS%2Fwr3Ei0qW9x4tIvdTord%2FEr3dY3V9r0uGhQJ%2FEPnz7WGiQT6wOgZNIOd%2BuFw5BZiu7u97zAQ%2FC3CAWlkEsAfbPAAJ4CeZpwSeb1lpvdkElg1%2FQszfmMfV628KYruUIdCwBlY1PAHDz5DGjPckvi%2FEmFcsGf2%2F9VPk9d%2FZ9AwzDOe5bu%2F5%2FcMI%2F69681Kpv8M8wxMtL5tn35S8%2FkuuahSzX3qA6B7dV6ktEY3gKoeCwIjyOJHLjoHgkAHD3D3Ce13gpC2IngDl8B6r4%2BY1fff6L3bj0qBa%2FRa%2FFZf6p1eFaHGkHkh1HZyr%2FUtaMa%2Fx1q2WwnfGoF13aEBGsfxm9POde1MlLzZH%2FFzUQD54UF8Tm1e9pWsXjNX3xTSetWnif0ervvtEjDdJ%2Fbrk9y%2Bs0dN3A2LZi3vJ%2Bf0CQQzeQIJG%2FLnzcMhUl7qnrHXXj%2F65fgkEns%2BjYaINq25L8MWmHJnU%2FV4cKhoFmrWuXKlNT%2FgjFeauzb%2F5DpU5fnFeX1%2FMV33as%2FPW2dLH%2F178hnv%2BFSlEBNBzPfFGgcD6ohh6kGGH%2Bwt519gRwe00q8YumtD1f%2Bw5IEE7h4xUo2iedT%2BzU3%2FitOXy%2Bxyf19UFi3sif2%2Burf%2Fghgl%2FihK90DMNRPrfUJECFMlOlblDJUCa4%2B%2BepQ6%2BbKsNokj0L4siCH5Xrxv0vvfioj9rbdbhTGpTDmHatPPbFE2kYKNotUl4O%2BSkvpkTOWHSDNgNfJN2BZ1it8JLuPTp3mdyW8%2BwvdRR6pn%2F8nuJJaeMLw8pwfEHF1qy4k6CglJCxL5HluPpwN34Tfuj2rkGIB79ePl%2FfsMQBb3U8dXKWoOPq4%2F%2F%2F4IxeMxe5XrXjNerxHrPXolfrFZf38FduNLtreUIAsPq63VZiw7lqLF9wUcXwSH%2B21jib0tdfhSh4zQyYx9%2BjLef%2Btz4IiXMxy%2FQth8UZE7xo3dBDtPQJSAicn3DRlR7piZk%2B7rcEZkLnkpKpwP3yAi5%2F92vZAoIDXy9%2Fs84r44t9%2BhQEA%2BxZzretAZ%2BSdzQ2xY3h%2Fq8vrXKoRhMT7HuFhz4GEyPskZYix075fOxgTZJhBS4XGiVTa5v6%2BxXL4oJv4zBgiMOrXSimYDu178FfL7To%2BEMSJDBMLLV38CfXrOc2ZfLPkUt3%2B4vu%2B4r5VL6Gvfr5%2Bv69ev0Ir8VfHxAb1H8E2RjWpxH78GBR82%2FlMbqSwztH%2F5c1y%2F5tX%2FCd92mr1rQVKPyv6bkhKkGGX%2F%2BjOV6xbC1%2FR4yvBB0CDieW7O5HzYO7zakZK0z%2Fxgrd80TMzdb9u4%2F7fgZGWl9Sp1Eam8D5aPJ%2B8mIEWY4sUac5rnsnvKyFCtoDm4V4Byqpnotf4soc8KicsrZ%2FadBtxi1eD%2Feti8eR1DYiauJqLRMBo8o8c%2FJCHNRThoPeWaSQNfxRfpfiMdnF1Vbtl6Q5c7Qwoho3hb3GB3lEsC524Goq3gG2rsHHcZaz5s9lwDFrqQ0u5kq2sWWkoZrJqC8Xd%2BVC6mxJmJm7WColwr0fr8Kmsbud61n6%2BOg8BRb9wL4IS6aGnL8L02y%2Fsc6VnyQI%2F1BCVjuYNUu88Jf7usv%2FWCTP79%2BLqg1y%2Fk9%2FeiGe711f4nk8Yp%2F65a%2BgSw0n0fapXNeRsnG%2FaL9qJiYQK2jksoxvfZ48XwkAUmoYgLT6xs6W9nrtl3%2BpuIaA95L7tl5DHt8uvLFF9p5H95VIEZ44W9rfbJ%2FQy5W8lfj2SVR8X1qok%2BX7co8IAvDprx7KyQBsVPyTqg0QlFyLtLmq%2FLW5%2FQTbtYr9RQP1tfszM1fuIvc%2Bbui%2FX65a9x8mU75oz%2F%2ByO%2F%2BFTn8%2Feb6kmZ7P%2F5ZM7j%2B%2BN1P78bIZ37zVfCUqnLPrUvDjSvt69RRgvse%2BoX%2Bl8JjgQCAIIRDwIRsOWlLr3g2O6fgvzKQ1d1V25K3gmD3x2Ap%2BIH3LrV8qG1W1F3%2Bjp4j%2BCmi%2BESglOYeICogLHzvByeAr%2FqwViRNidPVMyt%2FAAAAwJQZodh2oFf6Evd%2FS9XrV3Rf%2F79W7qBB6O%2BP4P%2Br9a%2Fk3WXP2vd9%2F%2F9ouqlRK%2FWu4u7wMzDhi5cN%2BSqXW%2F5u%2Fxbd0UmXDEsG9q2wqFYe1hfNVDOhdNGBhJAebbHOTH9i2WjYdr%2BAKgBWLLlWyD7fMJRr%2Ff28dxXYrfusXdit1pdrHr1evVyeWhBN7rY%2FXq5Vr5%2BAW4fzB65rqqIQaMvij72sPDhuLUnU9c%2FT8U0QVQ6i8xk7Z78bbwgNmpZ2NqSO5LKPA4uBsxbPUh46eNRVyLGGca04DPDQU%2BAKHsOM%2F4pNT3nDgJe5jP5QT5arHWb16s06IuKQ0hdXeWtKp4M74EFIehaPHnAZvE7qPLAdODShdM25DsRSmxnMvjzFM%2BCjxddVyKTlGBS8Ie6%2F9xDnVbSi6VXsQJDQne%2Bqyfcu%2BGy007zxzMEjuuSS6wtkuvQvKe6uvq80oRr0zkDQq%2BIaPUCQYBR5V1luUyy%2FgagVglzdp22rGau%2Fgg90He%2FAuSD6D7UJJMKPpaD0YuGDSLo6aCg%2FXgtEmEhQ1276tqKp5hjU%2F4YQR4xWRqW7X7WlTwipcfSp%2F1BLVVVa459Fu%2FfD%2BhfS3drLFd%2BtSety7UiSy9r2%2BK%2FEfl3UCSQczNd%2F9oe%2FwqsHwrWYqxS3V4omuJk9ar1il9Zd3xlZdYFoJBQIRaMyNQ2TAh%2FdzwilxApCau%2B1gj2YLIlj%2BzMNAYcCVqW8J6GYCPeo8NNmTK6kh17p6hc3LWvPu%2BBa1QT6X1dfL%2Bt3a1VS5fSuequfrG%2BJiqIrJ8C4ELfkKCwcFwAKYdAUweAAQYOAsQRfkTRDcO%2BABoPCYPDhZg9xVvZMSYfMwH7PRdj%2BDkINXWO0KXnrF%2BJ4mvQTlXLNasS332CQ%2FHfXGLBQFNuCsDaHQSAA6DwfKIZgF7WQWcYOJy5FaUnBUt2fPoe78bMMEhBcA4vim7FkzNQXjQS6jYQ80qTJbSVWeOr6L%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%2FBKvv8KYrJznnAPLAAZMCo6DwU1ktKgZm8u3s310pRyF6hXzUuFZYABGDaHR6BrjH5JzDf4661x5q4RREdDQKvFpbPVgh2U6cZl93RJ9HQ4fsWRAZjTVXJH6Kz7EkrW3Kzvs2Zm%2FwyUYT7Hy%2Bo0Sev6fuIJBO5h3rB92D7l%2B3DLi9lsJx0s4D%2BUxenNLYJ356%2B%2FRe91bte7Vu16XD3X4TIqaqfBLnL5UM1l6rwgXfJH6%2BMCZAdfjB1%2BD0ZDHYMJhzfGQQHUYKCgqG3%2B%2B%2Byjd33qrvxBjwyZh%2BfTT2bSp9e%2FzFveT%2BwIwZ8IGuX3bvfT2JitxWfy%2Fd1xNbFyy1zVB33t0I8IiASVr7V6Jl32i1999km%2B%2B68EZdmrPxBECZyW%2BBHJfCe78rIt0ZoYK7tq%2Bizvs59Ka2QgDv%2Ff3q%2Fu7p%2F%2BFMtor%2FHcidfF8Xz34Is5mfK77KRrPdfXdX3av7ZGS%2B%2FzHZnGTiKBLy19C4VSWvCt%2B5shf8WIvAoLJcbNS3vvzawhlvtC3u%2BW%2FVna1yrXffYT3TZXvuief%2Ffhru7WyKLf771eCU0sC57t5bewWQ4OjoGcsG3b9mXIbhq0HXjaZryDxpEROEmWDf%2FwJP27qFR%2FgVIHi3Kkqe%2BWbZ1PDiqxmYOcDV4BwR%2BeOZItsg8Go7SgTZDVNgOosf%2BX3IQriRkqrOmK7bBgMEtPu%2BjcoawOfTJIyukpW5XfWmBqhs5z2WUnyJZcggSEPtM0rjIu4dktUMnI8V%2BkE%2BagSF3VwEXzQ2nyiyhHnugRlO5uZbklyqdlPJyXd3t5Ii9PmLnLvtdfiL2eamW1Z2hMsnp14g1soYDyiqWofQUJVqDvBbrDdwQ%2B8wHTLbtuvZ%2Fcwxw1u4wijHubCTeGgre4gcMrU9Cf6bArMkhxiMVcMdsA1eF%2F8zi72%2FT7p3%2BtC6GeKWMQ4DGGiUXJdgs1c9xKlVVhz8act3q0E8Yd%2BHwttzWlkoyWypXoflHrU1IVYNSJTfLikOEApSAHfzQLvPseyrZZbFg9MOFhSY0wXpdZflIS8cRQVqJjSoZvVSBTD5uZOprveHVR%2FL4bh3roxggFFLd931bnrl1L7EMIxIm93vq7on5G%2F0T%2B%2Bq%2FV%2B0WZW33Jff7NxoQElspxBKCA%2F0aX5OOPqe5LuW%2B58xFq19C27RCJk8VdaBB3DbTSwrUD6MfX8qUePNOWETYO%2Fy3KT8Rjb9fnss%2BVOQg7tGSAxnBNaujBEf4hpqKEJBFxcYxR5cRqPipo%2BRCJUbBbVxjUYUGoe8fh45UrKCUiSR7hKPqlsuRe4zpJO9Qd8JX3OGhzlq9RhAQHlhgz%2BiLFAwf1ThoPeX6Z%2F8v1xJgQjKSraEVO8jEx%2FiT4hwudIYVqPL3LmFH0XSAxyagHI%2BOj95ZhQU5OjeK%2Fd6g0sznW%2FkFEffCQFbOjGsJcvLLd%2BJLbt3t%2FLTczH8290T7Jr%2FwTarJtF7shpd7ytsk2esrUR3NTly4s5wUTx42%2FVTL%2Ffbh2anEwfFtX9zWn8WL8JfhnDQMiPliqV%2BXNcQWPk6r85b2gvqszv6H5v52ODq5PSrnxhdxtSUGq79cNVZMQ0JQ5Oyu8Fht%2BPudirvFZAnqhbyevVa5fosqn0Ujvd%2F1YpwnqwJ6NGOyVr%2Bci%2BHE0%2Ft%2BEUhOFaq%2Fmq9KfEFe9J3pJOCEdyX%2FtBAIJBZH%2FPj4Ue43nJ%2BP5IUwNz7hU4107LfP%2BPeqffjzjuWgNIem2LXNextyRvuH2evFQpyNe1T73596qqtCWu1ldqxG%2Bi1NBZXa4bl2Mh796zuXe4bOESXdO9p22ngBKNSQJhQLBQJhQTJgLEQTBcLGgUhMJCEJBELNVMpr1owk37ZjLvMpR0urT2Grv1vxnk3%2BX%2BH%2Bc%2Fgl7O%2BI26gLqvX3Vug%2Fjhx2%2FCaimOu6zZpV0vrgO%2B3034V08370Ai06wYyOuNJ07NbdR%2Fh%2Bi9C094%2Fiay7aMjh%2FA2DKEel5FTN5a3K4nEASmrZ7OJ67hPhfIIdtKUlxpw3APo1TNT3Zfx8XAXd%2F%2FgAF0o2oZ%2BFiB37manRHbu1V2UbKPvNTNoEiQF5ddeDhAptmjpB0yUXiGCHCKM443%2FScLW9M1cNDG8bvZkzzv%2Fhfyd6lLSMUQ58SraUZhHS1Lgwdta9EDiDjQM1ag4ABIlSMKBUSBYJhQTDQMBYcBYyBYMBYKhgLCgLCQJBEjI12y%2BY67oma56qpdZDcatJXQ%2FiaifF8%2BCPj%2Bj%2BI%2FymrjlZ3W78Jpf7Hx9LnEqPr6btfvDjr988yOoSRDWh4%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": "command=APPEND&media_data=MaeTBok%2F38KSEFphEBezxZRuDvSr4qjOq%2B3v%2Fs%2Fp8t%2FQIy460eWX%2FyxhuPJgpFHqwSssbQXBqoYjV8te7YJsNAxal6qDRfcjzmUsa%2BXf9ejvdFfEUKWofxRNUqyl5bta%2BJvxROOsswBiZ1%2F6%2BXe6alH8dd4o0r7hVW%2Fh7BrDtSYKJOPDRqOzFtb7C9MVxBxkM9C4cQzKg4AmB36QVEMJFxk37cQ0Q6ZQ6wiF%2Fk9q1x8uMIuIfhyRIQYfJ86XQ70Hw1xd6VuFvXM2%2FT4KLv3vr3WVehbHffxcnomVerzaor%2B6xeB%2BF%2B2Umqy%2BBUgZsI4KMvVvcV05rJ%2FAUAgEhwIRgBCwMQLCZcvcG8YzaJcJgPAJt%2FKP4WAnH4Wu4hxWFEhDn6zjpDyVthBzi042Qf4XxVGQYBvlp%2BThsbtX2Gjh5JR8E9rwTOxVA3UXjW%2F%2FX4U2tBkDAS91tOHnT1dAnlyD8FZW8tz%2FKYpbTue4r3Y%2BXyfDT7ggnsov8EPpFLx1EW0X6MAatXo845jq5Se%2BZCU4eIdAcfDcnlU0NX43O6OpgopUSCLK%2F1vieHE%2BhxI3HPP%2FfSlwH67HPWM5eJ9P7KS%2F923X8ERLGbOLll5%2BJ%2FV7lRWSYbHita8Q%2B8UNhvfgUR4LTKtK9%2B8CicRVddK8MICCM8GJgpEPOAHnw8HCwACMUAAjPAcDuNVxjJ9Gem1IhNKdgsRn8KxQACcKDgNTcXTu5YDXhH9qPgGAE6THU%2F%2F8p82%2FjIfSY0DimiQ8NvGyFcQeQIArL%2FvhkioaYPquOic%2F4gqCRGhnmSPPye1vLIyR7a82VlFfxJQMqTIR1fYvVoNeCUkdNHxNiOGbH4IZ58fZ%2BuH5PHS4fgp6BPogPPnu9S%2F%2BteSiv%2Btd1a%2BSP4j2QUbTfVeRrHPASQkERHPnHMvylF%2F%2BOiq0yjFhPY3x9BTNNK%2BT0Pb9G1r8FebM0EmdDvYryVFuZ%2F11XrB6%2FnKv8OsD%2FjDXu93dpq7X8M3vXyDBjIPn9ekuWiLlR3eP%2F%2FC3Qxw6tU9f9iKVLWeqA4YlxP%2Fgwl%2BfopAvUbG3soNJj%2FmziBWJe5qufOT97%2B1dmocG9MH2KrCCBAJa08OPyHkStQ1%2FPgzN%2FBGbG9fpLl%2BW0Wuda774vhmRN9eJJnGC2SeOyvXJd8hBGPUsyT3RuXIUU00pPD%2FcZMWkFWoMaLSks4mOpj%2F6Ky7q57R4O%2FWS5fZqyoPlK7%2FzY0Y%2F1YfXu1ck8wqErbT1kEoWN1E2FzU9gIiY9y8p2pDRbW5qUfPQPDx4HA7b4nd%2FbqSLJ9wb8uiOpQZtFW1rViB2%2BnmCyuoaB8TK6arV%2BgG5LS1wKyJIvcpgCVlq3deihDjXm4uGpPd1IkSGtaXwnw1dSD76VGAkb6Pf8FBQI9RZtCD%2BO%2BKiX%2B3XfloaO1afSxNoVl%2BXu68VnCAKtJNbRAz80ssyQnovfr6S0eJTJ%2Bf%2F0QU%2FAHuaJdSBD2Rp96GkaSlteWT%2Fjq8bnNGn9%2FzcdPhuf1Yw3KQbJsv%2FWmzvLOff1t4ze3DTge88HY%2FAh%2BKX3c4hylQeEgsqiesg2xh32%2BWqJ%2FtmZIUZrSW5RLVPfWQTYUqCTzLHy1ONJbkTYy3pV3U1y1rQKSUoAvNnC0hnJunqoMqLf%2FUn8n36VadUJK3TfLk%2BP%2BvWXff69J6J1er15r37rzlVGTWcXryku%2F6whb9I6rzFctP4REUjF8dhjr4v%2Fbxtl6BTtoWrzXIvUtjKsv1fs6fIInowV3r4lt1kbDrewS4hwTgx4hxIHHoZKvphyR5Kq%2FWbGm5FEt%2FUZ0lzY0%2FLpNyLH%2FS%2BCNvajRN2r3pGoemkr9Kb4RL%2Baye9ZQgRKXb86uXL1lU4QEmYj5u%2BfD5UVv3CPL2lpcHV8v%2F5jU3DY8vR2sU8kGXV%2FkMTO7R4q9XSk87%2F%2FIIlH7%2FJNn%2B%2BfB5ol%2F9zSZ67cXCFnnKkievLhaQfXrT1pe1uqtvVih93tF3tqB%2FL62iwjT3ncepVky9msYdo7UibcPe9XWo8pKpExWqttoKCODtgfq%2F8mTrng%2Bv0Lyr1ahWK36KO36xSk9%2F8%2BX1bT36yXb9aT0uu6wl%2FJcY9%2BWxWNsv3CstyYM9qSJr59S%2FmhxPVd%2FhCPNH%2BN%2B21X6Ixr1FVSszlx2Et5E5M%2BZLQ1o%2B5C%2F%2FxHqzUuQoVZSpu%2F6HdSyzyEpXgAAALZ0GaIIgqBX3XL%2BheXz%2Fr3a9NauVa5TeuV1fr36t9rFd%2Fr3a9drlXrb%2BqI%2BIq1b9bVyV61N69vxw4OEgVSpeA7yx5r%2B%2B14IBnvrwTMtP4UjSYFsfgtPDiMWnTNlPDCs2OwO8p0BnOQ63JhsZSN1Kpxhd8%2BoZjRhwGE2kOvghJ1PbvVcExA2XgV81CoDRQ07vDJcbN4dnLyON6Zd30fqFfUsX6xdE8EO5%2FJ71%2FQS%2Fyn2%2FvtWX%2Fcl3yy4VEmJNKnwmPGkx1rsHG2YPkcWD18tf35BXBndGM7WiU4iaLlV7jRY3h8NqUdv1TVpJ%2BVAeX%2FPDDsqSO%2BQPHWRHNqxbktIeQ8tQlRcWLG5TSb6mNlwLNxLc3SyUWo674O9g1mgVTpodil2IZMy03bVWKPQeIig667IBGXdRC%2FNK1PaMBr7AvjKGiiM6ibT8CwIGm239CYVYlyDc%2BofFEqzyfC2q2aJLEgSuV9rcj7bGUpw4q%2BLaLh0o2PA%2BVE1JwVoReoBprUztsSj7qejCPf%2F53wMDCg4WRv%2FzXCxxaE5a0ofy%2BEy5WNhj%2BW2RY3q8zJQqTnonXF4Ymx4bzPnuOuc0G6LyDov%2FT9er5Pn%2F7r1f9e%2FXr7V%2B79emHaXb6r8MEEcr1WI6W0hVkNF%2BmB3pcw%2Fz%2FoOmS9%2BOek3%2Bb%2F%2F0HSo%2FQPByaBfiXQdPdMFZU9bZiBWqqtVQP59o26K8SQVGkxctl5eXi4vJezGZxFv5TtdRpVFxcXNil4uzC%2FFxekPju2LZtymS7xJRstwIvF2pPFxcXF5k%2BlXx3xduNde2PLlwQts9%2BIaJx67e96WFqU%2Fv9%2FqR8RfO%2Bd9dL3eKUV%2FXv167Xur9Yv1lXq0tr1ernjcn898mXxMR0wsIxzG%2BvV1ovXSE96anvMJRYoz0Sp%2FXKT1e%2B%2FtW%2FV67GCLDgIH8TqeTtSWX980dzV%2FQ7X%2BmFMCT8EB9tKngrZlsQtKTBP1z86gBww0akIJ1mnpy%2B5Lk94pBVXPW1%2BhL1a9FX%2BrSWryc1er1%2BvCAgMeOF%2BO%2BfUdqjvWGf4qtauE0l0aW%2FFIEki8xz3I8xPb%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%2BHziifNZHEfxQbYr6Q2FqTokGcm%2F8LQ4iZGI2mspnTM9pZ%2B%2F0jhAJD%2FvHfwXwSl56GHxkur4tPvy59BYW97vrHddD%2F5hAceJEhb9%2BCvRNqc0JX05yYpCH3lVkuX2F8R2wa%2Fsp2iGnW4bmpdG%2F8aaVzOwQisUW73tZPP6cnTe%2BhDBGZ7Iitt%2FqkJ%2FWXRHTfNV91%2FTZPbr9WFFyELXNCiVRc5Rbq%2FwQ%2BT6%2FNjUpLuuh3SFYql2XLfvrJFbvvX%2FQl2pcQR4hYltGQkDyqW%2BImwGN4pmsauNTXC%2FpjDvpbT8d9yx4hkz7YeNfSA%2B%2B%2B76%2BH9Fa0of2W4zOeX6q1BFLh%2B36%2FBX3Z5ppBMsQca8QcyEkZG6mG1iYScWi9J9On%2F168UvCy7usEWHut%2FUy8WQemvC2KWfp%2BWW8vdehLdsRd5PEE0Tq6ddBMSh5HgvzyEBP9tkCgmQQ6JR2GJXsmx2EFE7V6gz2nixA7ZRf7CQgsPZ0BZsoVx5Y2bOu52dwBkbrxxdX%2F2GcaLrr4tbPXVovV6%2B%2FXuiV79Wq%2BrvTTWl9XK3JyYu%2BcEO1SOpk9%2F7IbHcqG%2BzRgTu9Ll%2F%2Bv0eDsl3fvvT2Qg4Ztz%2FBDhu4wcq%2Ft%2FhifAS%2FLzdUabNlYkgZ1h9CchqqT75LUIkCMEXpqER0mFKDbjgeVSBRPL5mQpLjcuEBNxrMV8fHALWdzGj12LjIZX64zQc4WxW5YWysjDlijZ62MFuNJ0frJaG5TY7ZeewlwTwAReu%2Fihj3QW5L4nqTH6l0L8dyWMb1%2BOY9ZKKN8Eeba7nIpU%2BVWJJZ%2Buom9tG%2Bu2gS3iH932wmsZXbE8%2FBr3D93w5jk0YZ%2BPzTCN05S0j7P4ImxePKUTuoUl9cu4gV%2BEcviCO7337fWTx0ibCEI84veQQEaaE3mOWj8v%2FqCLA%2BUrOXbupcQatFcfWvzeHGW9AoqZJF1qw3rpNHOn0HjYBubmVUKA7rWPCxVamUb%2Ff48ndJzVTr5GC%2BntvEIKrvDpJf14%2B8HakjHRBq5duuatBA%2BHr5aok9fi4d%2F3jLRcjbntpXrL9jDlxLA60c9uel5hP%2B9ZHKMxrJ4o4uXtt9335CgmJpqbW4x7E61haFCasniiVlpzNDWehN%2BiP3WK9yN8hHy03qrJbxgxsXz4MmzqPL7jJv935C3S716khlDU7hv26kJu8vr6mu77yK%2FsE54JdrYLWtbntM0V%2FKkV%2FaBYI7RDZEgz75asY8zMe1mYgJRi47X0vgq315LIIx8iB32r7CZQ7UmC2Wo%2BpEyEWolsvimqbf%2FjZqGw191Nc0iYgmZa3%2BvipWm96CtjUX%2BBhDIYttyEokiYwWuzTb%2FEEBQVVHdB7xovLqJLp5x5ni%2FllN79QWCW61X5qRa4twn4xFxGnmFgolpXnmA%2F9VV%2FIX18Vv0dvyGjoxPtk6r777RXCtW7Jar2Cjeak3X7Z2QhcvrO6JlSXv1LP52TZd7JSfearmMjfe5VNht%2B%2BwjLVLfnhR95PNTfcZiPSp1Flx0ltIg35lKlVa2TX4gmPNPVMyV9%2FoRiSet9cuOPijjJi%2B09651FUp8daby%2B75BZBDtp%2BJr6yb9BFHe%2Fi5fOZSan%2Bnq6nSvHc%2F5f3f5iPf9H656uifKn47k%2FC9f0sv5kSd6zG2ImzvzGBLuFvmfHSF5asJlFkU9%2FGMpPyTNyWh1e%2Fi6PQ9%2F1jpPWHXmLbun%2F9vd%2F0Ie822iPv6ILJhM9kCSi%2FeWIRyKTU%2F%2BaKyZ1pQAACHBBmiEISgVyX9IX7Ge83J0t%2Brfq36tdqdJqlb9Yute%2BK77Xzv%2F9Wq7uvV3612tfE169Y7lu1f9XvwSEhYTIqKnrL62ythgg79T34AaXzyS%2FttLHf%2FS8PhVsZJ%2FpoyxM2%2FS4kHQSKXX086Ps%2BVYMcuKpC18N1xqu%2FVjtfUKxXnn6REqN6kSvWt%2BBHE7wYCAqwwSjdJ9pgpTTX%2FC7DvCczykPhpll%2FuhV9c%2By%2BE4Td4aizlIIMxdJF5qk3y%2BE32IYKSdTmp5bR0Ee2ayyxu0jCNvfp98Q8xTZRCFFKrn1%2BI7l9wqUtsO%2BSYGq8oR%2BQBz5xPMe58GWgeSCskEe8Gvwy%2BIDWh2%2FwqwwUDNhnTy7Dbfh%2BsZphgl3XpF16KSe9sNlDBIA1BlMdjamuLl8ybH6%2Fk0iW8RiEN6qVT3TcGD%2FrF4V%2FF47lCPJ8nvupUTKW%2Fi79XP17vgZ96%2F5zMfxLtYiF97z5xdBD%2BPrK8L1qpLZDFU68c%2F%2FLG6qq1WV62ZEdZ8ybcpkuy%2Fn%2BNKjhqvVVWovWCsdtlraammk%2Fc9z%2BPK1885FPWtlb1PXo8XqtSd4onu7Xq9eu6i69Wu5HZRZBhv5PsqfNBCXNnXS8CXzL1XTIT0R61J61Jckt%2F2sXAy1ikMNGi0niyjv9WEn1Icas8ah7V4ynVd8YZrzMnoPPkiIU5LHRB%2FqqDJrh60utZ6h8G4ib%2B%2BTM5ZetYZQHyRVBgkZ7o7EmTXqyT1%2BCeu5IOXKvVIjT1%2FhauKvyerqnlNBva6XTF8GN5tMOpv2GK5JLR%2Bocvr9eq4r1qS7L4WlXYLDUTmYoJVMjZTXvw6VwT%2BZJDTf7JA12nr8%2Bt1%2FBhLDM8KCBUS0lQOkEG2h6tbVNObdGK5fSdbBBDOYYdpu6xqhkUHVdw60lDCV6jtzZvrNg4Zsr8nzRTtWHyLX2VZo%2Bod5oB2qJLZlT73Jlv5axLkxH5v0fpfVn6tEer1uhZL1MKyGKV65ScPc1eGcmUa%2B6vr7ITUcQL0LPZf%2FUQILz4ajJY2SDmuT91KyIO8aanxOy3bh%2Fnh61aQ5J96qNtJFpnGYDF2Nfg74wcG5lEyF9jOuhHxrZGUYQS%2B8n6QKMBjbZ7iJyXVeJ4y0Q5X%2BhaZbrdE7u%2FVruSf1VuiFcsvioQt1vPUxHis4gfiPJlTQ%2FhyOCd8J3CkX0bUdEJ8kdlNrsA%2FE91kv%2BHC8nUgykWLt%2F56%2FLFHH8EVIhB44l%2FX0SLJ%2Br%2F9C83t2ifl%2Bi9Sy3UOQzD8F5RloC33rfgfxC4sMaE%2BGNN%2FsioJlA8bfXwS0ZDENMsiZbW%2BSJ5sv0e3d3N6skwcjvHhMWRdPd%2BxIJ%2Bqujf28Rl34lo3vEoFuK8XVbPx9z521TY4n%2F6E5fl7lMS%2BHKQMajtZZ8qtZpfERhMc%2BWi8hJIRpfvsp%2FhLNTaSo71wVYZmZadBQxMyz1C0n78EvXNDqVHPcN3E3%2Bvford11l%2BIL%2FwiqwJZPxIjP4MXTfn4mGcEPnBA3NR%2Bce%2F3D84iou1XmGO7iteKl92PjVK9Lv8EZ2pcfY3kqGN5SHAmbn5%2FrmMm1ONS3oX4nsg0hZHm5cxBgfz18j5WJebmFsdk3u%2BYtcv1q%2BdakXjjVV2zGGLzH3o7DO9DXyDJe%2FrCF7%2BXuMqc0fnwS8dx5LeD3BLOYivlpbV5VknYIhOkknXcFJp8O5dFWYz%2BsKUTPTr5ampcvovfr1cSvUKJ77%2BJ7r0VuYpe78dkrMO57uv77Md3d1fYI%2BT%2BvyCsrHYg9yQ1cnbT4Zn3FUNXl%2F%2FxQnNmE3UAbfqXnvBWLKYaqhj%2F6S%2F5Fhi%2BgdQzXgGBIzus8pvQDpDFHPFYcQmfyeH5pRUedpm97Fvo%2Ffgmlg%2BHESZ9yvRe%2FVuL%2FWqvte4JVavXVq%2B7W9WQx0jaJ%2BxGcYN3a990T36%2FJ7f%2FdX2E7OfMaMf5a%2Fy9fl%2FI8iBBD9EGXjW%2BgIBnRoBCNwLetY0mR1oIl5WpQhE0BC9sv%2F%2FXqGeUfpkY5WE9itz%2F7wgjFG0R%2BnjVNlMCQEc8yBVvuw%2Br%2BXAnhxbUE7wGspKLFeewF%2FBT0E2O2fVMfL8ldjiYzK%2BdT1sZXR716C6BY0mOXzfxNLDGWG4T966ofwBiG1J1xFegHGv04JHrnqyf9eWLKaO6TSVVScVDYWlre5ZdUfr9S0l07yky%2Ftcu6J7%2FeQrsb%2Fgh1k7PzeM1Se9fjtIeo7VY9jfX%2BzGKx%2FgjGvdJj8FRvHLNLqgXJxIvv3ya32X2nLcERMJRimgNM0LZkxs1tYdIk71LoOF4FGjUIW%2FrS96Erqv6cYtVnt%2FqOoKX%2BX9lqhnPl7uM4y3L8KGkMZMWurXLjDpbkjt0DHKKyw%2FLR79IZjlRcXjk11d%2BBZxu%2FckKINJHMxvMly4%2B2KNk8dJhc2dlEUyIWP7FXvl04sk9oWzwvr1j1dXXghInpy%2FWK7%2FBH0nw%2FCe6dPeTxVXL2rmNjAydfQJRd7WPBB%2Bx32CfLSgbYfXWdm5sr0%2BOEPGEIm66FXnBC%2Bn59Pp2lQPtBqKy4B2uqUmp%2F30oVmDbq3Kn5EqNfDrZtxrlMv1uEyaqkl3u4KCqvNHrX2CuNtHXiS5m3jZfmkzMYclhxlvezqXIqaSXRgnpO%2BaLd9EMLJtHzg%2FZKK79Hf9ddyeQl06uieXd%2Fa9Xl5P%2BCi2p4wpP4d8verLMZjG4nyfTZHQma1pU4%2BHIx5R7oNU6Zt%2FfZu0Uxrx1e%2FEUp8q%2F1CJQo982e47EOpfzjLly13fF%2B0fPgpEUN5W%2Bu7K9DW%2FV5LUqSerz%2Brl2TDjUf6vd2vsERy%2F0%2F4gZZ33ftBPjHooM3vmUJWkuTmPte296%2Fyfj5D4IiIZn%2FXaGtQrdevTadWrgl9uMe%2BWWXN8cI50UjeXk82z%2F1j24JAlworhgAAAwyQZohiGoFf6FxX692rdydKxLaxd9Unq3MX8n2veEv1%2F%2F2vZPr7v%2Fv7%2F51jS3XSs%2FV8v%2F8vE1xF0vhiGCcQyLh%2Bb5nXgEcv8Sw4WQ3qaOXMIiDSdilkYQGpkqJ7kfVuNde3ORBbfpTpTJCKa4lGMtY2Ryfsub7v7%2Bbtcu0XLi7vvFfV1K0X69Jf6sOc4LzZ%2BlGWgviWNyzy5jJJQ7Q2JKUP8Ihpka0uHftBD7Vgy5wPVzpk36bNTRnjV6DuwZoxBtjtWDLLl5rH9ED5h%2BwwixerqrG6G4LfIKgDWPzuag6YcnpUjvGbPaOQbIg34IRarTjcWKdVRPxeay%2BLlj2WFP0GLOZ1RJ%2B9f0lcBm9PaUND%2BESDYOD%2BDIlFWUmyqbsIQQ%2FngtpyN5LHx77rXcnwlswNJAvVeLZXgY5rjZR9cQ4KJ6P%2B0G2pDN9yBQ4dQYwUbGo%2FcAFepL%2FR7%2B96bH8YNVRp5RBzkuAay01zxC1570T7%2F64r4j7VqCS069fohfX6v8T3%2BuUtyXfhkycrFeDNL4lNXVKfJ%2BPWgzS8%2Bn3JHMuolxfzQ0W7u%2F%2BPy467oFvNQxlmEp2Zf%2FkG5VV1VV1XIA70jbn1vnQfKqNVVUklrvtDUusmpLZbfXsoL%2FwBUqMOog6t%2Bm63EZXy7%2FArFhkme6%2F9lcsJK%2FCdHwktal4la7Xu57k1vxQpu27bt3j338TJsRXSF99K5EXGdrla8hAoalCVd7KHEryNv%2FdK9D%2BmX%2By%2B2nShTg7UBVRqB6EBdmETayggSQqp1fWPPRobW04PM931k%2BMyehNXt4r%2FV%2F1y%2FVj0L%2BJXqubYmuLXqyfMQWTYYcQ3BzRppOy9a%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": "command=APPEND&media_data=mILNrEB2v7zPqPs5V84gNj%2FmV3k%2BTl%2F%2BFvBsHvkku%2FV661uZo0c8KF9QQkd9Ovnr52GrWw%2BUAe1ef7LR7lBDdAq%2FTQDcaF08MzkgwTVMm8NMhkxYGA2%2BHZ74bnqSp51hE%2F68eJM2MLIILar%2FL6%2Fhuyh9JjWhsLJJcT%2F6GlB%2BYRjQxa%2FhG3HcY7Gfbjl9%2BmZPSvdyFx3Xl8uXLhot3d38JcGmXS6aU29%2FhO%2B6e8v%2FqHLCjGKdbQ4YeijpmBCrhy2Y9isRXnwte5a3OY%2BNJdhmEn%2BRvfhL92%2F08JYZa9XJ6r3geAIG%2FBB8ECu69cvF16%2BbXnesYX2JYXESkFAOGVJQ4%2BbVjZ7rBsR4sN6j4a1Z6YKstzpH%2F9HKrWGVl%2F%2FCxFonPYDhKwex9V4kPIIH%2FmztoKT29rCvaHBnqGpXaoww3P%2Fe7iS3d3fyu9%2F%2F1f8PbmpEjGxhMWZS4mpbA7SqR%2BNlHT%2Fl%2Fs%2FOdYdZF%2F6m1D5JZ6U1vaDP4Y5MxUw%2FcIo4niB4McYJCX8MWmFpk%2FeJ1DbWAg4v17jbekRdjv1vJ%2FjwHmo4rtpUMFQFBkMrh6K01R5%2F%2BptQ%2Fb3uSFDtIC7YzaSJ4jI%2BiXL6wl0wv%2Fgj9S0aUVX%2BtVhDQpZPXqvbl%2BXeqL2vUL63N5n3reMGWv%2FFii5EuH%2B2M%2FtvKVKnatxGtt9v7Ol70uy8bMcn7%2B9OdMLiNDcjOMJnW987%2F5oVLdK2iYxwFRfqHqV%2Fr8PCUWUP4ReBaafG3wGsOOr0YEut022D7%2FGzv%2FePDMOvN4KwRHgLR7HfCdfan0Ob8n3fuJEIkeNIAR%2FT%2BZdVnWnf086aX%2BlSC5w9p%2B8bBX1%2BAg2oPf%2BkKkcNyrxuoLzX5mivtQm6u5grDdKWF%2Fw6ZEslP3Mqgh77r1a%2BLpehRKr1r6%2F1r6%2FXvXc9BwhM3WEzllbwx%2FqE%2Fk%2BPSv5ZWPqyfG7%2BzwudwjOTiDtNMj9ixLDi3ipGh6t2DjDW9qwqXCJGfvoY6Y71dBrd6kph5fs%2FYIPGK4I2wOlOasCwjvJam1gZNBA3pfk9b%2FBBDurhDaHtEhTMILbbEO5BgcMAxfTTv%2FvI8U2UFl2Q9jcH7KiDdJw5fENNSxhOaAkoFHsfVg6e9isMZbGKUlbCZbKtaH66x4HJTrM63gGNXen23G9hOGlJV0mCK%2B1Fk%2B0%2Fob4cXpAx%2BpAdQbPQfqnYdT%2F7LZNo52P9O4IL3cP8kLS16rRDka%2FFjhxuvQagiUxqfDpQRiclWn%2FXpq19X1a9folXvtpx9vS3lGZWE6XcPzoDpdGYYwHuljt3CMDg39h%2FJ96eSEsdISXolZyel9Y63JRg93Et9WHCpOZ9sPh2lMPYb3aCdyi%2F%2FcLpMW%2B4JPHTxl%2BFJ2TnnZOWHKM4hY%2FV2NN4XIgIumU4ZUzOWOWO8P%2B2hacL0joWR98CJ%2BF%2Fv6ypMUbM3GXcwmbbmGZfb6aGEIimuXqBwdqN6u5k8anEfmXv2hl33czO08pdzLrR3mfpuo46RWJ4KTntxv1yn75cdZHgu0nnx%2Ft7QfKIJebUB1ui9o4MxIcu%2Bvp594T%2BF%2BvLBIfcQ52v16TWrvcERVXzf99oR2T8q%2FJQ8Zyk971xfPC9L8KlCTXFX%2Bl5BA2Q%2FK9KvHhkTs2UFHsP%2BeAjR2EIrBhX3X%2BNZ7J7%2FqCIu792QgR9%2FM%2F%2FFdIa0c5MeXy%2FLyfvEVhgx8HWj8V1%2FaHis2C0XuICZf3eMemKIgW7LSGGn2rvsIm6jA1aWUd9z4xYND%2Fiq5Uv2e%2BIsu1qpyFht9%2F0ra3mEQf%2FWkYjAcvrvhWai266S%2BJmv5Ikmkpb%2B97DZyYqPrcQ3XbLsKvwYT0%2B5%2BpK3w%2FXWPO73Lm3bpa0KwS8f8vXJnJuVl8UO%2BQWafKeKxmtfd3Pz%2B6E9T9IggcZdLX6trv3%2BQraf819%2Fuunv9a39b7w1cKNLmVcihn%2Fl%2B%2BlBHe923%2FcQaA%2F6S%2BizHs%2B4jjmSz%2FtwdbZf88iBd0uWx8hQF2MvylKe47x715gXZQEfP1lFuLu%2BMNSmIX348T7Obg%2FojrLc9W200%2FXQSu%2Bjvr3GHd6bvPj3Z5ZNeQFYhvbVXVTZ71fdbUubbwhenL3ZRLpfyTZXsxMmfjjrTxvL7SVylvSJuS638u3qjsUWghzpHNX0ZaSfcSEBDrrd3FfYpaloVGtfWq9Ecm1RYJfX8sM89ivvJ%2FXwmO7RBHQo6jJ5CiF%2F55CJEvgAAAJ4kGaIgiKBX2hL16v2r%2FSviP9a%2FWq9XJbWr5rta%2FWqkLUydrXTIr9q%2F0uZwZq%2Fz%2FSpV%2F%2F%2F9d5PRK7XVcv69Eetdq36v2taQWIcg4QZw5EciEtrRjeSbufrCXDExMBGOyI4P9ZYZ6jq9X%2F0rDNy%2FKO%2BEjWL5f8IcEZ9Tns%2FWq4q%2FV7y1r9evlV69Xr1e%2FVyJvJ7ghK3uEjaZyUDtMvysP8c%2FEQ9XO%2BhXG9EqDVBRvKEwjJsErj69QvMRowQMltWnT%2FHeU%2Fan%2BXzzsS3D2CiekKANPn0sXlOGmoLC%2BAE9fZ4uFqd%2BsrLG51EGBJHS73qwy62XH1NSb%2Fo3i3WPRUHZUamOrmjhCXDI0fEkTPw4FuJQgw92tApPBo10%2BZcrr8gf6qNbE3el%2FyojIsFaWNRm2HBqleVBiWKPlpDbLVZ%2Bvlr31%2BudtH1dycvqrnd%2BsrqluvW5K04lQyYnp4v6Z9%2Bpgj2kalC8vRbt5ZoKurazVSXJ1GRHXEz7%2Ftz6Uz1GlZnNLK3VOnlmVXUnJk3360qm8YyzWy69lBFhwHtPvX4ZI76njND%2Bl77rtCe3191qrSSr1VyevRHNb8ncWIjhWaFubzZ9aEvqfXsnlGXF%2FhIskFvd5dDv%2BSie5Rz%2Bnvtap5qjTcOithVMd%2FFFpa1T70WYSnEl0YgyyqnJ%2FvWgp13EV5%2B5BXC6%2BR8fqVBuJZ3ozIDIXtKjOrca70b5uVHYfWvllotYKum%2FVr0X6xfmJhvJAbiQUZbY35jDLfTZZeAq1s9vuIz5PRe9utCYz1f8xGsa0l%2FXyEey%2FGnMbBFTMtdmtFbodjsafhCMvIw6j3lpl3%2F4QqiU0OznwSkH54JfDnUcVv7Y0vcZjuLe1gDd0i3Rz1oVBWxhmYuIPwsQv0GfXbvAYIjKxK1NV%2FLqj1JWtfq7rVlDuVK5VcuX9ar1fuR%2B4JPGy5Y%2FCJOXEimNJWdeAmPo0O116h%2FhPxRvQW1O9jYMyKEBPTIEBIFGCa%2BvbHb3G1690XqKIboVNyd2R6h05yY9xloD1tHlvdUUYX%2F5CmY2FvXFCCXsZ0hyUX8EHMSSUEK1euZYl8YNfbk9qfUReS3JGLvW8RN7HfkQJI6%2BPtML7IgWS4B22RCJ5VbIt8l4cZBa65%2BwfafL0DUu7fuiP0eu1InRHyrVcvWvfPV%2Frq%2FVioEk29eOTJd9%2FYJJcisqVjJ%2BWmR0CDcOod1QQjn5xuU0saZjV3%2B5ojGx0iEqEE%2FbbHziJMwY%2FY9T4AwxBsMHagDf6%2B9N99uF4ZMBdMA4qdTYneApd6b1m%2FsCM3VzENy6OLUin2Horn8vt30HeYxj3Ui%2FXIZWrHoahd8yY9fu3k%2FX40uf933Zu8%2Fp150SZ0X33rjLuVjcMMvsrGljjY4g%2FBWRhizr4KZM5mYDdfoUX4uP3P5wzGkx35ZcPKcXs9wV3f4HdWNblF5xEEitAd%2Fs4M5f1fBLNXtnpbLXNBCPQh3bPOw9HIjNfTnkrj74lvOody5RSmmiR9%2F%2BvfPd1hPdr3sq9JfnfiX53rKWkI7WhZoYuK8DXx5mNNQhi0vusNg2YH0evk%2Fht8jCsVhV8UYy%2FF92XEVDpSf6P7%2FIJjtzy%2FftB3xvzxEZKPoBxl9VUJwf0YfyDg4KdJ4wZPZOnw%2BQaM3Q4yx17ThKzi%2BB142CkqKH8n8%2F4VKkHUKogIAs5KktTp6%2FDcSSxT%2FbJq7%2BwWnvd7Vzf4RJ4dpjv3KJleJ%2FRYvxBh6GTKc8XYI1JPpb6G71bTsxrtAm4OxykbtjaXfvy%2B27WI4qshIxJA%2Bt6EWboJnsxpn8K3ZitHyWEJ4NBl8B1SG0X%2Fx7%2F%2BTvgG4BYn9Fe8f9F8nxzQqOeGf4zGkyVdoY9fQ8elQf%2FHfUDV1JRpvhAoCJ38v%2Fk%2FNybGa2frv4xoZu3tI8PWYzCfk0Inmu%2Bn3MugWpalNf%2FBLsxeA3nTEmct1f0YoQso6sy%2F0Ee7idDUvje9flM9%2FohVoFT%2B52dGn9WPwRlYUoyfLH4b5aIGv41LUtCfph%2B97u6Ancc6EuaZfsENU9B%2FhCz1qD5cd783xqVkFsfG%2FKtcV1yd9N32vXm1OtV%2F6LF5Pr6f48Y7u%2Fn6V7%2Bg8UIRxmXERmfpeN3LMDAZm71Zjg5Fw%2BhNbEv4I4%2BCp0Cvr6CZOT5WN1eT70W8RqPDBJpCSiz58QU9%2B1VpeCIs38vyEzEQ9lvgqpJUGrv7u%2F4fO8e6bzYPNr6Zya%2B3KbCR4eZf%2FUNkx1wa%2Fq7YFA%2FQYlx84YC%2Bvtq2kmf9gtshAmOOSkBKVua7L974MPJArw39SyEmP0ax8Gn4b4%2FK19HIei9XW1bf%2BM3%2FWI1drcvxG2Zlr6%2Bh5scBCd78PTy%2FDZRmah8TSqQTGyNsv9%2FQI5AtGQUet%2Fe3%2FzTL5w%2BTxBFj6bZoaT7MJGiIvCnQv565sOc%2F4KBXDsLRujw1l7E2TP4VkBBDYxLrhNa1eRfD7Z9L%2FGnBHP93GiVrhXxX1X3Rc832CTzY53rekXtPgiIovt%2B9313hUl1NjtEVX9fUMO335pwgDMEA14JDu%2BmH7tU235CDIzpb4t4gfhPsiZ5Zfi4%2F4We5e4Hz4G2dfCl6fjQubjDukaixRoN%2FY6hKmlZFoy3k4KCVXjBhIU%2FqoY682F%2FQUjYgrqNHOWCAriP4cREbQ1hL8MT5fX0hGwwTfXU9pqHrxegrujajcQ0eg19IPOV63y5yDe9KJDYvjj7XzOgE71bv9epC%2FCWS1ay%2F%2F91cq7xRpwQKSodTT8%2Fi7rqjrJ%2Ff2TDTNHpTyw21d%2F73f8FBW32Rc%2BrzXzmfnsqphz9P6Bafd8tMX48l45DfQKX40Mc%2FHGhPU1ZBAWo9Rz%2FwTEWiAtyB0y0SJ5P78X0Q%2BQk8BDJCrTxh3e76VpE%2Fbd39hDHjaXOK90n1%2BHySRWUeoGXjeoXVph%2Fk0kPqexLpjVL%2BA5QL5t74BtgVz1%2FNrXEFBIfSSIDwkOL3c3otRHlEVN2Z8LFJnkFJdl8oYCjSW27BHSszfEfm3WvBDbfr813vfuCWkvmpl7mIXE%2B%2Fw5xdVxE0Uf%2Bt8EQmQwv0%2FL8Jk35zZrwWm4YTaQ5njUZ4vxGBD5f0LUwzqeui3EyRZyovuMoL%2FEvL%2Fr79s2X07%2BxMf77v1u4k7v7vwgOXvCA4FxMVu1fuNo738114g0Gb3zU%2FmzZr0WKR%2BkbN2ffqci%2FHisPH1S%2Ba2GtN6yXE9VcZt6xU19%2BKiyc%2BYresQixxXu6BGGL%2BG80RV0CsSLvPSkk%2F5uXlyu%2Ff4slOqV5Ln9DYKter0RgTyc37KSm%2BnurR4LxFFaTxAzhV9dX3ggQVPfct%2BwYWn9tpWm00%2Fk9y5d8vy14Zuj8Qy2Xfrpw3ezq23En5LjLrzDX1fSt%2Brk1zPXBCEDYJ59%2BbbrAAAAaJQZoiiKoFcloSZP1cxn8YzUgLuXie%2F%2F1f79k6VX7776brV%2FT%2FWL%2Fq5e1rvr6OkvGeV3J61fFK7d%2F12vVmEAgJl%2BXJ9bA1%2FDciOPNRv4YwCaqo7%2B3F3gVLv1VaKjjaZSRsQCZ%2BYPtH79Xu%2B17uqO7%2FWr7Vqur%2BWvXpPViXpW1SFOcyyGi05OanXNQIOMxGGl3Osr%2FLi%2Bg2CHMqD9AlziwzF8lkckXcEOG1EGWp%2FfW7go1SIwPDxfDaY8qCkTYnOoDxsZAOvunr0S8rwz8B0gcqNtXr8Mc%2FZ0gN2LV6%2FkNDD6p85Uqwi%2Bvv75ZPXu5LVpPXKaeb0Zh85F%2FPrXX8pXrl8CXX1cV0eCUqost62Mvv9VfffzS1Zf%2F0Xv1iqWa5R2f4frldq9%2BKFG9aFKv0Tqd5e0Jq6KWu1Yq%2B5boQsXff4oQOjL7AUxJYfwV6lJOpmJI4aV%2FVJ%2FoXFdr%2FHLtXr36vVapQ9rhJ6v%2BtTerlesq9b1E1r5d4QzevdV%2BtSerxHrFXq%2Fs1XStTClpv1GHnQWbseFGI7uUNPfcTDMABXyfaa9Vc%2FZL3%2BOuWnkXtSMKfE6mkeul6r5Zbq5vBATSMRfbtNADHdz121bajIYspCbL1xf8Ny4JaetwXkL%2F3dYqKRb%2FiTz0%2BbMvvl%2F9IEJMeRJfeuSfLMsK9Q3D95Bq09Hr9Oa%2FhLox%2FPjXvgh9TR79Ceu1iq5KSvVv17lr1bv9e83ya8SbmilP80ENY%2Fy2eEQmY%2BZ32427A4YRMFcsIIP2cpZWLsPCB9sZX3d5wBdlECv0AnokbW%2FGcwxNIlyY3b8CX2Otsx8r6akG2B%2FElG4T27uzLmTLfeX9dxd3%2BM36fCBKAw85NcmNYcO8y%2FwURsbPzr%2FL8EeMzpevTOFF%2FfRQSlODXeUfMQ%2FfglsmEkCirNn34X7BB2ntTS1jVo6phPz%2FEq1T%2FrL9elutV1%2BvX3e%2FuKEZ6InPYSjWeM9DnnwYbu5YchOvLp%2Bz%2FkEkDAjqVofw9ew1B2TTuzXx6WDGGJAathxfm%2F%2Fx5LUUdR%2FjhEQ93%2BIKnfPb9faNB7oSx%2BKJSlMtZlZba%2F7nxNQX7KWjZTf8EJi9ed9vwS4bkdN%2FaaHrjD4JZqVvJGqS38PxFK2iz418NbtXHpDMb%2FnKvvWjNMvxHr71XvX2yCL3%2B%2B78t3v9h6G6YtMOSJnY%2B%2By1tdGi%2FJhPImoYm%2BZFixkwXn%2FwTTVgXsewbpkSz9bATPwYFtPghZiuKRWMPGu8%2B%2FDetgZu5ONfwa6J33kE0V9YYNonhxGHmB%2B5deGW0%2F6C2F3G1RIdSKJR099%2FRojq5J%2B%2FxU3js43XWpn4ZvGSHqHNL%2Fy%2F94cpDzV6a%2FgZ8z1r1flEFGX1T97d%2BpiUyzhfBHds7uKb69W46x366ruTwRG4wYpd%2BI0Bj4wsuY0y%2BUowMnjgka%2BwQkgePmINt4bvuuhB5Pp%2F4a1VamQkjO%2F68h73Xqz8URgpWJWJWP0JSn5DEWdlXgvhvpUuTOsmt%2F%2FCHyV48rBcfCATWvd1ov69V%2FNfovaC%2BRd4sRx4xxJejFzyYD2ciwj78vD%2BzSDZ0A41IfxfDEkrqe%2FPWapF5%2F4nlyVdJF%2BjPv6BERDcqjf8UXjQyLr6uP4%2F8gnNbL4uOPvym8iIoh%2BUVaQTXxQmOlh8aLn%2FDu7UpjupBBNWC3t8KJQ8DSLmypi%2FTxl%2B97kWuTevwREQEkNC4H78VJn7tInjf2E%2BLzhgIT90HNK9ej4fuVj%2FXqX0QjBXR%2FCeNAqEpy5QF8EnLDL8pKcMp6vis4sYY9lIxL69Y%2Fcg0I87H83vrEYaVYtOaSVfRs5i1%2FFx%2FHomRUCLNVOX%2F%2BrZd3r1qX8OQ0qPHlwIFqgM5mIf93YTkDEIWKEB1QQHlaHePjJ8I4%2BMK%2FNlkzLQoxXq4%2BQsySq9TF%2BCilap7u39fnO325ekd64Ixg9THUxw2C7u9LZuuHvfSO634rwrk8fcfvtHYFd5hRr%2FwmUaCl%2BWf89z6bIegOX1PfhIj07W18EdV%2B%2FECbT4e1f%2ByIU9X5P3pX%2FMYeLLj1riJeJaaCA73tp6uIg6vk%2BHcVpq92QhL7d9a9%2Bj4a5FBL3fLTF6IjdXoS8T5MVP%2BzW2ovwS7ZjHHQqUFfvxGNDE%2FdtrXP79Ofb3JH3s%2B76BlvrXkpJfxGlXm1e7vfSMl7ifQ%2BL9YvRFwq1ZMX6%2Fsvr%2Bzbtbk4lFf9ld9LXvX8oQdH95fQ%2FVjpL16sS2rpr7p5Pfr0TAAAAT0QZojCMoFf6EtXq1WrYz86hDVfpfpRin6sdcvqVXfat%2Brnf6xVx36xf%2FF9%2F%2Fr92rfr3%2FSrKqomk%2B167%2BVeqiF7tfXa9XlNHQlYPkOjxN4oIq3a9fJ%2BrPkXrquv9YK9WJBy2m9XDpv0Zj9WrwRVzQcfPVNbf9%2FeT79CTp8qv2rE%2Fq36t2rEW%2Fbk8wpDkY96fXdF9%2By9oXUnqKbvuX16X172Jq%2B%2Fiaui%2Fwxr%2BhjdoXmq0Tr9Hq7WKS1avVz9e8ZWq9asUpc%2BuUvqxMX%2FXIKDMr%2F%2Bte7u0JcRX2rvDeS5fV5rq5C%2B%2F%2Fr6gj4D%2B5b1S%2FiKsV1qtr9X8TyfH%2BvScXJdVSeU3N5fdf98v76gh2i3UX1%2FexzMF4mI9H6%2FViT1aKeuIM973%2FMRakSV6sSpxj%2FZR0ub%2FwSiOfOEnLldfvy0r1JYO4yOL4Qo78bSoG0Y0Q1Afu%2FRzNEWtS3J5hFXrwiVpoeF3sh8ZOImtX3%2BQR%2BCemhHDATXCeS%2F2Owl%2FvwYa2QMBGkz6SjQIjeODQzf8LFYbofM%2BQ6GJy%2Fpo%2F%2Ba7%2FwSaaTXfh8is0A4biTePHaUiRxSjkMKLRQxO3RfFcc6A5mY%2FLjtwq9fzdG%2FwTlmlz55fnr7Zd%2FmJKxcty3clXouUvoQ5%2BOu21g7MRoFmIew%2B9cNCbHdiWhTyf%2FwS8NIaC4xTSy%2FtHxfiCUBZc2yEGX%2F4sQVk079N2FJ4X3s2TP4TE2nvf8URDHUzXILux9fFO2FqT8ERToNnl%2BCEx0EA3nPL8FlzqY4CQV6LrB0%2FvwQcbIMA6DKYo%2BmS9TIkqY6aIDh%2FgirlLseojjbJpGOIP9Fk%2BO56l8dr%2BtCe16aXuXwmIGhER0ZGYeQ4koYGA%2FiYeiSPVqnaICQMD82MmP8vn%2F7Gvv8xsZXfiserxyQ21c9%2BXS7%2F1Yry40cevV09rVCvtaq16RYS9%2BhEvwUlKith6zHOXsJP6%2FJ%2FEy%2FD7kt%2BvDcE3z1L6%2FESHXmLeVF8mVmvxGpmOzZnJU9mJlY%2FId35f%2BlRH%2FLVf4I8YSuUH5uO4V%2BNTRfl7u7Jhus69e%2FMSWX8EZwyuzUgiPL80pyhEZ%2Bj3HwXCM3t6s%2FLL%2FS6iEIZ%2BCMvNjq8wlmkwzvXgpFcdokRKH5QXOrIOjvXgrO01gQPY43P%2FbtpuvF5bRcqtYrfqsX6sWvUXe5abuvDRiePGNSzao%2F%2BCKgZIcFeepA%2FjgxfXkPx4QH4IaHaxjPxO3Wr%2Frzr5CFITR%2Fguo0nDx%2BcPBOqHb8I%2BeKshU%2Fkf3l%2FrwTk4dXQ6RIT1rXNYZxQrEL4Rp05fNv%2FObyr%2FFeb46cf74aT8nCPz1QbMY7L9JToS6WeSVarCJf1yl8hD00Cdy%2B7Hv80QsffaLW9cYQ17GVF5gs1MR0UcGfY4ygcv4qPjffe%2Bax3OQRNyTyWh7%2FgixkKF%2BvxBsuefP1d%2BKJzZCFimP8vaGAAJrwRnlhbfL%2FrfrfnxTlg5gH%2F7JcZNuvQmLlKS7WT3pfy%2Fr5DF%2BWCP69%2BW95PLpWvnr5vW%2FWC9KlzcnoWe9V6y%2Feq%2FiSRVsbeSyZ3XL9dX4I%2B79%2BcizDBd9PRPv6%2FxGc1RhvLM%2FZf18l5%2FXgk0EYxnpvWL8pJWP6F%2Brpel9Fl2sXf6uFZd7l8hmlr8NaaV01sUg15n7o5asn8EhXnyKaQvuvyao1X0r9q5infRXa9On5PWDlnuXWSAAAAeGQZojiOoFfcloSxjP2I12vd%2FF6%2BM6T%2F%2F9X%2F77%2F779v1%2FWv1rtWfrF1d9%2F99q53zyiFu%2B%2Fl9ruuI5%2B11VGdJyNyMLEGQlSc%2F5Pv%2F4N%2FpC7q3%2FV%2B17uT1fm11V1cRyLTrJdV7fI%2FrJoQKFcdj7L71m9G6Ty5r%2BIk9C3r1y%2BWhRMa7%2B%2F%2B0Z9teybC2le7VfM%2BSfV9IrXP8tCv5auWWW%2FdYonvy%2FLPX0ib9z1bLv%2B1rus9dehktf6ud%2FrF34r32sX693z%2FrFJP9K3auSa90KW5V7vtXv1ahS9Ffr6%2FVuqKtfX6IxWX333JdCluOIv0W1XVr0ZJmNk0V%2FMR5%2FvXZ3Yb15fNlu4LJL9qNBSaT1K3YmWj3sg8hW4i%2Bi9J69%2Brqn%2BI%2BI7V5LWr9WlL8IrqLJpDDZQPJXVqXPX3VhrsxqdavQl%2FyFGybvOalyCNmNJNX5Pp%2BsJ6n9zGpP4RFXUFExPjuA7Y1PzEdahXFTY0UiUf3aKR4qELU4ZAl%2B%2B6zBCRgNg57YN%2Bjx5bvTqVal9aqJrymifm%2FUGEcJTRg6QQsFf7Q2yUm46Pr9heCzHqTaTB4i%2FP%2FeEuLqc%2FvYMhl0wDXp%2Fyff%2BM75%2BjtX4l%2BqQapt%2Fhs%2FD%2B6s%2BPlHyz7u%2B%2BwvpxiV4aUzL8tjMJ%2BoQJdEiUNCkx%2FhI1sUaI%2FU%2FuXDc6YS97QHaZ6%2FjlTCvwUdjO3jj6gye%2B%2FiCnynszNntOH3BLMu%2FUsNaCnGmSrzOxBDD%2B8iweMxcnouvlm9ak9FK3tXLk%2Fbs9wwO1IaNRI2PdRWq25qfL6%2Fgi2OPVQZPdPfDQtQylidfmXGyRA5f%2FcT7CPnHmiT238FpNJrPbLf3BaXEPl61XWlbOZfGtNq3r2Fy2%2BB20Ed1EShpS0Q5U%2F2dBW%2Fcl%2FUfu9H%2FaLll%2F6oQatpIYIVOJA61wYYScbszmrudsGPknr47%2Fp5fJ6cFMNjHSozL6GjZEBAdKk4r1Ctx%2BI06fR1bV2q0LCoOEnsfA7icRwUeXQstr%2Fe55fdFIn61FSnFKix40f7EwTbAC%2Fcigi%2FK%2B7IG9iyuP%2B%2BMApWhAOwtsk1xV2eqaMeMv79QSC33YZWZPf5SM79RrvfeT33XrbDB9wyzry0X9hhzc6%2FLzkEEvzerXk%2B0CC7fCXupFpu55y%2FC4x%2BY2G4lsHrsNQW7MPTNbjCvKOytSXdEHEtlmfd%2F64V8msr3Xqu9Pta669XXiKtd0m8cYxGAgxEFYKtWoPLj%2FoXy0AYeSQ7gmCFsTaiYHWPGPer%2B4V80iiDiTVJIeEJ%2F3cf3V%2FkKX6Z%2FvU9Alrmga7M5cowjNJmTEY2Qv3cnldT%2BU%2Bm9%2B5CDYvP%2FBRaMY4xieVN9NhKEbebjNN1nw9%2FbBJmwOPBm3czL9F6rWqy4j0fXaNUifBFhkg3eB67DAh8fBUk%3D&media_id=1254206535166763008&segment_index=19" + }, + "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%2FlSnuKqsQUhi44AZvnrMH4EE87o11cn99pEM%2B%2BTQmvyEjqZizJkn8rxm%2FVXeT5%2F3kMbO%2FcPQjz2DAq0bZGZxt7fyE16X%2FCpLEQYNWELJWhlfbKlT84eKs59C1o9NOqin%2BvtWlGSFA4v%2FHz0ZGmXWtc3OKcklq379ghIeiTCR0k7pY70J71k8EgyAP9%2BOstU%2F9L2HSgET175V9q9HeUMBfID14wK5QgxdwvKMgPL4DgIytgIiKFTuTZMG%2FcRjJZd0IuTyr%2FJ8v%2BYuEDF6C%2B%2FRSFwufUTu%2B%2FjUXvUMdUy0Ia0EuVIW%2Fvy%2Fy8lUV2v2Eb788Xur7hnlGCfIvhm9T933JMnLJd%2Bivd8uT2v6CogRk%2FQpy2qBnor7cIGa%2FXuGEShf2Gbvdf0GG8vL%2BrWI5eF0IBinfNhXu%2B7qP9%2F6OjlX%2BEnl%2F1K34iOkPnLk5LuINZ6UHuz0voGBcmt3d1%2BeL%2FoOSqH1bkSL8n6%2Bk5IStAaVwkuzoMbI1B2wPtSMme9M3YFaoEg2h0hPaGnDduuSh38dvlReu1y%2FWviPibtFi5%2Ber%2FFGdl3f8NmSnwOogS%2BgMgwhpbDd%2BGCsoyE2ncfidnDPaMEP5vbqXh0rD%2BfIV9%2Fsr6f0IZ%2BWgNjc%2FfiiUUaGQaMcehW17dbhcShxpk20Kep6G9fQGlDkT17BGQWYIvvp%2Fy3dDBHL8bR%2BxmzjrR2kqFxbhxlvGAAR0W%2FNwm72ny%2Bl9B3hIYXbmDul81wJzaRUJ2vqBwVzZf%2F%2BkviOtYpObsEVVXlk8%2FJe36TuJc%2BlyQglaDrzPF7xSOzj1glvQe78PDfXa9J4LTx8EIyz99qenhOfvcyLdeYkdk%2BoP%2BEuoxvu5GaZx5CCcs4ww4id%2Fb0CgmSo2MKErA2B5w2MiiiccOPMxk%2Be78np17xr30hMtLVN2cq%2Bg25NpYugRiQg3V6ByidV79ertYtq8pPfqqDhJ8Ttz6BD0WsHV8GE0KClyiHxkVvDyJZ%2Fk%2Be9wW4Juz5H71hdcWT%2B%2B8FNay%2B94ma7K81zXrwSF41tvw3LT3HyPIh7Uv9HODb3u6yftfiQkPjl9MEvy9r%2Fqyfru95Pxkql3toVvwkO1hMz73C5jFd%2FMR1FE3bqe56J%2Fc%2F16K%2Fry97XxQpgPLlwman%2BwYb3OYzkGpfkRfqrZSGpK5v%2FDc2NEvX8GN%2F%2BTu685VYeNd9r5IRD3N35f3dUQpZfLdXC0udxt%2BXXhaOltfd4JiPfNi8H0EhaMJeJ%2B7u%2FYJCZR4JML0P6YIvDbT69wWGqG5%2FpIhWiaB0n7TW%2BW9OyxVZCrJ%2FEb04igh9ovHw8cZ8R5Px%2Fw1LPqzHJ3%2FUEyteWU137pPRhb3epmr2Iq%2B0V6uXv6FTVqe%2BWg8%2FX4g0MT5dZ6f8FnPmNRHaSLewl%2B9VCxSYljXubPj7ymmvqy1JZN5tv8El3dlcekRlE9e7%2FxHKMklF6gL6ngMD7bvnBCTHGW3OaHssNZS3yfbLai2qRSebd7iu73fxXSDaIQvxLmNsunxRT4lvRFuTyrvNe75xfd90pf7uxd3e7%2Bf6R2q1v38IyXfr28RL9b8xD2173dAk4PeFzEJPftVF3f6T%2FCRZvy4%2F90kFKak9P%2BV%2BSilBvcSwgId77vd36hkhi96%2B2Xfqsc0hB4UqYx2mPS5rwOy9PamfZM%2BI6gtEwSb3YyfddhM5uWnaG92rfrl2rXd3%2BuUVv2i13PdF8Hxm31y5cnxOT7CSr7MSIfEPgAAACe9BmiSJKgV%2FoSxXEfq3xK9iFxCr9Yv1ea1aW0XquvUqe6xeSraulyu174n9de6nT%2FqV741E1Qxffq%2F69%2BvScXYpepZV6vU%2B92gRjIT%2F19%2Bkx0fxdqz58crv11y%2FP1Y5fJ6rL9e6dW7mlq1cu1qTzCeO04r4rwzpJPYWxa0ES6jMkEM%2FveodFwk89voHhhFrfdWh%2F6qr16bVeUF6x%2F1ee69fKfkcm9k%2BybvQhvcK32fHzfTXbLumbd1DaO90isSDt3dU3r3c3rlU9S3L3V5Pu%2F%2FNrVek2a4v9WO5lVzcT2sX6v%2Bvf1fffk169NxfavVfp%2Bqv8I%2Fq10TJ6xr9TqvlrFxZMZ18N5ZhB3Tn%2B5RROKJr0XvjFgqlXvqEfBQI41jpi%2BGX8jtIE5L3Te8G1NRgnDq4dubkFuKvNtnu%2BEt3XgPlhOcgvVy0Ar3hmym8ufexTKLvEl4mpjiHyTyXUxnyeP%2BqPldzLm5OxflzRAxiJ7DhA5M0BqszEWKYuYYh9cH9QX5jVoPppXqTgGnTc2YZcvDRkpRhHwwwPqyFp332HRKBDzXjnIIcNrRvYIQ537RjUde4iPiR5dwhz%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%2B4Jissxc6je4l9%2FVX5ovkv0Xw7P4ZI3lhnDnYQceWnH3lbMQilwH2g3qhYjX52wkyZ%2F6vd4rrjvH1d0RJd4d13%2BjdtqwvlNkkrLobEJAPwWLgzCQKrGjLQKrw8VWQWiy0dInqvjiM1NZx2WbIVvq5KsKPdf9YboB2x8TKrhYPrxN%2F5sMkBAdj3Z34LlI4eFgv3O56%2F4by%2BwRakRMiy9oRH8quq%2FUx7285tClX%2BCHmUMH2tbBUakkqccQbWIH7p64z1OVCihstRe7vf4zu43l92PKwJcftew9bxuwEams1BWRnDnbILblLW6Xwh5xkqKSyQqtAn2Son2AsfL6S7mz%2Fk%2FP%2Bo%2BTtCctym91eT7%2FkIaG5MZk9uvCxuOY25EuH1fVHLtq0GSjtLtNrRuGGDbosTAx%2BMwXw1HhEthj4ID2PiQz%2FotBwykc%2FmKG4vG8xVAgLgjJ9rE%2F7hEiWmtFbtrfeG4ebjVjD18tzqKXxhBSFTNWg5PGj%2FCR0z81O95Pfe8MlP91SH%2B%2F%2BxRWruzSKJvP7BAR8Jc48xx8qT3QNcenEs67%2Fh0R5e%2F%2F4bdk4ET70mZavn%2FL9H9EF3f6HTGgU0ts0202sw%2Bkp3%2FnPY%2FhpOpzY7N0SqpLTrxuT6%2FoE5c%2FZnz6yfGl5CCt%2FercPaQngdkrAZBhXghmpMZpjIKXj4k9bJFKB1Q%2BvjcCj495TaoUtBA%2Byl%2FB3YG6XF3UAo3Cto%2FtNqvr6E%2BMJmxrIjm8Vyelr4MCZMkSiXBXqYaqMiA8MW4XiiyiBlUyqZu%2FLfeqNoIxuXxhE79beOidYCvZ7D0GWQrPe77JBuo8Uc58%2F4RJl7Z6NeD32NmP2vjokKn8Almmi1%2BUsgxCC4B4HaHEqPEfP0%2Bv42yYtWxChQR6c5qfLAhPeIOC6j9AtpR9k8mS5ZBHdpM9D0fk86WRxBTR3GZXoq7RxHAGPskkrs5WZvPwLleoYkIJR%2FHyH9f8M5rJ%2FfWLG5DRMw0NU9rKXCwr4mru%2B%2FXv37yfPaWCI1mkLTNXQbj%2FJJ6vl4eRLPye6a6ZI8Jce9t4iXL88%2BLxV9K8OsXsvfle%2B70%2BSwzUQv6FufhA3M%2Fbt4Rs9p650wQGwSDvZIZZYyZtmUx18bMV%2B7RRhhrVTm5YScbkZq940q1%2BePJ5yVO4c0cG2WK7Zd%2BlpS0bcWlqTJ4FMYQ%2BOLDZ0FUIWljKin8zFsb2KQQ978fJd%2BuEfXCI4muJTBIJd3cy%2Bmr1aae7RGe4LZIa5xgv23cEWhv1k8W%2FpWFXhwpmN18ZJWbNs%2F95cayTgll6XkyUvcERBLnKn4bidDGPF822EZP4JxOjd3uxufgiJbu52K3nuWiXJ6Wm1QRM7aitk0gSPl5vff4eyrTLBVx2MDayvZgStcvklbynCfKipPfeS04bbqT%2FbTi8pnS5P7HXFCC93l9kKYjrX%2BtmLILafxxwozvtUnWTfSGvP4JRBBomMFmoz206mmz%2FCBT5Q9mjXNRbu3e8mp6VfjRocl%2BQhZ3ryebLVUmETYvyxF93ua6O7f1BUTHd5mOoey3lrfGQ5G%2BkNY%2BbvocxpwHd%2BfrE81oDV8t%2Fgo8Fblt3ux45BuW93%2Fm1qT95aFQSFx32%2Bu%2FL8Su0MuK3dy4K7refL1mqUjv5MxNtcskEaCLknr1evdrFerIq%2F3We%2F3xx938011PfwxS1a2a%2FQjJypNPPdYhZfNX1y9sQYvuzd73OdLHNQ1%2BtSsQS1b0h3162CTu%2BfTvxaH2777Vkkq13xvcROr%2FuGbyPrlXpeJp%2FE8hPf69%2BxUl9whJa2woCQLioGOug7hX9uN8gSr5%2FEvgAAB8NBmiUJSgV9zehLfEd%2F%2F9%2F998v%2FZLv7%2F%2F77%2FVjtZf%2F%2FL0f0nav%2F%2F30t%2BsvRler7%2BJr%2Bia5VqqJWr9a%2BVe8IgvMKLheFX0VYMRI0Egf4X1Wq%2BJvG02zH06pc%2BzHHLbqR%2FuznqO9kqHfu2CPg8pE5kqfwQUNy8dVq9WJB37tcu8JE19vbJ61IKJ7r1rmJq%2B1rw1MSG3tfDkLiOGk8asi2jylo1syan34745qny%2BJCEKAkIGCB7jmA9DqJK%2Ba5acchl9V6Uvl8kkESBQUKfjI8kI%2F5vt2vIwqDQkWgBgd04HOOfFili58FhRssZYwqDh%2BYA5t91Hvh9xPuXRPhBIxAhGriD6cHT6C7sFwVPXJQ%2B%2FyhMEdFHXopM2rtC4vtW%2BXwlr1vQ7yq1ir1r5r9Xrl6J6bk%2Flq%2B7izmW2D7Rm6LQlNPNV3IvceCIRy%2F2gMbCm7sVisVisVj%2Fqdx2QsfOiKyJsKFLjlt3dxWK3uKxW7jjH%2BSCkrGXRRltbxRisS4WzycELxcCSvmW86Ewnfy1RK5d4S5e%2Fb%2Fq57q%2Fat3NfddL0l%2FrhX%2BxPk03%2B2EsV%2FHIK9rvQjv17bWj97d%2BrPpcuVe5%2B79e%2FX365W%2BrVpN5L%2FVz3%2FX5U69tSUYEMHVwsAmSKM06jii9XHM1LtVtDsefTiY8kOPIKmKl%2Fb8B1%2FMo%2BSoEqQT6qRfcSvV6nBLfXVy%2BvVa9%2BrVdetdr3en9qr1%2FgmEUO5X0En7L%2Byq11o%2Fdr0916t5fExnq9euV%2BQZl7%2FMLdHf4el1gqlUfloFkhKQcuHXF%2FPDHOcB7zB7wFb%2BRLWicfxbTk%2BsRfGErU2mozuYmO5SHV0rnDrCEe86LuzxRgF3qfVi3frsUX6E93PSLFVzevT%2BHOW2S8e%2F964snHDmlmRfDPGiJxUHLy19F%2FvxQjFZ%2FP5A18Eg290g%2FV8vm%2BogQcxgS34%2FHROt6jL9vxmIpXw3%2FJQUOxHD4cEbMUubvq%2FRe5KqWrxS1a9%2BvrlVrL%2BG%2BDXrB%2BzBPwflMO4DkzF0vgTS4PiYSE4SuKGJHBs0%2F9x0t6Fo35zwRgbphf%2BFu73evpjNzT%2BCKQkolfvwqRAhtfo8uFIKljlh%2Fy7bW%2Fwhe%2BQ0hHCxd%2Fy72%2FnKsaIOP%2FrJfx%2FOQUsxF6HDKmVj%2F%2F8nqvX6vJcjcEAUJd34FgU2CcvggEeFxGuCILCQkKrG4%2Bp%2F8F0RFAMLAHx2WPWT%2FBILfev1gl8xHr%2BCMp17%2Br2aN1f6t%2BCooWWgXs%2BUVBJGp%2Bgi5fXqHLU2KvtjjywG5aXxuu68KPvtXnwh6XiE8Eojoj8ogLVzsP2UbENuLMBvwRC3a8q8wptTcv%2B97%2FBFVjk2X5C8aal8ZrWVVVHhm1xaX3WpIL5MOar%2BJXpeL4Cv4Cv%2BLyeGPwigj%2BzKTN%2BC8u74wD3rjxPj9eCjuO%2BVjYMHxD4%3D&media_id=1254206535166763008&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%2BJQVqr6I7W1zr1c1er%2Fr13%2BvVcl91KjRfo8q3Yi9D7ZiMWf7Q%2F1WvSevUT61%2Br5V6%2BWT16T1qr%2FVOiT%2FlMrP%2BEPASlDuycbLlxef%2BkbPgjJlwuGWy%2BruozDtJ3KctG7KbNhnc%2FuebyVIZPiaMZa3d6geKpUwXf5EriPQllerx61zEVEww0i%2FB%2BXrhh7J9%2FuGisz35WxmWY5H%2B8n46%2F7kEI4Yx5mfEXEj5w%2BGr3W52Vqdhgyei5dre5uW1afAgxXmypc6wNImGw4KvAPnyrxzuN98ExdVEHuDAf9%2BHKHjgAGWdK21b%2FiqZIiQGQcC4QIV%2BWa4qPL%2FfgjnYRbq8EgkjO7uzE2Yzd%2BH6OHJPqbkmxBjtMGqxsy%2F%2BevpOiQ5P7dcWR3qzuIWNhviFhVzUb%2F4g7s%2BPPn%2FCtcTp66npIFh%2BIv5btXPVZV69vwoHAWXd97qp%2F5byIJBxiHf4HIIFEYWr8GQQxCi9aCQPgmFD6rU1Bjri4qUbzgY%2BzoP3g%2BhWIAAIYHAACHBTFRgjwuBhNgXpJevGqIgd%2FV%2F%2BheteoXpL4xhbyCC6xojZN0ig4jbl%2FXcxLZ8%2BoLyjI%2BT%2Fzd71GQaCYYJ3Cn69tGjv0JcfBUZ0r1VLvbb9r5GV5u8x%2FXuxBAwkJ%2BFRXB7EThY3HLx91NDPxFmKrtb1v%2FnxSmhl9%2F9orpfXv%2Fe%2Bf9ZXZMS51Y8LCDbvu9YG8Ve%2FBeI8BRhr8FJBeskYeRUyBosMeuYARhaTPwgUohhCyWCjW1valD253UDJ%2FBPjK3HyWiS6FE93uCP0CLBbDuhcX5jS4DfCP4RIT8tEfj1J9%2Fm25v8OFl%2Bqlp%2F82k5c3vX%2FMWtL4LTVWqe%2B9cENa8v1dN98qL1jsv7oiqfi%2FCgbrxQq9jVPvXHFQe4SyE80%2BZiZj5ePDB6rwVUVPPHFd98Swpcv%2Fr6hXmxYte%2BMnqr39AiyqXLeX%2Fho83lXaxFe%2B7tEjeuybpfDhBtBq0BzTX6KMUqwuzHLQtEmXQoWQShGYtz%2B96P8L8bpqRIfX4%2Bv%2BEoEn4faWDFjUfGYA%2F8P8ZrvhxqEZF2OJAv2KnUOsDfJ69evuvTfxTo%2FbLiSE3cnkwGM4mLqfBEIe%2FX4KC56oEsPbu%2B%2Bw5m91%2BHb6%2Ff4b4ZiCOguGJxY%2F7MUdA3w%2BxIdLvtrD5HtuZjP40g1VFwIVUWMYKpqi%2BCOEZyeP25VxQIhTvVit4k98LLwRHbJtKgHAeovr679fUYbw3TGf6HhMxRggb%2BxuZC%2FhcaTL48x6%2BjGIB5f71BBG5OE%2Fle%2B7j9ChZPEv%2Burgl1zd1E5P3%2FRe6Ve8JCTY%2FK6vJ6%2FuTlzWvViBEap2eOAhP5PnjX4I6ze%2F0E%2BingPic3hgOrVHg11Y%2BzpHpN4JHk%2FIN%2Ff796Lgls6D48BsEr%2Fpa77ve1gsICN%2Bm72TZFBTKTmGM4fmx2ML6OtchOSsv7J4SnXqAHLTF3Y%2B6iMlXv2OChgFF0wDkiNY7GgFvsX1dl6LjCTheDxYWBkoTGzAO8JQzS%2BDFGUv2dokgzmsTBfbPAY7nCXvviOxO%2FrO%2BLX0vIjoXU9qPXq6YoYfEcSJ3QI1pZetZImWfj80%2BVj6hs9z6Hk4Gt1NtJaN0nSAzGnFy%2F%2FILykbsDDt%2FHdOmCMb3P3e2sVf4%2F2vcfX%2FovXfvfoR6vC%2FhlfwtMDMoZVm6NP5f7XGTMg1jHQfJ7JA3fyHXUDISU1cggov6%2BHC3jovHj5Vx3%2F4KZ2TKycMYvyWOdntv9WKTZf5OhRkhy4VjG6e994JBr3wKpfVXx5jXZWO98KsJOf7CRjY3mJxswBB7DMw9Wy7%2F9caLStcYa1FxdcXj4AZ59%2BmM5ppZKwHjCCzY78v%2BuhvWRqNuzQ%2BWULXeyutWGtM%2FbIhvLL7dM21xjYwqoZvkx6fH7rSCFa%2FHKLXl%2BKkpRlViP1VDkM9BceLi9%2FQUlYCR4GNEf%2FQsBj7JwEeicd%2BWj5%2Fc%2FrZd%2Fy9%2BKXl3aFv3cP%2Fr0nozC%2FbCMfGT%2Bc0Q3gSlymcKX%2B6UF9%2Bb0xgCA2vsR1A6KHr8LQ1A30LL2O0Vx8iswwad2pSwTb3YgPMvXn3r14Lrvbkzy16ghJyTZ3%2BKE5pb79ec9gSTaX%2FhEVoMggLC8aInSWZQeTPiox%2BdfTlx%2FEvRgD92POrTZ8EvYIIRKwZVpHCpw4lmSh09IQYVTSJijLd1nnU%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%2B6IR3vmwRC3vy9xRnVUpZINKkBsYoqVMMljb6nov9ukGr8a18kxVJ%2FiDVo0z9ny%2F1WCHWcVFs3p4VKjyzsUkJtEDLdKH0ZlwHDf%2Fh6XHoMv2ytKbh1X2DDakf7JlItYHIRn9H5P1c7qW8JmXt4lZibvWdgaxtPnivwoYNVioYY%2B%2FQw5xuMYQJE%2FHC8Pi3TX2NK8IMCbeAev71l7Gp%2FkJv1v9UUZGVBCXflXtHgjk2gHYSfJK5eu8UW97TaWSMRba%2Fd361%2FcpTfy%2F75dJ%2BXJ8R1rhu%2BMgQFfzaNzSL4M0TqWaCX3DNYcaZS0OPITjJ%2F7q5rlwj%2BXr7%2BNpa2LFO%2FLDufZxu9%2BUQ9vXWGY2ITz9fIGh0T7U85ZPrJ%2Bf4V5Yh7UhndWmalLpJ%2F%2B55V%2FIV9%2Fm1mYl%2F9Q1KSGmrB0GpjI5L%2F%2FDxlTWhbBDpEfjWMrEQsG6xsczH3BZC0Yu0ekv%2FqGd8X1mGiBgLCH9q4vzLtr%2FhKNQB4gxYwtH%2Fgr5IeeVgYZS8iNo1d8Gd3J61%2Bj1X%2BI%2BKa9waPfkJBL0z4990UyTAz49iTyqXUEhXsI6TD65S8MRJmvQnP%2BGhGbpr9A1GRn%2BTMx6ORH%2BYNGieUlrN%2Fk%2BAohHwudS2zh4RYn5faD18hldDyor%2Fiua2EQYPf5rA8PJm%2BLFWWAX6T75eaVy%2Fl%2FtXBCLj5C76vidC%2B6xWpdLuQ%2FN90vxAjC58fyOG5lXX2%2BldF%2F7wSSiBjJj1%2BQ8uPrzWb2vuw2x%2F34kEdZGb%2FYXIH3%2FabtzqasEgos%2FcrQMIeRBDd0vjQ6PX4ZSy%2FKM%2FCBMuV7L46CI8%2BWrhHRsYAe81pqz0ewO6WsSP9ZxzQwQBO0p1tMAzuAxtHLFKNohOytKqVr21JalPVkR6vIJcZzem911Rd7%2Ft8CzYWvvZ%2FE3paa4Kq710xwfPmGQFRF4on%2Bq8FFViCopkqb%2Fr3HzHIDK6g00pEWlJowRD34U105hYW4BErTwN%2FmFYLXxKNHrj8MbV6Fi3ePtdTVf1yku7m1q2RV15p4Hz%2BEKKcaLikfBcIDA4xyM8hj8EWmGk1N4d3ZdWeX9rzlzn2GSstX4ITvfnUvUIjowFFzYFUBwy3W%2FzU%2FMxL65LjiDMst8eYBLJ5l2QrMirbRbczjICMrHuHyD%2B1zji%2FyDRl2NMwvLXsrCRvBSanj0TWTQRg%2B%2Fp4RnqNKqutjJgVlozpJqFTlMutJyta2sZcJwNxD9PDK%2BT1i3HkzKm3zwieazu3DS734R78JyXtbwRCCk2TRBd30%2Fp8EYvcuaq1eW5LrwUGsDJCJqlirwSFfF21eCTjQ0G8wL8Xd955fiKr4dyOpJ%2BP%2FtfMbGpr%2BQXCJhVz%2BzEmxYC7YIu06cy%2F3qCc3OXHwgY%2FJDpIG%2B9YkFkwu%2Bh5L47EDcctrvct5cSI4OjhZlsuRx9ehBK14uKcl1n0CWLmzSaLZMHrO8TCmXBJofx3dhanWGr6jx3P3uCzuXTUF82FqbJjmX5BI7xhWsXibDTTMkV9%2BUgwol7%2BK2ga%2BV1TBgpTDJfX0EeIcysrJNXD0lil%2BI%2FCIrPjulYxRqGdGrXv4yr1dIIynSuIEYwQppr%2BtflLdJKT%2B6X5Rc%2F66%2FcV7r1IXfZOXOT1%2BspD%2F9SRiPAssXT8v5PQJxfxGG%2FljLJ%2BDsjljR6f%2FFxBOMfJmIw98ixb1TFVWr58G5lP5WIgn1ceX5%2B%2FElBHe96eZGKLmiO%2Bk77vx%2Bc4suWnB1ZrlyGcKgrPc5Cj%2FFGK3iBYEOJnufbGcuJbl1mVBZXlgzhxE%2B%2FYsggcbqebD4fltBOLurkvur%2Fef5fRoJPBIUtteX7kzpZBPwU9q9rf1qBiDDEeJc7i8E4WKjlBWn68TFkBl5VWMeviGlYkS5b2xTl859Txcf981X7x0YCwI4h4X5dOXDIAmRTYo3axOW%2F0POnJz5avV%2FkzX777uVEe%2Be4Jdv6QUCAKwoUKjOPw9%2FpCJRIoFAjDhlUOGdYhwe8OHMxk98IyhANhAbg6vqMt2XbOAcJRVECN%2Fy1EiojIh%2BmLacAAAC3BBmiaJqgV36F5VViPEa%2FU6fq03qmC%2Fifrv%2F9a9%2B%2B1On%2F%2F%2FX2veCX%2BsvEeDHpP1buuVZfrqK9evNMTjtJP72GjAwMIuFUNAv9GguGDvXm75ogNFLwSC0HvBGUw905AgHOWjrl1L8Hy%2BHXuLARoZDBKg3MvB54DzxcZlru4z0nn4E06YKKU%3D&media_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": "command=APPEND&media_data=eFE%2FfuFZYMQDlweeA2%2FE74cXimMm3%2F4Kq32OjwQDTEA4D3jMq%2FvFk94TerCHJipQGWOAacQNAY66cnps0oOI8q38V2opyflYEWD44yT%2FBjL9VH8RLlntBHJ%2FNhtB55GuffaC4jdyxGrAEMHEucAAQwUwr1TVeIFRuvQRf9em9Fb8gg%2BPrybMeiM%2Fhne6pjaKxQvXiOdh6UsXuQ25YyeevRoNXl%2BpNoXHmiA%2BgZiT9KY2bDj%2F85fA2NpYo37k8uDb95P2E8s%2FWjYJtp%2BO%2B%2B9IlmMwS%2B708QaJ3ey9bzC0A6xBmi%2BAd%2BSRcqLS4PLcFnpky6gz607UxtD5bQP6DHnZYYtjPZ%2BFeion6QTr5V6W%2F11%2Bvfr369KX9fRs9eL7NarJaP1YW08IZCHnJP4IwkKKYj8Q9u%2FyJkWL%2Bu38QhQi93dJ5fFiRJxWcEZOXH8s1N%2B0TBWcVctvezB3zhH3foKsy%2F%2F16yiMm2l%2F56%2Be3xHr1V8Fq5ZPXDgIsbIId3zMwM4HOs6q44uB%2Blc55M9fc8YTfDzzcKxZG%2B3VTXbrAoA4BCD8EYTzb7CCKDJoLn%2BjgAEqFIwsFQoVgoFgoFQsNAsGAsFBsFAqFBKJgqFgqIQkESK1U54zd1rmbkJSRbdzm6vVElj88ex8N97HR%2B%2FfP9U2kKW6j%2FJ1PNvm3ORpN7cjzy4%2Fw%2FkFu3u2JSP5ExFhdJdSFokZ8a%2BbfkGu21z2x%2F%2B%2BBgS6hxasj%2FNGLxRXE71aROLVsZz4AD%2BHpBwvYIepsvul%2Bmt7Ryo4xExP5MdEIBopxatLjQGoMd6%2B7w3l5YOrApQucKfY9S0XVhLPV3wCBx%2BYWeztmyBOy86oEAqdnTHJfXmlarSt2qjEi4Uv15xBwAEmFJEMJBMOAsFAwFhIFQoFQoNRINQuETK1WceKZbEpea3cLwpji4qTQ7bjf0%2FbNz5Zor5LtZefKtScc%2BiL1%2B5buu28%2FheYNOFid27v9375hjZUDhfvv%2BfECqmj6sId9Xx5Njx6MHKGVeIG9kr0504T0Hh8oryd5Gc0nAcPoqLbanwuhB1yOffLz5Zl1LF%2BVkuMfJ%2BP%2FdhOlunsrFBnyF%2FbX72uN%2FM%2Fh7SP3vxocv8fQVRZXQLU8UQRKJuglp1ScKFsrNUgvRErfHMLQl3uDgEmFJgoVgoNjIFhOJAsFAsFBqRgqETuet9ZzrupeMhnCRV4Xzdai8joFz6J0Pc%2B26MW%2FWXzD6RdzkizgJj4DNFfiHemVWG5qPjW%2BXYdWQqeWiXZM43c667jf7HFV%2F2P%2BAvZ4Ay9A63D%2F6VSD5lNYJWBaCy0u7ezL8sO6wI8C0d4G9P%2Fn3IeJ6%2ByU7LtXu6LSrOjm6V33x8SnGZT6MLXzyc%2FAg%2BY3XSACNyiQEir%2FuI1EXNZWTx7nFOa6dKfpWPQIXkkf2aFUr14pwSMnADgASgUkCwUIwUCwUCwUCwkCxXCgWCoUCYUCwTCokCYVEJnfSVzML3Des1eVqiJuVdxUnA4bkPO%2BY%2FSt4TX8l3L%2Bhu18H5f9knqfut3zv%2Bb5G%2FLhs8uyyvQFsa9gd1X6lgKauwmIv7yNX7Sf8%2FdrWGSl5vE2%2Bvw5MPm3%2FGZLfEMyHlqO2M5T74LtcxSDRJwKh%2FYsncj6gKlc34Y4TaLuuboGOHUdXy7FK6kRe%2B%2F2f5X6v%2BL3GTu4%2BKu31JY4LF68%2FsLE2pNtLVCpFBR8E6oZVkYRSVSvNeJT6AcASoUkGokKw0CwoCwYC4kEwUCokCokCpBM5%2FHz5r36zu7nJmqupu5qqSqNRDQ4puHRvF0Op4Pyep%2F5j4%2FhGv5PxMz7z%2Bp3n3UzW8nzZ4Uh7MWuNyWHVwkl9vyJHK8VzUI41D%2FV%2FM%2BJkw9MLVQ2DhS1KHbm%2Fr%2BSrtG1IvIxX8eyo%2BNewy521fGh8ejdd%2FkUC32w9Ug9rFgX6xnayMnHfK%2BB4Qv7uF9uBeYrnv6Tu6OdK4APP2m0QghddJZuWqcMUpWkJSvZBE%2FWdLWXK4og4ABKFSQ7EQLFQLDQLBQSmMLhUKBEzmtK3xvm4xN6pZV6pvVVeZ1ZNDduOci7LafD%2FaaF2qPa8dH%2BAg93Fyru2NIv3rXPSXmo3F%2BPAfsByUpz6L0s4GAE2qaTimhdV2eWwYEb35Cd%2Bn%2F0%2Bp8e7SrueU9YS70ydtoOjwu%2F8y11oIXNVJXR8deG%2BMDFC%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%2BoGBqAcDufa9Rgn0JSpjIOGReNBOGSEzKgIlCZRUycQsRPnojFfaG9XFUKVNX1xf1a6od%2BpH5PbiPyfgRYkgCPCfqAhgscJhB7etVl%2FMC3IyFjp%2BUehrzTr75u16PtXJbonx9%2BT1y%2F7yeIdBEUeSCSCoIDeYk5i9%2F6u6oGMP4ZgtjhRviQBIlRHQboDoIHVDtvCAs0FOAMYmhJC%2FblLeKbrb%2F%2Bvr1RT1%2B9P93b4qAABIEqH%2FKDiaviZ8J5sI0Pq7%2BJk%2BXDs3hx7hiLNhQAaa4AqjsNMyxVFriNCcqJ54P6EhxBEJHhYHLYEhYB%2F6hZFthRjo%2BT7Jw43LQhaEldmkb9jLNDOP%2Fof1arlVrV%2Br5fk%2FXKTdaxXl%2F%2FW6xy2u5PqVX4Xzfxwk4iggM1LKoFymoEiiwHN8CAABUbHU3QFRMRPqLuCAAQRxoRDUmCEUQeEgQpmbG%2BTo%2FQ3UBaD4lBxwfATAMbzrieoAFhwFVQOADcoUAAuLIAXMoRxQMMoxu%2BMIwxxsAOiiqeLF9O4m280fs7iy%2F%2FD8oZWAGSabFFroP9SM4y73v%2BPsajff9ajCQwp5g6lflZwQvFTDOfIchd9VganhZN2MnwLduWkiAspK3rPrtBMiVL5fly3%2BhmVZN80l9q0nfv7iyTy0iDGwVJOCfA44lNzgOKX2%2BN76KLD12AAS0ZCCZHBxmUNi%2F3tVCHNkAo%2FdNtKKNno7yGxBhc7iHEnIZrUFo1LPhaXvW%2Ff8QK0hrtxuOHRVjS6UiugU0iESkEsiEmDNKKAkl%2BM%2F%2BwxJAaZcfPlKtsbb%2F%2BqJ5x%2FNOhcFk%2Ff%2Foi8M0SKoEdXk9cvCvL%2F4M%2FAPMFGsBBjAj8BBhLfgIsd4CpgoFPmzE8AGj6F7fKLL9teUsOIQT77hiiSuVatEBrUh%2BpA1%2FwVeE3ig7kYvqLrdOx14gWZsPhDmSQjzcJnfSMptSZP3RFw2er2%2FhlP1a8xOCzJncFfBD7800mPAI%2FBbi4EpIkThqvBHBvowKLaHLEvxfE8J3f%2FEFaH23rGRlhRdHtkYoXHH18mhjTRr6L%2F99%2FaLXzchHFq0nKsqwjy%2FXwqbuK64SA0A%2BFxW4gcOcfbcn94CyBYBFAT4oRu4uqRc4GwEwSMld7Rc6wIRgsDkFO5cxWKxWHFxRAHAseS454EJAliQADfIiwB4GA89Hag50d7ihC%2F3BEPTGwld6L%2BquYlbeya1q5BkplaxTxfBqFQvFm4sDU4OTtHblFGg7TTHDitMR1LvB1rQIypv4%2F3SSOSfSvJZnlyRsL%2FCcX1z2%2Feu6tfwQ3LnFvNoRwMfky318nN3P6O%2F%2B%2BJAoDzG3fgRgmQguKHJknkAlh7lgQjj4ppxYgfxLnM4vvcf3Uklx8Vu%2FaVRPDcvwfIGdaae238TErLnZawL1zWAVmgAEHf8ExyeM3cy4RvpHSd%2BKx3LXKxRVr84gbe7ZjN%2B5hFI6T%2BNm0dvh8AlJACrNLolvjz5YMHnywd44Q9%2B%2F9iSM%2FijcV85Mvv8FxzpcNg5ZcGX%2F6FzpNtz5OMfhy8%2BV%2FIaHJ213Pr%2Blid%2BUEhZsPDy3K4bNucMV%2FHi7all%2F1xO5iMBO7Cr%2F1yu5OSrv0d6L4FUFYMQnGgt5PsNwr8eKfUfXkXresEY4CGHBBAuAqe8t27hUCvO3fA8GyVmF%2FxJ7Bn8V7%2FLM%2BUMDvvHQRaHtPkhq5gwGwJe%2BeH4iivd%2FLpXpa4%2FGtEkncdnn8GOg68IxZ8uNalzUIM%2B4Tq3R%2Ffv%2Bbgj2zgwd%2FV8WXVmXLm9Of1r4myeH7Fagxv9EKDxJO0J7J7%2FqQzhuTF3rvKbhK5THoEJzdW8qlLwgxNNeCQSuvdgnFbmEFDyJUG5ofKUCjzeQ4GIs5P8UOrabn%2F2FRNZP3LVfTG0L%2B0Xt3hfmGJSSQ7HLax4tt%2FfWCDpjINGULkk7rQVOhIJYUP6m3dI2y%2FXThAV5KxjY7eGPy%2FMh4D%2FzC5V%2F4I4fSePZOr5hSxGtk%2FHvUK5kwcj0IMI2tY%2BNmtH0gR9vJ8%2FakvmX2WGus2r61bFEapT4K%2BT9Xr%2FBOWJ%2BNIJLTGW3U4JS7WI9tA3bwm9wQ0TLKzHsroJGCcnthFo5ZvQ05UFV7sgGD3k%2B%2BvBdxprmDM%2BO%2BulFkY0ENt2JenY7zZBWOpiDctivOoH7pW%2BMMWWZr9F9rCo0jwWkLQaBesUwFa2vTTFWs%2FMprJ7qiCBoCeCQUE4MGGIGWtdtpfjcW0KwNoWA3n%2FfIMIAKfjkNj0yDCI72Mb9JzffuZh4ygg6dPICvwD%2FvHPMbSXllLqXYeY7UvHmCIt3eWRbJXwhJ9a9lOjJa9Xq30vV6L369J6EOCeHONDL%2B0Ru6XyfH%2Ba%2BsnrpbhKeP5aKX8NFnrs%2FGwYNii%2FSLe5YJfhKMU%2Fei%2BKIhsQZUNqi%2FZRu77FCISq%2FnfWT8ZBBFxxstOGJQcdS3Rs6LjD48n8nT44xe4uNriQaND6gOGV1UUJQ%2BOiDyfmLuWKg7NKS9nDVNL6Z7Kt7HlUqoxFBkw9liSwL7nry%2BBA9uOOK1uhkA4Z9IXTA36YgqNSMSy%2B%2FwSiTZCRVcAdrYyKuycGJLSk3peouMpPiqfxDgr3e%2FGz1LqX9IoQWbe%2BCZNeNMU5sNnXliyvC%2Fz7fVl%2FniJRfd%2BHBU%2BrSejy729Xru7MMsgEzdPz6roEemmfK%2FOV0I3eJRZa%2Bcnm37hue31zjI3%2F73Xd0Q7gkVqfyf6wSEgsxmRxPptwlfKNPz6iPFiHBRdS6catlPe0U4doIPJ6j52oQOLb7%2BMeZnUbcv%2FFgpKvZI2X9a2%2Fu%2FLemeINbbhP114%2BwcZe%2FExEO949vlqBj%2BKQTt3u4%2BWxWXQO1BWXCreLFWl1kD9BLbpA%2FoD%2FPuCo58yrYHiFooVGXJIFXO%2FLM3tEeFHrrvF2%2B8vC%2BlvYOByDJ%2BaxoC7irZMBaHpdTg9cbhqVjYTAkBQZuXljnPYy3GIcZykGqnItjp84HDIWp3yzRaCpQe4onjV%2FzZr0Tv2WXTnf77v9XLf0CjV06rYIv%2F0TL71dBInGshL7vsmDay9JFEiK5oVNF7BhxhreS4gmyywdypelUn0LZC5EE%2Fjvh9t%2FSi2K8%2BNVdm4zit88C47%2Fd7C8FhXd7uHGdLecuPyzJwhBuGmpNz1ymRCZ%2BT6hOLHiAn1tjRISJuljplyft15CcdxL5YPB3QJdLcuyUGoYWSJmDgjMC4%2FljOWG3Zh2tKhFWDAI0gNXeYgJMp0AfXhJJAwtCtRHUEYuIYN%2F0EYrmWuPu6XiOuvbif6xX7MyvXi%2FLSffUXmv8hYbaMXwQ1kpm%2BVE9qmr66k9BiAgiDu96TvylYjfl5PI1eQQQ197ZqVEjI%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": "command=APPEND&media_data=%2FN%2F%2Fof1XP6LNXQJRWkzrvJGzy9RmZjlII6tqvU1SrvCBZQrKSK0GP45a%2BS3Uy%2B78EmfvsV56%2Fx9B3eCkjHn%2B8xtjsSy3bQi7tGc0cZyu%2B%2FiYgjNMr5aAxve9RsnDLNK6NvJckXr7iKTy97%2Frb96iRPij%2BKPryR5XSfKbf3fCyDBBrWkbcSW77vMOrH%2Bo9E1Nhvkzjf88cU3jxIJbQlwX5fp07QT%2FNaK52iSrpYquy%2F%2B9eUhpf71ffShItUqT%2F6yUXCsvjbWJ7FBQfP%2F4uEPPKMRr6%2Fxb8v54VZYoVavlsd3fgfgTDsZXyXIS3S2feBeMAkAQeQMWOhG2Ky8nrqT0VyvVgXwQ2r6r1a7k66%2FJ%2FRIt%2BFzEM769bBAF%2BsBmiQyJFihI%2B4q8KnIcSzgVwflG4GND4AAADDpBmikKSgV3ydLiFxkSrruvV5PVg%2FXKp1ruedX%2BT%2F9U632rnfWpqpVFF8vxKv2tV6xfrV8RXrX6v3%2Btfhjy5lyC6FKwbOXXgxKXfz14ccf4e2v%2FAie32%2F%2BcPlbl%2BNS%2FgIMFpiaQP84G0H4YMfGr4VsligwIkQg5%2BJHXjUR1Zm49VqGkg%2FtenXjlBxKKsOxi2Vyi2WjZR12c4QjYgRIb1x0u2nOfk8f%2BsIaqR7l3iiah2X1eX1cr1clwJwNgoOfTUVlwtxbi2WMS4KDfykWO8kCkCgK6OtTapER1UT7Nv4Ng0FOO%2Bby%2BW54OPxIesqjywHJYijMZzXUDCCBXgGREI3ea5MDAI%2BjP4dwiywxjeCwixYbqgwjMH19JrC7MP0iK%2BLgQP0%2B3K0HIjuR8W9IZ9r2WwLrxBCIYXqakBUSx92LpYXp7Pq1mtVt1UxXbtOdxmejR06VVIslqABF7RtyjPUrcJJlWXZsmAwF9QAQ2BhAuXIHnMn33kETIxDwMPAck1r2TxxDJ4m%2FxgvkDfXy5BKhgFRpgoPQcDu2TmWed4CWDyOUCb%2F6b5u%2B8Uiu%2F9DcUsl%2Fq36vXq8vrF37Wtj8QOp0hQb%2B%2FyEXsapyCRZhBXWgmz7TTTmhT5QBeECR3wHdamMsG%2BMdCuXNwbcu%2FMC5zgdMVIECpJfA36bWTBWRogCSdIT3irmEJ3SICH5aPa4vulN1xABRCAFUnRCOzfJazDyKAGc%2B3mAAld5Mv009NPTTwc0OHeDq7l7qnPksdeCEp4wx2Di%2BPcNg6PkHrw3hTlq%2B6vuvRWMVv9SpfrqvXKsuf16T161mFmBaERF4rnUVvfmgmI7WRWeqBWTKYFZyxO1AgCeCItVp1M%2F8f6BVBqQi0JJkW1Liiwa%2FfWeBsgl%2BsDB%2FXjj%2FrrnQmpLXu%2BfuXCP%2BS8V1V%2BryXb0jDBoQATsoYcU46NWG%2FcFg2WBGCx6IaGBkEViU5BCHPMLEHjIYpVP1U7p%2FNMaoXmMPhN8eHzaKnUie7s31sskmWioXOpj5%2ByJ6ZJHiHXyS3dXVz%2Bgi0STx%2F7tFY5TDMH%2BB5Ply6fQajCRpF0yHAKejF0skGlhItoKqFKm%2Bun7wsWKxuI6IabLD%2BkNr9S1d%2FrV%2BrHzSS9r36sGKWvVia78wQ5ctVxviB%2BKAMUaZIOFORYx0eL%2BujHy7br%2BcaNUYnE7NVCFLFIzcbh%2Bh3JrLxRKLutfNO%2B1XD9KJ%2FqnYAzhcg6h1FNJExG%2BOmQZOEGeX%2FL%2FierC%2BixpHHvjrWSmZqG9vstjjdkr4xCzYvLSxPWozj0%2FrpQVyleaY7q2gI3ZINV7nv3L%2FJK8nJ8sl1TXUhNS%2BvRFmNl4dUrJ%2Bf2GLC4acjXTU1E%2F7cqBGRV2eoKjWIHxLgompnjkUcvjKauxoRj7LajxTNfEfYcyNx7cwrDTP3FvvsyBLDW6YVku233ILsOodEB4qzq2P6IHUvlW%2BXvUf80t%2Fl%2BnKWxs5v3JbLC%2FPIRKKLrg1sSzzBYQi3MzOe%2BEGg2%2Fv2wUz4Mgs5mIb%2Be%2FM%2FcinHGIueYBqD5Gczzvweny%2B37%2B4RjjfQbLU%2BR4YfiUoP9xNHbhiOo60eYj9C%2FVP2ve3Ip%2BTicnh%2FHgkLu7di%2BIcEOYhwubFmy4XKvwBYQYFLpFzROlhEBrAUwUGVVSVS43G0wWjxAYMq2lFcB874t40icb74zuIHHe2GbUwO8ZyxvTp2guUhK8YEfTNGpwrjo%2Bv32Hpu4MDMGAj%2BGpEA6LvbaMFKC1K8gYD7Vx7OdMfocK3llCJDkEGrIXxLjy8tFdcnpR342DG0p5j0ZRCEwfB3djiFOud8DwW2NcJwQ3OFoF%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%2FVXyeqQT7YIMCD89z3SLtDQMq5rbNHTNSbOBjwna7OsLuxpFLScgsR7h%2FqOA8gyYvbiWOCwEjXTj1lSHtJprhtr%2FiEG%2BCm0lVImf5f8QsFfltxCy%2BbSHGmParmGPyx30WclJ7uq4Iy1cAZVbuu%2BfLJ8pV5CbmI1%2BDCYfQNd51NjWVsdSp9%2Fyef%2F8RXJLzd36Exd7aGAhJcsc%2Bcd34CYJl8AiUB0E5TBLiu8JnAcAoX0xXxDnARQsbdRI%2BsSeKAZeFg5CgxuXVw8%2BZ3UbNP9QqUUAAlEgAEqDAxBsiAdwUE2CTIlZ%2BIFM%2BlMj%2Bf%2F84vv86xK%2FwQYSPu7XQKH8zyjwN1xmpsCAqx7B5NMnzIqDst%2BlXTqHyO1BUqWFU4YpBNR9Gy0%2BVOJfNOIf1tOC8pYgvfVtNVYWRFa7E4UBYbRJGij3K4fNLyD%2FzM1FcdXVUl61Mf6%2Bw0Jsbm%2B%2BPY%2F%2FHkfvY46hy0TQ%2Bgr887R%2B50f83yhkgQDbjvZr4dyoF6lcbg78l8ggZzWzHtGlw46e%2Fw5qf%2FhW9jS0RoK1KSLkL1GV%2F9WViMpK6NgxZjPqnxHHNYw1LaESU35Tny%2BE3b%2Fymufibteq1r9e8dl9Xx3ScBpCfgVxbu%2FwPfeAjw2Aa0GIocKp%2BC%2FED3OB8n7pNWHyuamA7NrKGM7UgZIAA0IV6M0QxI3%2BkfI4btiglf%2BEIBZ9w9a%2F40n8p59%2FDx1OInpmF5R8CJ7H%2FeLDghLfKHeJ4WzCZdtvXqN1JZ8C9afwSqhGt71j1gk4fy%2F%2BqE%2F3eGzO%2BvBA3vqjeVTWlKCggeZ08g8kv3f69vtUXL3Xt2aa1a%2BwUdzmOdj2lcOnd7ve77c%2BJ%2FeSocEMqZs78umeJtyGV7qevjZH13f8MLquq4ye0XK7%2BJkwFQCnhaIMivk9f7BhJgVZXj3fILHRzsUf1DolUCBJUeF1Lq7sufc3gkN%2BWphH4%2BfPUMW726BHG7nQI4bdl9E0sNEffVeJDyK%2FvVM0V30tWGtz4n%2BUMIuE1M%2F%2BoJSpDEqLmvtO3sugX5f7NUw%2FjctqP4JY0Ts2bIwYJreWfmvSHklh0zqMPUzB3kmXTMdizmxqfNkv1JuCCE7g2gQdJWY9oeyQMcYIXt7uoKG7mhVzqxkrCqFSHdLltbfxtrKbMFHDEtOkTVBRECAvYqR3VoPRA56uH%2F95Fgrszyry4Gl9aJq3iCuDc4rSz2%2FgzkSGrk5umq5B0vu%2BDAnybJ%2B%2Fa5f3bUEwzH8bskwYGTD1D5y%2FToMxigE3sNAVolVMgwVIzKdQgcF5PbC27w3W7Rxci1wgUWl%2F98n6%2FpoXmMnx14LxWdg8LlDXtmoR66wOiQ3vGkxb%2FS6IjDQya1nfO%2F6GUhQ0JjlXwyJu4NfyFOVWXV%2F07QchVLp48Ax6%2B73wK6XTGJ27ELCgSNbn3SkP%2FBBw48kQFWDHSF60ZNWHdebIDWr1RHGvqbwwIYYJ2m%2Fob8lWUI6XpUtVkjSG3N2fwQC0g4nm%2Fd4Ef4D3%2B%2F6%2FggpX1%2BT9bVvBfSjRtZBteoCad%2F1TyUUHtwgcH7HEVYkp5LWq9FlXWr%2FP17iukqS9dYJSbu79cXk9%2B7cNECqrjaABF3NYSMXKvDX%2FLu9LbsORwECO51aITq5hf%2FevoE5ZaQdl4WUx7%2FQVkdof4PZRaD8X4H7R%2B5r9P%2FwQyjeK4x933pksFVw21rAlGUDw0%2BfCNyNbGspMMyshWCqwjqGoYTrAm1%2B7fpejGY5MCn0nvr42WPKXxDHvgsiYmGaf5WGJpHEwU5EfQeaacSbXbArcvWjVPd5xh%2Fl9hzQckGiGep8Nnm%2BAordAja0%2F28CiDgzrOsIOfANHLxtVp3F0CXGBSBeD7U%2Fk%2B3MlYobdo94S08UodXdq7wEhr7Zz7huddIma5%2B%2F8nuE5GSJMML4Te5enNRQQL2tdvwo5Vt4%2BBC1zNUptbK55u%2F9oX%2B0LVXckHqfKUaXgZecT9N4c36oaqKKAk5Hh%2FgjnLfQYSM%2BTZTS%2BygoF5iPXWE%2BWzf7M6%2BrdFd7qxdozz7q9a16Jhl%2F5cPXe84KjJCIgoIPxYLUggJkR1H%2FzW05IS%2Br0oSwTr4TA%2BnsiZ8TR5bdSCvPV%2F56%2BMvVxD9ghvtwfljTW2yXZy%2B%2FWEyrfxqXX%2Bv%2FpHw%2FFCNBvGDuFUY%2FuNJXcnDL%2BUHDzxxJ%2FAaI2K8bZfPBTRy0lMtkhy%2BUepnjhDlnISMkuQnbyzo78HVBtRlVYXSLpWl9JahGJLL8D3fk3AIl792rvkPvAVNchbOowt9RxH54yapOL1DkvuYeo4QOxOaTRLzbaicEbwkrjDZxuoFXBidRISG%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%2F1PV4JC8AVMZy4929ZQUDtPBHdMIntHudK54Dj3lwk1F%2F0nLjJB8v5ckkvoX1U1X%2Bp6smqu1cHuW6L%2FQFQFIEwEIsILD34njsjO6Qfyy%2F4HI9DfA4sJevGqAuk8Mjwmhgk%2Fg7tTQCN4jF%2FAhkoMSGgdEicvA%2FSlE0i2FlZygqG3xiUx8zVQJxNi3TTIoVM5JI4DRiZLLTmKCuLdHjph1p0ph89mNt6qwrvG4D71pxJ7t5pEhLnDKeJj7fu7zHUYJRWJX0sTXoNXEL5oIJpu%2FoLSEghaaRvyDS003MhTYgsjd0OCnHCH%2F9Fr3Wv1qW%2B75K9arQmX1e91YuOQME4dWb4%2BMkWQ%2BSxH3nI%2FYXIHB4FIoFBJgVLQPLLdBgzQJuJaX0URAMJvO5RUjxmZfAqhgCSFiFwSyhsHQ7tLoB5H3A761cbgbXpfGxxeFU8bePzWULywDrCogaj0%2FdZVovkQF7uWlX%2F8FhR9k8l8MpmbmDf71r3BCVe0d6%2FCpi0egbaBjYm1xtXw053763xFzLcYznbZfWlgpoH5lqInze7Ahapu%2F5p8D6NL%2BK5BMbW7JCXcFfiGfbiRCTCRb7xVk1F%2Fo%2Bu%2B7uXB%2BEvAohom7ivgWQQeDMEDFXvXxJbu%2FgffgYRJj8AZE%2BgnvSX36oO%2BMzNpwQFmAB6q%2FpPbZAqDcsqMvxvUt9w%2FDs9TjG1Zw5%2BfAiGD3n0C46LzUiN4fl2ziiNXEvDWwQaVOkEbgsyHNupBwdvqbPQ0%2Bj1HAOJ06ojXeOF5h3xFugxDFLnS8Rh7G2AgQxJszmnUMwCOiVp%2BQG2CStt%2B%2F40xbhHhsK%2BHzZfW4p9%2BfNfHGIrY%2FZjtGTjMneD6%2BhZc1C5it5ffSxBZ%2B%2BbxmhBVvggNpX3Cqy7DiSDH8EbV5QUvq%2FjYD9uJOJCrCAvGR8s%2BGwYe4RPWxONxo3QY1YnT2KGKe0X%2FD2aw%2B0yCfTsOlII%2BI9qkzr9BG1j%2FgjJP4fFMrWbhiWFVfdccMf%2FDp2b9m%2FlvVGQ2Nlj%2Fev%2BDC8Pcy9Di%2FLsryf%2BrV2r%2Fq%2Fkr037wqOOP8pcvhl%2BFx5hy7y%2FcoGYYDwSCu%2BkLrtOXLfWEosaNvfswJrymCRwKjlH1ewixzsNcScFP3u8DQrERcQTHhwYG6osTwe4jX4Lx6YbEQr3vsPyCQyLA9eodrBeyYOF%2BqCQIrTjD1%2BzPKGqvEo48mjTULfJ5%2Fucix%2BGnaf6YKSnGDB%2BC2UT9t7uQZ7YICXFbws02eDy2WAMUBuPNSKk%2FSKe7%2FgoIm%2FbmUOfuMKoc0w%2BSZ8%2B%2FJEEZHqizk%2F8RklTk1a2FTHAU%2FuWimV%2FUL%2BXD56%2B0OJyXee4V5LLSVjVBAo5xP%2B%2Fi0dPd%2FErXxK66Jn9W%2FrlV83wJkCeZtG7ye8v4gfd821DZrInAknSv1axD3qBZl9%2Fk%2BbKYFwFKg%2FDLkKMgIJBlC0DbUWZgHKwO6sxWhhe%2FCBko12xLK3jtPgGAxRooMGnWX9oR4WPoKVF4WKAlU9gXPd8FrWOHAJR4onYE0HBCBi0wtJYY3296BOHZ1I0buekMxwSvQglaABRIXQcfZfHBCevwR7cPWGBzDuCUbuiZMDewk%2Fq8pA0Il%2BqeCBvfX5P31w8SSOTAqWD3zfqQcIr339d%2FghKPE%2F0cXqbyUtPU9fwraVk71PX06Fp6%2Fhw%2B7r%2FDuFL8kNmoUZEptOPPnUA8DF8M8aLJ3UqmysORTirIpt4I%2BPM57vsfY%2BuLlrnvuiePAg%2BQyl%2FWgO%2BPJurvCgqHwa2e5y%2BOBBLJYVjgL5THJrJgAPPB%2BgZ%2FQa%2FXd51Gw8JaCBaMHjzkwJfLkopm8GRLboLGvhNqzwoPoV9WWSE8Mv11lJL%2B9813fd4Z8%2BLOTP%2FU5ap3H%2F8vk2WuubCfd3KxKxX56hhgFC3%2BrKQURYZmM6mxLJ9brQYLiBYN36S%2Fxu1L%2F7hKeHlgPWOX3fWtRfjsoxjVYN62p79zerSei1k8PwZCeArBlWaB4jov%2F0taew1hIxTdOfS4Im1iXjRWYpPC6ZaBgK3HwQnSpHLeSV0TxH%2FJ793h4%2BiGYTvCAXeJbquSpmNfokt%2FgjKPG2zXF1pzjvxfVjHj%2BB7Al4LOm2K5UEF%2BmdGWLtpV9omtOQK7nbCt993cxhGT6sEn%2FU3lz4RPhtnaqMtvYZLUDGwmh4D8MQohhCH%2BuzUxykqmwVbcB%2BMxsY4g2WjbP%2FsIDO7cZayE8%2Ft0Ux%2FgnGjjJd740CC%2F4l918ZwJa4sfr6Yvb6dF%2FfscinazEFS4Ryyy%2BQvGt%2FKRLdbkIMA9tYUg%2F0pf%2BrBJx5lu1%2Fk%2FvcsP8S5YFd48CxmgOuWo6Pr%2Fo%2FJ%2BCfBtyOc%2BA7WmPez8O07b9zGPRL6xB84PvOx%2BDCtNqbigHfL3HhJ3jPovghve34LSBj3oCY6aHl%2BE52D%2BgXMwNUjk8ytfKQMfmX%2Fgsk4aeMYSY5djYkEQxJwpgXL0ZsWSJazhZhQKCFdhAXsk4WvUcyhjfZHIHxYZ1liDjwAxIHmkifBYBlWoH3Mqy0PHwjbzOAaPkQEGnLD6nfz5AUh0x8vgqrpfT1GhYPnwPvMEoMTcb2Tb3y1TUrKpk3%2BT2Qnxo4J02weuHW83MlCSfjvkQMJsgm8zpKmM6ViKX%2FWGC5xq%2FgEGVWep5M%2FtfXa9KrLIbVcXXgg0DZjMpxqneVGT5PMONujMLmNR8QXMgYrh8G%2BXM%2BKg2BuOg2kHRrT7fC%2BF5Enc2iiAwdSCWtBBHFvyfz%2Fgm%2BXhN7n%2F7K8VoYvJjtfnu%2BSuJvy%2Fv%2F4jNiHRvf8FV31QiLXJjTFM%2FF%2BhbaSvHma7xEK6%2FX9KU2X1mC%2BQw5kGE3GsJbl1b5fIf1GCAq01CH78lgazy%2BUhR2KPIdgsfEG%2FLxV9978viBysJsJhG2oUQxkE2Vr%2FPXgJGbPStBBRhZVUM85J38D90%2FZ4zVyfUMaWJqOJlSzLzvNvWmoy2AYTQ0yaEmQ%2Bf4Ae0rxIDoMhwY2PBuc06x5IeXJPsUIBQK8Nd3U%2Bt%2F00E6pVX567R9%2FBopeD%2FN6c%2BvMrpbur7Q9u%2FXXWYVCJYdGevy%2BN%2Bh%2BwmUMoAG%2FPDrrBHmNHt5OVeivZf1rRpZfX1FUr93vXe9%2FoSZNrb6y8ZfFciQ4wY0jmLXTW%2FZBYqCipbh408Nu%2BiGUpatkJH3KMJAZvwDwysvlIKOT4IWfxGhFpmjQR8sTcRszbGhPwovZUGyv4SECCDtgqqR8dLkTTNL4cEFBCaa7upb6uUgziGj7tmunPgqj7jm7bih8SOfB%2F7UT6ZfJ%2BlDnDJDAnPwkj8BeqrLi1xRa1A3sI6lz6q1Xx4sYKfE%2FhGhKVV6btB3V1kN%2Fg9DB1ntBF7uTlvyRyVFpfEGz5lo%2BvDZXnt8PhDqr4v1lXnqRRX69Wrz1qwM0f%2BUiFlz5LgUGOl%2Bb5IISXs%2B9sVFbCeeg1r5P2iRDFRNTU0LOQH6nCHao%2Fqw2JBQVm56PzB15Y4aYXw6sXjvum6JNiUKnl%2BLicOhoImPH%2BXwGJzVLl8DhCECEIDwwIyepsfIHPgHUF0baMvR8ICAV53BPCao%2F1EB%2BusNEiD6BaoAA8A8wheVmAB%2FGQpv0P6a7tc9Op5Fv0u8wifP4IjzJbu%2FET55My5SZi%2FCtFi26%2FokFNUdIRGHel6RGgz3aaVM27Rd5PNcS1RIsnmSXqHCbmos%2Bpx%2FWF0SOoh20f9kyoxgYyWrr3NmXwRlybBCN6mptrmNlHeC7WVeqdLlr0Vy%2FWVzojSfcP1B%2F03fhd78WcERHHu7HgVx4KhA1z4K%2Bw7Dteitp3ukV4EIPA%2FrFgAAC3VBmiqKqgVzDIu133L69drFUX2rdq3%2FNK36t1r36xd%2FX0vf%2FKrnv3%2Fl%2F%2BEVck9XPicUvfa9fr3a1Xq6k4KQUhw0ZXU3j3%2F4G8LBQzxXdy8tv4pyrMLHuQTjXg6FjeFloV%2B358SeJDSIYJ4gEaDAiwaAzl3C5%2B04MDeU8cOvpwaiFy9BfL%2F8qGtvBEwFqCPVwQr805NX9q0l99475TN%2FuvWK%2FVz9W%2FVMl0pbwesE4hz8vf48uLszURVA1V6jkHGxXcVv2nh4wFhKk6v1z9Z6aIqE%2Fx%2Fnu7sP8GNFNHqlW0lkTuOzx0q%2FVl5U3FN1bYCEKN41qhX7pAcw1VFysI5dQ5Ijvky%2BPf%2F8vgQAhEA0CoYKH5cnOGNG72qWLw%2FkcdaCfal48R7tY2aajjsdYICg1QK%2BDLaC3Amk9t3jntjbyINUgfYX3dA6buKQHYjmXMhap8IjQpT357BgzIVVLdrvH8t3w8EIIT5PW5HvU7%2Foe18X8T%2BvUKWrXr9e%2FVphm6aX1706NEOvRNwIGhBeIfnNEsCXB5Mb%2BWL3TKGXPAiGBDA%2BS3LWSq8E%2BDgEBC5it%2BNnIrZnA2mHouapqVEsYczv%2B7vSFTL9YH2qlT3vlJ4QgmcKDVoVywzGWN8G3LDyM8usAhgfgWsYi6wgqTHp%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%2BCbvnGV8cqc9sIzcvbb33W6DqddjeqfckpyvQGzLR0IZkpKLthfuGNqqDBrcgVt2Q8bVfOphCVHm0ZmTw%2B5AWFg%2F8dpg1kx3sXLZPWek8pCKOW9kmws%2B8VJJ4Qtj%2BIjyXflPnNg3%2Be%2BTzKVc7FZ8JS2Zqed93t%2Bsaz1%2FTNvSKXSHTh2URSXMhKj5x6yaIzFw9TZsluWz0My%2FPH%2FbdQ8Kivwvf7wqbGGg7eurxnzvU2k4tdShQq2xmrlrBjaxpClBRwVT9Aw7mn5%2Be8hb6FCyZPu%2FwRcmJMe%2BT7%2F1i3vYML2%2BW6%2FtLzX%2BmQur%2FBKcm03M7npp7J5f%2FaLF3ShhKBKddRz3qUFPexASS1yd6iQmdXNRCKPjfoFxPF8PvfBCLDs14NE5SV8iLVTBimPgqT%2BynBd6Xy%2BFxIKzBE4TGiRAHY1Dual55yFTEfv9YrvG7uQnq%2F%2FdT8tXJ6CtfonSd%2B3z%2FNT5i%2FERAjDvvn34aMyG5qdYEEbHIjGAAAANIEGaK4rqBXXoWnSu%2FXDvtaq5PVx9a8v%2FtYu1r%2F9c%2F%2F%2F%2Fa14Vq5xf%2F%2Fa1zqRv%2B1fuTm7%2FWr9a%2FWpd1Z2teXivwEKHd0MAERFBgZxDitFtos2bI33zNH9UGquQfx1rwGMsgddo8tEWgdv2IFIMCLEg6PdGd4pYz05pgCsgTTnEqeu7FaH8Oo%2BTw%2F%2BqTDn%2FxlHpUoE2oFX9b9%2FrFLe%2FmWu6tdSUR4FgEhjaiH8CkCIcbTfjiuehbfk2q4sqChCMnr5XDjzMW9Ga1foxvqQ8Bn52Dh8GBaA6jQxbpA5vDAe0xlWwVH6nxQNhtsGjx8Bx2NAFfdjL%2B5bx3%2BWprbGfalX%2FbXS%2FMiFFmSKyG%2BTpWmTgYrllvA7lSy%2F%2BRkCnravmVxPJACQe4Kj4t7LWSCaQbjEM%2FoscczRhJVcpOo%2FmslO5cPc2c1GaAEe%2BwN3g6ZdA8dVKJTNnHVq3gF2B8Uo2%2Bvh7Ldd9HED9M6H6kA5UL9%2Ba8n3J4IB4Y1pKTtRrqb%2FTtAoKo55p%2BT1iZYBXgn%2FQ2PW9etYongT1Y7q1ruT1bvuqui79YrysghTnxA%2BX0%2F2Ysdlj8CcwqVZVZVVXSJu00c1Div%2Fpp6aeLGBni63YEKNS3T8UFRHNVxPAYrwG%2BA3y18Ytp8rGxAPLBnA8sBijLGKDFBh8eVLeWxI4%2BDOwzL4LcfxLsyjqOviooaW%2Br%2BrQGBrAcMLleodtcVYHuWZwg7W8IVz71Jqu%2FqBgfgOUc%2FPdKjrJ1ClDL2UacmRbURzrVaqLYFN%2BX4UcQk4MKZgwFoFg8J0X1hvRcwgj5mrM%2BeBJR%2BrFf1iivWXLXrV0RWT%2Btw8BCghXuQ%2F4XXviV1%2BUVybzyT%2B%2FIShb9nIKoKcet893hBRhpA2hqRBMgg1fLhdlm74e%2FRW6J5%2F1e%2BJ83Hcjd%2FrX6132tSX3d161y92X0xkuxgSBjUNjSYY%2BWHJrMWjqkLWS9%2BMKMAYjy%2BYrYU0OwL0%2Bkk1OMLc6MnzXxAELW1%2FuEAsFgC3Qpav9BXv%2B%2BdXfrWK%2BDHtW4%2Fuh25btc%2F6569al3Wq9W1xH%2F6F6tRYrhIcb%2BumKJ3gTxvXe8KNILCAeDYHABbgP8asOALcH8BrRDjbNAekFNCv%2FSH1d1cknPc%2FrV3WmCQUPLPbfVgtJkzieXF9UFB7CNqjqq0uhn5Qlr3%2BYvEEvEEtH4UlAVTC0NAvdv6gq0vUz%2BXiKG%2BaW7dGnXqCjg94DJ%2BznAf4%2BsnBAQuDzQ9Ydn8lxqpMqCT6m%2BgrUCkQQ3uss5pNxn5PYsLDSpQtprJWs1ADVtNGXb82ca55FVT3L8m2%2B7nre7%2FR674M6ta%2FWKTVa8I%2Bm6eoZrz14diSP%2BCAmeg77KQQlbFdmAVujOnmv6cbN3UFGgsJdLgUb2GnQQNrVEGEvdXP7nyvveX%2BUvDxoldTMhdo%2Fr8eGKb1Nzrfy%2F%2BMQ4aweeS46X5ZRL7yQ00fDxUEeupnKCoIgwu%2FPpSI%2BZ%2F68yCohA%2B9MxWQwrGjGombBwTbz6Wmj%2FrbOxsnS4VZZD7Jyteg6ij473bjTJV5S0Q6uM4w%2BnGQxnr9a427ta%2BgfFXiPitFaS2SqUsI2D7HKCF1rjhmoPCY2XHXJ5kQj0Lh3mhdEcCSMS59d%2F39ejvjumSvrWKJwEObWAuxGaqy5eDIFICPH7xZgEHMENQHmy74dFlxweB4PB5jcdgBx8SVwKnge7P%2F3dcY6l8n8vaYZlo%2BQFeFkfX5MLwQm7gzatl3Ri40L9EZcN8Z7J4yexwjjCP%2F1Jp%2FTtDf55BuzO1eY98feTlQffQstPHfKfgyj%2F6D5xLAVl93gwm2Dv4HkVy7ZwhcMNfaDt9y52xO7uvywvL7feCDDiVT8KrKnLg41IZjVfLH00YA8VO7Epdt%2FxpFjc8bELWf3ZwGGmW6DP6Lh6z%2FjJ5dPJ5ihRJT0sA4X%2B74w1DvOPIgUQkG9CKyvfFBqPrDyWte11hvgy1KgL0d8NqVh4K45PrHFjTPvwFXZulsDLP4LLN7Bu%2B79e%2F6ur1evW%2Fdz9a9%2BuF0Sta40CcDoJeIcFYrFYrrgplGCMuFzEOCHHv1rXBQGRIQI%2B73dRdImTY%2F%2F0FSUt75vIv76EdxD7u7976RoFjBAVVgFyQ1SYDxYB8lr1Gf05QYJWrH%2FgJRj4NglK9SMSxGICXHE7v6fx73vrBOPYwQrl64xbvlr6HE46ROQADIfbJHEanobAHvNRl%2Fq4ptjYI18M3DNgo%2BbjLgGX9hD3eCmIMSAYyGX7%2FJGyIc09%2FY2c%2FxDz%2Bf2UboqISWM2rF4KZ6Ff%2F2CEvcQ5WlcPE0r4dtNjjLpKqK%2BEVGhzbT5SHsVtRQI6%2BndlJfEQg84OsWndOxNgtxc8QSzQHTP%2BGYcR%2BvfJf6O%2B%2F%2FiVqS1lfr1etWT0gTxIvyXu%2FwiKfV3d934xeDFYhCAjbSr1BMJNBMIwKJYqBJglulMoW0%2FX2HygmfA3esQ558p%2FSsjfAMCBlrAYD7%2Bsd5uAkdIaH1kwRaCOXuLJ9fYYDAbnhQG7v46S6%2FkG0TyKDRP5fUaKnD8s1B25ZjzQT%2Fe1g7gr1ZoDU63%2FEkJ5fL%2FJ6%2FWPK7fIpme7l51N6WJx89Lv%2B%2B7y%2F%2Buv%2Fcgl9foQZf57fDa2P9a%2Bp6%2Fn9vqrdFe4b8BJvwWhXWAhQiGgjrAkgg%2FsPCB5YTvcOI1T5rRJMdfjRleGvQLypMOYx3ZOvuU7J%2Fib45wwMrP6I%2B%2Fy%2BXPiOaJUozbX7%2FIV7vsd1V31Jn3%2FEWbVpprr5RuP5IG4zFOWNJ7WIUFMdZVMHW9AhqClyoEFsp2oVeQst8YZ9GE7Z34P8UG49O3LS7%2FJdJi%2FBHkDTtrF%2Ba1CbiCPcf9r1%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%2BRzvwnm35s6hwhqGawFQa7DBRzhykEbdQT%2Brl885AFTZOjmLdpEVhli%2BJXu58IOoCYEe1w%2FIQS4eA51oDuoKuWnuB8ahwwdbPcvsy%2BOBBzMoeg0ARWQ9Mz4mAAJc8B7kEBlXES70qA44DjKX%2BNbbvDHbmOewZk76lfYmnS3%2BMsLBvzfKGB%2BFij4OvwSvgXuOCIGLw1fhzBi7x%2F0QcRmd5oPXJHvtMXPB6BXOQe%2FaEeM4qa16bjG4F7txRV1QMXS36it51FidFRqHYYpuKWDYMcaDki087Fy0A%2F%2Bj%2FsebU908ep1wd1OjHIIHStI9zYlW5IXq6sO7sdDJcoy%2B0O2RrD9zGBvNJGEgskXh%2FC%2FHZWaucqgrDbD0VHRXOm%2BbBBBRTXENSeEr9o8BwOMDgJgKNxGTxvF4nmGDhmnRL%2F1JYfzcyGw20wXcKY8ZXagjXwqVeCl4Ev4%2B41nVmRkRoZHrSsOZabf%2BlRPSWE54JxcVyV%2Fn5f%2Fdeu9bLKGviHrGtf%2BX3vSDYi9Jf2IkWmpPdmWWwwdNqSyhgIwClwBq5QnMQ2IZLpYPn4Xu95Zaw0vo%2F77cN2BOUStfvGEj%2BaZAwN9%2B4JBe7wsv%2FWCgVhxF36GRQ8cuoFueHVAbbDfUGhRlC6x%2B5e%2F7LRw8d5q3v7coDGQQn8Ckx4i1gh3RKdXZuerNv%2FzgwPuUxbYRpAM2v9%2FfmXTgK6tH3pKLpDT89pi5gMrSgV%2FBYadidgZBINtfBmKbQqlnw5egzco8%2FW23DRWDH9OvsGCoZ%2B%2FCIkMQO2CQvzYMfl9fNDBecAoSJfJBX3NV7%2FlE5b%2FFalziFJ37s0mP4te%2FCtLcA%2FqD%2FZQlJm21hq%2FLDRpF8nl%2F3oJ%2BT6MZY%2FDcdGFvUGmrA4crP6Tlw9iMO9VCx8Gdh30IuWlqtHrGq34P%2FE81LP8v6P4JMdQbRauo%2BTp%2FrKZYG%2Bxfd9hmM0qxWprpx1FYJfyZwtuSS9%2FsNQPiwVEstHLnUoYGjjaJ%2FwYXaELuBYz%2Bgw7yMav42MHxtLzh8l7MaiTVxfV6sRHJDHBRx8G5MnTuoivutOhhC5EUL%2BBmDNzqQy0YepM%2BEVua3zOLLgVsBUvwUmFFwBRfD2hQOIFDCCqvSZQoYYStyidvgBmetYjRFdm0vbHFfdu3q%2FgmcJ3ozyXW2HGS3o01Lyz%2FFaRyeM7ewwFPboa%2B5Rh%2Fb%2FX3ZlhVz0woU5BPqh9BCc6f8sGqlUVz0aq389PaBXts7qYqu4LPVdXNZSthitGNHmzS6bik%2FZKKxQzEDZR8YIkO9CeEx4bFtw39fYFHqS%2F0d%2BnyzeiRX6LU9%2BoKzUV8%2BIETBjJWtClv8bgk2vEa2znUMDZM9zupzpVUln4R%2BYT%2FsFuEBCeRozXGVliHV4u1vjvAeMv1Vdd6uXSfW6hztKp9G4ywO%2F1Ww%2BCQtYCNugNs0Y9%2FjaGCF78KxswTtLf7yfaUVHFbnHm0doFLO%2F31ZDNXgu3r7BOcpoGPstOv7%2B%2FjxrvvcsOipwCJiyo9YO2gMHiH5x%2BGQeMQWkj5qAVa1Nynhosi9VwuWXFTHMf5fVGPZRsyElysPr6tzdrFW0MXaQKK0kgH7dSNaUsB%2Fhfz%2B%2FW17hXVE4lxt%2F7TGoIZ9ttOMx8hAR8JVQEv6tL9NUyIlX5BARh2quS%2FbLqAl8w7qurc5BAw8gKkfTtAq9pJx6iV8fyZnluGTqq%2BT7RAqH4Sw7w%2BYbCaq8wd15mFuKGnUgOrXIPA2YkcOsAq0wYmwY6DzaT%2FBGGR%2FgQaZflYyQ17w%2BJDIXCpNV1Vc%2Bt%2FWCOBDCIbEpR%2FRURSpxO0%2F4DvA0iz6QFzGuFTmrcp579EevV1S16LnKnIIRWb711ZiQwIkPXWXCbCdwQn8OnD6s69BJvsbTdVY59j4wh8dL2flyoTUeo%2BCG98cbBXdt90ro%2BDJ%2BPfhmMEL6%2BelL7JBM6Y6tEH1hXnzXsoE4eYSSDYNsaPH9QYEy4XGh%2F21%2BkTmvtXDnDvBr1wZmaeJH%2FwTicErZmzu%2FDe0EzYhar359586gsLwfZSukJfxZvziT%2B9SFBAI82zTMDETcY5qQldIF7p8X%2Bz4rvAr%2FpL8%2FYTt6gpKM1joa5pDhVbP%2Bm2ECTDYJFjzENqbk3f6RteWa6URPZQ7ug5hsg6u1gNhstl%2B45oFVYgZtxt3%2BsTyJWl%2FeSFBgV2mvNXSCLQh9gHSoB3L0u7JzIhBW9P%2BuIxBnY1ED7Mc86kvwlgoICyCiaYtSmxzx%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%2F14MO56Hwflevx6RuuvwUYZcy5aKRf8McGw9ByPMGz83G%2FYS82tPp7Gx1bnd7K673eL4o7Y1RooOu7BKUrD3cpm9fYIYB3FDYjDY%2FztpYRiZLyeqvwjrXy%2B6%2FyEAsMlu7WNsjm%2FHMnyUTfi90mbz02Z4dtNRnvLj2DAU8l%2FqXaCSal3eMGmHgol0mvaHuxrAoCywQdtNaQ013DEaNrbYP9j8vE2%2F%2FJr0Wr9FYG9Eeb1qSFfQte%2BtJ4YhWwlvZgd7n1Ptf9b7M%2Bq6J9%2BHRIy99k75mu1d9yYVdvgAAAmwQZoxDEoFf6E5dq6b16XL%2F78ZXv%2F%2F%2F%2B%2Be7WL9e4V8v%2F%2FpO%2F1f7%2FVrvpsZ%2Bn9e7k2g3wj8BuSh%2BLCYbhPzwWXf4J%2FB%2BzFT8Ym%2By%2BJsq2N8C976HrvO0FRKOH3LcGuX1LYgB4ktPHH8QPrPHoTbbxPrlRG0lWqeVh%2FlxnBfxwR0vL8b7QBR4lZVSQjdqHYrLDP5sJfYZXQon9Yu1eS1v2tSerEVvS6Cf7BBLYG56AEzK%2F84983726w069lwvPf9B6XrAFBtFN8vzZYuBP1NExYcBBt%2B%2BMv4hxq%2Bv8cJDs3uN8%2BOd4Qu%2F2PEB8%2BSeRGGqhqsfdShqyzpGZS3ur98lDZVtgJq8e7i82MD30I%2F%2FfsS6UCXfvqgvEc4jZZGxBsnWa5wgCY45LWlggyGKNXh3O2yx0aOSNVjUHbm05ooTjir8bDmm0NY2g0YtE6RWgkfs3%2FSQ9gfXCM9u6a0LXm%2FMTyU47P%2BIuYUVUCpcaGCXzXkIN%2BGi71Vf7cJImNcwapUJ%2Fq7SeIg%2BzfyMZCpUS4SJrpkY%2FiJCNEk%2F68sN%2Bwe8CWJANMePUAIe9%2FXIKvbyxcAEzEt%2FPN0zbTL1bteq1Ona9jvnfJ8tS36vJdVS8TfQau%2Fph%2BGWffL5f4aI7s6jUtprq1i%2FA5IK7t37vzJBWj6Y0Y0TWbwWNEja0UF5AWlt03mXoZQxeUx4ePcWzv3Hfd%2FG23HL9K6h3rERrW%2FPbfE0pz0sDQphGfK%2BUYhx2bfT0bui%2FWsxCkGwDX6F1x9moRSscHPZGr%2FLCZdpleOFWqEZnfLTXeKyk4cI2rvb08EzSv%2FozeB8ICFTL6t%2Brfr3Lfr1Cl76Fbux36rXKW69X7rjFbL%2B%2BCV%2FCIIxlCkUMy%2F5bglO73bfY%2Bg5fhmW0vNg6t4h39HqITQKqgPnzRImfr7Ry1X2vVV%2BvSX3V1dXVMtSevV6xVSL2X%2F%2FlRO4FpcvxSRSJAqhx4y99AZdhChA5783VVGcrfl8QVf1ZKAVI28qOcZe3IQU6%2B5Yx%2BQXEQD6E4DuZg8EHh2%2FmomiTW6Jv6n61aI5Y2QlFfzsMeWugYYE%2BvfzaQzvyvXaiyDzcuIKkR6CQ4Fii1sZifI%2ByaZA98TDojOtPQI9sj%2FFy83yyQ33NxETdrXBPppOP%2B39k%2BtcRc388z22l%2FuJKAj84%2Bf7uMHqNeH%2BJzPRcox%2FqCgmbDZkpKF%2BP5WIUUxgbnS%2BhsxsKkv5viZZdAQO6H67TB5YZb7kXrJd4Zzc1%2BivXrBXq%2F4IPHCxpsmsIdwYHD23DbHje4QdAw4zzL%2FrhuOhoLUPhq1j%2FSbIzx1K9P4WjBx293Ffs%2FGoVmxR8FUwhrG7kBwmyCAvZoEld6kjp%2B7%2FjZEPm73%2Ffusv2SwnOMfvIIYYy3yRl8ej%2FF2aBpF49rq%2FfEwWRpm0k2R6R5mED32zi%2FBhwuLWpA58qNzXX8n1CMlorO%2F1qRfEd9q7gb1i9L81coZ%2BHeqZpMEwML8NR5mAL7hu3D0tIiakm%2FGxoLXrHB1D4aCsMmmGg0jYcPnfEntbpqBlDXNTvUnHmBmCArSsViE%2BFydIMJNpvw6WiQ8j%2BvHo78f%2F%2BOm9X7nUUM8CDB%2FhspTUhilB8vyjFB39F2nfuF5CS%2BagbVeD8aLMcBu%2Fi4%2BJ%2F6NGcIAx8EBXomX61%2BIOeTyR86DMSv8EZLa8v1Yv1r%2BvXLnUyT3vNiSFe%2FpAkIx5pOK2%2Fwr14eWX9tvF3Cy0VIxUKrKyFtikHT4zoxnIPfo%2BmNhw90zIW%2BzBgZfvvRa%2FBB3Sgi7bNoIogNPQIrXI8KA2hgLV%2F%2FFknIKJ%2BY%2FKbD4V4ZnkxTw1KECEGjm3%2F8O7d7vnhd1%2BxRpMfxRaG99%2FnJjPwiRT%2FvnUfr34JrVJHKYvcX4%2Fjk5QcJuWqdDntn%2FC1UROE1mJP4TWl%2F8fmuOv18DaZlp3k4JeDrwg%2B5EK9ouvz1%2FFd3%2Bryern6xeI3RN%2BCE1aXX4UK1DNFokxNBEDfMEFNXkgx2RCxq442H4iYME37wffnEH5NWSBfJHQgT%2F0ct%2BcjFceJ3%2FDdTZRru53%2F%2BCEh8fYrw4V6dSMDhp%2FrwUdAIbIWzEaV%2FXX6iq%2FVj9WP16rk9eviV2%2BJkn%2BNrbL3d%2B4%2BDg0C2%2Fn9RQnctT%2FXlJxt%2B%2FBDSkCAJqZZf3%2F8OFmNT6qeNEP%2Fnv%2BhIMaWK%2FcEU2Z6Gf%2BycfeS9ljwkC5%2FCVunVH%2FP740MFqfXgklg%2Fi0z6zzVr3GxXgmpb3vnv1yrz24bv3i%2F612CQtnNKL8LkvSxnmpV%2FMojhQE9kxjWH9dfs%2B5Ta8NG5oLl6P%2FgkPGh1%2FP%2BCHNXcq7x3tEik9Fr9arz5bat%2F8M13VuO%2B%2Ffq78hHf%2Br%2Fn1hBw7lMz0%2FXnrcr0BfJ%2FfkghK%2Bzf8Eu5yDTfk3X4rEpXlz%2FJd%2F4S7u7or9GyrxhQrCmqC%2BqCBFTIO36BlqD97cBVJLWHAdEtqP4yH1yvXGQ3o5HdbuyVOnj370lfQYx9cts9fKSPv8PXDiI0lwkYTMPIcRvK2vw01L%2FPRaijyjDyqbgcXLtHTevXd6q5Xq9eCy6PulPnv%2BfDj7OL%2BvCOmjKwyPlgHOEAaH89WyBgjea8Hf%2FhfHhVfkquETvarC74f36gw842Nwe7%2FMU6hv%2FhqgiZSX6ba%2FBJugMls%2FBZ5JU3Lu75V4bs6RZWH4ItTkbL5SPv8Ni3ff5VF%2FwQ8ZB%2B2HwWG0p7zS3r34JdDPGEizBASGL15JEtOvG4QdzNnqRILGvo3QFz5f7MhpFH3DUt5m3%2Bkbfv7lIkXNL9CW%2BYvP%2BG61Wv1s6jd3%2BveStTec0X8y7czPwz5mFTs98Bf%2Bi435tOn89fOMFOcjv8N7vXyGc1%2FBLsr6RqQfnIo1Lugmmy7TXgkPu%2BH4Lrv2mhwNr%2FrP%2BHDIIfInVu2dL%2FwTZx5e9Jj9Fl%2BiN6rlr8mpb%2BpuQgrX0DA55eSlFiAr%2F%2FBDbrhmsyoEu73t68yDBOXlxJfGcMY4kr%2F%2Bx2%2FSei6u5C%2F%2BoL%2BUPjQIOQyupYjSVjZDpdFNfwR46MTuVYUn%2BN47bY382vZV01dIsvwSaOM1Qj8O7tXp%2BXXzpZyQ1Hr0Tvwjd6IYpOLmxgTWSte80f6I9esX63%2FPX8mpryluYYNXwTU8xF73y%2F34qstKr%2FBXrVrSb1i11gg3voGTMnHmvpcuZKaCdqTz%2FW77vE%2F0du1y%2FNe%2F5Lv7l8EhufMvwT5cJnNTqvRZSevV65V6Jlfh3DrNO6Y%2FL%2BkWD7c2%2F8Obu%2BTDHJbX%2F0TKW0dx9Wr1rtau%2BdFyonv%2F%2FCfkq1esXurkm61616M5Lf5Cu9%2FrlT3wVGdJ9NmXyym98AAAAbnQZoxjGoFddIWmcZ2Jule%2FWKXm4Ni11%2F3%2BrnV6rF999qVPjfpW7777yfP%2F%2F%2FfS92vSF%2F%2F%2FXvVer1cvaXurTCJWcjnB2NIP5Pn5fxxfCI%2FwwQX45Y178%2BFoIOjLaugIpqMiocPxTLo6bb%2Fhapy6fvv9F7CW83p%2BsKlq17n%2Bdev1i6W%2FX9%2BsX6%2FP1c%2FXu%2B1conrr0F7YXhAYehnZC%2FL2N1%2BVivoPRK9GXXUW%2BAITVilfuY8R%2BORDaciz479Y0wLvTEChuqF1aGONKov%2FbY7EnwO21eP9wUyemskXLxX4KAkNpSfcJFTRxEGIPNOn%2F19uCa0N3YwT2nLq5PiwpasECCNw9V6g1LK8vh4JCK4K%2Fkugg9TWA0FCD0Wi47gpsIkxyCMWtNdj602NHb7e2vxs4g2E51xnn%2B5d8BUUKGQEoKslsSP2zjj1H1%2BciKVnsg17f%2F6uu%2B0WVClc3qz5ZOlym9eyfr36J290jkU2lNZdHZfRf65PwW6N929vUOCco87ToyJbf%2FVxf0Njw%2FiHs7vHUvy5PCORmrqmnBG4QT62EohjiF9e5ekluvXKbi5Kp61rm%2BVe5V6uwSCr31%2BCwude97FJ7v1jHqI1pS9LdovSVr6ajMd5e6yv1ipV9F%2Fk%2Brq64mtVqn%2BHqj0ewI04Lh3TWKAqDDa%2F0Lsw6WTxwx9%2BSHd7Oh2j9G1PLwSvJdi52LBeru1c%2BI6I%2BW7Wr9eqia6X36xRcKN9LX5S4ZwF7RCp%2BDDTYhmmenv1lrl%2FvwpzYxUVizsO0gooa%2FWzOev6ye1y%2BIqkV1Ukvr30uE3rXzS%2BelHQhhclt1vh3y4zQ1cIeIFXM0S6Xsv%2FglwmaBVnrImLNj09c%2FX9IObl8F8bfG%2B%2B6lgwkjGf%2FCVQXX6Az5a9dSRdXNa9WquXfRP6t0T2rfrha1zY%2F5jIfnXw10TvWNA0Kog%2F8E%2BlfaLyf8fR2zY92VlZR%2FWXf4Zntlr6aiF%2FwRZyRhuKvwnpGIlOQFPQoU%2Fnq8xceiP%2BKsEiDqmn35q%2FBDZ88k7%2BsVd9IurL%2F%2BryDu3LXr1%2Bvfqzr%2FBIVV%2B9wSZsVgIGL8EZFYEwe8Pz18bBcWme4Q%2FC8bDQ744QVQZg9O1hnHhgOsMT2TQgf%2Fh2ODqVADdwYDaDRIsvM1hqXAcLX%2FjA9movrh%2Bev0UfnV5NGYv%2FDlAUVFX7jMZ7LPGx9gk44MddV4Lo0Kn2iw8X7mH460LSNYV993cv31rk1YVgUV6YoHuvDGRujgkeN0pLJY%2BEWfDA%2F8O8dZQ04aJPIGY6qtmpV%2F9F78F%2BPgQ2wjUMbHo%2B%2Byw%2F3P8FJOe0DZIMbDOwEAQ9fw0KHc%2FEVsSMEU0h6ZPPXzo03rwS8ab%2BXLAsr8EVrSY3vh28YZZxddf76%2B5W%2F1w%2BWvV6teri5rr2RLcnitpcghRtz5ZAtiRy%2F640q2zoGTShrFCAXTv2OgjVoICpy44Vxwso%2F%2BCu6Kj3qMoB18YGSWHw0WHW7PBOMh6T5P%2F5iR5kPDPF8t9sd356%2BNt70Ww16v33%2BG84tMqX5QgEaH0wH%2FBD3GzrVVrl8q5dr18i66qm%2B5%2FVh8mlbXh2eVAYRcZEqI39OmrIZQafrx5AncKT3UDJ9hw%2Bkxrwl2DUmD0Z%2F4iU0fPqv2VLX5fPT7kIqf%2FzEen2CsTu7xldKW735CMbU4989WDVGf%2B77qte6%2B%2B%2F1w8XXU3mJSuTyXpnMdlKwMilKH8OEl%2BsfEgnAXy%2F3qiv1%2ForlWCa%2BZBKJMDZkX3X5hBWP9cvznWg0Yz3%2FPY%2Fjxckt8l4atD0b8Pw%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%2FUoO16S174hfH6sdr36sd916sd%2Fhy6WsZQ07%2BX%2FpQ1CHvCeg2OWMQkp9aWn8MWmslBxo6%2BkjJfL%2F7hmadjBNp%2FtXz0QqUv6%2BCOYlGMlDUzfhHSHn1CUYBaqzPHCN3pfBXHwN9wy2KY1KHAyiAoHfRpqwnXq9W4ZViT17HElxrnv17tWv1arVia6f%2F5xytG39ecSvgt7n%2B8ugSHd%2FP9DcVOc1y03dvNVYPKghnJg%2F78JQTQ6nzKcufhC0zPqerl6VblYzWKzetVcnMtVl%2FrqrV%2F1jKf%2FOCEjCeuvc5CXxtW78hN2j1drU1%2Frr1XXay7Wu%2Flky1q55cfV%2FwnQHMbJgan12YL%2FLuMSkVi8bdrV2uXo1V%2Friq1fFf6x8d%2FVfySesUR6v%2BiwdokvwW5MxwSVA7evxPavTw3E1%2FN0knrXCaxVasXivi19rVX38bLd%2Br1uvfk8t%2FBZ3HglZzF8M%2FYCmfhOy6zBtNpH5ujLq95hAsGx3wR3ldhD%2FcVS743uXu7V7pr83dH81uGLiYXxd8gSQ%2BVn4JqPdN96%2FG9Wzy49XscmWw9bW1j%2FqRK8RbfHNxY4OL4WobNyTbXVqZSn6L6TXi5QZjsrVjB%2BiCsiQYje0la%2BCrtNZZU3OPcpL7k%2BqWW17u%2BketolJ%2FizVru38L80kEOnnMeFYWXHHDcif8ZTJKEn2W29li6Ca%2Frxg9ImfG14SZw325hJn7fsCrIoHhovCP1rgmn9HHnhd1eCTRR5B34K7NENnNBqKcLGhyoNQfFFXgjnGDfl%2Bvdhwu2llQDINGKPvz2ja7upelFL%2BQu79QTX231r9CKtP%2FlLPD2GjngbchhgELqe78Or9KF%2FBVyjEPpNDlHkP65F%2F41KpET8OEYSIOt2LRwFFMQq0Vb%2Fk3nz2DDC2V6zdfPXf6sfgk2NXTCrBDZ2SVV4V02pTJxKZlgPDj8NN8%2F8kpbOa%2FFdtMgwd69WLurriIj0TvPrBr%2FHSMsBSoq35q%2FdhSZ%2BCQsfMVwgbmrsTsFNlx54J9090X4MLT43HfXzqKKRZeF6jY6KuSxpIbYpLjGk9G1%2F%2FWCSwR3fxj6wfnyc%2BOr%2BT%2B%2Bs9%2FvGzx7%2FWKS11VPE3%2Br9mIpUH8hT12X1dk8%2F8YQzFgxhAe98r%2BhlEB%2FQI65gQB6d6%2F44srLeimRPnc18Edmu%2F6xfnuPKQZwgI4CyvXVevdr0nL33EF9f1b8EVNeL8ExKZEmh5UGvzFWhNfIQMOjhN1m4IymPw6i%2FA6QN%2Fsr7%2FRIP1Z%2BhD%2FkoU%2FSXjjh27XGknvumvRUoL1IYfPXyC7aDIqSOa%2FXr9eq16%2FBFy4%2BuX8vd15uq%2FBCR33y%2F5O9K%2FzcQ5XhPQG9wy1EIwcKs35Stv7rwQkbYnsdnr42Jvxkfvz19AnUlH%2FBRjTcgdJYlfw%2FBhLhabsCZ18u6%2FLYdDf71Oeq2uv3x1D%2FlOMyvOWLzVfifxq9WJr3eT3%2FyGe%2F4V7vlyvmtP%2BWlfl969X%2FJ3d%2FljdX15ucILq5PBUfKu5moL0GjM9%2FwRkxzNsH%2FV%2FzSb34SmNlGD2ysfdx0ltI3V3RH99NKLK1KRlzRexZc%2Bd0uKVer%2Bn%2BCOa%2FK7BDvc4KThPflNuafz1QHHHi03%2F1w%2FZSXsq1xere6%2Fmo35Pxf%2B1rsEmQ1dz8ERHdq9E9P%2BtQ8fcdhD1hFpW9J%2FtRs0x%2FZs8ZHuu7d815f0tTbRxmb%2FDh1rFeHkhX9TFv8Vsrl9%2FoeTd9ppSZk1RevCNe%2FLzUr1Yr2IKlWYuvZ3ZIcvrhXqak8pnfVyeisrxOtGjX%2BWqf8F2VgzFeOZMyOv16%2BJ8dqE0dHeSROr1e7PXyGha9kJlo%2F18Xf4ZPc8M4vzJD3ul7vwQ3vyt66N369XnqnUQmeLfzedgsfVo%2FXc3q9evfq57366%2FV%2BliPBFSW8b9CGKgAAAWGQZoyjKoFfdCOrkJ8%2F%2F6Ev3dq5wU%2F8%2FV8%2F%2F%2FE%2Ff%2F2r9Xf%2F1%2F1L3korH%2FfavJxdeiPVz2teGa38kFHHh5%2BzLFmm%2FqLx32ifa4VQTRo77f0fC5lg8LmPX246PBYr32r2O5eXcmqLXfaJlJ63frXeIX9b16vQpfKJ8n8fYQWsdEnAdBSb%2Fk238Jz18iXPRerP1fX0e60icJNWoq0htzjsV4W38d2OiJbkvlV13XqnT2pPPlbHon%2F9G6%2FPU2zZ%2F4KBLV%2B7xfnlB8dmpdCv4c0rpV%2BQ2xLf6sfJyHdFLX69%2BrP16rxy4v17pJ6Iv1cuiK9f8qsrdW7VleQjGMxn%2BrFQS1yVzSUlXjpXerXv1i76q5a0b9dc%2F6nSr7Xq3Xu16vBhLEhFkveMMfDbbxO%2BMxvP4KOgYxk8KlCAb1veq9%2Bvd9%2Fq77VnSKWqQ5X6IXu6tdVfTdri7xS3xPOrkvr1u1BHx6qA%2B7Xu7teku7Xqm%2B1Y516rrQmhX6r12vSerF%2BL5oJWkjZ8EPd3fklxzkf4WpHU2M5O9Q3pq9AvXlmPuy%2FBhSGgaU6sfL%2FwsKPQG%2FWtk9%2Fvvn7XvVfnpS%2F%2Brmv5Sef%2Brn6wV6t%2BGLNgbkpTc3WkwYYhy%2F%2BWwOlidGrtV8F9vH6b2qo5f%2F4KqqlKGAqHkQ9Xx4x4frr8EMpc8OVeCSE3FJ0enB%2BOyOYG8krJW1DY2QHC6%2Fgh7mI38sENzkJEsLLyy0spv%2FTVyLLkl6S16%2FWv175Fykwjk9YvwpIMSscllL0aIu5py5dKlg%2FBERcyx5M%2FP1pjkR%2F8JFdvdtpn9X%2FWvwYVy0RMKUEAVORkDAnMf%2BUidpFDXltW6v8Vxl8fe3uI47hvrrqn1SLl%2BKvvLDeqHZfhgbedE5aNlrLqcP%2Fgu1lymNmGQcfRdV5yL%2BeyW7DRb2l%2BSM0PkJN6Fv8EUfduH79Yw%2Brj75cdk%2B%2F9XVusFWrSerHxCnTuu%2FlpeCETJ42pj6svrkFzNEgGhMdKagGKhIlmIEKqCMsdXojb5Hxs04ZwgH42CZsD%2FjwC0CepBEdiWCs%2FpYQMAo4GLUDY1KIWJH81P%2Firtmlzxv89R%2BKoddfHCyf2i4X6EZfrl2it3%2BrV6mb8XmC75aMCs2X%2Bv7rXoiTCNStfd8l2pQfghJzS78EpV5jIWK8xd2azdlsbt%2FojP1i%2FXru%2FOJX8Mp5YL5SWA5J%2FBfytLSTfD7Rz9L7u9SAfwXefLKNkLXfhcq9xK9eP%2Bf03hOsuEe%2FiVyvZr9iHfflKkn%2FRcr8Efd2H0VIvonfhu93UeIL0b5%2FuzkXhil%2FVmPnhfq4%2BLnX0AzKPX%2BXVUveX%2F%2BvBD3eV%2BriX313a1fh2c%2BQ9dJhNlZQghcjTwoMffWfrvRHSeQtE%2F5b2X6kq8xJAfa%2B%2BUglm%2FE0J2BH75ROvBFa3q%2FXp%2Fv0WpC%2BFf9%2BQkpjKa%2BE%2Bm7RJUB%2Fd3ovuN47rwSeWcHYm9l2nd%2FoSw%2BeoznB2UO%2BSwRkRTDEaHZX19kI6PWExL481p4WJDEo%2BU3osZGlfyaYzxImqevv0dv1fiiZfIIHBCewGrOVfOOnRJPRL11%2BGixkauvmU22%2Fguw5Ul3d%2B7%2FRMR%2BJu%2B7BPXgiKzQ27fmuwr%2FV1eCAhB4P3yfDVjeYyUxy%2BZLaW%2FcVTb3ul8F%2BpJsGcuVi1%2B%2FDlrKPLpl9jaGUlL6BKefPdjrfiRLlMRlo9aatzf2iP3MTz%2F%2FyQWea%2Fk%2Bf17MQ1NA%2FosXd%2BuHd%2ByJb%2FJQRWPYIpBBpWH1Z%2BGquI6uR9v1dXV16Ll%2BYk2erHS37%2FVyXf9SJ3XspYNa9G6rE8uX2vnr4%2BUqcX4b460XlNIiL9eQt7q16lf%2BryeQRd4pHE2K%2Fif0fpPV75EWVXXrKr7vEPon9Eyks9fi3%2FBCZm1f1QAAAA9NBmjMMygV9%2FoTq6q9a%2FWLvte7vpWPtemml6pL%2F1%2FVvf%2BrqdWPVFb9e4Mb5buNL%2F%2F6EfYbJy9f0hyWn7LSf9VtNVXCE%2Fq%2FxKuXauXl3f6vJd9r1dq9cSrljvKTpam5a5ZvV68EVBUjkq14EDXnFL5jRjScXzHex%2FkO3pfBLySj%2BKPs%2FBFSugXZPIv9a7rCGr7UqVxUhf%2F5fr174le7l1Vu1ZL5jE%2FXr1XfosVTr19L36t3P0vV0uUnr01q0vr1XdS%2FcFOKVdqUEnq9Du0tr1cytXEr36t3JaOcEno1Vj9X6r30uVUy9Tfq179e%2FWD9eq1iiPVyh3i%2FXKvPaRSMIuB%2BX17xe7l9WLterlq5fV5vPX0a1%2Bv0nu%2B2%2FWK7WVerB09evV69VE3d2vUuJ0Xuy8uZPvfwkTCVhSfYIsP6sPhy4%2F7qMg59Qx%2F%2FgjqwgjA3%2B%2FPc%2Be69%2FjsrGklvs15e77%2FWCrWX4a3Q6nmZToLHMExz%2FVj6WKS17FEvlXsVp7XtX%2Fr0nlugRf%2FBF0DHTXL9FMMfhOgJ7PLZhj8pGmTSD%2FBDsIhdeO%2Fq85cxU0P%2FgtIh33twfqxV16wfnr7AhksUqvr369V1692uVevfr36%2B9V6K9a%2FE2ZkBRvOMFH%2FFRnSuLdF3%2BawaMaVlfhLljVqA0t5PVf33f4Iuc4WDL89fTk%2F6wVctr0k69PzV65X4%2BYECjGB1NNEI6DORTr1e3cxFSvsM8%2BqwGHDEvGb%2F4i1qx6q78Egl9m1%2BcmXyoDjCyi%2Bsque69Zdz%2BsfL%2F9rl%2BLJaWQ2zZnJfKUsOwS9Xbu%2FwQn3Sg7lsgjlY%2BCIpf9fhzlowS6jw6f%2BzU40I3xRyjT8dBAeIlktetb56%2BnLbNWevy0nSv0Ryb0Xvzby%2Ff5iZH%2FuX0Hfr35I4NP34nsBE7UBpdy2uvT%2FV79F7uTwSE3SYfBF5e1%2BWNy5rm9XP1lVsSm%2F8El7A3c%2FBCbaVuz18tY4VbKbDEoQBmJ0BY6yX1Q8t%2FBHsr9N65d36tV0T%2B%2F5PERlo%2Bu3frVgjtTCAs%2B%2FBhBJ4C%2Fk7uY%2FaU27fq3z5%2BUuiGe%2BevxpB%2FomUnhwr3r5Ib%2FXtL65fhk2ejv%2B5qxr0Vv0Tv17sXIOnN595H1kO7%2FykL2%2F6%2Fr1af0epLMTHSXAe1f8l799%2Fq8no3V56pm39eak%2Bnrqx2eu2Xf%2BCUru%2Bk92T%2B%2FxVKza3S%2BsFF%2FFawR23a5kly2jsCeS96tmd3deCSm%2F36xfgk5JM5fq78NllpqTsv3a67WvifEfdYr9CK7Wq9XllR2JLk9FKlXd9rV3Pj%2FaNr4mi%2BvwjJAAAECUGaM4zqBXVoSkf1Y%2BbrxHV%2Fqx%2BtU%2BO%2Fi%2Fjf%2Fjq9ZV6uKfu6tcv17tFdUunBDWLzC%2B%2BQ5WNXr0nycRXolVyrURVfhuzdbHGx6rEL3furd2O7klr08K3atXq0l9nxflolr1eifX%2BbWr9YJLxy06Y7Sb4QVlVV69LOtUM8o31r9al6WvH1cr1qhS%2FrUr66ta%2FWu%2B5r7Vjtal8%2BXx01Uy%2FUhMly0ywu5%2FWLtYquS69arta%2BZarwRVlEKByrm%2FWumu1dUqtWL2O36I9XK9WO1iqVarLvy%2BHE8r8EdyxYHsfnqybkr5rq1rtZXutd4r7VjuuZcpPWUwpe1cfBHtNUj%2BK0lYMZ3V9hOQ5nuz%2Bbnkvy0kAWoTtWiS%2F2%2BLyn0DaiPh25gQfSpn8F1773Z%2BCTc6j79evyd2av9Yu69e5e113Uqt3NusUvNyovfqQavBeTklqqpYfit%2F%2BKlvGBUUTVFQmMJZf8M2GMXPXxm3pyeIlcYQHy5T9QUUl56ddq4OriF7uT1rqq16R9asSeLt2EcxLQ%2BMEBgvj%2B7GqdBPs%2FopE%2FG9k6Q%2BAMuEEx%2BgpBbHCwro5bggEYhND%2F44jSV%2BIKwM1DPvZMaI2T%2FiLRjTBWIdXq%2FBNvSvZOforn6Jh3VnqG8wqF%2Fk9%2F17u1cFvnWUnq36kaXNvxU4QFFeywKM6HDAUibXwR1oBH0cVLh%2BCewZhDDGptNN7fnr9KOIevPX7lUfyxkdiyMigb8EXLTBk9yfyXf3d16sRfEyXV15CVAzsBsJL0V3aM5XjvNC0TMcMf%2Bi%2B77rwrNiB6T2atHKSrf853%2FmWGgbfoj9qw%2BfF0Bip%2BvV%2Fz5fwh9j4q1ik3Xy%2FVv1irwR25kRaRVdWc6%2FWaG5PKK5eX0dz9WIqVW%2FWu112tfgi3a6r1i%2FJd9eQk95fJpzL%2FZXx1b7v8pGWq829n9amsOHz%2BvvGCv%2FRKr17wh%2FWUvrWT8if68mlaXnv%2FPqX0TCr%2FCxXQQbhBkBvpUzqGl4oCZX%2F4qkQYsJxKwMgwYvqlDb58%2FBR2N2d2AsOz1OdRGh%2BXwSFpTR7s5F8qXPhPfOoT2upLNmv2YuGmqa9G7vhdHdeJr0R4bIyJdJfkMSzYpLcnor9nrqXf%2BC3nox3txXYIY2nV%2FCWwQ3flXhPu7T%2FwSEs7v2r%2Fq8votV64SF%2F1%2FwxojF1j6ZXWYyphk7SGv%2FgkvkZMjJ%2Bex9AyBhj1n55xfMtcoIMFeiOfgi8OoJRi7ORfG2cfWsnrKvRWVfaxV6vforJrWv1guUF9KLvdfaPv9E7sndJe9OQ0%2FBIV3QVh99z59a770%2BrX6Iy%2FPXyam1%2BCG1MPscFeLmJaXPNcTVXqitXrFinr0SqurkuX0XU3rKtH8Ry%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": "command=APPEND&media_data=r7kP0%2Fq4XhfH6d36xuv%2F9WH17%2BrV6u%2FW%2FcT4nHRwrArx0ACfBDHJyNSLj9%2BF9ErAbDHgUrEql1JhoPye9u%2FzEe9eiu%2FNlxrXlvmxeuHfdfXrV03qtS%2BrXUrVusX4TIqwQth0cuf%2BCQsmZRV4s174Ze35yqNtHp%2Ba%2B5PXX1G%2BrvwQ6Tv1%2BTCXh0b67xu0BBldZbKMDJvEC4Po5xuVgLtAUPuj0T378VNlengpiYqzx993d2evom4%2BOJ%2BQtKQfV99yerSaSJ1X33V934jIEAUe0wMOSGatdfmjQIvQM8lZs3qrOVVysf9WHyEH4xw93f6xS44QU7DzR6yeiYdq92tS6%2Fojh%2BCSjLRYTn4opA3QbkpsgxyfJhxmhAbRr4a8tGJjFopz9eTMw3T%2BXnox%2FXD8%2FUkJBgnQ%2BvR2fhvNLjEPeeMHnglX5jSQ%2Fgkw8kpfb9WO11XgijgXoAqeXDhBO6PeT09%2FwgILuP56fr4jV1aOztW%2FNSSyk%2B%2FXOKWMjPet68ERbET7H6wTeettAxhE%2F6JF2cSvj%2BKH%2FghlEG179fheid%2BsH61IrzlY7ll9nQIrtXLVGEVeOxn3TXXkImMgo%2F7Joo5mvR4q8%2FX%2BMIn1d%2B%2B7%2FVquvBCZ3QL1WI88MtL82fN2i6qzUmd%2Fmvs%2FhysxignRXRfQrq%2F0XUtrLua0ar9e%2FRXBL0f%2Buv1ruLurWpPV%2B5r%2FWr9Fw8X9Ce0Z74m%2FXt4OhlIqdEgAAARnQZo0jSoFfdehKdLjfr%2FpP1p15f1r%2FtYv1i6EFr%2BTie%2Bivta9Vc7%2FWLta9ZOJUiKv%2FGeyq%2F61V%2FrXyXX9LVcR%2BrHSK%2FxG%2F%2FnVpN9HEG5nLsEmHE%2BvxiT3v%2BoV7Wqom7ViqKVOtq8lS13190KV45bFX3%2BrSeuXf4nox44px%2FXL7q%2BCO0f8snn%2BvYa5WK%2BmyVnq%2FV%2F1qhz%2Bqfv761T945Xirm65hCy3EevdghkBb8HXfqx8T2rFXd%2FOr36v6qfcRK9cTd93cz8kEYinJVl%2Bcqm1P%2Fd3cISLUlfRsl%2FrVetSbq3dy3LfrVClq%2Blqm8Z66pFhyWrV6%2F%2FVOi3Xr03rqTwVaVxhO2Myw6WW7te7U91ycQpblWOV6uXSyUTd44n2T6%2BqDl9muVr%2F89fSJ7%2FV%2Fy2mBvXgh3t4WX%2F%2Ftfe31TZP1xerftXkFd%2BrV64UT9%2Fr6LGvfVhqkqPl906%2FDlSx1NZVv%2FqS%2FJJT%2FPUcBQr0Xk8mUHD4QFV8tDnowe5fWrxv5P19XrV3V30uGT1qvLsaAzs%2FNQUvYXwXdhBhBJMaPPf8M1NrcNfL0f9Wfq5%2BpwfnvbONP%2F8GHhpJuGDh9f4%2Fj69%2B7v7%2FPUMRFKtP%2FkvnEB883N4%2F5NcbLuvSWbjbyoCk%2Fl%2FBh0lpTMLaLOv%2FkKjJVB%2FwX4WRr7sBME0vmqGkn2H8EhECSDTgpBA8vz6lUMyJf1cnrl%2BCSjfYFtcP1iq1qSm%2Bde9VqJ8L6EneUVt1YyyQG5B%2FwQTyeEpTEqAuMDBhoPRPFrLSB4wRW0oD%2FlnNP14Ii74ffmJh2Jh8v9%2BsVeGsgzfD8d1vp9d9b566Zb%2FavXr1e955fWqurWru%2FWU0v5Na9XXf4IiY8bIG34JSjKOA9mgCm1Tpqv%2FIRtOa0Jd2GSTS4vx%2F7BfwXby22vX4I6SXX66u1qrWrmeXSu1qTzbu6f2CS81HerLwTPgDT%2Bvd9rhL4ZnmTL44wJp6j%2BvL3fZyKZ6%2F%2FOdXMfZflvvtE6W79ZWX%2Ffrz18cHwXDnfn14Zt59esuwQlz%2FX6u%2FDW6dfum68xJYHY%2Fl3d9lx8EEd5B%2Brn4nptZc7dAbQ0Cl%2FJsyDsP5bN9er1GrXUtTWi9EeGiFRaJfpyavPX%2BTB1ofrBRf1rWDt2M6S6vsEh7Vux%2BiN%2B%2FHRhfBfTRp0tqtx4GOL%2FqTH5eW8v16iLidG%2BWne%2F71ijeMFIsXGFFu%2BtVbdy99%2Fq%2F2pEr3vd%2BQQMA6cH2tfouXZ6%2BVFadeGSq%2Bo0RWjDVs45MfwR93y%2FRMv1g%2FDkuJPXNzreifi%2F%2FrXKQruv5TFy%2Fff4i2gSRREay%2F8130%2FzVkxr0jwVmrXGmI76v9bpPRem8pjY17OVTqKJP3auN5Pzf79Eyvz18pku68JaV0kvuXLTfm7T7%2Ffaa9AkK%2BfM9erSXL66r1lNf56%2ByCVg3lj2cingzt%2FdyX2hJyqXve%2BOEIr73P%2FnWt1v2ryeisd169LXPd%2BilL9cu5PRILolXryXb5f9f1OZSan%2FAAAAM8QZo1DUoFcnE%2FMhblXXKvd%2F%2F9Ktf86xd%2F%2F1aueH6sd8DD3%2F%2F1LXGftL32rjfE%2FXt%2F9%2FrXquu6uvXv7pFrqq8v%2FoR6EX6%2BC9WCteq65rvqVu%2Bv6Xq9XOupiP1b9fHa9k9f%2F6XuqvX2O5nHyL28hV7BHvaf9dM%2Fgh7IOQp7jYrjjziUyV0D%2FBLkDGPDE34lr8F%2BpxntMEe19thmRNVyfv%2F1da932s91K3devfa%2B%2FXKry%2F%2F3y%2Fq5J6tW6t31LF1SePJtNJuxWOdR%2Bisd%2FriEn7%2F3rWnJWvsJd%2Fr4S%2Fftrd%2Fql616TQntYq0aT1l7r3axTWvXvy1VVIpUx3TrurjoXLVVrBfq6%2Bl1XS9L4Le0apl%2FuNnr8uj6Tmm1b4jv4iIv9ekFd308nrh3N69Jl3ybf51Knct%2FrFE9VpS%2Brvy0TMkaB%2FWq9au1fgn%2Ba918%2FWX61GWpEk9Yq89RuAcL5HrirCuZEhNCAt68EFA2BsDD8JthW2tjbXVsbIX%2F4%2FvvzLkNV0E9HuO%2Bqsq%2FWftW5VeX11J67%2Fku7BIyWWck%2FtX%2FCUtfjjHfokqv9ZXxM9%2FrlJ6xaz%2BNvXxVX3dvntk4IZrr1ykxb1l%2Fnz%2BjkSrORSi50pT1A%2FXrB%2BphdyLXqz1Hrm6H0%2F69Ypr31V%2FPff6Iya%2BwWib0p86vyEZ3YC%2Bbjhn%2FVh9ZVzLUWX98yRYuFJEqy%2F9655Xbq9ez3fv9Ggu%2Fy%2Bd%2B%2Fz1e035PVu6x3tfyUWtfq9L6%2FJqq%2FFzZ9TYvVx89U46Zx%2BvNYRf%2FJU2f1lN6%2FG5PCukwZZmGNg0Ni2Vobmf69Wfl7TXza3V3f6wRHuSDX3k9YP1zBee59kTWf8mef9XUnxG9FL%2FbsZktE%2FRXK8hmtJeC8uW%2FLRzpF33BU%2FfBMSUz78Jn7u%2B0eKtfdF12uFbkz5rwSCj32Hy8md9opwz9YLu%2FddSei9%2BjMZf9%2Fv9ektFcq%2F3LndrUT6NhXo5KvWX6nb9WV5yL86Vlau%2FeWlnuvNff66n9HfxWXif11e6wdq3lxHnrDqT3%2FJ6vfrVvfIIu9evfrFeqEuqXqqF1f4pav1buvVv174RVy%2FJYNnf70nuT18Iq9YQ1fjtU6v036JBcAAADLEGaNY1qBXP6F12vfrV%2Bvfr3a5dr0tVS%2FrKrVv1bvon%2Fl%2FXLtXGhj9crue16L9arcE3UorYGG0GK4K9Xkpvrqx3L%2F1f42ohauT1Z6q5k9%2F%2F9Y5Jav3z7rwSbbfXYJ42VP2E1dgTz5UCTH4%2F%2F6tXq%2F6p0%2FWKr78VV%2FjZLXu5LXpJ6ur7k8pD417RddrFk%2Ff%2F9e%2FVpLrJXqv9XBLu1q%2FX3L%2BvVa1XrbtWd9zetX69y3F3c%2BEcl%2B6vV1atfEy%2BtVy3fyrUvGyWprv9YL9eltWu1lJ6JK7l%2BI9cojiMV3auD%2Btfq93%2Bur%2F5O1qhX4gdHWYuUZd%2BevssfX6JVeivfnr8MJxdC%2BiPdrlfxPr0lyeikFXucxRIGw3Z%2BUPtx3%2F9XJH799%2FuwR%2Bj9rlJrVMtSS9JXNy161J64SesVXXvptr1ZZf%2BsfRHNZzQ2%2BmCqyGmfw93VLLMdJVsNgwYeRT1g4D9eWxt3dydrlXrUV5SSf%2BsEVfYIy7J9fgk7vX4zu%2B44X7ZcpdSX4ntoMwHxpoyZhVZsvq81E%2FqUpPduYL36N0t%2FoT1%2BYjAR5UC%2BCH2ZUE9wr%2Bvb%2FXrte%2FXrx2peLk9ffrlfokqtFqbyEllGQcVaPLsnL68EUpB20p%2BQgbQln%2BJq%2FvVy32ixeq9J6sNn1%2BsvJ4c3uv2o1ovRu%2FR4PwSb3wr1q77Mbd9gk4%2B1%2B%2FdGwaSq%2FxBSI5EbN4buk0H8J1klGyXT%2FPKVk7B91c%2FrVZZdbnv85FjF1hUH69XG1wvzXsq9Hw%2FC0qWh02VkW%2ByP7L4IjSNon%2FLGwQL9dYLLbHavLM4tr5VDyvwS8YBUz4Ug%2Bvdf8WYkpC%2Fyr2ta6E4cZC%2BNXfd3aveevS%2BYQwmUl2v17Kx4zO7q7tcPz%2Bb9hD5Fu9%2ByfX%2BYstP5jJY%2FK%2BSkYj1vkK1S7uzE5qyf2vxGqPU3giJMxy7v1Kl3XrlXgj5INZV5LSN0u%2BX%2F3y%2F%2B4jSkFT%2Ftffit%2BsucRfSn%2F8EXPDX5bo%2F5tWRL3PL2i9VxXrGG%2Fy291a92vUvnXu6J7%2FucQv2ib7q7d9Xd9zUI5Pb%2Fv0LOknqVKuye%2F%2FJd%2BhR0%2FCWWC93eAAAC2kGaNg2KBXJ6F9%2BvTevVeT6%2F79elJ%2B%2F6sd3d%2BtrtWO%2B5NV6PL%2F%2F%2Buu1cbVn4KNkSjCDJvhVrX69%2Btdq%2F6sWKW76Ea9Yq5a9XXf61Wl86tfko41D%2F1i7WX5LVBNfNy0%2FXuwTcfFdqwBvR3DnWv1arv113%2BtV6xdN3%2BrfLE6rF2vT%2B8v711zv1cfU14Q%2BhMlr1T0O5BzqVj%2BrrVarVaq179Yrpde9Wr9ExGFP61eq9P%2Ff6xfqwfrhGeuX4JtpLGHHpT8Xs5mGDYTPrG69YqxWrq69cu1tN6mBXKrnd7N%2Bp0%2FV%2BVXr11JaJKbkufuTpWIq57kvuS5rr11J698sVct169V%2FkrZtbdA7TR7Vi%2FXVc03rUR6LXaufhvnf1ZFLlJUkE7I9kvsRnpqiRVYc27S%2BkNpPP6vWI%2FolSei1Vqx%2BhT%2Fol6J7f8T4geZa3YO0cnta%2FXLv89h5h4zK8v%2BuTmr%2BiMRPq6vXq9Fb9Yp7iPdgpdYPaI%2F612UuO6WvBf5pR2f1nRGCLfQaMKrMZa5X6vXERHgkNx0dGKvBJd9Kie6Zc%2FsS7%2FzEzQ%2FBHGhkhZRAwfnrKrlp8zvrEfFVromTE5rWL9Wr1yr1l3XmkXsmB%2FfdSWanvuvKQoYZcZn%2BW%2B5L7R0ofPUZ%2FwGz9%2BuXf5DaSu0fu%2Fz10GHpdj37Nul8uhlpr1dZf98KlYV0RUT9OAyZ0%2F5Pq1yiPPc%2FHl5b%2FVrv9dV56nRum%2F69Ecb%2FMJsMZ9vymLn3bX5GJcl1jaOx%2BrRNllDFlT%2BfrjebxP91aJFSXyQy6X0X3%2Fr0XOPgoNGhj8K%2FKvZTi78n1%2BDTSt%2F0TvyHvY2X66sxJaZZa1RalXvXmn9psniN58IaTzCH4JO7HLuZe933k9P%2B%2FRIqusTiF%2FN69%2BuX66%2FP6OIP%2FuW5HfXr3YLeTXu1i%2FKRkXPf6Evct8iv3Pa1%2BuIy%2F%2Fyer1ia93NxPhJr2X%2F9e%2FRMP2RRrTqAAAAOqQZo2jaoFf6F5V0rd9%2Fr8m2I9f%2B%2BXv77u64j6%2B%2F%2B%2BX%2FtWP%2FpdVapE%2B1JfrlN65Ter72mfL%2F8fo5%2F1YbWvz4MclvP7xRJcXE6fuDGbVel9X%2FUyiT1c%2FVyT1frBHtttJwzurV%2FnsPuk38N2kdEtBRxElLQ7tXw3GT36BLHt%2F%2F6sHfeO3TfG99%2FCa%2BOjVYoV9zaq9%2BrEl16uD2pkf8Lx5%2BejpvX59Kce03Ey%2BrHa3755aIu1c9FWv1cr1qrV1er%2BzyPJ5qauO%2FXLy%2B7tX4v9XD9aiPV79T01r1%2Br1fXXrhy9Ver16t%2BuWK6pZLu%2FDDiR3Yltavnv1zEnq5fq9etV6uV6IwP4qWiP5d2JloW%2FSV%2Bi3ubVvauDP9ZV69Ger1detdojDbKSf2ub8QTLfTMsvNZJUvms4fftP1J45Ta6l1WomiInzWkv61T%2B%2Fr90df1i%2FXW7ey%2BriffrX69XdZM1%2FiD8Vu%2BX0TuyXtTesrtXVYJ8N6WhpHpsPnqwYzPQTaf8urv8R3PQ9P9L3usF%2Bvf1ydq9esVbq%2FBH%2BvS%2BCOpyDnL90ByMT%2Ba53asEnd37Lywd%2BsE1qdJrrnm9cprRGPz18Y768EhXY6E43%2BjV%2BhabJ%2FfqCIhTF%2FL9Y78IaCltejZl%2FL%2Fvi92EMDokFU7DbTLwR8OrrPVbrFX3lzejxfmM%2B7tav1arVojz2lStP9eTxsYXxhLUm7%2Fx%2BamELT0fwyeNZ9fLbf8EJM%2BcUl88vorfr01iKb5uuS2THTv%2BTatvzlced5RBYr%2B%2Ben66%2FIQ1LI4N%2B64vx9ZryXPKzZiq%2BCjSaPY7CP1%2BIjs42i5opuiNj5fJXkTab%2FHVIQcaIVWjvR7JWzSV1icR6L0no2FbrBdyX%2BiuV69J4I%2BYebb8FfIFjEEYAGvE%2FPm9eCPYY41%2Bp%2B4LY%2Bf%2Fyompd0ufy%2F9HX0Cgr2Rj%2BYhd30uF%2BuVX9rPF%2BepKOw%2F%2FPU2uj%2Fv8pHfXiySfyZ%2BUTZ3yh2EmZ%2F3vvLFfbtmS51cfFGxsL5A%2B%2F1i9r8lmv85Vpyf%2FiCMNZMD3vYXxOjMX7367nU3UhB%2Bju%2FJpP7rV9K1evXdYRr1eia%2FRO%2FXUnorBeuvydE68E%2FmyYhS%2BrcEUudwvBIQxEc9%2B3v8%2FfZb58dovd5P6vU2NZWYT0Xv1ikxO%2FUvpb9P3y%2F7%2BX%2Ff7Rulfgi16Et%2Bia%2FRa14MJDHx%2FbI%2FfrW%2BT7wpV%2Ffu8I%2FiahP1r0WD9FeW1Yq%2FyUh0h8nrl%2BrTwhq27%2Bd0krr8AAAXLQZo3DcoFfdURiP9CWMRntetSWtd1axSXJNVa9J61%2Brn6xd9y%2Bsu%2F1YL16sF1Yuip%2FXtn369%2BbDiLc5%2BXSu79eu7uvVyTia4ntWdrX61%2BrquVa6y3OoIo4vdx8R2Ms7CPf9%2BPi7v1%2FDmMNPX4xALjGX9Vf9573f69Jfcvr36vfqkTufyW6Uj6UF8zHvTg%2BRRJta%2FuH5mgvesXr4aV%2FpWk2pPXHXq0tEqVL9au6v9euYlerxIqnTl95f10LIdu37ybEovSfVVUSvXd%2BtVdcterSevfrF4T%2FrL9YvwnfNSwaSr1asv9c0nS9falB5f6t%2Brd3a%2BO1OCI6VrtZbFe%2FBNnjbLJ8253N2oQx1Bopw0NvPDE2c36uVk3XVf0rFzEq1erlWuUnN3%2Bsu79b%2Fq5%2BCikXxy7rbjgwGvwjNRryDBaVLl%2FDH3Mxcyv6kb8EOUgtkqghPUE3CL7lOWIhYIT5XAsrKIvtZdq9cT%2BtTer3eX%2FX9TcCXND34aNMh3xccHytj%2FW6fLH4cnh1qadF%2FwVWPYbrThx2OZgfu9V5PnXxFJEWFA8ayb%2B5NGqP4jDaobxxM%2FwxbaghzMKGO%2FdculK%2F8djkOgtS%2Bn1bJ90FNncIWdPuSG%2BiA4j2%2B3vJd1jt%2BrOGVTMq%2FiPRa5Vr3CRKjUYslRowy5f%2FsF0hjpwNZszS8l5fjycdpxXxUrcgBP8f7L2c%2F4z8ne2sa8blCD0imaREof0dP2tj82EeKdxl2j4shH0Pcf4zSKPsb%2FBHLykEv67WvyFSD2af8Ro%2BOPrpjJf39AuIe9pJA5WL6u5pVqW0XqXqtSTgvvd8ppWGdIOPj8n8%2FeC0lZMUXrFXgqKgp%2FwSvj%2FAg%2FxssKmOr8IYAhwwy5xi%2BW9hGOS%2F%2FYKrCB%2BaYXI%2B2W%2BxvjCv3aZtZWrv8Vhnd%2BIPfJjQ9ryr5QRRmnD%2BIbDMk7OvkVjINH%2FZAo4mL8RjBM%2FBI8nk2xIvXd1D39LWQlSM%2BeS%2F1qvWKe5fGRgEBWoI1Nx44R%2Fq7mrCZxy3AP4yYAAOEDDkKM4gPRr2tjXGFxt1AKn82F0xIrNes%2B%2Bb%2FkPCPg650X6%2FCZC9vzNrwjjNPtN8zHxPqq5ye%2F6gju3OwS372%2FRVMDf4b3tJ%2Fh%2FvOwEZcQ5vWURZN339jyMlm8pNEKDnlPBfOf4SqhAf73r71%2BCuErhE2%2FGAQn7J4OwSZ52suxPjeAqmP%2FWvyX3fgnvG0GrQZRaDZ2hNfgjJqcy52Cq%2BbHQTw3hta2LmL8kaGxxfgotXD9ONWOipLh13%2BswVz%2BsonwRYT0TstZf8pFwl241BkqmSN6rh5Jb%2BwRGfb12U4dpevBV%2FgkkPoDHRTd6WuNu78JPkelJ%2Btr2s7gyk1MNM8wHKA3SChVcuxL52NfQRPbhfOcZwHEmz%2FrwTnKqs7BktFy%2FNDK4P%2FEGulBf7CFLhf67MfP%2FwmRquhm%2BJm1rue68EuiS6PXiZoaLocfll%2F7%2FstBx4aHsFe88JYZYQyiHOqL712K1twdmKP4goZUj8dLH%2FBDz%2Fmda1vuwTkD6p6PO%2FhrugnN0logHwRsmdW%2FisbLCX6HKay%2F147Sx2l6MOLr9x%2B7X0Sh515fruhnYYFNYkEP04MZp7WNBuZj7q83zJK%2FyVhpSfvJ7%2FXNSzF%2FJ%2BvNd9Wr1UCjYcao5AdBeH0EuT7Bl%2BTwUVqyLT3usdhZTDGtERGn22qOrwT8VwY6D734IrS7%2FiKJ3jxtZPsfyU2umv7%2FHbnSZ495WO%2B8n7%2BqvSXXTvL6PXevkWKVN4oQPgqfg%2BhZfBRunez1%2Bi5Xd%2BsEvorCX6%2FIaqNBJ%2Bt3pr0%2Fk9f9Hc7y%2F%2FRiKIOZL7k1RdXZhDW0%2FIWhr%2B90PuvBJu%2BD8VXWldeCvdjj9PKcJQcMfX4gk%2BrlGTEH3d991deUtG9e97r0XCr7V74ma7ur7%2FEdNpw4uN969Wpr9a43n79e%2ByiGQxltLXklR2iLk9FquRXJfVirWognt%2F%2FrKSAAABGhBmjeN6gVxEt%2BhNfqdK9YO%2B1il9XJN1q%2BL6RW77VOvorn6pg%2Brv7urq74mtUTr5P1auJBIXh5%2B78EZNb7YE9Y36%2Bv1c%2B1c%2Bl67Voi%2F1er7XsVyDldq9dvwznNLr7kh%2FNq72rifj8a1fL%2F9CvPSWjP%2Bpk5XzT%2FBFJH9L9Wvdq36L36%2Br179TNHeiMC%2BuFerfq67r5vWD9Zu4i%2F1YjrXr6WvkkFLKK57%2FWXa1c1191667%2FCV7Pe38I0Hk9KmefHfrX6xVusa%2FV%2F1aIlWKT16XlV%2BqYn3%2Bv6sC2uHxHl%2FFVRisd36v2sXRNcT%2BpFlSq1WsUsRqznL5uvdo07NeetUz5%2Fxc6pkw9tAg1LQfVwT1YExH9Yrn7r1bq9bL%2F%2BrVf698tam3S9z8tgNMeN%2Fovr%2BvfhOqJvY0I7O%2FyRsY%2FrxEhEk0uHVJnwhaRsr8bY0bxAYCXiuN1Ks6ezNT4j46CfZTvhWQV16t38q9Jc18vuXOEGT%2FBbz%2FGRo4B1l%2F7xBOSp4MqZg18T5GCsevR3K8GBMOxKFOdOhqmgQ%2Bn1%2Ft8hdGr%2FRcP11%2BQlDjdD%2BrVt869JX814IdeL5ugssf1g7EFrXNv5KCKNIdGvcuHBAFhVfBVDf23aTZ8uSPHv1gr0SLL%2FriO01QccMP3z20a7urk7RXJvEkGgQXgDbKHdBJy%2Fr77kOfJGmX%2FgiPGgcvl2YmFk4ZPWD9cq8X5ILp15cve%2Fku%2FSvEVL84eu%2F1dN6sF5yL8rb%2Fd52UvlKXJAzXmJTSf62O%2F1i%2FIWVTY%2Fqz9mHfdB14aOHUJP8W5iC5L%2FwUQrJEXqj9%2BCW7Ng2RoYfvwSaGHt5XiGID9Yoq5PRek9Eir0R1eKhpyew4RcFY%2F0Vqv8XsazeNCAsEDsEcOKZ7eHRxxC%2BeF8v98QCKftn%2BmPyFtDxh0duq%2F4JDkydJ1%2BGKBDoeBYPaGB0l%2FTGIb5TGZKivl%2F%2Bpti5fRan8lV34T2c%2FyxVl%2FS%2F8nhnvC8EOdkgT9fq%2F4Tsb3GzHRX4knO%2BOmAyxL%2FiuhGYTlP8JeZQOpjovwReaTNeoi0n26%2FhsrtWTPoBrFX8pSCN236J%2BuL8RXv1cn85Fan3%2F1Yk9zMm%2BXw2WTpJIg6%2FYQ3c5PPX1M34LurrTi3tdeuv83D19LvXr%2BMjoAI6Bop10eOmxeCI%2BIpvfvaX8TnYDArLYg0PfvVoj9goK88vPrE8J5P7%2F%2FRcpfMIjoura%2FE%2Bf6Zzf8ExRwaPpven%2FE3Z%2FN1f61L5C5jdP4IYI33Ph4%2FZOUxf4SM3HpwgvRuh7Tetd0i071d%2BEtqukl8x5%2B3ewnfc2%2B%2FqvXv1f1V01rVeCIkQseFe9DTff5scEfry6dNeuH4I%2BklB%2BKzwl9jcdpL9r4S8dMj%2FUuUhI4y7L7%2BqxVfYI%2FLmFeCMr0mB1%2BSk%2FfpGs717pjdE3%2F6t2ivfSteJzWS75LRoq8Efmoz8hb83eT0%2F6gh18Si1J6EOd14J%2B78ZVqd9%2BhLTPEdW9iVyq%2F1KD9EeEvZjX1ABJBSQRBQJBULBQThkLhQMBYSBYKhYKhQaiQahQrhErk1nv9eMpx4TSZdJLyqvKhrRNDi%2Bov%2F4v1etvV%2FWtMv7%2FfWekr4WRL4g38rzr6fL1%2F3NKg7%2FaJTOno5fYa4T66IIL%2BntHJAcwRF%2BljorngTxp81ZdRcc%2FVNS7pWYupGkNnjMTDC6vNj8lwHZVF8k3LGPXFfr9BKxSrEfENOe0j2dOiH1Jl5OP7fTEIRoGbUY7%2B5gPD18Pz7QdFfs6WnIsEl%2B%2FmAwThGUE%2BNk4SvdSkCqnJD8VwcBLFSRMCYyDUKGYKBULFQRhEar3bvqu1t3lynW0q93zdVVS3Umhu3B8i5n6HifRdAeOnqf9AC8BeiRG2SZ9Mi7ClXySxMNVfP9NQ%2BBcw8jR34rvwWOw5K9%2Fbgn7l8LzZkFfhQD1EN2t4z6WmzEzcFvMRQqcQKAnhTpACukT3hO6Dukf1Mlms%2B2H0cN72Di900ADVezySUBdN5%2BrIaKnTspLfdeirRVFk4TVC1zrvisZ8psIRpN52TmslJ7E6b4iGmvaYP%2FkKIe2%2Ff%2FE3V3%2BzsfMNQMfz%2FtyMHDTPPVZZO8hWVOVgcBKJn%2BDRgs0LGEpEty9W55a%2BAZMPXFNV8C6tfqqsDRk5arfV5Jj1CFqaSQZTCh6%2BGvr%2BlC%2FxnPyppRfF31Omuqf79VWiw%2F8W7qqKWlpd5ofgOx%2BJO8o30ndVUQicgSGhgBrJSaGmq3yO%2F13oPXPl5E1%2BQrl128UJSzhnAB1UUlFWA%3D&media_id=1254206535166763008&segment_index=34" + }, + "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%2Bm3qYzFYGfG5XCUyzepEssGg78iZ58QJ04JcDomEYnS0wEx9XiTdmaynBYtW5bMbjal71%2FwPkfqdE1FVTJlKk1jdMGOu%2FAfFf0%2FsKLwhFwy07JpWiXdsfoePwvAC1kEIg0vUgrUTAwE4MMSbkFDnKwA5nzuylwCmeEqemCaqKvU9MVauNVB9XJJXIPtx1aqburtpxrvL8WhglCI2qLeH%2FaLSCAABE2AsABN2D1ff0A4AAABWVBmjgOCgV2vjf2LVfyr3%2F%2Ff%2F693%2F%2F0Svc1%2F%2F7%2FEL3zrXfV6%2Fr36x%2B175e17%2F%2Fv%2Ftfna%2B%2FXyX%2FlkketJWP1lbMgrvJ6%2FyeISuMN5PPzCPeYyMbDiLP6uvUWVXfJ3RPn%2FVj9SJ%2Btfrl6EVV6rzX0tV6y91Yq%2BiPS%2FBFKTZnNcHuGob63rTXxwkRf4%2Fy82Plxg1JMv%2FF%2BQkQia%2F%2BS7%2FcF15ReUalEUcqtW%2FWx8tXjuVO%2B1Y6RX%2BTpMVvouJ%2BbWTykvOx83J%2B9uoIZTLbV9N6OmFWid8i9PE%2Fr0nq98t883rL9cpfXvJq175Fd3dNVycb3fr1l%2F%2FUt8T7MvfS9d8%2Fa5fE0v%2FwnnBAF%2B6oGvWC765BXxHJavfEq%2Fd8s189SX0rElidhx1MVqY74mru6u5te%2FXu%2F179Yqu%2FWu%2F1PSertyIkCS%2B5W2uoLNBxs2XmZvIJFN9%2B6BHEDPXqC6OG3w4npqj6vE4yk4I%2BdS1Lrgbi5N1y6qv3WpeWrq5i%2BifYKJ4ZxAT5oY1Gph%2BCKfN9fip4SbVJtGMPU6C%2BCaufIYpuVby6m0l9cK8MWmbNIZIXA6%2BlHUVhn4vSLJ96tK5LWu1dVJVy0TP5c3Wj%2BKo6JQa4gPA%2FwmQv5QmEr%2Fn%2Bu8TCcXTvgwRtODqDT%2BX71wTHFZ%2B90yxWGI5s7%2FFXQCmM2oSjFB8WQn%2Fl8bx80nk%2F5bHHUGr7dZ%2Fis%2F7c7K5Pkkkurn%2BTqr0WL9am8FHQDJo0yYY0BffgsJJxwkGWBeik%2FotYxT3KQsZjf8R6IwgI2CmtHZuSS%2Fr5iNtPXq35S7v8fbt4kbkskeTY%2FXY2r%2FPU6Mn%2Fyio%2BID%2BX69E6l6rqu0WLxWb1y%2Bld1K0nr2T0%2F5fGkHjgkdEpmwSy97P%2BaPHlUEB4dksQ6SvHSY1dWd%2FYdrGRI6vMxa6zcID1CfzOKB5Wfo3DmE3J0TXkwq8bGx%2Fw3o9ZIKnWDQ%2Fr7R4q8EJJdpxVZKuS09rF%2BXl%2B9evc1pZfmpa9W7kz179SpXq4%2Bci0CLcw1%2FxdnvHc%2BvEx82bggF54URG%2BTu78JzD5yCln8S%2F8wnTf4IjMCk9vycqj8uxvV3ySevT3L4IsPxCdsv3dJHr7Y0ho3HviaGwGqGURsqL%2BQhWMfEBv1KdgON97Pb8%2ByrIn79Zackv1lfok6vMc8TAAD%2FBLd%2FCPlMvDJ71%2BUQdiZn8wmEWngfYVINyU%2BbLd3x%2F7V9kviLl9HSH4JMYldr8QIhE2x4ywGBk2vs0LuRbWXOvkR8PwuSb8aTc9jVz%2FJ7%2BuC0rIZHLuMldh83m%2FxNa1X%2FCRDoTIKAzBm2PgiPufQ5EF%2F8I6QdRch6UfZO%2FUnr%2FwjbZTggKGxzmKoVI2BH4%2BGF1MBaByhNNgYEgfpl7FHwpoDq0jYw%2Bpjr53lY65mK1dSfVyQrF%2BSOwjw7CXfCEggJgs2FJJFfjBs%2BSQm9svuQrl%2B1X%2Fd3%2B5L3debyw%2BI7bQ1r%2BEaGag2g93f69f7EvfauUje%2FyEkUNf348CBrUL4RmSxbs909NeJLttsbZ2a%2FlIVi9U3Iwujf4%2FKp%2Fsx8%2BaL5PXV%2BsHCcnixHLlaXxFN7DtZf%2BCsoYUzx2EbQ3OcT2DSE1rjK8EhMogJdy%2FBGJnzy%2FUpuycpp34IiZCSUvxF27Ct0n4rrrF0kviCk%2Fvv9XNWkCPy6%2BX9Kvvd%2B35%2FXv0SX5iOfNF%2Fv%2FzFMw%2FtWfuSH%2BCO9%2BH5b3R0%2F%2BK05mZff5pYmEEcMtXfhru6%2B2trYLeXOQ0zysv%2B%2Bvfmu%2Bu1jWT1%2F%2BVFc%2BXtW%2BLWLf%2Fa92tX6tN5TO%2F93t%2FhPmxVXfo8VXfgivv0no1dvu5MTk%2BXyHffdaqzr6Yl3zeimBHQAAAE%2FEGaOI4qBXLR%2Fwp08loS1%2BtS3LsSiixP%2B1ZxPzLX637%2FX532r9ry9rF6olfrX61%2BtfrXavXrXa5STq%2FavdrVWqcPqZY%2BsH6v%2Br%2F%2Fq9erGTz%2F%2F1vJTrevXL5eqRv10tV0su1nKta%2FWqVqevuna%2BqUMu%2FWTy70vfRC1jlpUhXfq5N61P6vF%2BiQX4JjkJtAADkzpBd9q5ECiS%2FRN3PquX65Xxav%2Br92tP16mMf%2Ff66%2FQmr9Er%2Fteu%2F1Mk9y6qwLRNzrlT1d4xYVT6rwlYdmf3jK7V69eu1ysd2qE%2F192r16w6llEcT6p19F1%2BiP2CHOzOzL8Fe9ROrjg4EP52LA%2F%2BWpErE%2FC2rVzu7n9WJB3cZS9BBRpJ7%2F5bsi%2F%2B8%2BIH5QnCVwBigf1Ronz67zhgZ%2F8E0pBxpBYo2%2FXqFfauOXzqxUT3JasVzK8RutV69fllogKyXklYQ7HJ7r%2FI%2FUnBjDQoL6v%2BTDty0%2B9XfsBB1azakbuuXvuTnVyb1qYv%2Fqusv6viuOEG1x3oEQKfh4gea%2BgdINORmG1oVhoNhCiFdOgfVBHVyKP%2BaOpjaldec7f4SMH8X4anOEGrr9cPSal9YvwRVVhyi%2FORU2pWPXcty%2Bixd%2FrFXgkpbbknolfgo8v0hg21XiKenlZfXk3l9ff5Cy%2FvXD00ZPkURhIymZKkXnq9iZ5PEEjp98M7wuj8nkj8EXKMJ7lRPj6zlX3bPDJRMvq9evVLN4sk6SND6hNim%2BjbnwhOCsYAI0POU9WJ3zsfmsMEP2cTTl4Pgjyv78Fp2zw70PD8xLAxtB10oJLA43TKV%2BflQbsa%2BXy3YdEvV3svN3dcq930T%2Bry3Xq42CO%2B1ll%2B%2FwmR93HBCcDYD%2BSH7gnR7KXHTz03o2GX%2FXvxRXpvevzede5ct9v8hM%2F%2FQtIviTRs2%2Bssl61%2BE7t0PLyiB%2BCTbu4ct33Vy%2Bj5fojJE3kx8EJleELlCJsMW4NJ8akSXoE9YXMSHjxjr8NJd3%2BCM%2FHzZEwv1rzzGbDZjiTSHDfC%2BWGlZNI%2FRf%2FiARDD%2BP09n4oTLFE4QE0PXmOc2PPEwG%2FnwXbjJp%2F48Rx4vD%2F%2BO5Zvlv9Hay%2Fr5rtb9X%2FXqXqCIixkDfg%2FJmMY1RF%2B%2F3xfXgi8aTEH7O3rRfc88bA5%2FqfZf%2FohGNJ%2FzZxAS%2BkvCvlUFDAeUfWzGzX%2F4rMgKYuUMbINQfwhkNThgJWNaY6zKfvh%2B732IkMSiQy2ZFGgl5TlRymme0Ru5PWp%2FViXwYTMehm2jPThpmRQ9J8v9%2BELGitreOzXkCAMv%2FqC2hDc77RhBoLDl5%2FwWbG6plh3NIiQra1y29BFM%2FJdv%2BXP9ec6%2B3V%2FgkJsRZOpeo8jWDJyoKusNLs68k%2Fv%2BUpVNm%2F2QeuuGo9X7Wvy8eq%2B1zSLqtVaW6L%2Bv34KDY%2FKgUz2bEna7whYeT2llj%2FgnLljUoYeO1rm3v8EnRHgw6u%2B97qvS%2BivXq4%2BKMsgIAxh%2BewS9F1NeTy18xS5fXTkEbpE9HeT1e75WIQHIYq%2FEFeJYZfMv0gXXMx%2BKz1eTen991p7BFYUqEqDt95MZOH%2BFvP4%2FTN3%2F73rUtf2Yl7iHry%2BhLMdvyd6uJq%2B%2B%2B79Xl9Gr8tLf7od%2FoEnVFmN%2BogqyZhqJ11dF%2F%2F8NOvBCXdyFJf7EO%2F81nf9X%2FR3kqV7tf37rWvVjuvV%2FG7WvvdSFu%2BiEIZlL%2F%2FL5CO%2By%2F%2FeAAAAadQZo5DkoFd9ITK7r16vWu1qTdcp%2FXKvU7fFLl%2Bruv%2F9e6J7Xq9WO7urqml9a7W52urtWktX7UXY726m5a1QmtdCf1Yomh3Yx33UOZS%2FVX0Tfomvpe%2FVg%2BTvvu9QQ93w5f1i%2FWdXlkBA549VrqqhKr6JiL%2FXprkmp9SklZofVFl7q1SEIvu64mW1bHSe3RPVqxL69frVX3d9161V%2B4IiJyf13dy2iy557ltaiL7WL8nRjpwyl3Uq%2FLqv9X5%2F1%2FW60n6vd8vxPd%2Bty%2FXp%2FWCrXX6ty98u9zR2M0uXjqEHDMPN%2FrKa1eatai7k9erwUYyICVEtprWZJl2CW4wMvgDu%2Bvfd%2F4Zwgcy%2Fr5va%2FBNjbO5iZhkzdKG6tdVaud1auXyrLteqevWom6fqayLoEnaHJnkxtXBRJDQQRYLQ2uOnnteq92CqK%2FGMW9Lgx6Rjfp5dZPl%2F%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": "command=APPEND&media_data=3uvhIceGZty7j%2Brr9ElCHhyqHG7ymnjI2%2F%2BI0Ef60O9H67y2FN9%2FhAgSbaUOvGDZ%2BWP6uSeQ5868Ehs%2F69Q0Ld73P6mh9Ge%2FWuVWAqi7tF6X1z5f%2FUhJswUkn4%2BFbU7AgG274oZllwVBf%2BCikflBAdZkSffkIEDh7Z%2BX6%2FDZ8JnJ435gwE1cbWH81gTEPH1ov6%2BCLcLJjb9TDU%2BEHQoovylvXZivPCTwVl3dPeHYRf7J7r9EIRLDSTzrYmeiF76RX7mXqiVXghw3Fgf1%2BM1Y%2BCpvzWrxDvFN9Jy6yD%2BCL3bg2%2BTN4GPaz4VKMnn68MLje0esemSDa14rjhx1gy%2F%2BJJKoyxsZQz8OZ%2BGkmLUE2h6r6D%2FYIyR4ZvqnrmKMiAsSMSpO8fFTogmc8wcaMZ%2BbjRx2v7xOK190TrXrl%2F9Q4WOAq4SsCjmn%2FxFOg1xwx%2FWKRepaZ%2FQ%2Buvy0Mn66cL9Xn96kZrb%2F9CU62cjH9R2%2F8hMciL4ThFZeQ9ggEogM37tQjLXB38n7x8IC34I5WL9RF3qj9Xr1XUuT9H%2FxQgiTpzP67%2FzFs56En726mu%2FurBIWnfNXq7J7f%2BrwUE3e7%2B7Vv1lZf6%2B%2FEFd%2B7tbBCa9nrv9HZ3J61JZDQ1dZ%2FhPAaQ%2BWG3Pl5f9dWDX3XlK93V%2FYokINjscaTMrdKVoEca%2Bmfdh8RjympQEjmp9eThhqr4fEbaSBpzNq7s3aaJ73v4vvFcnoTFJyV65VrLL%2BiVP6LL9Gg%2FIR6OX1i%2F7q%2F0J79Xv1i7RO7m9HgrwREPjXVeiyq%2B5yfP%2FTyVRoq8xHe8AAAAP2QZo6jqoFf6F5%2F1crm%2F7V2M%2F69Wv1auluX6xX6xVRff6u%2F5pe%2BT9dd9%2F9qnHV%2BvMicSqZeeuJmxtauesmTy%2BOpjqXdrorfxy9dMvfq5q%2FvFfI6thLpR%2Bvq%2BLV09%2FrV3LqG83tqqr%2FuCXRrHBL%2F1PXfgnfZ7VYmxv1A4CDiLP9l8FEgfjgmPdpz8EhH399UK7ohFa%2FU9Vq6LpZPVq1XK4PJjL3RPpf%2FX1MLfeX31JRekucd5grsdI%2Ffr13NRqv%2BrO%2B%2B%2B%2FwSEJ5Gddrqf0Wu8UvL7qwJd0X%2Brfr0nPNzdqd9eI3jxl2%2Fy9gxlb%2BJ%2BTte6T4zwpkoj9Wq%2BmXr6Vv16S5b9V1frqTxOa85Wpiqg2Fq%2Fk%2FXvterkkrq16rv1yluS68vm8v6%2BCzkoxzwjl17NWh1%2B8fjf9wxCCe68EO8qgwt%2BonMIxpMXMWAl9evSetfa65Vlyy%2BtVxK9%2BvZf%2F4jwtzRnhaPBfYodk9tS1rui1X4errdDTk8zB01MHWSIH7Pk9cK817pdolmxp%2B0%2FGhifrVek1Xu%2B5cXXpPXyTy5BAbH8FFBjALjB1GfctwW9t0mvwmSg4eSED6JD%2FwhHpz0yv8y%2F%2BCE4wbeux%2Bvfgkxw308hO%2FFkTS6P%2BVicIBXlh5sjiCtQeWT5%2FXrvqltEYu%2FwkWnKfnCV%2FiCzfcNKw2%2FxGOMhe8CJvPfa%2Fsnp99eCqf3epP7whmYhx2Ob94t9kk9Pd9eerbDDGMgf%2FPUoTGsv%2F5CDK1%2FuincXmy%2BrRfiTKOpjd6fx3GBCba7150qfwS90WXOu%2F0evyb3%2BCEjR43ipfcjtf0Wsv6%2BCPI3799gjtp0lqTJ%2FW9eiV7rYq1eb0WK%2FRmCJ5r%2F%2BHOGUWQ3BhAyLHr5fRUgrzGP%2F9C2Ij0R5PWKvWv1lEesX56w4pz%2F%2BUjDwxJj4IZv8vzYyY%2FylXjB9B%2FL3f5i83XgjINghPvXmGPP68ovk3deGSSKozRXJVD%2F%2BhNS7%2FP7rKS1ey%2F%2Btl%2FXzVXL4bINGXQKv44eP4IY6ID5WMuTrwQlyqNTWjXl9WFWpRLzmJUQkdypXqz9YrtCEgdQQ73avXVeEpkr%2BkruvDRZvbi%2BdLRDrT8M6HKyszDvDA%2FXnOxekn78QIuUM8yiMGPltN685VTtr%2F2SiLDJ4Iy49Y2fqz9ZVITd1axfr0vlNcwAAd%2BcrD255lFH4IqN%2BL9W%2FRMK9CX77u%2B6L%2F617sYa16sr17vtZ5Lr1qUv9r16IwJf67vyeOyiu1corvs9f2y6%2FLS32Tqz%2BsH5N7m4vXv3JZC5e78Rlpz5p%2Bu91ksNZTF94XbkfdNht9Xu6CL613J6NVam3uW%2B5Jb2Jluiev%2FVxHotTeQ27KAAAAGOUGaOw7KBX%2BhbchPV32td7f%2F7xH%2Btd1akuCH%2F%2F9df5Pz%2F%2F9Vw%2Bu9X9%2Frr7%2BTpe%2FpWH1rvrWrr%2FV5PWv1y%2FUyV6vchHhHrV0S5JhHWEXjv132i1J2r475pfrk9kWVeuIql%2FXUvrBWEZLsiGvhGeqk8YN8ZOBUn9XflrtfVirV69e%2FXv17vHcY36vQSXt0X%2Fqy%2FVv65ZeleSdarzE3d3%2BXxpMrwSFStZfrsVa9Vr0g5dY74Xd%2Br9rVUny%2FNLk%2FrFXrqT0MevQl6xBa9FqS7xqVwTCP2I%2BTtcu5%2FXv1i%2FWrtdcEf5CZ4JEJ9zfcTdYX%2FrlUsVxMXvdJ4RFy6yWimS%2FWoj1TA%2FFkpyJc%2FS%2BIqPjCQPyBA1r1rwQ7dt1ZdX38lZd5dfL98tevfr0nm2i9LqnwR354V%2Ba9%2FxUfxPMy3y%2Bu6kLOQb9wR73l%2BzPevJxmrJXUTUGdctfVSL1esv1quf7XuYnuusv%2FqXHrjA5%2BF8xEeBo6ZI7kBse0nqBYRMWifL%2F3jyMKyDi4L%2BhQgswYVWmEvT%2F%2BN2mxZz8iBSIjDqniin3eqKZgzH%2FBCfOxznf4c2KG6G3YQdwr%2FwRkHAQH%2Be9Qny0QFn%2F5Ywzp6aeuJK6Xs3Xiic%2FdWg1%2FRe4V7ri63Xq4jn5%2Fia7WLXJXxHRXxVeCQiOG%2FRNl9e8FEXNStNEMAqdvvDRZQgxgH3vw3DwufkvRiZ%2FHHT09mJh0bsgfyb07%2BxNtgxV6tMa8NapMUVMX956fRe5f2QdTH%2FkyJIckQkCEWi5Scter1cnq395N%2BMMToabtTY3qG1IpU0sBu4n89jDKv8ZCZhWjCCql75evHOzJjYGAoD4%2FTrSo1hgiXgXwTTl4FXt8xcZQv4mMoGmdk2Uj%2B%2BxU3D0Lh8Zg7V%2FgkxKY%2Ffl3vXqvjVr6%2Fmu%2F8ElOnbd0r9rLnXqku%2F17r565V7xOuWy%2F%2F2X9exRHVc3uEz7UwKhbEbsdLw%2FJ7BAMXqUo7c9gcv31gmMUPl5Q3xLCdBrL9d8vvVfzTsT%2F3BGLe%2FvdGb8XWnCd0v%2FJHMcL82UQELMm%2BJnnk4n2pV3q%2BrSF3uCDsWUh%2FZyfe9WMtzccOX3XndLQJ4e0v3v8ubmx0L%2BqL9aeCvG5Wz%2FGhlxpMaXsb%2FlhxTPP6%2BGEZ9fFggg7%2BDXpy%2B9Hel1i%2B5fXxpNtET%2FR%2Bp64rmRMhkTtH%2FjiQ05Jt%2F5bRCfws09v%2FMeCJ5P8%2FwvD8IG3eb7r8aRGvnOcjj%2BGk6ncI1dcvy16PVa%2BuX%2F4X5Vv%2ByVXvXaQjwv8O2BiIGI1RL6tQwNe2CLhuLUa4ww%2BCOdiH4sh9l%2FXwXTdgYDHkkKvj3HM8G5pPL%2FXYq4bWpo6ZHGYoCyghK9ZnVNx8MziAtDAh5Db9fGSs75BEFG6c6R39ppkHGgQ%2Fr5%2F2V5aN%2FwnNxwZfiGAYVO9cEHmpDSw9KiHvqHcC%2Bgv%2BP8bTBQwJfohhI%2F8E82IBwnr%2BMNYMEdTDFGWvoKegUF4kAhYs2vp6Vy8hzhvjOeqTxV4IqyqUE4S0X7Xp7R9XP361fvXQSIAmbsqbkHx8EJpEhL6ST4flrOkcibjPL7PGZSyKI6Xf5RUELw%2Fk%2FMbShfdLdeCSK5pNar1y%2FBLYysT9bFGW9WgvgyQBi8Z74ZU89WSsllYvtiT%2F9RhMMIuhvt29jw3a45Y6kI1dXiTIuBrvClL8l51W%2B6GAbjlIEuTCFJt%2F0Q4dx8EvT006fvwle6DjlXr7EloJsowiFe2R%2FfqOINHG1NM4YDecsSsfXpekra58EZbji7uKlg7WUvmLdJ1lrlodeXun9ihUn41HDhp%2Fjq2l%2B1mVDQzmiJf4mVvKw%2BVj8xb3%2BF974u6%2FJic3r%2FgivvX65af9%2FzGz43nQmMNq5%2BE975cpa7IzfT1f1qUViH3uzaqTdHl3pXWDT4s3FZWG%2Furvlm1y%2FfqFqMm5c6%2BND5UlZT%2Fidu3lzWuKvdin%2FfpHr7oFIoRf%2FsFxcsPJ3%2FC3c3Q9rGD%2BiD1w8qM2TzW6cVkznY9i4%2Bg%2BqXau8uP9VZ6396yW8%2Fn5Z%2FTv0J7nN4uvW8xf9dm3f7vbrUQU%2F8OcP3%2B63Ra%2FJVf6JKtUTD8GHHC63fX2zXryTw%2BVcq1W0l%2FoS4E%2Brg664i69EyrdcqX3gAABdJBmjuO6gV%2FoX19Ll0XjO1%2Bvdr3ctrl2p07q1yr17tS36%2B7qjK9fc6uOCn0Srd%2Fr3asSX9UOUX67q16a9EJ%2FdXXq7FK79eqpe0d%2BFq9Q7lW%2Bl6T%2Fkq1qS6wnvy72O9cM6T19T9H9VYXuojQCgNbg%2BAn%2Fyty5Pf1%2B12%2FRHXfPZPz%2F%2FXtX94Sl5W%2F%2B1f9e77XpLXruS1qW%2Fym40g3%2Bjs7kuS%2FpeoJLa1%2FjiZw5L%2B1ryYiXgV1d9LNJqJFYKVeKjsfUEZb37lrRqvueqa6tFqxS3favfE35ehv8JcvfhC39fWpfVpbV7taiLXUvq8lrLtYqL%2F7%2FhDLRzrxUXkUVutV61JauX61iln4teil6i%2FCrk%2BdWoK%2FL41i7xvc9%2BPoIJnBqhYbTI%2BbGUzmTi1hZQXU6s%2Fuz6ieqv4Lsi46mVFLtb71cTkVRlMVaDu1l%2Bvfqy7XpuIr16tVqie%2F%2FJ6vcouO%2B%2BPrqhyXV4YseNHBM%2FpGNkYduGIra4Q1GgR5qffu%2Bxs%2F3jSZ63p3P7KWcbeSg8MtaIgNJWjiR2%2F6nqOAhZ%2F7%2FH2bd93tX2InqwqfGQevfqO7osYBAt3QCR9Z91rx%2Fxf9W91qrov%2F8t14bwSvADSsoup1%2FvVwxgN%2FHlgdIt66nBp4%2FyzJRfYKyBndqfHkvBD5rBI%2Fb8%2FBquzI76NwJjfY2UMB1tFbHqhI4We3T%2Bwj1fHWYINzeUf5PX3%2FcEJ3f9k9d%2FBhd%2BBb%2FrmgxPDP2HCJm1sIEsw6iCdd%2B%2B%2Fx5MDqaXffsJb3Gkxh3qedYMvv%2BQsMxbg4DVmJmXnv9a7luvWpPLwTHl7iBZQWQlYl6%2F2mV%2FHgRG8oQDv%2BCUtrHlQICrr3Hc4YFPRYJbrA%2FedQCh5WIu7wSEhxxby9wW7xD5ri33uH8pmf5i2OuwTkcWOSxHKXgetMuH2mX%2FRTLH33e3dkenflJhhWipF67Luup%2FT%2BreeWIjZGrhSnVgVdBPlnQgCiEX9I%2Bi%2FZ5g2SUFpDYEVOAuPiHsMcxp8P0iHhPAU1KRH6r9MsT8c%2FzY5Am2wN%2BpZoMYGuAXyefq2GLjcrhXQaJscOFrzjLw6mv6vyen9%2Fm4%2BY5Pq18J%2BOVZ%2FSe5b%2FPr%2BHmFOlfWuisC4ry1dXLBH3l%2F%2FNd0R83k9%2F8JmuoRcOgMw%2F8dW2YTY8rIYxnSRCx3KVBwJ%2F49%2B%2Fzf5iaT09Dtk7a%2FKFx6c%2F9WPXT4otjmYvfL%2BCczz%2B3Br06on7648sO%2B1JErl0D5ofnr7bdbtSSiV%2FwV3butHdEcAAL6N2rkl%2FNXrlVy5KP3l3aI34IszBsL%2FfskvT7V33UXonv%2BpS5%2Fyky32kuHCytjVF%2Fg%2Fh3FGxox0coYEyWvwW73KxqOzgwW3ozsn1DScZnrVVkjdN9nd72r14QJGhoq1gzOPHHy5%2BEz06wSNgfP%2FJ96%2BCPeQfYbmte%2FX0vkrpLVFc917shnfXhqyQIn1%2BPLoviKe6CWVleK3t3Mv%2Fe7sUnr1Vnu%2FGdP9FsPhPOyi%2Bby%2F16ufaNh2E46YfnYQ4YDfJ%2FcEXHZOX4RlQBtrxgXEMDDDVLcgYD8VjwAjIcckHr8EFhhhZeR0RGkS8nQcePCyvr8vr6u3N%2FgijSDckwV5xK%2Fj54y%2Bidzr0xf1%2FtEc%2FV69WOXb5fCDigy%2Br%2F%2BrilcNaJa%2FbUiy8hZVFP4WzLmYUnBt%2F18sHQLL%2FX5Pn%2FryX1%2BIJdN7lLHpdbLGoRXJleCueCZWMrMDPpnoy0lL6xTejxV6J0nsRmuvLjIwU%2FKGShuAs9jZY7qPjI5M%2BMGAbl%2FReuWrWLv9XEv6%2BQzwynmQpf9fdrLKYShysbte%2F0aXd2j9drUnkNDq6z%2FRMQStRB2js6G7IeHZ8nnYT7wUaai2x1y%2FVv1evFZ1EdpVJmiUz4fvr0dOk7zmidj5plEkPkl%2Fc1P8m9yT9q4XojxF0Xx%2F%2F9CYO%2F17T13%2BzPctN0X%2FXJ3P16Lld91cRKYm7lub0d7uXVev1yrI57u%2F2IvIagAEuFJCMFAsGgwFjIFhuFCMFBsFBsFBEEQkIxKuSue%2FuydyRc5supWTEpxUNcD53%2FWv1L83on0E%2FVuL5oGU2vuh6i1jwL05%2Bvs640WPb%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%2Fa2C9dSX2sOT1SAW1c6Im6WuX9Wd3a6lv9a27Xa1%2BrL9XP69WYS%2B3%2BpPVivWoj1aX1v%2ByVuI9Xk%2B%2BWIuI9FY36nrksxn9%2FrVF%2B%2FyEGEzxyX%2BtTSwr62cpO7nubfkM%2BleJ9Fqqoj112Q3HjyN9Fyq5bn9RXZfdfBhsN2tyBJdRocn%2FDhDJomVb4wkf89fnD6c8PlK09%2Fq%2F5KTBv%2BGeRvobl30FaL%2Fgm3oc4ZjaYeXwzd2ssMIga1jyetVlyV8U69d1rrxG%2FX4%2BDDmNEk%2B%2BUeHF0Ev%2FXvw1MK0mBkMdaNfj%2F%2FCumcz8YCBpb03lY2Jr%2FhrdKwGyrUCFOYY2CnDn8N8rFWQjZP%2FvXLd%2F5rv7%2FWvwnY3y5%2FhmVfdYZvkz78Fs37vfv1dN6tN6vVr0vojD5edKQIF%2Bj9J5yK4sv8pskP5b3v0XvxZJ0lFzSXorg%2FEdojEnovfq1%2BuV%2BjOfipk7WHIYLrwTTpJfsnQFBL5CyU17Ny%2F5xa8NJ5H%2FRmL80xtJGUEA%2FPX7EHEQw1KOJ4%2F8l14dodWy5uuMCcXDEuxQv%2BLsDTSRkhoyBJeXj5jflscNxd%2BTw0THloGtYgwD%2F4Iz7u%2BvwT240%2BMPRB2DI79iuGklh4ijWscx34crN%2BX2IZEpt7369Jfcy9eX9WrWi%2F94Rh5V3iC9I8QM%2Bd7G18N1jxw1QHGRoX%2F0bX5zqtV%2F4XxpMVQiJVjhVJibE4TQ%2F79ev8M7VWfGaf%2BtfhgkM95rjjXPpKyTHkEA%2FXmoWTPhPtmZxzdA7VxVHG4xnwlwHpn4JdIvxpDvN5WT7W%2F%2FKJWgn%2BiP%2Bvfq%2Fzdy%2BtSeCE271UteFyuhtDI0UaVxdTqZw%2By%2F5cJmxvskMKQ3NHf5YXZX95f%2B1BhvbWHEm61%2BOD4NggNKuG7abnYX6VXc14it7PT%2FISar%2B0NTh8EhNDV68EpiBmcICi5mINeoIqdPY%2FKV02Fl9fxN5WJ2ZmPwTUmM6Te7vJ616gjLeUxy5a9YLv1V%2F1qvJu9S7fECo6bu7a8oib6DJ4R9s%2FwRloMm%2BWpcs6AsEkdM6m4r%2FIWJ%2BpfL6qr7%2F%2FRstJKm5MTk%2FfWwSib3gmaj9fL8Iaj0%2BOZ68gwFlLlx6u93foQ%2F6E4dgj7QzSD8EV2tzJ5fX36%2Fq8nr1Wve%2F5DHt9WOyseWuPEe%2B%2F4uXu1XffLk8vp%2BxO92OT%2B56%2FDyGRmSfcV5feQMD8tvX%2BS0ZVmX%2BS%2B7avLPdhDP5%2FKxtUu0V54%2B777taj3V%2FgnJpvP9h89fDLqNgw93aEwfrVbonQl612vfouUmI3LXqUGTz%2F4rNXKvQqqgAAALSQZo8jyoFfKhddS9%2Bvv16%2FWaT179e%2FXvVT1X7r36tcPr36t0RwMP69k8v66%2F%2B%2Bpe%2Bu18da%2B%2B%2Bpev5tpevlq6yVbjQ3x32v4hNFLL1134Q6h3BD3RRV69J6t3LFSt3%2BvV9evdELqvXpxS%2BWCLKoYe7iwlfL6HfZ6%2FIoTi%2BCGw3ourcXOEAUWgTAJI6J6%2Bv%2Ffq36udr9VapODNZVzY5XyZfWvR%2FtWKtWK5fpWPpek5Yh%2BvOrucZbdg%2BX5xAb078ldJQruYmqlck9W91epa42a69foj%2B1MF1cT2vfq12rbPrtZVqtVfzL3f69E8bd369iurVquW5OVXx25d2su%2B4u%2F1b9a7mu%2BX7XxdqdJPWCT1r9WK9a%2FWu5%2FZGBlUyDB3%2Btfr1Zd9%2FdYR1ycP%2FPeCEJ%2F3tL361fq8UT5%2F6tYf6vXnr9IlNL%2Bu11XNLaLLX%2FxX0tScR8R80nomUlotfoj3fZuwZ7fr361%2FJavH%2BsuwkWUi%2Fnl%2BCHnYkq8L92nL9UVV9J%2F85FRle8P%2FkLPP%2BepsPD9%2BS6PXoju7xu8J%2BCO34MQvJdRN2HM4OQDrVEhFnX%2Fz18iggMY3BteTqmb33c19yc%2B%2F6vterD4Rq%2B7wjRYpPDJA6lOQFA9fGLnbrzkX2xkg3C5PRZTeru3vSIK5%2FXpfR8vzEvZv1y%2FJfKiXrKr%2FNMGkBCovylff6MyM%2BsbvEYi0djuT2aQY2yeuv0VwJv8hMbETfyT02BrJvNvGibuvIeem%2FQiquW7u77R4u6V5jaof0WpMJiURqgyJ1COj5cExPD%2FckJa5TJ9CMtVZ6nUX%2BvOdfw0knOy5IfzXQO69Ysn5%2Fnr5Uxo9aSsxrG7GvQlzv9Gcnvd6E5fqlaurXpL7yfkn8vsj06sEl33GwRbt9ZPb%2FDXdtfRJonu%2F9EgjfRWGwQ6dNor0fVk9P973LZhT7nupUJy55PQjoz0eqvtW7ifMV9xdvu5IAAASxQZo9D0oFf6Fxdq532vfqx%2BsXdevv1bn7q11wS%2FXX3%2F8n610%3D&media_id=1254206535166763008&segment_index=36" + }, + "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": "command=APPEND&media_data=L%2BrO1%2B%2FW3h%2F3%2BuvJ7Vhq7Vj7WP0Yr9detS%2BsVXN%2FBH4T%2BLLptr5fCfgn8J%2F8UqX1iq6tcvj6te5FV%2FhlWd%2FrFfN%2Bsv1qTJWK1v9%2Fqz89YyT2v1Hlyhp9eexMjpP%2Bz19kp4yS%2BJWu8UTeku%2FP7GVfa93V1qvVVJqrfq1eiRSe%2B0aL89fNA76JT1dVXfkospr%2FXsUs%2Fr11K1evdrKvRnDd%2FjPoXXE9Ki93IO8%2Ffpdxvr1YvJ5fPyO%2F4n2l6Sde%2FXpLWLkJria4uMpYi%2FN517tYr9SpfP3fL1d9Er3RHd%2BrVquVeGNNGjfSVFHbkKNnhlSr1ETF3QHcZCt%2FrVv17Xq9T1f8y9fa91r369Xasv1q6dWDte%2FWr1PXhxE9f3NtOYx%2BXoZwAA%2FJcgg%2BwRTT6sSX3Xgh6Gdr9iN38rD1WVd9rFXrB89UT2rfr369Jas7uwWdpZA%2Bb%2FdYPwnnqlAwQsxz9zWwXrWRnxRuNR5TMe%2FIJlVSKNmJKzDdI%2B48RPS%2Bbk%2F69Ey8692vfN8tUZJ6LUviyak3BI9j%2BTNqL%2BcuWPG3T%2BX%2FXDUgvD6Lab%2FA9Ol8BL81DBb%2BEyeZKyur0vt9tP2isfiiSjJjRxpMaOX1%2FRa%2FEbo0OO1fvenWvEer1I0vrH%2FJdLL4eNKxfEfweg4SNvy6kYS%2FNI8v4JrAMKRP9lNPBhCmnfmmETpYyYXo9U%2FxJBvJ6XdFvfrXrUnotb9SkpyJflxfpi5fLl%2BSE%2F1qIsxAgwUixOXYXZfC8ep9zCupDEaHn%2F9lOcIBnNP8Fxg%2B5NIkwxDklrutfzFJnfhwg%2FTX01rJD712Ly0f6M46hDu7nDVCRO7%2FE7bRRhj6YOEPJ9qu4K9Or74eblAN%2Fwlei8nN%2Ffc1yWinT8ERNJLkq7svxONNxnYdDDm4%2BaCNpca6L7IQLRCenJ7feUuF9UrzHrHEx8YbMwnoIZMM%2Bzx6muMPAAD8sdGgz0b2WXya8hJeTbXmOc2kVj%2BEeYyUamFIyD2%2FY%2F1CBoLMRJVSYA9yDQyQ82Zf13MeGZL%2F8TjkV%2BgdtP56%2FioaBE2er%2FXognr%2Btl%2FycQSjkx3aZCGIkKTT2CupHJ7w1J9z3BXv%2Bi3qwnY76N3r1BDNGkgrBeCEksOVeEuwx4cjYRMHB%2Fw7a0NyhgUHU8bHRRU1mEBHRYf%2FiukG4lkyliAy8F3CnG4jXiDadDbbOsOxm5lOCI6auWeqeuGqFGELWMXv68olLHBhvTn9WfriSWhDD6sV64fiZCFdK%2F5Jktqr7rX8F2M3dZP33dCskAy7Gai%2Fm%2F6uzi10hok%2Fv8EQiMIOw%2BPkB%2FdNwgS7J5lMmewnvDTvF77rwTU2sDNNSmO9VZObOXsEZcbIP3P3N6LF2p0lXeYZBE0P6yxBuvMdPf5t1u9%2BtX33k9v%2BvNyU%2FeXP6sWuv7RevzGdn7rQn9HqsTl8hhxtfDv3kgx17%2FNpX3VqzvXdHrM9lf7FzsWsPSZop%2BSPRHxN37mZp%2ForeJycI%2FopC9e69cpiev%2F%2BCIQ7b8ty9eIKT%2BfL%2FLSvJfdl%2FX6uK9XjPWWX1%2F%2FRWV6yjYAAAALVQZo9j2oFff0hbH692tfakT9Xu%2B1q%2FWquX1d%2BrlX%2Btn65Xqsv1er%2BJUie65f%2Fq9UX8%2F65Vy99KtSeteq5SeCTlx9drXazhk8f8N9N8%2F1TRs947SLXa1V9Eq%2F6wVV1q%2BKJSVrFXF9S3Vfa1XL%2Brn69L4V2qdaWvyTf%2BC7u1dHcU6gktp8XZ6d%2Fx%2FT4ndKrPk8l%2FkvJ%2Bf9%2F1fEyXLatXSuYhT0JdWvSX%2BjOCPUEm7%2BJqvvqR4bvtX%2FVv4n1cvlq1b9ZVaxfrFV3y%2Fq8hPr%2FqftXqvHdKGqTl%2BlaEi%2F%2F16lT9ddqzXsT1dfPXq75a0p%2FXr9SJ6q0Zlrq77Wp7r1aQnz%2F16uOfV1LfmIdI%2F9cyS%2Fi%2F1r9aq%2BEOI7kZ93XFxd936v098nELeJNV99V8leuVdI9cSbqBR4bXPzCtNX6Ep%2F0SP2bttm9Xmvhu%2BX2%2FkWXz0T25uSK9aqwRF4wYYrwQ7VtwT3583%2BCEj319HLHfPC8t8vd3W%2FV4mveXE3XlEXr8xbHMxuS4nEV6%2BKy%2F9cn%2BXdrFXhDQCOzFob5%2F2Xm7Ab8STNJBFh5fVn6F1F3Xo3frUgrrJ9b9atPgkJHjh4pfDZ1nnX5hcfF3ksu3MlfjDUU0BiT48Y2pbuwDk%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%2F5n63%2BJ4enJdmrkbBg%2Fj6QqdOClFDhxAvv%2BmtC0Zf7Z8tGGr%2Bo76zoK%2Fg8N6Wz3j%2F4mYEsEG919ipF%2Bbx3mnsZhTr%2B%2Fc3bGYil13JhHr1kU7v%2BBvSxZ%2Fp18q3W3ZYnHZeOevd7cOVARy1FRMRLzM4n3uZcY58VLjPlFejxmyPKK%2BZX2FT4QkR1E7WeyWJb%2B1IWxB3qhck7OEd9l4qYWSkkc%2FciDgASAUkCoWCoUCxoCwoCwaEwkC4WChFCgnCglEISCJE5pzfv8cfmVK43rLNYl1kZUu6ScDlvubTfPXMd5fnf6t54%2Bfyxj66M%2BDtO7P0dnk91NE3OabD5UVHoGPJfMrQDJxOi%2F3vcW61YHH5T9%2Fwvb6jv13iD8iRVfoqej%2FvEUW%2Flfm8edH4fDVu9nfUILgTh7stmnVyiqvTUGiYJl4bV41vfvJGVVDKdzbHL72a5BHdtXRdzODENv9od5f9rleo8ta6edhzR9xxwPlFVB4skYeruFgUGEnhSd4xSte98i817XTvVDy3BwBIhSQphQLHQLBkNBYbhYKCMKDUSCUQmd3Ws8c3eJe5z0l7uUvKvKrSySxxD%2FXqvjOtv1%2Fx7fnJsr55X8M6%2FU3UtG%2Fj71kD9X%2F%2BPbooZly%2F5H%2BmqBFcr0jc%2BNGfrARF4OjiDD%2BbhZooa241Mb9NDV0oJrDvR%2B5lP23nP8CFF239Gr%2BalPiZF1czWzxSx7umWm1FeuNvlznNTiuRz1S8d9R%2Bu7yjHRco%2F%2BPW%2FQd5%2BIt5Wj8f2RXz9cLiEsWrobvrtorSzjnTmv5rI47JZ3WseFZozvOnAZod7E%2B8MYOASgUjCgWCg2DAWCgWDA2FQmEgWChWCg2CgVEQhIycerzx549L3V71LqKQYVa0jQ%2FM665po%2FUH7eN4uh5vN8RXn31SoUs3OgZMLSvB1%2FDrst7dgmIhvxf6w4CK8ZE5FpYNBu93oeD%2BYDfTmSBGsr1PoGipeIbgiHgemla32lP%2F%2Br9udmfWbGf5vWZ8UoAEG1VKSov6iM9%2Bp71q%2B9pA35T7%2Fq7gx44B73Bhq6JBg4rB%2BXG9ALjxNgH81%2FEeyXw8ez4ukFr7Cu%2BbJdhuYsCJbDqjIHstKGXCPSJe5PsxUx4VELK7eQOAR4UjChFCw0CwUCwnCwYDYXCwUCwUEwUCwUEYUEoiCISCISCITC9%2Bu9Zz3548bXVa35FVNZUyqa1SR7D8xor4B%2BZ%2F%2BvyD7Oft6s%2FxErc8f%2BP%2FTtF9fTlz52a%2BHcrMONkX9df%2FW1AGAaIuqmHF79UOYuXIfB4J1%2FNFaAH%2FvS%2FvgnGaiMO8ZzfqoO8wLQvV0e2xcATsZTSdbSI%2BvNv3e51OSY2z7nZiePgeBxaH6nW7MQO8zsLfV%2FGp7XyamY7T94rHPKOF9Prk3LqXx9T6HAAaPmcVQAwcnBSaXzL4IUWzPqFj%2FaKEIQq35Gm06fU0AcAAAJ7QZo%2BD4oFfdXYjxHXoT0l%2FrL5vnWKuTq7%2F7r1ftXsnxX%2F6xX6ufotfq1F%2F%2F%2Bark9E6W6wtr1lS4vXW%2F%2BnXv1Sdl8tkFL0XV9zXfqzov9av1l2uXct2Tx%2F8n7%2FzCvFYr0TE%2BtXRF830ry32ur5TiiqtT6fTGi6TY9yq4n3Qt%2FEZOlf9Ut0XJLNXXrUlqxVrXc0WrH6uk4jHLYl9ar1Y7%2FWor1q%2FXL9av1q%2FV1er%2Bqu%2FV5Z%2F1cq1cu1vJclzesprk9e569XrQurqrhFWlv9WIn16X1i7%2BeXdbu1qt1dVq12tSWtdE169dhvmnVApTwyT%2FEXctVyivtYP1eW16vWrYsVfueS5fXKvVx9Gr9aq5LnurR4vFeur159%2BeuiDUlPk89fOdLvu%2FPTB6DG8tN%2BSdjNa89cb79%2BtVXJ69Imb77Vqn7muvBJvfvz14q%2F3fqx%2Brfgjs3Ro3Mv6%2FJ66r4i16bSXKT0SX4bKsPyd2rcO2Z%2Brk8t3Z34sum76SuvOIXUdEz7%2BI9FyiPVu68EOk0rC133XmLblj84hfQKpH%2FOVyzZDw2PzX%2Bjd3%2BrTei9MKV169%2Bjunv9E9l%2Fr0Tv0Xq9e%2FKTZOrl9eqzie%2BSqs5LviUbpPRXS%2BjQS3PaFxhtGbsJUPXlz5CZa99hktBydfG7u5T3%2BJngZYy2evJe3%2FJr1alrorV69L6FOq68p2Boc0C2fBh7bKf%2F0SK7%2FIJ2zJfoRF%2BsU9oTXf5DPfuieX%2F3L6OVu5PRNfgiq9DerWVeevEKT914ISZ%2FevXUTL%2Bi5%2F2R39yehOp8mLusRWKvU1P6ERTXXo9fr011d%2Buq9FZIX%2F%2Bf1Y%2FKa9%2FsimNfz18%2Bt8AAAAJJQZo%2Bj6oFcnG%2F%2F1aE1z169%2Brd1a13V9rr4la6v%2F%2F%2F%2FtX72799%2Frc6lTr%2FAQgSfPJzY5ffr0X6uq1i7WLTLN83zO7%2B1dLas%2BTJ7%2F9r9U58I1UuUnrqvXphXXgv27fL8d2df6iLhG5Kn8aQEsEXjsTB%2BWNg4LTX%2Bs36vJe%2F4mqT1r9X77r1qS5LBGS92v0Vxr7muXnqdX%2FW%2F61%2BtTX561ZPbr%2F1qrUyUX%2F1RnBL6ZHirilrtXr1cluqWr%2FV4Qu7vdWTV8v6v3%2Buoz11frXa1PVRff%2FtXLnm0JXDkpPWv1ruS1y%2FXr9Yq9EqS0V%2B%2B%2Fkr1qvVLWn8tWsoq5%2FW5XokEvopq6SuSxXXLdrX61e6xSJXBf3dw3Tjr8xIbtaNPwgTk5l%2FMv%2For15sgXnDAq7J9%2Bv%2BeqAx6Vhf9RdSevV2rfIvX6v%2Br%2FrldqyKsmS%2F4IbSfBJ65V5CTZMGBJaPlf%2FLV%2BStV698lSxHlMZji%2FIW9916wxZWevnhfHZcOl1SZPky6qysfr1y77ivRe%2FQhzueeX0XpPX03q8Z66q689fbPT3f3cTdeCTu5wV5zLeNFf1fZrxsQm7R9fug3Y5fRspfCBTRmNZ0VjHm7fL9HInqiMSUV3q%2BT1giPROnuk%2FV2%2FX8h3fJpIzkt1aE1Uv6xSXV36I5d5PT%2FJzERzyspps0Tz1%2By%2F7815PT65PQlyIu%2FRndy%2BiuEuvtEe9%2FX8tme8tr1X%2BsqL%2F11qhPd16xV61%2Bsoj0I6%2FR8L9Fg7lfvrdferlfpK13XrFfrlE3F3JAAAACeUGaPw%2FKBXXEoW59f%2F99%2F%2F%2FfTd167nclE9zX%2BspLWprq%2B%2BjKrWvmv16W6plLfS5VaJ1Wiyq1c77x2XCp%2BsU%2F9EXa6rkr11%2Brl%2BuX69V%2FqwJ4jjUtwLd2mv5yLKxf8%2BOW5z1ddLBQ6VvMFh%2F%2BsXRC98laJd993Pfq4NZOfP1SPL3xauN9%2FEfq1dL1eru1atfkq6V%2F6vNder1f690TPOqWuJl43HeUT3EaNLdepmrVY6rVu%2FLVpR3%2Br1yvpa%2FVvmk9XJbr1fv9em9dT4%2F%2BrGK%2Fpeu5bmovs5FzzNDxVFxd%2FEV69dNPcly%2BTSaaF%2BrXiK94Qyaq6f1d3%2Bi9L6N3d2i9LOp6777oU%2F6yov%2FTxPrl%2BCOnNlw%2FJG9%2Bz3dvNj%2F1qvV57qeO9a%2FNacOpCfxOtbVX4Iuam5T11qvWu%2Fz8PonG4iAkO8vLk9a9u%2FWpLluL9Fcy%2F%2BphF377%2FCfRFuzICDUrXUT6xforVas%2FRcpbktGavRXIi682CJ4z9%2Fd4nP61%2BrX6NUR4KMsPKxcfRX%2FBES1MxLtF1%2Beup4%2F9arwmY38sChgOvLjn%2Fv9elv9FeIFLL69%2B7lzXk8Nzzt15fLnzXva1xHd6yqflnQHj%2FRH%2FMNfS%2BjP2CPmvgwvzaG9eGd39PFBsaXu%2B1aa0V6vuf0aKrlurRa5QR%2BfXU9f8QRGQg7ySX8kZi%2FfmkH7%2Fgk1q35j3Y693au7l9a1rJ5K5a1ZVef0TWX1%2F7Pg%2BixEMBRPf%2BiEl%2FUv7ye8ubL%2Fl%2BvfvJ8%2F6v%2BivcFtXfo%2BX567M3%2FUuufJ%2BfwhE%2BhTP0cpXfaKdPVcv1dNZBW6J6oS9L%2FFd%2Br47al112vRdr1erxGIyQAAAA4hBmj%2BP6gV1ctV3JaF1P6sV61JasPqxL69FX%2BsVetdq9er1qbe78vd%2BhP6Jl2bDd0n77q6tFeuLr1r9Xr1ftX%2FWK77l9Xscuu6J5f63%2FPU8Bol%2F%2FsnDyLveobKSFqp0LaDa%2FuiPPPV16K%2BKxXtXTX8TNSq%2FdehFTt38vtHa7q6v9Xl9Xu6pZJHuQnqxRNeJFXvemvQmf8hHfU6PO%2FWv1lwazdLqM9arWvXr9Yv179kvVei1d8EderJqv16vXu1bqx392vSX7rlXStfJvX9UXrtiJl4HbTCy8ci%2B7k9fHxN1q9Vq75ZOleXLr1Y%2FVjRyfICzx2O5oL3w1rlJeX93IGBa34T3U%2Fsccq%2B6M7bGxXUXe69XouUsqmruT1e%2FV7vfr%2BQjaaff6K9vXrwQWCHRxvTQK2UlQMxBpsY1Ka%2Fl%2F1wQ4DQMe89p2%2FV%2F1l%2Bur9ZSWtfq%2Fyy6r0vlxoZKxB8JkVLDWvuB5f%2B8eTjJh2J9YI4YFwg%2B%2Fyic0a8VsOeEPW%2FqjHwgTHqu5Em%2F4RcKirEBXljbo0imb9cvzZ%2FP9ybop2kuvV7ubUWTCybKsJP4%2Fm1k6L6%2Bu9fUqisTyJ%2Bb8n999eK4KVeZmmrBCWan1WQkdBQrDCv8R2Y%2B0Pf1xHr0vosU3jDM8Grul8%2F46Jj%2FBDWMgk7hLX9%2BzFyeS%2FzXy47OVaY1L%2F%2BCMktKE%2F56hui4f9%2FrqEbV%2B2TjxhLvKVqRR%2BzH9AbHfr7ieXuMzn2X1%2FMeZQh0SWuYx%2FP%2B0NrSuxF7vzd3FbotVdCvvL8I6%2F6NUnrq7777%2FKUdhHoJciFM09mKf%2Frdgjl9mz1%2BYTGhHz8JkPnbtxHrVX3J6Euk8QKm%2Bh1ov3%2F%2BrLJ6f7O3bqzyt88LsOnr8OGjZgyXXh1JX%2Bwzsj%2FX9CP45f18dspmUMkM0N2XxEtEfoByf4jTCXB1trEZyvUy%2Bv%2F5JmOvQvLy%2B4i4n2IMzalv7rwRRulVdn6FxUX%2F1rxQxORnuj%2BzuxvXiZNMM5WKHU9Wa75%2FRXrue5PC1x8aP4rl8f04C%2FRIqL7%2B9M1JhlcL%2FVM%2Bv4RNjxYWjMuagh%2F%2BCErCrCPyiPMd3169VqarF6ufyGp3%2BbP9X%2BbNszDfeK3hpTK2nyi7GO4%2Bv%2BQkmfLk3%2FNd9eUt3k8TzsNx%2FPiL%2FQlL3V%2FrKdest5PUMf%2B63ryiiYzyLiX7m9Ca7u%2Fmk5PLluriZ%2F%2FyCuMrASIUlCwUCwVEwkCx4DYVCgnCwUCwVCg1CwVCgTCQRCYRIzeqfaTNYmTd61i6zjKVMcQR0HQerQfBPkdB%2Bn2J%2F79ixdq1NjV7Wks%2BUmXBm%2BGFBaNcVXaCsO9UwCoBPifReNr6L%2BX%2B6%2B589VrcXx%2FPZ%2BgGtwhr7j0nckhs9vTKZgFHPgtHe6uB9c8aqnEdPPrHH8e%2BE%2FW%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": "command=APPEND&media_data=4ZLLy8s1hOnXq1uvdnftHODua0Tu69Wnx%2F7XpPXou%2B%2FzEm%2FJ8f8pP7%2FEWWb5PP5yr%2BDspk%2FzYi4i%2B57lv8EOe95f%2FXvE%2FCOvRWlv89jNtr3aEZV7Ln9X%2BryXfkImfd33XmF4yIXF%2BpWmXv%2BhEEvk3ftWu1Z2hZGQfo25J4I8noqq1xl3%2BrS%2Bixd9%2BmtS7lFO%2F8vQQ9KVyej67mXuGS8nf7NM%2B7L%2F4jLZO2Rn6wXV%2Buq9e%2BaT1i%2FX1XLct9yP3ryiHfL4Iyq15VavJ6LqvXpcrk3kv8mVLUunXho8ogL6xV0%2FJ6HVLRNDom1%2BrfrBWXrJGCYpfr19q9wrJ66lgAAAAf1BmkCQKgV%2FoXlPc3EK9aE%2FGf5fX%2F%2FnVOl69eCz%2Brj%2FAt1aud1fasSc181dKZpfVpOf5Vetlq6n6ly76vbV7te7iPWUlq5cEPusV333flkEicb03fJ1a4dq8pP7%2F%2Blb9XdrUtx%2FrsXNV2ry7rh%2BrsdyXa5X6tWqnB%2BrE%2Fr1%2BvS%2BhEpqJ4Wph0TLRBf%2BJ6uvXr9WK9WK9WBPXrvv5llJOvfEVcvq8XfaxX61Jy%2B1EXXExdrlXojlWsX6wS%2Bidc6PB3J6lS7WKW%2B5NKJ9XKu7rykU2ZPRd01VerRFqy7Wq8xCv5bt%2B5u7ivRZVdc0uqu7XKTxZJTretLvvuvJb1Xo7lX2sV3GWrdonR7%2Br8R0a5qSei1XlJmpEXCflvu%2FRsu0N79iIcSbuvLSb%2Fnr46l9Jhr1lXosUXcnq93V9kvu%2FViyf3%2F%2Bsq8nYZ73Xokoq0ev1r1kuX0Su6uldVdeLNH2X8%2BJr4gobbZ%2FYGcQa%2Fkmv%2FEVZmSao5RHYIY%2BM3mpXcX6LUb6JFLfaK0vrF3z1Py%2Frh%2Burur%2FZ93XqwL5xijqD%2F7lu%2FN1a%2BCITQ7kSWxWlS3cvrhfmM76lq5Yvlq5rry9N%2FrF32SWnb3zUhxl8%2F6xVuXe5H6SLFNckP16L1evb95rl9e7mswjjeZeGKxFCcq6V%2F17FbQ31q%2FVp7v2KJjPUAAAB3tBmkEQSgVyehba%2Blcr1y7mterdYpL%2BJ%2Bv%2F%2F8n9%2F9%2FKrHat%2F2vh%2Fvq7iPXpfWU11xHzFJhvUtfU9cZ3IKf9FSs8vauX6sTeiP%2BST%2F4LbGwM%2BZba317Rs9P5dqS%2FvZTGq6w%2BXnH0ijDUQe8mlIK%2BNGOAO%2Fodlw138lDvmMcsqMmO8TqT6%2Fq16ES8tcXfqnTL%2F%2BhHVNIzn1a9piyuD2W%2B0V69e%2FVu16uSh37v6V8UT%2BrP1i7WpOIk5l6ub1Xv1Kbq91r9cr8wg%2F5Pqm8MpH6uSuSr%2FU4KXXfNPtVV%2BrncnguIyBm9PcBrNadu%2F5dJRck6Kyyev%2Fdy%2BsavVu4rdYq9ctfgo8Nz%2FW4iC9mZvwRlzPz0cXSq5%2BUUYfLbV13vGkxau776StjP0fvdem6WCJpr9dylrmJuIc2EOq5rbmpa9DKNtGoDUxDzSA4DUtF7Bj8p%2BfqC7N8wdP8NmWK9r2T738Eft3Mv59YzGs8sJDLR2MsmGofg5WA%2Bz4mLc%2BggZz3HB0MHJYoyVEfJ%2Bi1JTycnRyy77XXfxH69Pur%2Bu%2FoIk3KQeXGD3c4xrXVtnRJM%2F5KcsfbElUHclpw4yxW%2FehFofj%2FYaXTyj8v9eIMFDKjr4P6oq9x1mkfN5Jc10x3T%2FoTcRcR6Blzr8sQ0B7oWz8KU8IykhCSAmvn5zI3thFp1Q20vyOD%2B5T%2BURytCdfqWlvHKkZcnrhJ618ypvYivUoPxZpWL6vW9CqJpMVg%2B%2BHus5frrHk4Orh0J6jDHtA%2Blrr7SFWoZO%2Bv19hD8%2FBiVEHt%2FxpMf%2BLE59vffqr5PqrSUEE9hVZfh7LR%2B5YqTJBMHpR9k0tJ%2FZ3tBMybLPGTSbWa0lEBhxEsdXyZuxLBHGkEQqpM%2Bye3%2BWGZmWPvil9fsFpx9kFR8Z3%2FtNQfh264CnI8hIH9HvK0YZ1f%2Fh6UxZsJKWh6ksKlMXBWOo9Loe%2FsUr%2FWr4rteiJJXOJ7rxZHYKHLvRUx6IMyZUl%2BoFmfl92T%2Bfz%2BL8Epb3HMkDVPY1N2EeCR0SroBrXlVjrLbm26GEh2YlaMYpNUjOrP2wXl%2FfcFsxpMm73y16I%2FFun7QrP%2Bxyryr7ZQ5YzKfYat7r8Otz8n3q%2BII%2Ben3bl%2FdcEWPC8m7FrhOvvAYReajqaZ8ktjrVG43L5ml2I8S2exqVH36Kel9XVfRcmWvVv3RPv%2FHmbRlqKfrOkDdVVwCqq0vX%2FYmtBAsDu608x8tprsepVeMnhnhgo7LufOkGJMVxir1l766UxUh3wGtDz%2F2EKie6f86nySn%2F1vdST9dcejp3e79m8FmCqtvPSj%2BU%2BOTrXeGMK17MywX%2BEDBeLWplbL6fWisRPE9rb9e%2FWX6t%2FWeit6fp%2FjxnFuOOTww6Oso0TynL4JboPotMPsLPug%2FflK8BTJj3HL9de%2FzEdgb%2FiPLRUMQ%2FI9x%2Bd3H8r%2FvL6ftii3vqx9wyQOzyj8lntfiq5P31wYQPt9qyzXtbG0GrQa%2BY5RFY7kFvfW6ZBA8Lh6Hz5Pj1yTyyJMv3eoT3lyWwUROMQcqv%2BRIz0Xsv%2FiKPl5u8JiOrRnFdWQnuXJPuvxPPWVJgd2Yl9%2B8IayKOgJoQjIl%2FYfoxI8Y%2Bc51w1c3%2FJ%2Bb9GhuL870FF9PdsVZx0xW1euBC1Lb85Zf8qiT74NF%2FsUKrn8fp0fLqyk7HizpUObcdLnfjIeuewjw31kJBBpEolJfGVjk9Ht8JGYv9g0DCBxdrqcgkYbVnreoyiiBtuO7y%2Fuf174iRaR%2FrW0Qu79x5Hfaf1VeP0gkx26yCVfpCt7y%2FfWI8noDjtJPP%2FLEqSGVc7tQUY7TpuTCyiLrOXL9is3lXgxk37DpQgxPr9pnoI3f%2Fad9jbUZBHX2GZT9ZRip199N%2Fq%2BhpMERgR905ufW%2FaclaL1CXDfJcNLs9TeC20MCRSxMbCFV0gi1O4UXY%2BzB19r2SloVvryhmH5dhOZPr%2BgjNpwwPd9DmY2E4bntKXxTvfjePOSbnwf16pF1%2BLFjhd1U0PLf6NUTf6LLxLr0I6TwW9gwfmr3lrfBHarjDYJ4q2RPdr5bPON8ny6fljA%2BD%2B3rs08B33%2Bvfovb%2Bh%2BdIZhrAl%2B4l%2F77O%2BcEPllbJ7%2FpgsojGPgNab%2BWhT4%2FBr6CZLYbQI35vifNWCUtbGRFi9l96VIpRY77rXhb5SG3fP7W2RrL%2FyaP1dKy78%2Bq7zv3CIpBzfxkiQ11nX3XWTwt%2FDJQifK%2BvzTMNPCB75Pd76RXfgjve7ul6kIzc9vyT7Evf3f%2BCI7hL9r7emCTGpRKffYLcuPQdcuW1p0EhGEXGLVksvBBNz8vsdA%2FyI4ZoWH2W%2Fkw1Po7Zf18lHeSb9tFw5y7v3fq80v69V69exRr08uM71wSaUqJtd%2F56%2BHF8m1i%2FRHP17J66e%2F5JoBIErm%2FFxHaxD8G2yoP873fk9dcSy5afEvxL5eXupQQn3eKa%2FVF6vXprJdr%2BQxiS3352CX0lvaZr3%2FPZ%2B6RjKu9UXv5PRy1PV%2FyjINpl6VwlNT6SWzb3VrhVN%2BhLctN%2BuKr11%2Bvfr1fL6JKrR2PTqEJWnl8vye0M7vAAAAF60GaQZBqBXJTYyL9%2Brna9Xq1br31%2BvXa9eq9Xq36tVr0kqt9dF%2F8X1K3%2F69Jy169XEfS9fanTu8te3k0UmwhMkn6Rea0tSL8XvRiZ%2Bcg1tNi%2BEvD06cAVa%2B0%2Bf%2FtYqVJYEHXq1Ui90namb9W7VIC5Yn1lXq5Xr1TkJSG4iruGoAZPX8X%2F%2F9fjjRrrdyc8t24VjrcbM9bKYHqHyYvjZl5cS%2Blc%2FBWXgl%2Bf%2FDqBqWF%2Bb%2BjfEbN3%2B3q1VqxV%2FMvdq3693k8%2F%2B%2FVq9e%2FVpOl6S72q%2F1QhsntX%2FUjOd99ghG5qbip3DMNt0vC%2FXxsF55tYh0atXK9WV98RXr1T9rri5bXrl%2FWKrr1cq%2BT%2BXT%2B%2FdWHU5qw%2Fun%2FVUnFSUdE%2Bjy%2FWpbv1bvrVx9a%2Bt%2Fybq691d3V3urKuI9XJZ69Ze%2F6Ll3%2BUQMt3o9iMH68H66FYvPhnEXWK3urH6LBJxNWrlb%2F%2FghJPDy%2Fdhs3v3c%2B65a9F6X65aoqrXv1erl9ar17l9zEtQD%2B5aFaDd7OeEHGe%2Fq72dAutXfbKZduV%2FyFnxA%2BvXL%2FrgkMaxpr63vZqCH2vrby7fL6PVeuXUs9V4pX2uriZIT7ka%2Fq2hRKBszwHBK1uO2seTj0daGA0SeLQAm%2B35%2Fo7FwkyaD%2B77BCJP967Wt%2FhG%2BXng89eEoo5V4MDRt9IPmaGmWglDfv%2FnBDz4N8z1LDskIQP%2BTNL8FJ43l6Bg6zF%2FMICpxaXcMw%2BdL0lDE%2FlT%2F%2FDmRmRiK0OpUuXvFbtdvn8utP5YmxZHhZMdmARPqc1%2BcFXaadiKcXwPVP%2B71pvk%2Fl%2FNuu%2FVe7yeHX9gn3LxNeLGtz1ZR4suCR37qzS6ghI4lktjsfxpk7II9j%2FQ2W60qR7%2BI60ZcBZLIMby%2BT7ktXJfe4fv%2FikXu6v0IkuSfsEhoBnvUuQ3dRtkSDbqCWYegGs3pTGMX226myJI0IDT%2FZBMYGT9TEqEOJ49gjuXPL17PWb0%2Fs3dHKTHGWVXonm%2F%2F7K7%2FUxksuUbvxumeb1rusojvvvurR%2B%2FV7J9%2F4LhGpUh%2ByTbh9iKSAx8XC40U1iYWyleD4MoC%2BxBEk3377fE9UyZ%2FcQW0q6rJ%2Bdl12iuKicEpHucglsGN5%2BPyD8fqQN%2BYcmbg9xhM6S%2BEpafHRk7vNIGAron75bi%2FNgLrqSx9X7%2FKXh3LGX%2FhH4nv%2BS0dlXVq4%2BhD7vBJsI0S55fljN6F15dzhAHk9%2F7KV36fBGV92eSCIVu0438I0p7HbHe2fGhLjZt%2FuVRRcGXKpszXRuEegwrHYMtHxkTvpSemnuGDFkPojCJu1a6z%2BuN3P5Pb3xRyYvCZinv3biIH0vtH0ENyfPvfovquk%2F%2BrmjfRuQyi%2Fj8n7%2FrHt9%2F6Kkov%2FeSU0SH8EM5OODHycbv19kMWhh6iq3CcvoflhyfxPuE9sDqS6HdqT99cI7N9sET9HnNJ0rlx8C7QZantDMpsFTJoZteJ7zTpgl9JgQ3LbmFw3%2BI3HDGM%2BaY%2F7jrK99QIegRO4v7BGLNTail%2BX1lUXz998ve7xQoX2bMXb2dAliFkQ%2FO3P8WT0vf0Plkz5cn9%2B5tqBnh6gR89sbvPzeT9r%2F8EUyBpC6yenrlGvf8xnh7Nul%2BJMwKkFZcjTZCp5f9c3JjOrcJFW%2Bxy2muonFb8bM%2Fk8X5Nr%2BrktH70J%2BI775dr2KGHDd88OraLkND4WG6qzFlz%2BWsmNpa5yr5Uk%2Bp53G2X7l%2ByEwfYaknqWqSm3vYXiyLWeX2CIXnMX%2B%2FWvdU%2BlVFiEYYBm7jR6iHEMerckmfO8myFyWjt99aTaL4JCZ8d57q5L8%2FxXnyeGrlq2h8JlEciton071YInx%2F7Nxfd5Mvr7UVp2Tyy%2BIJLezPnzf9B7mkxg%2BT3zJ%2BvV94j8v4grv7ul5P4ve7iv%2BitLf6Ll3l%2F%2F%2B0TUkvP5POQQb%2BpXyfGke%2FqsXZj7vl77yfv%2FVXf5LPdXtyeE9qmlI7%2BE7ur8fQnX63uvdS1r5OjflqN8n9z5L33d1k0%2F7zVes%2F1ECBLjPaafvAEsFJhIEwsVwsaQ0GAsFAsFCMFAsVAwFQuEhCJz7b6zfrzhVRnCSqlRUylNJcdDlX3N8a%2FPPwXduXxw%2FCPB8vg03m4BPrvyk2fvFv9IOTfCKLvZ%2Bo%2FVFBhpRuSs60Sraj0Gl4J%2FrkwvXwiBkC%2BVfOJ%2FspjomvSqD1fv6JsK2zuUm2uscAkkVKCmugvGZ%2FkYdGaU1B78CqNJ0JAMYDYNRUbPALhMwddBg%2Bfe%2FVhfTfUtvYAaOeIt7u4BKMZIkFRGP7x699m49R%2BHPdzr%2FXWoH3wvKhfcoo6eicqRh9l%2FicfTKkhdzELdvv%2BV1omlFMihE3y8qAxQ6qNt7tHnA4ABLBSYSBYKBYUBYJhYcBYUhoLBQLCQTCQTDgLCkThEJCMK5XHe%2BeLrkuokmQlUYFtRwLuXFNvTlrh9I9vIWvH%2BDPb1bpJdfSrCXy4GdDBspHk2Eac8b9t1AlA28Gbu%2F1hXRr3jHd3sNVPf3WXwd1iapz5b%2Bf4zjyxn9ux21HqOVn4vUWR3K5kGW%2BpAbj%2F%2FH9QN%2BQ0ZcB9vxQNiLYLlxqQmOQrC0PVZN8vsZQEwm5CFmFNF8vNr6TYOJBIafZIvnyFurvA6MqQS%2Fxux8tz2TyjbiAxnZm%2Ftvq7P2vvuG37Tu08nmHHxru3F6DFXx%2FMEYXUkRO%2FqNT4%2FqyCPT6zgvYAurpKIH42kMfqm5A4BJhSQLCQLBQLBgKBYUBYaBYMhYKhYKBYiBYShgLCgTiIQhMLnpWPXnd7lTWzrKlZdUMRcuPI0Puk5j%2BZTj9Sb%2F%2Fiv%2FdrOF9nZzpAV2WGzjb8ONU%2FjsJ9acY33Bv%2Bspx1dtVuNm2Fuz8jAnbQulfK7H%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%2BMcHe6SsOUVQd3I6av5U1UagK0wrkf66c9wBhdXMAbtLjCRU%2FHrk%2FLu8U67ToyPG%2FT5%2Bv%2FQMtJSHT9vrPpQAAupK5WfsxHK%2B5n1HF6V%2BBEzjySt5zlFMh7OdbSs3e%2BtQVVwXff9JUQlSsyHXyTsgvAy2%2BsawXiySowwsDgAEmFJBsFBMSAsGAyFhwFQsJwwFAsJQoFgqFhuFQoESGF41rm87587uufrurtN5cTE3Kl6ROBp7XPOE0aE56W%2B7jH9H7Egv6OtPQOmNAFu%2BQ98cdkDvDefS%2BhSAI%2FRc7Y9HqBYp8DEQr4uh%2BnwWGYNZHPhWixV16Z%2Bq8tYF9cpWIVrI1AbgsMYEV43XLWuUfw%2FSfc7eUf38rkCbOyQALtQBodf%2FnX0%2FPh07g6weJ5wKeeMN%2B7aXbqCATl07tQoALyA%2BxtHe5gFZcvt1e65%2BPyMIR7HkwF%2Fy4WvcV08eQph9zcsBU10b79cazuafDVZF2sub34R5oI%2B7x6IOAAAAFtEGaQhCKBX%2BhcUlIrHfyrXxPTL1X33XrXd3%2Bsu17gh791r%2F777Vz%2F9X%2BTr5f%2B75v7tdV61dqxfNz7iS0R%2F0Xv1kVmqvKTG46cEVdy%2Bis6sJa99vqpWL%2F5FddS9%2BvVdWuVXUqI2T2%2F9W0C2XsLJaO83q%2FHwgLWbaJW5PCnewQ6Cgg%2BN7Pl9fUpQ%2Bnrq6vu%2FVq5Kvuh3d8T32td3d2rxZPX%2F%2FWYV6sikl%2FR26sV1DAh2iNLA5qxWghVr3fKsP5Kv3XL4irr1i%2FV9W83ghlp06LfPfrrtWSc91%2BgnVrXc2X6qxy3eT3%2FwQkjbag4myeNfYSo5TvcqhT3aK9XVFWO%2FS%2Br3xHdXPasdi%2BXTm9wTK55uv69%2BJJedkPQ2GfJ9%2F0E9imXKonGD32i9XEeGNU9etfrFY7y8Ev9dXP%2BsTrdetS%2BsVWLJxCwvLlNYnu2kdi4%2B4qNSakabCNKclL79boGaLcgFixfLTxX8KZVFCjLRg2n8cMk1wot3hChZZCzrmZgpmSgstzEnevn8KZLrkv0W56rV8i9N6t32YmErB7Cu59W0%2B96%2FCdnvbnX7h0ox5Z6boJS%2B%2BuONUty7%2FqfKNm2uP%2FxBiWiGduzIQnqnr%2FmjTb%2BX9fBFZlgHZdirL9%2BeDuq%2Burq0d%2F1fqWDxOsn4i4m31kJqTJPdr8EMHYZ%2FX4XI1hfdPVg4U4sIXWG0STYj%2F4uoBD1aCw4iTeT4%2FxIlk%2FVA0t%2FgntNcj0bRh1%2BCYxBeZisER%2BDn35ZcZaP3Ny0%2FDZ8uPhQRDRr%2Fzyer%2B69%2BvVS8%2Ff6933a3eWxZMvdg4ET0aT%2Fvqx3SSxoHAZvL%2FXZIeRM5B0Ou37N32xjXo8EXF7ZQbqr9HY%2BjGu%2F4SKPtH079r3bIXpdvXfYiYiUlrt5SVQ6buSk8eRF7lisCHyfAEJPqCg0ZERYcw2Sf%2FTqu6EwhZ3f7QQaJFbODZSeLf0aH2ill9Puju%2F0J7J6%2F3zbM4MddrpZZPTf9W696qx2Yuk%2FXJ7ZOvZ6%2BG4lmEodtesv61Xqh565ab9CibuQn7XeHjL1nIkU6hqkus05FH0viN2BJKwJFV9gjvd2HXlpDry%2Fgq1SUwIBOYx%2BT3V4jL9pjfsnHhMdG%2B3zQ5NLt8%2FKcq%2FhIwWpkh3u%2BZekFff65V6M%2F6EsPgiJDQ5KnBrfVjidQLzzfVJm7wmVO%2FD49qy8MSE%2FmKMnrWjY%2ForqsEZgjZyzzIIK5SCiKZFL%2FIWtfguOaiXT0sOc1u77F4%2B%2Bn72d2o424aSOBBkvAJLDOsvvLf0WFa2bhwTDsWBu6%2FDzBv0uoLyDouv8kbv2EVhi0Pc91f6P1r3pW4a81rNWVF%2B%2FL9xAib5tRB6Rz7%2FlvKxo6NUXf30yqbB%2Bx%2FIePjJna3d%2FhExqNcyBODYFFdWE9shBzY11Lkp5zlK4J7NASMKqDzqIt3jPDzwjkBuZwStD3LiGE9Lv%2FEWpLjqD9CuenH5BmOnvaFkSKusvui%2Fvv6oRKrBJeYM8NHuVLHAgO7XUFkJWPIDiV6S2Z8qKWjcs9H%2B%2B%2B%2B8nrv4jMyhuYnO3v65QXFe%2FOUeLvRuzODAZyHbuSZTB9%2BUEJaHetKuCMo2mfZZZPj%2FCRowVfE2JmO%2B%2B97%2F6PLtSVXLnr17%2B%2BT418UKHxOa0QHw6iHPlF9W%2BenKIKCNsVX%2BZihv3vq9P9s408q%2FsEV78nCnfvs4peGE6j9oX%2F8m3ejVX5yCMI8L0VVKvYSOzfy5333k%2Fuy%2BI1Rel%2F1WqvTllFSQ5PL%2Fy%2FX%2Br%2Byldt%2Bz1%2FGh8GFsJ3rp32cixpB%2FqfFZfxql3t%2FsksPvsnKaXZo%2ByeR%2B3ZtV32r0snKXRhhpu%2Ffb27e3k8nJ6K3ayr0V13ynjNtzX%2B%2B1i71F9Wxj2b1a5Pry%2BI9C37yen%2FSsntiEkvZejfK%2B78s3l6HRJe6S%2B1f9cq8vV%2FItd1fmyWia%2FWDT5Dve%2BpLRIO6y6up8AAAEBkGaQpCqBX2hb%2Fq5Xr36uUM5wv1rtXqiFr%2F%2F%2FomW5E9fS5XOr9Xf%2F%2F%2F%2F89PJ92vV6tUv564ma4MaXvw2TJ%2FfxOlborqu7ocpc76VqFEpbu17q617lm4lYrtWO%2BxNkgbySQN6vXv2JIWXYNHfauDItbrRWLrVIAjJiPWCvQjKn61Zj5cpXkpbyfr6%2F6%2FLxh%2BnXu%2Br06HL1V9qW8JatXO%2B63Xpb7r16I5Va%2FqXlXviV6W5L7UoonluQmi%2Fb%2BQhIfS%2FLd9yei1V0K4Qv8vLCIuS1sdS13d1cl1a4d%2FrXurHzT%2BFqJAbMdBUPlLdTlQv4i4q1b9fXVJ69XrV%2BCQlOWOVeaT%2F6LqXwsTLjx0uMtrjY71v%2FXlmGUbBnIJvRe8uT1i5ZuaXxZC%2FjY0dYOBn%2BCcmwMZsH3Kk6y%2F3%2F6EuKnz1%2BMpj%2FMTm%2Fwj5NMlv%2BOHWgO3%2By4cvJ%2BzctP0WLb8t%2FrUX69J6Jlk9V3wT0CWkrLbV5CshmnXmIPxOQmbOK5f%2FlV%2B3bJD3%2BbEK%2BrrwzoZaRL45CqS4f3qXrynTdjnnriK9e%2FVpyfv%2BMFMRfwgzlu5WOEzlLWvZZDZDQ%2B8CNr0bE33jnvV%2FfeTy7XryFbHInR7BD6pObfq6uJtcv0Xr9ev1avWK7IayMnTu8FcV%2Bf7y9z54O%2Bwne%2B29e%2FLRprBMXd8tLDfZjNz%2Fu7OVZrboD%2FYY81GCml%2Bp%2BQfOMHDUz7LJK%2FJbRevtW7%2FXpfVnrXq2q%2FsxuOkTfYal%2FWH0u7%2FsvHzGl9fnruWP0%2BUpWEVvaNrsEhM%2F6yefVWUu5YK%2BwkfnstCmPV4k1jhx0IVbsPen0Vxus4mT16TiLvsEIl32NevfffffYTFa2SK%2FbPRX2Q3N9996etP9mjZonOMHZdJ9viqsNwtQF7ITQtrGaCpDGYdvE%2F%2FXnj0%3D&media_id=1254206535166763008&segment_index=38" + }, + "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": "command=APPEND&media_data=61332uN3u%2BMnkvvsEcxstF2FOpMtOT29TasnNLvsUW7u7v2WUxCqgPlWxRCsT%2BNoO9qWCQbd6VbRiP%2FISVFHJzYig3w8zqZl4wWT2Tk%2BTx%2F%2B2fUqS2jCBJobLqOeErHP27v1RP3y3L%2BhMUkL3fqYU7%2Bwxxz28Op52sMW4uV%2Fs9fsTyw2W7%2BwyV7Vfw93fZ33t1BCU%2BB%2BTT4tb4Xmyt7trpm%2F0Ovff4Is0H6rXVuQRjZB16OYtt%2FrTvv0WvxYjiuk%2F6P13L6kar77IIqz7EFm%2FdPsmmvZab%2B%2B%2B%2FwvJDIkm78GPhlvUTYVT7N5fsXY9EqjknV%2Fsmk%2FyXv6rqW16tTH3R1K%2F6vdq5Q6UQ%2BLtYruTVWVfr333upfW5VryVKnSrrJ%2B%2F4ZO76zbb9eCEdeej%2BoJJqd93rFz6vsVEl%2FRFa%2FV36titfr1X%2BtT5Pfd8TJVfIuX5N3tr%2BAAAAClUGaQxDKBX33doT36933d1axTevzq9taumX3fd2rlWsX6xfrFLy3y1xFWvVa%2FO%2B6v9WJfBJjQ6fVX38XilderkR6sfrV%2FEepbvJ8%2Fak02bSs%2FWXtf7DdG%2BykxzZ%2F1l6h%2FsyhAEJHC4f3u7HxtveUUxkFf62HwRSsXuqr4ivWpvXp%2F%2Bl8rlmu1%2Fc67Mn4vkq5dE0OWnStXvdaod2JOLVq1ViuevUifEy2rpvIYymn%2Bi1EX2spB0szuiVrrhTTulVlZfRPc9NjtfYpXEeuX65RYrkwxvSXUtE1avJ6sT%2BuUnsxRqt%2B%2FP1pV6LL2Jr%2FDf2r9ek1V5vXqv9e7vxZB8ZKB1Do0K6rzcmNrwQlZ42XDq%2FRsKuvRevVel5ZPVqwjr0XUnqdL8gqfEBNBAPxNhjHB2BkUe%2F0Laa5fVu9HFyaonRnsmWTInlKTPd26pa9Yv17vbq6JnaXnqXE%2F%2FhfnBAFyjXdfbHXp9onScT81ej5fr3o6zqz17vun%2FEeQz3%2FQlgI8N7x0LCv4SsG84F9cL9XSeiV4j7Eyy3PVxV0X9%2FktEYC77k5u%2F0WKy%2F6%2F5MNJdDUbzH3dJ%2BS%2FxRsfecJYyhf5pBWjG49J9ei7RenuJ9E13L6JBI7z19Mu0Ck9%2F3QvLd6J0V6Psu0M6rXWn79eu1S0n4jylw4zrk%2B%2F%2BvdJLu%2B7RdW3%2B72kWrv3vxYzGfaK8Rv2CTnzBfoS78WIid5c3Jd3XoX1etV6vJ6wX69%2BQ0OmKfLq%2FV4ZnN7r45T691f%2BeqJa%2BT1le97guzWufM0%2B7Lz0OY7k82fL0%2BrZPf%2FZJ%2Fd4mhbn6sVay7k9T1k%2FP8291vVoRX4vmxqrVJrlxH3R5e9l9y%2F5e%2BfuJv9dVc3X6uUrqT1aa6ut8AAAAMZQZpDkOoFdcX8naE133%2F33%2F39%2F%2FrF9f%2F%2F99rX6xf861%2Btf9%2F%2F%2B%2FfX3k%2Bv%2F%2F9Xr6y%2F1rtavb5upVTrddrL5vZlSj5lcfXXfzHxeJd9SMrElJUtVrXUr%2BxS1Jd0i1Va18y16XxXzfq97r2X%2Fic17%2Fq3YLrpWb2fWnyES3dorDZ6xjTn1lOmX1dJ2r1derd%2FIvfr3oTVNfq16V8RZf%2F6T5NK%2B%2B%2B4i1aqu1aqVavmWquvWpPWqoxXr1r9crtme7r1cr0d%2Fkl5MV1tYr6Srl4yuSSRZfXvxBlT9pyehOXa4V6v%2BuXl%2BqwV2uX6tWqtN6slvuXcxONMvo8Et1931IjmKWTk7qiJLv16bzEfWX7%2FDVpmvpt1%2F4qK2WSir1TF1fBH0r5UTzyVcXD04Xb4O%2BHz4maiXKoB3zd3d3V10itL69%2BvSXfm46MaOanoE5s1z5khhJKyu7%2FuUjevRO%2FFcuEI3lGO690cuEl5ZLR%2FY7y616t179W%2FXJEr%2FXru8RpbVFJHROPBfCcsD4gsa07%2FCZrcqFz5q0JbtlKx17EB%2BfR0IuN%2Bvd%2FfotVd333E9GIjdqi%2Ff5DpFow%2BvchI%2BMnl%2F31g3v32qUNghKcvSnTteryGjOjp02%2Fu2j%2F5LWkl%2BcSv4zcyXVPV%2Fq%2FVJPL4oVJmjIECWkRJaspTUV3PZjvZ3f2idJyyevT8iP3urB%2BxTQw%2Bke370t%2BrvxIt7ekyRb3P9iBWXD0Oo%2F5tur7%2BaXSm9DZSWiPN6I7fvVrKy%2F3dX61Vnr8Os%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%2Buq1vtjUUEeXwsF2RPojdMguvpB%2Bap%2F95B5xhFyr7%2BrzoxiOK%2F4NpUF5ciSiAGgW4HNxHU1siosdx7v%2Bt%2FXfzP3vUf%2Fzp%2FurfXZm19Hsx776pIk%2BDTV%2Ft%2BqemfCaR3gmOk1NiSCMnE6dcgHAR4UkCwUGYVCwYCwYCgYDQXCwUCoWConGgVCg1EgYCwXDIRCYRG5rnjnbfx73znEknHatNZinN1NXE6GtOA7DoDn38R9HK82dx1HC30%2B5%2BMfo6JEIA0Do%2F%2Bfcqn8DJT%2F%2BPycMfmnJA1jWHLsFf3jEXPbo6hu%2BlKnRBWHudeoPW%2FW%2FYEsCVd%2FefJdfKDhrP87c17xmLOqXrJeXHMt7Byvu5ER2uzjysc5%2FI7uENf4Pd3Pndz972ZzrcdSZoXVWckmgRivMLugBZiJoBmqt7iRya7yMHHhmyBz%2FU5EoKo0zyaf4zCJVyssIKLd4%2BQPzsDgASYUkIYUGwUCw7CwVCg1EwVCwUCoUEYkKoRC4RGeHHdX7%2FXbnfV1d6zmtLqqZQ41Vuh3fyTdtz%2FQcc3fQKeno5LX8uyQ7%2FcHoZXL6KPe7ET%2FsnPt%2FV%2Fifacz4Nv4rDHvRR%2BjBhfaJyj0f5LecCRjboJDU2%2BYzWNe3cC8m1h7cfCOmotYemwxtdh9ot%2BoewPC8jB5uAT1GPlG7OyvAVX0OtN4z9S9osF6b7l%2F%2Bt30601xPvl3YPn5gK4PGF%2FiA8scARCFM4O7sAQh1LkqRXkeuwHAASgUkGwVCgjC4WDAXDAaCxnCwXCwVChFCxEC4RC4RGc51zN8%2B3i%2Bd8Lqe3OVJKGKOItwOL8Y3ngXc11oH9I8P1Eiceh%2BPBpss4QlXSvC%2FiYT%2B7TgPJMpK5D%2BgV0aUqBQTnYo8HXRF%2FznQS1%2FUWNbhgFcmGxAoqyOxVa5aTqr9qxC%2B19cHIlPdDOp0B6%2BlF7dWx5Jxp%2BKDZ260XFAHRREBa%2BxObm5EBhYr5HplBxgZSC7z%2FS5xQGovmYXy313AD61QAz%2Fv78J%2BG1fesg1UFF%2BBtBNS9tawV6RZYZikt7XufmDjbMDgAEkFJQoFRMFAsNAuFgwGgsRAsFxMFwsFBqJBMJwqEQqERvFzt37e%2BpO84uqe28q6ipmM1NWcaD3f0t9Lzbd8mjp4EvZ8LNDv1DvfBnskkqbP9af4uQajsAu6bgs4fq39W%2FvdiznrI6vd62a9WfgU2407kEwj4adTu6e%2BUxNwDXXetlCsdYF6Xp0tCrS%2FE1Pw9wN33sudcomO03uPR3kDTh8W%2BkjhPq%2Bo9DKccWX6F4H3z7ai5QC%2BNskltkEjXqqa3suyG7vw9dKUAeyQAItDPHRvvo0qNI19TsoCvq2aNvO5b5FLfLa8BVp1pkI15UrcV6RBwAAB8FBmkQRCgVyp6%2FQvu1arXrvtcror77%2FXv17l%2BXtWH%2F%2F%2F%2B%2B1Y7Vx%2F9W7%2FXsZl7ydLld1fa1XS91LLrXu1751bpw2bOQXXB%2FqWLfT5PD6118Tr69s91GMy%2F%2BbriaHTudEXif174nl7X%2F6%2BocqTL6XKSpWO1Z1d%2Frrvr5bsEsfIkB8CDWB%2Ftzub69n6Iw%2BCHKC2ZFGZBT%2Fqx2Ca7ThpM4zY4D7%2FlgGvPLz%2F2a77tWJRS36KxV32tVf2vV69N6uMlb%2FQ59PWT397MNwhcn71%2BCHdm%2BvxME7dOeQaFnmz%2FL4hovSXfoj0KW%2Ba6WT175rv4jtWXcnr1%2BsqtYpPXu1dQr7V57Vp6VYpOVZcX%2BYyMSj%2Fu76kd3zL3xi7dFfFcTWq9xPTL30vfq1DuVLuK9WNyuLJpAN9v6sdyCwWwRic6R4uK0TGSWv10%2Fa9EU8mq9P69%2BrfrFVSJhk9%2F65Q9HS42MAeQXjLYQx8RaSHCyaSxseSpWy7%2FUOcdLpUWeI8Imnf%2FnpA%2FjKKc7sIyEhlo5Tdtg0DhjLKGWx1S0QLnpykEqhHmqC%2Bl%2Bi4frKr7%2BeW%2B65pNVb9a%2BI%2FVjoj0vETdgz5qOZclAm4dy%2FsN9Je%2FKlaDS%2FXvcFRQxMaDmPNVZdfjeNj9zxHzCD%2FDRjDFGISUBq0Omj%2Fr37DFzkeS9fhxmn1PhupqZC%2B0hMakNdoKl0GWYH%2B3iQb%2BCJC%2B8b77%2BGonceaGSLmu%2BykOW9Ax9q8kpLr%2Fkvk%2FRXxX3VX697rFEY%2FVPr3ORZkpofyfR1%2BGrOhNHNKMTXhFi%2Fj%2FYJyBLxpUA6RCFmuLLsJf%2Bssd4bCXoX7sF5qDDqfL42y1%2FCb30KS3k9N%2FD1lg1i%2FHgQRpfkoPFxqhNWpVC9D8qj%2FV8ry%2FFu%2BS7cWQohDTNHaMF31Vhy9Axoulzoi79O2EjoDCDXU%2BiX9IDrdRFZSaEMETfaB2K7lp4sGUlyfJ9O6a8v5ZPRW%2Bvr6%2BvrUlgwEbuzSKC%2BMNiCqaf%2BG8YXQ1Gvz%2Fp6R%2ByeVdqCAkeCpaINmkPD52jIiMVZwEyDjAf3Lh3YNejDi6VpJE8h4yUYLhvsVbKOCjAX7egg%2Bn%2BP6efPYTPu93%2Bsnv%2FMGaIPstfRfOWJtLYm3B3JXf2GhGOPqJfH2Y9mf1PUppcbP8nuT%2BFbqPvPZCXr8OM7p%2BkvPVhNH%2F%2BcM8Dr2g3e5l9o%2BfOXu%2B0fvku1Z5PctW56sn39OKEMY6PB8BHrwPP6KJfJ%2B13jojeh%2B8X8WaX8267wlw6NXz50%2B7qSw%2FUGhsNOY%2F%2Fhxfj%2F19mES4O9cnz%2Fnqasfl%2Fp76sK3wz1IMFSRmhJsfL%2FdkR8XymqMVd5E5bOkemcN%2BG4HhX82tfDh8vxf4bwJqXMZqwauuetaqpF1MTw6%2FcKfVQeELrYOWirMuvxo8aB2314Zh9ye6mF8kPk%2Bv7F1zY73%2BGsz46jfNM%2F0X21pP71vhqA93LA9pyziC4gqDsfa%2F6hOqa8SpyffSjxt2SN6OivVoVFp3ye3vhyGNS6EP7UeZ%2BE3DcD99NHxfoyowI9b%2FNxU691SzWi1JEo%2Febcnl%2F5W%2FzDLoIF2mt95uP5fzZf%2BylwwcmqzCb2vkFcYlSfdfOUpmLJN2cQsbJb%2F3ddQJz4G%2BPlAY68aCCd%2F23UEHhpaywhtogLmJFzWhNF36egibj44ds5FhBJX3RJqdPhwXNLc%2F4YTks6vQZMijWW59CnD9le2X35S%2FLd1X3cVaFfx%2FQ76XS4v3EZvu2EGrWfoRZLncHgoei%2FT%2BaTCZ9znU0V%2Fo6Rn%2FIdIMt2f4Zrhc4ie%2Bj8vnq%2BldkMDFNEBbL4Tmh7SZglyfj14TJjLLQ89JPe73LjV4NsS%2B97EFG1haCvaHF3jKYTM0uoLhf%2FYSkU%2BbxYMPIGAxoRHrEWhpo8kpQf3Bje4BnJW6nsfKmxNt%2BhYk6TJef3VJLJ6s7q%2BO7f4JxGYkEnF7kbmft74K6Zv2d4e0egKX2KoY00WEGYYLBXZ56%2B07XZ6%2BMvVe8%2Fk%2Fv89KeETFvl%2FOG7xGxnNfjPbYa%2BjlXzhIvo6vCV7dyRH4um%2BCYS96O9yl%2BQVJllJ%2BVVuO0CQMOsuUTI5%2F0CGq%2B9Hirc%2FsHPjB%2FE6He5iTYfBGcjN%2FdjjN4mxHyEpaPF5mPG%2FH1bXLmsFhlW8VFLk7l7XLq6buTP5%2BLq%2BO%2FxQgcF5xE8eBU%2BSLzYF%2FTL%2F7hUoJXz7Y%2Bx0N9Y8icxQPZppuP8N8Gv63f5eFawsfq1PYMC3fPmoyk8L%2FJ5L1TlI1%2BfduCImphspbdw%2Fd2kvNLDEzd5tQRxl%2B%2Fb4JCatOfjBs%2B8dLh733d8oTtyUg7BBuG8E0W%2F0SfztKkMu9zFikoD3faez5QiMeUEASD0NIQV3Xx%2F1SuIKUZeCAPOQRov%2F3ZX03uS613f3ruTsFBb3afrJ73Lf%2Bvdq5d12r%2FrLvv8ERnf73OZfhzsvX%2BnxJT3LpXQNqX%2BX1c%2Bsv%2Ff9ZPuu89fzUCPBTb1vWkoS1m7z%2F8XBTJn73%2BSjTV4t63hUEMxB95dvjHoXy5L9k7vb5N3rFIXu7jJo347vtFfv5FaTvFKXkr5UWDvvhvvbuxEYlfuCHu7GT1vd%2BcJ3vn3f1fp91v6173d%2B812Eon3np6tXu73V5M7r1i%2Bl6T0R7uuLqCSReyeggmuiRU%2FXAAABahBmkSRKgV30hLSDPahH8UryeuUk%2Ffa94c9S5dr3%2FP%2F3%2Bixe%2FX30VxmrnBn%2BtSVfonSVLqS%2BiP1qstUoqNDfjvmP4Vy%2FB%2F4bq2T9%2F%2BDrPcsKG9obP%2FasS3UhHdilSd3zcvdCvu51115Pz%2BXyQrhNrn5NCnf76IE7Q%2FXsCqJcEEaQXc99Ud5i0GbU%2F%2Fw73GTpHtCOQfdft0MN2L%2FPUaiGov%2BT6drwW2cZlNH70cJl%2F3wRctJlilfqn6VrtXiLquafkVE7tE7J8f%2FZydGpdX%2FJeuTzr9DXCtFyr0TqozuUn3%2F%2Fq8nqn9Vgl9ek9e%2BJVv17te8V7uc%2Fvwqzv2jeOTq0eXPW%2FSL1Dl1il78Kflmv4mXS8vx%2B%2FXVeEzUrjzX%2FwlGh2fcf%2FoE6kd%2Fl7%2BEfQ9dSZa1dEq%2FaxfMrxnSv83JLrc9fouXaJFViDUKVcyjPfUj1d1hmvf%2BTfq812X5v5L77rUEhObGGa%2FGWEM2MBtoWlShod0DjYQFVQZ71Aho24DMICYGmJTBGXNbsdX4kxMJdzXBtd1RGT3f%2Bm%2FVdclWjurtXqWt1qS1fta7Wx2r%2BWeukbfrskWZI%2BZzTI3oLkqRK8Vei3cYW%2FUQVof31hdMJfbh6fxo%2F3EGaZy0xZvf4L6SU5IZaFjX18MYN%2Fk%2Fveid3k%2BVG6ctg6NbgygyUFhQZ2qotKCFfOtykG7HfktIZK2MwGyaIC%2F460bKcNrd359QJfxKK76WpOeriLtuuX8ldmzw6hRCGMwHvomm857LY316G1k%2BvWwiZgYchef5qYy0NMdjagjRr%2FTwgCqb2kcMfL88f0MoQW1giVGiH5VHyf2v5PL8TFkbJmlfydPkOe2D%2FiIhybmzaQSX8K3QJtC5qiPbOpbX%2F9eveEvD8Td%2BjZivRGPxZ7nSP0tD4ra%2FybboHTX2%2Bm8nn7auzfvb7s2Jr0H8QdhDEf%2Fc9PvaKR1uINozF4cdFpmT2aX9y0XJfJ%2FFvr4TsTn%2B%2F6tE67WK4lffPLCdYPO38v3%2BCw2HKt5gvRRyPcy%2BO2aa3gHPDJ6%2B%2BaPq%2BeMmKnosrD77BOLtvfczhZpfiTXuzvk%2Be668nlz5tg3UlX4Z4em1r7U3qF64mXJRerpemL%2FG%2FU1k8V%2B%2BwmYgwTznNxsf3k%2B%2F8tn%2FshCCOuS%2FJtEzVnKv8PE%2BvzFlUfxBJSVpTYen9kmo133%2FgjLbe%2Fff4JMtjQyRRV5S8NTz1dXJzS%2Bj1yoztGExF%2BTHBcDvYk3P74%2BID907%2Fk8%2FXmOH5evqvyynb1S5fq%2Bu%2Bxd2WwkAjv%2Flkwxia%2F4QEcepZbJWyzH3U%2FihIYxcAXoZc6umRNZvCW9Y%2Bi9fESjkJtSs%2FV56%2Fi3%2BY09b0U%2FP%2BFTZdzJE1GWrR1cwgP01gn3l%2BXOu%2FzW1G7n8x3v%2BQ0rErH0XqpMnnJJ%2BjsxoZHK%2FsF%2BETT2JeHfdWENpCT9%2F5domfx8cZOo%2B1LQbMMqi96%2B3uDAShAPvskymh%2FhAtykV%2BT3x8hfngkEu94u4jVTJ%2BtdJvdlXt3%2Bta7%2F3eUVyQs3CFBnEBYCS5e0mb5j%2Bil%2F9ydHf5Y2Wf63%2FzUh8idL7on1%2Fk3TrzFzvQ9QRzqIVZx4S%2BbqsNtUGmuF6BCTZRnl%2BagpMYS9HrfqyNDnvUc%2FwTPtwqfXO%2FBkT1o%2FS%2FLC5BCW11005scuMF%2FBR0Szys5XD69%2BrBeQ77X3Rv%2FPXyJbZrWu1r%2FBCWm%2FvcJ72b7lEPz2P46v8gxhxsuN%2FZXHCX%2FmK7%2F2SIcfk%2FF%2BR%2Ba9i6V9q8nr31k8%2F%2Fl0r6Wurr5L01oS1%2BIGY6raY%2BRNL1%2FId9O7rst7sa82mlJ7IYeKCn%2Bt67917SkvjNTRCsn%2Fk7u7vevR4qte9a9cPiKhd33RPpfql63dXJX7%2B5DO%2F8EV33PVEc9aqvN7lFdbo%2BpJUdKBEREK%2FozHV%2BjwS3VrBz1aI3P%2BuVwAABHRBmkURSgV1KhPd16v%2Btdr%2B6r9XL4m6N%2F%2BKXpPXvVcP1c%2FXL9ek9WKv9XvCOtV6%2FUt2rK6WpfKTFn5Or179F7qDmYkUg7j1wxo2LJjpYWkocQef%2Bv0dMiWs%2Ffcl86p%2Flk5V6vXu1dillpv1rL%2FXkIOtY2Ag36JCR0qvWWqub6jAYWDHWV%2BGJGJacjU1D5vr8Nx1q4l6jcunVaRpEW%2BGZC8uB3NVNsxjG0X4GvywGv4rOr3%2FLaL5fq98Wve6s18ZEc0t1aNl6hXy0uWmomZNv6HoQ0nRTSC0zGff5xq%2Fbl36sLugYQyTrkSU3Xu91LItf6n7ucnnHforc9eid%2Br1VJtS%2BpAXiyy9HynoYz%2F85l8pkbl91do%2BeQV1zcirml9ZRVqcpPV%2B%2B2ZFjupPR41Wtdq%2F6yk9SpVrdJ69F3d16Ll3q%2BvRO4fr1e42bdek5pOb9a%2FVrurKS99my0pbDMx0MXWI9fir9uHUL6WhC9HY%2BUu7yfG%2F9sxCW6h2ubvzqbpHZVUlyXXq5V6XzCKUCFrK2%2BLr7II8vT6sIUet3n%2B%2Bxx40X%2FXNFB%2FYMubET06ASTBEH9iDKcloHIPoHcn175Z5%2FfZYwWX99uXNraE1fqzu4I69ak9ar1f9alsIE42bMHe5knsfR40Jm1G4WjRxMPw%2FyO9s3D8SG%2FwyJHTR3f7DhuJZ%2FglLly9ysRZPH3zGy07BcRAgw03mYpxdgwLnwPLMzqLgpkxpHF9ufsfDnLR9cPxQf99%2FrKv657ky5r%2FRNd9iC5jJ%2FhHNQMn7NyGKe7sVjqYuXia9D33XiNmNlnVs77BF5p4diqB4%2B1LD7zcNQ0Ms9ndWh81%2F%2FOdfjw3cy%2Bid2vXa92tRFonbv7C1KZLIvHRMwnHmnIi7NOZWwPfaF1k%2Fq%2F7KIlz3%2BCK97j5OrP5%2FcqQt%2B%2FR8uzmX8eL59fvu%2FqXa8f77%2BZFrJ8%2F6yiL0%2F2FTI55DRAdhDqF1I1OjHBg%2F1fffeTx9%2BrXDshE6fYIx5cpJOq%2B%2F0Mw%2FRcoq0U9dr3fqa933JdWQUPGPr0J6%2FVj5%2BlFDCKZFLp06vsEguezBbion5%2FlMRhGy%2FBEJnjxfojguL%2BfTsTR2kvtcO%2FdHYfBGZ32O6urKRDiFjuvBJg%2FYuySk0%2FViCPt249H2%2BSXDgABa5P3%2FJjVj72%2F%2BcqhvteP%2Fw2JNPay%2FpF0Unr8m9%2B61y99lFI8mb777PVu2Nid%2Fd333Xmk%2Frk%2Flu%2Byl0Zy%2B3T096X%2BXuvMXd9rlzE%2Fq%2FyXP3V%2B9akFPTk9HYPySS%2FwX7Yz9mburDBBoUk%2F%2FaJ47Dk2cqcdfKoIn35xLklt%2Fv0TLdvvcuvFkVqjuTP5Du%2FshZMvten6Xrj6vb%2F4TFVfdIxHdXu8hcsK9Ux%2BGiPuvsw7F38l%2Fk400NLq9vnqXdPzP6R0k%2FouVM%2B1yKuV5fuhD%2BX2evoJs%2B%2B%2Fz1%2BhJm36u%2BmV7xHuQlver9%2BXl931ZKN0pPz%2F%2Ffd1aEuFzUKz4qlbz5sQq9YqSX1s1%2BryClfhDJuQlm792ZJP%2BW78AAAhtQZpFkWoFcnFdF3UhPX69VU2111axV69VXfMb%2F%2Bsb475O1i4Jeiu64ru7u6tTJNkm8Ie9b0ev4PzXKvfgklHnYJA8ve7Vvi17FeO3OCulMna9VCdBLsPt%2BSsv1%2BuXzVoRV1cpf3vPX4371viMYe%2BQPman6yo8EstludAvuxvbSC8wzmhHn1tVOs1%2FX4ItxlvbhCyfdf%2Fh%2BzhwZrp0VIpffQqd20gfjRI%3D&media_id=1254206535166763008&segment_index=39" + }, + "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%2FYbnGVd%2FOu%2BT8X8%2BqIo54sW%2FKOLb7fNTz0D0S73G2tPfOIMfBXLTBviFIwqHURNaB%2BIxGwewS3EXDGg%2FuXH0Li4%2ByHunCB7lF5PR%2FwiWMj4h9gnh5zEtM2O%2FKnwhWBuWaqh7cMlG0qYK7l9F6rq%2FdX8u%2FXptrz1i7ITc%2BSeLrki8fBUMRwf0XTvCFB2W4XIbODHbgD%2FU2se4Q6x6phzLo4loUUSgNOvyHQeAuVuE2DdLkYfpNB%2BJrAhDqW%2BV9sP2r0A6oSch4jnSyC%2B%2ByZOYfYQTBTYbPdo5tfh9fj12XsLHvd2W9ulPkj2nIqPBGI0iZlk8HJ8GBAk10hZg0S1uksI8JhcZRP6Fwn0jUOv5PC9yS4xKQuxTeUJHZgOt8V%2BG2a1ZR9ScKP7lo9%2BcK8l93Wig33PqTGflrS%2FVyflk70gQfV8eGCbto3KS1xoiKRwfs951DLX9YaPARb8%2F%2Fn9GvzLh5zw5Pi%2Bmg0RAQYglnWEufuuVYwvFyfhPkh662yXtIJ3J7OKRr8V%2Fk8Dr76z5SKIfFuP9H9YXwHZyZDs0zWpmoOC8e%2F9xHhvvdV9yL%2FsQW0NssfHBQW9Gogw0ktz3ZnyxXBDnZlx9niLSCU5EZstVHxehcmYkOkFT66xsR4DG9A7PV%2F7Mc7vnE4i%2FuttWnv9cpN%2FE%2B0M6ieH2oeLO5jXmxqslMjoCR6wN5JD0DDrCZAD%2BTEf2eFoIvAbGaK6D0WxxtbETSgh6a5urwDYeJ%2FRWpU0eCO93y5ewmVFfNnR4uzHvbT6n%2FfehL59%2BI90gtQ5S3KX5yEcuoOVQuevghaYobO9f2hdQyV7HY%2BdfY%2FqlqXLyf1c91y569Wu1b9X5tXO%2BziJaIcH7D0hIWo%2BJCysEs8thszYZIw3wdhsowCfabqcPQJn47%2Bw%2F9nNqDXEhrBsKhz%2B3I8nn%2Fk2iZ8jyfC%2FWmiSid3pSoQRmDHa%2BRrx6ecKk2Y%2F7Sn9bKJX%2FydrpmK7tafBX47KxXGDx%2FW3NCvLjgojSNeM%2BrSjxU%2F9iuCSP%2BQoQL04%2FPX6QyRGp5o9fx7vfXUVdovdJPffiNR1oyT1hD%2B72fpb4ftCMNxOGC6BDL6ZVsNrswQTDCd2oGKxMDCiVcFjCjkXRLcf%2FSFnHF1AKlu7tYqNYE5A04MDqBILe0wskew4MMv18dEgzveqTHssPNxtEUPa97ihA3TYvIvQuzlxCcMI4ObFf2bo%2FbU8Vz0mkl5y0gmaBLRfDAiP0Sp8dC%2FA1U6svh%2FJ87rQXGqFrLw8ld%2BX8IttfrTwqaz5iUJeO%2FoER4cdrHS8V4Zu59vR1q%2FQr%2BR1pB7YDdwykChbvJERHr%2FfU1TfjAk7Z0HE2CLEQQH3cd%2FhPvbD0TkrgQH%2BYpP5PJa2wT6AoO6lt3sRrJ9EfqFoTGLvPv9b3SR%2B5r7n%2FYZj2W%2BOO%2BEvdeeWHv7DRg0luSE2b1PUdIvSK7%2FhzcdEBewtF4JtPN%2F2LQKuDths5dAJfcnWv9cQk8uiNLaTj4BdnF2ranTbQ11BEG%2Fhzb0E6%2Bcd2nhoRSL42pHd%2F%2BvvxlB%2BwR0T%2FfYasQ1Y6xy%2F%2FxUCovjjRfcblfcYTDZZc18ZKzUJHx3v4nte8wiW16777705pTT51ElYY58LSNjrwPCzj6DGAw%2BPD%2BsVwzQy9gqDUiFgcfBVGTw8Zq5PGrojDXHQg%2BmUGYmQm99PtS7J8Z%2B5ZtPnvVShfHSXiJiZM3X%2FCLF2l1qG%2BoRafThGL48NunrDk9P28n5%2FRd739Ct5l4sfq8Eg3nonD4TEO%2BekIXGyuTxyy1Bfgxxs8uQ4xe5TlogH%2BsSbw3OuGxiddC7Fwm6%2Bwee07N%2B9FWOzUyYI5l9%2FrJ95l%2BxTfel%2BhdS%2FV1ZCnzdu3Dg7CXLrgzCQtF%2F0uSXcYAg3bSQdKBmhAf3Jux3r8bE7BoyWYhWaYmj3tJeSbu3J9e36H%2BXJ%2Bmp%2BTxz0nkRfhzSuvtsIfK3sVxZGbd3f32xLItcntRP%2FhEzHRDgX4hGdhGhHIPQ0Iio%2F6r5cfEgiKST8Xi2SNe9A2X%2BXFsxKpL6BGe42v1PxAoJls3vT9f1qsI%2B%2Bv9ZfrV5fFkNipcn0RLrk8N1JOZn2BgV4gmhUXmK6Jg3t89fHSWStzetd%2FNnr51pc5s9fyKB25nPX2dQbFRWYst7%2BSKz58apnBMQ%2FvGUx3JVil2TloWknjneVmmInJeIu6i8np7vocZBCfe9eq1x%2B3dEebqIxHxS4QtG%2Bjz2P9Imyfpv%2Fvl90%2Byne%2BT73qvXvu7Ym9%2FoV2w%2F5wRkj%2Fu5xOTxdIlvvcIX%2Bhb%2Fr3d1d36JhJaK%2BgI%2B%2FVL2QjM%2BeE1i4j9Zbv1ytpfv1ZlNS9z%2BAAAI5UGaRpGqBXd7%2F5a5unriOuru7vvur7790LYq1yiefpVrvta%2FWv1qvVj4v2vl7%2FViXsvDTLNJeda4rRIt22L4Er2Prp3HR1%2F33JRO947u%2FRa7V%2F1qvvif1w%2BJk0JkvS2unwrHS%2F9wBPjEsg533qmNtGhNB7NHvJUF5LY%2B10n1%2Bskh%2FOFd8AMW%2BLT%2FcHIKP8Ye0OElPk8%2FyIFnHh5e5CThF%2B%2BtPDstD5KX0Tw3a%2FbzK3Yaf3JOFvxs44KYkYM3Eevlmmnzhq96zMRgzu2evFa9Fcod2%2BJu1il6UiVtTVVtfq1evc36KcRyI2u3G1Hvfb6M5Rf8iv1CY138bX7ghx6I7j2GYcn5ocKevxkEe%2F1RW4TqqW0TpPWLu77l4iTdcK9XOFn%2FVt5K%2B3%2Beo01XS%2F%2FOcyu1P9%2Bj9dNVyClkuvXKMvv8xhounEoD5f%2FqvR8ryb0P%2BLktTOqi61VPJxdeusc%2Fq4n9WDyUWfiGFiNobaMfkhwu6cyR9V5RBh85rzhGdf0IGcutOaH6FvV1Ag91PfolVBLXrF6E1z%2FrV%2Bsq9XLuldgkI583anwUZubNLeLWqYyGmvK3uXnsmZVlGrx5rFioOwrUJzRn39BHwZQbowlaBXuHD6N5f0hM1J4N%2Bo8RMppksmfcPsS2JpjLEfUs%2FeoLGAyTo8v17wQ16oeK7upfnUqYFfdyE3xK%2F%2FVivVv1w36YJDJJF9F2vw3DV9H4OEvhKisiImJN9iZKW9310SOKPqRX56Xg%2B%2BWG7Po8SPh97sLwRSG96Sj50yfqrmQgxLto0gce9C%2BPvHCFJiTiWlB%2BS72lDuIuPerTri1xww1T%2BcNzkEdInYelk2%2FwiUH9g07UMDiI37jTIl%2BZSA4fwhKltckfEE9JHZ1FzRlNX5wZoXHO%2Bu%2FRu4Ru%2Fmr1arXpovaRqQl0ey7FUFOxOY2zTs6C5h0stSIcLPhiisTkN%2FLH6wyiia8pfJ896gm%2BFuKPCNZIz%2B7DIlnevh%2B2sbb%2BXk%2BjyRFwQYQadruJe9njrQ%2FV%2BWrBl3J4ZPguMMaP8TkQqWxSRJeSkHFoX2OORY7DoNN9WNeoiwRHPgFX5q%2FvsK1i%2BOPrpg%2BIPRydq%2F3UJbo0Dy02j9e6J3f69Vr3KvdF8Mq0mvL32xj371bnOuapEv8kK9JO8blQZlCEuJH%2FCR5DxQgGgV0WvcFBBsdGHs82eyf2%2BygwoGVI1z2MSvLzYG59%2F%2FBLolxQcvb1DMv9fZxpI7sryeF9qCDkUSrvvQ4xReHab%2B3IuU5VGSNp7%2FL6mVYTM3pXpWbhq%2Bm58ei7N26QVoGGUzdlpai1%2Fk8vTc9faHH%2F82%2BD0S4TR8r9e%2FWpBRP6%2B7X3d%2F%2BjdIpLD23MwRcFaeKFAOAMT1fVfsLcgi8IIH1uBtV1Pc8c2FsDgJ90B%2Fcn0Y3LhoJQyWZ0RAeYNuJ%2FVeDCWmfJmKAorY3L0SWX9XnsNBk8x%2F1BCJLDZd9hw2N7X%2BXhhdF%2BbPU16jrfSt17U3a%2BavNfWT72rNVj1Vhv3Dk%2BbTj6DHi7MLDAe%2BTZXvU9eveK9E%2B6xfqx86lS7r%2B6658ntqyWFxFhQY5GPghIW2dKM06%2Fd4JZJU6hyKOyug7Cy3DZT%2BMjNrw%2FLQf084ZMipkCWvxgSHbFZvt8K%2BXeI%2BasOsfK%2F%2FoEJTyquX4JKtPY6wQlvdm3wSkOMiwc5J6xkHea9t6RNZPe92ij3z0k%2BUldw2K1RL8f1Ko6VU9frcYPfs%2BD8N371UOVNUdNi%2Fy7QTXMkWctj4Kfo9z8YImtBo0LF1uj5XTfq1euV6XuvVfaN1O6Yl3%2BmQRIGBm8njfom5JQh5vHru%2FCkl6f0Ytk9qolMNicuV%2FDs1KryP0FKkcS%2F%2BNXLFzjOT5VacjQxNhspWKA64%2FrtGmmTke0Tur0g35oLQKMniYZHUWgvghOfPy7D%2FjQg93DadEUAqzl46Vn9gg8rEfHx60FT0DW7zUX7DYqilIKmUetx%2F%2BGhaQ1rYZY%2Fg399nIm%2FAGZODvDmRyr%2BA%2FWfS4sXEZcus0lV6fyfZulo7%2Bool7UX6lshL3ofyf15%2BGSUSrKfGdl6aiKUuJsbbwYEZEzDfLzZiaUPr1Zft%2Fd4rE%2FBjJiUZMZk9qXwycZPG%2FoknzMNRL7PX5E%2Brqf2rtXkMDfEEjK%2FNm2Bu9ORDOahs0x6mWHtuS7dS424hBqf3YuPjjFa%2B3koDYQaHQbG5gwGtXhTmEhjwEq67S%2FI%2F8thAy3kSO5h93vlp9xEubzsGk9n4WKFGI6huMsvX4A0g3TQNRzIEJ8%2FxOxVr3RPSd%2BTWRFNu%2BKwR58%2B3pUHCON8ny5pl%2F39hPVkkXJ6fQLejlpicg9lotPlnz2iVQIiny%2Ft2oX7SSRckGesh%2FFHmmOJEkgkZQz3df3CE1SRud3Zt7OnIQ9iTmY8ErVtuzoE5G42g1aD8XuUfmlo1CYjczPnECnL%2Bq0EiSZ5M2qoVg760VQYeMRdNDB2plJofy%2Bn1W2%2FX2USB2rm5jJ%2FObY6JETVfH1t%2F8EFz%2BIm8vyfeT49Pl9C3v7f4sVHH120S5PfXz4MImfUmzm%2F9YYx8ZfuXM9V6fFOonDAoq9T9JH0RsdHKsJjBfTCGev4CF7ve%2Fk%2BbX0V3Xk%2FF%2FBDH8fZ%2BW78v%2FqGuXusOt93Dv7tMEpMtC03eLcTgv3u7euZEMkTTDSTzJ4Vr%2B0LEu77yEZP7f1nZPc99foFgiP%2B7yYambOtP7q%2B6l0qkjsdu99QimQpL%2FJ6FZaL91OlT%2Fr3enSMMj5YfW6hzz4w9Aa%2FRh9a5y%2B%2FgQMjVQ1YZvevvhicSzs9fD9u4XeTxr0j1%2BNpQ1pC2ev04a7koorL8rPX0yKHTu3wv4h8viH%2Fa0bbJyjbB%2FOCOT48tow%2BSUZSMR8KiL8KR5c%2BTpvZMuDbRepIjNkXzUt5vd6ZKCYm6V360Xm4m8Rqvu9f2R90ny3Svs9f1SI1Aez19XY3U7Rcvrh%2BrRy36yy%2Fdeuw5aKarf1yffqvkkCHLnXyVi77l%2Bye%2F%2FVobB3k%2Bf%2F9EevV8n3%2Busv76618T9ZbovzAh925TsUKu7z5wAACJVBmkcRygV1aF9%2BvV6vd3c1qxXrXurfqRMv%2FfU69U8nq5fq5W6pk%2FXqur7WLur%2BWrXqyeFOtOsVMRnjr0vzTz4%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%2Fj4cRPrkvpyw50BgZ4a%2FjiRqvPoN8O80Rrg%2Br%2FrOUoPlU4yRdhsh4Wq%2FLBDMmmOu57C%2FJ5Pz5lVp6T30TYsuVdmLcIuL0t%2B%2BwsZbYHebj56mUmh%2FyoXKRLb7Dk1nc%2BU%2BUkHEM732Ug5TnzeCHcIkfkmOzZ3wj2vcq9%2Biv7E9E%2Fq3y%2BJ99%2BQnGWmhbDgyN3OuZM%2Bp%2F5fOr6%2FBDCPAlH9jJ971hssaGUlt64SO5z%2FJ7X%2BfL%2BRUND8v0uzl756KNHr2CPdKxrSKw0TPg35h6k1r8n0RUVOCeu6Ng3tt3MQuT4%2BfR4sW793S2CO73Sv2CgVDSZvx%2FwqudPoyzXtc%2B1dlDtZ%2Ff69t3MTPnWDATu76angv%2FLyeCbe2ixaHowqV%2FuI%2Fz0Nw1JZBRB4Gvp9evMgX56YQDDEz3%2FjyzHDRx4liD2%2Bmp%2F3E9beUiYljSXbdjk%2B33%2FOgUZ%2B9b3v7gt3pvd3ekCPdUnPdETL5ta3f50I0imPBov35Fu97x5oyhHRmYyEjktc0PJe16161Pk%2BfU3ui%2B%2Bt6V%2B4v6hC4Qu9TfRf83Vh339hYST97zjxlMKyJ%2F2L9L1cl%2Bi9wjqWX33urFcvt33KeCTuWncv0G9m7sPyantYu0Jb0prWu69X6e2R4M6KWLjf0rUv69WK382T1rqq1OlO39RAwS5e76gAABW9BmkeR6gV%2FoXly9%2FE9%2F9%2F%2F%2Fr3f%2F139frl3%2FyrXV38Sp0%2F7%2FWu%2F%2F%2B%2F%2F%2BQvv4QVj9WBKT5vmqmV65uvJ4f%2FyLLJ8%2F9Um25qiIvd9q%2FUiQeJFC%2BBrU3OJQlYO%2B3u2Ir0XX612rpaEFZ9K9E%2FP%2F9aurteq1Y7WpfV%2F1rvtEh5PH7PJBNpP5%2FzkDcdaHkHqNyPp%2Fk%2BNrsEOQIDCFgXzy8T0PbsLCIaX%2FLIZMaJfd0rd1MRV3v32ixj51f9WP1yu167riZulrvvd9E%2FZcxK%2BlenfxKv%2Brl7EeicPJQrtnUnfutSc%2FT91a1%2BrHawS1lHSryqH6PVXXEdJ3rm8UvVzo7d9UnPLxFVVX32tcDjen7mMklq6FfMnSX0j9WFdc8o5cpvWWO28JCeP%2FWWit7o2v0eV%2BIFRYosRF7F%2BGbnu6hvrq0f9%2BrpPVruvWrtWMV96FxZpf5%2F%2BCWO3Pc2Gpfll%2FXc150XEo%2BX4sQzanGsmDhCuxMTfQ9mKW0Jq8L%2Fl8RXK%2B16pVbnl3Xpalg3FVAkNRhKwexeHYKJ4c8ENcLJxS8u3wvMw5kGVmxMeEYGZeiaga%2Fr3%2FBCcea%2F7lOI6PtEP%2Fn2%2BTmYaxuT0%2FwuXHxJ1bu6%2FhFphPjQlewbKwZaNIKy%2FTRXvHZcme7n5wRmm9Ysnu79ByHkS3uDaAUHhEMX6%2Fk9nLkwuSOOgoFfHmrtX%2FWGEVXxTKyKP4fvQK4QYJp5DT7q6A%2BMi8Ssy7JPs4lf4bwx9UV%2BJBIaw4LMmMyemXqC4khBDSB0Q40IhpwYF9G5ijAgPRcpSDaZx%2Bv32Q58CNnnHzuuOf7C%2FKMvP42gX9zQ2j1Py%2BT44d%2BiPXrhV6BNu7QzLY66c%2FsEQ1GcMBlxnYSJAO%2F7lvL%2Fs1zF371ct7vJ6v%2F19kx28aQWLjijxZbd7no935a5c%2FOINRvgieHQZ2J7BpO99R%2BTsz3snb99o8V%2BvVa5ScRXJV991faFV33333333332UTjpEq332C3xDkZEw08NMdhblog6vhPjbvtU6PhD0eNdnHL9Y6Pg77KduNi95PiI%2F77CRtymgqmX999nEuP2xxK32YQhRYuyD2n9oU5k%2BDr%2FtZdm45EqyFvu8mqe%2FQlyR%2Bq11SX5UcQsI3fg%2F5PL%2F7PX8qsaE%2B7%2B%2B90loWdu%2B%2B%2B0FNd9nHr4x%2F%2B%2ByccBwMAeyiobd4r07fZTh1LX%2Fst7uS7WHejvVrVWj15V2hXc6Et32URu%2BflEEhxLgtdAiWE7h0Z%2B%2B%2BzWnOGfaPrblhckgYDOGY0me%2BGae3K%2F2C0s8Pc7HF27Ahsx9nsM71%2FaNXZtEmy2XDSw%2BzoL2A514bnq%2Bs8ypf9hzOm%2Bo9Lq%2F77777BGLPjOweU3rKs3HPLfrXtd9oRlz998%2B5rPUsY26f9mpYfESZvs9fhxx8e%2B%2B8nj%2B0isNlIVITr7DUdQcHZnelP77BIW4cce2O%2BxxmBMh1DgK3dCuF%2BTwk3yzjO9G4kt5WKb97Nx2x3O1%2Flbz%2BJJuxQjlLSmp32hOI5%2B%2FNVrusf3JfaFP3q82EzBSeilJvCG%2B%2BwR3uXsNosx2azv3zvTfnBLd75kjTCh15zGe7yeG%2BpBeHZ%2Fv77XXKERTdGsmfj%2FqFfvZ92bjnpqfMJdN0%2B%2Bl0ilvfLq%2BvV7zau1V95Ppr3yeD%2F9giM7G7GzJ4e%2BelD0Q0f%2BTydXw5Y311Mv%2BT06XLTfo1PXzLTMHW2iJnkuz1WPDY%2F28mfG6vi%2B1f9e4%2FJ8eW%2B36vt3Tk%2B0JahSzeiyrVYKi1PZPH%2F7759GvZhWW%2F3d%2FZylaMpCtE%2F2r%2B0eDtT1XUTz9kGMyknujdX8TVjj6lQnKsVkv9a7WXdwwI6Pq%2BP8bVzmnG2V%2FfcnVXdS95PLy1AAAB8NBmkgSCgVz3dxXSFy6VWJbkur%2BO6P7v1qbmku7VvzmX82tbR%2FfnsfwP6X617qRGaNzYI3mPn7onlX9eithImtr%2Fa3L9XdqnaFK%2FSWXzXatUq%2FKvFL1XPVo0Gx8E5TU8977dQvOwY3clJ4p%2BnohrvJ5tfQVnJAjZl5sxfLO36ceaQ0SL9xlw1KyfEnT87Jlwe3lBGUfCVVdhsN93ZqwxgqYleRHUpqJ9FTcBIFZPz%2FiL%2BaYnjT%2F5vaCHUltdy11MXHnx9nghu1mzxDiLRa7XpOlNVazHdcRdd3%2Brl%2BrhcvrodC%2FN65B3dct3ehN3P65dq13XolV3l%2BnrChIw107dnkvWvsnS6%2BXRQS5faQUCseurQnK6LVqu6u1cxyulRLm4tek9WkeTizcF%2FOsYrPkRvzLP2hP9NmQsUHr%2FS1o%2Fz0k8X7T%2FR2qif16b1ik9YpOaS6u70aouzbm%2FgkFWabWt1JAqsJRqwbSXetIDHxF%2BPvtjbkuN9wGwPqCg%2BDbaLzkFKOZPYv8YaRSHGLjRsv0EafKQV7WiRMlkhU9KMpCpJbtHf3VgrWvdau%2B6q7X%2Fa1IK3V3TL1ZJubFsVoEBsd92cuc3HS0MWUYWCSIhj9QJNtythurJ4vdmWT0dc7ElZg774lGSl5f9YgRGzVpDoI5slMhL0FTbNItONs0TDyu9v69QrZpVWDHmvVhRqKoMwg0Gf5PqzpNQQ23Vxeozu%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%2BogS77nSO7y%2Bkn%2BndWRdNk8N%2Btef5et%2FXv5enUhmBJkS8nxv%2BisEZZzFj3yeXkXk9%2FrOVfG8fvfDRn5V2ZXxu7WOXbsuvOVXjPfyfG9V6hw12OpJ4cSeDrYwPg2tUHJIDrX4ZVmbAv3Xgj4yhA688snt%2FQiMbh0GwgXc8tI6M%2FxmOvk4YOjzQvN35lG9%2FQi0QEpBfGSITLL5fruhFMvF56UjH20l%2FWvQ9TUR7o7yXtD%2Fre1Ynk%2FtdoUQhfBf0zN49bk%2B%2F6C2%2BKqUmvsjA%2B4BWZMMr8a8Sf09go4hkWlIVvlk99P9ZNZflfzUx32K%2B3L4K4%2BSg3V95Pe%2BrBHVt9bno9a%2FT%2F7sa9vclhwRnHlX6zP%2BUmEjQGebpLcF1vCPT9Oldjv7CBbt8daG0flIKb44kZXdnzd%2Fl%2B5rv8vmkXtEb9iz7vuXFfGEX7qu4Tsnlf0LGbvRB733CVzx6Qeczl%2FffW6QZKbOuG1K%2Fro5Yvhp2NsTqr9KnbWT6Ps197t%2FetP8jBJLfLa1aCIgvd8FR5brvOzy%2BqiZZMmfxAkJ3gM8R5yCelK7KqhfkiCHv35P4gbdK99kncneq9d1NAiEUwnt5Ty92TiyDBr3VjL65WVsrVt5f6r%2B%2Fy9U%2Fr2%2Fou915MbuY%2B16gioYJ4k73OnBOIszx5lgPZCZSE2SfW0%2F5W8uRX3%2FV95ZNWj9k8fo13d99WW9318v6K76X5JmopalfURXDaJ3fZzL5jJt6kt8uGuX33LXsv1k4Lt2%2BXLCurVx7BaV2sufG6qz%2BXxmsnhdX3m6N369%2Bve2vc6seXXoSYp5e61WD6vpcPk8j4JyY7n%2FQi%2FOyvk9%2F%2BJtcu1f9eq0Iy7wAAAIOUGaSJIqBXXoX369%2BvX666u17uul79empl7p%2FdXOtY36%2FP1b9e7Xv17pP17vte7X3%2F69%2F5NX8RXr1erV666K672u1b6OR3MaHJrLI010Xj8vVICjexlxg%2BzpAUcCfeN8uA42XXc7u0Xu8d%2FtW8wr9VK0lrU9q5I88%2FnCuJzbwIN%2FZfxY%2BiTLtrgaklEXYZIq7D6jC4ZP52CvDHSDAp3bjuduwYeXlw3FZeCbuNsm399bWDDP42Q2xrPsfIqmJt9ME34RNs%2FPfGjNYWH3FbT3aKz4j9e%2FVkla5XaxY7%2B%2BI%2FWr9aiPVjshnf1%2FVKUhN%2B6K2X9%2FDU%2F3cDU2rNH%2F85HwRJywnnVcn6L3pTQ%2FXq103VXrV8RXN00t3WQZu9e4Iive7a%2FYpb5%2F0JarXvT%2FVna9N6xSSXL3L667%2FXq8EJpTGx9WbVo%2FV691%2FrlydLwk%2FC1Wk9TpN69Va6yfv%2BsHclrL9FP%2FcWIyGjEOB22hay%2BU%2BaPj%2FanvyiEV%2FUIYsUH68CvifjrYF%2FdWju7vLxy0hU9arbrV%2BpeifXpRT%2BWGCcuVKgHvF4yifQtAt0G5zHNs7e4rvHx33TIQfEQc3ZDRHh2xqB%2FauUu3MvqX4QNTYyemcx9IWviZSCUgysSsJbupkR%2Byfv%2F3fUl9q9ar1erpPXqpl7y17fnhw2NCdRtYvBL95j6%2FPXSwnKZJKYZPIeIqq5rBFe8%2BGoM6tVNzidF8v%2FuGy440fXmNGLY7LjuVyT5sFt%2FL6vuFiXMShDpfwFuvjDR1a9QWccBseMRssqtA6VBx0l9l%2FE9Qxs7HZDUMRf6Xj7aQ6aWns0SMtUt7z5PFrdsIYDQTjMolNp6Imfk6e%2FR%2B8v5Okr16qauaT1dU%2FNZPBnJXKa95PrSewzKaOcoCVWUJWff%2FJ4K64KicZhLTcE%2FtJh7XK%2F3ubOg%2F22lIgU9NDpa%2F3lGIffbDAm7N704Pn3H%2Bcq%2FGbnuyIEBnIRvl7y8mI6jf6YyWUn3nfhAiMOM0VTQf%2FhxF0WNySrERXNGP0%2FerljaN%2BB%2FIIP5Y772fwXnjGu8N6nwZapU%2F%2FBFMQZxhNSXEYKiM9M1OOIMcn7tC%2BvH%2B579f0Tva8uTLDBnOIMhpkOx5t2XrkGCGRcT%2FxvaVDdBnM4wbM5zUbuKSZoUNcbPq1R0ofHkw5Ois6MMXWbTWXN2ojtpXh6epUGHtgioESFSC5J6j4n70W2F7lbQQ4rTF3ssPrMmSfyu%2BywrGT0q6fGhj%2B4ZMbeyfUc%2FH%2Fv1CWNg4q3L3vXCvagby3vp18ca0%2BtQzwd7Zu%2Bgg2P2FJ41%2F9I%2FVavWXNci3vqQju%2FBP0E0MwiZqaXAIJRbyXhqRz4AwN1b9sH%2FYhcckJmPB3xzeyeMl0x2G%2BiT0S%2FF586x0aPw1ren4v%2Bzzi4PozC490PYTEO98zHMoKIWZRzlWf%2FXXXhmnRmL99mbbdFqbw4jvJ%2FUNly0HTJKvxFKRX9FIn4LzbvDq%2Fhe0v8cKlCiadQW44Qu3evjQIH6peurRZS9LFd%2FfcjpZEXLn7QiDUV5iGCAI7JUCdq1BT7aQadt4Si%2Fm8HUcvWBQ%2Bk1%2Fk8f625Wci%2FypBpp%2BW2%2F9Xyej05P5T6Qxl8Qbksd86%2FcqjyOOe9WTyeOIOT10qvJ4E%2Bv5zrbKln5P7%2FBFDcIM%2B%2F4copWEAk4DZc9RUn9w3z5YY0if%2FOVfw7E0bzb5K9WKu9uTdFcfDRrAvWLBD9f3H%2F4cNxZ4VZ7gJwn%2F85WfmWHxsDJLYok8f61E2WhwgwUlyeHpE8Tt8Pav1TN9tgMtUyiOXBskQtcRAjh%2Bs9NK9F9ihXJ5PJ%2B%2B%2FxQ3Diep5izPk%2Fl8iC%2FjZuHBl6DHSwrMOCG4D%2F4dEeMiAhkSY%2BCxd0zoePqVjxrqfzC4T8on5PjIuzkf7RhHBjtgTG%2BqX%2BnQmqSkWQirov1l6K%2FUCLufHMvk75DKvi%2BMhBI9jbwlmuDlncra69ylHxOa2G9mMcNxs2e8nz3lii8vdUmPqDJSez3fyiAz%2BjdzYKbvvywQGDqfXtltu3Ouh4R0idJl%2BzZkoZ7HJ71%2BFeUiUa3ZZ3222zGZPFenHT%2FyqHD6mdmTKVXQehhgQ2mcZ4aBiEMpvXsSh3c4L%2FaTjOMghn4UTDiI49zGZ0RrifmYTuiR1BrxAuT618MlXdQi%2F44v0dIseT16T5Nr25N8nvt6lEbMtdhPR0n5ISeqdpKSlk8f%2BJtWkha9WobK77Hz6nXYJMPJmQWzsN1TXVFx2NmC%2Bmn%2FUevjp59H1D2Kjdjt3vuv4aiee%2FTFk3elf0C4eVQ%2B%2B7DZBCV9PaJ2lrE7tDYcEjaB9CdFhC1jVXSU8Ex8vtv11DjUBl%2ByJmXyse%2FvwXPxl5aE5eVTLrk9CO%2FNaLnd2F5wgNgRQ%2FHQew7lvX4NYZ%2FRdfnr7YzyFBfPX4Ucl%2Bo5V%2FMiGkz7%2FJivy9hqXN6%2B4JD%2F%2F29CddgnLC84vtX%2BGJNtTEnqKEEwY93ly4unP9glOT9725TXn%2FtmLd31IUx%2BhLSQz33%2BvW0%2FIR5kYGT9yGLRvk%2FNS3yfflvk9P8OHbTe48SjL4NvU6lZk9kus9fYoymOnz13NAnGBBULo3PcI9IZNlDtDhjaI3t%2Fgt3tH9iWvyTGKj3778sEm9%2B2CYpbnPEdy8pBk7S90T7wWS34%2FTiP5S7ur72Vo8XfjPjdQn2vVqpao3jdSl1tkEXlpXeS2cxfp89n0GG32hZQQ13bnPceMpML%2BkV%2FV3f%2Bi92ve0vfq%2FBJrrTy%2BTsXQrsn2b%2BXJnTl5PL%2F9%2BOzd3%2BhLyYz%2Bry33VSvV1X2vjVYnyyfS%2F%2FWVesVbrVNMn9cAAALVUGaSRJKBXV9yVVV11V1oTFN613cCPxK133331dff%2FfeTw%2F64i7Wv1fplKkvrFd9X18i10h7mzEzX60j12gVed5VITGDO8CAgYJgnrj5cCUbwP4X9ftMJymLBwnVJxt33wKPfB7fovVqveTXr12sXL2sVeinuaDRkcqRNWZVK%2F1LglwCB%2BsB8MLVW336v906zhrZPyQ%2BmpTPS5mHrBgCPnKzsD%2FDpOWmfLn5IvQ9huOslrLiUpkbM%2B0A7Vjk2C6jZDlmWGjOQQk4Lpb09tGDqrl%2BuMXTymK3PhieYy3%2B319uGUVp9fhgT0I9%2ForFk9f%2FurXsnx%2F9%2Fr2O%2BX6sdStXq3c1S%2B%2FXu17tGi6zzpTFvDOc%2FJ4f5xCm0pr%2FfYaLpu8ppFX9YsS%2B%2Bf%2Fghy0fh9hWYVCbhgPxbo7GSiQE5dTeOkM9N7eMI4EtWdCClq5V92vUKJfgi%2Fr44JVbFbcv%2F6sS30T81etfq0TklGcay32hZ07ZHv3Vo7V0vfS9fyc0l%2FNJ69XMr%2FMvVzexHzWT5qvBgbVD2rB%2FZiWpqkr%2FRVieWhaLH08loS9H6778lSpcvf6935PRHff61d3RFX%2Br%2F9%2FnLbJ6P%2BigoEbMJu8lloMG98cuZEWKmeJNe7CQJ0eoZjKDsZgfSZ81oEwNb7qD%2BuP%2FR6sctiRX9rnfrFWJ1RFf8%2Fa97qxV%2Frl7nOz%2FGs7iMrDYrkgLG2zzQdv9SagwvveMEWCHuH6%2FaWoUmH4BpG4SfXM%3D&media_id=1254206535166763008&segment_index=41" + }, + "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%2BoICSARpiSgUefl7r8qw0DulyeVKV4Wh5EDegRgaUcfFvVg6xsFJgw%2Ft8E3Hn1APuf%2FPw3Q5fUiiJYf9xR6b73k8HfUUIizJlLTI6l63Kifs5LnJM5Pr1JBCQg7OpTyX32HcaGP4bRcOjktd9yNENST%2F%2B5aEcnlkZ%2FDJfysNUpZj7W34cz171LBLeHf8bj04FmPUwNflzaLFRPXr6f8nNUtc9cu3pEr7rb7ChCBgIViduSo5eZ7njZ4%2BG0WZSVEJ%2BwtAFGv8De%2Fn47eBut%2BfFcHyBgXKA2Zk2DBHdG%2BnNvhTKgfsh8jX%2FmvchYF5AwIptBFQjfe8V%2FwQi2T7sns%2B%2BYRLg6gXvqTySvUXGiJO5JfJ9a8nYi%2B8z%2Bzd2rCJliT98SGC8IXFV60TGmX7Q%2BZaw4XGjnsce%2FP9goNHb2vQ6pRoScEPlYdzhsuXOvkfI%2B5%2B1qvXKi%2F%2FrVetVderV6L3VTKSC47n974LFgzCQ%2B97DJQ6IW5VHK%2FU4J5kZpm7uShvBB60L2WgHCJg95oFsNkj4hPqPiQcnoXqIiYnSPj8rewqULu%2FXVVD6P%2F6gRbryye6um2cq2RjLaYUYlqPYJSBWXRp7m1DREO%2BUeZjOwyQfkijPX2ED6FFTbKKH2rWaOhyQkKZPtS07BP5tcYQvxbKSDths3SCBZRCslfQ7uxpH%2Fk8tfNCQz%2BpPdRNXwR%2FLTucEd7uw3PP3fE3d16NLauCrRuX3j4gO0QG1epz1wxJL%2F8WXdM8LA0RmlOg4Jz4Nl%2Fn6Y3jbHtLm7C45LSKzzRZ%2BNoFDJ74LZSjQnepD3%2BFxiFKolUSqKzvnf%2FoOHHQQn8FCOiTHSgUI%2F2xI9l%2Bx7BVnDAZAgcLrYYP0kNNgNqRF2Pw1NuCDwM%2BzAffLGLgOLTpXlaCr%2FeX6E2PIdnQwV5VwZVPjiYNWzbG7EHjb66m7BANcow7ujwE%2BdAb%2BefpQTaRttBD4PP2FTGLwCm5BZwlvHNZmH3ix9YjLq0J7l1ZeTzk1%2B9C%2BTz6X0vox05wyR9VTDyWXoE2MCTthJ%2FX%2BFfJ%2Bdj7%2B60bfVWGyj4OB%2BuGJKP%2FnMrZs5Rr77yi93k8dewVES3uNx1M11NdnYMJhLd31O9pl%2FbmOLxgj7R29L2T2Ir8hA2kNgKIZHLS6hOCzSy8d%2BhLx4QHk9nusPcuDOVFA3HiLF2JjWPs%2Fk8NVoMZXhtiWMj1%2Bv0ZIBue7A84%2BBI2zqlrRZqamgaZMgLKaHvE3f%2B0y0VD0HeVRhlFwSRPUG728%2FQy6PqRL1hx3R4UtSwyiOamag1753KN7tg9gwLpHMR6Ohdj46Vh6GsMIrDtFcKesTr1qa%2FUhnLmUv7a4cl4%2FcMJWvsGR4FqnS%2FNbbYf2wy1L6EQiXvY3LGC1KwNx8FVWaGz4Lk%2BLrUkYGlcR7qVeO5aMoeTGYPWfl7C%2FcowZsZsIr9YwJOrw3yYSS%2BX4WX13XX4SrXJ%2B9WjkWKlO%2F%2B4kIkXvPB%2FYTEK83HK7wnzlNFV4dpWsEi9fEvcJTC7OIrl5O22b%2BwgbYMCgJAYdRATm758f2bd2Dk%2Fm6yewgJmzG6eVh%2B3sOmh0VC%2Ft8vx18notxL%2BTxa9ylLj3vaLFXonfovT%2Bcqx5cfrzDmi5y%2F0pWEY8Cp6Asg8YfjWPfbYS7t7QZsLMk8N6cKlAhrYGx3%2Bzx%2FLSCpqPA2IcHyQMBaCb3cP73NlK77sPoqbQkdbtWEnjv4wr7z0vbefH4lF0xNGzqu7732Cq77ve94MnlvucmZbJ%2F5fETS3BFWl7b2HCceN2v8cPFxOIGvdKN%2FLqfGXcpjEW2eOPK5ruzLyeu%2BIjBhc%2BYSIIDuC%2FiXTp5fyfD5aksIl%2FUEokf9AXDjLX2NuWIIELlNPwbbQ3P98l97P7Rdd6awmV3e78nlfa%2Frl3%2BteTiuvJvPhPIZgiCA3S9QSmQ37vSDVuCErj%2BXdVlsefPXZO7ew5u7T%2FWah1vhy7J8GHolhnfyeJL9hrc%2B2v3w4p%2Fye8t%2F2TAlruH%2Bv4iO%2B9O6MgzZqQl753Rvvxce9P58SfIe9FbWbd3s60WmySsXE3V%2B6Fv2rO1rzfJ5%2BfV%2FZxSjiD%2F7IWOjJ8vaLW364R5Vl71CaEMZPD3%2Ffn2KWuGr5bu%2F0JJSX6%2FIiuG7P81EpeUEMmbxcUiKW56tWT3k%2Bv%2FxH3ECj2P%2F9TXZqcik1P%2BAASoUkCoWChnDAZDQYEwVDAmC4WC4kCoUEpGCoUCJhXx%2Baq%2B%2BM3ZdLb4JWSUS0lXoai8y6%2FiPQv3%2F7z5P9W9qH2FeV8flbo15kgCYH8vl3ySE7Ptar%2BuOrJAZiDvsvqov7s0rCX182ptnxIEbLPjBpeNMajR0OEHY7Kd7%2Fjdp5OPa7nDFOM391gW%2Bg%2BG2Qh78XQuIhrPZEda%2Fr4ONVwM8VcmvbuXOEjwzfKJz9Weq96P9b%2BcL5QfPpMk5CRgU6hffpP%2BM3i%2B47%2BAnVawkjwtfA66TtW8m5FglOOvjblOJ6iLlal905Yh9vNAHASIUkEYkCx6GxEE4UEwVEgWCoUCwlEISEI08HHvDc7%2BPGgha25MZfFRHQ5r%2F2%2Fwf8WmX5VaOwj%2FXUmVW4v8mqJMx3i%2Fp2sHuXTHK4KVOOgtvt414dCWYs3po5%2FXv%2FL%2FP%2Fl4bZeuRGG3uK1t2%2FWfF%2BsPQcQ1zsUothwvfyy53XYVtgQV6PVHWd3bnuhqAQKFbLeT0AVAQJZGZqGJrxc%2F8u%2Fnbn9z%2FA7zCdBINkCHdmiGF%2BycwQ6gsgQOcr9QT7SoK5erqv6J2IMTIjVS1HCyvpM20gIAzIkKlb1mFDcxZli16g4ABHBSQTBQShYLhYKBgKBgbDQKhYKHYJiYShMQleipz3xmceLq9YmsW43kYStSJobrrTjG58dfGvy981R8bXD9Uf4tvGkd63P6Tb3Dz%2BjCrhbVQIZe9OPhUmfwP4x%2FC856vtDhONNerfVv%2FNeM89H6eDh%2FR9vS%2BsDh5KL3XKmacAZfEM%2BIgrg%2FT7GTPoJ8uKECmsEBHyCUY%2Fcn%2Fjrv7P%2FC%2Bh%2Fho9TOSrRMgUAqq9R8AhEJIg1VE%2B7oiY4KaHhqfsrp%2F6dF5fjrp%2F%2BfEjObBWUhFTpelKz3td0vGuvVwy2BwASQUkEYUG4YCwoCwYGx0EwVEgXCoZCxFCJXNPr53vrdefnWXJu0qOK2lYTqpHQ5z8%2F%2FVaK5t%2BQfA7z2XLhaMG5Qz0D8p8yy0VOqquH9y9OgnXqRtujBsPTEcbN3hup1D0aTWPOTvM77tsOFq1ftQv%2Fv8fLw%2FB%2FkENGqxaJQBg%2Fx7FlbtUFpuNfx%2BcUoS%2Fk7L838eeTy%2BP6bg6LPOBaSi%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%2BGnlrxqrfPdetKbydPw6K%2BJd2tpK6cEwcAAABrZBmkoSigV%2FoXFdS13Xr369Xq81rFy3Trr%2Fv%2F%2F%2F%2Fv%2F7Ut9f82rO%2F1i%2B1iq1fv42tC69X7u1yqdYL8psHYleqEsbJJjGnIJS%2F5g12b5Q87Suh%2FomcTxCQXH2X%2FE46VtpfXK%2FVj9eujf1qqI%2FWV32rn6nT3VypVf0J9Q4Siuvx1A%2BtRF9jakNe4ZwiYbKvBqkw3%2F9Aks72FyuInHsh1%2Blevp9WGSqjIkdK5VP1r%2F9Wmu%2FWqta%2BLV6%2FR9a5Pb18n174JbY5788PZPtb3ZEDe%2BdH6S0S8na12tztX9Vf9XPk%2BEouVWPDGWKX19V73q5J6rVL7q0nEyXPfutSX2r1r%2BCMm5VD1I9d%2FovTVYpavucQrTvomXW%2FRpfj8q9jTjCZ3BeUX6a9v1R8P174qS17i71VjuX1qrWrpqrRYvX9CmUvX8OHvdfzwPH4k0i9COogXJxPTd16LV0klXd5PI9erS6%2BpicMLLk%2Ft9w3PC6AYRIdy9GlHSv%2FVLzuRGqXr7nOo7OtjH%2F8Fxncv33wr1Y9QW816KNDQK2%2FQgTlp6RaXe%2FLqz0eXcunLxFF%2F%2B%2Fakn7Vx1KZw5LWZl%2F%2BwTyypR0bHsoMv39CibP1d4IuXef9d4zAH4516JxkEBi51G%2BtcNib3X2cYaOt1KV3%2FmNwO2mfiqBo2DHSFM%2BTxC3wuFa4bth8%2FcF1tH%2FqUgH8ggg%2FkEH3Ju%2F4aEtAMbhI01hmcDC%2F7nI9By%2F%2F8L70OVTG0Gsy0sPLXXJ83zLUxf%2Ffk779IOWkDLFwfc5lC4ZUVD%2BNJywlDUJ8FayhgN6ylzHflUTIKG6BaJKuUHzhze8%2BT7prwuSF0ZO%2B0rMOuZeQ%2F8F3TaZobQwMu%2B%2FU%2FKzGEjP4sLXp%2BVhWKL4f9fxl96qjsUJvyqYyeLW1%2FDRTwvyg3tYF%2F7sinFP%2FCuGZ9qBeNGG08nlfGcmkaH%2FN3eX%2FdQVY779pz0%2FtfIevoI6iWGpF1fr1bclSt2rkmXXmEPfr59q42NiAqhoXLmYXcI9%2FKVfToe76cM%2F%2FyfnbdCYELUO%2FnydCvXcd440BSf1LuCfaOf2hz3wyfi%2Fnr9Rs9%2BfTqblY0%2F3WqvRf%2FNOVcOM%2BtM%2F8t8gEXq4k%2BmX%2FyKIpKoz42%2BdHevRbG6ie8nt%2FQcCCjsz5fyMXu7Ezww6lJ%2Fl%2Bsp0KGYlloQ7DBp4ePic1Di%2BRyf%2FJ4erdk%2FiVzvWro763VcPwoZbyXKxfcMqZg%2B9M9eocHzw15LOopQ9P%2FfYpqlf69k92%2FURe1adF%2BFqBPfcpivjpL6mA%2Fnr7UELRgralv9Fe9te%2BSrXr9ekqR%2B6%2FNqwTz57vd1bPOOUbPEBOE%2F5PKtcEJeX2de2svDqLuX8WXnUDQPaoceoPk%2FUOGGabEs%2FM1HckGRw8khc7hso7J9fOhrUj9Ij6pGE8nm24g%2BGt5QkYWGbaBxc3Qz93WFGZXQ68SYxywsv33CLlWviuYLsggcvB0P8gp5A1%2Bcav4QME3%2FgjMH0mj7h8RQrpcR1zfoT116WiJCItZuhbekYxdS6dfJ7EGxWWlAYyMOD1q7q6zTbOGe9F0CLysM21kOzHgM%2FXqF97u93fMXNr30YaYRv0wRMoR7pL4weE39RxGev4%2Bl%2BMDBXieV9AZFH8V4KsUKdheKc7E%2FGZgwrhC1w%2Bi7naGA6Jbxx0TUdmE9Ug1HUztTrDnK8PqU%2FSy%2FPpJAoFrpXMKeUtNLOtc8voRlk%2B%2B%2F7PX0ZwnHB1Sfa%2FhOxnT%2BEuDoyn%2FSPXz2ZFrwSXffdyLsKKxRaG5WaO%2BxJLmLG6JrsIxymz93J7mPVjU3%2FmEZnlZ%2BTDXcf4g2UTnLzMNytSlw1p6F8pW7e1siEmbSMxmYr5Fwhel5O9Vu0JaXJXq1Xrd0LFY0vg0v3J4d25dkWnL%2F6%2FgvLlySg4qX35pjIzUDk9O999KYo2ygOdz%2BT9Tq6PKn3nSs79UTqf4cJbRH68NTi%2BtyCXvRffUkUIoMIWGZc3d%2FE%2F%2BCPkv3qOEzblizRXbdu30TL9et%2FhwpWKHXxGHxfYKyvfd2y0%2BLeuhUEsE6F933vFklXvP5VILJ%2Fb%2BQz2B9o%2FwSmfTOY5cc%3D&media_id=1254206535166763008&segment_index=42" + }, + "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%2Fd3Sv3ksx93333d0KlFa9Fyr5PVL7kuze70W6GZd99yX2he%2FXWvG1rz5PB9X7%2FXPLdeteqxZf%2F65%2FnvNuyZyT39cu6f9cT3d1DvBBbBxtErvsgh5qYAAABypBmksSygV916Etfq%2FS%2F16tfr1esV%2BsZ%2BsU1yz3d%2Bsv16%2BL6Xq%2FVpPWL9Yv1ZfonVE1fKrDOew9qiGkt2jt3%2BuqtYu1yr1lLdcy1V%2Fqx8t%2BrFeuqsxDS9Kkgh0b2OcEnPSzlePCq9H7ckITM5xIv3fNe58sbL97H33KOlusV98XhJTdfZE9vzdSka64m6uSfZqiZc61o16kc13%2BiRVV3V16sV66rCGrjfkXxP6mv0bCy%2F%2F3Wj1fSsdq3TfrqTWM9ZdrX2rX5yLHl%2Fr0WpZ1ix3yrCtXkp6tYpvXD9XP16r77V%2B%2BpcN26IRL8s09r4qLFQpBBnINZPaLUvSxZPT%2F%2Be91eT1i7WK%2FXv1l%2BvV6uV6wmT%2B%2F9eSYmZg2ZM89ZzQNT9gkx0JGnlv1BDGM4soYC9agwyeT7R81LBhM0%2FzluVfQItotXVJ6xfS93%2Brd36u%2FVprPx%2BEOnPuJVGi7BHOCAM24Mnz%2Fu%2B%2Bw95qXb3Q0l8NTVgs0%2BoISu79alXiyE51G%2Bz3%2FCB4C0LasN9zf%2Bj2k9auYlek4hWVm1khs1ar%2BNkVtJPrVdddhcjLD0S9res9ZKfsNzwQ9RomNeLto5%2B%2Bx4t7vRPlY5P71LyeB6%2F2C4j6ZP2OzkXHcPNZulYueuNRFeM2PaP3bnQInyeS6theweVRexqmWkrHk9e55rV7FfEXN3exfs5oLDVmv7Ifd5Ph%2FwX42DjiKis%2BrOaKXyeXr9hq60i342CmgXGT70N%2BpvBOSOpiXHFioXdhk6wYlB6XTsEIP9P7c3nKbl%2FJJSS99gk3umyfMb9HEp7zvjqJnsKvolXSesH6t%2Bs%2FaIxeN5Pv9e%2FCHvrXuwuaTLG4CNpwG%2BcgR%2Fd7XNURIM3kPyfRP2FuA7Um%2FCCh6CVsVJhQMn8nh%2FYI58%2FavDF3YG735cRh%2FWQWwMyR%2FYKBD72neDsLU3zUNS9TVmydQ%2Fr7DmVeVcg5hmkf9gh3f3ZfL9nr%2BNPVxmp1Nex%2FoTXZxGz8xYcSfZ%2FvmWgN3kqQuajyftZdy%2BvVe3if16rqG8n7%2FLk8v%2FvrIK8bLq%2B6BDObXvroJhbeCM5ckDST7hwS0Ig20q9Vs7TXd6wdm2N9C5MtvQdHYMCNPMR%2F9vG0HrmgZj5P43LEwYD3fSSsGv82rJ7t%2FoVL9X5R1tI5DiX9DcwR84vj8rH5UNaBAPlBh3d32HoNQ0nEosTNiM3oS3jP6MzjiNuTo8x932cRF%2BNJvs6RNbOwyViDUn2twss2BfTY4JHMsfEhr%2BzSMJu%2Fr2c6cPLhUcLctgtFPenHBL2yea2S4bKNgn%2BuPpcc4Yg3pHtG1k%2BS1xENGZ%2BtVX9kPRPq8OCcxl1DLcf%2BtcbsTs6IhB4ae78oB1jRooGDH3eKzEo4ON4VnTknFamVxu5%2FcS4eGvfBLqjQUGUHJ9fwi%2BxZuUMG3tnUev1gY2lMosZN1SzT%2FoTFcTk8S8kRMId78NCQQi3ffJ7r5On6sEgxJcgtHhnobwfeMiT9YIyoORRw0VhwzugH1LCyKt%2F0LZk%2BuucNGcoQDIoWNXNL%2BwRFhmX6fy76TRWQwRLqY5z5oKyxT7vUcEP46JD9hTmzhu0NSO%2Fnb4ZP5PssIxoUjhS%2BRUNsuhFUD5o6XsfNS0WikCzHCi3BtjMvX4ygxoyXCEx2zHaNDTvT3aoscny%2Bvzj5c8kHbz5fLpJUotmgbyXJd4R1L2CEU9fd7ddLmWilFaCaakDAt3J5VkqFqgYrvpOuw0YRMT4%2BTzWraJGDhPsywRw2s%2F399yahymXNfmWkUUpqG7wVf%2FXy0ZqbnJ%2FGb7hw9W0Mt84SLSUf%2BcjyQHLCFon3zheOiIs9%2Bf36uguuL%2FTm%2FgkK1M5tzXWMs74d3LU1E7Qbu42SPiDLxIZny%2BcnSqux7HVvzs%2ByOunbgjJjiZvLl72ZPm%2Bbwj%2Bi1%2Bi9JdXvye6J9C%2BbkFFC%2BYP9gj7axZPzXwtCBv8%2FSp3%2BPj6VpCwkPpT2Giu%2BrFDDfNwcFXpv9%2Bob7uv6EG7963v8SVRF%2BWm%2BdX7OSvhvu2o8qfK%2BaFkPnbvk9tryC4I93P%2BL%2B1fnGCrvmOSmMFWlu7G3JdGSuHKQ5cfu9kb%2F2epNT%2F5Lvd7%2FFbu93f6Es%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%2BFayif%2F0fvaxS%2BzePy%2BtfPXrXasq0cwq3y%2Fr4cGAm%2BK83B%2Bts6kheX8v%2B4UI9kYIBgRQwFalmjt%2Bbpokuh%2F1uyQh4RO6jHezHM%2FYaEu%2Bvj%2B9Dlu3L0k4X1jhsmfdZWJ7WRNhxcxRjrV6K93GESpBZXu3fe%2FyhgMYTe6v6lhCK%2BogfmkzW4gs%2BZ4BdfHrdE1%2BjvXXPyy82viKFPVV4Y1KYxbgheo%2B4Q5ceeEcNu%2FmDH5Cml5fX8FthhM41ZrKQWSCs%2FMTPiA%2FrBk%2B7%2F7yePdnQropl7du%2FwTHHJUDg3Td91L3Zk9c%2F3CewMtMbZd%2FhmWhaIFEpc3%2FqS0jo6Vwzlsl6%2BgjqJYd0JcbWx989eva%2F75e%2F0Sq4m%2FN3cm4XNQyBALfCFg%2Fv6mQw53HPB6fwtKBsGrAq8I2O2lJBir8vr9BrkIurYZaVoYfXiRd73f84heG1Pfu%2FvaW5Lb%2F%2F33dF%2BM%2FFl0EPghNYOHW6JB%2FxPfaL0trF%2Bre6tVy2i9cRmGDgIT6WiUc64eSyf7EJIIOaCOj4MwRx0gYCNnjRW%2BrDE2gl0d9Wv5hBF4wmf4LQi7nIOjc04Deonc5ogVPTP2%2F5LxXl9%2Fz3LDqbfxNU%2F6PXT861%2Bpgdq4KK7v3qyGcIlE0zfVgoItLNLODJ%2BXRNsr3QXOLOZYNcSGftbwRnuUMB5dhwoRcPftFMYPS5ei%2FaK9IugXmSY3hZk%2Bvx8Sh1I0khJUM1oRzHOeWGb5CJoJ3f17lEvl9KqGbeRCsYMrhn85OYLsqtQsKnD8oZKzRXXG7H9avu2wse5Azne2ng%2FHRuq0iT0%2F6liPQmvE8ngvrry%2BJV9e%2Bv%2BS%2FCop7vGhOsB2s6uMET5PL%2ByXf32uu0dLk9OXsUSNCXcGYiGu0nBCVBJ%2FfZk%2FdzaDM4fKk6ysXeGAorpcjQdNHkruovPlCOYDJp6Nl6QSonqW4ecPsXjSETNV7154%2BEf1x%2FhHRFHIK9ieC9yjOM2BJpC6zYPmP7dEt446JqOzGyXLn8kdTH8kriiXMLeXKppPRKrifiJLq0SLvJ6d%2F1AgnMXsi3QMYy2CAkFVHiJ0n%2FUHrGdPQDjBj8PRJjC6Mij9kx82boXV9m5K7yfTvqGtE9z8y0lNqw7orm%2Fx5DrtDAWO3vP%2Fe9iiZPJ%2FJ7vW%2FZhOOXWs7COJmPngie%2Fnsy0TkGzpVTKS3b1Psu7HL%2FJ4SK77dvY6iTR24X2OpjWoPCCcIITu%2BfspcS%2FvnR9ZPL%2F%2FV5N1ionp%2F9r3aFZeL7uzEuCYao%2Bi6WLTnnKvsEeAmMFaC%2FUf84bLu6%2FjJSUDb2vctef4IIImC1a4ofwj335POivzghFXd5d1LvG3%2FNe%2FOI7vbfQ0ocFjNNrFkV6fyeW4n99kEXeTCPvxPvx%2B2i51tVz3JErT%2Fk8jPf0am5b7d99%2Fnr4fS7Hf5yy%2BzKGAjA2KecN3fhP9EOGjn6Lo8oHyKA8t3%2FsFJs%2F7onseXfLy9%2BX33JfffaFtV9y7V2tcXy%2BLoQ7l2OvL2Gab7%2FqkhP2Xd9Phsu75fjCf0Pc%2Fz1y3dQr5faM%2FeoT%2B79DWrPu%2FE6xFakjqoXWXfjYId7vzrHOzb3V1j1L65famLn77OKVsu%2F7wAEsFJAsNBOJBMKAsGAsRDKFBMGAsGAsNwqERmFG7re%2BMXlZq25crHnszcVONSp5HKY3cn0rw23X3Pvmm%2FmCSe2bid3u1QoV2ais4LzxW6qYtBnNoasbW1RNTNT%2F1fFCJEO9lfy%2F3Zz0B%2FUain8X6H22quMAwPylr2zmm0aLur02V%2FoPWgV%2F199%2BfBdePVQV15AVlyTe6%2B8YgzjLilzs8IFltw59TjSUx%2Buqlf4zPKIYM9wET2b7SYL1%2Fil04XyZ3S4VzbtH%2BeFugXKjst6%2Fzq7KNVmVA75NXO%2BenCkwc62dh2wkGr51G1%2FsxOJENGmtmk3q40rOe071M%2Ff0wcABLBSQZhQKhgSCZaFULBQLGcQkTnXOuavXeqrLSoubl1jFKdaq3kfteI%2Fo%2F0X4v4AaXoG%2F4H12bHqXwuZOfutko6mm6tFl2jeNfb2VA2SF4UFJRylulv7jlM%2B%2BaDjv%2BW8vJwfKfPJDNQ%2Fr2rjQCEUNa9v930%2BIhatmC8O%2Fq9eMEhFKaBMMdLKfmxlGU%2FCcY7YwFhig77r7MZdXZ9zj1pwXhz9%2FnYyxl%2F23RSV26zXWlL2Tac%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%2BrZVW3HQRhw5A4AEsFIwoFgoFjuFAshAsFCMFwsVQuFQiRWm%2BPnWavlS8kioSqm6TNcQvgfxNOpy4ifKbjL9fhX0u2Lw8I%2FPtOjV%2FG%2F1bD3WDT5qnlZeqxcfHfw3ypVVRX7hY1CTnNKHZgYAoz7d%2FSeXnJVCceZ9Gv888caH%2B1L2fFdH%2BRu3XwZZW%2FT%2FbxIydqZhXubXeCR6fbF7dPn3ZS3pQOp7xC1NS4U2YS8U0ky0jZ1ZYT0727%2F8aH0l5rKGTHCC0lQcgT1vOop5rH4O8y2d2mjG963n6fHs8t17fHnyAwf7dKwkQmVfVyiaLq5KT6pVpdrRst7vbNPhUvj0g4AEkVJDMSAsRAsNCMFBMhwsEwiR6lt1vjK146y5SXuSopVKXNXV6HJfk33bW3H%2F0g%2FDy0Hpp60PFNKtyk%2FbPyvo9%2F2iS%2FEO3%2Bh8pfwKCr%2F6r1Uylb0n%2FrPTa%2F57z21GI%2Bmfk%2B2x%2Bj8JJOOkScnlMAKTeL%2F7QJr9YbDhADWdXifWgkR2EdOLTKvoThODztIMQiz6hOpmqOVxD4YXi1A0qJRoWru2ZjsooxunqCzX%2BvA76uE4New7IvEF4Cnf5MN8V6O4TytZ3gh1PfS5p67X19lRAuy35ygAgUCEFR%2Bnp1%2F4BUfG8bLwlIX5wxul7DPsuDgAABMJBmkwTCgV%2FoXl3Lcpf%2F%2B5d1b9cv1aW1Y%2FVi%2FVIldWrdrq7Wq9Xu5PWK7W6if35Pfr3V9goNjJdcOQXTxdyX2jynn6lyn9XL9XJbBaShvve%2Ffa1yqnVC76SWyeODi3u8937I5FeP14RwjcQ717vZ%2Fe3zkXzGmV9osXau7v5cKanu%2BibHd%2B60JkyCa4ua2KtyqVfaO5Xo7%2F3BDz1iPavXrlF8TfrBWn%2BvXfct30vdV%2BuXfVF30i9XLdnJ3Rjsv8tK%2Ft4sUq5eX4ng9ur4q7Rdfq92uXRM3NJZyLlVjSX%2FyeX7egNGcYO%2BXt5GZGdrFYrr%2BuYV4r7%2BXu%2FRdfq82vZjZQwL0%2Fp9cNXhOz3bjR%2F7777XDs3Gy4YDk%2FP93lJd99o%2FfKvVRsRdUR%2BvVd%2BilBV5PD%2Bg0Kd3rPU6lDJXSP1YubKwQkfMFj3ZJkrH%2FYkn%2B9X5PT%2FOZc8H%2Br9m4uetu9%2FfsJHjxz9GSSuS5fXsv%2FfEWhWVWQ937PVGPJlCoL9st77JYDIIsCvfYXkGzMTe3dR560O2%2FsrZB1Td8dfsh3v2Q0dTGDl9X8MnbDbBM%2BU%2Bm%2FfffaJ3fa91fr3fy3kftovXmxNjxD7I%2FDy0dwld2VnVZ0CnAo%2BBQHffKcO5Gyfmt0evDSWX%2Bzb3%2Bxb377Qh%2Bo197kvvV9O%2FtH7J4a%2F3vvUs9XS4%2F8br17uXVWsv%2F9WjMbKwSEFZn0WXYiTWxzEM6j9WT0pfd99lu%2Fs9R0iQKP6rOVbz3%2B11q4e71eCMXPRh7jfeT1df7IMxXz6r0VjtFavXpJpekfxsl907ohqAneTxq9NkyBJ9fV2UuIw3kqPLu733Hw1%2BwXFelvHRBGd6lwRm4xRK1ZBmT%2BqPjd99gjPDSJR%2BXZRDe9H7iYwEh3nUc%2FNHr%2BNlxVHkT6Pl3%2Bjwc6Fd6k3fnQltH6vQrvXJ4XieI6myGp1Tw5PXWsOXdrrBF8fj%2F9iS50jrRI68dPR1u%2FRf2eofU%2F%2F%2B3DcO73%2F3uXIY1F9%2BoV22uNjt8KsjV%2Fp8FV6baY6JLjkYxfnBqXH676AbnXnTQrk9NfCOE7hGPsdfP9lsN771JfpBsXIPvr4z3AOa5vJd%2FaEd36l5LpJq%2BSL8ZCAUZQwXhgWI9irzR8fBCbBfDTlwHjDZpF5VcqWOvsdPq0oaYOgW%2B9ROevDctV9FZdyO95PC%2F%2B9jrrVwYFdhj45N7AhrDmycZO2WLLuiMdiJgwGVnP5kFy5%2Ffyanv1KcZp%2B11EmN5sk8zHrWXrXyef7oSxd%2Fq134mi1%2BpG9bJ5idbmCEeBUS6KtWdorOwTXt3s7C5dlve3J77ye%2Bq%2B%2FVmy0fKanUn2hcXYIYfT7O7nuTs32CMVRu76cnJ8v%2Ft%2Btd29TixfJrLvvtCGV6O831F%2B5CQ%2BLzP106slJ9Phkqp2Jj4wgbPQUnh75JWPs0n8n6n9lu2%2Byt6p9nkAw%2FohNJqRGZPbTl%2Bxfmo333z8%2BzyZ88%2FPo3u%2B%2B9uT8Tr%2BTPp%2FoblcVlvv5V7z9Xq9E8XL%2FyefvtjLu%2FRAmd3fSfyo%3D&media_id=1254206535166763008&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": "command=APPEND&media_data=J3dej9UKqVK15biyjHfz9i7o8ub4vtDYvVe6p56ymuLXuj1x8F6tyq7n7BDNS9zyPvy6vtEeTCWpTn7P6L5P4R%2FEGSfit%2BfvAAAEtkGaTJMqBX3XKhPfr36xf9%2F5f%2F75V6a6uT1dV%2FCv%2Fff%2F%2F6v3%2Bi9XE1LXFdXd2iPWT%2BsF5JSXkGO0fvJPXFQiV9amJyXsFGdAUlwjwvCY8id%2FEzjpZzmKy5o7oY%2BO%2BJXvjr9ett92ueXVGdk%2B26uhBT5Vhhil%2FuCIiO%2Ft7qIxsQTtp%2B5aQ779XRvKMafDZRgaooqQmiVDjJthfxCi0u1ab16I0v16tOK%2FnIId%2B3%2F1c%2FLve5XMJzMZf%2Fs9fKjW%2BwnCEGddWs%2FOSe%2F0VtX1xfRP6J0QK%2F1aqWulb9cq9av1qS1qVXk3uXr45f%2B693J0qcr1qb1cirk9GgkFf6PV3Vzcq5S89%2BuFWtVcnrKM9Xr1Yn9Yq9WK9ar1Yv1MCvRpSeUu04m%2FJWonJ%2FWonxRt31NG9%2B90fDui%2Fv5SM7%2FiuddsqTvXvvf%2FNIPotUWj6uepie5vWviFiv16vR9V4bGXuo3z0U%2Fyf3v%2FiiFPaaYU5%2F2G6a6qjNOAvW5Re77Mbm%2Bw5hxyWpFyqDiA%2Fvb5bBnz%2B7v1q5Czf7%2Fiicnk8jOfy7k5%2BVCe8V9V1%2BS79fSI4JKLNcyXxlep3Eb3jiDAF%2FSq%2Fm4difOT5%2FfvtCXG%2Fz3R940PT%2Fu7725fqQRHREIMq6%2FBCW3oPr89TmhuX%2Fq1%2FOV%2FnEBkfXr36twRPd%2Frh7r0nr1ZaJl4nUBD9hMzGNgkbhpp877cbNlA%2FXv%2BYby%2FYoRe7pGO%2B%2B11u%2Fvs9cdRKH7%2Ffqf9%2FDqdh1eqcu0WoRU%2BCIRZMzzlV9q4vf%2FLGF%2BlvmK6L2re6%2F7%2FQthd7GSR995PH3zQMpBVPs%2FD33ct2hPV6uSX%2Bj1%2BhXSWevw9c19nMrEjGkH%2FYYKUROwNhAbRlgVdF1Y5qIv3qFfJ%2Bf0LLzqAj43FfQ93o%2FdnGM%2BMlHMoD2UpYWyqd9kFDaDVoPYcKIiA9fjhRmVzYv32Y4QOXg%2FJ6fuCURy8Yy4Be7C42FVlchjx1r3Pjsa7PR0CE2PsjHN3uCO97hzy2it%2BitdkM99uX5ZD7vtEZq352RaXauyeu12CW5D3Zi7AmCsNEy7V8tPSKvsEQlIfAAnbsENiqssODvR0QxqGzr3CcJj9nx8dGQeBFo9hDbfjQeH29nbuFOV8i867BYzkfKrv12PjYwmDMTqOULNJPEh3v7GWAy0xsYR4edRsPGkHu7d5%2F2ImxjpVKK3vuMwi6vvvn5Ql42WGzvJ4eu40Mtfk%2B%2Fa%2ByzkHfZy5Saf%2F7DlbDLRaFAxsmf7djrk9Nr%2BsMXfveqayU%2Fen0JfJ%2B7rmNnY77HGYFh6LDjlGmM3tvcX9kO%2B%2By7pdsic6Ta4nu375ffu7v931fffZiTRoLfaK%2FfffYZOeHUY%2F%2F9nuPTzXZv2URnx9nrw0nE%2Ff6ExirBaIbQYbhRDRmONe%2Ffl8vfL32hLt9NCCu9y97fb3vv9cpP%2BXrXvdX5179de%2FZhkdfe9u99OJnL0fQf%2FfZN37yfD%2F9999iyN2kE2nffffa92Ivu9%2Bfy9GXz8vffffDdcT0Zd6eE6L%2FkyeTTP5%2B9G%2Ffffduf%2FQ8qd3l8Tz997cTpten7x39YK9E6vWUmun%2B6vtW7VjtFPdq7hdT13W6J1cnffie3%2BEWKa0oAAABWJBmk0TSgV3xKEt0V39r3fa92vfr3lrF%2F%2F%2Bvf%2FqdP%2Fde%2F%2FV3PxP6xdr3kq369Vq3a%2FO17vvv9ekrXpLktTp4xr1J516sm9ajVY4kpMs%2BJrdF6J3Xu1Yk1ntWJb7BLjtOpdf3O%2B%2ByE2n3q9lzbVr1cXYonqk9eiKaTq%2FXrT5DO%2Fd9z95PH%2F7ifQmr9Yu1ZJatVr14r%2Brc9YysVXJ5BVI%2F%2B6OdO%2FpFcRXvi%2Brk9XP1bteu16WJk6Vqte61wri%2B69Yt%2B%2Bt1KI4NwkDSEybo7V6xVhCtfqx3P6yov%2F691SZP5jbBhxnWeIqr0dirqiZOW7q6urrJtBrmNuXJf%2BtcuwVYwJ%2FdDLkhilR9%2BDCeVg%2BDtQGMQu8NJj6L%2BW%2BE8210iZ8TcdGhgsmfoTBJa9P6y%2FXr9Xv1ZL65VkmJd%2FNMagbDDi1HxdhW5ueCJyJfhO1qOnHumbiDucO8ATLeA%2FiDDD5f6qdzVal%2BIjrUtUUtsJUl6sfgnhRfZX%2BYYvt%2Bck%2F4m677H449IDp1c4rx0TSP0vXfRFeuryb8wg8P8bo50qXQgmNfc9u40aOevlDAZV2H8O%2BGPCE17hxCD8H%2B%2BV40IeOn9FevBZZgnGch8%2BY4dvWivJ7%2F0EyNoD3RgNdEY176iO0%2B5cuyywn6FdX9yy5p%2FCR0gZnx1ZTEpB%2BIsGCv0gdqLmriJfXv1qKXgjojH4vHSyb3XHWj%2BGrsqfXVCMMH%2Fhwro9ZqnSf%2FMTLhYfFywQXNG2y%2BSTP8TpPKxf850ofGtf8xkZFCwXxBWZ77KQf7oHHWf9EY3vgn2A2BDlZSDvYW%2F%2BIozwf20%2Fu85Jn9Hndqd533Wq1c%2F6wc6uXcmCHXjxTERm%2BGWpeOguLV8TgHDKm9l0z50nxW7WH0SFvb9TFyfsdNwrM%2Fd5aP%2B%2BpXt5Or7lfsEIk5NLr8WIhpJDRXrsE3d81NxqRbz1rUnr1L4lF%2FXF9rXfrqyyDKRggD7GRjL4Z49e7azMR8hejop9zqP5hGPic29aElS3d9K%2F8R1WXFip8JkyWp%2FP6vva%2BILdqT%2F83HTFiLq5pf1ytV5r76gQb3NmIwfkHo8%2BjgnE0YZkhWwKNHuv4JvVDciaGDpd970urML40k2%2BCcVjVIVcrI2O%2BWrcNlH5zfFuX6MbHwfQijd%2BCcx%2FB38%2Fj9NmT81%2Ftj6V6vFcko4Qv26hWWG%2BgMsFlUjBoi%2BusSK4J%2Fe8ap7UqVf%2FmKb24q5EO9LX1rkqurEYcS4L30x8FS9vWuxZTpIrd99mNW%2FziVVNf9Q0SRt%2Fkp0wsr4aW%2F%2BrcQVkcea9xP3BD1SP%2BcH6lTJ%2BV%2BKMndf2ye%2FYLpo%2FYGPU%2ByfPv%2FhTw0pg2IluehoZI4170WWvUbP2vHBrgu9b83cq%2FtXqyq42aX%2FCMaG1QHzKJQ1nDAZ%2F3H1k%2BsojjZv%2Fglnl4OryZyr0JdJa9FxdvdfwgIbKGAo%2FN754W6r2v9fWX9adWeuTyf3ZX3vVw1J%2BKTfdDGj7zQozWIymNSmPyfH%2Bwi99D4TEKlrDaXBv5CRmEXsfCtwYDQIhdCn86TYnUGh%2FL%2Frkl20nqV%2FUx3vv%2BSy3vXlverRanUoR292zDrAYCt1j%2Bv6Kz9WHv9FTgt%2FX39dz5C4Z1PfwXYT8hjGQlZc9v3IQ2L%2FZHXk%2FNeR33Wqxdo%2F2ra1ePK992M%2BXvV%2FdxtwY1613%2BQRknvxeVE%2FdL89fLMSwsqsui%2Fr%2BX%2BvPcbZ6fi0RzJ%2FflRysZhAXVDY%2F82vF1qTu68nLS%2FR3it1gkyZfOKXx%2Fv%2FZ2N9TovVvXrr3RZeqFRfmI7%2BP7%2FcsOXQlC%2BuEavtYu1lXEy%2BvfVzoulW1y%2BT3kusR7RsvN%2FXK4AAAELUGaTZNqBXXoS52teEf%2Ff%2F%2F%2Ff%2Fxa1%2BtfrX%2F%2Ff%2Faxd%2Ffa%2B7VztYu1c%2F%2F%2FXv1In610d1q%2Fau7%2BEa4he%2BLl9XJs2l4wUa92devhAVXqwpwgKU94QGFJiz%2FPVKSn0KWTmu0di%2FVz9av%2Flv1q%2FV%2FiPLvJl9GlXq9z16PqTi6uuW%2BIW%2F65eGq5d36v3Lrk%2BP%2Ff%2Fl3PS3%2Br5L761g%2BX9ex3d8T4Y1a9WDDUtXdr3dcRN4Ix0qmVSy7Ie793aPl8UvVtfJVdXV1k3qtXxPcnPV%2BEK5ZPz%2Fy%2B%2F5zL5amvWGt%2F5%2FMtdI8vnVu%2Bb%2BlevXLq%2BWhXX3RKxVd7q9%2BjPzoTXRKv7%2FsVKvKv9CXverXU%2FSvXyer%2Fqx%2BtdJVl7vuqIV6xwjnCQh33pU3Xe9HOv7g3y9%2B%2Fd5MmlfNQomuKV%2Bi5KpoILxwj1Dhk0FDtzLvts2ZX77Lvd2S86P19%2FDde9%2F%2FNvm60J6%2BVcpqW61ri1rvgtyeH5%2FjifmEDwK9IiwML5owDz%2F4QshxbOGUVws%2Fe3%2Biuyef0vuCToglY4a1Oosg%2FT%2FD9ZZ%2Bu914sl77nznW26%2F1%2F9bffW3U8vosp9%2FzCq1vXv3SQTtX8peXtr173BMcfTGvTG9R2f%2Fsgzp9WGe7qGWj%2FyfP%2BSenWQ0TJ9xPojPxMoAYdSeeCzX%2BTzFd3pe%2F4Zo8lqTp%2Fm89P8aHLCcK93nKvkfI%2BfLmou4gm%2FOIUdRHCmDMJD%2Fgj2OuvynQDhDwrECNasrziFnfEr%2FtfKPzmJSD8go4gO%2BWrVwsJCA2Xh1Gv497%2FfouV%2BuXzLK5EXsUt72T3D%2Btw0SNSd9Cl2v%2F2a7f4IS902ePDKJ3deHB77v1Ox97WcYvhlODcwRRs5asOG05eRW8A0WtG%2F3oJTBFmSjM5eNS98n1q7o6UNoQzsE4t2XBLuH%2B%2F4WI%2B1%2BViv40VdrHCAjyZIVu0d%2F1Z%2BtVuid79o7%2BX2QUq6s%2BCmPCyvDH9lvfL4QD269hPeYNiXHMH778orGsa5mPaL1q%2Fmsnpv%2BlVyfy7%2FY43OwgMqj5ft%2BvOV0dS3U6ZlbXhgiIlQnr9eret%2B%2B%2B%2B%2BwRitJLu%2BXvvsMle75TpTQ%2FufZL3s6PWNjJX3Pv35e%2B%2B%2BwTH3Y8xEPM2vk8VVy3zqO2a6fffeqvhgjJ5%2F9QnJhVVaG5SX2CQY9g312CGMXfs7OVgkzKZtikEQ%2FRtq7vs5e%2BPmifJ7uvqx3337qxVlvfvvbqCHH5H2BN5PRoL9CX7V79YOpWlvc%2F2czvjpLOWNlvvv3PX8kA3Osk8n9ez%2BzQmh%2BzkUYGxvX%2BS%2BwR02b%2B5dj%2F6vJL296G%2FQvq%2F7RYvVTp3fJtiojjk7DNpHdfj8vHl770b97v7u1l5BC5c6t3yrLl96l3a9lHSX5VY%2FQ2CrrQmvVq9cpPRGOfVDbot9L%2Fn8T%2Br8vLNdWveTwzoXkgBJJn%2BFRhM4Sky5klsya8hcyDTL1ILmBoEmU6V1utyKvsw8BPu4tpYW8f0NTVKTIQq4tJdy3yFY9pLSP15wWeNUgTwe3Q7Gq6042AJhHAAaFZw506Mqb2zFlUB0qYSgdlxq%2FXgUdctgr6Qg76rTNirLk5Nv7mBVMx%2BIu9gXtRDPYrrt0vLyA6bCqt74nl5iIvIUlggCoQDJM5cFXFPLYE9CFlKRTIJOiApEYyiaqFNNPTbFsKQnYz4VLCiWXSMUt547zwpiyBOQ3ow4HIcsuE5RS6oBTnSqkxlI%2FIGIsj4g5Ta38LWdvCYuu6iX48jLbiIGgNmJsYzYifhxycJwAEimf4jZyZVVyVlNewQuldVZKXiTKR5LtoV9WJJ2k7By0qOl2b8UWcxMSV8aXbU2ZuMDgvf7j00KmqvnScw%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%2B7ryZK7n1YY3dWvWO%2FqHc6rpf16SrruLMbQMN511q9l0J0KLFKo8EPclyckmE%2FaO1c1X33Xr0hPL%2F9VcWllgkNxPJbl8n4v4%2FJE5ByR01pkIJ8qip0vm4zvk8%2FJLye9kX6GlC0G0yP%2FB29iPms8DR%2F4v3PfaP1z8vd%2Bvdq7uTdYqyzbu92VhwQfGoQszLwmwd3fTquu9Xu07%2FhIsZaO92u%2F7I1YN%2FiJrFpqax332630XqfF3LRHkJP1N4RmiET3VBj73uxngw3NW%2BLce7KcU%2BQNNb1IKJ7q%2B%2B%2FiZvQnrhOkFroWxYjLRsgYXoD7D2UUh6e6JRjgQId7kXq%2B4H2yOb5pKefAHHyl%2Bw%2FrHF%2BMCHzG2lnn%2FtD1GkheMj1l%2BgdTuKUEeG%2B8n26m4LcY93fbJ5uTdBOmyxViJbaRwFRg3hv5p1Fj3YiXBm8NJm%2Bb7hI4%2F4CRt%2BHze%2F6jXu4gnd%2FLTcly6PV%2Fo9cv6ymJ4eSSYQM6aPLOTo1BV3bQ6IOrub%2FbYSeH3ZDl5QwH2KJDAnbwPGpUUnl%2FgwqXnX247I2CsPh1fg%2FZLv0XKe4w%2BtxrNPr0dBfHkFcgr0zi6WhGZl%2FyQIbMR%2Fu2VlGW7k9H99zliDZaPQDjYkqnxEZaG05aEv6klstl7aWbvLYiS8pxK%2BOp2x9Wvdq0v%2B6355PXpU%2BCoUpex6lAoy7gJH6A3n2%2Few5IWokP4DgN35Z6zxMzgYb4L5p5qVviukREw0ESLAKn%2BXJ4r36a%2B%2BvvZvuybd4YLN%2FiuD%2BWYwbql8vof%2FW6PKS%2FJXLJ9%2F%2FUr9clPVovnH9%2FkHO0gLiyRtfVeGYYiTOANgSj4kOgZFP3bSsJPz%2FJtEzpXEUiSf3fJc4Lzub13dn6KPI6VUEpmd3mx33FrVQYWbNf6yeD719EOJ9kN85t37%2FEdJxW%2FcuCSPyoerjEouKW76R4v11d1GZi8V8tCO%2FROk8J7b4zNhvq3mXl%2F3%2F1l%2BWGuu0CLkaTv6YrxwYT47S%2BteYQMJngtb3qz2Ndr6mnz3WWEvGGgowWClHa26BIIw0mp6%2FC4tQbmV8I6J%2Fb8PMtza1Pd90pPJ1ao%2FidLd6lchnFfl%2Bwrj4PAVn4ihgOvpBByeuF8kmDQ6Pr7y%2FfWCSPidlqTYp%2F%2FRyuB%2B50f6W92c91FhogG86Yg0ee%2Bslj6XS%2FYMKscn5oah6%2BT2B%2FauEyZsDUZjEt1l%2Fu6F5pDbKkbF96VjygJ%2FRdrp5%2FNoDeQkK9yqZYUxb07FL%2FfQ%2F4AyYtIVA9u7oVpeIy0x1oOc%2FxEH%2BbRe6cQ7geX1%2B1yy%2F%2FZxM58ZMaC%2FHm3q%2BifVa75atCnOIlfvJ6f%2B3yePbl%2BrpSzwMMFvl%2F7cmCZ9y2nyd35f4Li3uXg3%2BqtGfYIN78wNsyS3TuW64z2WkOuV1W19Amt1qhjuUIvfonZPX1v8UJY72cI2FuP4SIjMt463Upfv8M8qENJ6jinUGh%2FJ6J6RXl%2F7%2Fv8FOJ04jmXysX43t9IuWZf5i2d9orncR6xd9iBT77vt92dilm4779ibvoBpJny%2BlExzv7v7F7273zghLu7uzRtlD7Y6ks3aegr9r3%2BQ%2Byr34vmwiMwymzlzUsuz5U0kTG8veaSCI5cf7VeSbLkvPz%2FZiVs%2FoSzcra9xeilBQIfW94K9C3d5Pr%2Fu%2B%2F16pxRsIWdLu%2FvJ%2BX5KMxq8Mltz9fJ2f8mnT2COf%2FDL%2FX9%2BrvfcpkF%2B73u30h0Ek77k9%2Fuvx13D4kT2RaNUX%2FISHkfxvE7crNHGTiP5L8XeI7nJ%2B%2B9Ffkve%2F0Naru%2B5r8QlT8TxLFPvR4i%2B4UafrxF739idp72mvR6ko%2F%2BbGHP78ub0tJ9vmu%2F1RaqLRcr9TgqE%2BXkvGIo7d1iF3%2BhrqFPisuP16vRNWn%2B%2FdF75KvshHf%2BuWT8vd%2BSqja3uNrVdVZKI%2Bd%2F1AAABstBmk6TqgV3eX%2F4Rl9C6uefie%2FX9Y3%2F%2F%2F%2F%2F2sX%2F%2Fyd6vVnasf1BnUzxFrUk6yyfX95Pr8T%2BQEZNIuMeqL3M3ZTXAI%2Fp1fP6t%2FNIOR%2Fd3a9JajFJOWrWruXl5PcR4gjjjfwFPGmrb%2F7BRRlt9Gwd3OwQ5zUE7RXVnYKJcZ6BSb7yX40WOwxJNWM9H6NfMoTJH3LSLK%2B69Fyu%2B64n9TndrFfqxPk5PHr8nh%2F9SHP1ELmzbbo%2BWn9xOG9m9nw3EZaEH7rmkHIvKq8d51Cv%2F5VY%2FktUv6xXy3dDuxJejj6U%2FG%2FfS67%2BL1%2Bvfq5FLi9X6J6IMKKPnH%2Fdiuf0J1fddVdXiif16ulMl%2BtdyVizcaa8BlyzUEYvd%2B90RuxIh23jw%2F6D%2B4nlv0J77rW%2FXpLXq9XJJdj2jYdmispE%2F7lw9pIUbTqNGF2QMfEXpzktfaH5ftyCHVPPbhxAVeTxxDyXkJPWbkkiau%2FR79VTyLiu%2BkV6fphwYY0k7GvG%2B%2FNk3fsnd9j52%2BVhaK2eP8JFA3Z9A%2BJfMMS5Y6hWPW0F%2BGk%2BjrRKf77BcRy7QZxigZCUT999hqjCBxB4%2BJDhr%2BGp5HssxuwZyRbQkyYruEav3080nEyeCS7y0f1yeV%2FYcEBwWohLhAdUHhExPj9gq0UEenjSzGRIC%2Ff4hb1%2B%2BNXaL8%2F1ReM9RvYFwg0WQ6R3qOAMk0w2%2BnS4PukGCQcH0%2Bi%2FYkqJ33vvV4IJ7G2f2w9mutaCRhLP0CDO5x0E7Nw6snvbiECOcYJCQN9N%2BXlIc5IBj0LBb69Q8mLMH9Nz%2B8qnaEt%2BsVQgdWI1LxNS%2BEsy79d%2FWGhD3dceRIH%2FTCWxHqinApUdvNkKXmigHFVeFeHE5PnEC%2Bs2e2nGkhg55PP6TBaTOMF85p8snw0vk2vSlu7T6boWJu97%2BooRaqliiRQx8njpeCE7hkg8vp92GofSu76%2BiB33t3OZz4hM%2BzcNXHqXKFjmP%2ByaN%2BcklJwQLBa%2BziXfeR%2F6xVBbXr0mHf6xfxClUaKKGTpI6YYwwiiPqBOfAgdo%2F%2Bez%2FSCP4QkJP7%2Bg7YbwJvYE847Kk77%2F1IIDQ2Y4X%2F2CfuUYMgYGG5MRaqoEOS64c4oXe733bijO%2Fuz28%2F9ehtRF773spQzfH2qoi0tjkur2eCS%2Byiy%2F568%2FeT69fZ3%2BU%2Bdl16npKZeriKv3Wr566RXX0Fx1EwGMtQdwlAzBZgbX5EkeG3nBFejwe3Slrvv0v0fWhWiEtGI0HJ8%2F4TIkXGD04wmfffaK%2FYesb3MMNkrnGDq7M4wx%2FauHLOgMED7wZWsEm5TDpLnZ91i%2FOVfxre%2FRev1yvE%2B76R0q7yV5PG%2FS6ggOjFMEVDaBIGp0lgSclnrjKP%2BxaMVBx44XtCW7D4y91Y9ttKz7NNUX1dul9r4SEMXoW96OjFff0UTy%2FKaQXSQFo8N5IUCW2c1F9F4LxHDCnGNUooGdJqgPxmk%3D&media_id=1254206535166763008&segment_index=44" + }, + "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": "command=APPEND&media_data=%2FVuKFlIIc1Xxke%2F2Yz3fhMfeXJxHze9ehOG7T7MIe%2Fm6v5LktSWFcwbezhZkvB73DnrYH%2BUEWwnL9ZP3%2BuwxjQOu08mWuERrAONcpEr0mnFZvGjEyY5%2FgiKwMdBAfrneNv1AjtyM0%2BT3%2B7GE3c3Nm29yqM6%2F4TjNf7gy19omWT498lgM3fk8N%2FHlMIC4uPtEBjb7baJNRoZga%2BehPU3agsog%2FF%2B72IBUsXI3WiItUuc4%2Fxwxoy53vsEtKgbRu%2F0nEe0Lms36hYnQnqya9aknqia75eJ26RhG7706WX2u1FR1WmNCgTsKjk8PfFXfvfZ66VmgtIf53e%2B5r1amj2vku1Usv7fnKvjp5j0WXddijOUyMyM7%2BmPd%2B3cImLnsnd4cKVVUo32%2BzUChDwryrI8oXvOzxt4Vrn1v8uj%2BV21WsvWEOazahx7iXqvu0LvPJ2T1dsRzjIMMW4%2F5T1%2BdRmftWOUNlppIcX8Eb0fv2%2B77BIU%2BeuwQyEm%2BvvU%2BQmOPqnl799TXz6ipQkTj0I4QLnr5Pj%2FewRM9kO7%2FPEETfLR%2FG1FYu773q%2Byi7v2hTP%2B%2Fia9Dd%2BS8pevxvhtdaTtPvJ475Fk%2BnyIkSKNSeivs10%2FfYc7u754X99WtF%2FvrJ7qu0CiGKZxPbe5uHH%2FMhEJ1rAfDWIbl3d4JSXjzXbQdaH7CfWslvjkjkuTx9SLzajfIkWLu74%2FFcm6FxdPWM1fo%2FlXkonh1Rn8snPDJ8lfmSsa%2FNe%2Bvc%2FD7Qf4zT1vqy4Xv0NTrqidxqKe%2FQztte238i3fy8vqhcPuh2j7tX91e%2FWKtn%2FV6oRV%2BKI%2BTRRgyrHPvy0RL2rn1eVSc111qCKQ0at%2B%2FYgS5934AAAb6QZpPE8oFdcT9dL8%2FxX6F9%2F2rH%2F%2F%2F38UsX2sVesx%2Bp79Yv1iu69e%2FV69cpN1b9XODn%2Bv%2FXv1lXr1zfuvdr0u2usvxv0CMnLRvlRdemL477y5Ui%2B4XNlojcbZPuPtIM1NLQ4h%2FX6ufr1Pw9q19frXa9XJd%2FrVWp0k4le9n%2BkbvaJCc8wt%2F0C2YgoE8xI5Bx2y%2BXW2FcSUAIiu9Jf5%2BWssPXx%2F39hyNl17r6ZjLTkWwz4QM%2F%2BY59OpX%2BWCDUsPIP7zcqO5e6%2Bk9e%2F%2Bbm%2B5Cef%2FJp%2FNURkM%2B9reci%2BOy4vCKnIiZAZmNyw%2Fct%2Bv0xkSTNL6IRMny28n2hfcq%2B5wtBIumYiaWDXy5rJdQ3EwacXs6O3eKkc4r6RfeH6LOq7usnpJNP5qgccUtQ7W%2F5Bjzr%2BvV5Pd2hPeJ%2BFtDulZMnlu%2B6rm5%2FiL9Wongi%2BoLhEZeT5R8eLpA98ngtVZJJymmEK9CZSz9rlQpaFL8ternyK5d3y7ikTFk4y1w59q0l7rb9xJOVeVcpLfoS98str3fatJxPflNXJ3NsnYIzc3Fqaeh%2Fd921JfcTjY2Ql5YaoDUtXAuphJhK85da%2FLyDX2x%2BX%2FQThK4H2NhoQYAtGEugPpQ2XbQuL%2FBL7Zak4wRsZGSEi04w1uHxiWR%2FSL4m4kN%2F16gsWY%2FQvLtevC%2Bfpe7V636aS%2FmWx7rmOfzm2MihwQPvmPrbHGba%2F6BZrfNiA7sutd%2F4rOo2JMdTEfxpT4ceuDMXQ%2BJX7MM4lrWvHyGko%2FvuhEg9pI6pyWUUYhKKTcsH509DLoG%2BLclZ2cg5cvzYZlbatvi1Y40g%2FJAjj7JCy1VJz7CNqN7Pbd5SPPZ6Xcr4qhLI9oX1csvr00u3m0TJlERetKdAg0cmQ4lxGegkx0M8F%2FLg%2BMmULkCZn9W3lJBDh0TDfyx%2BuGU1f%2B%2Fwh4l%2Bqt%2FzMSf84lx51EeQv5SvvL%2FkuEREMYIXd%2FOSN6NxugxpoAn1rNTWkBVr4070mNifBtqjUnB43mpfPX9HhDpHJbvprYnt1E93DCjzBdi5bugbyDBHy6pc8Klj%2FurLhGjs%2Fx9aaZt%2F0FaJLYYC35SCD%2BihidzH%2F991aK9%2BvX66r17llvrpPmEFJGMQjPY39oE3SStfXLq333jLtpcNwviqChlSnrwr8ihWXGlYULTWpjXBGyNij%2FbJrL9HY5RRnHZeJr0M7HsEJXjyCevs29OwZyJSD3eyHmM1esmhHaauEp2LCSQrLQdaGDHXEtgzepN6f0OeevthxgL2J2FeDHavoOalHEB9SmT0%2F5HyfX%2FLhH0X36oT79Tp8XXE6vWuvuy%2F1WMFTUml5M5I3gMeim97%2BCaH2szfEt9Fz1pEmE8QktXKCfUYawmWpEE%2Ffgj%2BeEvr82bDQik%2BeessuFzv3Z58pvyfPub%2BGz8JeL3LpG3EJrrDhbv79OamoNiI7l0x%2B2jGTOT2%2F%2BZP0fr3Xqx%2FuS6hWqvn5e9r4SFTEoP6Xfai4V6dPKrLW%2B6D9KSJ%2F99q%2Bzrsl0XvYrZyr%2BzDiZ%2Fm3vam2IuNtDvILcjuSD2W9DyNDTR6whfJ61Vk9arvdqIKw5chtH%2F0L2nHbB8pYSwU31l56%2BjIiGSP%2BUuWy2rRe%2FXVRa9%2BsXa1%2Bsq4v1qrvl8Stym82jN8n4blhMCAjfss4xINLhLyDo6eiVMWU5v9Dvj4bKG7Wfb9GOpGi%2F%2FCJBRPGKfumXQoXjTLp3%2FFdRwLQTYOW%2F5Pbu0ymuax2p6IJJg80f7Iy%2FNct9W7yd3y%2BKoW%2Boz%2BS5dW7Hbv8QU8OhDjL5G9%2FiiuPDo%2Fd9YZxjZh9fX99eQxaDMr%2FCeokOWHkjS38oL7AY1R9jUhK1VkHE93%2B3xGgzkjkoDLlFMU6f79CNXfDu5PQ%2Bm98eEx%2FES5vcfGDTyerdC9X69EYT3E998u3sJCiXnhen8J27xdJrIIDJ5ad%2Bq8s%2Bfvy8tKtPJ6%2BtdlHuXOna0blFbvtkYFHUzye7WT6uync6CgalZm6%2BTwrwl33M%2FwRBG0klrxP5e%2B%2FS3ve%2FrT4WHBJm%2FfL6Cd1OkjZI5FY4SKfTLvb9AuK797%2BF3q6r0dZPTt11T5xC5DQwRfy72l7EDXfeQ3qLcIipR41uGYUR89kNrU6giw%2By3w7R9e4gh2XxWXPYIr3vy7iLBJukr6LyCb3btNCHluUnnfLf0Qsfb%2FJ5Jv%2BlUjmy%2FgGGWBH39ormT2b%2FPX3xgoPf0uXJ6Nvtcuyk0nvfJHQoU7Lfyas%2BcOSH9Okvetblmz7BGXdKLS93J3RKF98TVJ0q9WL%2B17lu%2B25F5F5FsV0OY5du4Iuk7DL33xbH3fl439el0kOfr7J3e3NLd9X8TQ6PRv%2Brd%2Bxq5VlXcmTk98I%2F2%2F6rXn%2BT5eTz%2Fyd3WU9X3EJ%2F1wAAABJNBmk%2BT6gV36EuNr8%2Barq69aki%2F%2B6vuvXPfrXc9y33VyXL%2FiPknvwdjTP8t2CSzwO01d6goI9Ki9fA7QOffrPY5RMdS%2FQ5H73a13Y75fqTyetdSsVa1LdUTXqZKi%2FcNEBLpeefd32Y4341qGqN9j5Ujvp9EwyfpP%2BmlZbs%2B6HbzEl%2B1VX6LV3jl9NNdq5UtQQ1j%2FkyNddb%2FaMzUTuG67%2BT5l1%2BpFcibm9e91arUzUTy%2F173Xu4i8nh%2Bvk3XN0uUvqdLwzu4y17eS44RanjmvGWjcnhe21c6EvUbOK%2BpXiLWK7q1OkuSYnB%2FmtCdfonckJEXuY1fJ5Vk%2FfaEt3%2BvXaueK3urxFq8lrUtr3YKBHNnNkXKpRe5I4Oj6S9Fd%2BKM5aeTCZYuJjjKL5tQNzx12X%2F%2B77q95K1deinTa%2F%2BcijZoWmj%2FVrh6lo98SKh5mpn567cXvlcf3U%2BYaNuhfRFLXE%2FESWreSUQmFkRG%2B4JI2la4R%2F4%2BCchrecJxyV9X4ZFu71%2BVi%2FzGvDqm5PzfwVy0cOommV4n33qdExmJj8R0DNPLnfvq1IWWX32urIjujU6EmafdZVBHPffKLETGhoHGobZbSWTzX3NjgIC%2F8UUzh0XP3evXJ6%2B%2Fter8NEwci7n45c%2BwkWwc9LvXmJu9uoVxiyWnhxKB3oV8ZMcerck9lI6sRwPprCn%2FlBGJY7G%2BvdWK9WvEa6Xoi%2B6X4sZELHHBP8nv%2B4IbzqMX4YjnlzR8pzhJfbz%2BjUNWq1%2FGzx5ezFzRerc3Mx9Gvd69sVe%2BhOVfdXXW9MkunfOCPYy5udo7v1lG8133k9rX9vsQeR6MP7lKsFm0ftiHf333zor9kLQpV7ncM1SYQZ78VX8OGWRnqe87%2F5OTz%2F%2B%2BX1NSz59FYEubmv0JrJ8z%2FSL3ffPSayDHBZxd3y%2B36gjJx0TDjqi4e32CO8MEmN35ihuL97xRDqd%2FUxs6hgP5ShRpwDfRHSkFN2%2Bup%2FzC5WPYJjOHUjLnIZS9EJu%2Bu%2BeI9DXwkten%2B1iuXlpK%2BjWq2M6mzV%2Bju5sUZo%2BFzd%2Ff4XLCPk%2FFYJbqUxg3yvlf9W4kqi7x3%2F%2BoIbx8j4N9ta%2BQERh%2F%2FoDfkzZMHwR%2FOuG5cFN6Y6IkoYCPC4L1%2BrS3p4aPFefsbgwGRjOM0h4QqFnUfMebf%2BfWv%2Bc3seXlDUOKZqj%2FWMaf%2Fnr%2BQYMMJ4P6Fvdxc7Gbut6cq5PV9ayfFLv3z9ii2N7s%2FuCa9%2BGp8oouVe%2BUTOyFlbWJVHZyCicbQalMfu8EoRd38rBU1Ou0nFjM2caHUH3OfHWpMI%2FPqx63xi%2Fjt7p05c7POQowKf9C612JM3MxD1M1iDz99xsT3k9nfzYJ%2BhVEuhZxN3lY2gxyanCBX3vN73fovUl%2FR%2BrWp%2FXlKIveT0VfU6d998vZPN9ihd77bsv%2FWYU9%2F0NyiSe3%2FUup9DGOXQ%2BCIqGnTcO5CeMSqvU%2FPz6P5%2B%2B%2FP5f3e1TvMR33RsitauvQ%2FrS%2F3V6v1fd7n%2B%2FZV7nq%2B8nw%2F%2Ffeov77%2FWDFbr1bh%2Fv9SJXrlXr0kE0vMGyXvy1cubLVJffeASgUlCgVCQUEwkEoWHAUCxECw0IYWCgmEoXEIzCreuXt%2FT2vd8zciVqZM1SjDib6X5DnsvB19vzxP2%2BdWkNvcvnzM%2BBzydVz6Xrl%2BnEL%2BAasjuqSsXPt2DJB9z88HztETy%2B4b09oihGlHlqO0ofsEUB6lYPitQ7c311fwdrs7xv0KTzNjOuORMFnsr%2BXfSelIAoJRkCpXdqC31fP3pckpdrU4%2BG8T73ZQu98dIajtMwiIsK3mqiVw7Jl%2BhAVIHZsDPwXiVashIC9X%2BLwvN6IMQBCFBAutLYfSJM9pYDgASAUkGoUCQUDAWCgWCgWCgYCgWIgWCgmCoUKxDCoRI5Vu9%2FP33u6zOK45RFaraUpfEvNWPS5f5Djy777%2FqX9FHDDf8x8Png7LC0n%2F%2BIvnprRfXk42QJ177JX03zRRthaygB2IJJl90l4iTAOFM843q54evia7XWphQzGfdycZJGOfb5Utgq%2BmNLEgm5pEK1x0KW1JBzahuXyZFmu6i6rtGwMDEgYG0RZPnRC3%2Fmh75mc1gbE1gKPKXWcg2CWeghBkcwiDVYQLu4UBg%2FsHIHg%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%2Fqf7X4Cw8N5554fOeuX9YxwvZtjOplqIXJSlfUuKQRxKg4ASgUiCgyCoWEgnCgYCgYCgVCwUEYUIYVCglKJ29ZW78dT368a3q8mm7ZdTnjczTqUnQ28Y6DuOfqJ2dlXGvu7P8jD1%2FtzfGkHoul4dy0r91vsPHCjMexKn6vR94JozfwO2%2B83AHLD4gM%2Bf2tK8J0YjXHxH%2B3%2BXinErDtzggziuzeiNnLCLXTyQO6yRdDy7vstc7Oy58Y3fd1dHd06Of9fZkk7LnlU8ubhHScl9nSrHV8gCY5dp%2FDETsWcMliqrEimK0CCgwhLYDgAAACP0GaUBQKBXd9%2FoW9CP9au79cqmI%2F8FVdf%2FWX%2B%2F9%2F%2F%2Br%2F%2Fv1%2FVu1r9X6%2F%2F%2F1qENieBCN6TrV9OJSM54JxPgnElsG7%2Fzejs%2B117U0svr0lq5%2BsX66v0aL9bj4Ict3cp74Qz0sh4GWH5afyxhx7%2FWLtFftWP16uW8E7q4jH58IZLk3rfViNXPxWK%2FpdS1TSyep0iPRmes%2FoT1cn69CmP0t8gwkO7Q3pbXqtYr9Wx2KzNXrFXr0u6t%2BsomdXr0K1VoT36xV6vFesUl16wVgi8GPd3UqFavyn0brxJuViVjV9ob3corS4Z%2FSsfqx8lesXIRJ6tfqxO18ww%2Ff714rnqxJmI%2B5Nzb3VaF6k4mTkXu1dNdq6XvDO%2FEDOHYsCg72L8gt7oaL%2F3mERkUuUnyyKI2mcvcb6F1EykEIDDUTb6d3x%2B4Sn97tfgrvfe9OsNrrBCd33P0ZLJ6v%2Ber5f9epK2bCd93k36E1%2BtS5y%2Fo3SezTr689eHE5f%2FPYJ3f4h%2BT2U%2FJAty5n6GZf%2F74n4mt0d6xOOd5u5WC%2BhD18RcnobUlghI79fnELGzx%2FXkvGQVM%2Fnr73f4JBTd7Im5OaS6tBfoixA7n9ZWV4JL37EvnKvvNO3fOT79XMfbcRia1XrUT4TFMctPJA%2FrKIXqU5WJWIj57Qtkq7W%2FIMvfc1xPmNN%2BleSq%2FQRZXG%2BTeJ35AhNTXsuK%2BS1eEr2739QSXvevLapfisv%2BHlYomHN63r0RlP9CehK%2BXFdehMVet5rk0vzXfPy%2FrFNAAAD3kGaUJQqBXLVJ6E9L667WK7knWKqprd33auXdevqppvWupekyavZVl3aZ73Ks3q1Vfq6qOWKvXYv11XrlJck%2FPcu%2FohBmI%2FerYIp2GE1YSfNfiLBmLQ24whI%2FW%2BsWurDV7%2Bj569%2F2WCdeYM3Y2H9WifR%2Bq65Y31qS0OY7XqqqpHe7mqu0JZXqxL6ur1i%2FWo30K6TYmEdUJy%2FV%2B1qb166snr%2F2K57kta%2FVjuX1yq1YxXL6xd%2FRRHB%2BMp26FpJfWq9Wll7W369XrL9XiNV6sIe1ar9QSDNxDkvrsEVy0QOA37%2FOdf0h2XvV2JEJEzwfYkxS9obBVrB3Ld3N69V3r1dX2hUWT3%2B%2FvfezsGEnZ3U%2FYKjCzLe8aGh0hjzCuLWJiEE%2B6MZfnezoIyEkDctHeUjafTViaBsrKMFK2bPaF6ktYq9au5qI%2FRe4N%2FieCwmi%2Fr13%2BQJUoQNPbvJ59d66%2B0Vsnj92E6BDxflhAdGXNPsTKSG2df0euNzsXrqru5MTmu%2FMV31hkR%2BaPNEQrwsv0Tu%2B68tq1%2BIlNpDYz7vvrfts5MR%2Fr%2BvMR910GYdyyXLdr5TI2MLq%2B5eI6kJrrk0qxOoN%2BAk%2Fow6Yfah%2FcfLzcl%2FBJ5vKvILdF%2FMZoHbF5f%2B8suFz%2FXuluqy3vXaE61p19RVNEZPk%2FkGW3%2FcozTPFerN%2FYY7s3vXh5Pp%2F5LO7%2FEUr93%2FXkKD8kD8kH2WeS%2BKJdOnJ39gjHtNbFPq%2FwSjMuR9b8H4cy2NRmuRQcYP20%2B9Lr0NIkl9167y5P9N9WfoRX5jcdZke3%2FgoCL78%2Bv9ih3JhWMiXXdVdX%2BKLjpdb89b4vMgPR9BjP2dd4kRz1bxhwd%2B4TFz5wTex1ur1PFdEqvW669%2FLNcV9a1V2vowhV%2FX4ot7w4plavoeUn9mX%2B7p7%2Bmr%2FMIzf6fGmTsXiI5KoN5GzjLRGG1R8vMxvv%2FJe%2F0CEu2qY5IolIpd980vopUqWi%2BC196%2BrK6yvyvJ71dNodLJ%2BX9Cd7VGb%2FcJYQvR9IhjW2nX1v1beVepe%2BvT%2FdaP80cff%2FfWhPbGsogrErD8T8%2Fz%2BrV5Ru7%2FL3f6vXoreL10vfdZ99dWT3trwyODqq%2BvsMZ5ddbLpFckyvfrVff4sQ4N7LlOyvPlanksGDN73HryiCnS3lo%2ByfXfXXXoWxv2u7uR%2BFfn91lercwx3SSqa9PfV1dda07%2FyYHkvfCf%2B%2FU0mJdKl3mXn%2B%2F1rk%2FqIf%2FaCOvn%2FWrvz6Tfk93ssvXr68snrXjiL02f5334l36t6Vilv0SUnaO5%2Bru1Sh9T3au56plbv9cpO6zf6XwiS78vlv%2FdQAAABAJBmlEUSgV9SEv%2BvfF9MvfE%2FJ%2F%2F0Yr%2Fr3wj%2BvfCXBz2r%2Bx%2F6v9f99r3%2F103%2F%2FxP%2BT5%2F%2B1%2F%2F2qZaFO0XvghXvQv5u%2FLXN%2BidJzyfcJKCTwi%2BLtwbMHyGvbfE%2BGyVB0mx60B%2F9rqQctz9ex3yx39XSt336r3fasav6IXq2RWJ7WXB0Tz8XtUvywQmhLwbqwJ928ThPeH9jolLv1Y%2FWp%2FVj6V3pV6tef2cUpta%2FLdbRxIsiuET%2FrlJXN4Xbm4J1ykFLXq3df061J6v3VLfrFfrF%2FUT3J5xC%2B2Mzv0iFvJzy%2F2rY7p%2F4jVYu5fV3v3f3dcq9%2BvZf%2BuulYP179eq%2BvJ5%2F9etfJl%2F%2FvVZTeuVZYsVxl4eDvfLQu3OsarHjLyqMYTOxfq8nv%2F1hWhvX6v2r1uvd3UuU3rhXrr4n9Yu7y%2F%2Fx46pNHbSGuUg2eUJx0ue%2BzOaStId5F0iZ93afyfFfy%2BhfWK%2Fk6Twci6%2F569eq5Z9m4cFJJTwXRn%2F7LII24i2uvz1RHUSP%2B3JElJnWjeT4L%2F0ZbMTPJ6XvkmImI689dIbafuw%2BXcHyh0rltBFyJzfd%2Bh7%2FN4b%2BXl%2F%2FuieLq5cvRucYvDt9f1Pgq8ONIpGCQOWhSOEB4WWQhfhk8f8LYHzKEvfUupoMjrY6mHwgJfjdNcsE%2BS%2FZqwk%2B1L8GFKOiIunG0CjyFw%2F4kEPPhaM25vFl8nsVSFJgINUfYjLfmoaiprkr2L6kfqx34mTZPk%2Br2hYrL72XOersq%2FtF7J4fkl5e9i4aJlMXVPGSJ%2BUms32epFE8PqUVjyCuQXKOxf9ntNd7dcn36qyDbJSRP2CKlj7WKn9nO%2Fx8bedf0099P%2Biv%2BvohNOCodL%2BCJnCPk%2BnaY67EygaPiS2GTfL5Pf9QUT53IkoCi0LSyqerpm%2FdXcvYIxb3svmjr7qxApLpEp9qVdgivvqtaYWvLo%2F1cpIoyP%2B1r3z84JOHGhO%2FOLv5yic0iDEnN4nJf6PlforO%2B%2B%2B0TucgqNAgPk8Evb2Xvd8nx%2F6Em6J996%2Bb3XfotIddnWirDZofUzqsrH9mEx4HgPsXORfnhKxvuoQaT0LaWLkQ5fH0T4%2B%2Fvqvw0Ypo4W1H7n%2Fqd3Nn6%2B0Qgy0NBAHRLzEVfZdIfy6PES0%2FMxl77EFazWdRvJ7vuSvUT24r%2B5H9Ib1XJCc06HYbr8nhttk3L1VdS5PB%2F%2B%2Bp%2Be6rbtuJyTxBPf%2F8TlJ6aWuhJ8n5r%2F9O8p7tvk%2FzXv3qXq0Vzbrk%2Fv%2F%2FRvz93ftXv3%2BjtFpVcnn0%2F1%2Bsqa%2B%2Ffye%2FJ25t6iwgNMvltH56up5NUEe%2Bl6SE6uTWouQnu%2F8t%2Fa1d9%2BbU9euFUTQqUueLiVfXl1ru1f3%2BpQw%2FRnl9ZXk94AAAALiQZpRlGoFffeT0%2FqhkXa%2FXu%2B6tW8FlYv%2F%2B%2B%2BiOf%2F5Fbvh5%2FXr%2Bv1i%2FV3at2rfJ3%2Fk9v%2FCGcgxaf79e7%2BIr1yk9WdrVYW1Av68FfJ6eCGCkTqsvw34FY3Zh0vB0st1T47vjsutQSXl3%2Brq6on9aov%2F9%2BuXxckvOhTO9xP32%2FLHfX32hLqFLY5epelucvfaxd3zK5V93dXz16FNq%2FZ13332hr1fEy0SrLFYrVq5Ja55L5e9v%2BV3ITd91aGZVdVoWyTdaj%2FXr4qa%2B71vklHeSLdT98hdXLd5db%2Fr1JjSdy5eG4bl777vvrv175O5vV79elvi1Y5fJrBD3O%2FP333337r1XVrUXxNX2rP1ebN4%2Fur77777Q7vJ4Pl4PlNLnNaHxd3fxd3NfE8%2BjfthLl%2B%2B%2B%2BzFopvR0E%2BaHn%2B%2B%2B%2Fqqru%2FQ2V8XV0OZXKlZvJXgh8pgglLnP3p0tKruS9HffkXX333318nz3aHyrBmPqEViq%2Fpcu5c%2F%2BifApOuYJRmG%2B%2BzZwgDL%2Bta6KrrnQSX32Ue94rE0WKs39euzeX2Gk98%2FbCD2%2Fw2XFgVcJ2LF%2FYUtbNKXwRSkikvZc9TiObJP7dLn7nxVD8rv0qieXxGnfov2%2BUJJX6uuienuXk9cvS2FSdc6Lr7OI2Vsl8jcipGvLz1IRJCMvoL15Fr%2Fxfw%3D&media_id=1254206535166763008&segment_index=45" + }, + "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%2FSE5X613%2BvX61drFW6u%2FVk3q%2Fct8%2FVya1V9q980vr3zeqxy7XuqvWVcnyeI%2FJXJv6KOyS%2BSxyCPqHEzg%2FWLnWN1ZPX%2FXvm7%2BJn9XPlVx9XKqV5fy%2F35BgIf8%2BugQ4MYLXc%2Fryx3L7tC3J7sV3fI101evSbN1V9ecYvpF3v7%2FRHkya9BHq9e6rqVjrxxPOxyypNVNxH6tJyfL%2FeT3W6%2BqpWfS9NusX6sdrWOf1c369XMrfERHrKt16Tnk2okJLc%2FrV44n0byLB8hh2e2hg6P%2Bm0u64juRfOvVLXEXslIJvuifGa9%2BWwkTEXuSiEE4u1wk5viKwzkvon9XehNcR8RUxHDhPCSbXW7q%2B6RVdXdXdEd%2FF81Vy0Vz91%2B%2FkWXl%2BuX3JX3a5P3%2B7J61rZghy%2Bn9P3feT3WTuXm7u%2FH69BGV8l%2F0u5ydKvXffPc3K3fn92EC33Td8%2FxCH9V38kssTKzXV8sT336Zwgv8f%2BnSdV36CPX9X01093yyub%2B%2BXn7777yeHu9yVS988vr13JL5C1c3dOv76%2BwSBR79nMnLy1L2hrmp%2B%2Beuavu0Liu%2B9v99yy8vP37fenb9lyeCvr33333W3JlXDt3LfffffLy8%2FLy3V32gtrn2E%2FfffejXvxvgj74xOROfzie5PQZqvXLJ9%2F%2FfiS6ClRO9zb6duurvvvl3Iv3y89XcOJ7Ly8vE3693LVTi%2B5K%2BXv2WrQQ7Z%2Bz%2B%2B%2B%2B6i6u5%2B4uiLzvl5e%2B%2B6vviayUE3%2FWvl2hD%2BvffPy98vaweJ%2FHequFV2tfrXLSfkm1c7qZVdoXkJ8%2F83okH65XLz8%2BAAAAJxQZpSlKoFf6ExS39K5%2BtfG1UtfrX65V6t7rV%2BrletRPq42ur9cP1ruT1rq61i7%2Ba617tYO5fOZcG%2BX%2B9ZLq%2F0Jar%2FV79Xk1WLteu1%2BNyaqz3WK9QQjI0175PjRP9a1%2FV69C2ktW%2FXu1ljumk9Yq5lqvWuu7V%2B5al73V5H%2BcYvl1L6ojh63dXdoIv2rudX%2Bl7FbivV79Xn8oQ461KT6%2F7upiL6QRYbV%2B%2BXv2avWv1ruLnp6rLKtVoXctbrq6%2B1jnF161V9165S81Unr5Nd8lVrV9LVzy8101%2Br3MRXqx81wjuJ68UEroGzSSo1r7m5MSLaCcu7vxb516X1bvz6yZLvX84SXhudf%2Fz1%2BchPIqeI9Si%2FJNaW6ZBNwX1Knjt%2BuVetRGTsmv13tvv%2B%2FMEqHN%2Fr1a%2BTes2xM1yRF4jeTLrfitCixSr0LSVSHr59KZ9ckTfoJ36bqktarqT%2FJvc4UUsJZte5rm70ull841f4bwGopEISbV0Le%2BJ5ZPRW7rLkuuvJp9%2Ft1JS6%2BqCmvzhFf2j2TXYt7ieS79HikuomVbfUiVdb%2Btl911OFlVa%2F19ULw9T%2Bxo0VaD5Pf9fc4rDU8%2F84Jxox78YB679nEL8q08MyxNxa7b9T1OoyK%2FU1%2BitJNXqyIGWiBdklkh%2Ba%2F9Fon3r%2BT39L9uK%2Bd7pe567jp58m%2FSFjbR1fosu6pELeIhOn5PJeTdo9r9W7qkke6yTXqccvp5tH33WqO569IhLlUQr9r0lJWV1l%2B9XU9TWlLne5eX%2F%2Br9vu6pf%2FWLy%2B17ieLq%2BWa5KWpKsndyRF4rq7orue%2B7tGfbnMuXybif9Ffu%2BI5rvuaAEsmf4VGE5QsUKkSZcq1Lyp5sKWYboUboviN4j3Sp4RMjCruNJ3XWTpwokSgTr5M5AS7%2B9Vp0WndPAaxDGIf%2F9vU8pqqaZJLccyzA0%2BP5zZSYRiFCYmInXtfG835%2Bl4OtwtXR0Yu2Ozjs99EXRSJUv8DSYrTOj0lwFi%2BzKoBCDerIdvV42n9gElY7jcQYX%2BHGDVJv352tMWcJ231acAr6g%2FgfES%2BghP517hB0lmoUf79et6356Wn50k10KO7KyMCpB%2F9spkg5xvMT1IAVHq45NCo2AHARiZ%2FlvZRlSypCqnnoe9feQADzH%2FSAAP9F50AA%2BJ%2F5AAHxv%2FIAA1%2Fff8fSAAAAB9v0Hj%2FJAAAAD7L%2B3%2Fx4wAAAAdV%2B3dN%2BXd7xQAAAAAAP8T4DT2WAAAAAAA%2Fu3S%2F3QAAB7cdwAAAAAAAAADgAAADYNtb292AAAAbG12aGQAAAAAx8rup8fK7qgAAV%2BQAAelgAABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAGGlvZHMAAAAAEICAgAcAT%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 new file mode 100644 index 00000000..0637a088 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testResetLastResponse.json @@ -0,0 +1 @@ +[] \ 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 new file mode 100644 index 00000000..572e6b85 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testSetOauthToken.json @@ -0,0 +1,46 @@ +[{ + "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 new file mode 100644 index 00000000..6a5c021e --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testSetProxy.json @@ -0,0 +1,20 @@ +[{ + "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 new file mode 100644 index 00000000..9f7acf1a Binary files /dev/null and b/twitter/vendor/abraham/twitteroauth/tests/kitten.jpg differ diff --git a/twitter/vendor/abraham/twitteroauth/tests/mocks.php b/twitter/vendor/abraham/twitteroauth/tests/mocks.php new file mode 100644 index 00000000..b3127313 --- /dev/null +++ b/twitter/vendor/abraham/twitteroauth/tests/mocks.php @@ -0,0 +1,21 @@ + + * 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 new file mode 100644 index 00000000..f27399a0 --- /dev/null +++ b/twitter/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/twitter/vendor/composer/autoload_classmap.php b/twitter/vendor/composer/autoload_classmap.php new file mode 100644 index 00000000..1573664b --- /dev/null +++ b/twitter/vendor/composer/autoload_classmap.php @@ -0,0 +1,14 @@ + $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 new file mode 100644 index 00000000..b7fc0125 --- /dev/null +++ b/twitter/vendor/composer/autoload_namespaces.php @@ -0,0 +1,9 @@ + 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 new file mode 100644 index 00000000..35a93688 --- /dev/null +++ b/twitter/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\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 new file mode 100644 index 00000000..740109de --- /dev/null +++ b/twitter/vendor/composer/autoload_static.php @@ -0,0 +1,53 @@ + + 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 new file mode 100644 index 00000000..c5b5220e --- /dev/null +++ b/twitter/vendor/composer/ca-bundle/LICENSE @@ -0,0 +1,19 @@ +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 new file mode 100644 index 00000000..d8205ec5 --- /dev/null +++ b/twitter/vendor/composer/ca-bundle/README.md @@ -0,0 +1,85 @@ +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 new file mode 100644 index 00000000..5213e976 --- /dev/null +++ b/twitter/vendor/composer/ca-bundle/composer.json @@ -0,0 +1,54 @@ +{ + "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 new file mode 100644 index 00000000..264923b3 --- /dev/null +++ b/twitter/vendor/composer/ca-bundle/res/cacert.pem @@ -0,0 +1,3138 @@ +## +## 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----- +MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT +EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx +ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6 +XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk +lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB +lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy +lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt +66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn +wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh +D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy +BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie +J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud +DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU +a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT +ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv +Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3 +UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm +VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK ++JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW +IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1 +WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X +f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II +4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8 +VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u +-----END CERTIFICATE----- + +QuoVadis Root CA 3 +================== +-----BEGIN CERTIFICATE----- +MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT +EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx +OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg +DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij +KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K +DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv +BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp +p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8 +nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX +MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM +Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz +uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT +BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj +YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 +aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB +BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD +VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4 +ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE +AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV +qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s +hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z +POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2 +Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp +8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC +bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu +g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p +vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr +qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto= +-----END CERTIFICATE----- + +Security Communication Root CA +============================== +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw +8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM +DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX +5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd +DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2 +JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g +0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a +mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ +s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ +6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi +FL39vmwLAw== +-----END CERTIFICATE----- + +Sonera Class 2 Root CA +====================== +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG +U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw +NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh +IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3 +/Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT +dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG +f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P +tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH +nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT +XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt +0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI +cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph +Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx +EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH +llpwrN9M +-----END CERTIFICATE----- + +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----- +MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw +EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN +MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp +c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq +t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C +jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg +vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF +ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR +AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend +jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO +peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR +7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi +GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64 +OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov +L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm +5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr +44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf +Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m +Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp +mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk +vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf +KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br +NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj +viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ +-----END CERTIFICATE----- + +SwissSign Silver CA - G2 +======================== +-----BEGIN CERTIFICATE----- +MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT +BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X +DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3 +aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG +9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644 +N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm ++/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH +6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu +MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h +qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5 +FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs +ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc +celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X +CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB +tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 +cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P +4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F +kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L +3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx +/uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa +DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP +e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu +WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ +DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub +DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u +-----END CERTIFICATE----- + +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----- +MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG +EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz +MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu +QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ +03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK +ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU ++zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC +PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT +OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK +F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK +0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+ +0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB +leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID +AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+ +SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG +NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx +MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O +BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l +Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga +kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q +hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs +g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5 +aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5 +nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC +ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo +Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z +WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== +-----END CERTIFICATE----- + +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----- +MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE +BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG +A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC +R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE +ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn +dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ +FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+ +5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG +x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX +2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL +OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3 +sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C +GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5 +WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E +FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w +DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt +rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+ +nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg +tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW +sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp +pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA +zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq +ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52 +7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I +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 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----- +MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxDjAM +BgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24x +MTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYw +MjEyMTczOTM5WhcNNDEwMjEyMTczOTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx +EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NM +LmNvbSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2RxFdHaxh3a3by/ZPkPQ/C +Fp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aXqhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8 +P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcCC52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/ge +oeOy3ZExqysdBP+lSgQ36YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkp +k8zruFvh/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrFYD3Z +fBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93EJNyAKoFBbZQ+yODJ +gUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVcUS4cK38acijnALXRdMbX5J+tB5O2 +UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi8 +1xtZPCvM8hnIk2snYxnP/Okm+Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4s +bE6x/c+cCbqiM+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGVcpNxJK1ok1iOMq8bs3AD/CUr +dIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBcHadm47GUBwwyOabqG7B52B2ccETjit3E+ZUf +ijhDPwGFpUenPUayvOUiaPd7nNgsPgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAsl +u1OJD7OAUN5F7kR/q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjq +erQ0cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jra6x+3uxj +MxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90IH37hVZkLId6Tngr75qNJ +vTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/YK9f1JmzJBjSWFupwWRoyeXkLtoh/D1JI +Pb9s2KJELtFOt3JY04kTlf5Eq/jXixtunLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406y +wKBjYZC6VWg3dGq2ktufoYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NI +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----- +MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJV +UzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2 +ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9u +IEF1dGhvcml0eTAeFw0xNzA4MjMxOTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJV +UzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2 +ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9u +IEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALldUShLPDeS0YLOvR29 +zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0XznswuvCAAJWX/NKSqIk4cXGIDtiLK0thAf +LdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4Bq +stTnoApTAbqOl5F2brz81Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9o +WN0EACyW80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotPJqX+ +OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1lRtzuzWniTY+HKE40 +Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfwhI0Vcnyh78zyiGG69Gm7DIwLdVcE +uE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm ++9jaJXLE9gCxInm943xZYkqcBW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqj +ifLJS3tBEW1ntwiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1UdDwEB/wQEAwIB +BjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W0OhUKDtkLSGm+J1WE2pIPU/H +PinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfeuyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0H +ZJDmHvUqoai7PF35owgLEQzxPy0QlG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla +4gt5kNdXElE1GYhBaCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5R +vbbEsLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPTMaCm/zjd +zyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qequ5AvzSxnI9O4fKSTx+O +856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxhVicGaeVyQYHTtgGJoC86cnn+OjC/QezH +Yj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu +3R3y4G5OBVixwJAWKqQ9EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP +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 new file mode 100644 index 00000000..0109ba03 --- /dev/null +++ b/twitter/vendor/composer/ca-bundle/src/CaBundle.php @@ -0,0 +1,353 @@ + + * + * 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 new file mode 100644 index 00000000..2649372c --- /dev/null +++ b/twitter/vendor/composer/installed.json @@ -0,0 +1,317 @@ +[ + { + "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 new file mode 100644 index 00000000..85f97fc7 --- /dev/null +++ b/twitter/vendor/composer/installers/LICENSE @@ -0,0 +1,19 @@ +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 new file mode 100644 index 00000000..6de40853 --- /dev/null +++ b/twitter/vendor/composer/installers/composer.json @@ -0,0 +1,105 @@ +{ + "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 new file mode 100644 index 00000000..01b8a416 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/AglInstaller.php @@ -0,0 +1,21 @@ + '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 new file mode 100644 index 00000000..79a0e958 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/AimeosInstaller.php @@ -0,0 +1,9 @@ + 'ext/{$name}/', + ); +} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php new file mode 100644 index 00000000..89d7ad90 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php @@ -0,0 +1,11 @@ + '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 new file mode 100644 index 00000000..22dad1b9 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/AsgardInstaller.php @@ -0,0 +1,49 @@ + '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 new file mode 100644 index 00000000..d62fd8fd --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/AttogramInstaller.php @@ -0,0 +1,9 @@ + 'modules/{$name}/', + ); +} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/BaseInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/BaseInstaller.php new file mode 100644 index 00000000..7082bf2c --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/BaseInstaller.php @@ -0,0 +1,136 @@ +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 new file mode 100644 index 00000000..e80cd1e1 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/BitrixInstaller.php @@ -0,0 +1,126 @@ +.`. + * - `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 new file mode 100644 index 00000000..da3aad2a --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/BonefishInstaller.php @@ -0,0 +1,9 @@ + '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 new file mode 100644 index 00000000..6352beb1 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/CakePHPInstaller.php @@ -0,0 +1,82 @@ + '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 new file mode 100644 index 00000000..ab2f9aad --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/ChefInstaller.php @@ -0,0 +1,11 @@ + '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 new file mode 100644 index 00000000..6673aea9 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/CiviCrmInstaller.php @@ -0,0 +1,9 @@ + 'ext/{$name}/' + ); +} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/ClanCatsFrameworkInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/ClanCatsFrameworkInstaller.php new file mode 100644 index 00000000..c887815c --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/ClanCatsFrameworkInstaller.php @@ -0,0 +1,10 @@ + '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 new file mode 100644 index 00000000..c7816dfc --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/CockpitInstaller.php @@ -0,0 +1,34 @@ + '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 new file mode 100644 index 00000000..3b4a4ece --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/CodeIgniterInstaller.php @@ -0,0 +1,11 @@ + '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 new file mode 100644 index 00000000..5c01bafd --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/Concrete5Installer.php @@ -0,0 +1,13 @@ + '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 new file mode 100644 index 00000000..d37a77ae --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/CraftInstaller.php @@ -0,0 +1,35 @@ + '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 new file mode 100644 index 00000000..d94219d3 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/CroogoInstaller.php @@ -0,0 +1,21 @@ + '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 new file mode 100644 index 00000000..f4837a6c --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/DecibelInstaller.php @@ -0,0 +1,10 @@ + 'app/{$name}/', + ); +} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/DokuWikiInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/DokuWikiInstaller.php new file mode 100644 index 00000000..cfd638d5 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/DokuWikiInstaller.php @@ -0,0 +1,50 @@ + '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 new file mode 100644 index 00000000..21f7e8e8 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/DolibarrInstaller.php @@ -0,0 +1,16 @@ + + */ +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 new file mode 100644 index 00000000..fef7c525 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/DrupalInstaller.php @@ -0,0 +1,16 @@ + '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 new file mode 100644 index 00000000..c0bb609f --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/ElggInstaller.php @@ -0,0 +1,9 @@ + 'mod/{$name}/', + ); +} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/EliasisInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/EliasisInstaller.php new file mode 100644 index 00000000..6f3dc97b --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/EliasisInstaller.php @@ -0,0 +1,12 @@ + '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 new file mode 100644 index 00000000..d5321a8c --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/ExpressionEngineInstaller.php @@ -0,0 +1,29 @@ + '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 new file mode 100644 index 00000000..f30ebcc7 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/EzPlatformInstaller.php @@ -0,0 +1,10 @@ + '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 new file mode 100644 index 00000000..6eba2e34 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/FuelInstaller.php @@ -0,0 +1,11 @@ + '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 new file mode 100644 index 00000000..29d980b3 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/FuelphpInstaller.php @@ -0,0 +1,9 @@ + 'components/{$name}/', + ); +} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/GravInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/GravInstaller.php new file mode 100644 index 00000000..dbe63e07 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/GravInstaller.php @@ -0,0 +1,30 @@ + '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 new file mode 100644 index 00000000..8fe017f0 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/HuradInstaller.php @@ -0,0 +1,25 @@ + '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 new file mode 100644 index 00000000..5e2142ea --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/ImageCMSInstaller.php @@ -0,0 +1,11 @@ + '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 new file mode 100644 index 00000000..352cb7fa --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/Installer.php @@ -0,0 +1,274 @@ + '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 new file mode 100644 index 00000000..c6c1b337 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/ItopInstaller.php @@ -0,0 +1,9 @@ + 'extensions/{$name}/', + ); +} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/JoomlaInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/JoomlaInstaller.php new file mode 100644 index 00000000..9ee77596 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/JoomlaInstaller.php @@ -0,0 +1,15 @@ + '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 new file mode 100644 index 00000000..9cb7b8cd --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/KanboardInstaller.php @@ -0,0 +1,18 @@ + 'plugins/{$name}/', + ); +} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/KirbyInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/KirbyInstaller.php new file mode 100644 index 00000000..36b2f84a --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/KirbyInstaller.php @@ -0,0 +1,11 @@ + '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 new file mode 100644 index 00000000..7143e232 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/KodiCMSInstaller.php @@ -0,0 +1,10 @@ + '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 new file mode 100644 index 00000000..dcd6d263 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/KohanaInstaller.php @@ -0,0 +1,9 @@ + 'modules/{$name}/', + ); +} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/LanManagementSystemInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/LanManagementSystemInstaller.php new file mode 100644 index 00000000..903143a5 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/LanManagementSystemInstaller.php @@ -0,0 +1,27 @@ + '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 new file mode 100644 index 00000000..be4d53a7 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/LaravelInstaller.php @@ -0,0 +1,9 @@ + 'libraries/{$name}/', + ); +} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/LavaLiteInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/LavaLiteInstaller.php new file mode 100644 index 00000000..412c0b5c --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/LavaLiteInstaller.php @@ -0,0 +1,10 @@ + '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 new file mode 100644 index 00000000..47bbd4ca --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/LithiumInstaller.php @@ -0,0 +1,10 @@ + '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 new file mode 100644 index 00000000..9c2e9fb4 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/MODULEWorkInstaller.php @@ -0,0 +1,9 @@ + 'modules/{$name}/', + ); +} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/MODXEvoInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/MODXEvoInstaller.php new file mode 100644 index 00000000..5a664608 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/MODXEvoInstaller.php @@ -0,0 +1,16 @@ + '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 new file mode 100644 index 00000000..cf18e947 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/MagentoInstaller.php @@ -0,0 +1,11 @@ + '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 new file mode 100644 index 00000000..e463756f --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/MajimaInstaller.php @@ -0,0 +1,37 @@ + '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 new file mode 100644 index 00000000..ca3cfacb --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/MakoInstaller.php @@ -0,0 +1,9 @@ + '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 new file mode 100644 index 00000000..3e1ce2b2 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/MauticInstaller.php @@ -0,0 +1,25 @@ + '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 new file mode 100644 index 00000000..30a91676 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/MayaInstaller.php @@ -0,0 +1,33 @@ + '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 new file mode 100644 index 00000000..f5a8957e --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/MediaWikiInstaller.php @@ -0,0 +1,51 @@ + '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 new file mode 100644 index 00000000..4bbbec8c --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/MicroweberInstaller.php @@ -0,0 +1,111 @@ + '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 new file mode 100644 index 00000000..0ee140ab --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/ModxInstaller.php @@ -0,0 +1,12 @@ + '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 new file mode 100644 index 00000000..a89c82f7 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/MoodleInstaller.php @@ -0,0 +1,57 @@ + '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 new file mode 100644 index 00000000..08d5dc4e --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/OctoberInstaller.php @@ -0,0 +1,47 @@ + '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 new file mode 100644 index 00000000..5dd3438d --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/OntoWikiInstaller.php @@ -0,0 +1,24 @@ + '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 new file mode 100644 index 00000000..3ca7954c --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/OsclassInstaller.php @@ -0,0 +1,14 @@ + '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 new file mode 100644 index 00000000..49940ff6 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/OxidInstaller.php @@ -0,0 +1,59 @@ +.+)\/.+/'; + + 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 new file mode 100644 index 00000000..170136f9 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/PPIInstaller.php @@ -0,0 +1,9 @@ + 'modules/{$name}/', + ); +} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/PhiftyInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/PhiftyInstaller.php new file mode 100644 index 00000000..4e59a8a7 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/PhiftyInstaller.php @@ -0,0 +1,11 @@ + '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 new file mode 100644 index 00000000..deb2b77a --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/PhpBBInstaller.php @@ -0,0 +1,11 @@ + '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 new file mode 100644 index 00000000..4781fa6d --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/PimcoreInstaller.php @@ -0,0 +1,21 @@ + '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 new file mode 100644 index 00000000..c17f4572 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/PiwikInstaller.php @@ -0,0 +1,32 @@ + '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 new file mode 100644 index 00000000..903e55f6 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/PlentymarketsInstaller.php @@ -0,0 +1,29 @@ + '{$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 new file mode 100644 index 00000000..5eb04af1 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/Plugin.php @@ -0,0 +1,17 @@ +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 new file mode 100644 index 00000000..dbf85e63 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/PortoInstaller.php @@ -0,0 +1,9 @@ + '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 new file mode 100644 index 00000000..4c8421e3 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/PrestashopInstaller.php @@ -0,0 +1,10 @@ + '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 new file mode 100644 index 00000000..77cc3dd8 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/PuppetInstaller.php @@ -0,0 +1,11 @@ + 'modules/{$name}/', + ); +} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/PxcmsInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/PxcmsInstaller.php new file mode 100644 index 00000000..65510580 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/PxcmsInstaller.php @@ -0,0 +1,63 @@ + '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 new file mode 100644 index 00000000..0f78b5ca --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/RadPHPInstaller.php @@ -0,0 +1,24 @@ + '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 new file mode 100644 index 00000000..252c7339 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/ReIndexInstaller.php @@ -0,0 +1,10 @@ + '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 new file mode 100644 index 00000000..09544576 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/RedaxoInstaller.php @@ -0,0 +1,10 @@ + '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 new file mode 100644 index 00000000..d8d795be --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/RoundcubeInstaller.php @@ -0,0 +1,22 @@ + '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 new file mode 100644 index 00000000..1acd3b14 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/SMFInstaller.php @@ -0,0 +1,10 @@ + '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 new file mode 100644 index 00000000..7d20d27a --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/ShopwareInstaller.php @@ -0,0 +1,60 @@ + '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 new file mode 100644 index 00000000..81910e9f --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/SilverStripeInstaller.php @@ -0,0 +1,35 @@ + '{$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 new file mode 100644 index 00000000..762d94c6 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/SiteDirectInstaller.php @@ -0,0 +1,25 @@ + '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 new file mode 100644 index 00000000..83ef9d09 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/SyDESInstaller.php @@ -0,0 +1,49 @@ + '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 new file mode 100644 index 00000000..1675c4f2 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/Symfony1Installer.php @@ -0,0 +1,26 @@ + + */ +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 new file mode 100644 index 00000000..b1663e84 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/TYPO3CmsInstaller.php @@ -0,0 +1,16 @@ + + */ +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 new file mode 100644 index 00000000..42572f44 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/TYPO3FlowInstaller.php @@ -0,0 +1,38 @@ + '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 new file mode 100644 index 00000000..158af526 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/TheliaInstaller.php @@ -0,0 +1,12 @@ + '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 new file mode 100644 index 00000000..7c0113b8 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/TuskInstaller.php @@ -0,0 +1,14 @@ + + */ + 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 new file mode 100644 index 00000000..fcb414ab --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/UserFrostingInstaller.php @@ -0,0 +1,9 @@ + '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 new file mode 100644 index 00000000..24ca6451 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/VanillaInstaller.php @@ -0,0 +1,10 @@ + '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 new file mode 100644 index 00000000..7d90c5e6 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/VgmcpInstaller.php @@ -0,0 +1,49 @@ + '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 new file mode 100644 index 00000000..2cbb4a46 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/WHMCSInstaller.php @@ -0,0 +1,10 @@ + '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 new file mode 100644 index 00000000..cb387881 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/WolfCMSInstaller.php @@ -0,0 +1,9 @@ + '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 new file mode 100644 index 00000000..91c46ad9 --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/WordPressInstaller.php @@ -0,0 +1,12 @@ + '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 new file mode 100644 index 00000000..27f429ff --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/YawikInstaller.php @@ -0,0 +1,32 @@ + '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 new file mode 100644 index 00000000..bde9bc8c --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/ZendInstaller.php @@ -0,0 +1,11 @@ + '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 new file mode 100644 index 00000000..56cdf5da --- /dev/null +++ b/twitter/vendor/composer/installers/src/Composer/Installers/ZikulaInstaller.php @@ -0,0 +1,10 @@ + '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 new file mode 100644 index 00000000..0de276ee --- /dev/null +++ b/twitter/vendor/composer/installers/src/bootstrap.php @@ -0,0 +1,13 @@ + + 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 new file mode 100644 index 00000000..6b0a5c73 --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/README.md @@ -0,0 +1,891 @@ +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 new file mode 100644 index 00000000..6c724a2a --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/bower.json @@ -0,0 +1,25 @@ +{ + "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 new file mode 100644 index 00000000..7addea7e --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/build.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/twitter/vendor/jublonet/codebird-php/composer.json b/twitter/vendor/jublonet/codebird-php/composer.json new file mode 100644 index 00000000..586f39c2 --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/composer.json @@ -0,0 +1,45 @@ +{ + "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 new file mode 100644 index 00000000..cd28e1c9 --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/phpunit.xml @@ -0,0 +1,26 @@ + + + + + + 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 new file mode 100644 index 00000000..87e7409c --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/phpunit.xml.hhvm @@ -0,0 +1,22 @@ + + + + + + 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 new file mode 100644 index 00000000..ee25bee1 --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/src/cacert.pem @@ -0,0 +1,3314 @@ +## +## 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----- +MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT +EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx +ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6 +XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk +lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB +lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy +lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt +66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn +wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh +D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy +BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie +J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud +DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU +a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT +ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv +Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3 +UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm +VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK ++JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW +IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1 +WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X +f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II +4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8 +VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u +-----END CERTIFICATE----- + +QuoVadis Root CA 3 +================== +-----BEGIN CERTIFICATE----- +MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT +EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx +OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg +DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij +KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K +DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv +BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp +p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8 +nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX +MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM +Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz +uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT +BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj +YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 +aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB +BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD +VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4 +ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE +AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV +qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s +hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z +POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2 +Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp +8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC +bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu +g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p +vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr +qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto= +-----END CERTIFICATE----- + +Security Communication Root CA +============================== +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw +8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM +DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX +5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd +DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2 +JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g +0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a +mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ +s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ +6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi +FL39vmwLAw== +-----END CERTIFICATE----- + +Sonera Class 2 Root CA +====================== +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG +U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw +NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh +IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3 +/Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT +dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG +f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P +tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH +nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT +XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt +0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI +cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph +Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx +EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH +llpwrN9M +-----END CERTIFICATE----- + +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----- +MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw +EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN +MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp +c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq +t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C +jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg +vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF +ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR +AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend +jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO +peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR +7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi +GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64 +OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov +L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm +5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr +44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf +Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m +Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp +mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk +vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf +KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br +NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj +viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ +-----END CERTIFICATE----- + +SwissSign Silver CA - G2 +======================== +-----BEGIN CERTIFICATE----- +MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT +BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X +DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3 +aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG +9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644 +N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm ++/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH +6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu +MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h +qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5 +FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs +ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc +celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X +CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB +tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 +cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P +4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F +kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L +3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx +/uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa +DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP +e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu +WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ +DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub +DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u +-----END CERTIFICATE----- + +GeoTrust Primary Certification Authority +======================================== +-----BEGIN CERTIFICATE----- +MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx +CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ +cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN +b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9 +nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge +RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt +tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI +hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K +Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN +NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa +Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG +1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= +-----END CERTIFICATE----- + +thawte Primary Root CA +====================== +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE +BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 +aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3 +MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg +SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv +KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT +FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs +oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ +1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc +q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K +aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p +afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD +VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF +AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE +uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX +xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89 +jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH +z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA== +-----END CERTIFICATE----- + +VeriSign Class 3 Public Primary Certification Authority - G5 +============================================================ +-----BEGIN CERTIFICATE----- +MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE +BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO +ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk +IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB +yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln +biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh +dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz +j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD +Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/ +Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r +fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/ +BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv +Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy +aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG +SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+ +X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE +KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC +Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE +ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq +-----END CERTIFICATE----- + +SecureTrust CA +============== +-----BEGIN CERTIFICATE----- +MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy +dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe +BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX +OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t +DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH +GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b +01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH +ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj +aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ +KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu +SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf +mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ +nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR +3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= +-----END CERTIFICATE----- + +Secure Global CA +================ +-----BEGIN CERTIFICATE----- +MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH +bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg +MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg +Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx +YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ +bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g +8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV +HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi +0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn +oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA +MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+ +OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn +CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5 +3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc +f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW +-----END CERTIFICATE----- + +COMODO Certification Authority +============================== +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE +BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG +A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb +MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD +T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH ++7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww +xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV +4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA +1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI +rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k +b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC +AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP +OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc +IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN ++8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ== +-----END CERTIFICATE----- + +Network Solutions Certificate Authority +======================================= +-----BEGIN CERTIFICATE----- +MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG +EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr +IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx +MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu +MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx +jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT +aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT +crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc +/Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB +AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv +bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA +A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q +4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/ +GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv +wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD +ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey +-----END CERTIFICATE----- + +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----- +MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE +CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g +Um9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oXDTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMC +TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l +ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ +5291qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8SpuOUfiUtn +vWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPUZ5uW6M7XxgpT0GtJlvOj +CwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvEpMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiil +e7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCR +OME4HYYEhLoaJXhena/MUGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpI +CT0ugpTNGmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy5V65 +48r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv6q012iDTiIJh8BIi +trzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEKeN5KzlW/HdXZt1bv8Hb/C3m1r737 +qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMB +AAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcC +ARYxaHR0cDovL3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqGSIb3DQEBCwUA +A4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLySCZa59sCrI2AGeYwRTlHSeYAz ++51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwj +f/ST7ZwaUb7dRUG/kSS0H4zpX897IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaN +kqbG9AclVMwWVxJKgnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfk +CpYL+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxLvJxxcypF +URmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkmbEgeqmiSBeGCc1qb3Adb +CG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvkN1trSt8sV4pAWja63XVECDdCcAz+3F4h +oKOKwJCcaNpQ5kUQR3i2TtJlycM33+FCY7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoV +IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm +66+KAQ== +-----END CERTIFICATE----- + +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----- +MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG +EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz +MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu +QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ +03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK +ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU ++zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC +PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT +OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK +F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK +0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+ +0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB +leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID +AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+ +SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG +NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx +MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O +BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l +Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga +kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q +hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs +g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5 +aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5 +nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC +ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo +Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z +WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== +-----END CERTIFICATE----- + +Chambers of Commerce Root - 2008 +================================ +-----BEGIN CERTIFICATE----- +MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD +MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv +bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu +QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy +Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl +ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF +EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl +cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA +XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj +h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/ +ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk +NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g +D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331 +lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ +0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj +ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2 +EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI +G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ +BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh +bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh +bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC +CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH +AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1 +wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH +3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU +RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6 +M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1 +YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF +9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK +zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG +nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg +OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ +-----END CERTIFICATE----- + +Global Chambersign Root - 2008 +============================== +-----BEGIN CERTIFICATE----- +MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD +MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv +bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu +QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx +NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg +Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ +QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD +aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf +VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf +XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0 +ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB +/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA +TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M +H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe +Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF +HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh +wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB +AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT +BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE +BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm +aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm +aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp +1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0 +dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG +/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6 +ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s +dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg +9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH +foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du +qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr +P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq +c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z +09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B +-----END CERTIFICATE----- + +Go Daddy Root Certificate Authority - G2 +======================================== +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu +MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 +MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 +b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G +A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq +9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD ++qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd +fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl +NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9 +BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac +vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r +5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV +N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO +LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1 +-----END CERTIFICATE----- + +Starfield Root Certificate Authority - G2 +========================================= +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s +b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 +eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw +DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg +VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB +dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv +W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs +bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk +N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf +ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU +JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol +TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx +4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw +F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K +pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ +c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 +-----END CERTIFICATE----- + +Starfield Services Root Certificate Authority - G2 +================================================== +-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s +b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl +IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV +BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT +dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg +Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2 +h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa +hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP +LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB +rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG +SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP +E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy +xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd +iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza +YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6 +-----END CERTIFICATE----- + +AffirmTrust Commercial +====================== +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw +MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly +bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb +DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV +C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6 +BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww +MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV +HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG +hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi +qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv +0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh +sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= +-----END CERTIFICATE----- + +AffirmTrust Networking +====================== +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw +MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly +bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE +Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI +dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24 +/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb +h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV +HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu +UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6 +12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23 +WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9 +/ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= +-----END CERTIFICATE----- + +AffirmTrust Premium +=================== +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy +OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy +dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn +BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV +5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs ++7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd +GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R +p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI +S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04 +6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5 +/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo ++Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv +MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg +Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC +6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S +L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK ++4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV +BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg +IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60 +g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb +zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw== +-----END CERTIFICATE----- + +AffirmTrust Premium ECC +======================= +-----BEGIN CERTIFICATE----- +MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV +BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx +MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U +cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ +N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW +BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK +BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X +57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM +eQ== +-----END CERTIFICATE----- + +Certum Trusted Network CA +========================= +-----BEGIN CERTIFICATE----- +MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK +ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy +MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU +ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC +l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J +J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4 +fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0 +cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB +Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw +DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj +jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1 +mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj +Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI +03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= +-----END CERTIFICATE----- + +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----- +MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE +BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG +A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC +R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE +ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn +dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ +FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+ +5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG +x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX +2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL +OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3 +sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C +GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5 +WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E +FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w +DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt +rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+ +nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg +tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW +sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp +pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA +zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq +ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52 +7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I +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----- +MIIFwzCCA6ugAwIBAgIUCn6m30tEntpqJIWe5rgV0xZ/u7EwDQYJKoZIhvcNAQELBQAwRjELMAkG +A1UEBhMCTFUxFjAUBgNVBAoMDUx1eFRydXN0IFMuQS4xHzAdBgNVBAMMFkx1eFRydXN0IEdsb2Jh +bCBSb290IDIwHhcNMTUwMzA1MTMyMTU3WhcNMzUwMzA1MTMyMTU3WjBGMQswCQYDVQQGEwJMVTEW +MBQGA1UECgwNTHV4VHJ1c3QgUy5BLjEfMB0GA1UEAwwWTHV4VHJ1c3QgR2xvYmFsIFJvb3QgMjCC +AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANeFl78RmOnwYoNMPIf5U2o3C/IPPIfOb9wm +Kb3FibrJgz337spbxm1Jc7TJRqMbNBM/wYlFV/TZsfs2ZUv7COJIcRHIbjuend+JZTemhfY7RBi2 +xjcwYkSSl2l9QjAk5A0MiWtj3sXh306pFGxT4GHO9hcvHTy95iJMHZP1EMShduxq3sVs35a0VkBC +wGKSMKEtFZSg0iAGCW5qbeXrt77U8PEVfIvmTroTzEsnXpk8F12PgX8zPU/TPxvsXD/wPEx1bvKm +1Z3aLQdjAsZy6ZS8TEmVT4hSyNvoaYL4zDRbIvCGp4m9SAptZoFtyMhk+wHh9OHe2Z7d21vUKpkm +FRseTJIpgp7VkoGSQXAZ96Tlk0u8d2cx3Rz9MXANF5kM+Qw5GSoXtTBxVdUPrljhPS80m8+f9niF +wpN6cj5mj5wWEWCPnolvZ77gR1o7DJpni89Gxq44o/KnvObWhWszJHAiS8sIm7vI+AIpHb4gDEa/ +a4ebsypmQjVGbKq6rfmYe+lQVRQxv7HaLe2ArWgk+2mr2HETMOZns4dA/Yl+8kPREd8vZS9kzl8U +ubG/Mb2HeFpZZYiq/FkySIbWTLkpS5XTdvN3JW1CHDiDTf2jX5t/Lax5Gw5CMZdjpPuKadUiDTSQ +MC6otOBttpSsvItO13D8xTiOZCXhTTmQzsmHhFhxAgMBAAGjgagwgaUwDwYDVR0TAQH/BAUwAwEB +/zBCBgNVHSAEOzA5MDcGByuBKwEBAQowLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9yZXBvc2l0b3J5 +Lmx1eHRydXN0Lmx1MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBT/GCh2+UgFLKGu8SsbK7JT ++Et8szAdBgNVHQ4EFgQU/xgodvlIBSyhrvErGyuyU/hLfLMwDQYJKoZIhvcNAQELBQADggIBAGoZ +FO1uecEsh9QNcH7X9njJCwROxLHOk3D+sFTAMs2ZMGQXvw/l4jP9BzZAcg4atmpZ1gDlaCDdLnIN +H2pkMSCEfUmmWjfrRcmF9dTHF5kH5ptV5AzoqbTOjFu1EVzPig4N1qx3gf4ynCSecs5U89BvolbW +7MM3LGVYvlcAGvI1+ut7MV3CwRI9loGIlonBWVx65n9wNOeD4rHh4bhY79SV5GCc8JaXcozrhAIu +ZY+kt9J/Z93I055cqqmkoCUUBpvsT34tC38ddfEz2O3OuHVtPlu5mB0xDVbYQw8wkbIEa91WvpWA +VWe+2M2D2RjuLg+GLZKecBPs3lHJQ3gCpU3I+V/EkVhGFndadKpAvAefMLmx9xIX3eP/JEAdemrR +TxgKqpAd60Ae36EeRJIQmvKN4dFLRp7oRUKX6kWZ8+xm1QL68qZKJKrezrnK+T+Tb/mjuuqlPpmt +/f97mfVl7vBZKGfXkJWkE4SphMHozs51k2MavDzq1WQfLSoSOcbDWjLtR5EWDrw4wVDej8oqkDQc +7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKqv+x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31I +iyBMz2TWuJdGsE7RKlY6oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr +-----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----- +MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxDjAM +BgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24x +MTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYw +MjEyMTczOTM5WhcNNDEwMjEyMTczOTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx +EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NM +LmNvbSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2RxFdHaxh3a3by/ZPkPQ/C +Fp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aXqhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8 +P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcCC52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/ge +oeOy3ZExqysdBP+lSgQ36YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkp +k8zruFvh/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrFYD3Z +fBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93EJNyAKoFBbZQ+yODJ +gUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVcUS4cK38acijnALXRdMbX5J+tB5O2 +UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi8 +1xtZPCvM8hnIk2snYxnP/Okm+Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4s +bE6x/c+cCbqiM+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGVcpNxJK1ok1iOMq8bs3AD/CUr +dIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBcHadm47GUBwwyOabqG7B52B2ccETjit3E+ZUf +ijhDPwGFpUenPUayvOUiaPd7nNgsPgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAsl +u1OJD7OAUN5F7kR/q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjq +erQ0cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jra6x+3uxj +MxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90IH37hVZkLId6Tngr75qNJ +vTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/YK9f1JmzJBjSWFupwWRoyeXkLtoh/D1JI +Pb9s2KJELtFOt3JY04kTlf5Eq/jXixtunLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406y +wKBjYZC6VWg3dGq2ktufoYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NI +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 new file mode 100644 index 00000000..52018bde --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/src/codebird.php @@ -0,0 +1,2720 @@ + + * @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 new file mode 100644 index 00000000..fd344c4a --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/test/README @@ -0,0 +1,16 @@ +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 new file mode 100644 index 00000000..6cbae4a5 --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/test/codebirdm.php @@ -0,0 +1,204 @@ + + * @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 new file mode 100644 index 00000000..dd54dfc4 --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/test/codebirdt.php @@ -0,0 +1,97 @@ + + * @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 new file mode 100644 index 00000000..2017e1c6 --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/test/constant_tests.php @@ -0,0 +1,40 @@ + + * @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 new file mode 100644 index 00000000..3f49661b --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/test/curl_tests.php @@ -0,0 +1,57 @@ + + * @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 new file mode 100644 index 00000000..9114a2d7 --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/test/detection_tests.php @@ -0,0 +1,288 @@ + + * @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 new file mode 100644 index 00000000..b5d6d043 --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/test/environment_test.php @@ -0,0 +1,40 @@ + + * @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 new file mode 100644 index 00000000..f4ab9261 --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/test/media_tests.php @@ -0,0 +1,56 @@ + + * @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 new file mode 100644 index 00000000..086dfa2e --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/test/oauth_tests.php @@ -0,0 +1,130 @@ + + * @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 new file mode 100644 index 00000000..f316cd16 --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/test/replyparse_tests.php @@ -0,0 +1,361 @@ + + * @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 new file mode 100644 index 00000000..1656f3d2 --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/test/requestparse_tests.php @@ -0,0 +1,212 @@ + + * @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 new file mode 100644 index 00000000..321c2ee3 --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/test/returnformat_tests.php @@ -0,0 +1,70 @@ + + * @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 new file mode 100644 index 00000000..4c2cd094 --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/test/setter_tests.php @@ -0,0 +1,253 @@ + + * @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 new file mode 100644 index 00000000..3a4f5fb3 --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/test/signing_tests.php @@ -0,0 +1,166 @@ + + * @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 new file mode 100644 index 00000000..b47da416 --- /dev/null +++ b/twitter/vendor/jublonet/codebird-php/test/singleton_tests.php @@ -0,0 +1,31 @@ + + * @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); + } +} diff --git a/viewsrc/lang/de/messages.po b/viewsrc/lang/de/messages.po index 7cd70c0c..b397c392 100644 --- a/viewsrc/lang/de/messages.po +++ b/viewsrc/lang/de/messages.po @@ -14,7 +14,7 @@ msgstr "" "POT-Creation-Date: 2021-02-01 18:16+0100\n" "PO-Revision-Date: 2018-03-20 07:26+0000\n" "Last-Translator: Tobias Diekershoff , 2018\n" -"Language-Team: German (https://app.transifex.com/Friendica/teams/12172/de/)\n" +"Language-Team: German (https://www.transifex.com/Friendica/teams/12172/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/viewsrc/lang/it/messages.po b/viewsrc/lang/it/messages.po index e063ba17..0b9f3f93 100644 --- a/viewsrc/lang/it/messages.po +++ b/viewsrc/lang/it/messages.po @@ -3,24 +3,21 @@ # This file is distributed under the same license as the Friendica viewsrc addon package. # # -# Translators: -# fabrixxm , 2018 -# #, fuzzy msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-02-01 18:16+0100\n" -"PO-Revision-Date: 2018-03-20 07:26+0000\n" +"POT-Creation-Date: 2013-02-27 05:01-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: fabrixxm , 2018\n" -"Language-Team: Italian (https://app.transifex.com/Friendica/teams/12172/it/)\n" +"Language-Team: Italian (https://www.transifex.com/Friendica/teams/12172/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: viewsrc.php:49 +#: viewsrc.php:39 msgid "View Source" msgstr "Vedi Sorgente" diff --git a/viewsrc/lang/it/strings.php b/viewsrc/lang/it/strings.php index b0b07861..348cfe7b 100644 --- a/viewsrc/lang/it/strings.php +++ b/viewsrc/lang/it/strings.php @@ -3,6 +3,6 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $a->strings['View Source'] = 'Vedi Sorgente'; diff --git a/viewsrc/viewsrc.php b/viewsrc/viewsrc.php index c4d21ccb..eefb7105 100644 --- a/viewsrc/viewsrc.php +++ b/viewsrc/viewsrc.php @@ -36,5 +36,5 @@ function viewsrc_item_photo_menu(array &$b) return; } - $b['menu'] = array_merge([DI::l10n()->t('View Source') => DI::baseUrl() . '/viewsrc/'. $b['item']['uri-id']], $b['menu']); + $b['menu'] = array_merge([DI::l10n()->t('View Source') => DI::baseUrl()->get() . '/viewsrc/'. $b['item']['uri-id']], $b['menu']); } diff --git a/webrtc/lang/cs/messages.po b/webrtc/lang/cs/messages.po index 9485b565..217385f8 100644 --- a/webrtc/lang/cs/messages.po +++ b/webrtc/lang/cs/messages.po @@ -4,53 +4,56 @@ # # # Translators: -# Aditoo, 2018 -# michal_s , 2014 +# Michal Šupler , 2014 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-04-29 15:56+0200\n" -"PO-Revision-Date: 2014-06-23 13:05+0000\n" -"Last-Translator: Aditoo, 2018\n" -"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" +"POT-Creation-Date: 2014-06-23 14:45+0200\n" +"PO-Revision-Date: 2014-07-02 15:10+0000\n" +"Last-Translator: Michal Šupler \n" +"Language-Team: Czech (http://www.transifex.com/projects/p/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" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -#: webrtc.php:18 +#: webrtc.php:20 msgid "WebRTC Videochat" msgstr "WebRTC Videochat" -#: webrtc.php:24 +#: webrtc.php:26 msgid "Save Settings" msgstr "Uložit Nastavení" -#: webrtc.php:25 +#: webrtc.php:27 msgid "WebRTC Base URL" -msgstr "Základní adresa URL WebRTC" +msgstr "WebRTC Base adresa URL" -#: webrtc.php:25 +#: webrtc.php:27 msgid "" "Page your users will create a WebRTC chat room on. For example you could use" " https://live.mayfirst.org ." -msgstr "Stránka, na které budou vaši uživatelé vytvářet chatovací místnosti WebRTC. Například můžete zadat https://live.mayfirst.org." +msgstr "Stránka, na které budou vaši uživatelé vytvářet WebRTC chatovací místnosti. Například můžete zadat https://live.mayfirst.org." -#: webrtc.php:44 +#: webrtc.php:33 +msgid "Settings updated." +msgstr "Nastavení aktualizováno." + +#: webrtc.php:47 msgid "Video Chat" msgstr "Video Chat" -#: webrtc.php:45 +#: webrtc.php:48 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 is a video and audio conferencing tool that works with Firefox " +"(version 21 and above) and Chrome/Chromium (version 25 and above). Just " +"create a new chat room and send the link to someone you want to chat with." +msgstr "WebRTC je video a audio konferenční nástroj který funguje s prohlížeči Firefox (verze 21 a vyšší) a Chrome/Chromium (verze 25 a vyšší). Stačí vytvořit novou chatovací místnost a poslat link někomu, se kterým chcete chatovat." -#: webrtc.php:47 +#: webrtc.php:50 msgid "" "Please contact your friendica admin and send a reminder to configure the " "WebRTC addon." -msgstr "Prosím kontaktujte administrátora Vašeho serveru Friendica a požádejte ho o konfiguraci doplňku WebRTC." +msgstr "Prosím kontaktujte vašeho administrátora serveru friendica a požádejte ho o konfiguraci WebRTC rozšíření." diff --git a/webrtc/lang/cs/strings.php b/webrtc/lang/cs/strings.php index 5ab781bf..23a7a6cc 100644 --- a/webrtc/lang/cs/strings.php +++ b/webrtc/lang/cs/strings.php @@ -3,11 +3,13 @@ if(! function_exists("string_plural_select_cs")) { function string_plural_select_cs($n){ $n = intval($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; } + if (($n==1)) { return 0; } else if (($n>=2 && $n<=4)) { return 1; } else { return 2; } }} $a->strings['WebRTC Videochat'] = 'WebRTC Videochat'; $a->strings['Save Settings'] = 'Uložit Nastavení'; -$a->strings['WebRTC Base URL'] = 'Základní adresa URL WebRTC'; -$a->strings['Page your users will create a WebRTC chat room on. For example you could use https://live.mayfirst.org .'] = 'Stránka, na které budou vaši uživatelé vytvářet chatovací místnosti WebRTC. Například můžete zadat https://live.mayfirst.org.'; +$a->strings['WebRTC Base URL'] = 'WebRTC Base adresa URL'; +$a->strings['Page your users will create a WebRTC chat room on. For example you could use https://live.mayfirst.org .'] = 'Stránka, na které budou vaši uživatelé vytvářet WebRTC chatovací místnosti. Například můžete zadat https://live.mayfirst.org.'; +$a->strings['Settings updated.'] = 'Nastavení aktualizováno.'; $a->strings['Video Chat'] = 'Video Chat'; -$a->strings['Please contact your friendica admin and send a reminder to configure the WebRTC addon.'] = 'Prosím kontaktujte administrátora Vašeho serveru Friendica a požádejte ho o konfiguraci doplňku WebRTC.'; +$a->strings['WebRTC is a video and audio conferencing tool that works with Firefox (version 21 and above) and Chrome/Chromium (version 25 and above). Just create a new chat room and send the link to someone you want to chat with.'] = 'WebRTC je video a audio konferenční nástroj který funguje s prohlížeči Firefox (verze 21 a vyšší) a Chrome/Chromium (verze 25 a vyšší). Stačí vytvořit novou chatovací místnost a poslat link někomu, se kterým chcete chatovat.'; +$a->strings['Please contact your friendica admin and send a reminder to configure the WebRTC addon.'] = 'Prosím kontaktujte vašeho administrátora serveru friendica a požádejte ho o konfiguraci WebRTC rozšíření.'; diff --git a/webrtc/lang/de/messages.po b/webrtc/lang/de/messages.po index e5e37294..a8b153d0 100644 --- a/webrtc/lang/de/messages.po +++ b/webrtc/lang/de/messages.po @@ -5,52 +5,51 @@ # # Translators: # Tobias Diekershoff , 2014 -# Tobias Diekershoff , 2022 # Ulf Rompe , 2019 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-04-29 15:56+0200\n" -"PO-Revision-Date: 2014-06-23 13:05+0000\n" -"Last-Translator: Tobias Diekershoff , 2022\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"POT-Creation-Date: 2021-02-01 18:16+0100\n" +"PO-Revision-Date: 2021-02-01 20:17+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: webrtc.php:18 +#: webrtc.php:19 msgid "WebRTC Videochat" msgstr "WebRTC Videochat" -#: webrtc.php:24 +#: webrtc.php:25 msgid "Save Settings" msgstr "Einstellungen speichern" -#: webrtc.php:25 +#: webrtc.php:26 msgid "WebRTC Base URL" msgstr "Basis-URL des WebRTC-Servers" -#: webrtc.php:25 +#: webrtc.php:26 msgid "" "Page your users will create a WebRTC chat room on. For example you could use" " https://live.mayfirst.org ." msgstr "Auf welcher Seite sollten deine Nutzer einen WebRTC-Chatraum anlegen? Du könntest bspw. https://live.mayfirst.org verwenden." -#: webrtc.php:44 +#: webrtc.php:45 msgid "Video Chat" msgstr "Video Chat" -#: webrtc.php:45 +#: webrtc.php:46 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 ist ein Standart für Audio und Video Konferenzen der von allen modernen Browser unterstützt wird, Öffne einfach einen neuen Chatraum und sende den Link an diejenige Person, mit der du dich unterhalten möchtest." +"WebRTC is a video and audio conferencing tool that works with Firefox " +"(version 21 and above) and Chrome/Chromium (version 25 and above). Just " +"create a new chat room and send the link to someone you want to chat with." +msgstr "WebRTC ist ein Werkzeug für Audio- und Videokonferenzen, das mit Firefox (Version 21 und höher) und Chrome/Chromium (Versionen 25 und höher) funktioniert. Lege einfach einen neuen Chatraum an und sende den Link an die Personen, mit denen du chatten willst." -#: webrtc.php:47 +#: webrtc.php:48 msgid "" "Please contact your friendica admin and send a reminder to configure the " "WebRTC addon." diff --git a/webrtc/lang/de/strings.php b/webrtc/lang/de/strings.php index 207bedf3..0f5f0a1e 100644 --- a/webrtc/lang/de/strings.php +++ b/webrtc/lang/de/strings.php @@ -10,5 +10,5 @@ $a->strings['Save Settings'] = 'Einstellungen speichern'; $a->strings['WebRTC Base URL'] = 'Basis-URL des WebRTC-Servers'; $a->strings['Page your users will create a WebRTC chat room on. For example you could use https://live.mayfirst.org .'] = 'Auf welcher Seite sollten deine Nutzer einen WebRTC-Chatraum anlegen? Du könntest bspw. https://live.mayfirst.org verwenden.'; $a->strings['Video Chat'] = 'Video Chat'; -$a->strings['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.'] = 'WebRTC ist ein Standart für Audio und Video Konferenzen der von allen modernen Browser unterstützt wird, Öffne einfach einen neuen Chatraum und sende den Link an diejenige Person, mit der du dich unterhalten möchtest.'; +$a->strings['WebRTC is a video and audio conferencing tool that works with Firefox (version 21 and above) and Chrome/Chromium (version 25 and above). Just create a new chat room and send the link to someone you want to chat with.'] = 'WebRTC ist ein Werkzeug für Audio- und Videokonferenzen, das mit Firefox (Version 21 und höher) und Chrome/Chromium (Versionen 25 und höher) funktioniert. Lege einfach einen neuen Chatraum an und sende den Link an die Personen, mit denen du chatten willst.'; $a->strings['Please contact your friendica admin and send a reminder to configure the WebRTC addon.'] = 'Bitte schicke eine Erinnerung an deinen Friendica-Admin, dass WebRTC noch nicht richtig konfiguriert ist.'; diff --git a/webrtc/lang/es/messages.po b/webrtc/lang/es/messages.po index f1113ada..ae877e03 100644 --- a/webrtc/lang/es/messages.po +++ b/webrtc/lang/es/messages.po @@ -9,46 +9,50 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-04-29 15:56+0200\n" -"PO-Revision-Date: 2014-06-23 13:05+0000\n" -"Last-Translator: Tupambae.org, 2016\n" -"Language-Team: Spanish (http://app.transifex.com/Friendica/friendica/language/es/)\n" +"POT-Creation-Date: 2014-06-23 14:45+0200\n" +"PO-Revision-Date: 2016-04-18 19:15+0000\n" +"Last-Translator: Tupambae.org\n" +"Language-Team: Spanish (http://www.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=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: webrtc.php:18 +#: webrtc.php:20 msgid "WebRTC Videochat" msgstr "WebRTC Videochat" -#: webrtc.php:24 +#: webrtc.php:26 msgid "Save Settings" msgstr "Guardar ajustes" -#: webrtc.php:25 +#: webrtc.php:27 msgid "WebRTC Base URL" msgstr "WebRTC URL Base" -#: webrtc.php:25 +#: webrtc.php:27 msgid "" "Page your users will create a WebRTC chat room on. For example you could use" " https://live.mayfirst.org ." msgstr "Pagina donde el usuario creara una habitación de chat.\nPor ejemplo podría usar https://live.mayfirst.org ." -#: webrtc.php:44 +#: webrtc.php:33 +msgid "Settings updated." +msgstr "Ajustes actualizados." + +#: webrtc.php:47 msgid "Video Chat" msgstr "Video Chat" -#: webrtc.php:45 +#: webrtc.php:48 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 is a video and audio conferencing tool that works with Firefox " +"(version 21 and above) and Chrome/Chromium (version 25 and above). Just " +"create a new chat room and send the link to someone you want to chat with." +msgstr "WebRTC es una herramienta de vídeo conferencia que funciona con Firefox (versión 21 y arriba) y Chrome/Chromium (versión 25 y arriba). " -#: webrtc.php:47 +#: webrtc.php:50 msgid "" "Please contact your friendica admin and send a reminder to configure the " "WebRTC addon." diff --git a/webrtc/lang/es/strings.php b/webrtc/lang/es/strings.php index 797567fa..aeaf7ee0 100644 --- a/webrtc/lang/es/strings.php +++ b/webrtc/lang/es/strings.php @@ -3,12 +3,14 @@ if(! function_exists("string_plural_select_es")) { function string_plural_select_es($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $a->strings['WebRTC Videochat'] = 'WebRTC Videochat'; $a->strings['Save Settings'] = 'Guardar ajustes'; $a->strings['WebRTC Base URL'] = 'WebRTC URL Base'; $a->strings['Page your users will create a WebRTC chat room on. For example you could use https://live.mayfirst.org .'] = 'Pagina donde el usuario creara una habitación de chat. Por ejemplo podría usar https://live.mayfirst.org .'; +$a->strings['Settings updated.'] = 'Ajustes actualizados.'; $a->strings['Video Chat'] = 'Video Chat'; +$a->strings['WebRTC is a video and audio conferencing tool that works with Firefox (version 21 and above) and Chrome/Chromium (version 25 and above). Just create a new chat room and send the link to someone you want to chat with.'] = 'WebRTC es una herramienta de vídeo conferencia que funciona con Firefox (versión 21 y arriba) y Chrome/Chromium (versión 25 y arriba). '; $a->strings['Please contact your friendica admin and send a reminder to configure the WebRTC addon.'] = 'Por favor contacta a tu administrador de friendica y envíale un recordatorio para configurar el accesorio (addon) WebRTC.'; diff --git a/webrtc/lang/it/messages.po b/webrtc/lang/it/messages.po index f018cb6e..df0903f2 100644 --- a/webrtc/lang/it/messages.po +++ b/webrtc/lang/it/messages.po @@ -5,51 +5,55 @@ # # Translators: # fabrixxm , 2014 -# Sylke Vicious , 2020,2023 +# Sylke Vicious , 2020 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-04-29 15:56+0200\n" -"PO-Revision-Date: 2014-06-23 13:05+0000\n" -"Last-Translator: Sylke Vicious , 2020,2023\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"POT-Creation-Date: 2014-06-23 14:45+0200\n" +"PO-Revision-Date: 2020-09-17 11:39+0000\n" +"Last-Translator: Sylke Vicious \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: webrtc.php:18 +#: webrtc.php:20 msgid "WebRTC Videochat" msgstr "Chat video WebRTC" -#: webrtc.php:24 +#: webrtc.php:26 msgid "Save Settings" msgstr "Salva Impostazioni" -#: webrtc.php:25 +#: webrtc.php:27 msgid "WebRTC Base URL" msgstr "Indirizzo base WebRTC" -#: webrtc.php:25 +#: webrtc.php:27 msgid "" "Page your users will create a WebRTC chat room on. For example you could use" " https://live.mayfirst.org ." msgstr "Indirizzo della pagina che i tuoi utenti utilizzeranno per creare una chat rom WebRTC. Per esempio potresti usare https://live.mayfirst.org ." -#: webrtc.php:44 +#: webrtc.php:33 +msgid "Settings updated." +msgstr "Impostazioni aggiornate." + +#: webrtc.php:47 msgid "Video Chat" msgstr "Chat Video" -#: webrtc.php:45 +#: webrtc.php:48 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 è uno strumento di conferenza video e audio che funziona in tutti i browser moderni. Ti basta creare una nuova stanza di conversazione e inviare il collegamento a qualcuno con il quale vuoi parlare." +"WebRTC is a video and audio conferencing tool that works with Firefox " +"(version 21 and above) and Chrome/Chromium (version 25 and above). Just " +"create a new chat room and send the link to someone you want to chat with." +msgstr "WebRTC è un sistema di conferenza audio/video che funziona con Firefox (dalla versione 21) e Chrome/Chromium (dalla versione 25).\nCrea semplicemente una nuova stanza e invia il collegamento alla persona con cui vuoi parlare." -#: webrtc.php:47 +#: webrtc.php:50 msgid "" "Please contact your friendica admin and send a reminder to configure the " "WebRTC addon." diff --git a/webrtc/lang/it/strings.php b/webrtc/lang/it/strings.php index 0e1bb5b8..42649337 100644 --- a/webrtc/lang/it/strings.php +++ b/webrtc/lang/it/strings.php @@ -3,12 +3,14 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $a->strings['WebRTC Videochat'] = 'Chat video WebRTC'; $a->strings['Save Settings'] = 'Salva Impostazioni'; $a->strings['WebRTC Base URL'] = 'Indirizzo base WebRTC'; $a->strings['Page your users will create a WebRTC chat room on. For example you could use https://live.mayfirst.org .'] = 'Indirizzo della pagina che i tuoi utenti utilizzeranno per creare una chat rom WebRTC. Per esempio potresti usare https://live.mayfirst.org .'; +$a->strings['Settings updated.'] = 'Impostazioni aggiornate.'; $a->strings['Video Chat'] = 'Chat Video'; -$a->strings['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.'] = 'WebRTC è uno strumento di conferenza video e audio che funziona in tutti i browser moderni. Ti basta creare una nuova stanza di conversazione e inviare il collegamento a qualcuno con il quale vuoi parlare.'; +$a->strings['WebRTC is a video and audio conferencing tool that works with Firefox (version 21 and above) and Chrome/Chromium (version 25 and above). Just create a new chat room and send the link to someone you want to chat with.'] = 'WebRTC è un sistema di conferenza audio/video che funziona con Firefox (dalla versione 21) e Chrome/Chromium (dalla versione 25). +Crea semplicemente una nuova stanza e invia il collegamento alla persona con cui vuoi parlare.'; $a->strings['Please contact your friendica admin and send a reminder to configure the WebRTC addon.'] = 'Contatta il tuo amministratore Friendica e ricordagli di configurare il plugin WebRTC.'; diff --git a/wppost/lang/C/messages.po b/wppost/lang/C/messages.po index 187b0316..fea16eee 100644 --- a/wppost/lang/C/messages.po +++ b/wppost/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:51-0400\n" +"POT-Creation-Date: 2021-11-21 19:18-0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -59,10 +59,10 @@ msgstr "" msgid "Wordpress Export" msgstr "" -#: wppost.php:185 +#: wppost.php:182 msgid "Read the orig­i­nal post and com­ment stream on Friendica" msgstr "" -#: wppost.php:235 +#: wppost.php:240 msgid "Post from Friendica" msgstr "" diff --git a/wppost/lang/de/messages.po b/wppost/lang/de/messages.po index b3f1e38e..6d2b1863 100644 --- a/wppost/lang/de/messages.po +++ b/wppost/lang/de/messages.po @@ -13,9 +13,9 @@ msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:18-0500\n" -"PO-Revision-Date: 2014-06-23 13:07+0000\n" -"Last-Translator: Tobias Diekershoff , 2017-2018,2022\n" -"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" +"PO-Revision-Date: 2022-01-22 17:45+0000\n" +"Last-Translator: Tobias Diekershoff \n" +"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/wppost/lang/it/messages.po b/wppost/lang/it/messages.po index efd90e1f..204bf67c 100644 --- a/wppost/lang/it/messages.po +++ b/wppost/lang/it/messages.po @@ -5,67 +5,71 @@ # # Translators: # fabrixxm , 2014-2015,2017-2018 -# Sylke Vicious , 2020,2023 +# Sylke Vicious , 2020 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:18-0500\n" -"PO-Revision-Date: 2014-06-23 13:07+0000\n" -"Last-Translator: Sylke Vicious , 2020,2023\n" -"Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" +"POT-Creation-Date: 2021-02-01 18:16+0100\n" +"PO-Revision-Date: 2020-09-17 11:42+0000\n" +"Last-Translator: Sylke Vicious \n" +"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" -"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: wppost.php:41 +#: wppost.php:39 msgid "Post to Wordpress" msgstr "Invia a Wordpress" -#: wppost.php:65 -msgid "Enable Wordpress Post Addon" -msgstr "Abilita Componente Aggiuntivo di Pubblicazione Wordpress" +#: wppost.php:80 wppost.php:84 +msgid "Wordpress Export" +msgstr "Esporta a Wordpress" -#: wppost.php:66 -msgid "Wordpress username" +#: wppost.php:87 +msgid "Enable WordPress Post Addon" +msgstr "Abilita il componente aggiuntivo di invio a Wordpress" + +#: wppost.php:93 +msgid "WordPress username" msgstr "Nome utente Wordpress" -#: wppost.php:67 -msgid "Wordpress password" +#: wppost.php:98 +msgid "WordPress password" msgstr "Password Wordpress" -#: wppost.php:68 +#: wppost.php:103 msgid "WordPress API URL" msgstr "Indirizzo API Wordpress" -#: wppost.php:69 -msgid "Post to Wordpress by default" -msgstr "Pubblica su Wordpress per impostazione predefinita" +#: wppost.php:108 +msgid "Post to WordPress by default" +msgstr "Invia sempre a Wordpress" -#: wppost.php:70 +#: wppost.php:114 msgid "Provide a backlink to the Friendica post" msgstr "Inserisci un collegamento al messaggio originale su Friendica" -#: wppost.php:71 +#: wppost.php:119 msgid "" "Text for the backlink, e.g. Read the original post and comment stream on " "Friendica." msgstr "Testo per il collegamento al messaggio originale, p.e. Leggi il messaggio originale e i commenti su Friendica." -#: wppost.php:72 +#: wppost.php:124 msgid "Don't post messages that are too short" msgstr "Non inviare messaggi troppo corti" -#: wppost.php:77 -msgid "Wordpress Export" -msgstr "Esporta a Wordpress" +#: wppost.php:131 +msgid "Save Settings" +msgstr "Salva Impostazioni" -#: wppost.php:182 +#: wppost.php:231 msgid "Read the orig­i­nal post and com­ment stream on Friendica" msgstr "Leggi il messaggio originale e i commenti su Friendica" -#: wppost.php:240 +#: wppost.php:289 msgid "Post from Friendica" msgstr "Messaggio da Friendica" diff --git a/wppost/lang/it/strings.php b/wppost/lang/it/strings.php index 504a077c..94885848 100644 --- a/wppost/lang/it/strings.php +++ b/wppost/lang/it/strings.php @@ -3,17 +3,18 @@ if(! function_exists("string_plural_select_it")) { function string_plural_select_it($n){ $n = intval($n); - if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } + return intval($n != 1); }} $a->strings['Post to Wordpress'] = 'Invia a Wordpress'; -$a->strings['Enable Wordpress Post Addon'] = 'Abilita Componente Aggiuntivo di Pubblicazione Wordpress'; -$a->strings['Wordpress username'] = 'Nome utente Wordpress'; -$a->strings['Wordpress password'] = 'Password Wordpress'; +$a->strings['Wordpress Export'] = 'Esporta a Wordpress'; +$a->strings['Enable WordPress Post Addon'] = 'Abilita il componente aggiuntivo di invio a Wordpress'; +$a->strings['WordPress username'] = 'Nome utente Wordpress'; +$a->strings['WordPress password'] = 'Password Wordpress'; $a->strings['WordPress API URL'] = 'Indirizzo API Wordpress'; -$a->strings['Post to Wordpress by default'] = 'Pubblica su Wordpress per impostazione predefinita'; +$a->strings['Post to WordPress by default'] = 'Invia sempre a Wordpress'; $a->strings['Provide a backlink to the Friendica post'] = 'Inserisci un collegamento al messaggio originale su Friendica'; $a->strings['Text for the backlink, e.g. Read the original post and comment stream on Friendica.'] = 'Testo per il collegamento al messaggio originale, p.e. Leggi il messaggio originale e i commenti su Friendica.'; $a->strings['Don\'t post messages that are too short'] = 'Non inviare messaggi troppo corti'; -$a->strings['Wordpress Export'] = 'Esporta a Wordpress'; +$a->strings['Save Settings'] = 'Salva Impostazioni'; $a->strings['Read the orig­i­nal post and com­ment stream on Friendica'] = 'Leggi il messaggio originale e i commenti su Friendica'; $a->strings['Post from Friendica'] = 'Messaggio da Friendica'; diff --git a/wppost/wppost.php b/wppost/wppost.php index 0405f78a..7f96bfea 100644 --- a/wppost/wppost.php +++ b/wppost/wppost.php @@ -6,6 +6,7 @@ * Author: Mike Macgirvin */ +use Friendica\App; use Friendica\Content\Text\BBCode; use Friendica\Content\Text\HTML; use Friendica\Core\Hook; @@ -13,9 +14,7 @@ use Friendica\Core\Logger; use Friendica\Core\Renderer; 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() @@ -34,13 +33,13 @@ function wppost_jot_nets(array &$jotnets_fields) return; } - if (DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'wppost', 'post')) { + if (DI::pConfig()->get(DI::userSession()->getLocalUserId(),'wppost','post')) { $jotnets_fields[] = [ 'type' => 'checkbox', 'field' => [ 'wppost_enable', DI::l10n()->t('Post to Wordpress'), - DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'wppost', 'post_by_default') + DI::pConfig()->get(DI::userSession()->getLocalUserId(),'wppost','post_by_default') ] ]; } @@ -85,15 +84,15 @@ function wppost_settings(array &$data) function wppost_settings_post(array &$b) { - if (!empty($_POST['wppost-submit'])) { - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'wppost', 'post', intval($_POST['wppost'])); + if(!empty($_POST['wppost-submit'])) { + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'wppost', 'post' , intval($_POST['wppost'])); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'wppost', 'post_by_default', intval($_POST['wp_bydefault'])); - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'wppost', 'wp_username', trim($_POST['wp_username'])); - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'wppost', 'wp_password', trim($_POST['wp_password'])); - 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::convertForUriId(User::getSystemUriId(), trim($_POST['wp_backlink_text']), BBCode::BACKLINK); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'wppost', 'wp_username' , trim($_POST['wp_username'])); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'wppost', 'wp_password' , trim($_POST['wp_password'])); + 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 = HTML::toPlaintext($wp_backlink_text, 0, true); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'wppost', 'wp_backlink_text', $wp_backlink_text); } @@ -107,17 +106,14 @@ 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']) - ) { + if ($post['deleted'] || $post['private'] || ($post['created'] !== $post['edited']) || + !strstr($post['postopts'] ?? '', 'wppost') || ($post['parent'] != $post['id'])) { $b['execute'] = false; return; } } -function wppost_post_local(array &$b) -{ +function wppost_post_local(array &$b) { // This can probably be changed to allow editing by pointing to a different API endpoint @@ -157,20 +153,20 @@ function wppost_post_local(array &$b) function wppost_send(array &$b) { - if ($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited'])) { + if($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited'])) { return; } - if (!strstr($b['postopts'], 'wppost')) { + if(! strstr($b['postopts'],'wppost')) { return; } - if ($b['gravity'] != Item::GRAVITY_PARENT) { + if($b['parent'] != $b['id']) { return; } // Dont't post if the post doesn't belong to us. - // This is a check for group postings + // This is a check for forum postings $self = DBA::selectFirst('contact', ['id'], ['uid' => $b['uid'], 'self' => true]); if ($b['contact-id'] != $self['id']) { return; @@ -180,8 +176,8 @@ function wppost_send(array &$b) $wp_username = XML::escape(DI::pConfig()->get($b['uid'], 'wppost', 'wp_username')); $wp_password = XML::escape(DI::pConfig()->get($b['uid'], 'wppost', 'wp_password')); - $wp_blog = DI::pConfig()->get($b['uid'], 'wppost', 'wp_blog'); - $wp_backlink_text = DI::pConfig()->get($b['uid'], 'wppost', 'wp_backlink_text'); + $wp_blog = DI::pConfig()->get($b['uid'],'wppost','wp_blog'); + $wp_backlink_text = DI::pConfig()->get($b['uid'],'wppost','wp_backlink_text'); if ($wp_backlink_text == '') { $wp_backlink_text = DI::l10n()->t('Read the orig­i­nal post and com­ment stream on Friendica'); } @@ -191,7 +187,15 @@ function wppost_send(array &$b) if (intval(DI::pConfig()->get($b['uid'], 'wppost', 'shortcheck'))) { // Checking, if its a post that is worth a blog post - $postentry = (bool)Post\Media::getByURIId($b['uri-id'], [Post\Media::HTML, Post\Media::AUDIO, Post\Media::VIDEO, Post\Media::IMAGE]); + $postentry = false; + $siteinfo = BBCode::getAttachedData($b["body"]); + + // Is it a link to an aricle, a video or a photo? + if (isset($siteinfo["type"])) { + if (in_array($siteinfo["type"], ["link", "audio", "video", "photo"])) { + $postentry = true; + } + } // Does it have a title? if ($wptitle != "") { @@ -211,9 +215,9 @@ function wppost_send(array &$b) // If the title is empty then try to guess if ($wptitle == '') { // Fetch information about the post - $media = Post\Media::getByURIId($b['uri-id'], [Post\Media::HTML]); - if (!empty($media) && !empty($media[0]['name']) && ($media[0]['name'] != $media[0]['url'])) { - $wptitle = $media[0]['name']; + $siteinfo = BBCode::getAttachedData($b["body"]); + if (isset($siteinfo["title"])) { + $wptitle = $siteinfo["title"]; } // If no bookmark is found then take the first line @@ -221,7 +225,7 @@ function wppost_send(array &$b) // Remove the share element before fetching the first line $title = trim(preg_replace("/\[share.*?\](.*?)\[\/share\]/ism", "\n$1\n", $b['body'])); - $title = BBCode::toPlaintext($title) . "\n"; + $title = BBCode::toPlaintext($title)."\n"; $pos = strpos($title, "\n"); $trailer = ""; if (($pos == 0) || ($pos > 100)) { @@ -229,7 +233,7 @@ function wppost_send(array &$b) $trailer = "..."; } - $wptitle = substr($title, 0, $pos) . $trailer; + $wptitle = substr($title, 0, $pos).$trailer; } } @@ -240,10 +244,10 @@ function wppost_send(array &$b) $post = preg_replace('/(.*?)<\/a>/ism', "\n$1\n", $post); $post = preg_replace('/(.*?)<\/a>/ism', "\n$1\n", $post); - $post = $title . $post; + $post = $title.$post; - $wp_backlink = intval(DI::pConfig()->get($b['uid'], 'wppost', 'backlink')); - if ($wp_backlink && $b['plink']) { + $wp_backlink = intval(DI::pConfig()->get($b['uid'],'wppost','backlink')); + if($wp_backlink && $b['plink']) { $post .= '

' . $wp_backlink_text . '

'; }