Browse Source

merge master in prod

Kevin 3 years ago
parent
commit
3e5e731c2c
100 changed files with 1631 additions and 847 deletions
  1. 1 0
      user/plugins/admin/.gitignore
  2. 65 15
      user/plugins/admin/CHANGELOG.md
  3. 1 0
      user/plugins/admin/admin.yaml
  4. 16 2
      user/plugins/admin/blueprints.yaml
  5. 4 1
      user/plugins/admin/classes/admin.php
  6. 3 3
      user/plugins/admin/classes/adminbasecontroller.php
  7. 15 1
      user/plugins/admin/classes/admincontroller.php
  8. 242 180
      user/plugins/admin/composer.lock
  9. 6 0
      user/plugins/admin/languages/en.yaml
  10. 2 0
      user/plugins/admin/languages/pt.yaml
  11. 0 0
      user/plugins/admin/themes/grav/css-compiled/preset.css.map
  12. 0 0
      user/plugins/admin/themes/grav/css-compiled/template.css
  13. 0 0
      user/plugins/admin/themes/grav/css-compiled/template.css.map
  14. 1 1
      user/plugins/admin/themes/grav/scss/fonts.scss
  15. 2 1
      user/plugins/admin/themes/grav/scss/template/_admin.scss
  16. 1 0
      user/plugins/admin/themes/grav/scss/template/_login.scss
  17. 4 1
      user/plugins/admin/themes/grav/scss/template/modules/_buttons.scss
  18. 2 2
      user/plugins/admin/themes/grav/templates/forms/field.html.twig
  19. 4 1
      user/plugins/admin/themes/grav/templates/forms/fields/editor/editor.html.twig
  20. 6 3
      user/plugins/admin/themes/grav/templates/forms/fields/fieldset/fieldset.html.twig
  21. 24 1
      user/plugins/admin/themes/grav/templates/pages.html.twig
  22. 4 0
      user/plugins/admin/themes/grav/templates/partials/base-root.html.twig
  23. 1 1
      user/plugins/admin/themes/grav/templates/partials/nav-quick-tray.html.twig
  24. 1 1
      user/plugins/admin/themes/grav/templates/partials/nav-user-avatar.html.twig
  25. 42 0
      user/plugins/admin/themes/grav/templates/partials/noscript.html.twig
  26. 1 1
      user/plugins/admin/themes/grav/templates/partials/plugins-list.html.twig
  27. 2 2
      user/plugins/admin/vendor/composer/ClassLoader.php
  28. 9 9
      user/plugins/admin/vendor/composer/installed.json
  29. 12 0
      user/plugins/admin/vendor/composer/semver/CHANGELOG.md
  30. 1 2
      user/plugins/admin/vendor/composer/semver/composer.json
  31. 1 1
      user/plugins/admin/vendor/composer/semver/src/Constraint/AbstractConstraint.php
  32. 3 7
      user/plugins/admin/vendor/composer/semver/src/Constraint/Constraint.php
  33. 1 1
      user/plugins/admin/vendor/composer/semver/src/Constraint/EmptyConstraint.php
  34. 1 1
      user/plugins/admin/vendor/composer/semver/src/Constraint/MultiConstraint.php
  35. 2 2
      user/plugins/admin/vendor/composer/semver/src/Semver.php
  36. 22 25
      user/plugins/admin/vendor/composer/semver/src/VersionParser.php
  37. 41 0
      user/plugins/email/CHANGELOG.md
  38. 19 0
      user/plugins/email/README.md
  39. 6 3
      user/plugins/email/blueprints.yaml
  40. 3 2
      user/plugins/email/classes/Email.php
  41. 5 0
      user/plugins/email/cli/ClearQueueFailuresCommand.php
  42. 5 0
      user/plugins/email/cli/FlushQueueCommand.php
  43. 5 4
      user/plugins/email/cli/TestEmailCommand.php
  44. 126 60
      user/plugins/email/composer.lock
  45. 24 0
      user/plugins/email/email.php
  46. 2 2
      user/plugins/email/vendor/composer/ClassLoader.php
  47. 1 1
      user/plugins/email/vendor/composer/autoload_files.php
  48. 0 1
      user/plugins/email/vendor/composer/autoload_namespaces.php
  49. 1 0
      user/plugins/email/vendor/composer/autoload_psr4.php
  50. 3 0
      user/plugins/email/vendor/composer/autoload_real.php
  51. 7 10
      user/plugins/email/vendor/composer/autoload_static.php
  52. 131 66
      user/plugins/email/vendor/composer/installed.json
  53. 1 1
      user/plugins/email/vendor/doctrine/lexer/LICENSE
  54. 4 0
      user/plugins/email/vendor/doctrine/lexer/README.md
  55. 23 6
      user/plugins/email/vendor/doctrine/lexer/composer.json
  56. 64 63
      user/plugins/email/vendor/doctrine/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php
  57. 64 6
      user/plugins/email/vendor/egulias/email-validator/EmailValidator/EmailLexer.php
  58. 36 3
      user/plugins/email/vendor/egulias/email-validator/EmailValidator/EmailParser.php
  59. 5 5
      user/plugins/email/vendor/egulias/email-validator/EmailValidator/EmailValidator.php
  60. 1 1
      user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/ExpectingQPair.php
  61. 0 2
      user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/NoDNSRecord.php
  62. 66 20
      user/plugins/email/vendor/egulias/email-validator/EmailValidator/Parser/DomainPart.php
  63. 16 9
      user/plugins/email/vendor/egulias/email-validator/EmailValidator/Parser/LocalPart.php
  64. 37 3
      user/plugins/email/vendor/egulias/email-validator/EmailValidator/Parser/Parser.php
  65. 8 3
      user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/DNSCheckValidation.php
  66. 3 0
      user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/Exception/EmptyValidationList.php
  67. 7 1
      user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/MultipleErrors.php
  68. 16 3
      user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/MultipleValidationWithAnd.php
  69. 1 1
      user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/NoRFCWarningsValidation.php
  70. 2 2
      user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/RFCValidation.php
  71. 7 1
      user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/SpoofCheckValidation.php
  72. 4 0
      user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/QuotedPart.php
  73. 4 0
      user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/QuotedString.php
  74. 19 2
      user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/Warning.php
  75. 0 0
      user/plugins/email/vendor/egulias/email-validator/README.md
  76. 9 15
      user/plugins/email/vendor/egulias/email-validator/composer.json
  77. 3 4
      user/plugins/email/vendor/egulias/email-validator/phpunit.xml.dist
  78. 19 0
      user/plugins/email/vendor/egulias/email-validator/psalm.baseline.xml
  79. 19 0
      user/plugins/email/vendor/egulias/email-validator/psalm.xml
  80. 16 0
      user/plugins/email/vendor/swiftmailer/swiftmailer/CHANGES
  81. 0 15
      user/plugins/email/vendor/swiftmailer/swiftmailer/README
  82. 19 0
      user/plugins/email/vendor/swiftmailer/swiftmailer/README.md
  83. 6 9
      user/plugins/email/vendor/swiftmailer/swiftmailer/doc/messages.rst
  84. 1 1
      user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift.php
  85. 0 2
      user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream/ArrayCharacterStream.php
  86. 0 227
      user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream/CharacterStream.php
  87. 245 3
      user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream/NgCharacterStream.php
  88. 9 6
      user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php
  89. 1 1
      user/plugins/email/vendor/swiftmailer/swiftmailer/lib/dependency_maps/mime_deps.php
  90. 1 1
      user/plugins/email/vendor/swiftmailer/swiftmailer/lib/swiftmailer_generate_mimes_config.php
  91. 1 1
      user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Encoder/QpEncoderAcceptanceTest.php
  92. 1 1
      user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Encoder/Rfc2231EncoderAcceptanceTest.php
  93. 2 2
      user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/AttachmentAcceptanceTest.php
  94. 1 1
      user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/ContentEncoder/QpContentEncoderAcceptanceTest.php
  95. 2 2
      user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/EmbeddedFileAcceptanceTest.php
  96. 3 3
      user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/MimePartAcceptanceTest.php
  97. 2 2
      user/plugins/email/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug206Test.php
  98. 1 1
      user/plugins/email/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug650Test.php
  99. 0 3
      user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/CharacterStream/ArrayCharacterStreamTest.php
  100. 1 1
      user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Encoder/QpEncoderTest.php

+ 1 - 0
user/plugins/admin/.gitignore

@@ -1,5 +1,6 @@
 themes/grav/.sass-cache
 .DS_Store
+crowdin.yaml
 
 # Node Modules
 **/node_modules/**

+ 65 - 15
user/plugins/admin/CHANGELOG.md

@@ -1,3 +1,53 @@
+# v1.9.16
+## 09/01/2020
+
+1. [](#bugfix)
+    * Fixed a glitch which allows user to delete entire pages directory [#1941](https://github.com/getgrav/grav-plugin-admin/issues/1941)
+    * Fixed the hidden login plugin toggle
+
+# v1.9.15
+## 06/08/2020
+
+1. [](#bugfix)
+    * Support markdown in `fieldset.text` [#2934](https://github.com/getgrav/grav/issues/2934)
+    * Fix data URLs in avatar images [#1889](https://github.com/getgrav/grav/issues/1889)
+    * Fix for deleting files in plugin configurations
+
+# v1.9.14
+## 04/27/2020
+
+1. [](#improved)
+    * Added `slug` and `type` to blueprints
+1. [](#bugfix)
+    * Support markdown in `fieldset.text` [#2934](https://github.com/getgrav/grav/issues/2934)
+
+# v1.9.13
+## 03/05/2020
+
+1. [](#improved)
+    * Updated vendor libs
+1. [](#bugfix)
+    * Fixed toggleable buttons no longer holding false state [form#406](ttps://github.com/getgrav/grav-plugin-form/issues/406)
+
+# v1.9.12
+## 12/04/2019
+
+1. [](#bugfix)
+    * Fixed saving configuration in PHP 7.4
+
+# v1.9.11
+## 11/06/2019
+
+1. [](#improved)
+    * Added new "secure delete" functionality [#1752](https://github.com/getgrav/grav-plugin-admin/issues/1752)
+    * Center text logo [#1751](https://github.com/getgrav/grav-plugin-admin/issues/1751)
+    * Added required span to editor field [#1748](https://github.com/getgrav/grav-plugin-admin/issues/1748)
+    * Warn users if JS is disabled [#1722](https://github.com/getgrav/grav-plugin-admin/issues/1722)
+    * Added target rule to quick links [#1518](https://github.com/getgrav/grav-plugin-admin/issues/1518)
+1. [](#bugfix)
+    * Fixed `Badly encoded JSON data` warning when uploading files [grav#2663](https://github.com/getgrav/grav/issues/2663)
+    * Fixed `accept` for SVG in `file` uploaders [#1732](https://github.com/getgrav/grav-plugin-admin/issues/1732)
+
 # v1.9.10
 ## 09/19/2019
 
@@ -24,13 +74,13 @@
     * Fixed issue with `array` field nested in `list` that were losing their index order when the list reordered
     * Fixed file form field failing resolution checks in certain circumstances
     * Fixed issue with deleting files in config based YAML files
-    
+
 # v1.9.7
 ## 06/21/2019
 
 1. [](#bugfix)
     * Fixed issue with charts in dashboard where label would cut off [#1700](https://github.com/getgrav/grav-plugin-admin/issues/1700)
-    * Resetting a user's password clears the user's site access [grav#2528](https://github.com/getgrav/grav/issues/2528) 
+    * Resetting a user's password clears the user's site access [grav#2528](https://github.com/getgrav/grav/issues/2528)
     * Fixed issue with permissions toggle [#1702](https://github.com/getgrav/grav-plugin-admin/issues/1702)
 
 # v1.9.6
@@ -72,7 +122,7 @@
     * Added a new **YAML Linter** report to the `Tools - Reports` section
 1. [](#improved)
     * Updated package.json scripts to properly use gulp compiler
-    
+
 # v1.9.2
 ## 04/15/2019
 
@@ -85,7 +135,7 @@
 
 1. [](#bugfix)
     * Fix for Page saving issues [#1648](https://github.com/getgrav/grav-plugin-admin/issues/1648)
-    * Remove status message when picking folder for move [#1650](https://github.com/getgrav/grav-plugin-admin/issues/1650) 
+    * Remove status message when picking folder for move [#1650](https://github.com/getgrav/grav-plugin-admin/issues/1650)
 
 # v1.9.0
 ## 04/11/2019
@@ -120,10 +170,10 @@
     * Homepage link should be `https://` [#1564](https://github.com/getgrav/grav-plugin-admin/issues/1564)
     * Improve lang string to describe XSS security settings [#1566](https://github.com/getgrav/grav-plugin-admin/issues/1566)
     * Take admin setting for 2FA into account when showing user 2FA badge [#1568](https://github.com/getgrav/grav-plugin-admin/issues/1568)
-    * Moved `ignore` and `key` field into form plugin  
+    * Moved `ignore` and `key` field into form plugin
     * Improved usability of `System` configuration blueprint with side-tabs
-    * Cleaned up UI in `Scheduler` tools page 
-    * Updated languages     
+    * Cleaned up UI in `Scheduler` tools page
+    * Updated languages
 1. [](#bugfix)
     * Fixed user edit links if Flex Objects plugin is installed but user isn't Flex User
     * Fixed deprecated `sameas()` Twig test
@@ -133,15 +183,15 @@
     * Fixed issue with Safari browser and blueprint fields with `toggleable: true` [#1643](https://github.com/getgrav/grav-plugin-admin/issues/1643)
     * Incorrect 2FA lang code [#1618](https://github.com/getgrav/grav-plugin-admin/issues/1618)
     * Fixed potential undefined property in `onPageNotFound` event handling
-    * Proper fix for `vUndefined` when updating plugins/themes 
+    * Proper fix for `vUndefined` when updating plugins/themes
     * Text in Tab Tools/Direct install disappears [#1613](https://github.com/getgrav/grav-plugin-admin/issues/1613)
     * Fallback to page `slug` in Pages list if title is empty [grav#2267](https://github.com/getgrav/grav/issues/2267)
     * Fixes backup button issues with `;` param separator [#1602](https://github.com/getgrav/grav-plugin-admin/issues/1602) [#1502](https://github.com/getgrav/grav-plugin-admin/issues/1502)
     * Set default state for `show_modular` to `true` [#1599](https://github.com/getgrav/grav-plugin-admin/issues/1599)
     * Removed `tabs`, `tab`, and `toggle` fields as they are now in Form plugin
     * Fix issue with new page always showing modular page templates [#1573](https://github.com/getgrav/grav-plugin-admin/issues/1573)
-    * Fixed issue deleting files in plugins/themes/config 
-    * Fixed array support in admin languages, e.g. `DAYS_OF_THE_WEEK`    
+    * Fixed issue deleting files in plugins/themes/config
+    * Fixed array support in admin languages, e.g. `DAYS_OF_THE_WEEK`
     * Fixed user login / remember me triggering before admin gets initialized
     * Fixed a bug when deleting files via AJAX
     * Fixed error page not to be the frontend version
@@ -154,24 +204,24 @@
     * Removed duplicate language strings
     * Fixed default `job_at` so it does not fail if missing
     * Minor JS group `bottom` fix
- 
+
 # v1.8.20
 ## 03/20/2019
 
 1. [](#improved)
     * Added security field to column [#1622](https://github.com/getgrav/grav-plugin-admin/pull/1622)
-    
+
 # v1.8.19
 ## 02/13/2019
 
 1. [](#bugfix)
-    * Moved `show_modular` to proper place - Doh! [grav#2362](https://github.com/getgrav/grav/issues/2362)  
+    * Moved `show_modular` to proper place - Doh! [grav#2362](https://github.com/getgrav/grav/issues/2362)
 
 # v1.8.18
 ## 02/12/2019
 
 1. [](#bugfix)
-    * Set default value for `show_modular` [grav#2362](https://github.com/getgrav/grav/issues/2362)  
+    * Set default value for `show_modular` [grav#2362](https://github.com/getgrav/grav/issues/2362)
 
 # v1.8.17
 ## 02/07/2019
@@ -192,7 +242,7 @@
 1. [](#bugfix)
     * Fixed calendar js module not properly loading for datetime field [#1581](https://github.com/getgrav/grav-plugin-admin/issues/1581)
     * Fixed deleting file when using file field type [#1558](https://github.com/getgrav/grav-plugin-admin/issues/1558)
-    * Unset state from user if not super or user admin   
+    * Unset state from user if not super or user admin
 
 # v1.8.15
 ## 12/14/2018

+ 1 - 0
user/plugins/admin/admin.yaml

@@ -26,6 +26,7 @@ session:
   timeout: 1800
 warnings:
   delete_page: true
+  secure_delete: false
 edit_mode: normal
 frontend_preview_target: inline
 show_github_msg: true

+ 16 - 2
user/plugins/admin/blueprints.yaml

@@ -1,5 +1,7 @@
 name: Admin Panel
-version: 1.9.10
+slug: admin
+type: plugin
+version: 1.9.16
 testing: false
 description: Adds an advanced administration panel to manage your site
 icon: empire
@@ -14,7 +16,7 @@ docs: https://github.com/getgrav/grav-plugin-admin/blob/develop/README.md
 license: MIT
 
 dependencies:
-    - { name: grav, version: '>=1.6.8' }
+    - { name: grav, version: '>=1.6.22' }
     - { name: form, version: '>=3.0.0' }
     - { name: login, version: '>=3.0.0' }
     - { name: email, version: '>=3.0.0' }
@@ -243,6 +245,18 @@ form:
         type: bool
       help: Ask the user confirmation when deleting a page
 
+    warnings.secure_delete:
+      type: toggle
+      label: Secure Delete
+      highlight: 1
+      default: 1
+      options:
+        1: PLUGIN_ADMIN.ENABLED
+        0: PLUGIN_ADMIN.DISABLED
+      validate:
+        type: bool
+      help: Shows the user a field to enter the word DELETE and enable the confirm delete button.
+
     hide_page_types:
       type: array
       label: Hide page types in Admin

+ 4 - 1
user/plugins/admin/classes/admin.php

@@ -1671,8 +1671,11 @@ class Admin
     {
         $reports = new ArrayCollection();
 
+        /** @var Pages $pages */
+        $pages = $this->grav['pages'];
+
         // Default to XSS Security Report
-        $result = Security::detectXssFromPages($this->grav['pages'], true);
+        $result = Security::detectXssFromPages($pages, true);
 
         $reports['Grav Security Check'] = $this->grav['twig']->processTemplate('reports/security.html.twig', [
             'result' => $result,

+ 3 - 3
user/plugins/admin/classes/adminbasecontroller.php

@@ -325,7 +325,7 @@ class AdminBaseController
             }
 
             $isMime = strstr($type, '/');
-            $find   = str_replace(['.', '*'], ['\.', '.*'], $type);
+            $find   = str_replace(['.', '*', '+'], ['\.', '.*', '\+'], $type);
 
             if ($isMime) {
                 $match = preg_match('#' . $find . '$#', $mime);
@@ -737,8 +737,8 @@ class AdminBaseController
         // Process previously uploaded files for the current URI
         // and finally store them. Everything else will get discarded
         $queue = $this->admin->session()->getFlashObject('files-upload');
-        $queue = $queue[base64_encode($this->grav['uri']->url())];
         if (is_array($queue)) {
+            $queue = $queue[base64_encode($this->grav['uri']->url())];
             foreach ($queue as $key => $files) {
                 foreach ($files as $destination => $file) {
                     if (!rename($file['tmp_name'], $destination)) {
@@ -943,7 +943,7 @@ class AdminBaseController
             $settings = (object)$blueprints->schema()->getProperty($field);
         } else {
             $page = null;
-            if ($type === 'themes') {
+            if ($type === 'themes' || $type === 'plugins') {
                 $obj = $this->grav[$type]->get(Utils::substrToString($blueprint, '/')); //here
                 $settings = (object) $obj->blueprints()->schema()->getProperty($field);
             } else {

+ 15 - 1
user/plugins/admin/classes/admincontroller.php

@@ -487,6 +487,11 @@ class AdminController extends AdminBaseController
 
         $data = (array)$this->data;
 
+        $folder = $data['folder'] ?? '';
+        if ($folder === '' || mb_strpos($folder, '/') !== false) {
+            throw new \RuntimeException('Creating folder failed, bad folder name', 400);
+        }
+
         if ($data['route'] === '/') {
             $path = $this->grav['locator']->findResource('page://');
         } else {
@@ -494,7 +499,7 @@ class AdminController extends AdminBaseController
         }
 
         $orderOfNewFolder = static::getNextOrderInFolder($path);
-        $new_path         = $path . '/' . $orderOfNewFolder . '.' . $data['folder'];
+        $new_path         = $path . '/' . $orderOfNewFolder . '.' . $folder;
 
         Folder::create($new_path);
         Cache::clearCache('invalidate');
@@ -585,6 +590,11 @@ class AdminController extends AdminBaseController
         /** @var PageInterface $obj */
         $obj = $this->admin->page(true);
 
+        $folder = $data['folder'] ?? null;
+        if ($folder === '' || mb_strpos($folder, '/') !== false) {
+            throw new \RuntimeException('Saving page failed: bad folder name', 400);
+        }
+
         if (!isset($data['folder']) || !$data['folder']) {
             $data['folder'] = $obj->slug();
             $this->data['folder'] = $obj->slug();
@@ -814,6 +824,10 @@ class AdminController extends AdminBaseController
             $folder = \Grav\Plugin\Admin\Utils::slug($data[substr($folder, 9)]);
         }
         $folder = ltrim($folder, '_');
+        if ($folder === '' || mb_strpos($folder, '/') !== false) {
+            throw new \RuntimeException('Creating page failed: bad folder name', 400);
+        }
+
         if (!empty($data['modular'])) {
             $folder = '_' . $folder;
         }

File diff suppressed because it is too large
+ 242 - 180
user/plugins/admin/composer.lock


+ 6 - 0
user/plugins/admin/languages/en.yaml

@@ -1,4 +1,5 @@
 PLUGIN_ADMIN:
+  ADMIN_NOSCRIPT_MSG: "Please enable JavaScript in your browser."
   ADMIN_BETA_MSG: "This is a Beta release! Use this in production at your own risk..."
   ADMIN_REPORT_ISSUE: "Found an issue? Please report it on GitHub."
   EMAIL_FOOTER: "<a href=\"http://getgrav.org\">Powered by Grav</a> - The Modern Flat File CMS"
@@ -43,10 +44,12 @@ PLUGIN_ADMIN:
   EXPERT: "Expert"
   EXPAND_ALL: "Expand All"
   COLLAPSE_ALL: "Collapse All"
+  SECURE_DELETE_DESC: "Type DELETE and confirm"
   ERROR: "Error"
   CLOSE: "Close"
   CANCEL: "Cancel"
   CONTINUE: "Continue"
+  CONFIRM: "Confirm"
   MODAL_DELETE_PAGE_CONFIRMATION_REQUIRED_TITLE: "Confirmation Required"
   MODAL_CHANGED_DETECTED_TITLE: "Changes Detected"
   MODAL_CHANGED_DETECTED_DESC: "You have unsaved changes.  Are you sure you want to leave without saving?"
@@ -825,3 +828,6 @@ PLUGIN_ADMIN:
   DEBUGGER_CLOCKWORK: "Clockwork Browser Extension"
   SHOW_SENSITIVE: "Show Sensitive Data"
   SHOW_SENSITIVE_HELP: "Clockwork Provider ONLY: Censor potentially sensitive information (POST parameters, cookies, files, configuration and most array/object data in log messages)"
+  VALID_LINK_ATTRIBUTES: "Valid Link Attributes"
+  VALID_LINK_ATTRIBUTES_HELP: "Attributes that will be automatically added to the media HTML element"
+

+ 2 - 0
user/plugins/admin/languages/pt.yaml

@@ -43,10 +43,12 @@ PLUGIN_ADMIN:
   EXPERT: "Esperto"
   EXPAND_ALL: "Expandir Tudo"
   COLLAPSE_ALL: "Recolher Tudo"
+  SECURE_DELETE_DESC: "Digite DELETE e confirme"
   ERROR: "Erro"
   CLOSE: "Fechar"
   CANCEL: "Cancelar"
   CONTINUE: "Continuar"
+  CONFIRM: "Confirmar"
   MODAL_DELETE_PAGE_CONFIRMATION_REQUIRED_TITLE: "Confirmação Requerida"
   MODAL_CHANGED_DETECTED_TITLE: "Alterações Detectadas"
   MODAL_CHANGED_DETECTED_DESC: "Você tem alterações não salvas. Tem certeza que deseja sair sem salvar?"

File diff suppressed because it is too large
+ 0 - 0
user/plugins/admin/themes/grav/css-compiled/preset.css.map


File diff suppressed because it is too large
+ 0 - 0
user/plugins/admin/themes/grav/css-compiled/template.css


File diff suppressed because it is too large
+ 0 - 0
user/plugins/admin/themes/grav/css-compiled/template.css.map


+ 1 - 1
user/plugins/admin/themes/grav/scss/fonts.scss

@@ -3,7 +3,7 @@ $fonts-default: 'Roboto' !default;
 $fonts-mono: 'Inconsolata' !default;
 
 $font-definitions: (
-    Josefin+Slab: 400,
+    'Josefin Slab': '400',
     Roboto: '300,400,500',
     Inconsolata: '400,700'
 );

+ 2 - 1
user/plugins/admin/themes/grav/scss/template/_admin.scss

@@ -244,7 +244,7 @@ $content-padding: 1.5rem;
 
         display: flex;
         align-items: center;
-        
+
         a:not(.front-end) {
             display: inherit;
         }
@@ -798,6 +798,7 @@ body.sidebar-quickopen #admin-main {
 
             .button {
                 margin: 0;
+                height: 37px;
 
                 &.dropdown-toggle {
                     margin-left: -4px;

+ 1 - 0
user/plugins/admin/themes/grav/scss/template/_login.scss

@@ -103,6 +103,7 @@
         justify-content: center;
 
         &.text-logo {
+            text-align: center;
             font-size: 4rem;
         }
 

+ 4 - 1
user/plugins/admin/themes/grav/scss/template/modules/_buttons.scss

@@ -24,7 +24,10 @@
         font-size: 90%;
     }
 
-
+    &:disabled {
+        opacity: .6;
+        cursor: no-drop;
+    }
 
 }
 

+ 2 - 2
user/plugins/admin/themes/grav/templates/forms/field.html.twig

@@ -2,9 +2,9 @@
 
 {% if not blueprints or (blueprints.schema.type(field.type)['input@'] ?? true) is same as(true) %}
     {% set originalValue = originalValue is defined ? originalValue : value %}
-    {% set toggleableChecked = field.toggleable and (originalValue is not null and originalValue is not empty) %}
+    {% set toggleableChecked = field.toggleable and originalValue is not null %}
     {% set isDisabledToggleable = field.toggleable and not toggleableChecked %}
-    {% set value = (value is null ? field.default : value) %}
+    {% set value = value ?? field.default %}
 
     {% if (field.yaml or field.validate.type == 'yaml') and value is iterable%}
         {% set value = value|toYaml %}

+ 4 - 1
user/plugins/admin/themes/grav/templates/forms/fields/editor/editor.html.twig

@@ -11,7 +11,10 @@
             {% if field.help %}
                 {% set hint = 'data-hint="' ~ field.help|tu|raw ~ '"' %}
             {% endif %}
-            <div class="form-label form-field hint--bottom" {{ hint|raw }}>{{ field.label|tu|raw }}</div>
+            <div class="form-label form-field hint--bottom" {{ hint|raw }}>
+                {{ field.label|tu|raw }}
+                {{ field.validate.required in ['on', 'true', 1] ? '<span class="required">*</span>' }}
+            </div>
         {% endif %}
     {% endblock %}
     <div class="form-field {{ field.classes|default('') }}">

+ 6 - 3
user/plugins/admin/themes/grav/templates/forms/fields/fieldset/fieldset.html.twig

@@ -48,9 +48,12 @@
       >
 
           {% block group %}
-          {% if field.text %}
-          <p>{% if grav.twig.twig.filters['tu'] is defined %}{{ field.text|tu }}{% else %}{{ field.text|t }}{% endif %}
-          <p>
+              {% if field.text %}
+                {% if grav.twig.twig.filters['tu'] is defined %}
+                    {{ field.markdown ? field.text|tu|markdown : '<p>' ~ field.text|tu ~ '</p>' }}
+                {% else %}
+                    {{ field.markdown ? field.text|t|markdown : '<p>' ~ field.t ~ '</p>' }}
+                {% endif %}
               {% endif %}
 
               {% if field.fields %}

+ 24 - 1
user/plugins/admin/themes/grav/templates/pages.html.twig

@@ -107,6 +107,7 @@
 
 {% set modular = context.modular ? 'modular_' : '' %}
 {% set warn = config.plugins.admin.warnings.delete_page %}
+{% set secure_delete = config.plugins.admin.warnings.secure_delete %}
 {% set admin_lang = admin.session.admin_lang ?: 'en' %}
 {% set page_lang = context.language %}
 {% set type = 'page' %}
@@ -405,10 +406,19 @@
             <p class="bigger">
               {{ "PLUGIN_ADMIN.MODAL_DELETE_PAGE_CONFIRMATION_REQUIRED_DESC"|tu }}
             </p>
+            {% if secure_delete %}
+                <p class="form-secure-delete">
+                    <input id="secure-delete-field" autofocus type="text" placeholder="{{ "PLUGIN_ADMIN.SECURE_DELETE_DESC"|tu }}" />
+                </p>
+            {% endif %}
             <br>
             <div class="button-bar">
             <button data-remodal-action="cancel" class="button secondary remodal-cancel"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|tu }}</button>
-            <a class="button disable-after-click" data-delete-action href="#"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|tu }}</a>
+            {% if secure_delete %}
+                <button id="secure-delete-btn" disabled="true" class="button danger disable-after-click" data-delete-action><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONFIRM"|tu }}</button>
+            {% else %}
+                <a class="button danger disable-after-click" data-delete-action href="#"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|tu }}</a>
+            {% endif %}
             </div>
         </form>
     </div>
@@ -421,5 +431,18 @@
     {{ parent() }}
     <script>
         $('.admin-pages .form-tabs .tabs-nav').css('margin-right', ($('#admin-topbar').width() + 20) + 'px');
+        {% if secure_delete %}
+        $('#secure-delete-field').keyup(function () {
+            var inputValue = $(this).val();
+            if (inputValue == 'DELETE') {
+                $('#secure-delete-btn').attr('disabled', false);
+            }else{
+                $('#secure-delete-btn').attr('disabled', true);
+            }
+        });
+        $(document).on('closing', '.remodal', function () {
+            $('#secure-delete-field').val('');
+        });
+        {% endif %}
     </script>
 {% endblock %}

+ 4 - 0
user/plugins/admin/themes/grav/templates/partials/base-root.html.twig

@@ -40,6 +40,10 @@
         {% include 'partials/messages.html.twig' %}
     {% else %}
 
+        {% block noscript %}
+            {% include 'partials/noscript.html.twig' %}
+        {% endblock noscript %}
+
         {% block page %}
         <div class="remodal-bg">
 

+ 1 - 1
user/plugins/admin/themes/grav/templates/partials/nav-quick-tray.html.twig

@@ -18,7 +18,7 @@
             {% endif %}
             <li class="{{ item.class }} hint--bottom" data-hint="{{ item.hint }}" {{ data_tags|raw }}>
             {% if item.route %}
-                <a href="{{ url(item.route) }}">
+                <a href="{{ url(item.route) }}" {% if item.target %}target="{{ item.target }}"{% endif %}>
                     <i class="fa fa-fw {{ item.icon }}"></i>
                 </a>
             {% else %}

+ 1 - 1
user/plugins/admin/themes/grav/templates/partials/nav-user-avatar.html.twig

@@ -1,2 +1,2 @@
 {% set user_avatar = admin.user.getAvatarUrl() %}
-<img src="{{ '?' not in user_avatar ? user_avatar ~ '?s=80' : user_avatar }}" />
+<img src="{{ ('?' not in user_avatar) and (not user_avatar starts with 'data:') ? user_avatar ~ '?s=80' : user_avatar }}" />

+ 42 - 0
user/plugins/admin/themes/grav/templates/partials/noscript.html.twig

@@ -0,0 +1,42 @@
+<style>
+.error-message {
+  background-color: #fce4e4;
+  border: 1px solid #fcc2c3;
+  width: 100%;
+  padding: 20px 30px;
+}
+.error-text {
+  color: #cc0033;
+  font-family: Helvetica, Arial, sans-serif;
+  width: 100%;
+  font-weight: bold;
+  line-height: 20px;
+  text-shadow: 1px 1px rgba(250,250,250,.3);
+}
+.full-height {
+  display: block;
+  width: 100%;
+  height: 100%;
+}
+</style>
+
+<div id="noscript" class="full-height">
+    <main id="admin-main" class="full-height">
+        <div id="titlebar" class="titlebar">
+            <h1><i class="fa fa-fw fa-exclamation-triangle"></i>{{ "PLUGIN_ADMIN.ERROR"|tu }}</h1>
+        </div>
+        <div class="full-height">
+                <div class="error-message {% if config.plugins.admin.content_padding %}content-padding{% endif %}">
+                    <span class="error-text">{{ "PLUGIN_ADMIN.ADMIN_NOSCRIPT_MSG"|tu }}</span>
+                </div>
+        </div>
+    </main>
+</div>
+
+<script type="text/javascript">
+  function checkjs() {
+    var element = document.getElementById("noscript");
+    element.style.display = 'none';
+  }
+  checkjs();
+</script>

+ 1 - 1
user/plugins/admin/themes/grav/templates/partials/plugins-list.html.twig

@@ -42,7 +42,7 @@
                 {% if isTestingRelease %}<span class="gpm-testing">test release</span>{% endif %}
             </td>
             <td class="gpm-actions">
-                {% if (not installing and (plugin.form.fields.enabled.type != 'hidden' and plugin.form.fields.tabs.fields.login.fields.enabled.type != 'hidden')) %}
+                {% if (not installing and (plugin.form.fields.enabled.type != 'hidden' and plugin.form.fields.tabs.fields.options.fields.enabled.type != 'hidden')) %}
                     <a class="{{ data.get('enabled') ? 'enabled' : 'disabled' }}" href="{{ uri.addNonce(base_url_relative ~ '/plugins/' ~ slug ~ '/task' ~ config.system.param_sep ~ (data.get('enabled') ? 'disable' : 'enable'), 'admin-form', 'admin-nonce') }}">
                         <i class="fa fa-fw fa-toggle-{{ data.get('enabled') ? 'on' : 'off' }}"></i>
                     </a>

+ 2 - 2
user/plugins/admin/vendor/composer/ClassLoader.php

@@ -279,7 +279,7 @@ class ClassLoader
      */
     public function setApcuPrefix($apcuPrefix)
     {
-        $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
+        $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
     }
 
     /**
@@ -377,7 +377,7 @@ class ClassLoader
             $subPath = $class;
             while (false !== $lastPos = strrpos($subPath, '\\')) {
                 $subPath = substr($subPath, 0, $lastPos);
-                $search = $subPath.'\\';
+                $search = $subPath . '\\';
                 if (isset($this->prefixDirsPsr4[$search])) {
                     $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
                     foreach ($this->prefixDirsPsr4[$search] as $dir) {

+ 9 - 9
user/plugins/admin/vendor/composer/installed.json

@@ -1,27 +1,26 @@
 [
     {
         "name": "composer/semver",
-        "version": "1.4.2",
-        "version_normalized": "1.4.2.0",
+        "version": "1.5.1",
+        "version_normalized": "1.5.1.0",
         "source": {
             "type": "git",
             "url": "https://github.com/composer/semver.git",
-            "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573"
+            "reference": "c6bea70230ef4dd483e6bbcab6005f682ed3a8de"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573",
-            "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573",
+            "url": "https://api.github.com/repos/composer/semver/zipball/c6bea70230ef4dd483e6bbcab6005f682ed3a8de",
+            "reference": "c6bea70230ef4dd483e6bbcab6005f682ed3a8de",
             "shasum": ""
         },
         "require": {
             "php": "^5.3.2 || ^7.0"
         },
         "require-dev": {
-            "phpunit/phpunit": "^4.5 || ^5.0.5",
-            "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0"
+            "phpunit/phpunit": "^4.5 || ^5.0.5"
         },
-        "time": "2016-08-30T16:08:34+00:00",
+        "time": "2020-01-13T12:06:48+00:00",
         "type": "library",
         "extra": {
             "branch-alias": {
@@ -164,6 +163,7 @@
             "security",
             "xml",
             "zf"
-        ]
+        ],
+        "abandoned": "laminas/laminas-xml"
     }
 ]

+ 12 - 0
user/plugins/admin/vendor/composer/semver/CHANGELOG.md

@@ -3,6 +3,15 @@
 All notable changes to this project will be documented in this file.
 This project adheres to [Semantic Versioning](http://semver.org/).
 
+### [1.5.1] 2020-01-13
+
+  * Fixed: Parsing of aliased version was not validating the alias to be a valid version
+
+### [1.5.0] 2019-03-19
+
+  * Added: some support for date versions (e.g. 201903) in `~` operator
+  * Fixed: support for stabilities in `~` operator was inconsistent
+
 ### [1.4.2] 2016-08-30
 
   * Fixed: collapsing of complex constraints lead to buggy constraints
@@ -57,6 +66,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
     - Namespace: `Composer\Test\Package\LinkConstraint` -> `Composer\Test\Semver\Constraint`
   * Changed: code style using php-cs-fixer.
 
+[1.5.1]: https://github.com/composer/semver/compare/1.5.0...1.5.1
+[1.5.0]: https://github.com/composer/semver/compare/1.4.2...1.5.0
+[1.4.2]: https://github.com/composer/semver/compare/1.4.1...1.4.2
 [1.4.1]: https://github.com/composer/semver/compare/1.4.0...1.4.1
 [1.4.0]: https://github.com/composer/semver/compare/1.3.0...1.4.0
 [1.3.0]: https://github.com/composer/semver/compare/1.2.0...1.3.0

+ 1 - 2
user/plugins/admin/vendor/composer/semver/composer.json

@@ -34,8 +34,7 @@
         "php": "^5.3.2 || ^7.0"
     },
     "require-dev": {
-        "phpunit/phpunit": "^4.5 || ^5.0.5",
-        "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0"
+        "phpunit/phpunit": "^4.5 || ^5.0.5"
     },
     "autoload": {
         "psr-4": {

+ 1 - 1
user/plugins/admin/vendor/composer/semver/src/Constraint/AbstractConstraint.php

@@ -11,7 +11,7 @@
 
 namespace Composer\Semver\Constraint;
 
-trigger_error('The ' . __CLASS__ . ' abstract class is deprecated, there is no replacement for it, it will be removed in the next major version.', E_USER_DEPRECATED);
+trigger_error('The ' . __NAMESPACE__ . '\AbstractConstraint abstract class is deprecated, there is no replacement for it, it will be removed in the next major version.', E_USER_DEPRECATED);
 
 /**
  * Base constraint class.

+ 3 - 7
user/plugins/admin/vendor/composer/semver/src/Constraint/Constraint.php

@@ -184,7 +184,7 @@ class Constraint implements ConstraintInterface
         // '!=' operator is match when other operator is not '==' operator or version is not match
         // these kinds of comparisons always have a solution
         if ($isNonEqualOp || $isProviderNonEqualOp) {
-            return !$isEqualOp && !$isProviderEqualOp
+            return (!$isEqualOp && !$isProviderEqualOp)
                 || $this->versionCompare($provider->version, $this->version, '!=', $compareBranches);
         }
 
@@ -197,13 +197,9 @@ class Constraint implements ConstraintInterface
         if ($this->versionCompare($provider->version, $this->version, self::$transOpInt[$this->operator], $compareBranches)) {
             // special case, e.g. require >= 1.0 and provide < 1.0
             // 1.0 >= 1.0 but 1.0 is outside of the provided interval
-            if ($provider->version === $this->version
+            return !($provider->version === $this->version
                 && self::$transOpInt[$provider->operator] === $providerNoEqualOp
-                && self::$transOpInt[$this->operator] !== $noEqualOp) {
-                return false;
-            }
-
-            return true;
+                && self::$transOpInt[$this->operator] !== $noEqualOp);
         }
 
         return false;

+ 1 - 1
user/plugins/admin/vendor/composer/semver/src/Constraint/EmptyConstraint.php

@@ -46,7 +46,7 @@ class EmptyConstraint implements ConstraintInterface
             return $this->prettyString;
         }
 
-        return $this->__toString();
+        return (string) $this;
     }
 
     /**

+ 1 - 1
user/plugins/admin/vendor/composer/semver/src/Constraint/MultiConstraint.php

@@ -102,7 +102,7 @@ class MultiConstraint implements ConstraintInterface
             return $this->prettyString;
         }
 
-        return $this->__toString();
+        return (string) $this;
     }
 
     /**

+ 2 - 2
user/plugins/admin/vendor/composer/semver/src/Semver.php

@@ -37,9 +37,9 @@ class Semver
 
         $versionParser = self::$versionParser;
         $provider = new Constraint('==', $versionParser->normalize($version));
-        $constraints = $versionParser->parseConstraints($constraints);
+        $parsedConstraints = $versionParser->parseConstraints($constraints);
 
-        return $constraints->matches($provider);
+        return $parsedConstraints->matches($provider);
     }
 
     /**

+ 22 - 25
user/plugins/admin/vendor/composer/semver/src/VersionParser.php

@@ -52,11 +52,12 @@ class VersionParser
     {
         $version = preg_replace('{#.+$}i', '', $version);
 
-        if ('dev-' === substr($version, 0, 4) || '-dev' === substr($version, -4)) {
+        if (strpos($version, 'dev-') === 0 || '-dev' === substr($version, -4)) {
             return 'dev';
         }
 
         preg_match('{' . self::$modifierRegex . '(?:\+.*)?$}i', strtolower($version), $match);
+
         if (!empty($match[3])) {
             return 'dev';
         }
@@ -107,6 +108,9 @@ class VersionParser
 
         // strip off aliasing
         if (preg_match('{^([^,\s]++) ++as ++([^,\s]++)$}', $version, $match)) {
+            // verify that the alias is a version without constraint
+            $this->normalize($match[2]);
+
             $version = $match[1];
         }
 
@@ -116,7 +120,7 @@ class VersionParser
         }
 
         // if requirement is branch-like, use full name
-        if ('dev-' === strtolower(substr($version, 0, 4))) {
+        if (stripos($version, 'dev-') === 0) {
             return 'dev-' . substr($version, 4);
         }
 
@@ -236,6 +240,7 @@ class VersionParser
 
         $orConstraints = preg_split('{\s*\|\|?\s*}', trim($constraints));
         $orGroups = array();
+
         foreach ($orConstraints as $constraints) {
             $andConstraints = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $constraints);
             if (count($andConstraints) > 1) {
@@ -268,9 +273,9 @@ class VersionParser
             && 2 === count($orGroups[0]->getConstraints())
             && 2 === count($orGroups[1]->getConstraints())
             && ($a = (string) $orGroups[0])
-            && substr($a, 0, 3) === '[>=' && (false !== ($posA = strpos($a, '<', 4)))
+            && strpos($a, '[>=') === 0 && (false !== ($posA = strpos($a, '<', 4)))
             && ($b = (string) $orGroups[1])
-            && substr($b, 0, 3) === '[>=' && (false !== ($posB = strpos($b, '<', 4)))
+            && strpos($b, '[>=') === 0 && (false !== ($posB = strpos($b, '<', 4)))
             && substr($a, $posA + 2, -1) === substr($b, 4, $posB - 5)
         ) {
             $constraint = new MultiConstraint(array(
@@ -314,7 +319,7 @@ class VersionParser
         // version, to ensure that unstable instances of the current version are allowed. However, if a stability
         // suffix is added to the constraint, then a >= match on the current version is used instead.
         if (preg_match('{^~>?' . $versionRegex . '$}i', $constraint, $matches)) {
-            if (substr($constraint, 0, 2) === '~>') {
+            if (strpos($constraint, '~>') === 0) {
                 throw new \UnexpectedValueException(
                     'Could not parse version constraint ' . $constraint . ': ' .
                     'Invalid operator "~>", you probably meant to use the "~" operator'
@@ -322,11 +327,11 @@ class VersionParser
             }
 
             // Work out which position in the version we are operating at
-            if (isset($matches[4]) && '' !== $matches[4]) {
+            if (isset($matches[4]) && '' !== $matches[4] && null !== $matches[4]) {
                 $position = 4;
-            } elseif (isset($matches[3]) && '' !== $matches[3]) {
+            } elseif (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) {
                 $position = 3;
-            } elseif (isset($matches[2]) && '' !== $matches[2]) {
+            } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) {
                 $position = 2;
             } else {
                 $position = 1;
@@ -334,19 +339,11 @@ class VersionParser
 
             // Calculate the stability suffix
             $stabilitySuffix = '';
-            if (!empty($matches[5])) {
-                $stabilitySuffix .= '-' . $this->expandStability($matches[5]) . (!empty($matches[6]) ? $matches[6] : '');
-            }
-
-            if (!empty($matches[7])) {
+            if (empty($matches[5]) && empty($matches[7])) {
                 $stabilitySuffix .= '-dev';
             }
 
-            if (!$stabilitySuffix) {
-                $stabilitySuffix = '-dev';
-            }
-
-            $lowVersion = $this->manipulateVersionString($matches, $position, 0) . $stabilitySuffix;
+            $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1));
             $lowerBound = new Constraint('>=', $lowVersion);
 
             // For upper bound, we increment the position of one more significance,
@@ -368,9 +365,9 @@ class VersionParser
         // versions 0.X >=0.1.0, and no updates for versions 0.0.X
         if (preg_match('{^\^' . $versionRegex . '($)}i', $constraint, $matches)) {
             // Work out which position in the version we are operating at
-            if ('0' !== $matches[1] || '' === $matches[2]) {
+            if ('0' !== $matches[1] || '' === $matches[2] || null === $matches[2]) {
                 $position = 1;
-            } elseif ('0' !== $matches[2] || '' === $matches[3]) {
+            } elseif ('0' !== $matches[2] || '' === $matches[3] || null === $matches[3]) {
                 $position = 2;
             } else {
                 $position = 3;
@@ -401,9 +398,9 @@ class VersionParser
         // Any of X, x, or * may be used to "stand in" for one of the numeric values in the [major, minor, patch] tuple.
         // A partial version range is treated as an X-Range, so the special character is in fact optional.
         if (preg_match('{^v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.[xX*])++$}', $constraint, $matches)) {
-            if (isset($matches[3]) && '' !== $matches[3]) {
+            if (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) {
                 $position = 3;
-            } elseif (isset($matches[2]) && '' !== $matches[2]) {
+            } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) {
                 $position = 2;
             } else {
                 $position = 1;
@@ -462,11 +459,11 @@ class VersionParser
             try {
                 $version = $this->normalize($matches[2]);
 
-                if (!empty($stabilityModifier) && $this->parseStability($version) === 'stable') {
+                if (!empty($stabilityModifier) && self::parseStability($version) === 'stable') {
                     $version .= '-' . $stabilityModifier;
                 } elseif ('<' === $matches[1] || '>=' === $matches[1]) {
                     if (!preg_match('/-' . self::$modifierRegex . '$/', strtolower($matches[2]))) {
-                        if (substr($matches[2], 0, 4) !== 'dev-') {
+                        if (strpos($matches[2], 'dev-') !== 0) {
                             $version .= '-dev';
                         }
                     }
@@ -511,7 +508,7 @@ class VersionParser
 
                     // Return null on a carry overflow
                     if ($i === 1) {
-                        return;
+                        return null;
                     }
                 }
             }

+ 41 - 0
user/plugins/email/CHANGELOG.md

@@ -1,3 +1,44 @@
+# v3.0.9
+## 06/08/2020
+
+1. [](#improved)
+    * Disable password autocomplete in password field
+    * Don't save empty string in password field [#134](https://github.com/getgrav/grav-plugin-email/issues/134)
+
+# v3.0.8
+## 04/27/2020
+
+1. [](#improved)
+    * Updated vendor library files
+    * Use Grav's Parsedown class
+
+# v3.0.7
+## 03/05/2020
+
+1. [](#improved)
+    * Updated email validator library
+1. [](#bugfix)
+    * Fixed `Invalid resource theme://` on CLI command `test-email` on Grav 1.6.21 and later versions [#128](https://github.com/getgrav/grav-plugin-email/issues/128)
+
+# v3.0.6
+## 02/11/2020
+
+1. [](#improved)
+    * Updated email validator library
+
+# v3.0.5
+## 02/03/2020
+
+1. [](#bugfix)
+    * Fixed a date in changelog (no other changes)
+
+# v3.0.4
+## 01/17/2020
+
+1. [](#improved)
+    * Added ZOHO configuration example
+    * Updated SwiftMailer library for PHP 7.4 support
+
 # v3.0.3
 ## 08/16/2019
 

+ 19 - 0
user/plugins/email/README.md

@@ -159,6 +159,25 @@ mailer:
 
 It's that easy!
 
+#### ZOHO
+
+ZOHO is a popular solution for hosted email due to it's great 'FREE' tier.  It's paid options are also very reasonable and combined with the latest UI updates and outstanding security features, it's a solid email option.
+
+In order to get ZOHO working with Grav, you need to send email via a user account.  You can either use your users' password or generate an **App Password** via your ZOHO account (clicking on your avatar once logged in), then navigating to `Two Factor Authentication -> App Passwords -> Generate`. Just enter a unique app name (i.e. `Grav Website`).
+
+NOTE: The SMTP host required can be found in `Settings -> Mail - > Mail Accounts -> POP/IMAP -> SMTP`.  This will provide the SMTP server for this account (it may not be `imap.zoho.com` depending on what region you are in)
+
+```
+mailer:
+  engine: smtp
+  smtp:
+    server: smtp.zoho.com
+    port: 587
+    encryption: tls
+    user: 'ZOHO_EMAIL_ADDRESS'
+    password: 'ZOHO_EMAIL_PASSWORD'
+```
+
 #### Sendmail
 
 Although not as reliable as SMTP not providing as much debug information, sendmail is a simple option as long as your hosting provider is not blocking the default SMTP port `25`:

+ 6 - 3
user/plugins/email/blueprints.yaml

@@ -1,5 +1,7 @@
 name: Email
-version: 3.0.3
+slug: email
+type: plugin
+version: 3.0.9
 testing: false
 description: Enables the emailing system for Grav
 icon: envelope
@@ -18,6 +20,7 @@ dependencies:
 
 form:
   validation: loose
+
   fields:
     enabled:
       type: hidden
@@ -168,13 +171,13 @@ form:
     mailer.smtp.user:
       type: text
       size: medium
-      autocomplete: nope
+      autocomplete: 'off'
       label: PLUGIN_EMAIL.SMTP_LOGIN_NAME
 
     mailer.smtp.password:
       type: password
       size: medium
-      autocomplete: nope
+      autocomplete: 'new-password'
       label: PLUGIN_EMAIL.SMTP_PASSWORD
 
     sendmail_config:

+ 3 - 2
user/plugins/email/classes/Email.php

@@ -4,6 +4,7 @@ namespace Grav\Plugin\Email;
 use Grav\Common\Config\Config;
 use Grav\Common\Grav;
 use Grav\Common\Language\Language;
+use Grav\Common\Markdown\Parsedown;
 use Grav\Common\Twig\Twig;
 use Grav\Framework\Form\Interfaces\FormInterface;
 use \Monolog\Logger;
@@ -178,7 +179,7 @@ class Email
                         $body = $twig->processString($value, $vars);
 
                         if ($params['process_markdown']) {
-                            $parsedown = new \Parsedown();
+                            $parsedown = new Parsedown();
                             $body = $parsedown->text($body);
                         }
 
@@ -202,7 +203,7 @@ class Email
                             $body = !empty($body_part['body']) ? $twig->processString($body_part['body'], $vars) : null;
 
                             if ($params['process_markdown']) {
-                                $parsedown = new \Parsedown();
+                                $parsedown = new Parsedown();
                                 $body = $parsedown->text($body);
                             }
 

+ 5 - 0
user/plugins/email/cli/ClearQueueFailuresCommand.php

@@ -40,6 +40,11 @@ class ClearQueueFailuresCommand extends ConsoleCommand
      */
     protected function serve()
     {
+        // TODO: remove when requiring Grav 1.7+
+        if (method_exists($this, 'initializeGrav')) {
+            $this->initializeGrav();
+        }
+
         $grav = Grav::instance();
 
         $this->output->writeln('');

+ 5 - 0
user/plugins/email/cli/FlushQueueCommand.php

@@ -40,6 +40,11 @@ class FlushQueueCommand extends ConsoleCommand
      */
     protected function serve()
     {
+        // TODO: remove when requiring Grav 1.7+
+        if (method_exists($this, 'initializeGrav')) {
+            $this->initializeGrav();
+        }
+
         $grav = Grav::instance();
 
         $this->output->writeln('');

+ 5 - 4
user/plugins/email/cli/TestEmailCommand.php

@@ -59,6 +59,11 @@ class TestEmailCommand extends ConsoleCommand
      */
     protected function serve()
     {
+        // TODO: remove when requiring Grav 1.7+
+        if (method_exists($this, 'initializeGrav')) {
+            $this->initializeThemes();
+        }
+
         $grav = Grav::instance();
 
         $this->output->writeln('');
@@ -69,8 +74,6 @@ class TestEmailCommand extends ConsoleCommand
 
         $this->output->writeln('');
 
-        require_once __DIR__ . '/../vendor/autoload.php';
-
         $grav['Email'] = new Email();
 
         $to = $this->input->getOption('to') ?: $grav['config']->get('plugins.email.to');
@@ -86,8 +89,6 @@ class TestEmailCommand extends ConsoleCommand
             $body = $grav['language']->translate(['PLUGIN_EMAIL.TEST_EMAIL_BODY', $configuration]);
         }
 
-        // This is the old way....
-        // $sent = EmailUtils::sendEmail($subject, $body, $email_to);
         $sent = EmailUtils::sendEmail(['subject'=>$subject, 'body'=>$body, 'to'=>$to]);
 
         if ($sent) {

+ 126 - 60
user/plugins/email/composer.lock

@@ -8,30 +8,35 @@
     "packages": [
         {
             "name": "doctrine/lexer",
-            "version": "v1.0.1",
+            "version": "1.2.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/doctrine/lexer.git",
-                "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c"
+                "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c",
-                "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c",
+                "url": "https://api.github.com/repos/doctrine/lexer/zipball/5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6",
+                "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6",
                 "shasum": ""
             },
             "require": {
-                "php": ">=5.3.2"
+                "php": "^7.2"
+            },
+            "require-dev": {
+                "doctrine/coding-standard": "^6.0",
+                "phpstan/phpstan": "^0.11.8",
+                "phpunit/phpunit": "^8.2"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "1.0.x-dev"
+                    "dev-master": "1.2.x-dev"
                 }
             },
             "autoload": {
-                "psr-0": {
-                    "Doctrine\\Common\\Lexer\\": "lib/"
+                "psr-4": {
+                    "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer"
                 }
             },
             "notification-url": "https://packagist.org/downloads/",
@@ -39,48 +44,52 @@
                 "MIT"
             ],
             "authors": [
-                {
-                    "name": "Roman Borschel",
-                    "email": "roman@code-factory.org"
-                },
                 {
                     "name": "Guilherme Blanco",
                     "email": "guilhermeblanco@gmail.com"
                 },
+                {
+                    "name": "Roman Borschel",
+                    "email": "roman@code-factory.org"
+                },
                 {
                     "name": "Johannes Schmitt",
                     "email": "schmittjoh@gmail.com"
                 }
             ],
-            "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
-            "homepage": "http://www.doctrine-project.org",
+            "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.",
+            "homepage": "https://www.doctrine-project.org/projects/lexer.html",
             "keywords": [
+                "annotations",
+                "docblock",
                 "lexer",
-                "parser"
+                "parser",
+                "php"
             ],
-            "time": "2014-09-09T13:34:57+00:00"
+            "time": "2019-10-30T14:39:59+00:00"
         },
         {
             "name": "egulias/email-validator",
-            "version": "2.1.7",
+            "version": "2.1.17",
             "source": {
                 "type": "git",
                 "url": "https://github.com/egulias/EmailValidator.git",
-                "reference": "709f21f92707308cdf8f9bcfa1af4cb26586521e"
+                "reference": "ade6887fd9bd74177769645ab5c474824f8a418a"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/709f21f92707308cdf8f9bcfa1af4cb26586521e",
-                "reference": "709f21f92707308cdf8f9bcfa1af4cb26586521e",
+                "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ade6887fd9bd74177769645ab5c474824f8a418a",
+                "reference": "ade6887fd9bd74177769645ab5c474824f8a418a",
                 "shasum": ""
             },
             "require": {
                 "doctrine/lexer": "^1.0.1",
-                "php": ">= 5.5"
+                "php": ">=5.5",
+                "symfony/polyfill-intl-idn": "^1.10"
             },
             "require-dev": {
-                "dominicsayers/isemail": "dev-master",
-                "phpunit/phpunit": "^4.8.35||^5.7||^6.0",
+                "dominicsayers/isemail": "^3.0.7",
+                "phpunit/phpunit": "^4.8.36|^7.5.15",
                 "satooshi/php-coveralls": "^1.0.1"
             },
             "suggest": {
@@ -89,7 +98,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.0.x-dev"
+                    "dev-master": "2.1.x-dev"
                 }
             },
             "autoload": {
@@ -115,20 +124,20 @@
                 "validation",
                 "validator"
             ],
-            "time": "2018-12-04T22:38:24+00:00"
+            "time": "2020-02-13T22:36:52+00:00"
         },
         {
             "name": "swiftmailer/swiftmailer",
-            "version": "v6.2.0",
+            "version": "v6.2.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/swiftmailer/swiftmailer.git",
-                "reference": "6fa3232ff9d3f8237c0fae4b7ff05e1baa4cd707"
+                "reference": "149cfdf118b169f7840bbe3ef0d4bc795d1780c9"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/6fa3232ff9d3f8237c0fae4b7ff05e1baa4cd707",
-                "reference": "6fa3232ff9d3f8237c0fae4b7ff05e1baa4cd707",
+                "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/149cfdf118b169f7840bbe3ef0d4bc795d1780c9",
+                "reference": "149cfdf118b169f7840bbe3ef0d4bc795d1780c9",
                 "shasum": ""
             },
             "require": {
@@ -177,20 +186,20 @@
                 "mail",
                 "mailer"
             ],
-            "time": "2019-03-10T07:52:41+00:00"
+            "time": "2019-11-12T09:31:26+00:00"
         },
         {
             "name": "symfony/polyfill-iconv",
-            "version": "v1.10.0",
+            "version": "v1.15.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-iconv.git",
-                "reference": "97001cfc283484c9691769f51cdf25259037eba2"
+                "reference": "ad6d62792bfbcfc385dd34b424d4fcf9712a32c8"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/97001cfc283484c9691769f51cdf25259037eba2",
-                "reference": "97001cfc283484c9691769f51cdf25259037eba2",
+                "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/ad6d62792bfbcfc385dd34b424d4fcf9712a32c8",
+                "reference": "ad6d62792bfbcfc385dd34b424d4fcf9712a32c8",
                 "shasum": ""
             },
             "require": {
@@ -202,7 +211,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "1.9-dev"
+                    "dev-master": "1.15-dev"
                 }
             },
             "autoload": {
@@ -236,26 +245,40 @@
                 "portable",
                 "shim"
             ],
-            "time": "2018-09-21T06:26:08+00:00"
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2020-03-09T19:04:49+00:00"
         },
         {
             "name": "symfony/polyfill-intl-idn",
-            "version": "v1.10.0",
+            "version": "v1.15.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-intl-idn.git",
-                "reference": "89de1d44f2c059b266f22c9cc9124ddc4cd0987a"
+                "reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/89de1d44f2c059b266f22c9cc9124ddc4cd0987a",
-                "reference": "89de1d44f2c059b266f22c9cc9124ddc4cd0987a",
+                "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf",
+                "reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf",
                 "shasum": ""
             },
             "require": {
                 "php": ">=5.3.3",
                 "symfony/polyfill-mbstring": "^1.3",
-                "symfony/polyfill-php72": "^1.9"
+                "symfony/polyfill-php72": "^1.10"
             },
             "suggest": {
                 "ext-intl": "For best performance"
@@ -263,7 +286,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "1.9-dev"
+                    "dev-master": "1.15-dev"
                 }
             },
             "autoload": {
@@ -279,13 +302,13 @@
                 "MIT"
             ],
             "authors": [
-                {
-                    "name": "Symfony Community",
-                    "homepage": "https://symfony.com/contributors"
-                },
                 {
                     "name": "Laurent Bassin",
                     "email": "laurent@bassin.info"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
                 }
             ],
             "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
@@ -298,20 +321,34 @@
                 "portable",
                 "shim"
             ],
-            "time": "2018-09-30T16:36:12+00:00"
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2020-03-09T19:04:49+00:00"
         },
         {
             "name": "symfony/polyfill-mbstring",
-            "version": "v1.10.0",
+            "version": "v1.15.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-mbstring.git",
-                "reference": "c79c051f5b3a46be09205c73b80b346e4153e494"
+                "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494",
-                "reference": "c79c051f5b3a46be09205c73b80b346e4153e494",
+                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
+                "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
                 "shasum": ""
             },
             "require": {
@@ -323,7 +360,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "1.9-dev"
+                    "dev-master": "1.15-dev"
                 }
             },
             "autoload": {
@@ -357,20 +394,34 @@
                 "portable",
                 "shim"
             ],
-            "time": "2018-09-21T13:07:52+00:00"
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2020-03-09T19:04:49+00:00"
         },
         {
             "name": "symfony/polyfill-php72",
-            "version": "v1.10.0",
+            "version": "v1.15.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-php72.git",
-                "reference": "9050816e2ca34a8e916c3a0ae8b9c2fccf68b631"
+                "reference": "37b0976c78b94856543260ce09b460a7bc852747"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9050816e2ca34a8e916c3a0ae8b9c2fccf68b631",
-                "reference": "9050816e2ca34a8e916c3a0ae8b9c2fccf68b631",
+                "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/37b0976c78b94856543260ce09b460a7bc852747",
+                "reference": "37b0976c78b94856543260ce09b460a7bc852747",
                 "shasum": ""
             },
             "require": {
@@ -379,7 +430,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "1.9-dev"
+                    "dev-master": "1.15-dev"
                 }
             },
             "autoload": {
@@ -412,7 +463,21 @@
                 "portable",
                 "shim"
             ],
-            "time": "2018-09-21T13:07:52+00:00"
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2020-02-27T09:26:54+00:00"
         }
     ],
     "packages-dev": [],
@@ -424,5 +489,6 @@
     "platform": {
         "php": ">=7.1.3"
     },
-    "platform-dev": []
+    "platform-dev": [],
+    "plugin-api-version": "1.1.0"
 }

+ 24 - 0
user/plugins/email/email.php

@@ -1,6 +1,7 @@
 <?php
 namespace Grav\Plugin;
 
+use Grav\Common\Data\Data;
 use Grav\Common\Plugin;
 use Grav\Plugin\Email\Email;
 use RocketTheme\Toolbox\Event\Event;
@@ -22,6 +23,7 @@ class EmailPlugin extends Plugin
             'onFormProcessed'           => ['onFormProcessed', 0],
             'onTwigTemplatePaths'       => ['onTwigTemplatePaths', 0],
             'onSchedulerInitialized'    => ['onSchedulerInitialized', 0],
+            'onAdminSave'               => ['onAdminSave', 0],
         ];
     }
 
@@ -48,6 +50,28 @@ class EmailPlugin extends Plugin
         $twig->twig_paths[] = __DIR__ . '/templates';
     }
 
+    /**
+     * Force compile during save if admin plugin save
+     *
+     * @param Event $event
+     */
+    public function onAdminSave(Event $event)
+    {
+        /** @var Data $obj */
+        $obj = $event['object'];
+
+
+
+        if ($obj instanceof Data && $obj->blueprints()->getFilename() === 'email/blueprints') {
+            $current_pw = $this->grav['config']->get('plugins.email.mailer.smtp.password');
+            $new_pw = $obj->get('mailer.smtp.password');
+            if (!empty($current_pw) && empty($new_pw)) {
+                $obj->set('mailer.smtp.password', $current_pw);
+            }
+
+        }
+    }
+
     /**
      * Send email when processing the form data.
      *

+ 2 - 2
user/plugins/email/vendor/composer/ClassLoader.php

@@ -279,7 +279,7 @@ class ClassLoader
      */
     public function setApcuPrefix($apcuPrefix)
     {
-        $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
+        $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
     }
 
     /**
@@ -377,7 +377,7 @@ class ClassLoader
             $subPath = $class;
             while (false !== $lastPos = strrpos($subPath, '\\')) {
                 $subPath = substr($subPath, 0, $lastPos);
-                $search = $subPath.'\\';
+                $search = $subPath . '\\';
                 if (isset($this->prefixDirsPsr4[$search])) {
                     $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
                     foreach ($this->prefixDirsPsr4[$search] as $dir) {

+ 1 - 1
user/plugins/email/vendor/composer/autoload_files.php

@@ -8,7 +8,7 @@ $baseDir = dirname($vendorDir);
 return array(
     '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
     '25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
-    'def43f6c87e4f8dfd0c9e1b1bab14fe8' => $vendorDir . '/symfony/polyfill-iconv/bootstrap.php',
     'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
+    'def43f6c87e4f8dfd0c9e1b1bab14fe8' => $vendorDir . '/symfony/polyfill-iconv/bootstrap.php',
     '2c102faa651ef8ea5874edb585946bce' => $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php',
 );

+ 0 - 1
user/plugins/email/vendor/composer/autoload_namespaces.php

@@ -6,5 +6,4 @@ $vendorDir = dirname(dirname(__FILE__));
 $baseDir = dirname($vendorDir);
 
 return array(
-    'Doctrine\\Common\\Lexer\\' => array($vendorDir . '/doctrine/lexer/lib'),
 );

+ 1 - 0
user/plugins/email/vendor/composer/autoload_psr4.php

@@ -13,4 +13,5 @@ return array(
     'Grav\\Plugin\\Email\\' => array($baseDir . '/classes'),
     'Grav\\Plugin\\Console\\' => array($baseDir . '/cli'),
     'Egulias\\EmailValidator\\' => array($vendorDir . '/egulias/email-validator/EmailValidator'),
+    'Doctrine\\Common\\Lexer\\' => array($vendorDir . '/doctrine/lexer/lib/Doctrine/Common/Lexer'),
 );

+ 3 - 0
user/plugins/email/vendor/composer/autoload_real.php

@@ -13,6 +13,9 @@ class ComposerAutoloaderInitdec5d78def1384d1f20996ded9d7efbf
         }
     }
 
+    /**
+     * @return \Composer\Autoload\ClassLoader
+     */
     public static function getLoader()
     {
         if (null !== self::$loader) {

+ 7 - 10
user/plugins/email/vendor/composer/autoload_static.php

@@ -9,8 +9,8 @@ class ComposerStaticInitdec5d78def1384d1f20996ded9d7efbf
     public static $files = array (
         '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
         '25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
-        'def43f6c87e4f8dfd0c9e1b1bab14fe8' => __DIR__ . '/..' . '/symfony/polyfill-iconv/bootstrap.php',
         'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php',
+        'def43f6c87e4f8dfd0c9e1b1bab14fe8' => __DIR__ . '/..' . '/symfony/polyfill-iconv/bootstrap.php',
         '2c102faa651ef8ea5874edb585946bce' => __DIR__ . '/..' . '/swiftmailer/swiftmailer/lib/swift_required.php',
     );
 
@@ -31,6 +31,10 @@ class ComposerStaticInitdec5d78def1384d1f20996ded9d7efbf
         array (
             'Egulias\\EmailValidator\\' => 23,
         ),
+        'D' => 
+        array (
+            'Doctrine\\Common\\Lexer\\' => 22,
+        ),
     );
 
     public static $prefixDirsPsr4 = array (
@@ -62,15 +66,9 @@ class ComposerStaticInitdec5d78def1384d1f20996ded9d7efbf
         array (
             0 => __DIR__ . '/..' . '/egulias/email-validator/EmailValidator',
         ),
-    );
-
-    public static $prefixesPsr0 = array (
-        'D' => 
+        'Doctrine\\Common\\Lexer\\' => 
         array (
-            'Doctrine\\Common\\Lexer\\' => 
-            array (
-                0 => __DIR__ . '/..' . '/doctrine/lexer/lib',
-            ),
+            0 => __DIR__ . '/..' . '/doctrine/lexer/lib/Doctrine/Common/Lexer',
         ),
     );
 
@@ -83,7 +81,6 @@ class ComposerStaticInitdec5d78def1384d1f20996ded9d7efbf
         return \Closure::bind(function () use ($loader) {
             $loader->prefixLengthsPsr4 = ComposerStaticInitdec5d78def1384d1f20996ded9d7efbf::$prefixLengthsPsr4;
             $loader->prefixDirsPsr4 = ComposerStaticInitdec5d78def1384d1f20996ded9d7efbf::$prefixDirsPsr4;
-            $loader->prefixesPsr0 = ComposerStaticInitdec5d78def1384d1f20996ded9d7efbf::$prefixesPsr0;
             $loader->classMap = ComposerStaticInitdec5d78def1384d1f20996ded9d7efbf::$classMap;
 
         }, null, ClassLoader::class);

+ 131 - 66
user/plugins/email/vendor/composer/installed.json

@@ -1,33 +1,38 @@
 [
     {
         "name": "doctrine/lexer",
-        "version": "v1.0.1",
-        "version_normalized": "1.0.1.0",
+        "version": "1.2.0",
+        "version_normalized": "1.2.0.0",
         "source": {
             "type": "git",
             "url": "https://github.com/doctrine/lexer.git",
-            "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c"
+            "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c",
-            "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c",
+            "url": "https://api.github.com/repos/doctrine/lexer/zipball/5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6",
+            "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6",
             "shasum": ""
         },
         "require": {
-            "php": ">=5.3.2"
+            "php": "^7.2"
         },
-        "time": "2014-09-09T13:34:57+00:00",
+        "require-dev": {
+            "doctrine/coding-standard": "^6.0",
+            "phpstan/phpstan": "^0.11.8",
+            "phpunit/phpunit": "^8.2"
+        },
+        "time": "2019-10-30T14:39:59+00:00",
         "type": "library",
         "extra": {
             "branch-alias": {
-                "dev-master": "1.0.x-dev"
+                "dev-master": "1.2.x-dev"
             }
         },
         "installation-source": "dist",
         "autoload": {
-            "psr-0": {
-                "Doctrine\\Common\\Lexer\\": "lib/"
+            "psr-4": {
+                "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer"
             }
         },
         "notification-url": "https://packagist.org/downloads/",
@@ -35,58 +40,62 @@
             "MIT"
         ],
         "authors": [
-            {
-                "name": "Roman Borschel",
-                "email": "roman@code-factory.org"
-            },
             {
                 "name": "Guilherme Blanco",
                 "email": "guilhermeblanco@gmail.com"
             },
+            {
+                "name": "Roman Borschel",
+                "email": "roman@code-factory.org"
+            },
             {
                 "name": "Johannes Schmitt",
                 "email": "schmittjoh@gmail.com"
             }
         ],
-        "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
-        "homepage": "http://www.doctrine-project.org",
+        "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.",
+        "homepage": "https://www.doctrine-project.org/projects/lexer.html",
         "keywords": [
+            "annotations",
+            "docblock",
             "lexer",
-            "parser"
+            "parser",
+            "php"
         ]
     },
     {
         "name": "egulias/email-validator",
-        "version": "2.1.7",
-        "version_normalized": "2.1.7.0",
+        "version": "2.1.17",
+        "version_normalized": "2.1.17.0",
         "source": {
             "type": "git",
             "url": "https://github.com/egulias/EmailValidator.git",
-            "reference": "709f21f92707308cdf8f9bcfa1af4cb26586521e"
+            "reference": "ade6887fd9bd74177769645ab5c474824f8a418a"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/709f21f92707308cdf8f9bcfa1af4cb26586521e",
-            "reference": "709f21f92707308cdf8f9bcfa1af4cb26586521e",
+            "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ade6887fd9bd74177769645ab5c474824f8a418a",
+            "reference": "ade6887fd9bd74177769645ab5c474824f8a418a",
             "shasum": ""
         },
         "require": {
             "doctrine/lexer": "^1.0.1",
-            "php": ">= 5.5"
+            "php": ">=5.5",
+            "symfony/polyfill-intl-idn": "^1.10"
         },
         "require-dev": {
-            "dominicsayers/isemail": "dev-master",
-            "phpunit/phpunit": "^4.8.35||^5.7||^6.0",
+            "dominicsayers/isemail": "^3.0.7",
+            "phpunit/phpunit": "^4.8.36|^7.5.15",
             "satooshi/php-coveralls": "^1.0.1"
         },
         "suggest": {
             "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation"
         },
-        "time": "2018-12-04T22:38:24+00:00",
+        "time": "2020-02-13T22:36:52+00:00",
         "type": "library",
         "extra": {
             "branch-alias": {
-                "dev-master": "2.0.x-dev"
+                "dev-master": "2.1.x-dev"
             }
         },
         "installation-source": "dist",
@@ -116,17 +125,17 @@
     },
     {
         "name": "swiftmailer/swiftmailer",
-        "version": "v6.2.0",
-        "version_normalized": "6.2.0.0",
+        "version": "v6.2.3",
+        "version_normalized": "6.2.3.0",
         "source": {
             "type": "git",
             "url": "https://github.com/swiftmailer/swiftmailer.git",
-            "reference": "6fa3232ff9d3f8237c0fae4b7ff05e1baa4cd707"
+            "reference": "149cfdf118b169f7840bbe3ef0d4bc795d1780c9"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/6fa3232ff9d3f8237c0fae4b7ff05e1baa4cd707",
-            "reference": "6fa3232ff9d3f8237c0fae4b7ff05e1baa4cd707",
+            "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/149cfdf118b169f7840bbe3ef0d4bc795d1780c9",
+            "reference": "149cfdf118b169f7840bbe3ef0d4bc795d1780c9",
             "shasum": ""
         },
         "require": {
@@ -144,7 +153,7 @@
             "ext-intl": "Needed to support internationalized email addresses",
             "true/punycode": "Needed to support internationalized email addresses, if ext-intl is not installed"
         },
-        "time": "2019-03-10T07:52:41+00:00",
+        "time": "2019-11-12T09:31:26+00:00",
         "type": "library",
         "extra": {
             "branch-alias": {
@@ -180,17 +189,17 @@
     },
     {
         "name": "symfony/polyfill-iconv",
-        "version": "v1.10.0",
-        "version_normalized": "1.10.0.0",
+        "version": "v1.15.0",
+        "version_normalized": "1.15.0.0",
         "source": {
             "type": "git",
             "url": "https://github.com/symfony/polyfill-iconv.git",
-            "reference": "97001cfc283484c9691769f51cdf25259037eba2"
+            "reference": "ad6d62792bfbcfc385dd34b424d4fcf9712a32c8"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/97001cfc283484c9691769f51cdf25259037eba2",
-            "reference": "97001cfc283484c9691769f51cdf25259037eba2",
+            "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/ad6d62792bfbcfc385dd34b424d4fcf9712a32c8",
+            "reference": "ad6d62792bfbcfc385dd34b424d4fcf9712a32c8",
             "shasum": ""
         },
         "require": {
@@ -199,11 +208,11 @@
         "suggest": {
             "ext-iconv": "For best performance"
         },
-        "time": "2018-09-21T06:26:08+00:00",
+        "time": "2020-03-09T19:04:49+00:00",
         "type": "library",
         "extra": {
             "branch-alias": {
-                "dev-master": "1.9-dev"
+                "dev-master": "1.15-dev"
             }
         },
         "installation-source": "dist",
@@ -237,36 +246,50 @@
             "polyfill",
             "portable",
             "shim"
+        ],
+        "funding": [
+            {
+                "url": "https://symfony.com/sponsor",
+                "type": "custom"
+            },
+            {
+                "url": "https://github.com/fabpot",
+                "type": "github"
+            },
+            {
+                "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                "type": "tidelift"
+            }
         ]
     },
     {
         "name": "symfony/polyfill-intl-idn",
-        "version": "v1.10.0",
-        "version_normalized": "1.10.0.0",
+        "version": "v1.15.0",
+        "version_normalized": "1.15.0.0",
         "source": {
             "type": "git",
             "url": "https://github.com/symfony/polyfill-intl-idn.git",
-            "reference": "89de1d44f2c059b266f22c9cc9124ddc4cd0987a"
+            "reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/89de1d44f2c059b266f22c9cc9124ddc4cd0987a",
-            "reference": "89de1d44f2c059b266f22c9cc9124ddc4cd0987a",
+            "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf",
+            "reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf",
             "shasum": ""
         },
         "require": {
             "php": ">=5.3.3",
             "symfony/polyfill-mbstring": "^1.3",
-            "symfony/polyfill-php72": "^1.9"
+            "symfony/polyfill-php72": "^1.10"
         },
         "suggest": {
             "ext-intl": "For best performance"
         },
-        "time": "2018-09-30T16:36:12+00:00",
+        "time": "2020-03-09T19:04:49+00:00",
         "type": "library",
         "extra": {
             "branch-alias": {
-                "dev-master": "1.9-dev"
+                "dev-master": "1.15-dev"
             }
         },
         "installation-source": "dist",
@@ -283,13 +306,13 @@
             "MIT"
         ],
         "authors": [
-            {
-                "name": "Symfony Community",
-                "homepage": "https://symfony.com/contributors"
-            },
             {
                 "name": "Laurent Bassin",
                 "email": "laurent@bassin.info"
+            },
+            {
+                "name": "Symfony Community",
+                "homepage": "https://symfony.com/contributors"
             }
         ],
         "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
@@ -301,21 +324,35 @@
             "polyfill",
             "portable",
             "shim"
+        ],
+        "funding": [
+            {
+                "url": "https://symfony.com/sponsor",
+                "type": "custom"
+            },
+            {
+                "url": "https://github.com/fabpot",
+                "type": "github"
+            },
+            {
+                "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                "type": "tidelift"
+            }
         ]
     },
     {
         "name": "symfony/polyfill-mbstring",
-        "version": "v1.10.0",
-        "version_normalized": "1.10.0.0",
+        "version": "v1.15.0",
+        "version_normalized": "1.15.0.0",
         "source": {
             "type": "git",
             "url": "https://github.com/symfony/polyfill-mbstring.git",
-            "reference": "c79c051f5b3a46be09205c73b80b346e4153e494"
+            "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494",
-            "reference": "c79c051f5b3a46be09205c73b80b346e4153e494",
+            "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
+            "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
             "shasum": ""
         },
         "require": {
@@ -324,11 +361,11 @@
         "suggest": {
             "ext-mbstring": "For best performance"
         },
-        "time": "2018-09-21T13:07:52+00:00",
+        "time": "2020-03-09T19:04:49+00:00",
         "type": "library",
         "extra": {
             "branch-alias": {
-                "dev-master": "1.9-dev"
+                "dev-master": "1.15-dev"
             }
         },
         "installation-source": "dist",
@@ -362,31 +399,45 @@
             "polyfill",
             "portable",
             "shim"
+        ],
+        "funding": [
+            {
+                "url": "https://symfony.com/sponsor",
+                "type": "custom"
+            },
+            {
+                "url": "https://github.com/fabpot",
+                "type": "github"
+            },
+            {
+                "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                "type": "tidelift"
+            }
         ]
     },
     {
         "name": "symfony/polyfill-php72",
-        "version": "v1.10.0",
-        "version_normalized": "1.10.0.0",
+        "version": "v1.15.0",
+        "version_normalized": "1.15.0.0",
         "source": {
             "type": "git",
             "url": "https://github.com/symfony/polyfill-php72.git",
-            "reference": "9050816e2ca34a8e916c3a0ae8b9c2fccf68b631"
+            "reference": "37b0976c78b94856543260ce09b460a7bc852747"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9050816e2ca34a8e916c3a0ae8b9c2fccf68b631",
-            "reference": "9050816e2ca34a8e916c3a0ae8b9c2fccf68b631",
+            "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/37b0976c78b94856543260ce09b460a7bc852747",
+            "reference": "37b0976c78b94856543260ce09b460a7bc852747",
             "shasum": ""
         },
         "require": {
             "php": ">=5.3.3"
         },
-        "time": "2018-09-21T13:07:52+00:00",
+        "time": "2020-02-27T09:26:54+00:00",
         "type": "library",
         "extra": {
             "branch-alias": {
-                "dev-master": "1.9-dev"
+                "dev-master": "1.15-dev"
             }
         },
         "installation-source": "dist",
@@ -419,6 +470,20 @@
             "polyfill",
             "portable",
             "shim"
+        ],
+        "funding": [
+            {
+                "url": "https://symfony.com/sponsor",
+                "type": "custom"
+            },
+            {
+                "url": "https://github.com/fabpot",
+                "type": "github"
+            },
+            {
+                "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                "type": "tidelift"
+            }
         ]
     }
 ]

+ 1 - 1
user/plugins/email/vendor/doctrine/lexer/LICENSE

@@ -1,4 +1,4 @@
-Copyright (c) 2006-2013 Doctrine Project
+Copyright (c) 2006-2018 Doctrine Project
 
 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

+ 4 - 0
user/plugins/email/vendor/doctrine/lexer/README.md

@@ -1,5 +1,9 @@
 # Doctrine Lexer
 
+Build Status: [![Build Status](https://travis-ci.org/doctrine/lexer.svg?branch=master)](https://travis-ci.org/doctrine/lexer)
+
 Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.
 
 This lexer is used in Doctrine Annotations and in Doctrine ORM (DQL).
+
+https://www.doctrine-project.org/projects/lexer.html

+ 23 - 6
user/plugins/email/vendor/doctrine/lexer/composer.json

@@ -1,9 +1,15 @@
 {
     "name": "doctrine/lexer",
     "type": "library",
-    "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
-    "keywords": ["lexer", "parser"],
-    "homepage": "http://www.doctrine-project.org",
+    "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.",
+    "keywords": [
+        "php",
+        "parser",
+        "lexer",
+        "annotations",
+        "docblock"
+    ],
+    "homepage": "https://www.doctrine-project.org/projects/lexer.html",
     "license": "MIT",
     "authors": [
         {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"},
@@ -11,14 +17,25 @@
         {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"}
     ],
     "require": {
-        "php": ">=5.3.2"
+        "php": "^7.2"
+    },
+    "require-dev": {
+        "doctrine/coding-standard": "^6.0",
+        "phpstan/phpstan": "^0.11.8",
+        "phpunit/phpunit": "^8.2"
     },
     "autoload": {
-        "psr-0": { "Doctrine\\Common\\Lexer\\": "lib/" }
+        "psr-4": { "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" }
+    },
+    "autoload-dev": {
+        "psr-4": { "Doctrine\\Tests\\": "tests/Doctrine" }
     },
     "extra": {
         "branch-alias": {
-            "dev-master": "1.0.x-dev"
+            "dev-master": "1.2.x-dev"
         }
+    },
+    "config": {
+        "sort-packages": true
     }
 }

+ 64 - 63
user/plugins/email/vendor/doctrine/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php

@@ -1,31 +1,21 @@
 <?php
-/*
- * 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.
- *
- * This software consists of voluntary contributions made by many individuals
- * and is licensed under the MIT license. For more information, see
- * <http://www.doctrine-project.org>.
- */
+
+declare(strict_types=1);
 
 namespace Doctrine\Common\Lexer;
 
+use ReflectionClass;
+use const PREG_SPLIT_DELIM_CAPTURE;
+use const PREG_SPLIT_NO_EMPTY;
+use const PREG_SPLIT_OFFSET_CAPTURE;
+use function implode;
+use function in_array;
+use function preg_split;
+use function sprintf;
+use function substr;
+
 /**
  * Base class for writing simple lexers, i.e. for creating small DSLs.
- *
- * @since  2.0
- * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
- * @author Jonathan Wage <jonwage@gmail.com>
- * @author Roman Borschel <roman@code-factory.org>
  */
 abstract class AbstractLexer
 {
@@ -47,36 +37,43 @@ abstract class AbstractLexer
      *
      * @var array
      */
-    private $tokens = array();
+    private $tokens = [];
 
     /**
      * Current lexer position in input string.
      *
-     * @var integer
+     * @var int
      */
     private $position = 0;
 
     /**
      * Current peek of current lexer position.
      *
-     * @var integer
+     * @var int
      */
     private $peek = 0;
 
     /**
      * The next token in the input.
      *
-     * @var array
+     * @var array|null
      */
     public $lookahead;
 
     /**
      * The last matched/seen token.
      *
-     * @var array
+     * @var array|null
      */
     public $token;
 
+    /**
+     * Composed regex for input parsing.
+     *
+     * @var string
+     */
+    private $regex;
+
     /**
      * Sets the input data to be tokenized.
      *
@@ -90,7 +87,7 @@ abstract class AbstractLexer
     public function setInput($input)
     {
         $this->input  = $input;
-        $this->tokens = array();
+        $this->tokens = [];
 
         $this->reset();
         $this->scan($input);
@@ -104,9 +101,9 @@ abstract class AbstractLexer
     public function reset()
     {
         $this->lookahead = null;
-        $this->token = null;
-        $this->peek = 0;
-        $this->position = 0;
+        $this->token     = null;
+        $this->peek      = 0;
+        $this->position  = 0;
     }
 
     /**
@@ -122,7 +119,7 @@ abstract class AbstractLexer
     /**
      * Resets the lexer position on the input to the given position.
      *
-     * @param integer $position Position to place the lexical scanner.
+     * @param int $position Position to place the lexical scanner.
      *
      * @return void
      */
@@ -132,9 +129,9 @@ abstract class AbstractLexer
     }
 
     /**
-     * Retrieve the original lexer's input until a given position. 
+     * Retrieve the original lexer's input until a given position.
      *
-     * @param integer $position
+     * @param int $position
      *
      * @return string
      */
@@ -146,13 +143,13 @@ abstract class AbstractLexer
     /**
      * Checks whether a given token matches the current lookahead.
      *
-     * @param integer|string $token
+     * @param int|string $token
      *
-     * @return boolean
+     * @return bool
      */
     public function isNextToken($token)
     {
-        return null !== $this->lookahead && $this->lookahead['type'] === $token;
+        return $this->lookahead !== null && $this->lookahead['type'] === $token;
     }
 
     /**
@@ -160,23 +157,23 @@ abstract class AbstractLexer
      *
      * @param array $tokens
      *
-     * @return boolean
+     * @return bool
      */
     public function isNextTokenAny(array $tokens)
     {
-        return null !== $this->lookahead && in_array($this->lookahead['type'], $tokens, true);
+        return $this->lookahead !== null && in_array($this->lookahead['type'], $tokens, true);
     }
 
     /**
      * Moves to the next token in the input string.
      *
-     * @return boolean
+     * @return bool
      */
     public function moveNext()
     {
-        $this->peek = 0;
-        $this->token = $this->lookahead;
-        $this->lookahead = (isset($this->tokens[$this->position]))
+        $this->peek      = 0;
+        $this->token     = $this->lookahead;
+        $this->lookahead = isset($this->tokens[$this->position])
             ? $this->tokens[$this->position++] : null;
 
         return $this->lookahead !== null;
@@ -199,10 +196,10 @@ abstract class AbstractLexer
     /**
      * Checks if given value is identical to the given token.
      *
-     * @param mixed   $value
-     * @param integer $token
+     * @param mixed      $value
+     * @param int|string $token
      *
-     * @return boolean
+     * @return bool
      */
     public function isA($value, $token)
     {
@@ -218,9 +215,9 @@ abstract class AbstractLexer
     {
         if (isset($this->tokens[$this->position + $this->peek])) {
             return $this->tokens[$this->position + $this->peek++];
-        } else {
-            return null;
         }
+
+        return null;
     }
 
     /**
@@ -230,8 +227,9 @@ abstract class AbstractLexer
      */
     public function glimpse()
     {
-        $peek = $this->peek();
+        $peek       = $this->peek();
         $this->peek = 0;
+
         return $peek;
     }
 
@@ -244,10 +242,8 @@ abstract class AbstractLexer
      */
     protected function scan($input)
     {
-        static $regex;
-
-        if ( ! isset($regex)) {
-            $regex = sprintf(
+        if (! isset($this->regex)) {
+            $this->regex = sprintf(
                 '/(%s)|%s/%s',
                 implode(')|(', $this->getCatchablePatterns()),
                 implode('|', $this->getNonCatchablePatterns()),
@@ -255,32 +251,37 @@ abstract class AbstractLexer
             );
         }
 
-        $flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE;
-        $matches = preg_split($regex, $input, -1, $flags);
+        $flags   = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE;
+        $matches = preg_split($this->regex, $input, -1, $flags);
+
+        if ($matches === false) {
+            // Work around https://bugs.php.net/78122
+            $matches = [[$input, 0]];
+        }
 
         foreach ($matches as $match) {
             // Must remain before 'value' assignment since it can change content
             $type = $this->getType($match[0]);
 
-            $this->tokens[] = array(
+            $this->tokens[] = [
                 'value' => $match[0],
                 'type'  => $type,
                 'position' => $match[1],
-            );
+            ];
         }
     }
 
     /**
      * Gets the literal for a given token.
      *
-     * @param integer $token
+     * @param int|string $token
      *
-     * @return string
+     * @return int|string
      */
     public function getLiteral($token)
     {
-        $className = get_class($this);
-        $reflClass = new \ReflectionClass($className);
+        $className = static::class;
+        $reflClass = new ReflectionClass($className);
         $constants = $reflClass->getConstants();
 
         foreach ($constants as $name => $value) {
@@ -299,7 +300,7 @@ abstract class AbstractLexer
      */
     protected function getModifiers()
     {
-        return 'i';
+        return 'iu';
     }
 
     /**
@@ -321,7 +322,7 @@ abstract class AbstractLexer
      *
      * @param string $value
      *
-     * @return integer
+     * @return int|string|null
      */
     abstract protected function getType(&$value);
 }

+ 64 - 6
user/plugins/email/vendor/egulias/email-validator/EmailValidator/EmailLexer.php

@@ -73,25 +73,73 @@ class EmailLexer extends AbstractLexer
         '\0'   => self::C_NUL,
     );
 
+    /**
+     * @var bool
+     */
     protected $hasInvalidTokens = false;
 
-    protected $previous;
+    /**
+     * @var array
+     *
+     * @psalm-var array{value:string, type:null|int, position:int}|array<empty, empty>
+     */
+    protected $previous = [];
+
+    /**
+     * The last matched/seen token.
+     *
+     * @var array
+     *
+     * @psalm-var array{value:string, type:null|int, position:int}
+     */
+    public $token;
+
+    /**
+     * The next token in the input.
+     *
+     * @var array|null
+     */
+    public $lookahead;
+
+    /**
+     * @psalm-var array{value:'', type:null, position:0}
+     */
+    private static $nullToken = [
+        'value' => '',
+        'type' => null,
+        'position' => 0,
+    ];
 
+    public function __construct()
+    {
+        $this->previous = $this->token = self::$nullToken;
+        $this->lookahead = null;
+    }
+
+    /**
+     * @return void
+     */
     public function reset()
     {
         $this->hasInvalidTokens = false;
         parent::reset();
+        $this->previous = $this->token = self::$nullToken;
     }
 
+    /**
+     * @return bool
+     */
     public function hasInvalidTokens()
     {
         return $this->hasInvalidTokens;
     }
 
     /**
-     * @param $type
+     * @param int $type
      * @throws \UnexpectedValueException
      * @return boolean
+     *
+     * @psalm-suppress InvalidScalarArgument
      */
     public function find($type)
     {
@@ -107,7 +155,7 @@ class EmailLexer extends AbstractLexer
     /**
      * getPrevious
      *
-     * @return array token
+     * @return array
      */
     public function getPrevious()
     {
@@ -122,8 +170,10 @@ class EmailLexer extends AbstractLexer
     public function moveNext()
     {
         $this->previous = $this->token;
+        $hasNext = parent::moveNext();
+        $this->token = $this->token ?: self::$nullToken;
 
-        return parent::moveNext();
+        return $hasNext;
     }
 
     /**
@@ -179,6 +229,11 @@ class EmailLexer extends AbstractLexer
         return  self::GENERIC;
     }
 
+    /**
+     * @param string $value
+     *
+     * @return bool
+     */
     protected function isValid($value)
     {
         if (isset($this->charValue[$value])) {
@@ -189,7 +244,7 @@ class EmailLexer extends AbstractLexer
     }
 
     /**
-     * @param $value
+     * @param string $value
      * @return bool
      */
     protected function isNullType($value)
@@ -202,7 +257,7 @@ class EmailLexer extends AbstractLexer
     }
 
     /**
-     * @param $value
+     * @param string $value
      * @return bool
      */
     protected function isUTF8Invalid($value)
@@ -214,6 +269,9 @@ class EmailLexer extends AbstractLexer
         return false;
     }
 
+    /**
+     * @return string
+     */
     protected function getModifiers()
     {
         return 'iu';

+ 36 - 3
user/plugins/email/vendor/egulias/email-validator/EmailValidator/EmailParser.php

@@ -17,11 +17,33 @@ class EmailParser
 {
     const EMAIL_MAX_LENGTH = 254;
 
-    protected $warnings;
+    /**
+     * @var array
+     */
+    protected $warnings = [];
+
+    /**
+     * @var string
+     */
     protected $domainPart = '';
+
+    /**
+     * @var string
+     */
     protected $localPart = '';
+    /**
+     * @var EmailLexer
+     */
     protected $lexer;
+
+    /**
+     * @var LocalPart
+     */
     protected $localPartParser;
+
+    /**
+     * @var DomainPart
+     */
     protected $domainPartParser;
 
     public function __construct(EmailLexer $lexer)
@@ -29,11 +51,10 @@ class EmailParser
         $this->lexer = $lexer;
         $this->localPartParser = new LocalPart($this->lexer);
         $this->domainPartParser = new DomainPart($this->lexer);
-        $this->warnings = new \SplObjectStorage();
     }
 
     /**
-     * @param $str
+     * @param string $str
      * @return array
      */
     public function parse($str)
@@ -57,6 +78,9 @@ class EmailParser
         return array('local' => $this->localPart, 'domain' => $this->domainPart);
     }
 
+    /**
+     * @return Warning\Warning[]
+     */
     public function getWarnings()
     {
         $localPartWarnings = $this->localPartParser->getWarnings();
@@ -68,11 +92,17 @@ class EmailParser
         return $this->warnings;
     }
 
+    /**
+     * @return string
+     */
     public function getParsedDomainPart()
     {
         return $this->domainPart;
     }
 
+    /**
+     * @param string $email
+     */
     protected function setParts($email)
     {
         $parts = explode('@', $email);
@@ -80,6 +110,9 @@ class EmailParser
         $this->localPart = $parts[0];
     }
 
+    /**
+     * @return bool
+     */
     protected function hasAtToken()
     {
         $this->lexer->moveNext();

+ 5 - 5
user/plugins/email/vendor/egulias/email-validator/EmailValidator/EmailValidator.php

@@ -13,12 +13,12 @@ class EmailValidator
     private $lexer;
 
     /**
-     * @var array
+     * @var Warning\Warning[]
      */
-    protected $warnings;
+    protected $warnings = [];
 
     /**
-     * @var InvalidEmail
+     * @var InvalidEmail|null
      */
     protected $error;
 
@@ -28,7 +28,7 @@ class EmailValidator
     }
 
     /**
-     * @param                 $email
+     * @param string          $email
      * @param EmailValidation $emailValidation
      * @return bool
      */
@@ -58,7 +58,7 @@ class EmailValidator
     }
 
     /**
-     * @return InvalidEmail
+     * @return InvalidEmail|null
      */
     public function getError()
     {

+ 1 - 1
user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/ExpectingQPair.php

@@ -2,7 +2,7 @@
 
 namespace Egulias\EmailValidator\Exception;
 
-class ExpectedQPair extends InvalidEmail
+class ExpectingQPair extends InvalidEmail
 {
     const CODE = 136;
     const REASON = "Expecting QPAIR";

+ 0 - 2
user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/NoDNSRecord.php

@@ -2,8 +2,6 @@
 
 namespace Egulias\EmailValidator\Exception;
 
-use Egulias\EmailValidator\Exception\InvalidEmail;
-
 class NoDNSRecord extends InvalidEmail
 {
     const CODE = 5;

+ 66 - 20
user/plugins/email/vendor/egulias/email-validator/EmailValidator/Parser/DomainPart.php

@@ -35,27 +35,17 @@ use Egulias\EmailValidator\Warning\TLD;
 class DomainPart extends Parser
 {
     const DOMAIN_MAX_LENGTH = 254;
+
+    /**
+     * @var string
+     */
     protected $domainPart = '';
 
     public function parse($domainPart)
     {
         $this->lexer->moveNext();
 
-        if ($this->lexer->token['type'] === EmailLexer::S_DOT) {
-            throw new DotAtStart();
-        }
-
-        if ($this->lexer->token['type'] === EmailLexer::S_EMPTY) {
-            throw new NoDomainPart();
-        }
-        if ($this->lexer->token['type'] === EmailLexer::S_HYPHEN) {
-            throw new DomainHyphened();
-        }
-
-        if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
-            $this->warnings[DeprecatedComment::CODE] = new DeprecatedComment();
-            $this->parseDomainComments();
-        }
+        $this->performDomainStartChecks();
 
         $domain = $this->doParseDomainPart();
 
@@ -77,11 +67,50 @@ class DomainPart extends Parser
         $this->domainPart = $domain;
     }
 
+    private function performDomainStartChecks()
+    {
+        $this->checkInvalidTokensAfterAT();
+        $this->checkEmptyDomain();
+
+        if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
+            $this->warnings[DeprecatedComment::CODE] = new DeprecatedComment();
+            $this->parseDomainComments();
+        }
+    }
+
+    private function checkEmptyDomain()
+    {
+        $thereIsNoDomain = $this->lexer->token['type'] === EmailLexer::S_EMPTY ||
+            ($this->lexer->token['type'] === EmailLexer::S_SP &&
+            !$this->lexer->isNextToken(EmailLexer::GENERIC));
+
+        if ($thereIsNoDomain) {
+            throw new NoDomainPart();
+        }
+    }
+
+    private function checkInvalidTokensAfterAT()
+    {
+        if ($this->lexer->token['type'] === EmailLexer::S_DOT) {
+            throw new DotAtStart();
+        }
+        if ($this->lexer->token['type'] === EmailLexer::S_HYPHEN) {
+            throw new DomainHyphened();
+        }
+    }
+
+    /**
+     * @return string
+     */
     public function getDomainPart()
     {
         return $this->domainPart;
     }
 
+    /**
+     * @param string $addressLiteral
+     * @param int $maxGroups
+     */
     public function checkIPV6Tag($addressLiteral, $maxGroups = 8)
     {
         $prev = $this->lexer->getPrevious();
@@ -125,6 +154,9 @@ class DomainPart extends Parser
         }
     }
 
+    /**
+     * @return string
+     */
     protected function doParseDomainPart()
     {
         $domain = '';
@@ -166,12 +198,12 @@ class DomainPart extends Parser
 
             $domain .= $this->lexer->token['value'];
             $this->lexer->moveNext();
-        } while ($this->lexer->token);
+        } while (null !== $this->lexer->token['type']);
 
         return $domain;
     }
 
-    private function checkNotAllowedChars($token)
+    private function checkNotAllowedChars(array $token)
     {
         $notAllowed = [EmailLexer::S_BACKSLASH => true, EmailLexer::S_SLASH=> true];
         if (isset($notAllowed[$token['type']])) {
@@ -179,6 +211,9 @@ class DomainPart extends Parser
         }
     }
 
+    /**
+     * @return string|false
+     */
     protected function parseDomainLiteral()
     {
         if ($this->lexer->isNextToken(EmailLexer::S_COLON)) {
@@ -195,6 +230,9 @@ class DomainPart extends Parser
         return $this->doParseDomainLiteral();
     }
 
+    /**
+     * @return string|false
+     */
     protected function doParseDomainLiteral()
     {
         $IPv6TAG = false;
@@ -262,6 +300,11 @@ class DomainPart extends Parser
         return $addressLiteral;
     }
 
+    /**
+     * @param string $addressLiteral
+     *
+     * @return string|false
+     */
     protected function checkIPV4Tag($addressLiteral)
     {
         $matchesIP  = array();
@@ -279,13 +322,13 @@ class DomainPart extends Parser
                 return false;
             }
             // Convert IPv4 part to IPv6 format for further testing
-            $addressLiteral = substr($addressLiteral, 0, $index) . '0:0';
+            $addressLiteral = substr($addressLiteral, 0, (int) $index) . '0:0';
         }
 
         return $addressLiteral;
     }
 
-    protected function checkDomainPartExceptions($prev)
+    protected function checkDomainPartExceptions(array $prev)
     {
         $invalidDomainTokens = array(
             EmailLexer::S_DQUOTE => true,
@@ -320,6 +363,9 @@ class DomainPart extends Parser
         }
     }
 
+    /**
+     * @return bool
+     */
     protected function hasBrackets()
     {
         if ($this->lexer->token['type'] !== EmailLexer::S_OPENBRACKET) {
@@ -335,7 +381,7 @@ class DomainPart extends Parser
         return true;
     }
 
-    protected function checkLabelLength($prev)
+    protected function checkLabelLength(array $prev)
     {
         if ($this->lexer->token['type'] === EmailLexer::S_DOT &&
             $prev['type'] === EmailLexer::GENERIC &&

+ 16 - 9
user/plugins/email/vendor/egulias/email-validator/EmailValidator/Parser/LocalPart.php

@@ -5,7 +5,6 @@ namespace Egulias\EmailValidator\Parser;
 use Egulias\EmailValidator\Exception\DotAtEnd;
 use Egulias\EmailValidator\Exception\DotAtStart;
 use Egulias\EmailValidator\EmailLexer;
-use Egulias\EmailValidator\EmailValidator;
 use Egulias\EmailValidator\Exception\ExpectingAT;
 use Egulias\EmailValidator\Exception\ExpectingATEXT;
 use Egulias\EmailValidator\Exception\UnclosedQuotedString;
@@ -20,9 +19,10 @@ class LocalPart extends Parser
         $parseDQuote = true;
         $closingQuote = false;
         $openedParenthesis = 0;
+        $totalLength = 0;
 
-        while ($this->lexer->token['type'] !== EmailLexer::S_AT && $this->lexer->token) {
-            if ($this->lexer->token['type'] === EmailLexer::S_DOT && !$this->lexer->getPrevious()) {
+        while ($this->lexer->token['type'] !== EmailLexer::S_AT && null !== $this->lexer->token['type']) {
+            if ($this->lexer->token['type'] === EmailLexer::S_DOT && null === $this->lexer->getPrevious()['type']) {
                 throw new DotAtStart();
             }
 
@@ -35,12 +35,13 @@ class LocalPart extends Parser
                 $this->parseComments();
                 $openedParenthesis += $this->getOpenedParenthesis();
             }
+
             if ($this->lexer->token['type'] === EmailLexer::S_CLOSEPARENTHESIS) {
                 if ($openedParenthesis === 0) {
                     throw new UnopenedComment();
-                } else {
-                    $openedParenthesis--;
                 }
+
+                $openedParenthesis--;
             }
 
             $this->checkConsecutiveDots();
@@ -58,15 +59,18 @@ class LocalPart extends Parser
                 $this->parseFWS();
             }
 
+            $totalLength += strlen($this->lexer->token['value']);
             $this->lexer->moveNext();
         }
 
-        $prev = $this->lexer->getPrevious();
-        if (strlen($prev['value']) > LocalTooLong::LOCAL_PART_LENGTH) {
+        if ($totalLength > LocalTooLong::LOCAL_PART_LENGTH) {
             $this->warnings[LocalTooLong::CODE] = new LocalTooLong();
         }
     }
 
+    /**
+     * @return bool
+     */
     protected function parseDoubleQuote()
     {
         $parseAgain = true;
@@ -86,7 +90,7 @@ class LocalPart extends Parser
 
         $this->lexer->moveNext();
 
-        while ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE && $this->lexer->token) {
+        while ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE && null !== $this->lexer->token['type']) {
             $parseAgain = false;
             if (isset($special[$this->lexer->token['type']]) && $setSpecialsWarning) {
                 $this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS();
@@ -118,7 +122,10 @@ class LocalPart extends Parser
         return $parseAgain;
     }
 
-    protected function isInvalidToken($token, $closingQuote)
+    /**
+     * @param bool $closingQuote
+     */
+    protected function isInvalidToken(array $token, $closingQuote)
     {
         $forbidden = array(
             EmailLexer::S_COMMA,

+ 37 - 3
user/plugins/email/vendor/egulias/email-validator/EmailValidator/Parser/Parser.php

@@ -8,7 +8,7 @@ use Egulias\EmailValidator\Exception\ConsecutiveDot;
 use Egulias\EmailValidator\Exception\CRLFAtTheEnd;
 use Egulias\EmailValidator\Exception\CRLFX2;
 use Egulias\EmailValidator\Exception\CRNoLF;
-use Egulias\EmailValidator\Exception\ExpectedQPair;
+use Egulias\EmailValidator\Exception\ExpectingQPair;
 use Egulias\EmailValidator\Exception\ExpectingATEXT;
 use Egulias\EmailValidator\Exception\ExpectingCTEXT;
 use Egulias\EmailValidator\Exception\UnclosedComment;
@@ -21,8 +21,19 @@ use Egulias\EmailValidator\Warning\QuotedString;
 
 abstract class Parser
 {
+    /**
+     * @var \Egulias\EmailValidator\Warning\Warning[]
+     */
     protected $warnings = [];
+
+    /**
+     * @var EmailLexer
+     */
     protected $lexer;
+
+    /**
+     * @var int
+     */
     protected $openedParenthesis = 0;
 
     public function __construct(EmailLexer $lexer)
@@ -30,11 +41,17 @@ abstract class Parser
         $this->lexer = $lexer;
     }
 
+    /**
+     * @return \Egulias\EmailValidator\Warning\Warning[]
+     */
     public function getWarnings()
     {
         return $this->warnings;
     }
 
+    /**
+     * @param string $str
+     */
     abstract public function parse($str);
 
     /** @return int */
@@ -50,7 +67,7 @@ abstract class Parser
     {
         if (!($this->lexer->token['type'] === EmailLexer::INVALID
             || $this->lexer->token['type'] === EmailLexer::C_DEL)) {
-            throw new ExpectedQPair();
+            throw new ExpectingQPair();
         }
 
         $this->warnings[QuotedPart::CODE] =
@@ -80,6 +97,9 @@ abstract class Parser
         }
     }
 
+    /**
+     * @return bool
+     */
     protected function isUnclosedComment()
     {
         try {
@@ -122,6 +142,9 @@ abstract class Parser
         }
     }
 
+    /**
+     * @return bool
+     */
     protected function isFWS()
     {
         if ($this->escaped()) {
@@ -140,11 +163,14 @@ abstract class Parser
         return false;
     }
 
+    /**
+     * @return bool
+     */
     protected function escaped()
     {
         $previous = $this->lexer->getPrevious();
 
-        if ($previous['type'] === EmailLexer::S_BACKSLASH
+        if ($previous && $previous['type'] === EmailLexer::S_BACKSLASH
             &&
             $this->lexer->token['type'] !== EmailLexer::GENERIC
         ) {
@@ -154,6 +180,9 @@ abstract class Parser
         return false;
     }
 
+    /**
+     * @return bool
+     */
     protected function warnEscaping()
     {
         if ($this->lexer->token['type'] !== EmailLexer::S_BACKSLASH) {
@@ -174,6 +203,11 @@ abstract class Parser
 
     }
 
+    /**
+     * @param bool $hasClosingQuote
+     *
+     * @return bool
+     */
     protected function checkDQUOTE($hasClosingQuote)
     {
         if ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE) {

+ 8 - 3
user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/DNSCheckValidation.php

@@ -15,13 +15,13 @@ class DNSCheckValidation implements EmailValidation
     private $warnings = [];
 
     /**
-     * @var InvalidEmail
+     * @var InvalidEmail|null
      */
     private $error;
-    
+
     public function __construct()
     {
-        if (!extension_loaded('intl')) {
+        if (!function_exists('idn_to_ascii')) {
             throw new \LogicException(sprintf('The %s class requires the Intl extension.', __CLASS__));
         }
     }
@@ -49,6 +49,11 @@ class DNSCheckValidation implements EmailValidation
         return $this->warnings;
     }
 
+    /**
+     * @param string $host
+     *
+     * @return bool
+     */
     protected function checkDNS($host)
     {
         $variant = INTL_IDNA_VARIANT_2003;

+ 3 - 0
user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/Exception/EmptyValidationList.php

@@ -6,6 +6,9 @@ use Exception;
 
 class EmptyValidationList extends \InvalidArgumentException
 {
+    /**
+    * @param int $code
+    */
     public function __construct($code = 0, Exception $previous = null)
     {
         parent::__construct("Empty validation list is not allowed", $code, $previous);

+ 7 - 1
user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/MultipleErrors.php

@@ -9,16 +9,22 @@ class MultipleErrors extends InvalidEmail
     const CODE = 999;
     const REASON = "Accumulated errors for multiple validations";
     /**
-     * @var array
+     * @var InvalidEmail[]
      */
     private $errors = [];
 
+    /**
+     * @param InvalidEmail[] $errors
+     */
     public function __construct(array $errors)
     {
         $this->errors = $errors;
         parent::__construct();
     }
 
+    /**
+     * @return InvalidEmail[]
+     */
     public function getErrors()
     {
         return $this->errors;

+ 16 - 3
user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/MultipleValidationWithAnd.php

@@ -30,12 +30,12 @@ class MultipleValidationWithAnd implements EmailValidation
     private $warnings = [];
 
     /**
-     * @var MultipleErrors
+     * @var MultipleErrors|null
      */
     private $error;
 
     /**
-     * @var bool
+     * @var int
      */
     private $mode;
 
@@ -79,6 +79,12 @@ class MultipleValidationWithAnd implements EmailValidation
         return $result;
     }
 
+    /**
+     * @param \Egulias\EmailValidator\Exception\InvalidEmail|null $possibleError
+     * @param \Egulias\EmailValidator\Exception\InvalidEmail[] $errors
+     *
+     * @return \Egulias\EmailValidator\Exception\InvalidEmail[]
+     */
     private function addNewError($possibleError, array $errors)
     {
         if (null !== $possibleError) {
@@ -88,13 +94,20 @@ class MultipleValidationWithAnd implements EmailValidation
         return $errors;
     }
 
+    /**
+     * @param bool $result
+     *
+     * @return bool
+     */
     private function shouldStop($result)
     {
         return !$result && $this->mode === self::STOP_ON_ERROR;
     }
 
     /**
-     * {@inheritdoc}
+     * Returns the validation errors.
+     *
+     * @return MultipleErrors|null
      */
     public function getError()
     {

+ 1 - 1
user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/NoRFCWarningsValidation.php

@@ -9,7 +9,7 @@ use Egulias\EmailValidator\Validation\Error\RFCWarnings;
 class NoRFCWarningsValidation extends RFCValidation
 {
     /**
-     * @var InvalidEmail
+     * @var InvalidEmail|null
      */
     private $error;
 

+ 2 - 2
user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/RFCValidation.php

@@ -9,7 +9,7 @@ use Egulias\EmailValidator\Exception\InvalidEmail;
 class RFCValidation implements EmailValidation
 {
     /**
-     * @var EmailParser
+     * @var EmailParser|null
      */
     private $parser;
 
@@ -19,7 +19,7 @@ class RFCValidation implements EmailValidation
     private $warnings = [];
 
     /**
-     * @var InvalidEmail
+     * @var InvalidEmail|null
      */
     private $error;
 

+ 7 - 1
user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/SpoofCheckValidation.php

@@ -10,7 +10,7 @@ use \Spoofchecker;
 class SpoofCheckValidation implements EmailValidation
 {
     /**
-     * @var InvalidEmail
+     * @var InvalidEmail|null
      */
     private $error;
 
@@ -21,6 +21,9 @@ class SpoofCheckValidation implements EmailValidation
         }
     }
 
+    /**
+     * @psalm-suppress InvalidArgument
+     */
     public function isValid($email, EmailLexer $emailLexer)
     {
         $checker = new Spoofchecker();
@@ -33,6 +36,9 @@ class SpoofCheckValidation implements EmailValidation
         return $this->error === null;
     }
 
+    /**
+     * @return InvalidEmail|null
+     */
     public function getError()
     {
         return $this->error;

+ 4 - 0
user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/QuotedPart.php

@@ -6,6 +6,10 @@ class QuotedPart extends Warning
 {
     const CODE = 36;
 
+    /**
+     * @param scalar $prevToken
+     * @param scalar $postToken
+     */
     public function __construct($prevToken, $postToken)
     {
         $this->message = "Deprecated Quoted String found between $prevToken and $postToken";

+ 4 - 0
user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/QuotedString.php

@@ -6,6 +6,10 @@ class QuotedString extends Warning
 {
     const CODE = 11;
 
+    /**
+     * @param scalar $prevToken
+     * @param scalar $postToken
+     */
     public function __construct($prevToken, $postToken)
     {
         $this->message = "Quoted String found between $prevToken and $postToken";

+ 19 - 2
user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/Warning.php

@@ -5,19 +5,36 @@ namespace Egulias\EmailValidator\Warning;
 abstract class Warning
 {
     const CODE = 0;
-    protected $message;
-    protected $rfcNumber;
 
+    /**
+     * @var string
+     */
+    protected $message = '';
+
+    /**
+     * @var int
+     */
+    protected $rfcNumber = 0;
+
+    /**
+     * @return string
+     */
     public function message()
     {
         return $this->message;
     }
 
+    /**
+     * @return int
+     */
     public function code()
     {
         return self::CODE;
     }
 
+    /**
+     * @return int
+     */
     public function RFCNumber()
     {
         return $this->rfcNumber;

File diff suppressed because it is too large
+ 0 - 0
user/plugins/email/vendor/egulias/email-validator/README.md


+ 9 - 15
user/plugins/email/vendor/egulias/email-validator/composer.json

@@ -2,7 +2,6 @@
   "name":         "egulias/email-validator",
   "description":  "A library for validating emails against several RFCs",
   "homepage":     "https://github.com/egulias/EmailValidator",
-  "type":         "Library",
   "keywords":     ["email", "validation", "validator", "emailvalidation", "emailvalidator"],
   "license":      "MIT",
   "authors": [
@@ -10,23 +9,18 @@
   ],
   "extra": {
     "branch-alias": {
-      "dev-master": "2.0.x-dev"
+      "dev-master": "2.1.x-dev"
     }
   },
-  "repositories": [
-    {
-      "type": "git",
-      "url": "https://github.com/dominicsayers/isemail"
-    }
-  ],
-  "require":      {
-    "php": ">= 5.5",
-    "doctrine/lexer": "^1.0.1"
+  "require": {
+    "php": ">=5.5",
+    "doctrine/lexer": "^1.0.1",
+    "symfony/polyfill-intl-idn": "^1.10"
   },
-  "require-dev" :   {
+  "require-dev": {
     "satooshi/php-coveralls": "^1.0.1",
-    "phpunit/phpunit": "^4.8.35||^5.7||^6.0",
-    "dominicsayers/isemail": "dev-master"
+    "phpunit/phpunit": "^4.8.36|^7.5.15",
+    "dominicsayers/isemail": "^3.0.7"
   },
   "suggest": {
     "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation"
@@ -38,7 +32,7 @@
   },
   "autoload-dev": {
     "psr-4": {
-      "Egulias\\Tests\\": "test"
+      "Egulias\\Tests\\": "Tests"
     }
   }
 }

+ 3 - 4
user/plugins/email/vendor/egulias/email-validator/phpunit.xml.dist

@@ -8,7 +8,6 @@
          convertWarningsToExceptions="true"
          processIsolation="false"
          stopOnFailure="false"
-         syntaxCheck="false"
          bootstrap="vendor/autoload.php"
 >
 <testsuites>
@@ -19,8 +18,8 @@
 </testsuites>
 
 <filter>
-  <blacklist>
-    <directory>./vendor</directory>
-  </blacklist>
+  <whitelist>
+    <directory>./EmailValidator/</directory>
+  </whitelist>
 </filter>
 </phpunit>

+ 19 - 0
user/plugins/email/vendor/egulias/email-validator/psalm.baseline.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<files psalm-version="3.8.3@389af1bfc739bfdff3f9e3dc7bd6499aee51a831">
+  <file src="EmailValidator/EmailLexer.php">
+    <DocblockTypeContradiction occurrences="1">
+      <code>self::$nullToken</code>
+    </DocblockTypeContradiction>
+  </file>
+  <file src="EmailValidator/Parser/Parser.php">
+    <MissingReturnType occurrences="1">
+      <code>parse</code>
+    </MissingReturnType>
+  </file>
+  <file src="EmailValidator/Validation/SpoofCheckValidation.php">
+    <UndefinedClass occurrences="2">
+      <code>Spoofchecker</code>
+      <code>Spoofchecker</code>
+    </UndefinedClass>
+  </file>
+</files>

+ 19 - 0
user/plugins/email/vendor/egulias/email-validator/psalm.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<psalm
+    requireVoidReturnType="false"
+    totallyTyped="false"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns="https://getpsalm.org/schema/config"
+    xsi:schemaLocation="https://getpsalm.org/schema/config ./vendor/vimeo/psalm/config.xsd"
+    errorBaseline="./psalm.baseline.xml"
+>
+    <projectFiles>
+        <directory name="EmailValidator" />
+        <ignoreFiles>
+            <directory name="vendor" />
+        </ignoreFiles>
+    </projectFiles>
+
+    <issueHandlers>
+    </issueHandlers>
+</psalm>

+ 16 - 0
user/plugins/email/vendor/swiftmailer/swiftmailer/CHANGES

@@ -1,6 +1,22 @@
 Changelog
 =========
 
+6.2.2 (2019-11-12)
+------------------
+
+ * no changes
+
+6.2.2 (2019-11-12)
+------------------
+
+ * fixed cmopat with PHP 7.4
+ * fixed error message when connecting to a stream raises an error before connect()
+
+6.2.1 (2019-04-21)
+------------------
+
+ * reverted "deprecated Swift_CharacterStream_ArrayCharacterStream and Swift_CharacterStream_NgCharacterStream in favor of Swift_CharacterStream_CharacterStream"
+
 6.2.0 (2019-03-10)
 ------------------
 

+ 0 - 15
user/plugins/email/vendor/swiftmailer/swiftmailer/README

@@ -1,15 +0,0 @@
-Swift Mailer
-------------
-
-Swift Mailer is a component based mailing solution for PHP 7.
-It is released under the MIT license.
-
-Homepage:      https://swiftmailer.symfony.com/
-Documentation: https://swiftmailer.symfony.com/docs/introduction.html
-Bugs:          https://github.com/swiftmailer/swiftmailer/issues
-Repository:    https://github.com/swiftmailer/swiftmailer
-
-Swift Mailer is highly object-oriented by design and lends itself
-to use in complex web application with a great deal of flexibility.
-
-For full details on usage, see the documentation.

+ 19 - 0
user/plugins/email/vendor/swiftmailer/swiftmailer/README.md

@@ -0,0 +1,19 @@
+Swift Mailer
+------------
+
+Swift Mailer is a component based mailing solution for PHP 7.
+It is released under the MIT license.
+
+Swift Mailer is highly object-oriented by design and lends itself
+to use in complex web application with a great deal of flexibility.
+
+For full details on usage, read the [documentation](https://swiftmailer.symfony.com/docs/introduction.html).
+
+Sponsors
+--------
+
+<div>
+    <a href="https://blackfire.io/docs/introduction?utm_source=swiftmailer&utm_medium=github_readme&utm_campaign=logo">
+        <img src="https://static.blackfire.io/assets/intemporals/logo/png/blackfire-io_secondary_horizontal_transparent.png?1" width="255px" alt="Blackfire.io">
+    </a>
+</div>

+ 6 - 9
user/plugins/email/vendor/swiftmailer/swiftmailer/doc/messages.rst

@@ -520,9 +520,8 @@ Setting ``To:`` Recipients
 or ``addTo()`` methods of the message.
 
 To set ``To:`` recipients, create the message object using either ``new
-Swift_Message( ... )`` or ``new Swift_Message( ... )``, then call the
-``setTo()`` method with a complete array of addresses, or use the ``addTo()``
-method to iteratively add recipients.
+Swift_Message( ... )``, then call the ``setTo()`` method with a complete array
+of addresses, or use the ``addTo()`` method to iteratively add recipients.
 
 The ``setTo()`` method accepts input in various formats as described earlier in
 this chapter. The ``addTo()`` method takes either one or two parameters. The
@@ -558,9 +557,8 @@ Setting ``Cc:`` Recipients
 message.
 
 To set ``Cc:`` recipients, create the message object using either ``new
-Swift_Message( ... )`` or ``new Swift_Message( ... )``, then call the
-``setCc()`` method with a complete array of addresses, or use the ``addCc()``
-method to iteratively add recipients.
+Swift_Message( ... )``, then call the ``setCc()`` method with a complete array
+of addresses, or use the ``addCc()`` method to iteratively add recipients.
 
 The ``setCc()`` method accepts input in various formats as described earlier in
 this chapter. The ``addCc()`` method takes either one or two parameters. The
@@ -596,9 +594,8 @@ Setting ``Bcc:`` Recipients
 it, and are set with the ``setBcc()`` or ``addBcc()`` methods of the message.
 
 To set ``Bcc:`` recipients, create the message object using either ``new
-Swift_Message( ... )`` or ``new Swift_Message( ... )``, then call the
-``setBcc()`` method with a complete array of addresses, or use the ``addBcc()``
-method to iteratively add recipients.
+Swift_Message( ... )``, then call the ``setBcc()`` method with a complete array
+of addresses, or use the ``addBcc()`` method to iteratively add recipients.
 
 The ``setBcc()`` method accepts input in various formats as described earlier
 in this chapter. The ``addBcc()`` method takes either one or two parameters.

+ 1 - 1
user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift.php

@@ -15,7 +15,7 @@
  */
 abstract class Swift
 {
-    const VERSION = '6.2.0';
+    const VERSION = '6.2.3';
 
     public static $initialized = false;
     public static $inits = [];

+ 0 - 2
user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream/ArrayCharacterStream.php

@@ -8,8 +8,6 @@
  * file that was distributed with this source code.
  */
 
-@trigger_error(sprintf('The "%s" class is deprecated since Swiftmailer 6.2; use "%s" instead.', Swift_CharacterStream_ArrayCharacterStream::class, Swift_CharacterStream_CharacterStream::class), E_USER_DEPRECATED);
-
 /**
  * A CharacterStream implementation which stores characters in an internal array.
  *

+ 0 - 227
user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream/CharacterStream.php

@@ -1,227 +0,0 @@
-<?php
-
-/*
- * This file is part of SwiftMailer.
- * (c) 2004-2009 Chris Corbyn
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * A CharacterStream implementation which stores characters in an internal array.
- *
- * @author     Xavier De Cock <xdecock@gmail.com>
- */
-class Swift_CharacterStream_CharacterStream implements Swift_CharacterStream
-{
-    /**
-     * The char reader (lazy-loaded) for the current charset.
-     *
-     * @var Swift_CharacterReader
-     */
-    private $charReader;
-
-    /**
-     * A factory for creating CharacterReader instances.
-     *
-     * @var Swift_CharacterReaderFactory
-     */
-    private $charReaderFactory;
-
-    /**
-     * The character set this stream is using.
-     *
-     * @var string
-     */
-    private $charset;
-
-    /**
-     * The data's stored as-is.
-     *
-     * @var string
-     */
-    private $datas = '';
-
-    /**
-     * Number of bytes in the stream.
-     *
-     * @var int
-     */
-    private $datasSize = 0;
-
-    /**
-     * Map.
-     *
-     * @var mixed
-     */
-    private $map;
-
-    /**
-     * Map Type.
-     *
-     * @var int
-     */
-    private $mapType = 0;
-
-    /**
-     * Number of characters in the stream.
-     *
-     * @var int
-     */
-    private $charCount = 0;
-
-    /**
-     * Position in the stream.
-     *
-     * @var int
-     */
-    private $currentPos = 0;
-
-    /**
-     * Constructor.
-     *
-     * @param string $charset
-     */
-    public function __construct(Swift_CharacterReaderFactory $factory, $charset)
-    {
-        $this->setCharacterReaderFactory($factory);
-        $this->setCharacterSet($charset);
-    }
-
-    /* -- Changing parameters of the stream -- */
-
-    /**
-     * Set the character set used in this CharacterStream.
-     *
-     * @param string $charset
-     */
-    public function setCharacterSet($charset)
-    {
-        $this->charset = $charset;
-        $this->charReader = null;
-        $this->mapType = 0;
-    }
-
-    /**
-     * Set the CharacterReaderFactory for multi charset support.
-     */
-    public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory)
-    {
-        $this->charReaderFactory = $factory;
-    }
-
-    public function flushContents()
-    {
-        $this->datas = null;
-        $this->map = null;
-        $this->charCount = 0;
-        $this->currentPos = 0;
-        $this->datasSize = 0;
-    }
-
-    public function importByteStream(Swift_OutputByteStream $os)
-    {
-        $this->flushContents();
-        $blocks = 512;
-        $os->setReadPointer(0);
-        while (false !== ($read = $os->read($blocks))) {
-            $this->write($read);
-        }
-    }
-
-    public function importString($string)
-    {
-        $this->flushContents();
-        $this->write($string);
-    }
-
-    public function read($length)
-    {
-        if ($this->currentPos >= $this->charCount) {
-            return false;
-        }
-        $ret = false;
-        $length = ($this->currentPos + $length > $this->charCount) ? $this->charCount - $this->currentPos : $length;
-        switch ($this->mapType) {
-            case Swift_CharacterReader::MAP_TYPE_FIXED_LEN:
-                $len = $length * $this->map;
-                $ret = substr($this->datas,
-                        $this->currentPos * $this->map,
-                        $len);
-                $this->currentPos += $length;
-                break;
-
-            case Swift_CharacterReader::MAP_TYPE_INVALID:
-                $ret = '';
-                for (; $this->currentPos < $length; ++$this->currentPos) {
-                    if (isset($this->map[$this->currentPos])) {
-                        $ret .= '?';
-                    } else {
-                        $ret .= $this->datas[$this->currentPos];
-                    }
-                }
-                break;
-
-            case Swift_CharacterReader::MAP_TYPE_POSITIONS:
-                $end = $this->currentPos + $length;
-                $end = $end > $this->charCount ? $this->charCount : $end;
-                $ret = '';
-                $start = 0;
-                if ($this->currentPos > 0) {
-                    $start = $this->map['p'][$this->currentPos - 1];
-                }
-                $to = $start;
-                for (; $this->currentPos < $end; ++$this->currentPos) {
-                    if (isset($this->map['i'][$this->currentPos])) {
-                        $ret .= substr($this->datas, $start, $to - $start).'?';
-                        $start = $this->map['p'][$this->currentPos];
-                    } else {
-                        $to = $this->map['p'][$this->currentPos];
-                    }
-                }
-                $ret .= substr($this->datas, $start, $to - $start);
-                break;
-        }
-
-        return $ret;
-    }
-
-    public function readBytes($length)
-    {
-        $read = $this->read($length);
-        if (false !== $read) {
-            $ret = array_map('ord', str_split($read, 1));
-
-            return $ret;
-        }
-
-        return false;
-    }
-
-    public function setPointer($charOffset)
-    {
-        if ($this->charCount < $charOffset) {
-            $charOffset = $this->charCount;
-        }
-        $this->currentPos = $charOffset;
-    }
-
-    public function write($chars)
-    {
-        if (!isset($this->charReader)) {
-            $this->charReader = $this->charReaderFactory->getReaderFor(
-                $this->charset);
-            $this->map = [];
-            $this->mapType = $this->charReader->getMapType();
-        }
-        $ignored = '';
-        $this->datas .= $chars;
-        $this->charCount += $this->charReader->getCharPositions(substr($this->datas, $this->datasSize), $this->datasSize, $this->map, $ignored);
-        if (false !== $ignored) {
-            $this->datasSize = strlen($this->datas) - strlen($ignored);
-        } else {
-            $this->datasSize = strlen($this->datas);
-        }
-    }
-}

+ 245 - 3
user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream/NgCharacterStream.php

@@ -8,13 +8,255 @@
  * file that was distributed with this source code.
  */
 
-@trigger_error(sprintf('The "%s" class is deprecated since Swiftmailer 6.2; use "%s" instead.', Swift_CharacterStream_NgCharacterStream::class, Swift_CharacterStream_CharacterStream::class), E_USER_DEPRECATED);
-
 /**
  * A CharacterStream implementation which stores characters in an internal array.
  *
  * @author     Xavier De Cock <xdecock@gmail.com>
  */
-class Swift_CharacterStream_NgCharacterStream extends Swift_CharacterStream_CharacterStream
+class Swift_CharacterStream_NgCharacterStream implements Swift_CharacterStream
 {
+    /**
+     * The char reader (lazy-loaded) for the current charset.
+     *
+     * @var Swift_CharacterReader
+     */
+    private $charReader;
+
+    /**
+     * A factory for creating CharacterReader instances.
+     *
+     * @var Swift_CharacterReaderFactory
+     */
+    private $charReaderFactory;
+
+    /**
+     * The character set this stream is using.
+     *
+     * @var string
+     */
+    private $charset;
+
+    /**
+     * The data's stored as-is.
+     *
+     * @var string
+     */
+    private $datas = '';
+
+    /**
+     * Number of bytes in the stream.
+     *
+     * @var int
+     */
+    private $datasSize = 0;
+
+    /**
+     * Map.
+     *
+     * @var mixed
+     */
+    private $map;
+
+    /**
+     * Map Type.
+     *
+     * @var int
+     */
+    private $mapType = 0;
+
+    /**
+     * Number of characters in the stream.
+     *
+     * @var int
+     */
+    private $charCount = 0;
+
+    /**
+     * Position in the stream.
+     *
+     * @var int
+     */
+    private $currentPos = 0;
+
+    /**
+     * Constructor.
+     *
+     * @param string $charset
+     */
+    public function __construct(Swift_CharacterReaderFactory $factory, $charset)
+    {
+        $this->setCharacterReaderFactory($factory);
+        $this->setCharacterSet($charset);
+    }
+
+    /* -- Changing parameters of the stream -- */
+
+    /**
+     * Set the character set used in this CharacterStream.
+     *
+     * @param string $charset
+     */
+    public function setCharacterSet($charset)
+    {
+        $this->charset = $charset;
+        $this->charReader = null;
+        $this->mapType = 0;
+    }
+
+    /**
+     * Set the CharacterReaderFactory for multi charset support.
+     */
+    public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory)
+    {
+        $this->charReaderFactory = $factory;
+    }
+
+    /**
+     * @see Swift_CharacterStream::flushContents()
+     */
+    public function flushContents()
+    {
+        $this->datas = null;
+        $this->map = null;
+        $this->charCount = 0;
+        $this->currentPos = 0;
+        $this->datasSize = 0;
+    }
+
+    /**
+     * @see Swift_CharacterStream::importByteStream()
+     */
+    public function importByteStream(Swift_OutputByteStream $os)
+    {
+        $this->flushContents();
+        $blocks = 512;
+        $os->setReadPointer(0);
+        while (false !== ($read = $os->read($blocks))) {
+            $this->write($read);
+        }
+    }
+
+    /**
+     * @see Swift_CharacterStream::importString()
+     *
+     * @param string $string
+     */
+    public function importString($string)
+    {
+        $this->flushContents();
+        $this->write($string);
+    }
+
+    /**
+     * @see Swift_CharacterStream::read()
+     *
+     * @param int $length
+     *
+     * @return string
+     */
+    public function read($length)
+    {
+        if ($this->currentPos >= $this->charCount) {
+            return false;
+        }
+        $ret = false;
+        $length = ($this->currentPos + $length > $this->charCount) ? $this->charCount - $this->currentPos : $length;
+        switch ($this->mapType) {
+            case Swift_CharacterReader::MAP_TYPE_FIXED_LEN:
+                $len = $length * $this->map;
+                $ret = substr($this->datas,
+                        $this->currentPos * $this->map,
+                        $len);
+                $this->currentPos += $length;
+                break;
+
+            case Swift_CharacterReader::MAP_TYPE_INVALID:
+                $ret = '';
+                for (; $this->currentPos < $length; ++$this->currentPos) {
+                    if (isset($this->map[$this->currentPos])) {
+                        $ret .= '?';
+                    } else {
+                        $ret .= $this->datas[$this->currentPos];
+                    }
+                }
+                break;
+
+            case Swift_CharacterReader::MAP_TYPE_POSITIONS:
+                $end = $this->currentPos + $length;
+                $end = $end > $this->charCount ? $this->charCount : $end;
+                $ret = '';
+                $start = 0;
+                if ($this->currentPos > 0) {
+                    $start = $this->map['p'][$this->currentPos - 1];
+                }
+                $to = $start;
+                for (; $this->currentPos < $end; ++$this->currentPos) {
+                    if (isset($this->map['i'][$this->currentPos])) {
+                        $ret .= substr($this->datas, $start, $to - $start).'?';
+                        $start = $this->map['p'][$this->currentPos];
+                    } else {
+                        $to = $this->map['p'][$this->currentPos];
+                    }
+                }
+                $ret .= substr($this->datas, $start, $to - $start);
+                break;
+        }
+
+        return $ret;
+    }
+
+    /**
+     * @see Swift_CharacterStream::readBytes()
+     *
+     * @param int $length
+     *
+     * @return int[]
+     */
+    public function readBytes($length)
+    {
+        $read = $this->read($length);
+        if (false !== $read) {
+            $ret = array_map('ord', str_split($read, 1));
+
+            return $ret;
+        }
+
+        return false;
+    }
+
+    /**
+     * @see Swift_CharacterStream::setPointer()
+     *
+     * @param int $charOffset
+     */
+    public function setPointer($charOffset)
+    {
+        if ($this->charCount < $charOffset) {
+            $charOffset = $this->charCount;
+        }
+        $this->currentPos = $charOffset;
+    }
+
+    /**
+     * @see Swift_CharacterStream::write()
+     *
+     * @param string $chars
+     */
+    public function write($chars)
+    {
+        if (!isset($this->charReader)) {
+            $this->charReader = $this->charReaderFactory->getReaderFor(
+                $this->charset);
+            $this->map = [];
+            $this->mapType = $this->charReader->getMapType();
+        }
+        $ignored = '';
+        $this->datas .= $chars;
+        $this->charCount += $this->charReader->getCharPositions(substr($this->datas, $this->datasSize), $this->datasSize, $this->map, $ignored);
+        if (false !== $ignored) {
+            $this->datasSize = strlen($this->datas) - strlen($ignored);
+        } else {
+            $this->datasSize = strlen($this->datas);
+        }
+    }
 }

+ 9 - 6
user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php

@@ -264,13 +264,16 @@ class Swift_Transport_StreamBuffer extends Swift_ByteStream_AbstractFilterableIn
             $options = array_merge($options, $this->params['stream_context_options']);
         }
         $streamContext = stream_context_create($options);
-        $this->stream = @stream_socket_client($host.':'.$this->params['port'], $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $streamContext);
-        if (false === $this->stream) {
-            throw new Swift_TransportException(
-                'Connection could not be established with host '.$this->params['host'].
-                ' ['.$errstr.' #'.$errno.']'
-                );
+
+        set_error_handler(function ($type, $msg) {
+            throw new Swift_TransportException('Connection could not be established with host '.$this->params['host'].' :'.$msg);
+        });
+        try {
+            $this->stream = stream_socket_client($host.':'.$this->params['port'], $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $streamContext);
+        } finally {
+            restore_error_handler();
         }
+
         if (!empty($this->params['blocking'])) {
             stream_set_blocking($this->stream, 1);
         } else {

+ 1 - 1
user/plugins/email/vendor/swiftmailer/swiftmailer/lib/dependency_maps/mime_deps.php

@@ -84,7 +84,7 @@ Swift_DependencyContainer::getInstance()
     ->withDependencies(['mime.charstream'])
 
     ->register('mime.charstream')
-    ->asNewInstanceOf('Swift_CharacterStream_CharacterStream')
+    ->asNewInstanceOf('Swift_CharacterStream_NgCharacterStream')
     ->withDependencies(['mime.characterreaderfactory', 'properties.charset'])
 
     ->register('mime.bytecanonicalizer')

+ 1 - 1
user/plugins/email/vendor/swiftmailer/swiftmailer/lib/swiftmailer_generate_mimes_config.php

@@ -173,7 +173,7 @@ function generateUpToDateMimeArray()
     ksort($valid_mime_types);
 
     // combine mime types and extensions array
-    $output = "$preamble\$swift_mime_types = array(\n    ".implode($valid_mime_types, ",\n    ")."\n);";
+    $output = "$preamble\$swift_mime_types = array(\n    ".implode(",\n    ", $valid_mime_types)."\n);";
 
     // write mime_types.php config file
     @file_put_contents('./mime_types.php', $output);

+ 1 - 1
user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Encoder/QpEncoderAcceptanceTest.php

@@ -20,7 +20,7 @@ class Swift_Encoder_QpEncoderAcceptanceTest extends \PHPUnit\Framework\TestCase
             }
 
             $encoding = $encodingDir;
-            $charStream = new Swift_CharacterStream_CharacterStream(
+            $charStream = new Swift_CharacterStream_ArrayCharacterStream(
                 $this->factory, $encoding);
             $encoder = new Swift_Encoder_QpEncoder($charStream);
 

+ 1 - 1
user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Encoder/Rfc2231EncoderAcceptanceTest.php

@@ -20,7 +20,7 @@ class Swift_Encoder_Rfc2231EncoderAcceptanceTest extends \PHPUnit\Framework\Test
             }
 
             $encoding = $encodingDir;
-            $charStream = new Swift_CharacterStream_CharacterStream(
+            $charStream = new Swift_CharacterStream_ArrayCharacterStream(
                 $this->factory, $encoding);
             $encoder = new Swift_Encoder_Rfc2231Encoder($charStream);
 

+ 2 - 2
user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/AttachmentAcceptanceTest.php

@@ -18,10 +18,10 @@ class Swift_Mime_AttachmentAcceptanceTest extends \PHPUnit\Framework\TestCase
         $this->contentEncoder = new Swift_Mime_ContentEncoder_Base64ContentEncoder();
 
         $headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder(
-            new Swift_CharacterStream_CharacterStream($factory, 'utf-8')
+            new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
             );
         $paramEncoder = new Swift_Encoder_Rfc2231Encoder(
-            new Swift_CharacterStream_CharacterStream($factory, 'utf-8')
+            new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
             );
         $this->emailValidator = new EmailValidator();
         $this->idGenerator = new Swift_Mime_IdGenerator('example.com');

+ 1 - 1
user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/ContentEncoder/QpContentEncoderAcceptanceTest.php

@@ -25,7 +25,7 @@ class Swift_Mime_ContentEncoder_QpContentEncoderAcceptanceTest extends \PHPUnit\
             }
 
             $encoding = $encodingDir;
-            $charStream = new Swift_CharacterStream_CharacterStream(
+            $charStream = new Swift_CharacterStream_NgCharacterStream(
                 $this->factory, $encoding);
             $encoder = new Swift_Mime_ContentEncoder_QpContentEncoder($charStream);
 

+ 2 - 2
user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/EmbeddedFileAcceptanceTest.php

@@ -18,10 +18,10 @@ class Swift_Mime_EmbeddedFileAcceptanceTest extends \PHPUnit\Framework\TestCase
         $this->contentEncoder = new Swift_Mime_ContentEncoder_Base64ContentEncoder();
 
         $headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder(
-            new Swift_CharacterStream_CharacterStream($factory, 'utf-8')
+            new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
             );
         $paramEncoder = new Swift_Encoder_Rfc2231Encoder(
-            new Swift_CharacterStream_CharacterStream($factory, 'utf-8')
+            new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
             );
         $this->emailValidator = new EmailValidator();
         $this->idGenerator = new Swift_Mime_IdGenerator('example.com');

+ 3 - 3
user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/MimePartAcceptanceTest.php

@@ -16,7 +16,7 @@ class Swift_Mime_MimePartAcceptanceTest extends \PHPUnit\Framework\TestCase
             );
         $factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
         $this->contentEncoder = new Swift_Mime_ContentEncoder_QpContentEncoder(
-            new Swift_CharacterStream_CharacterStream($factory, 'utf-8'),
+            new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8'),
             new Swift_StreamFilters_ByteArrayReplacementFilter(
                 [[0x0D, 0x0A], [0x0D], [0x0A]],
                 [[0x0A], [0x0A], [0x0D, 0x0A]]
@@ -24,10 +24,10 @@ class Swift_Mime_MimePartAcceptanceTest extends \PHPUnit\Framework\TestCase
             );
 
         $headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder(
-            new Swift_CharacterStream_CharacterStream($factory, 'utf-8')
+            new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
             );
         $paramEncoder = new Swift_Encoder_Rfc2231Encoder(
-            new Swift_CharacterStream_CharacterStream($factory, 'utf-8')
+            new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
             );
         $this->emailValidator = new EmailValidator();
         $this->idGenerator = new Swift_Mime_IdGenerator('example.com');

+ 2 - 2
user/plugins/email/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug206Test.php

@@ -10,10 +10,10 @@ class Swift_Bug206Test extends \PHPUnit\Framework\TestCase
     {
         $factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
         $headerEncoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder(
-            new Swift_CharacterStream_CharacterStream($factory, 'utf-8')
+            new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
         );
         $paramEncoder = new Swift_Encoder_Rfc2231Encoder(
-            new Swift_CharacterStream_CharacterStream($factory, 'utf-8')
+            new Swift_CharacterStream_ArrayCharacterStream($factory, 'utf-8')
         );
         $emailValidator = new EmailValidator();
         $this->factory = new Swift_Mime_SimpleHeaderFactory($headerEncoder, $paramEncoder, $emailValidator);

+ 1 - 1
user/plugins/email/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug650Test.php

@@ -13,7 +13,7 @@ class Swift_Bug650Test extends \PHPUnit\Framework\TestCase
     public function testMailboxHeaderEncoding($name, $expectedEncodedName)
     {
         $factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
-        $charStream = new Swift_CharacterStream_CharacterStream($factory, 'utf-8');
+        $charStream = new Swift_CharacterStream_NgCharacterStream($factory, 'utf-8');
         $encoder = new Swift_Mime_HeaderEncoder_QpHeaderEncoder($charStream);
         $header = new Swift_Mime_Headers_MailboxHeader('To', $encoder, new EmailValidator());
         $header->setCharset('utf-8');

+ 0 - 3
user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/CharacterStream/ArrayCharacterStreamTest.php

@@ -1,8 +1,5 @@
 <?php
 
-/**
- * @group legacy
- */
 class Swift_CharacterStream_ArrayCharacterStreamTest extends \SwiftMailerTestCase
 {
     public function testValidatorAlgorithmOnImportString()

+ 1 - 1
user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Encoder/QpEncoderTest.php

@@ -393,7 +393,7 @@ class Swift_Encoder_QpEncoderTest extends \SwiftMailerTestCase
     private function createEncoder()
     {
         $factory = new Swift_CharacterReaderFactory_SimpleCharacterReaderFactory();
-        $charStream = new Swift_CharacterStream_CharacterStream($factory, 'utf-8');
+        $charStream = new Swift_CharacterStream_NgCharacterStream($factory, 'utf-8');
 
         return new Swift_Encoder_QpEncoder($charStream);
     }

Some files were not shown because too many files changed in this diff