From f28cc01e8245852c9db4cb14e2eb0c2643571b8f Mon Sep 17 00:00:00 2001 From: kevin tessier Date: Sun, 13 Oct 2019 21:45:30 +0200 Subject: [PATCH] add plugins --- .gitignore | 2 - user/plugins/admin/.editorconfig | 17 + user/plugins/admin/.gitattributes | 8 + user/plugins/admin/.github/FUNDING.yml | 8 + user/plugins/admin/.gitignore | 14 + user/plugins/admin/CHANGELOG.md | 1713 ++ user/plugins/admin/CONTRIBUTING.md | 1 + user/plugins/admin/LICENSE | 21 + user/plugins/admin/README.md | 111 + user/plugins/admin/admin.php | 1014 ++ user/plugins/admin/admin.yaml | 47 + user/plugins/admin/assets/admin-dashboard.png | Bin 0 -> 241372 bytes user/plugins/admin/blueprints.yaml | 514 + .../blueprints/admin/pages/modular_new.yaml | 52 + .../blueprints/admin/pages/modular_raw.yaml | 101 + .../admin/blueprints/admin/pages/move.yaml | 7 + .../admin/blueprints/admin/pages/new.yaml | 62 + .../blueprints/admin/pages/new_folder.yaml | 31 + .../admin/blueprints/admin/pages/raw.yaml | 106 + .../admin/blueprints/config/media.yaml | 36 + .../admin/classes/Twig/AdminTwigExtension.php | 118 + user/plugins/admin/classes/admin.php | 1968 +++ .../admin/classes/adminbasecontroller.php | 1122 ++ .../plugins/admin/classes/admincontroller.php | 2394 +++ user/plugins/admin/classes/gpm.php | 430 + user/plugins/admin/classes/popularity.php | 303 + user/plugins/admin/classes/themes.php | 22 + user/plugins/admin/classes/utils.php | 54 + user/plugins/admin/codeception.yml | 18 + user/plugins/admin/composer.json | 51 + user/plugins/admin/composer.lock | 2852 ++++ user/plugins/admin/hebe.json | 15 + user/plugins/admin/languages/ar.yaml | 308 + user/plugins/admin/languages/bg.yaml | 361 + user/plugins/admin/languages/br.yaml | 600 + user/plugins/admin/languages/ca.yaml | 641 + user/plugins/admin/languages/cs.yaml | 819 + user/plugins/admin/languages/cy.yaml | 90 + user/plugins/admin/languages/da.yaml | 737 + user/plugins/admin/languages/de.yaml | 769 + user/plugins/admin/languages/el.yaml | 710 + user/plugins/admin/languages/en.yaml | 827 + user/plugins/admin/languages/es.yaml | 758 + user/plugins/admin/languages/et.yaml | 760 + user/plugins/admin/languages/eu.yaml | 182 + user/plugins/admin/languages/fa.yaml | 731 + user/plugins/admin/languages/fi.yaml | 237 + user/plugins/admin/languages/fr.yaml | 819 + user/plugins/admin/languages/he.yaml | 418 + user/plugins/admin/languages/hr.yaml | 609 + user/plugins/admin/languages/hu.yaml | 756 + user/plugins/admin/languages/id.yaml | 696 + user/plugins/admin/languages/it.yaml | 724 + user/plugins/admin/languages/ja.yaml | 645 + user/plugins/admin/languages/ko.yaml | 108 + user/plugins/admin/languages/lt.yaml | 363 + user/plugins/admin/languages/nl.yaml | 737 + user/plugins/admin/languages/no.yaml | 686 + user/plugins/admin/languages/pl.yaml | 687 + user/plugins/admin/languages/pt.yaml | 550 + user/plugins/admin/languages/ro.yaml | 819 + user/plugins/admin/languages/ru.yaml | 812 + user/plugins/admin/languages/sk.yaml | 555 + user/plugins/admin/languages/sl.yaml | 245 + user/plugins/admin/languages/sr.yaml | 819 + user/plugins/admin/languages/sv.yaml | 632 + user/plugins/admin/languages/th.yaml | 690 + user/plugins/admin/languages/tlh.yaml | 9 + user/plugins/admin/languages/tr.yaml | 717 + user/plugins/admin/languages/uk.yaml | 552 + user/plugins/admin/languages/vi.yaml | 73 + user/plugins/admin/languages/zh-tw.yaml | 706 + user/plugins/admin/languages/zh.yaml | 819 + user/plugins/admin/pages/admin/ajax.md | 7 + user/plugins/admin/pages/admin/backup.md | 8 + user/plugins/admin/pages/admin/cache.md | 9 + user/plugins/admin/pages/admin/config.md | 7 + user/plugins/admin/pages/admin/dashboard.md | 7 + user/plugins/admin/pages/admin/denied.md | 4 + user/plugins/admin/pages/admin/error.md | 9 + user/plugins/admin/pages/admin/feed.md | 7 + user/plugins/admin/pages/admin/forgot.md | 12 + user/plugins/admin/pages/admin/info.md | 7 + user/plugins/admin/pages/admin/installer.md | 7 + user/plugins/admin/pages/admin/login.md | 37 + user/plugins/admin/pages/admin/media.md | 8 + .../admin/pages/admin/notifications.md | 7 + .../plugins/admin/pages/admin/pages-filter.md | 8 + user/plugins/admin/pages/admin/pages.md | 7 + user/plugins/admin/pages/admin/plugins.md | 7 + user/plugins/admin/pages/admin/preview.md | 7 + user/plugins/admin/pages/admin/register.md | 56 + user/plugins/admin/pages/admin/reset.md | 16 + user/plugins/admin/pages/admin/site.md | 7 + user/plugins/admin/pages/admin/statistics.md | 7 + user/plugins/admin/pages/admin/system.md | 7 + user/plugins/admin/pages/admin/themes.md | 7 + user/plugins/admin/pages/admin/tools.md | 5 + user/plugins/admin/pages/admin/update.md | 8 + user/plugins/admin/pages/admin/user.md | 8 + user/plugins/admin/tests/_bootstrap.php | 11 + .../admin/tests/_support/Helper/Unit.php | 80 + .../admin/tests/_support/UnitTester.php | 26 + user/plugins/admin/tests/unit.suite.yml | 9 + user/plugins/admin/tests/unit/_bootstrap.php | 3 + .../tests/unit/classes/controllerTest.php | 42 + user/plugins/admin/themes/grav/.eslintrc | 165 + .../admin/themes/grav/app/dashboard/backup.js | 42 + .../admin/themes/grav/app/dashboard/cache.js | 49 + .../admin/themes/grav/app/dashboard/chart.js | 138 + .../admin/themes/grav/app/dashboard/index.js | 12 + .../admin/themes/grav/app/dashboard/update.js | 1 + .../themes/grav/app/forms/fields/array.js | 193 + .../grav/app/forms/fields/collections.js | 261 + .../grav/app/forms/fields/colorpicker.js | 581 + .../themes/grav/app/forms/fields/cron.js | 145 + .../themes/grav/app/forms/fields/datetime.js | 63 + .../themes/grav/app/forms/fields/editor.js | 237 + .../grav/app/forms/fields/editor/buttons.js | 416 + .../grav/app/forms/fields/filepicker.js | 140 + .../themes/grav/app/forms/fields/files.js | 383 + .../grav/app/forms/fields/iconpicker.js | 298 + .../themes/grav/app/forms/fields/index.js | 72 + .../grav/app/forms/fields/mediapicker.js | 92 + .../grav/app/forms/fields/multilevel.js | 279 + .../themes/grav/app/forms/fields/selectize.js | 58 + .../grav/app/forms/fields/selectunique.js | 160 + .../themes/grav/app/forms/fields/text.js | 13 + .../admin/themes/grav/app/forms/form.js | 139 + .../admin/themes/grav/app/forms/index.js | 16 + .../admin/themes/grav/app/forms/state.js | 150 + user/plugins/admin/themes/grav/app/main.js | 78 + .../admin/themes/grav/app/media/index.js | 230 + .../admin/themes/grav/app/pages/filter.js | 148 + .../admin/themes/grav/app/pages/index.js | 53 + .../admin/themes/grav/app/pages/page/add.js | 67 + .../themes/grav/app/pages/page/delete.js | 15 + .../grav/app/pages/page/disable-buttons.js | 5 + .../admin/themes/grav/app/pages/page/index.js | 47 + .../admin/themes/grav/app/pages/page/media.js | 201 + .../admin/themes/grav/app/pages/page/move.js | 13 + .../themes/grav/app/pages/page/multilang.js | 22 + .../admin/themes/grav/app/pages/page/unset.js | 18 + .../admin/themes/grav/app/pages/tree.js | 135 + .../admin/themes/grav/app/plugins/index.js | 92 + .../admin/themes/grav/app/themes/index.js | 46 + .../admin/themes/grav/app/tools/index.js | 1 + .../admin/themes/grav/app/tools/logs.js | 14 + .../grav/app/updates/channel-switcher.js | 24 + .../admin/themes/grav/app/updates/check.js | 26 + .../admin/themes/grav/app/updates/feed.js | 68 + .../admin/themes/grav/app/updates/index.js | 186 + .../themes/grav/app/updates/notifications.js | 170 + .../admin/themes/grav/app/updates/update.js | 19 + .../admin/themes/grav/app/utils/2fa.js | 32 + .../grav/app/utils/bootstrap-collapse.js | 210 + .../grav/app/utils/bootstrap-transition.js | 52 + .../admin/themes/grav/app/utils/colors.js | 152 + .../admin/themes/grav/app/utils/cron-ui.js | 864 + .../themes/grav/app/utils/formatbytes.js | 11 + .../admin/themes/grav/app/utils/gpm.js | 57 + .../themes/grav/app/utils/jquery-utils.js | 50 + .../admin/themes/grav/app/utils/keepalive.js | 32 + .../admin/themes/grav/app/utils/offline.js | 21 + .../admin/themes/grav/app/utils/packages.js | 458 + .../admin/themes/grav/app/utils/request.js | 38 + .../admin/themes/grav/app/utils/response.js | 101 + .../admin/themes/grav/app/utils/scrollbar.js | 40 + .../grav/app/utils/selectize-option-click.js | 42 + .../grav/app/utils/selectize-required-fix.js | 28 + .../admin/themes/grav/app/utils/sidebar.js | 179 + .../admin/themes/grav/app/utils/storage.js | 41 + .../themes/grav/app/utils/tabs-memory.js | 29 + .../admin/themes/grav/app/utils/toastr.js | 6 + .../admin/themes/grav/css-compiled/fonts.css | 3 + .../themes/grav/css-compiled/fonts.css.map | 1 + .../themes/grav/css-compiled/nucleus.css | 3 + .../themes/grav/css-compiled/nucleus.css.map | 1 + .../admin/themes/grav/css-compiled/preset.css | 3 + .../themes/grav/css-compiled/preset.css.map | 1 + .../themes/grav/css-compiled/simple-fonts.css | 3 + .../grav/css-compiled/simple-fonts.css.map | 1 + .../themes/grav/css-compiled/template.css | 7 + .../themes/grav/css-compiled/template.css.map | 1 + .../admin/themes/grav/css/chartist.min.css | 1 + .../grav/css/codemirror/base16-light.css | 36 + .../themes/grav/css/codemirror/codemirror.css | 332 + .../themes/grav/css/codemirror/paper.css | 39 + .../themes/grav/css/featherlight.min.css | 8 + .../themes/grav/css/fork-awesome.min.css | 12 + .../admin/themes/grav/css/hint.base.min.css | 5 + .../admin/themes/grav/css/iconpicker.css | 223 + .../admin/themes/grav/css/nucleus-ie10.css | 24 + .../admin/themes/grav/css/nucleus-ie9.css | 62 + user/plugins/admin/themes/grav/css/prism.css | 121 + .../themes/grav/css/pure-0.5.0/grids-min.css | 15 + .../admin/themes/grav/css/selectize.min.css | 1 + .../themes/grav/fonts/forkawesome-webfont.eot | Bin 0 -> 186490 bytes .../themes/grav/fonts/forkawesome-webfont.svg | 2810 ++++ .../themes/grav/fonts/forkawesome-webfont.ttf | Bin 0 -> 186300 bytes .../grav/fonts/forkawesome-webfont.woff | Bin 0 -> 113404 bytes .../grav/fonts/forkawesome-webfont.woff2 | Bin 0 -> 90420 bytes .../rockettheme-apps/rockettheme-apps.eot | Bin 0 -> 4838 bytes .../rockettheme-apps/rockettheme-apps.svg | 16 + .../rockettheme-apps/rockettheme-apps.ttf | Bin 0 -> 4644 bytes .../rockettheme-apps/rockettheme-apps.woff | Bin 0 -> 3348 bytes user/plugins/admin/themes/grav/gulpfile.js | 110 + .../admin/themes/grav/images/favicon.png | Bin 0 -> 13203 bytes .../admin/themes/grav/images/grav-regular.svg | 1 + .../admin/themes/grav/images/grav-small.svg | 1 + .../plugins/admin/themes/grav/images/logo.svg | 1 + .../admin/themes/grav/images/transparent.png | Bin 0 -> 5123 bytes .../plugins/admin/themes/grav/js/admin.min.js | 30 + .../themes/grav/js/form-attr.polyfill.js | 80 + .../admin/themes/grav/js/vendor.min.js | 52 + user/plugins/admin/themes/grav/package.json | 63 + user/plugins/admin/themes/grav/scss.sh | 2 + .../scss/configuration/fonts/_support.scss | 75 + .../scss/configuration/nucleus/_base.scss | 14 + .../configuration/nucleus/_breakpoints.scss | 16 + .../scss/configuration/nucleus/_core.scss | 2 + .../scss/configuration/nucleus/_layout.scss | 8 + .../grav/scss/configuration/nucleus/_nav.scss | 3 + .../configuration/nucleus/_typography.scss | 14 + .../scss/configuration/template/_base.scss | 5 + .../scss/configuration/template/_colors.scss | 15 + .../configuration/template/_variables.scss | 22 + .../plugins/admin/themes/grav/scss/fonts.scss | 11 + .../admin/themes/grav/scss/nucleus.scss | 27 + .../admin/themes/grav/scss/nucleus/_core.scss | 217 + .../admin/themes/grav/scss/nucleus/_flex.scss | 195 + .../themes/grav/scss/nucleus/_forms.scss | 62 + .../themes/grav/scss/nucleus/_typography.scss | 86 + .../grav/scss/nucleus/functions/_base.scss | 2 + .../scss/nucleus/functions/_direction.scss | 37 + .../grav/scss/nucleus/functions/_range.scss | 13 + .../grav/scss/nucleus/mixins/_base.scss | 2 + .../scss/nucleus/mixins/_breakpoints.scss | 44 + .../grav/scss/nucleus/mixins/_utilities.scss | 30 + .../scss/nucleus/particles/_align-text.scss | 46 + .../scss/nucleus/particles/_visibility.scss | 0 .../admin/themes/grav/scss/preset.scss | 1750 ++ .../admin/themes/grav/scss/simple-fonts.scss | 11 + .../admin/themes/grav/scss/template.scss | 97 + .../themes/grav/scss/template/_admin.scss | 1322 ++ .../themes/grav/scss/template/_buttons.scss | 131 + .../themes/grav/scss/template/_colors.scss | 19 + .../themes/grav/scss/template/_core.scss | 51 + .../themes/grav/scss/template/_custom.scss | 2 + .../themes/grav/scss/template/_dropzone.scss | 285 + .../themes/grav/scss/template/_editor.scss | 287 + .../themes/grav/scss/template/_errors.scss | 17 + .../grav/scss/template/_extensions.scss | 58 + .../themes/grav/scss/template/_fonts.scss | 40 + .../themes/grav/scss/template/_forms.scss | 789 + .../admin/themes/grav/scss/template/_gpm.scss | 207 + .../themes/grav/scss/template/_header.scss | 3 + .../themes/grav/scss/template/_jqcron.scss | 105 + .../themes/grav/scss/template/_login.scss | 190 + .../themes/grav/scss/template/_media.scss | 331 + .../grav/scss/template/_nav-toggle.scss | 71 + .../grav/scss/template/_notifications.scss | 116 + .../themes/grav/scss/template/_pages.scss | 352 + .../themes/grav/scss/template/_phpinfo.scss | 35 + .../themes/grav/scss/template/_remodal.scss | 329 + .../themes/grav/scss/template/_tables.scss | 192 + .../themes/grav/scss/template/_tabs.scss | 118 + .../themes/grav/scss/template/_toastr.scss | 183 + .../themes/grav/scss/template/_tools.scss | 101 + .../grav/scss/template/_typography.scss | 162 + .../themes/grav/scss/template/_utilities.scss | 5 + .../grav/scss/template/modules/_base.scss | 5 + .../template/modules/_bourbon_essentials.scss | 120 + .../grav/scss/template/modules/_buttons.scss | 57 + .../scss/template/modules/_colorpicker.scss | 253 + .../template/modules/_datetimepicker.scss | 466 + .../scss/template/modules/_input-range.scss | 87 + .../scss/template/modules/_scrollbars.scss | 98 + .../scss/template/modules/_toggle-switch.scss | 20 + .../bourbon/_bourbon-deprecated-upcoming.scss | 8 + .../grav/scss/vendor/bourbon/_bourbon.scss | 77 + .../scss/vendor/bourbon/addons/_button.scss | 374 + .../scss/vendor/bourbon/addons/_clearfix.scss | 23 + .../bourbon/addons/_directional-values.scss | 111 + .../scss/vendor/bourbon/addons/_ellipsis.scss | 7 + .../vendor/bourbon/addons/_font-family.scss | 5 + .../vendor/bourbon/addons/_hide-text.scss | 10 + .../bourbon/addons/_html5-input-types.scss | 86 + .../scss/vendor/bourbon/addons/_position.scss | 32 + .../scss/vendor/bourbon/addons/_prefixer.scss | 45 + .../grav/scss/vendor/bourbon/addons/_rem.scss | 33 + .../vendor/bourbon/addons/_retina-image.scss | 31 + .../scss/vendor/bourbon/addons/_size.scss | 16 + .../bourbon/addons/_timing-functions.scss | 32 + .../scss/vendor/bourbon/addons/_triangle.scss | 83 + .../vendor/bourbon/addons/_word-wrap.scss | 8 + .../scss/vendor/bourbon/css3/_animation.scss | 52 + .../scss/vendor/bourbon/css3/_appearance.scss | 3 + .../bourbon/css3/_backface-visibility.scss | 6 + .../bourbon/css3/_background-image.scss | 42 + .../scss/vendor/bourbon/css3/_background.scss | 55 + .../vendor/bourbon/css3/_border-image.scss | 59 + .../vendor/bourbon/css3/_border-radius.scss | 22 + .../scss/vendor/bourbon/css3/_box-sizing.scss | 4 + .../grav/scss/vendor/bourbon/css3/_calc.scss | 4 + .../scss/vendor/bourbon/css3/_columns.scss | 47 + .../scss/vendor/bourbon/css3/_filter.scss | 5 + .../scss/vendor/bourbon/css3/_flex-box.scss | 321 + .../scss/vendor/bourbon/css3/_font-face.scss | 23 + .../bourbon/css3/_font-feature-settings.scss | 10 + .../bourbon/css3/_hidpi-media-query.scss | 10 + .../scss/vendor/bourbon/css3/_hyphens.scss | 4 + .../vendor/bourbon/css3/_image-rendering.scss | 14 + .../scss/vendor/bourbon/css3/_keyframes.scss | 35 + .../vendor/bourbon/css3/_linear-gradient.scss | 38 + .../vendor/bourbon/css3/_perspective.scss | 8 + .../vendor/bourbon/css3/_placeholder.scss | 8 + .../vendor/bourbon/css3/_radial-gradient.scss | 39 + .../scss/vendor/bourbon/css3/_transform.scss | 15 + .../scss/vendor/bourbon/css3/_transition.scss | 77 + .../vendor/bourbon/css3/_user-select.scss | 3 + .../vendor/bourbon/functions/_assign.scss | 11 + .../bourbon/functions/_color-lightness.scss | 13 + .../vendor/bourbon/functions/_flex-grid.scss | 39 + .../bourbon/functions/_golden-ratio.scss | 3 + .../vendor/bourbon/functions/_grid-width.scss | 13 + .../bourbon/functions/_modular-scale.scss | 66 + .../vendor/bourbon/functions/_px-to-em.scss | 13 + .../vendor/bourbon/functions/_px-to-rem.scss | 15 + .../bourbon/functions/_strip-units.scss | 5 + .../vendor/bourbon/functions/_tint-shade.scss | 9 + .../functions/_transition-property-name.scss | 22 + .../vendor/bourbon/functions/_unpack.scss | 17 + .../bourbon/helpers/_convert-units.scss | 15 + .../helpers/_gradient-positions-parser.scss | 13 + .../scss/vendor/bourbon/helpers/_is-num.scss | 8 + .../bourbon/helpers/_linear-angle-parser.scss | 25 + .../helpers/_linear-gradient-parser.scss | 41 + .../helpers/_linear-positions-parser.scss | 61 + .../helpers/_linear-side-corner-parser.scss | 31 + .../bourbon/helpers/_radial-arg-parser.scss | 69 + .../helpers/_radial-gradient-parser.scss | 50 + .../helpers/_radial-positions-parser.scss | 18 + .../bourbon/helpers/_render-gradients.scss | 26 + .../bourbon/helpers/_shape-size-stripper.scss | 10 + .../vendor/bourbon/helpers/_str-to-num.scss | 50 + .../vendor/bourbon/settings/_prefixer.scss | 6 + .../vendor/bourbon/settings/_px-to-em.scss | 1 + .../vendor/color-schemer/_color-schemer.scss | 31 + .../color-schemer/color-schemer/_cmyk.scss | 14 + .../color-schemer/_color-adjustments.scss | 30 + .../color-schemer/_color-schemer.scss | 208 + .../color-schemer/_colorblind.scss | 29 + .../color-schemer/_comparison.scss | 15 + .../color-schemer/_equalize.scss | 5 + .../color-schemer/_harmonize.scss | 59 + .../color-schemer/_interpolation.scss | 34 + .../color-schemer/color-schemer/_mix.scss | 40 + .../color-schemer/color-schemer/_mixins.scss | 29 + .../color-schemer/color-schemer/_ryb.scss | 76 + .../color-schemer/_tint-shade.scss | 9 + .../themes/grav/templates/config.html.twig | 90 + .../themes/grav/templates/dashboard.html.twig | 70 + .../themes/grav/templates/default.json.twig | 5 + .../themes/grav/templates/denied.html.twig | 18 + .../grav/templates/email/base.html.twig | 194 + .../themes/grav/templates/empty.html.twig | 0 .../themes/grav/templates/error.html.twig | 20 + .../themes/grav/templates/error.json.twig | 1 + .../themes/grav/templates/forgot.html.twig | 17 + .../grav/templates/forms/field.html.twig | 114 + .../forms/fields/array/array.html.twig | 96 + .../backupshistory/backupshistory.html.twig | 32 + .../fields/blueprint/blueprint.html.twig | 12 + .../fields/colorpicker/colorpicker.html.twig | 38 + .../forms/fields/column/column.html.twig | 14 + .../forms/fields/columns/columns.html.twig | 12 + .../forms/fields/cron/cron.html.twig | 6 + .../fields/cronstatus/cronstatus.html.twig | 71 + .../fields/dateformat/dateformat.html.twig | 24 + .../forms/fields/datetime/datetime.html.twig | 26 + .../forms/fields/editor/editor.html.twig | 50 + .../forms/fields/fieldset/fieldset.html.twig | 96 + .../forms/fields/file/file.html.twig | 116 + .../fields/filepicker/filepicker.html.twig | 17 + .../fields/frontmatter/frontmatter.html.twig | 10 + .../fields/iconpicker/iconpicker.html.twig | 45 + .../forms/fields/iconpicker/icons.yaml | 6570 ++++++++ .../forms/fields/list/list.html.twig | 195 + .../forms/fields/markdown/markdown.html.twig | 10 + .../fields/mediapicker/mediapicker.html.twig | 20 + .../fields/multilevel/multilevel.html.twig | 120 + .../forms/fields/order/order.html.twig | 55 + .../fields/pagemedia/pagemedia.html.twig | 58 + .../pagemediaselect/pagemediaselect.html.twig | 2 + .../forms/fields/pages/pages.html.twig | 52 + .../forms/fields/parents/parents.html.twig | 26 + .../fields/permissions/permissions.html.twig | 70 + .../forms/fields/range/range.html.twig | 42 + .../forms/fields/section/section.html.twig | 26 + .../fields/selectize/selectize.html.twig | 19 + .../selectunique/selectunique.html.twig | 42 + .../forms/fields/taxonomy/taxonomy.html.twig | 30 + .../fields/themeselect/themeselect.html.twig | 31 + .../forms/fields/userinfo/userinfo.html.twig | 19 + .../templates/forms/fields/xss/xss.html.twig | 6 + .../themes/grav/templates/installer.html.twig | 13 + .../themes/grav/templates/login.html.twig | 11 + .../templates/media-list-content.html.twig | 19 + .../themes/grav/templates/pages.html.twig | 425 + .../partials/backups-button.html.twig | 21 + .../templates/partials/base-root.html.twig | 133 + .../grav/templates/partials/base.html.twig | 1 + .../partials/blueprints-new-folder.html.twig | 21 + .../partials/blueprints-new.html.twig | 21 + .../partials/blueprints-raw.html.twig | 17 + .../templates/partials/blueprints.html.twig | 35 + .../partials/dashboard-feed.html.twig | 14 + .../partials/dashboard-maintenance.html.twig | 33 + .../dashboard-notifications.html.twig | 13 + .../partials/dashboard-pages.html.twig | 19 + .../partials/dashboard-statistics.html.twig | 24 + .../templates/partials/feed-block.html.twig | 3 + .../grav/templates/partials/footer.html.twig | 5 + .../grav/templates/partials/header.html.twig | 11 + .../partials/javascript-config.html.twig | 43 + .../templates/partials/javascripts.html.twig | 11 + .../templates/partials/list-sort.html.twig | 12 + .../templates/partials/login-form.html.twig | 31 + .../templates/partials/login-logo.html.twig | 14 + .../templates/partials/login-logout.html.twig | 15 + .../templates/partials/login-twofa.html.twig | 26 + .../grav/templates/partials/login.html.twig | 34 + .../grav/templates/partials/logo.html.twig | 20 + .../partials/media-list-wrapper.html.twig | 32 + .../media-list-wrapper__list.html.twig | 23 + ...edia-list-wrapper__list__filters.html.twig | 28 + .../media-list-wrapper__sidebar.html.twig | 50 + .../templates/partials/messages.html.twig | 14 + .../partials/modal-add-package.html.twig | 89 + .../partials/modal-changes-detected.html.twig | 13 + .../modal-reinstall-package.html.twig | 38 + .../partials/modal-remove-package.html.twig | 44 + .../partials/modal-update-packages.html.twig | 89 + .../partials/nav-quick-tray.html.twig | 40 + .../templates/partials/nav-toggle.html.twig | 3 + .../partials/nav-user-avatar.html.twig | 2 + .../partials/nav-user-details.html.twig | 19 + .../grav/templates/partials/nav.html.twig | 96 + .../notification-dashboard-block.html.twig | 6 + .../notification-feed-block.html.twig | 3 + .../notification-plugins-block.html.twig | 6 + .../notification-themes-block.html.twig | 6 + .../partials/notification-top-block.html.twig | 6 + .../partials/page-children.html.twig | 11 + .../templates/partials/page-legend.html.twig | 11 + .../templates/partials/page-move.html.twig | 20 + .../templates/partials/plugin-data.html.twig | 63 + .../partials/plugins-details.html.twig | 62 + .../templates/partials/plugins-list.html.twig | 74 + .../templates/partials/register.html.twig | 22 + .../partials/release-toggle.html.twig | 9 + .../partials/spinning-wheel.html.twig | 3 + .../templates/partials/stylesheets.html.twig | 17 + .../grav/templates/partials/theme.html.twig | 13 + .../partials/themes-details.html.twig | 120 + .../templates/partials/themes-list.html.twig | 82 + .../partials/tools-backups-titlebar.html.twig | 7 + .../partials/tools-backups.html.twig | 76 + .../partials/tools-direct-install.html.twig | 29 + .../templates/partials/tools-logs.html.twig | 78 + .../partials/tools-reports.html.twig | 15 + .../tools-scheduler-titlebar.html.twig | 6 + .../partials/tools-scheduler.html.twig | 33 + .../partials/userinfo-avatar-credit.html.twig | 1 + .../partials/userinfo-avatar.html.twig | 5 + .../themes/grav/templates/plugins.html.twig | 89 + .../themes/grav/templates/preview.html.twig | 24 + .../themes/grav/templates/register.html.twig | 28 + .../grav/templates/reports/security.html.twig | 20 + .../templates/reports/yamllinter.html.twig | 22 + .../themes/grav/templates/reset.html.twig | 19 + .../grav/templates/statistics.html.twig | 15 + .../themes/grav/templates/themes.html.twig | 83 + .../themes/grav/templates/tools.html.twig | 50 + .../grav/templates/unauthorized.html.twig | 1 + .../themes/grav/templates/user.html.twig | 64 + user/plugins/admin/themes/grav/theme.yaml | 0 user/plugins/admin/themes/grav/watch.sh | 27 + .../plugins/admin/themes/grav/webpack.conf.js | 41 + user/plugins/admin/themes/grav/yarn.lock | 5990 +++++++ .../plugins/admin/twig/AdminTwigExtension.php | 6 + user/plugins/admin/vendor/autoload.php | 7 + user/plugins/admin/vendor/bin/picofeed | 1 + .../admin/vendor/composer/ClassLoader.php | 445 + user/plugins/admin/vendor/composer/LICENSE | 21 + .../vendor/composer/autoload_classmap.php | 18 + .../vendor/composer/autoload_namespaces.php | 10 + .../admin/vendor/composer/autoload_psr4.php | 11 + .../admin/vendor/composer/autoload_real.php | 52 + .../admin/vendor/composer/autoload_static.php | 63 + .../admin/vendor/composer/installed.json | 169 + .../admin/vendor/composer/semver/CHANGELOG.md | 66 + .../admin/vendor/composer/semver/LICENSE | 19 + .../admin/vendor/composer/semver/README.md | 70 + .../vendor/composer/semver/composer.json | 58 + .../vendor/composer/semver/src/Comparator.php | 111 + .../src/Constraint/AbstractConstraint.php | 63 + .../semver/src/Constraint/Constraint.php | 219 + .../src/Constraint/ConstraintInterface.php | 32 + .../semver/src/Constraint/EmptyConstraint.php | 59 + .../semver/src/Constraint/MultiConstraint.php | 120 + .../vendor/composer/semver/src/Semver.php | 127 + .../composer/semver/src/VersionParser.php | 548 + .../plugins/admin/vendor/p3k/picofeed/LICENSE | 21 + .../vendor/p3k/picofeed/lib/PicoFeed/Base.php | 38 + .../picofeed/lib/PicoFeed/Client/Client.php | 712 + .../lib/PicoFeed/Client/ClientException.php | 14 + .../p3k/picofeed/lib/PicoFeed/Client/Curl.php | 412 + .../PicoFeed/Client/ForbiddenException.php | 10 + .../lib/PicoFeed/Client/HttpHeaders.php | 79 + .../Client/InvalidCertificateException.php | 12 + .../PicoFeed/Client/InvalidUrlException.php | 12 + .../PicoFeed/Client/MaxRedirectException.php | 12 + .../lib/PicoFeed/Client/MaxSizeException.php | 12 + .../picofeed/lib/PicoFeed/Client/Stream.php | 205 + .../lib/PicoFeed/Client/TimeoutException.php | 12 + .../PicoFeed/Client/UnauthorizedException.php | 10 + .../p3k/picofeed/lib/PicoFeed/Client/Url.php | 283 + .../picofeed/lib/PicoFeed/Config/Config.php | 102 + .../lib/PicoFeed/Encoding/Encoding.php | 33 + .../lib/PicoFeed/Filter/Attribute.php | 700 + .../picofeed/lib/PicoFeed/Filter/Filter.php | 144 + .../p3k/picofeed/lib/PicoFeed/Filter/Html.php | 243 + .../p3k/picofeed/lib/PicoFeed/Filter/Tag.php | 208 + .../Generator/ContentGeneratorInterface.php | 23 + .../Generator/FileContentGenerator.php | 36 + .../Generator/YoutubeContentGenerator.php | 67 + .../picofeed/lib/PicoFeed/Logging/Logger.php | 114 + .../p3k/picofeed/lib/PicoFeed/Parser/Atom.php | 395 + .../lib/PicoFeed/Parser/DateParser.php | 128 + .../p3k/picofeed/lib/PicoFeed/Parser/Feed.php | 315 + .../p3k/picofeed/lib/PicoFeed/Parser/Item.php | 562 + .../PicoFeed/Parser/MalformedXmlException.php | 13 + .../picofeed/lib/PicoFeed/Parser/Parser.php | 397 + .../lib/PicoFeed/Parser/ParserException.php | 15 + .../lib/PicoFeed/Parser/ParserInterface.php | 191 + .../picofeed/lib/PicoFeed/Parser/Rss10.php | 318 + .../picofeed/lib/PicoFeed/Parser/Rss20.php | 330 + .../picofeed/lib/PicoFeed/Parser/Rss91.php | 13 + .../picofeed/lib/PicoFeed/Parser/Rss92.php | 13 + .../PicoFeed/Parser/XmlEntityException.php | 13 + .../lib/PicoFeed/Parser/XmlParser.php | 246 + .../lib/PicoFeed/PicoFeedException.php | 14 + .../Processor/ContentFilterProcessor.php | 39 + .../Processor/ContentGeneratorProcessor.php | 49 + .../PicoFeed/Processor/ItemPostProcessor.php | 106 + .../Processor/ItemProcessorInterface.php | 25 + .../PicoFeed/Processor/ScraperProcessor.php | 96 + .../picofeed/lib/PicoFeed/Reader/Favicon.php | 186 + .../picofeed/lib/PicoFeed/Reader/Reader.php | 189 + .../lib/PicoFeed/Reader/ReaderException.php | 14 + .../Reader/SubscriptionNotFoundException.php | 12 + .../Reader/UnsupportedFeedFormatException.php | 12 + .../lib/PicoFeed/Rules/.blog.lemonde.fr.php | 14 + .../lib/PicoFeed/Rules/.blogs.nytimes.com.php | 15 + .../picofeed/lib/PicoFeed/Rules/.igen.fr.php | 13 + .../lib/PicoFeed/Rules/.nytimes.com.php | 11 + .../lib/PicoFeed/Rules/.over-blog.com.php | 11 + .../lib/PicoFeed/Rules/.phoronix.com.php | 12 + .../lib/PicoFeed/Rules/.slate.com.php | 20 + .../lib/PicoFeed/Rules/.theguardian.com.php | 14 + .../lib/PicoFeed/Rules/.wikipedia.org.php | 29 + .../lib/PicoFeed/Rules/.wired.com.php | 44 + .../picofeed/lib/PicoFeed/Rules/.wsj.com.php | 15 + .../picofeed/lib/PicoFeed/Rules/01net.com.php | 18 + .../p3k/picofeed/lib/PicoFeed/Rules/24.hu.php | 16 + .../picofeed/lib/PicoFeed/Rules/444.hu.php | 19 + .../picofeed/lib/PicoFeed/Rules/888.hu.php | 16 + .../lib/PicoFeed/Rules/abstrusegoose.com.php | 8 + .../lib/PicoFeed/Rules/achgut.com.php | 16 + .../PicoFeed/Rules/adventuregamers.com.php | 23 + .../lib/PicoFeed/Rules/alainonline.net.php | 14 + .../lib/PicoFeed/Rules/aljazeera.com.php | 25 + .../lib/PicoFeed/Rules/allafrica.com.php | 20 + .../PicoFeed/Rules/allgemeine-zeitung.de.php | 23 + .../PicoFeed/Rules/amazingsuperpowers.com.php | 8 + .../lib/PicoFeed/Rules/anythingcomic.com.php | 13 + .../picofeed/lib/PicoFeed/Rules/ap.org.php | 13 + .../lib/PicoFeed/Rules/areadvd.de.php | 10 + .../lib/PicoFeed/Rules/arstechnica.com.php | 25 + .../picofeed/lib/PicoFeed/Rules/atv.hu.php | 18 + .../lib/PicoFeed/Rules/awkwardzombie.com.php | 10 + .../lib/PicoFeed/Rules/backchannel.com.php | 18 + .../lib/PicoFeed/Rules/bangkokpost.com.php | 19 + .../lib/PicoFeed/Rules/bauerwilli.com.php | 17 + .../picofeed/lib/PicoFeed/Rules/bgr.com.php | 15 + .../lib/PicoFeed/Rules/bigfootjustice.com.php | 8 + .../lib/PicoFeed/Rules/bigpicture.ru.php | 31 + .../lib/PicoFeed/Rules/bizjournals.com.php | 12 + .../lib/PicoFeed/Rules/biztimes.com.php | 22 + .../PicoFeed/Rules/bleepingcomputer.com.php | 15 + .../lib/PicoFeed/Rules/blog.fefe.de.php | 13 + .../lib/PicoFeed/Rules/blog.mapillary.com.php | 11 + .../lib/PicoFeed/Rules/brewers.mlb.com.php | 22 + .../PicoFeed/Rules/buenosairesherald.com.php | 17 + .../lib/PicoFeed/Rules/bunicomic.com.php | 13 + .../lib/PicoFeed/Rules/buttersafe.com.php | 13 + .../lib/PicoFeed/Rules/cad-comic.com.php | 12 + .../Rules/chaoslife.findchaos.com.php | 10 + .../lib/PicoFeed/Rules/chinafile.com.php | 18 + .../picofeed/lib/PicoFeed/Rules/cicero.de.php | 17 + .../lib/PicoFeed/Rules/cliquerefresh.com.php | 10 + .../picofeed/lib/PicoFeed/Rules/cnet.com.php | 37 + .../lib/PicoFeed/Rules/coinwelt.de.php | 14 + .../lib/PicoFeed/Rules/consomac.fr.php | 13 + .../lib/PicoFeed/Rules/cowbirdsinlove.com.php | 8 + .../picofeed/lib/PicoFeed/Rules/crash.net.php | 18 + .../lib/PicoFeed/Rules/csmonitor.com.php | 19 + .../lib/PicoFeed/Rules/dailyjs.com.php | 19 + .../lib/PicoFeed/Rules/dailyreporter.com.php | 15 + .../lib/PicoFeed/Rules/dailytech.com.php | 13 + .../lib/PicoFeed/Rules/degroupnews.com.php | 14 + .../lib/PicoFeed/Rules/derstandard.at.php | 14 + .../lib/PicoFeed/Rules/dilbert.com.php | 11 + .../PicoFeed/Rules/discovermagazine.com.php | 26 + .../lib/PicoFeed/Rules/distrowatch.com.php | 13 + .../lib/PicoFeed/Rules/dozodomo.com.php | 15 + .../PicoFeed/Rules/drawingboardcomic.com.php | 15 + .../picofeed/lib/PicoFeed/Rules/e-w-e.ru.php | 22 + .../lib/PicoFeed/Rules/economist.com.php | 25 + .../Rules/encyclopedie.naheulbeuk.com.php | 13 + .../lib/PicoFeed/Rules/endlessorigami.com.php | 8 + .../lib/PicoFeed/Rules/engadget.com.php | 10 + .../PicoFeed/Rules/escapistmagazine.com.php | 45 + .../lib/PicoFeed/Rules/espn.go.com.php | 11 + .../lib/PicoFeed/Rules/exocomics.com.php | 15 + .../lib/PicoFeed/Rules/explosm.net.php | 13 + .../Rules/extrafabulouscomics.com.php | 8 + .../lib/PicoFeed/Rules/factroom.ru.php | 27 + .../lib/PicoFeed/Rules/fastcodesign.com.php | 13 + .../lib/PicoFeed/Rules/fastcoexist.com.php | 13 + .../lib/PicoFeed/Rules/fastcompany.com.php | 13 + .../lib/PicoFeed/Rules/ffworld.com.php | 13 + .../lib/PicoFeed/Rules/foreignpolicy.com.php | 21 + .../lib/PicoFeed/Rules/fossbytes.com.php | 18 + .../lib/PicoFeed/Rules/fototelegraf.ru.php | 19 + .../PicoFeed/Rules/fowllanguagecomics.com.php | 10 + .../lib/PicoFeed/Rules/gamechannel.hu.php | 15 + .../lib/PicoFeed/Rules/gamestar.hu.php | 17 + .../picofeed/lib/PicoFeed/Rules/geek.com.php | 17 + .../lib/PicoFeed/Rules/geektimes.ru.php | 12 + .../PicoFeed/Rules/gerbilwithajetpack.com.php | 12 + .../lib/PicoFeed/Rules/giantitp.com.php | 12 + .../lib/PicoFeed/Rules/github.com.php | 14 + .../lib/PicoFeed/Rules/gocomics.com.php | 12 + .../picofeed/lib/PicoFeed/Rules/golem.de.php | 21 + .../lib/PicoFeed/Rules/gondola.hu.php | 22 + .../lib/PicoFeed/Rules/gorabbit.ru.php | 19 + .../lib/PicoFeed/Rules/habrahabr.ru.php | 12 + .../lib/PicoFeed/Rules/happletea.com.php | 18 + .../lib/PicoFeed/Rules/hardware.fr.php | 11 + .../picofeed/lib/PicoFeed/Rules/heise.de.php | 79 + .../lib/PicoFeed/Rules/hirek.prim.hu.php | 14 + .../lib/PicoFeed/Rules/hotshowlife.com.php | 23 + .../lib/PicoFeed/Rules/huffingtonpost.com.php | 13 + .../picofeed/lib/PicoFeed/Rules/hvg.hu.php | 17 + .../picofeed/lib/PicoFeed/Rules/idokep.hu.php | 18 + .../lib/PicoFeed/Rules/imogenquest.net.php | 8 + .../picofeed/lib/PicoFeed/Rules/index.hu.php | 29 + .../lib/PicoFeed/Rules/indiehaven.com.php | 11 + .../lib/PicoFeed/Rules/inforadio.hu.php | 25 + .../picofeed/lib/PicoFeed/Rules/ing.dk.php | 12 + .../lib/PicoFeed/Rules/invisiblebread.com.php | 8 + .../lib/PicoFeed/Rules/ir.amd.com.php | 10 + .../lib/PicoFeed/Rules/japantimes.co.jp.php | 21 + .../lib/PicoFeed/Rules/japantoday.com.php | 15 + .../lib/PicoFeed/Rules/journaldugeek.com.php | 11 + .../lib/PicoFeed/Rules/jsonline.com.php | 37 + .../lib/PicoFeed/Rules/justcoolidea.ru.php | 19 + .../picofeed/lib/PicoFeed/Rules/kanpai.fr.php | 13 + .../PicoFeed/Rules/karriere.jobfinder.dk.php | 12 + .../lib/PicoFeed/Rules/kisalfold.hu.php | 17 + .../lib/PicoFeed/Rules/kiszamolo.hu.php | 14 + .../picofeed/lib/PicoFeed/Rules/kodi.tv.php | 11 + .../lib/PicoFeed/Rules/koreaherald.com.php | 11 + .../lib/PicoFeed/Rules/koreatimes.php | 14 + .../PicoFeed/Rules/lastplacecomics.com.php | 8 + .../lib/PicoFeed/Rules/legorafi.fr.php | 22 + .../lib/PicoFeed/Rules/lejapon.fr.php | 17 + .../lib/PicoFeed/Rules/lesjoiesducode.fr.php | 13 + .../picofeed/lib/PicoFeed/Rules/lfg.co.php | 12 + .../lib/PicoFeed/Rules/lifehacker.com.php | 18 + .../lib/PicoFeed/Rules/lifehacker.ru.php | 22 + .../lib/PicoFeed/Rules/linux-magazin.de.php | 16 + .../picofeed/lib/PicoFeed/Rules/linux.org.php | 14 + .../lib/PicoFeed/Rules/linux.org.ru.php | 13 + .../lib/PicoFeed/Rules/linuxinsider.com.php | 20 + .../p3k/picofeed/lib/PicoFeed/Rules/lists.php | 13 + .../lib/PicoFeed/Rules/loadingartist.com.php | 8 + .../lib/PicoFeed/Rules/loldwell.com.php | 10 + .../lib/PicoFeed/Rules/lukesurl.com.php | 15 + .../picofeed/lib/PicoFeed/Rules/macg.co.php | 13 + .../lib/PicoFeed/Rules/maclife.de.php | 11 + .../lib/PicoFeed/Rules/magyarkurir.hu.php | 21 + .../picofeed/lib/PicoFeed/Rules/marc.info.php | 13 + .../PicoFeed/Rules/marriedtothesea.com.php | 12 + .../lib/PicoFeed/Rules/marycagle.com.php | 13 + .../Rules/maximumble.thebookofbiff.com.php | 10 + .../lib/PicoFeed/Rules/medium.com.php | 19 + .../lib/PicoFeed/Rules/mercworks.net.php | 17 + .../lib/PicoFeed/Rules/metronieuws.nl.php | 10 + .../lib/PicoFeed/Rules/milwaukeenns.php | 14 + .../picofeed/lib/PicoFeed/Rules/mno.hu.php | 14 + .../Rules/mokepon.smackjeeves.com.php | 10 + .../lib/PicoFeed/Rules/monandroid.com.php | 13 + .../lib/PicoFeed/Rules/monwindows.com.php | 13 + .../lib/PicoFeed/Rules/moya-planeta.ru.php | 21 + .../lib/PicoFeed/Rules/mrlovenstein.com.php | 9 + .../lib/PicoFeed/Rules/muckrock.com.php | 20 + .../PicoFeed/Rules/mynorthshorenow.com.php | 27 + .../lib/PicoFeed/Rules/nakedCapitalism.php | 11 + .../picofeed/lib/PicoFeed/Rules/nasa.gov.php | 14 + .../lib/PicoFeed/Rules/nat-geo.ru.php | 11 + .../PicoFeed/Rules/nationaljournal.com.php | 15 + .../lib/PicoFeed/Rules/nature.com.php | 13 + .../picofeed/lib/PicoFeed/Rules/nba.com.php | 15 + .../lib/PicoFeed/Rules/nedroid.com.php | 8 + .../lib/PicoFeed/Rules/networkworld.com.php | 20 + .../lib/PicoFeed/Rules/neustadt-ticker.de.php | 15 + .../lib/PicoFeed/Rules/nextinpact.com.php | 18 + .../lib/PicoFeed/Rules/niceteethcomic.com.php | 10 + .../lib/PicoFeed/Rules/nichtlustig.de.php | 8 + .../picofeed/lib/PicoFeed/Rules/nlcafe.hu.php | 18 + .../lib/PicoFeed/Rules/novo-argumente.com.php | 16 + .../picofeed/lib/PicoFeed/Rules/oglaf.com.php | 19 + .../picofeed/lib/PicoFeed/Rules/onhax.net.php | 15 + .../lib/PicoFeed/Rules/onlinekosten.de.php | 13 + .../lib/PicoFeed/Rules/onmilwaukee.php | 24 + .../lib/PicoFeed/Rules/openculture.com.php | 11 + .../lib/PicoFeed/Rules/opennet.ru.php | 13 + .../PicoFeed/Rules/openrightsgroup.org.php | 20 + .../lib/PicoFeed/Rules/opensource.com.php | 22 + .../lib/PicoFeed/Rules/optipess.com.php | 8 + .../picofeed/lib/PicoFeed/Rules/origo.hu.php | 14 + .../lib/PicoFeed/Rules/osnews.com.php | 11 + .../lib/PicoFeed/Rules/pastebin.com.php | 13 + .../lib/PicoFeed/Rules/pcgameshardware.de.php | 16 + .../lib/PicoFeed/Rules/peebleslab.com.php | 9 + .../lib/PicoFeed/Rules/penny-arcade.com.php | 21 + .../lib/PicoFeed/Rules/pixelbeat.org.php | 12 + .../lib/PicoFeed/Rules/plus.google.com.php | 11 + .../lib/PicoFeed/Rules/popstrip.com.php | 8 + .../lib/PicoFeed/Rules/portfolio.hu.php | 15 + .../lib/PicoFeed/Rules/pro-linux.de.php | 16 + .../PicoFeed/Rules/publicpolicyforum.org.php | 15 + .../picofeed/lib/PicoFeed/Rules/publy.ru.php | 24 + .../lib/PicoFeed/Rules/putaindecode.fr.php | 16 + .../lib/PicoFeed/Rules/recode.net.php | 20 + .../PicoFeed/Rules/retractionwatch.com.php | 18 + .../PicoFeed/Rules/rockpapershotgun.com.php | 11 + .../PicoFeed/Rules/rue89.nouvelobs.com.php | 13 + .../lib/PicoFeed/Rules/rugbyrama.fr.php | 20 + .../lib/PicoFeed/Rules/salonkolumnisten.com | 17 + .../lib/PicoFeed/Rules/satwcomic.com.php | 13 + .../PicoFeed/Rules/science-skeptical.de.php | 14 + .../lib/PicoFeed/Rules/scrumalliance.org.php | 12 + .../lib/PicoFeed/Rules/securityfocus.com.php | 17 + .../PicoFeed/Rules/sentfromthemoon.com.php | 18 + .../lib/PicoFeed/Rules/sitepoint.com.php | 13 + .../lib/PicoFeed/Rules/slashdot.org.php | 11 + .../PicoFeed/Rules/smallhousebliss.com.php | 19 + .../lib/PicoFeed/Rules/smarthomewelt.de.php | 10 + .../PicoFeed/Rules/smashingmagazine.com.php | 10 + .../lib/PicoFeed/Rules/smbc-comics.com.php | 14 + .../lib/PicoFeed/Rules/snopes.com.php | 22 + .../lib/PicoFeed/Rules/soundandvision.com.php | 21 + .../lib/PicoFeed/Rules/spiegel.de.php | 14 + .../lib/PicoFeed/Rules/stereophile.com.php | 11 + .../lib/PicoFeed/Rules/stupidfox.net.php | 13 + .../lib/PicoFeed/Rules/subtraction.com.php | 15 + .../p3k/picofeed/lib/PicoFeed/Rules/sz.de.php | 10 + .../lib/PicoFeed/Rules/takprosto.cc.php | 21 + .../lib/PicoFeed/Rules/techcrunch.com.php | 15 + .../PicoFeed/Rules/the-ebook-reader.com.php | 15 + .../lib/PicoFeed/Rules/theatlantic.com.php | 23 + .../lib/PicoFeed/Rules/theawkwardyeti.com.php | 12 + .../lib/PicoFeed/Rules/thecodinglove.com.php | 10 + .../PicoFeed/Rules/thedoghousediaries.com.php | 18 + .../lib/PicoFeed/Rules/thegamercat.com.php | 10 + .../lib/PicoFeed/Rules/thehindu.com.php | 19 + .../lib/PicoFeed/Rules/thelocal.se.php | 17 + .../lib/PicoFeed/Rules/themerepublic.net.php | 10 + .../lib/PicoFeed/Rules/themoscowtimes.com.php | 18 + .../lib/PicoFeed/Rules/thenewslens.com.php | 21 + .../lib/PicoFeed/Rules/theodd1sout.com.php | 8 + .../lib/PicoFeed/Rules/theonion.com.php | 12 + .../lib/PicoFeed/Rules/theregister.co.uk.php | 18 + .../lib/PicoFeed/Rules/thestandard.com.hk.php | 22 + .../lib/PicoFeed/Rules/theverge.com.php | 16 + .../lib/PicoFeed/Rules/threepanelsoul.com.php | 11 + .../lib/PicoFeed/Rules/tichyseinblick.de.php | 22 + .../Rules/timesofindia.indiatimes.com.php | 14 + .../lib/PicoFeed/Rules/totalcar.hu.php | 18 + .../lib/PicoFeed/Rules/tozsdeforum.hu.php | 15 + .../lib/PicoFeed/Rules/travel-dealz.de.php | 15 + .../lib/PicoFeed/Rules/travelo.hu.php | 17 + .../lib/PicoFeed/Rules/treehugger.com.php | 14 + .../lib/PicoFeed/Rules/treelobsters.com.php | 8 + .../lib/PicoFeed/Rules/tutorialzine.com.php | 20 + .../lib/PicoFeed/Rules/twogag.com.php | 8 + .../PicoFeed/Rules/twokinds.keenspot.com.php | 10 + .../lib/PicoFeed/Rules/undeadly.org.php | 14 + .../picofeed/lib/PicoFeed/Rules/upi.com.php | 15 + .../lib/PicoFeed/Rules/usatoday.com.php | 27 + .../lib/PicoFeed/Rules/version2.dk.php | 12 + .../picofeed/lib/PicoFeed/Rules/vezess.hu.php | 20 + .../lib/PicoFeed/Rules/vgcats.com.php | 15 + .../picofeed/lib/PicoFeed/Rules/vuxml.org.php | 17 + .../PicoFeed/Rules/wausaudailyherald.com.php | 27 + .../picofeed/lib/PicoFeed/Rules/welt.de.php | 20 + .../lib/PicoFeed/Rules/westfalen-blatt.de.php | 16 + .../lib/PicoFeed/Rules/www.bbc.co.uk.php | 33 + .../lib/PicoFeed/Rules/www.bdgest.com.php | 15 + .../lib/PicoFeed/Rules/www.bgr.in.php | 23 + .../PicoFeed/Rules/www.businessweek.com.php | 15 + .../lib/PicoFeed/Rules/www.cnn.com.php | 24 + .../lib/PicoFeed/Rules/www.developpez.com.php | 21 + .../lib/PicoFeed/Rules/www.egscomics.com.php | 12 + .../Rules/www.fakingnews.firstpost.com.php | 17 + .../lib/PicoFeed/Rules/www.forbes.com.php | 20 + .../PicoFeed/Rules/www.franceculture.fr.php | 14 + .../Rules/www.futura-sciences.com.php | 19 + .../PicoFeed/Rules/www.geekculture.com.php | 13 + .../lib/PicoFeed/Rules/www.howtogeek.com.php | 14 + .../lib/PicoFeed/Rules/www.lepoint.fr.php | 18 + .../PicoFeed/Rules/www.lesnumeriques.com.php | 25 + .../lib/PicoFeed/Rules/www.mac4ever.com.php | 13 + .../lib/PicoFeed/Rules/www.makeuseof.com.php | 18 + .../Rules/www.monsieur-le-chien.fr.php | 11 + .../lib/PicoFeed/Rules/www.npr.org.php | 28 + .../lib/PicoFeed/Rules/www.numerama.com.php | 15 + .../lib/PicoFeed/Rules/www.oneindia.com.php | 14 + .../Rules/www.pseudo-sciences.org.php | 16 + .../lib/PicoFeed/Rules/www.sciencemag.org.php | 16 + .../lib/PicoFeed/Rules/www.slate.fr.php | 19 + .../PicoFeed/Rules/www.universfreebox.com.php | 15 + .../lib/PicoFeed/Rules/www.zeit.de.php | 41 + .../picofeed/lib/PicoFeed/Rules/xkcd.com.php | 8 + .../lib/PicoFeed/Rules/ymatuhin.ru.php | 21 + .../lib/PicoFeed/Rules/zarojel.hu.php | 19 + .../picofeed/lib/PicoFeed/Rules/zdnet.com.php | 23 + .../picofeed/lib/PicoFeed/Rules/zoom.hu.php | 17 + .../lib/PicoFeed/Scraper/CandidateParser.php | 281 + .../lib/PicoFeed/Scraper/ParserInterface.php | 20 + .../lib/PicoFeed/Scraper/RuleLoader.php | 104 + .../lib/PicoFeed/Scraper/RuleParser.php | 102 + .../picofeed/lib/PicoFeed/Scraper/Scraper.php | 282 + .../PicoFeed/Serialization/Subscription.php | 175 + .../Serialization/SubscriptionList.php | 75 + .../Serialization/SubscriptionListBuilder.php | 204 + .../Serialization/SubscriptionListParser.php | 100 + .../Serialization/SubscriptionParser.php | 142 + .../PicoFeed/Syndication/AtomFeedBuilder.php | 65 + .../lib/PicoFeed/Syndication/AtomHelper.php | 139 + .../PicoFeed/Syndication/AtomItemBuilder.php | 63 + .../lib/PicoFeed/Syndication/FeedBuilder.php | 185 + .../lib/PicoFeed/Syndication/ItemBuilder.php | 209 + .../PicoFeed/Syndication/Rss20FeedBuilder.php | 76 + .../lib/PicoFeed/Syndication/Rss20Helper.php | 115 + .../PicoFeed/Syndication/Rss20ItemBuilder.php | 67 + .../admin/vendor/p3k/picofeed/picofeed | 135 + .../vendor/zendframework/zendxml/CHANGELOG.md | 104 + .../vendor/zendframework/zendxml/LICENSE.md | 27 + .../vendor/zendframework/zendxml/README.md | 48 + .../zendframework/zendxml/composer.json | 54 + .../src/Exception/ExceptionInterface.php | 12 + .../Exception/InvalidArgumentException.php | 15 + .../src/Exception/RuntimeException.php | 15 + .../zendframework/zendxml/src/Security.php | 406 + user/plugins/email/CHANGELOG.md | 228 + user/plugins/email/LICENSE | 21 + user/plugins/email/README.md | 469 + user/plugins/email/blueprints.yaml | 243 + user/plugins/email/classes/Email.php | 544 + user/plugins/email/classes/Utils.php | 48 + .../email/cli/ClearQueueFailuresCommand.php | 60 + user/plugins/email/cli/FlushQueueCommand.php | 60 + user/plugins/email/cli/TestEmailCommand.php | 100 + user/plugins/email/composer.json | 33 + user/plugins/email/composer.lock | 428 + user/plugins/email/email.php | 150 + user/plugins/email/email.yaml | 22 + user/plugins/email/hebe.json | 15 + user/plugins/email/languages.yaml | 164 + .../email/templates/email/base.html.twig | 214 + user/plugins/email/vendor/autoload.php | 7 + .../email/vendor/composer/ClassLoader.php | 445 + user/plugins/email/vendor/composer/LICENSE | 21 + .../vendor/composer/autoload_classmap.php | 10 + .../email/vendor/composer/autoload_files.php | 14 + .../vendor/composer/autoload_namespaces.php | 10 + .../email/vendor/composer/autoload_psr4.php | 16 + .../email/vendor/composer/autoload_real.php | 70 + .../email/vendor/composer/autoload_static.php | 91 + .../email/vendor/composer/installed.json | 424 + .../email/vendor/doctrine/lexer/LICENSE | 19 + .../email/vendor/doctrine/lexer/README.md | 5 + .../email/vendor/doctrine/lexer/composer.json | 24 + .../Doctrine/Common/Lexer/AbstractLexer.php | 327 + .../EmailValidator/EmailLexer.php | 221 + .../EmailValidator/EmailParser.php | 104 + .../EmailValidator/EmailValidator.php | 67 + .../Exception/AtextAfterCFWS.php | 9 + .../EmailValidator/Exception/CRLFAtTheEnd.php | 9 + .../EmailValidator/Exception/CRLFX2.php | 9 + .../EmailValidator/Exception/CRNoLF.php | 9 + .../Exception/CharNotAllowed.php | 9 + .../Exception/CommaInDomain.php | 9 + .../Exception/ConsecutiveAt.php | 9 + .../Exception/ConsecutiveDot.php | 9 + .../Exception/DomainHyphened.php | 9 + .../EmailValidator/Exception/DotAtEnd.php | 9 + .../EmailValidator/Exception/DotAtStart.php | 9 + .../EmailValidator/Exception/ExpectingAT.php | 9 + .../Exception/ExpectingATEXT.php | 9 + .../Exception/ExpectingCTEXT.php | 9 + .../Exception/ExpectingDTEXT.php | 9 + .../Exception/ExpectingDomainLiteralClose.php | 9 + .../Exception/ExpectingQPair.php | 9 + .../EmailValidator/Exception/InvalidEmail.php | 14 + .../EmailValidator/Exception/NoDNSRecord.php | 11 + .../EmailValidator/Exception/NoDomainPart.php | 9 + .../EmailValidator/Exception/NoLocalPart.php | 9 + .../Exception/UnclosedComment.php | 9 + .../Exception/UnclosedQuotedString.php | 9 + .../Exception/UnopenedComment.php | 9 + .../EmailValidator/Parser/DomainPart.php | 368 + .../EmailValidator/Parser/LocalPart.php | 138 + .../EmailValidator/Parser/Parser.php | 215 + .../Validation/DNSCheckValidation.php | 72 + .../Validation/EmailValidation.php | 34 + .../Validation/Error/RFCWarnings.php | 11 + .../Validation/Error/SpoofEmail.php | 11 + .../Exception/EmptyValidationList.php | 13 + .../Validation/MultipleErrors.php | 26 + .../Validation/MultipleValidationWithAnd.php | 111 + .../Validation/NoRFCWarningsValidation.php | 41 + .../Validation/RFCValidation.php | 49 + .../Validation/SpoofCheckValidation.php | 45 + .../EmailValidator/Warning/AddressLiteral.php | 14 + .../EmailValidator/Warning/CFWSNearAt.php | 13 + .../EmailValidator/Warning/CFWSWithFWS.php | 13 + .../EmailValidator/Warning/Comment.php | 13 + .../Warning/DeprecatedComment.php | 13 + .../EmailValidator/Warning/DomainLiteral.php | 14 + .../EmailValidator/Warning/DomainTooLong.php | 14 + .../EmailValidator/Warning/EmailTooLong.php | 15 + .../EmailValidator/Warning/IPV6BadChar.php | 14 + .../EmailValidator/Warning/IPV6ColonEnd.php | 14 + .../EmailValidator/Warning/IPV6ColonStart.php | 14 + .../EmailValidator/Warning/IPV6Deprecated.php | 14 + .../Warning/IPV6DoubleColon.php | 14 + .../EmailValidator/Warning/IPV6GroupCount.php | 14 + .../EmailValidator/Warning/IPV6MaxGroups.php | 14 + .../EmailValidator/Warning/LabelTooLong.php | 14 + .../EmailValidator/Warning/LocalTooLong.php | 15 + .../EmailValidator/Warning/NoDNSMXRecord.php | 14 + .../EmailValidator/Warning/ObsoleteDTEXT.php | 14 + .../EmailValidator/Warning/QuotedPart.php | 13 + .../EmailValidator/Warning/QuotedString.php | 13 + .../EmailValidator/Warning/TLD.php | 13 + .../EmailValidator/Warning/Warning.php | 30 + .../vendor/egulias/email-validator/LICENSE | 19 + .../vendor/egulias/email-validator/README.md | 82 + .../egulias/email-validator/composer.json | 44 + .../egulias/email-validator/phpunit.xml.dist | 26 + .../swiftmailer/swiftmailer/.gitattributes | 9 + .../swiftmailer/.github/ISSUE_TEMPLATE.md | 19 + .../.github/PULL_REQUEST_TEMPLATE.md | 14 + .../vendor/swiftmailer/swiftmailer/.gitignore | 8 + .../swiftmailer/swiftmailer/.php_cs.dist | 16 + .../swiftmailer/swiftmailer/.travis.yml | 26 + .../vendor/swiftmailer/swiftmailer/CHANGES | 338 + .../vendor/swiftmailer/swiftmailer/LICENSE | 19 + .../vendor/swiftmailer/swiftmailer/README | 15 + .../swiftmailer/swiftmailer/composer.json | 43 + .../swiftmailer/swiftmailer/doc/headers.rst | 621 + .../swiftmailer/swiftmailer/doc/index.rst | 12 + .../swiftmailer/doc/introduction.rst | 61 + .../swiftmailer/swiftmailer/doc/japanese.rst | 19 + .../swiftmailer/swiftmailer/doc/messages.rst | 950 ++ .../swiftmailer/swiftmailer/doc/plugins.rst | 337 + .../swiftmailer/swiftmailer/doc/sending.rst | 453 + .../swiftmailer/lib/classes/Swift.php | 78 + .../lib/classes/Swift/AddressEncoder.php | 25 + .../AddressEncoder/IdnAddressEncoder.php | 50 + .../AddressEncoder/Utf8AddressEncoder.php | 36 + .../classes/Swift/AddressEncoderException.php | 32 + .../lib/classes/Swift/Attachment.php | 54 + .../AbstractFilterableInputStream.php | 176 + .../Swift/ByteStream/ArrayByteStream.php | 178 + .../Swift/ByteStream/FileByteStream.php | 216 + .../ByteStream/TemporaryFileByteStream.php | 42 + .../lib/classes/Swift/CharacterReader.php | 67 + .../GenericFixedWidthReader.php | 97 + .../Swift/CharacterReader/UsAsciiReader.php | 84 + .../Swift/CharacterReader/Utf8Reader.php | 176 + .../classes/Swift/CharacterReaderFactory.php | 26 + .../SimpleCharacterReaderFactory.php | 124 + .../lib/classes/Swift/CharacterStream.php | 89 + .../CharacterStream/ArrayCharacterStream.php | 293 + .../Swift/CharacterStream/CharacterStream.php | 227 + .../CharacterStream/NgCharacterStream.php | 20 + .../lib/classes/Swift/ConfigurableSpool.php | 63 + .../lib/classes/Swift/DependencyContainer.php | 391 + .../lib/classes/Swift/DependencyException.php | 27 + .../lib/classes/Swift/EmbeddedFile.php | 53 + .../swiftmailer/lib/classes/Swift/Encoder.php | 28 + .../classes/Swift/Encoder/Base64Encoder.php | 58 + .../lib/classes/Swift/Encoder/QpEncoder.php | 300 + .../classes/Swift/Encoder/Rfc2231Encoder.php | 90 + .../lib/classes/Swift/Events/CommandEvent.php | 64 + .../classes/Swift/Events/CommandListener.php | 24 + .../lib/classes/Swift/Events/Event.php | 38 + .../classes/Swift/Events/EventDispatcher.php | 83 + .../classes/Swift/Events/EventListener.php | 18 + .../lib/classes/Swift/Events/EventObject.php | 61 + .../classes/Swift/Events/ResponseEvent.php | 64 + .../classes/Swift/Events/ResponseListener.php | 24 + .../lib/classes/Swift/Events/SendEvent.php | 126 + .../lib/classes/Swift/Events/SendListener.php | 31 + .../Swift/Events/SimpleEventDispatcher.php | 143 + .../Swift/Events/TransportChangeEvent.php | 27 + .../Swift/Events/TransportChangeListener.php | 45 + .../Swift/Events/TransportExceptionEvent.php | 43 + .../Events/TransportExceptionListener.php | 24 + .../lib/classes/Swift/FailoverTransport.php | 33 + .../lib/classes/Swift/FileSpool.php | 208 + .../lib/classes/Swift/FileStream.php | 24 + .../lib/classes/Swift/Filterable.php | 32 + .../lib/classes/Swift/IdGenerator.php | 22 + .../swiftmailer/lib/classes/Swift/Image.php | 43 + .../lib/classes/Swift/InputByteStream.php | 75 + .../lib/classes/Swift/IoException.php | 28 + .../lib/classes/Swift/KeyCache.php | 105 + .../classes/Swift/KeyCache/ArrayKeyCache.php | 203 + .../classes/Swift/KeyCache/DiskKeyCache.php | 295 + .../Swift/KeyCache/KeyCacheInputStream.php | 51 + .../classes/Swift/KeyCache/NullKeyCache.php | 113 + .../KeyCache/SimpleKeyCacheInputStream.php | 123 + .../classes/Swift/LoadBalancedTransport.php | 33 + .../swiftmailer/lib/classes/Swift/Mailer.php | 98 + .../Swift/Mailer/ArrayRecipientIterator.php | 53 + .../Swift/Mailer/RecipientIterator.php | 32 + .../lib/classes/Swift/MemorySpool.php | 110 + .../swiftmailer/lib/classes/Swift/Message.php | 279 + .../lib/classes/Swift/Mime/Attachment.php | 144 + .../classes/Swift/Mime/CharsetObserver.php | 24 + .../lib/classes/Swift/Mime/ContentEncoder.php | 34 + .../ContentEncoder/Base64ContentEncoder.php | 101 + .../ContentEncoder/NativeQpContentEncoder.php | 123 + .../ContentEncoder/NullContentEncoder.php | 79 + .../ContentEncoder/PlainContentEncoder.php | 164 + .../Mime/ContentEncoder/QpContentEncoder.php | 134 + .../ContentEncoder/QpContentEncoderProxy.php | 96 + .../Mime/ContentEncoder/RawContentEncoder.php | 65 + .../lib/classes/Swift/Mime/EmbeddedFile.php | 41 + .../classes/Swift/Mime/EncodingObserver.php | 24 + .../lib/classes/Swift/Mime/Header.php | 93 + .../lib/classes/Swift/Mime/HeaderEncoder.php | 24 + .../HeaderEncoder/Base64HeaderEncoder.php | 55 + .../Mime/HeaderEncoder/QpHeaderEncoder.php | 65 + .../Swift/Mime/Headers/AbstractHeader.php | 476 + .../classes/Swift/Mime/Headers/DateHeader.php | 113 + .../Mime/Headers/IdentificationHeader.php | 186 + .../Swift/Mime/Headers/MailboxHeader.php | 360 + .../Swift/Mime/Headers/OpenDKIMHeader.php | 135 + .../Mime/Headers/ParameterizedHeader.php | 255 + .../classes/Swift/Mime/Headers/PathHeader.php | 155 + .../Swift/Mime/Headers/UnstructuredHeader.php | 109 + .../lib/classes/Swift/Mime/IdGenerator.php | 54 + .../lib/classes/Swift/Mime/MimePart.php | 199 + .../Swift/Mime/SimpleHeaderFactory.php | 195 + .../classes/Swift/Mime/SimpleHeaderSet.php | 399 + .../lib/classes/Swift/Mime/SimpleMessage.php | 642 + .../classes/Swift/Mime/SimpleMimeEntity.php | 820 + .../lib/classes/Swift/MimePart.php | 45 + .../lib/classes/Swift/NullTransport.php | 26 + .../lib/classes/Swift/OutputByteStream.php | 46 + .../classes/Swift/Plugins/AntiFloodPlugin.php | 137 + .../Swift/Plugins/BandwidthMonitorPlugin.php | 154 + .../Swift/Plugins/Decorator/Replacements.php | 31 + .../classes/Swift/Plugins/DecoratorPlugin.php | 200 + .../Swift/Plugins/ImpersonatePlugin.php | 65 + .../lib/classes/Swift/Plugins/Logger.php | 36 + .../classes/Swift/Plugins/LoggerPlugin.php | 126 + .../Swift/Plugins/Loggers/ArrayLogger.php | 72 + .../Swift/Plugins/Loggers/EchoLogger.php | 58 + .../classes/Swift/Plugins/MessageLogger.php | 70 + .../Swift/Plugins/Pop/Pop3Connection.php | 31 + .../Swift/Plugins/Pop/Pop3Exception.php | 27 + .../Swift/Plugins/PopBeforeSmtpPlugin.php | 254 + .../Swift/Plugins/RedirectingPlugin.php | 201 + .../lib/classes/Swift/Plugins/Reporter.php | 32 + .../classes/Swift/Plugins/ReporterPlugin.php | 57 + .../Swift/Plugins/Reporters/HitReporter.php | 58 + .../Swift/Plugins/Reporters/HtmlReporter.php | 38 + .../lib/classes/Swift/Plugins/Sleeper.php | 24 + .../classes/Swift/Plugins/ThrottlerPlugin.php | 196 + .../lib/classes/Swift/Plugins/Timer.php | 24 + .../lib/classes/Swift/Preferences.php | 100 + .../Swift/ReplacementFilterFactory.php | 27 + .../classes/Swift/RfcComplianceException.php | 27 + .../lib/classes/Swift/SendmailTransport.php | 33 + .../swiftmailer/lib/classes/Swift/Signer.php | 19 + .../lib/classes/Swift/Signers/BodySigner.php | 33 + .../lib/classes/Swift/Signers/DKIMSigner.php | 682 + .../classes/Swift/Signers/DomainKeySigner.php | 504 + .../classes/Swift/Signers/HeaderSigner.php | 65 + .../classes/Swift/Signers/OpenDKIMSigner.php | 183 + .../lib/classes/Swift/Signers/SMimeSigner.php | 542 + .../lib/classes/Swift/SmtpTransport.php | 42 + .../swiftmailer/lib/classes/Swift/Spool.php | 53 + .../lib/classes/Swift/SpoolTransport.php | 33 + .../lib/classes/Swift/StreamFilter.php | 35 + .../ByteArrayReplacementFilter.php | 166 + .../StreamFilters/StringReplacementFilter.php | 70 + .../StringReplacementFilterFactory.php | 45 + .../lib/classes/Swift/SwiftException.php | 28 + .../lib/classes/Swift/Transport.php | 79 + .../Swift/Transport/AbstractSmtpTransport.php | 543 + .../Esmtp/Auth/CramMd5Authenticator.php | 75 + .../Esmtp/Auth/LoginAuthenticator.php | 45 + .../Esmtp/Auth/NTLMAuthenticator.php | 681 + .../Esmtp/Auth/PlainAuthenticator.php | 44 + .../Esmtp/Auth/XOAuth2Authenticator.php | 64 + .../Swift/Transport/Esmtp/AuthHandler.php | 268 + .../Swift/Transport/Esmtp/Authenticator.php | 37 + .../Transport/Esmtp/EightBitMimeHandler.php | 113 + .../Swift/Transport/Esmtp/SmtpUtf8Handler.php | 107 + .../classes/Swift/Transport/EsmtpHandler.php | 86 + .../Swift/Transport/EsmtpTransport.php | 446 + .../Swift/Transport/FailoverTransport.php | 105 + .../lib/classes/Swift/Transport/IoBuffer.php | 67 + .../Swift/Transport/LoadBalancedTransport.php | 194 + .../classes/Swift/Transport/NullTransport.php | 98 + .../Swift/Transport/SendmailTransport.php | 158 + .../lib/classes/Swift/Transport/SmtpAgent.php | 36 + .../Swift/Transport/SpoolTransport.php | 120 + .../classes/Swift/Transport/StreamBuffer.php | 326 + .../lib/classes/Swift/TransportException.php | 28 + .../lib/dependency_maps/cache_deps.php | 23 + .../lib/dependency_maps/message_deps.php | 9 + .../lib/dependency_maps/mime_deps.php | 134 + .../lib/dependency_maps/transport_deps.php | 97 + .../swiftmailer/lib/mime_types.php | 1007 ++ .../swiftmailer/lib/preferences.php | 19 + .../swiftmailer/lib/swift_required.php | 22 + .../lib/swiftmailer_generate_mimes_config.php | 182 + .../swiftmailer/swiftmailer/phpunit.xml.dist | 38 + .../tests/IdenticalBinaryConstraint.php | 62 + .../swiftmailer/tests/StreamCollector.php | 11 + .../tests/SwiftMailerSmokeTestCase.php | 46 + .../swiftmailer/tests/SwiftMailerTestCase.php | 38 + .../_samples/charsets/iso-2022-jp/one.txt | 11 + .../_samples/charsets/iso-8859-1/one.txt | 19 + .../tests/_samples/charsets/utf-8/one.txt | 22 + .../tests/_samples/charsets/utf-8/three.txt | 45 + .../tests/_samples/charsets/utf-8/two.txt | 3 + .../tests/_samples/dkim/dkim.test.priv | 15 + .../tests/_samples/dkim/dkim.test.pub | 6 + .../swiftmailer/tests/_samples/files/data.txt | 1 + .../tests/_samples/files/swiftmailer.png | Bin 0 -> 3194 bytes .../tests/_samples/files/textfile.zip | Bin 0 -> 202 bytes .../swiftmailer/tests/_samples/smime/CA.srl | 1 + .../swiftmailer/tests/_samples/smime/ca.crt | 21 + .../swiftmailer/tests/_samples/smime/ca.key | 27 + .../tests/_samples/smime/create-cert.sh | 40 + .../tests/_samples/smime/encrypt.crt | 19 + .../tests/_samples/smime/encrypt.key | 27 + .../tests/_samples/smime/encrypt2.crt | 19 + .../tests/_samples/smime/encrypt2.key | 27 + .../tests/_samples/smime/intermediate.crt | 19 + .../tests/_samples/smime/intermediate.key | 27 + .../swiftmailer/tests/_samples/smime/sign.crt | 19 + .../swiftmailer/tests/_samples/smime/sign.key | 27 + .../tests/_samples/smime/sign2.crt | 19 + .../tests/_samples/smime/sign2.key | 27 + .../tests/acceptance.conf.php.default | 37 + .../Swift/AttachmentAcceptanceTest.php | 12 + .../FileByteStreamAcceptanceTest.php | 162 + ...leCharacterReaderFactoryAcceptanceTest.php | 179 + .../DependencyContainerAcceptanceTest.php | 22 + .../Swift/EmbeddedFileAcceptanceTest.php | 12 + .../Encoder/Base64EncoderAcceptanceTest.php | 45 + .../Swift/Encoder/QpEncoderAcceptanceTest.php | 54 + .../Encoder/Rfc2231EncoderAcceptanceTest.php | 50 + .../KeyCache/ArrayKeyCacheAcceptanceTest.php | 173 + .../KeyCache/DiskKeyCacheAcceptanceTest.php | 173 + .../Swift/MessageAcceptanceTest.php | 55 + .../Swift/Mime/AttachmentAcceptanceTest.php | 126 + .../Base64ContentEncoderAcceptanceTest.php | 56 + .../NativeQpContentEncoderAcceptanceTest.php | 88 + .../PlainContentEncoderAcceptanceTest.php | 88 + .../QpContentEncoderAcceptanceTest.php | 160 + .../Swift/Mime/EmbeddedFileAcceptanceTest.php | 139 + .../Base64HeaderEncoderAcceptanceTest.php | 32 + .../Swift/Mime/MimePartAcceptanceTest.php | 130 + .../Mime/SimpleMessageAcceptanceTest.php | 1250 ++ .../Swift/MimePartAcceptanceTest.php | 15 + .../AbstractStreamBufferAcceptanceTest.php | 131 + .../BasicSocketAcceptanceTest.php | 33 + .../StreamBuffer/ProcessAcceptanceTest.php | 26 + .../StreamBuffer/SocketTimeoutTest.php | 65 + .../StreamBuffer/SslSocketAcceptanceTest.php | 40 + .../StreamBuffer/TlsSocketAcceptanceTest.php | 39 + .../swiftmailer/tests/bootstrap.php | 21 + .../tests/bug/Swift/Bug111Test.php | 42 + .../tests/bug/Swift/Bug118Test.php | 20 + .../tests/bug/Swift/Bug206Test.php | 40 + .../tests/bug/Swift/Bug274Test.php | 25 + .../swiftmailer/tests/bug/Swift/Bug34Test.php | 75 + .../swiftmailer/tests/bug/Swift/Bug35Test.php | 73 + .../swiftmailer/tests/bug/Swift/Bug38Test.php | 192 + .../tests/bug/Swift/Bug518Test.php | 38 + .../swiftmailer/tests/bug/Swift/Bug51Test.php | 110 + .../tests/bug/Swift/Bug534Test.php | 38 + .../tests/bug/Swift/Bug650Test.php | 38 + .../swiftmailer/tests/bug/Swift/Bug71Test.php | 20 + .../swiftmailer/tests/bug/Swift/Bug76Test.php | 71 + ...FileByteStreamConsecutiveReadCallsTest.php | 18 + .../tests/fixtures/MimeEntityFixture.php | 67 + .../swiftmailer/tests/smoke.conf.php.default | 63 + .../smoke/Swift/Smoke/AttachmentSmokeTest.php | 33 + .../smoke/Swift/Smoke/BasicSmokeTest.php | 23 + .../Smoke/HtmlWithAttachmentSmokeTest.php | 33 + .../Swift/Smoke/InternationalSmokeTest.php | 40 + .../Swift/ByteStream/ArrayByteStreamTest.php | 202 + .../GenericFixedWidthReaderTest.php | 43 + .../CharacterReader/UsAsciiReaderTest.php | 52 + .../Swift/CharacterReader/Utf8ReaderTest.php | 65 + .../ArrayCharacterStreamTest.php | 361 + .../unit/Swift/DependencyContainerTest.php | 191 + .../unit/Swift/Encoder/Base64EncoderTest.php | 173 + .../unit/Swift/Encoder/QpEncoderTest.php | 400 + .../unit/Swift/Encoder/Rfc2231EncoderTest.php | 141 + .../unit/Swift/Events/CommandEventTest.php | 34 + .../unit/Swift/Events/EventObjectTest.php | 32 + .../unit/Swift/Events/ResponseEventTest.php | 38 + .../tests/unit/Swift/Events/SendEventTest.php | 96 + .../Events/SimpleEventDispatcherTest.php | 142 + .../Swift/Events/TransportChangeEventTest.php | 30 + .../Events/TransportExceptionEventTest.php | 41 + .../unit/Swift/KeyCache/ArrayKeyCacheTest.php | 240 + .../SimpleKeyCacheInputStreamTest.php | 73 + .../Mailer/ArrayRecipientIteratorTest.php | 42 + .../tests/unit/Swift/MailerTest.php | 145 + .../tests/unit/Swift/MessageTest.php | 133 + .../Swift/Mime/AbstractMimeEntityTest.php | 1092 ++ .../tests/unit/Swift/Mime/AttachmentTest.php | 321 + .../Base64ContentEncoderTest.php | 323 + .../PlainContentEncoderTest.php | 171 + .../ContentEncoder/QpContentEncoderTest.php | 516 + .../unit/Swift/Mime/EmbeddedFileTest.php | 59 + .../HeaderEncoder/Base64HeaderEncoderTest.php | 13 + .../HeaderEncoder/QpHeaderEncoderTest.php | 221 + .../Swift/Mime/Headers/DateHeaderTest.php | 90 + .../Mime/Headers/IdentificationHeaderTest.php | 192 + .../Swift/Mime/Headers/MailboxHeaderTest.php | 367 + .../Mime/Headers/ParameterizedHeaderTest.php | 396 + .../Swift/Mime/Headers/PathHeaderTest.php | 95 + .../Mime/Headers/UnstructuredHeaderTest.php | 353 + .../tests/unit/Swift/Mime/IdGeneratorTest.php | 32 + .../tests/unit/Swift/Mime/MimePartTest.php | 234 + .../Swift/Mime/SimpleHeaderFactoryTest.php | 169 + .../unit/Swift/Mime/SimpleHeaderSetTest.php | 734 + .../unit/Swift/Mime/SimpleMessageTest.php | 837 + .../unit/Swift/Mime/SimpleMimeEntityTest.php | 12 + .../Swift/Plugins/AntiFloodPluginTest.php | 93 + .../Plugins/BandwidthMonitorPluginTest.php | 128 + .../Swift/Plugins/DecoratorPluginTest.php | 284 + .../unit/Swift/Plugins/LoggerPluginTest.php | 188 + .../Swift/Plugins/Loggers/ArrayLoggerTest.php | 65 + .../Swift/Plugins/Loggers/EchoLoggerTest.php | 24 + .../Swift/Plugins/PopBeforeSmtpPluginTest.php | 101 + .../Swift/Plugins/RedirectingPluginTest.php | 183 + .../unit/Swift/Plugins/ReporterPluginTest.php | 86 + .../Plugins/Reporters/HitReporterTest.php | 64 + .../Plugins/Reporters/HtmlReporterTest.php | 54 + .../Swift/Plugins/ThrottlerPluginTest.php | 102 + .../unit/Swift/Signers/DKIMSignerTest.php | 220 + .../unit/Swift/Signers/OpenDKIMSignerTest.php | 45 + .../unit/Swift/Signers/SMimeSignerTest.php | 653 + .../ByteArrayReplacementFilterTest.php | 129 + .../StringReplacementFilterFactoryTest.php | 36 + .../StringReplacementFilterTest.php | 59 + .../AbstractSmtpEventSupportTest.php | 558 + .../unit/Swift/Transport/AbstractSmtpTest.php | 1400 ++ .../Esmtp/Auth/CramMd5AuthenticatorTest.php | 65 + .../Esmtp/Auth/LoginAuthenticatorTest.php | 65 + .../Esmtp/Auth/NTLMAuthenticatorTest.php | 204 + .../Esmtp/Auth/PlainAuthenticatorTest.php | 68 + .../Swift/Transport/Esmtp/AuthHandlerTest.php | 165 + .../EsmtpTransport/ExtensionSupportTest.php | 561 + .../Swift/Transport/EsmtpTransportTest.php | 651 + .../Swift/Transport/FailoverTransportTest.php | 600 + .../Transport/LoadBalancedTransportTest.php | 838 + .../Swift/Transport/SendmailTransportTest.php | 150 + .../unit/Swift/Transport/StreamBufferTest.php | 43 + .../vendor/symfony/polyfill-iconv/Iconv.php | 741 + .../vendor/symfony/polyfill-iconv/LICENSE | 19 + .../vendor/symfony/polyfill-iconv/README.md | 14 + .../Resources/charset/from.big5.php | 13719 ++++++++++++++++ .../Resources/charset/from.cp037.php | Bin 0 -> 3779 bytes .../Resources/charset/from.cp1006.php | Bin 0 -> 3860 bytes .../Resources/charset/from.cp1026.php | Bin 0 -> 3779 bytes .../Resources/charset/from.cp424.php | Bin 0 -> 3210 bytes .../Resources/charset/from.cp437.php | Bin 0 -> 3841 bytes .../Resources/charset/from.cp500.php | Bin 0 -> 3779 bytes .../Resources/charset/from.cp737.php | Bin 0 -> 3834 bytes .../Resources/charset/from.cp775.php | Bin 0 -> 3815 bytes .../Resources/charset/from.cp850.php | Bin 0 -> 3809 bytes .../Resources/charset/from.cp852.php | Bin 0 -> 3808 bytes .../Resources/charset/from.cp855.php | Bin 0 -> 3809 bytes .../Resources/charset/from.cp856.php | Bin 0 -> 3194 bytes .../Resources/charset/from.cp857.php | Bin 0 -> 3763 bytes .../Resources/charset/from.cp860.php | Bin 0 -> 3840 bytes .../Resources/charset/from.cp861.php | Bin 0 -> 3841 bytes .../Resources/charset/from.cp862.php | Bin 0 -> 3841 bytes .../Resources/charset/from.cp863.php | Bin 0 -> 3841 bytes .../Resources/charset/from.cp864.php | Bin 0 -> 3779 bytes .../Resources/charset/from.cp865.php | Bin 0 -> 3841 bytes .../Resources/charset/from.cp866.php | Bin 0 -> 3831 bytes .../Resources/charset/from.cp869.php | Bin 0 -> 3676 bytes .../Resources/charset/from.cp874.php | Bin 0 -> 3410 bytes .../Resources/charset/from.cp875.php | Bin 0 -> 3776 bytes .../Resources/charset/from.cp932.php | Bin 0 -> 134095 bytes .../Resources/charset/from.cp936.php | Bin 0 -> 372283 bytes .../Resources/charset/from.cp949.php | Bin 0 -> 291504 bytes .../Resources/charset/from.cp950.php | Bin 0 -> 231436 bytes .../Resources/charset/from.iso-8859-1.php | Bin 0 -> 3779 bytes .../Resources/charset/from.iso-8859-10.php | Bin 0 -> 3780 bytes .../Resources/charset/from.iso-8859-11.php | Bin 0 -> 3746 bytes .../Resources/charset/from.iso-8859-13.php | Bin 0 -> 3783 bytes .../Resources/charset/from.iso-8859-14.php | Bin 0 -> 3801 bytes .../Resources/charset/from.iso-8859-15.php | Bin 0 -> 3780 bytes .../Resources/charset/from.iso-8859-16.php | Bin 0 -> 3782 bytes .../Resources/charset/from.iso-8859-2.php | Bin 0 -> 3779 bytes .../Resources/charset/from.iso-8859-3.php | Bin 0 -> 3674 bytes .../Resources/charset/from.iso-8859-4.php | Bin 0 -> 3779 bytes .../Resources/charset/from.iso-8859-5.php | Bin 0 -> 3780 bytes .../Resources/charset/from.iso-8859-6.php | Bin 0 -> 3104 bytes .../Resources/charset/from.iso-8859-7.php | Bin 0 -> 3692 bytes .../Resources/charset/from.iso-8859-8.php | Bin 0 -> 3242 bytes .../Resources/charset/from.iso-8859-9.php | Bin 0 -> 3779 bytes .../Resources/charset/from.koi8-r.php | Bin 0 -> 3835 bytes .../Resources/charset/from.koi8-u.php | Bin 0 -> 3827 bytes .../Resources/charset/from.us-ascii.php | Bin 0 -> 1859 bytes .../Resources/charset/from.windows-1250.php | Bin 0 -> 3721 bytes .../Resources/charset/from.windows-1251.php | Bin 0 -> 3782 bytes .../Resources/charset/from.windows-1252.php | Bin 0 -> 3721 bytes .../Resources/charset/from.windows-1253.php | Bin 0 -> 3542 bytes .../Resources/charset/from.windows-1254.php | Bin 0 -> 3691 bytes .../Resources/charset/from.windows-1255.php | Bin 0 -> 3454 bytes .../Resources/charset/from.windows-1256.php | Bin 0 -> 3800 bytes .../Resources/charset/from.windows-1257.php | Bin 0 -> 3616 bytes .../Resources/charset/from.windows-1258.php | Bin 0 -> 3662 bytes .../Resources/charset/translit.php | 3969 +++++ .../symfony/polyfill-iconv/bootstrap.php | 44 + .../symfony/polyfill-iconv/composer.json | 34 + .../vendor/symfony/polyfill-intl-idn/Idn.php | 280 + .../vendor/symfony/polyfill-intl-idn/LICENSE | 19 + .../symfony/polyfill-intl-idn/README.md | 12 + .../symfony/polyfill-intl-idn/bootstrap.php | 59 + .../symfony/polyfill-intl-idn/composer.json | 36 + .../vendor/symfony/polyfill-mbstring/LICENSE | 19 + .../symfony/polyfill-mbstring/Mbstring.php | 800 + .../symfony/polyfill-mbstring/README.md | 13 + .../Resources/unidata/lowerCase.php | 1096 ++ .../Resources/unidata/titleCaseRegexp.php | 5 + .../Resources/unidata/upperCase.php | 1104 ++ .../symfony/polyfill-mbstring/bootstrap.php | 58 + .../symfony/polyfill-mbstring/composer.json | 34 + .../vendor/symfony/polyfill-php72/LICENSE | 19 + .../vendor/symfony/polyfill-php72/Php72.php | 216 + .../vendor/symfony/polyfill-php72/README.md | 27 + .../symfony/polyfill-php72/bootstrap.php | 36 + .../symfony/polyfill-php72/composer.json | 31 + user/plugins/error | 1 + user/plugins/form/.eslintrc | 165 + user/plugins/form/.gitignore | 5 + user/plugins/form/CHANGELOG.md | 900 + user/plugins/form/LICENSE | 21 + user/plugins/form/README.md | 29 + user/plugins/form/app/fields/array.js | 194 + user/plugins/form/app/fields/file.js | 340 + user/plugins/form/app/fields/form.js | 94 + user/plugins/form/app/fields/index.js | 7 + user/plugins/form/app/fields/media.js | 174 + user/plugins/form/app/fields/tabs.js | 14 + user/plugins/form/app/main.js | 4 + user/plugins/form/app/utils/keep-alive.js | 15 + user/plugins/form/assets/dropzone.min.css | 1 + user/plugins/form/assets/form-styles.css | 80 + user/plugins/form/assets/form-styles.min.css | 1 + user/plugins/form/assets/form.min.js | 41 + user/plugins/form/assets/form.vendor.js | 32 + .../form/assets/object.assign.polyfill.js | 29 + user/plugins/form/assets/signature_pad.js | 617 + user/plugins/form/blueprints.yaml | 197 + user/plugins/form/classes/Form.php | 1273 ++ user/plugins/form/classes/FormFactory.php | 40 + user/plugins/form/classes/Forms.php | 92 + user/plugins/form/composer.json | 40 + user/plugins/form/composer.lock | 71 + user/plugins/form/form.php | 1094 ++ user/plugins/form/form.yaml | 20 + user/plugins/form/gulpfile.js | 84 + user/plugins/form/hebe.json | 15 + user/plugins/form/languages.yaml | 760 + user/plugins/form/package.json | 46 + user/plugins/form/scss/form-styles.scss | 289 + .../form/templates/form-messages.html.twig | 2 + .../form/templates/form-messages.json.twig | 2 + user/plugins/form/templates/form.html.twig | 8 + user/plugins/form/templates/form.json.twig | 1 + .../plugins/form/templates/formdata.html.twig | 20 + .../form/templates/forms/ajax.json.twig | 5 + .../form/templates/forms/data.html.twig | 1 + .../form/templates/forms/data.txt.twig | 1 + .../templates/forms/default/data.html.twig | 48 + .../templates/forms/default/data.txt.twig | 19 + .../templates/forms/default/field.html.twig | 139 + .../templates/forms/default/fields.html.twig | 15 + .../templates/forms/default/form.html.twig | 134 + .../forms/default/toggleable.html.twig | 9 + .../forms/dropzone/template.html.twig | 39 + .../form/templates/forms/field.html.twig | 1 + .../forms/fields/array/array.html.twig | 99 + .../forms/fields/avatar/avatar.html.twig | 10 + .../forms/fields/captcha/captcha.html.twig | 96 + .../forms/fields/checkbox/checkbox.html.twig | 36 + .../fields/checkboxes/checkboxes.html.twig | 43 + .../forms/fields/color/color.html.twig | 6 + .../forms/fields/column/column.html.twig | 9 + .../forms/fields/columns/columns.html.twig | 9 + .../fields/conditional/conditional.html.twig | 21 + .../forms/fields/date/date.html.twig | 8 + .../forms/fields/date/edit_list.html.twig | 1 + .../forms/fields/datetime/datetime.html.twig | 2 + .../forms/fields/datetime/edit_list.html.twig | 1 + .../forms/fields/display/display.html.twig | 17 + .../forms/fields/email/email.html.twig | 7 + .../forms/fields/fieldset/fieldset.html.twig | 14 + .../forms/fields/file/file.html.twig | 119 + .../forms/fields/formname/formname.html.twig | 5 + .../forms/fields/formtask/formtask.html.twig | 8 + .../forms/fields/hidden/hidden.html.twig | 9 + .../forms/fields/honeypot/honeypot.html.twig | 12 + .../forms/fields/ignore/ignore.html.twig | 0 .../templates/forms/fields/key/key.html.twig | 26 + .../forms/fields/month/month.html.twig | 6 + .../forms/fields/number/number.html.twig | 9 + .../forms/fields/password/password.html.twig | 6 + .../forms/fields/radio/radio.html.twig | 23 + .../forms/fields/range/range.html.twig | 9 + .../forms/fields/section/section.html.twig | 21 + .../forms/fields/select/select.html.twig | 67 + .../select_optgroup/select_optgroup.html.twig | 42 + .../fields/signature/signature.html.twig | 105 + .../forms/fields/spacer/spacer.html.twig | 19 + .../forms/fields/switch/switch.html.twig | 1 + .../templates/forms/fields/tab/tab.html.twig | 9 + .../forms/fields/tabs/tabs.html.twig | 66 + .../templates/forms/fields/tel/tel.html.twig | 6 + .../forms/fields/text/edit_list.html.twig | 5 + .../forms/fields/text/text.html.twig | 41 + .../forms/fields/textarea/textarea.html.twig | 41 + .../forms/fields/time/edit_list.html.twig | 1 + .../forms/fields/time/time.html.twig | 6 + .../forms/fields/toggle/edit_list.html.twig | 5 + .../forms/fields/toggle/toggle.html.twig | 62 + .../forms/fields/uniqueid/uniqueid.html.twig | 5 + .../forms/fields/url/edit_list.html.twig | 1 + .../templates/forms/fields/url/url.html.twig | 6 + .../forms/fields/value/value.html.twig | 18 + .../forms/fields/week/week.html.twig | 6 + .../form/templates/forms/form.html.twig | 1 + .../form/templates/modular/form.html.twig | 4 + .../partials/form-messages.html.twig | 6 + .../partials/form-messages.json.twig | 3 + user/plugins/form/vendor/autoload.php | 7 + .../form/vendor/composer/ClassLoader.php | 445 + user/plugins/form/vendor/composer/LICENSE | 21 + .../vendor/composer/autoload_classmap.php | 10 + .../vendor/composer/autoload_namespaces.php | 9 + .../form/vendor/composer/autoload_psr4.php | 11 + .../form/vendor/composer/autoload_real.php | 52 + .../form/vendor/composer/autoload_static.php | 44 + .../form/vendor/composer/installed.json | 51 + .../.github/ISSUE_TEMPLATE/bug_report.md | 28 + .../form/vendor/google/recaptcha/.gitignore | 7 + .../form/vendor/google/recaptcha/.travis.yml | 33 + .../vendor/google/recaptcha/ARCHITECTURE.md | 64 + .../vendor/google/recaptcha/CONTRIBUTING.md | 49 + .../form/vendor/google/recaptcha/LICENSE | 29 + .../form/vendor/google/recaptcha/README.md | 140 + .../form/vendor/google/recaptcha/app.yaml | 8 + .../vendor/google/recaptcha/composer.json | 39 + .../recaptcha/examples/appengine-https.php | 42 + .../google/recaptcha/examples/config.php.dist | 46 + .../google/recaptcha/examples/examples.css | 37 + .../examples/google0afd8760fd68f119.html | 1 + .../google/recaptcha/examples/index.php | 79 + .../recaptcha-content-security-policy.php | 152 + .../recaptcha-v2-checkbox-explicit.php | 148 + .../examples/recaptcha-v2-checkbox.php | 139 + .../examples/recaptcha-v2-invisible.php | 141 + .../examples/recaptcha-v3-request-scores.php | 120 + .../examples/recaptcha-v3-verify.php | 59 + .../google/recaptcha/examples/robots.txt | 2 + .../vendor/google/recaptcha/phpunit.xml.dist | 20 + .../recaptcha/src/ReCaptcha/ReCaptcha.php | 269 + .../recaptcha/src/ReCaptcha/RequestMethod.php | 50 + .../src/ReCaptcha/RequestMethod/Curl.php | 82 + .../src/ReCaptcha/RequestMethod/CurlPost.php | 104 + .../src/ReCaptcha/RequestMethod/Post.php | 88 + .../src/ReCaptcha/RequestMethod/Socket.php | 112 + .../ReCaptcha/RequestMethod/SocketPost.php | 108 + .../src/ReCaptcha/RequestParameters.php | 111 + .../recaptcha/src/ReCaptcha/Response.php | 218 + .../vendor/google/recaptcha/src/autoload.php | 69 + .../tests/ReCaptcha/ReCaptchaTest.php | 198 + .../ReCaptcha/RequestMethod/CurlPostTest.php | 123 + .../ReCaptcha/RequestMethod/PostTest.php | 149 + .../RequestMethod/SocketPostTest.php | 136 + .../tests/ReCaptcha/RequestParametersTest.php | 70 + .../tests/ReCaptcha/ResponseTest.php | 173 + user/plugins/form/webpack.conf.js | 65 + user/plugins/form/yarn.lock | 6136 +++++++ user/plugins/login/.gitignore | 2 + user/plugins/login/CHANGELOG.md | 632 + user/plugins/login/LICENSE | 21 + user/plugins/login/README.md | 535 + user/plugins/login/blueprints.yaml | 421 + user/plugins/login/classes/Controller.php | 603 + .../login/classes/Events/UserLoginEvent.php | 352 + user/plugins/login/classes/Login.php | 650 + user/plugins/login/classes/LoginCache.php | 105 + user/plugins/login/classes/RateLimiter.php | 110 + .../login/classes/RememberMe/RememberMe.php | 43 + .../login/classes/RememberMe/TokenStorage.php | 172 + .../classes/TwoFactorAuth/BaconQrProvider.php | 32 + .../classes/TwoFactorAuth/TwoFactorAuth.php | 76 + .../login/cli/ChangePasswordCommand.php | 177 + .../login/cli/ChangeUserStateCommand.php | 157 + user/plugins/login/cli/LookupUserCommand.php | 94 + user/plugins/login/cli/NewUserCommand.php | 302 + user/plugins/login/composer.json | 45 + user/plugins/login/composer.lock | 210 + user/plugins/login/css/login.css | 86 + user/plugins/login/hebe.json | 15 + user/plugins/login/js/2fa.js | 34 + user/plugins/login/languages/de.yaml | 128 + user/plugins/login/languages/en.yaml | 136 + user/plugins/login/languages/es.yaml | 115 + user/plugins/login/languages/fr.yaml | 89 + user/plugins/login/languages/hr.yaml | 41 + user/plugins/login/languages/hu.yaml | 22 + user/plugins/login/languages/no.yaml | 62 + user/plugins/login/languages/ro.yaml | 86 + user/plugins/login/languages/ru.yaml | 134 + user/plugins/login/languages/uk.yaml | 134 + user/plugins/login/login.php | 1109 ++ user/plugins/login/login.yaml | 58 + user/plugins/login/pages/forgot.md | 21 + user/plugins/login/pages/login.md | 42 + user/plugins/login/pages/profile.md | 80 + user/plugins/login/pages/register.md | 58 + user/plugins/login/pages/reset.md | 35 + user/plugins/login/pages/unauthorized.md | 5 + user/plugins/login/templates/forgot.html.twig | 6 + .../fields/2fa_secret/2fa_secret.html.twig | 31 + user/plugins/login/templates/login.html.twig | 6 + user/plugins/login/templates/login.json.twig | 5 + .../templates/partials/forgot-form.html.twig | 21 + .../templates/partials/login-form.html.twig | 64 + .../templates/partials/login-status.html.twig | 5 + .../templates/partials/login-twofa.html.twig | 25 + .../templates/partials/reset-form.html.twig | 27 + .../plugins/login/templates/profile.html.twig | 9 + .../plugins/login/templates/profile.json.twig | 1 + .../login/templates/register.html.twig | 1 + user/plugins/login/templates/reset.html.twig | 8 + .../login/templates/unauthorized.html.twig | 1 + user/plugins/login/vendor/autoload.php | 7 + .../vendor/bacon/bacon-qr-code/.gitignore | 9 + .../vendor/bacon/bacon-qr-code/.travis.yml | 14 + .../vendor/bacon/bacon-qr-code/CHANGELOG.md | 37 + .../login/vendor/bacon/bacon-qr-code/LICENSE | 22 + .../vendor/bacon/bacon-qr-code/Module.php | 37 + .../vendor/bacon/bacon-qr-code/README.md | 24 + .../bacon/bacon-qr-code/autoload_classmap.php | 43 + .../bacon/bacon-qr-code/autoload_function.php | 12 + .../bacon/bacon-qr-code/autoload_register.php | 2 + .../vendor/bacon/bacon-qr-code/composer.json | 29 + .../src/BaconQrCode/Common/AbstractEnum.php | 115 + .../src/BaconQrCode/Common/BitArray.php | 435 + .../src/BaconQrCode/Common/BitMatrix.php | 350 + .../src/BaconQrCode/Common/BitUtils.php | 51 + .../BaconQrCode/Common/CharacterSetEci.php | 134 + .../src/BaconQrCode/Common/EcBlock.php | 65 + .../src/BaconQrCode/Common/EcBlocks.php | 101 + .../Common/ErrorCorrectionLevel.php | 62 + .../BaconQrCode/Common/FormatInformation.php | 236 + .../src/BaconQrCode/Common/Mode.php | 70 + .../BaconQrCode/Common/ReedSolomonCodec.php | 476 + .../src/BaconQrCode/Common/Version.php | 687 + .../src/BaconQrCode/Encoder/BlockPair.php | 64 + .../src/BaconQrCode/Encoder/ByteMatrix.php | 158 + .../src/BaconQrCode/Encoder/Encoder.php | 687 + .../src/BaconQrCode/Encoder/MaskUtil.php | 291 + .../src/BaconQrCode/Encoder/MatrixUtil.php | 580 + .../src/BaconQrCode/Encoder/QrCode.php | 201 + .../Exception/ExceptionInterface.php | 14 + .../Exception/InvalidArgumentException.php | 14 + .../Exception/OutOfBoundsException.php | 14 + .../Exception/RuntimeException.php | 14 + .../Exception/UnexpectedValueException.php | 14 + .../BaconQrCode/Exception/WriterException.php | 14 + .../src/BaconQrCode/Renderer/Color/Cmyk.php | 160 + .../Renderer/Color/ColorInterface.php | 37 + .../src/BaconQrCode/Renderer/Color/Gray.php | 84 + .../src/BaconQrCode/Renderer/Color/Rgb.php | 148 + .../Renderer/Image/AbstractRenderer.php | 338 + .../Image/Decorator/DecoratorInterface.php | 63 + .../Image/Decorator/FinderPattern.php | 210 + .../src/BaconQrCode/Renderer/Image/Eps.php | 152 + .../src/BaconQrCode/Renderer/Image/Png.php | 115 + .../Renderer/Image/RendererInterface.php | 61 + .../src/BaconQrCode/Renderer/Image/Svg.php | 146 + .../Renderer/RendererInterface.php | 26 + .../src/BaconQrCode/Renderer/Text/Html.php | 91 + .../src/BaconQrCode/Renderer/Text/Plain.php | 150 + .../bacon-qr-code/src/BaconQrCode/Writer.php | 105 + .../bacon-qr-code/src/Common/BitArray.php | 372 + .../bacon-qr-code/src/Common/BitMatrix.php | 313 + .../bacon-qr-code/src/Common/BitUtils.php | 41 + .../src/Common/CharacterSetEci.php | 180 + .../bacon-qr-code/src/Common/EcBlock.php | 49 + .../bacon-qr-code/src/Common/EcBlocks.php | 74 + .../src/Common/ErrorCorrectionLevel.php | 63 + .../src/Common/FormatInformation.php | 203 + .../bacon/bacon-qr-code/src/Common/Mode.php | 76 + .../src/Common/ReedSolomonCodec.php | 468 + .../bacon-qr-code/src/Common/Version.php | 596 + .../bacon-qr-code/src/Encoder/BlockPair.php | 58 + .../bacon-qr-code/src/Encoder/ByteMatrix.php | 150 + .../bacon-qr-code/src/Encoder/Encoder.php | 652 + .../bacon-qr-code/src/Encoder/MaskUtil.php | 271 + .../bacon-qr-code/src/Encoder/MatrixUtil.php | 513 + .../bacon-qr-code/src/Encoder/QrCode.php | 141 + .../src/Exception/ExceptionInterface.php | 10 + .../Exception/InvalidArgumentException.php | 8 + .../src/Exception/OutOfBoundsException.php | 8 + .../src/Exception/RuntimeException.php | 8 + .../Exception/UnexpectedValueException.php | 8 + .../src/Exception/WriterException.php | 8 + .../src/Renderer/Color/Alpha.php | 57 + .../bacon-qr-code/src/Renderer/Color/Cmyk.php | 103 + .../src/Renderer/Color/ColorInterface.php | 22 + .../bacon-qr-code/src/Renderer/Color/Gray.php | 46 + .../bacon-qr-code/src/Renderer/Color/Rgb.php | 88 + .../src/Renderer/Eye/CompositeEye.php | 38 + .../src/Renderer/Eye/EyeInterface.php | 26 + .../src/Renderer/Eye/ModuleEye.php | 54 + .../src/Renderer/Eye/SimpleCircleEye.php | 54 + .../src/Renderer/Eye/SquareEye.php | 53 + .../src/Renderer/Image/EpsImageBackEnd.php | 376 + .../Renderer/Image/ImageBackEndInterface.php | 87 + .../Renderer/Image/ImagickImageBackEnd.php | 339 + .../src/Renderer/Image/SvgImageBackEnd.php | 369 + .../Renderer/Image/TransformationMatrix.php | 67 + .../src/Renderer/ImageRenderer.php | 152 + .../src/Renderer/Module/DotsModule.php | 63 + .../src/Renderer/Module/EdgeIterator/Edge.php | 100 + .../Module/EdgeIterator/EdgeIterator.php | 169 + .../src/Renderer/Module/ModuleInterface.php | 18 + .../src/Renderer/Module/RoundnessModule.php | 129 + .../src/Renderer/Module/SquareModule.php | 47 + .../bacon-qr-code/src/Renderer/Path/Close.php | 29 + .../bacon-qr-code/src/Renderer/Path/Curve.php | 92 + .../src/Renderer/Path/EllipticArc.php | 278 + .../bacon-qr-code/src/Renderer/Path/Line.php | 41 + .../bacon-qr-code/src/Renderer/Path/Move.php | 41 + .../src/Renderer/Path/OperationInterface.php | 12 + .../bacon-qr-code/src/Renderer/Path/Path.php | 106 + .../src/Renderer/PlainTextRenderer.php | 86 + .../src/Renderer/RendererInterface.php | 11 + .../src/Renderer/RendererStyle/EyeFill.php | 74 + .../src/Renderer/RendererStyle/Fill.php | 168 + .../src/Renderer/RendererStyle/Gradient.php | 46 + .../Renderer/RendererStyle/GradientType.php | 22 + .../Renderer/RendererStyle/RendererStyle.php | 90 + .../vendor/bacon/bacon-qr-code/src/Writer.php | 68 + .../tests/BaconQrCode/Common/BitArrayTest.php | 201 + .../BaconQrCode/Common/BitMatrixTest.php | 119 + .../tests/BaconQrCode/Common/BitUtilsTest.php | 30 + .../Common/ErrorCorrectionLevelTest.php | 40 + .../Common/FormatInformationTest.php | 104 + .../tests/BaconQrCode/Common/ModeTest.php | 42 + .../Common/ReedSolomonCodecTest.php | 111 + .../tests/BaconQrCode/Common/VersionTest.php | 88 + .../tests/BaconQrCode/Encoder/EncoderTest.php | 468 + .../BaconQrCode/Encoder/MaskUtilTest.php | 281 + .../BaconQrCode/Encoder/MatrixUtilTest.php | 336 + .../BaconQrCode/Renderer/Text/HtmlTest.php | 99 + .../BaconQrCode/Renderer/Text/TextTest.php | 149 + .../bacon/bacon-qr-code/tests/bootstrap.php | 10 + .../bacon/bacon-qr-code/tests/phpunit.xml | 11 + .../login/vendor/birke/rememberme/.gitignore | 4 + .../login/vendor/birke/rememberme/LICENSE | 21 + .../login/vendor/birke/rememberme/README.md | 40 + .../vendor/birke/rememberme/composer.json | 24 + .../birke/rememberme/example/action.php | 119 + .../birke/rememberme/example/css/style.css | 157 + .../vendor/birke/rememberme/example/index.php | 42 + .../example/templates/cookie_was_stolen.php | 4 + .../rememberme/example/templates/login.php | 14 + .../example/templates/user_is_logged_in.php | 31 + .../login/vendor/birke/rememberme/phpunit.xml | 7 + .../src/Rememberme/Authenticator.php | 293 + .../rememberme/src/Rememberme/Cookie.php | 104 + .../rememberme/src/Rememberme/Storage/DB.php | 145 + .../src/Rememberme/Storage/File.php | 119 + .../rememberme/src/Rememberme/Storage/PDO.php | 121 + .../Rememberme/Storage/StorageInterface.php | 66 + .../birke/rememberme/test/CookieTest.php | 31 + .../birke/rememberme/test/RemembermeTest.php | 352 + .../birke/rememberme/test/Storage/PDO.php | 98 + .../birke/rememberme/test/Storage/tokens.xml | 8 + .../birke/rememberme/test/bootstrap.php | 3 + .../login/vendor/composer/ClassLoader.php | 445 + user/plugins/login/vendor/composer/LICENSE | 21 + .../vendor/composer/autoload_classmap.php | 9 + .../login/vendor/composer/autoload_files.php | 10 + .../vendor/composer/autoload_namespaces.php | 10 + .../login/vendor/composer/autoload_psr4.php | 12 + .../login/vendor/composer/autoload_real.php | 70 + .../login/vendor/composer/autoload_static.php | 62 + .../login/vendor/composer/installed.json | 200 + .../login/vendor/dasprid/enum/.coveralls.yml | 2 + .../login/vendor/dasprid/enum/.gitignore | 3 + .../login/vendor/dasprid/enum/.travis.yml | 41 + .../login/vendor/dasprid/enum/README.md | 164 + .../login/vendor/dasprid/enum/composer.json | 30 + .../login/vendor/dasprid/enum/phpcs.xml | 30 + .../vendor/dasprid/enum/phpunit.xml.dist | 17 + .../vendor/dasprid/enum/src/AbstractEnum.php | 241 + .../login/vendor/dasprid/enum/src/EnumMap.php | 375 + .../Exception/CloneNotSupportedException.php | 10 + .../enum/src/Exception/ExceptionInterface.php | 10 + .../src/Exception/ExpectationException.php | 10 + .../Exception/IllegalArgumentException.php | 10 + .../enum/src/Exception/MismatchException.php | 10 + .../SerializeNotSupportedException.php | 10 + .../UnserializeNotSupportedException.php | 10 + .../vendor/dasprid/enum/src/NullValue.php | 55 + .../dasprid/enum/test/AbstractEnumTest.php | 121 + .../vendor/dasprid/enum/test/EnumMapTest.php | 243 + .../dasprid/enum/test/NullValueTest.php | 31 + .../login/vendor/dasprid/enum/test/Planet.php | 73 + .../vendor/dasprid/enum/test/WeekDay.php | 26 + .../paragonie/random_compat/CHANGELOG.md | 290 + .../vendor/paragonie/random_compat/LICENSE | 22 + .../paragonie/random_compat/RATIONALE.md | 42 + .../vendor/paragonie/random_compat/README.md | 176 + .../paragonie/random_compat/SECURITY.md | 108 + .../paragonie/random_compat/build-phar.sh | 5 + .../paragonie/random_compat/composer.json | 35 + .../dist/random_compat.phar.pubkey | 5 + .../dist/random_compat.phar.pubkey.asc | 11 + .../random_compat/lib/byte_safe_strings.php | 181 + .../random_compat/lib/cast_to_int.php | 74 + .../random_compat/lib/error_polyfill.php | 49 + .../paragonie/random_compat/lib/random.php | 247 + .../lib/random_bytes_com_dotnet.php | 88 + .../lib/random_bytes_dev_urandom.php | 150 + .../lib/random_bytes_libsodium.php | 88 + .../lib/random_bytes_libsodium_legacy.php | 92 + .../random_compat/lib/random_bytes_mcrypt.php | 77 + .../lib/random_bytes_openssl.php | 86 + .../random_compat/lib/random_int.php | 190 + .../random_compat/other/build_phar.php | 57 + .../random_compat/other/ide_stubs/COM.php | 20 + .../random_compat/other/ide_stubs/README.md | 7 + .../other/ide_stubs/com_exception.php | 11 + .../other/ide_stubs/libsodium.php | 90 + .../random_compat/psalm-autoload.php | 9 + .../vendor/paragonie/random_compat/psalm.xml | 15 + .../vendor/robthree/twofactorauth/.gitignore | 189 + .../vendor/robthree/twofactorauth/.travis.yml | 18 + .../vendor/robthree/twofactorauth/LICENSE | 22 + .../vendor/robthree/twofactorauth/README.md | 197 + .../twofactorauth/TwoFactorAuth.phpproj | 69 + .../robthree/twofactorauth/TwoFactorAuth.sln | 22 + .../robthree/twofactorauth/composer.json | 36 + .../robthree/twofactorauth/composer.lock | 980 ++ .../robthree/twofactorauth/demo/demo.php | 35 + .../robthree/twofactorauth/demo/loader.php | 50 + .../Providers/Qr/BaseHTTPQRCodeProvider.php | 27 + .../lib/Providers/Qr/GoogleQRCodeProvider.php | 39 + .../lib/Providers/Qr/IQRCodeProvider.php | 9 + .../lib/Providers/Qr/QRException.php | 5 + .../lib/Providers/Qr/QRServerProvider.php | 71 + .../lib/Providers/Qr/QRicketProvider.php | 54 + .../lib/Providers/Rng/CSRNGProvider.php | 14 + .../lib/Providers/Rng/HashRNGProvider.php | 28 + .../lib/Providers/Rng/IRNGProvider.php | 9 + .../lib/Providers/Rng/MCryptRNGProvider.php | 23 + .../lib/Providers/Rng/OpenSSLRNGProvider.php | 25 + .../lib/Providers/Rng/RNGException.php | 5 + .../ConvertUnixTimeDotComTimeProvider.php | 15 + .../lib/Providers/Time/HttpTimeProvider.php | 54 + .../lib/Providers/Time/ITimeProvider.php | 8 + .../Time/LocalMachineTimeProvider.php | 9 + .../lib/Providers/Time/TimeException.php | 5 + .../twofactorauth/lib/TwoFactorAuth.php | 249 + .../lib/TwoFactorAuthException.php | 7 + .../vendor/robthree/twofactorauth/logo.png | Bin 0 -> 2636 bytes .../multifactorauthforeveryone.png | Bin 0 -> 20735 bytes .../twofactorauth/tests/TwoFactorAuthTest.php | 381 + user/plugins/markdown-notices | 1 + user/plugins/problems | 1 + user/plugins/sitemap/.gitignore | 1 + user/plugins/sitemap/CHANGELOG.md | 101 + user/plugins/sitemap/LICENSE | 21 + user/plugins/sitemap/README.md | 66 + user/plugins/sitemap/blueprints.yaml | 91 + user/plugins/sitemap/blueprints/sitemap.yaml | 47 + user/plugins/sitemap/classes/sitemapentry.php | 11 + user/plugins/sitemap/hebe.json | 15 + user/plugins/sitemap/languages.yaml | 71 + user/plugins/sitemap/pages/sitemap.md | 3 + user/plugins/sitemap/sitemap.php | 158 + user/plugins/sitemap/sitemap.xsl | 107 + user/plugins/sitemap/sitemap.yaml | 4 + .../sitemap/templates/sitemap.xml.twig | 21 + user/plugins/taxonomylist/.gitignore | 1 + user/plugins/taxonomylist/CHANGELOG.md | 74 + user/plugins/taxonomylist/LICENSE | 21 + user/plugins/taxonomylist/README.md | 64 + user/plugins/taxonomylist/assets/readme_1.png | Bin 0 -> 12888 bytes user/plugins/taxonomylist/blueprints.yaml | 34 + .../taxonomylist/classes/taxonomylist.php | 88 + user/plugins/taxonomylist/hebe.json | 15 + user/plugins/taxonomylist/taxonomylist.php | 58 + user/plugins/taxonomylist/taxonomylist.yaml | 2 + .../templates/partials/taxonomylist.html.twig | 10 + 1860 files changed, 225261 insertions(+), 2 deletions(-) create mode 100644 user/plugins/admin/.editorconfig create mode 100644 user/plugins/admin/.gitattributes create mode 100644 user/plugins/admin/.github/FUNDING.yml create mode 100644 user/plugins/admin/.gitignore create mode 100644 user/plugins/admin/CHANGELOG.md create mode 100644 user/plugins/admin/CONTRIBUTING.md create mode 100644 user/plugins/admin/LICENSE create mode 100644 user/plugins/admin/README.md create mode 100644 user/plugins/admin/admin.php create mode 100644 user/plugins/admin/admin.yaml create mode 100644 user/plugins/admin/assets/admin-dashboard.png create mode 100644 user/plugins/admin/blueprints.yaml create mode 100644 user/plugins/admin/blueprints/admin/pages/modular_new.yaml create mode 100644 user/plugins/admin/blueprints/admin/pages/modular_raw.yaml create mode 100644 user/plugins/admin/blueprints/admin/pages/move.yaml create mode 100644 user/plugins/admin/blueprints/admin/pages/new.yaml create mode 100644 user/plugins/admin/blueprints/admin/pages/new_folder.yaml create mode 100644 user/plugins/admin/blueprints/admin/pages/raw.yaml create mode 100644 user/plugins/admin/blueprints/config/media.yaml create mode 100644 user/plugins/admin/classes/Twig/AdminTwigExtension.php create mode 100644 user/plugins/admin/classes/admin.php create mode 100644 user/plugins/admin/classes/adminbasecontroller.php create mode 100644 user/plugins/admin/classes/admincontroller.php create mode 100644 user/plugins/admin/classes/gpm.php create mode 100644 user/plugins/admin/classes/popularity.php create mode 100644 user/plugins/admin/classes/themes.php create mode 100644 user/plugins/admin/classes/utils.php create mode 100644 user/plugins/admin/codeception.yml create mode 100644 user/plugins/admin/composer.json create mode 100644 user/plugins/admin/composer.lock create mode 100644 user/plugins/admin/hebe.json create mode 100644 user/plugins/admin/languages/ar.yaml create mode 100644 user/plugins/admin/languages/bg.yaml create mode 100644 user/plugins/admin/languages/br.yaml create mode 100644 user/plugins/admin/languages/ca.yaml create mode 100644 user/plugins/admin/languages/cs.yaml create mode 100644 user/plugins/admin/languages/cy.yaml create mode 100644 user/plugins/admin/languages/da.yaml create mode 100644 user/plugins/admin/languages/de.yaml create mode 100644 user/plugins/admin/languages/el.yaml create mode 100644 user/plugins/admin/languages/en.yaml create mode 100644 user/plugins/admin/languages/es.yaml create mode 100644 user/plugins/admin/languages/et.yaml create mode 100644 user/plugins/admin/languages/eu.yaml create mode 100644 user/plugins/admin/languages/fa.yaml create mode 100644 user/plugins/admin/languages/fi.yaml create mode 100644 user/plugins/admin/languages/fr.yaml create mode 100644 user/plugins/admin/languages/he.yaml create mode 100644 user/plugins/admin/languages/hr.yaml create mode 100644 user/plugins/admin/languages/hu.yaml create mode 100644 user/plugins/admin/languages/id.yaml create mode 100644 user/plugins/admin/languages/it.yaml create mode 100644 user/plugins/admin/languages/ja.yaml create mode 100644 user/plugins/admin/languages/ko.yaml create mode 100644 user/plugins/admin/languages/lt.yaml create mode 100644 user/plugins/admin/languages/nl.yaml create mode 100644 user/plugins/admin/languages/no.yaml create mode 100644 user/plugins/admin/languages/pl.yaml create mode 100644 user/plugins/admin/languages/pt.yaml create mode 100644 user/plugins/admin/languages/ro.yaml create mode 100644 user/plugins/admin/languages/ru.yaml create mode 100644 user/plugins/admin/languages/sk.yaml create mode 100644 user/plugins/admin/languages/sl.yaml create mode 100644 user/plugins/admin/languages/sr.yaml create mode 100644 user/plugins/admin/languages/sv.yaml create mode 100644 user/plugins/admin/languages/th.yaml create mode 100644 user/plugins/admin/languages/tlh.yaml create mode 100644 user/plugins/admin/languages/tr.yaml create mode 100644 user/plugins/admin/languages/uk.yaml create mode 100644 user/plugins/admin/languages/vi.yaml create mode 100644 user/plugins/admin/languages/zh-tw.yaml create mode 100644 user/plugins/admin/languages/zh.yaml create mode 100644 user/plugins/admin/pages/admin/ajax.md create mode 100644 user/plugins/admin/pages/admin/backup.md create mode 100644 user/plugins/admin/pages/admin/cache.md create mode 100644 user/plugins/admin/pages/admin/config.md create mode 100644 user/plugins/admin/pages/admin/dashboard.md create mode 100644 user/plugins/admin/pages/admin/denied.md create mode 100644 user/plugins/admin/pages/admin/error.md create mode 100644 user/plugins/admin/pages/admin/feed.md create mode 100644 user/plugins/admin/pages/admin/forgot.md create mode 100644 user/plugins/admin/pages/admin/info.md create mode 100644 user/plugins/admin/pages/admin/installer.md create mode 100644 user/plugins/admin/pages/admin/login.md create mode 100644 user/plugins/admin/pages/admin/media.md create mode 100644 user/plugins/admin/pages/admin/notifications.md create mode 100644 user/plugins/admin/pages/admin/pages-filter.md create mode 100644 user/plugins/admin/pages/admin/pages.md create mode 100644 user/plugins/admin/pages/admin/plugins.md create mode 100644 user/plugins/admin/pages/admin/preview.md create mode 100644 user/plugins/admin/pages/admin/register.md create mode 100644 user/plugins/admin/pages/admin/reset.md create mode 100644 user/plugins/admin/pages/admin/site.md create mode 100644 user/plugins/admin/pages/admin/statistics.md create mode 100644 user/plugins/admin/pages/admin/system.md create mode 100644 user/plugins/admin/pages/admin/themes.md create mode 100644 user/plugins/admin/pages/admin/tools.md create mode 100644 user/plugins/admin/pages/admin/update.md create mode 100644 user/plugins/admin/pages/admin/user.md create mode 100644 user/plugins/admin/tests/_bootstrap.php create mode 100644 user/plugins/admin/tests/_support/Helper/Unit.php create mode 100644 user/plugins/admin/tests/_support/UnitTester.php create mode 100644 user/plugins/admin/tests/unit.suite.yml create mode 100644 user/plugins/admin/tests/unit/_bootstrap.php create mode 100644 user/plugins/admin/tests/unit/classes/controllerTest.php create mode 100644 user/plugins/admin/themes/grav/.eslintrc create mode 100644 user/plugins/admin/themes/grav/app/dashboard/backup.js create mode 100644 user/plugins/admin/themes/grav/app/dashboard/cache.js create mode 100644 user/plugins/admin/themes/grav/app/dashboard/chart.js create mode 100644 user/plugins/admin/themes/grav/app/dashboard/index.js create mode 100644 user/plugins/admin/themes/grav/app/dashboard/update.js create mode 100644 user/plugins/admin/themes/grav/app/forms/fields/array.js create mode 100644 user/plugins/admin/themes/grav/app/forms/fields/collections.js create mode 100644 user/plugins/admin/themes/grav/app/forms/fields/colorpicker.js create mode 100644 user/plugins/admin/themes/grav/app/forms/fields/cron.js create mode 100644 user/plugins/admin/themes/grav/app/forms/fields/datetime.js create mode 100644 user/plugins/admin/themes/grav/app/forms/fields/editor.js create mode 100644 user/plugins/admin/themes/grav/app/forms/fields/editor/buttons.js create mode 100644 user/plugins/admin/themes/grav/app/forms/fields/filepicker.js create mode 100644 user/plugins/admin/themes/grav/app/forms/fields/files.js create mode 100644 user/plugins/admin/themes/grav/app/forms/fields/iconpicker.js create mode 100644 user/plugins/admin/themes/grav/app/forms/fields/index.js create mode 100644 user/plugins/admin/themes/grav/app/forms/fields/mediapicker.js create mode 100644 user/plugins/admin/themes/grav/app/forms/fields/multilevel.js create mode 100644 user/plugins/admin/themes/grav/app/forms/fields/selectize.js create mode 100644 user/plugins/admin/themes/grav/app/forms/fields/selectunique.js create mode 100644 user/plugins/admin/themes/grav/app/forms/fields/text.js create mode 100644 user/plugins/admin/themes/grav/app/forms/form.js create mode 100644 user/plugins/admin/themes/grav/app/forms/index.js create mode 100644 user/plugins/admin/themes/grav/app/forms/state.js create mode 100644 user/plugins/admin/themes/grav/app/main.js create mode 100644 user/plugins/admin/themes/grav/app/media/index.js create mode 100644 user/plugins/admin/themes/grav/app/pages/filter.js create mode 100644 user/plugins/admin/themes/grav/app/pages/index.js create mode 100644 user/plugins/admin/themes/grav/app/pages/page/add.js create mode 100644 user/plugins/admin/themes/grav/app/pages/page/delete.js create mode 100644 user/plugins/admin/themes/grav/app/pages/page/disable-buttons.js create mode 100644 user/plugins/admin/themes/grav/app/pages/page/index.js create mode 100644 user/plugins/admin/themes/grav/app/pages/page/media.js create mode 100644 user/plugins/admin/themes/grav/app/pages/page/move.js create mode 100644 user/plugins/admin/themes/grav/app/pages/page/multilang.js create mode 100644 user/plugins/admin/themes/grav/app/pages/page/unset.js create mode 100644 user/plugins/admin/themes/grav/app/pages/tree.js create mode 100644 user/plugins/admin/themes/grav/app/plugins/index.js create mode 100644 user/plugins/admin/themes/grav/app/themes/index.js create mode 100644 user/plugins/admin/themes/grav/app/tools/index.js create mode 100644 user/plugins/admin/themes/grav/app/tools/logs.js create mode 100644 user/plugins/admin/themes/grav/app/updates/channel-switcher.js create mode 100644 user/plugins/admin/themes/grav/app/updates/check.js create mode 100644 user/plugins/admin/themes/grav/app/updates/feed.js create mode 100644 user/plugins/admin/themes/grav/app/updates/index.js create mode 100644 user/plugins/admin/themes/grav/app/updates/notifications.js create mode 100644 user/plugins/admin/themes/grav/app/updates/update.js create mode 100644 user/plugins/admin/themes/grav/app/utils/2fa.js create mode 100644 user/plugins/admin/themes/grav/app/utils/bootstrap-collapse.js create mode 100644 user/plugins/admin/themes/grav/app/utils/bootstrap-transition.js create mode 100644 user/plugins/admin/themes/grav/app/utils/colors.js create mode 100644 user/plugins/admin/themes/grav/app/utils/cron-ui.js create mode 100644 user/plugins/admin/themes/grav/app/utils/formatbytes.js create mode 100644 user/plugins/admin/themes/grav/app/utils/gpm.js create mode 100644 user/plugins/admin/themes/grav/app/utils/jquery-utils.js create mode 100644 user/plugins/admin/themes/grav/app/utils/keepalive.js create mode 100644 user/plugins/admin/themes/grav/app/utils/offline.js create mode 100644 user/plugins/admin/themes/grav/app/utils/packages.js create mode 100644 user/plugins/admin/themes/grav/app/utils/request.js create mode 100644 user/plugins/admin/themes/grav/app/utils/response.js create mode 100644 user/plugins/admin/themes/grav/app/utils/scrollbar.js create mode 100644 user/plugins/admin/themes/grav/app/utils/selectize-option-click.js create mode 100644 user/plugins/admin/themes/grav/app/utils/selectize-required-fix.js create mode 100644 user/plugins/admin/themes/grav/app/utils/sidebar.js create mode 100644 user/plugins/admin/themes/grav/app/utils/storage.js create mode 100644 user/plugins/admin/themes/grav/app/utils/tabs-memory.js create mode 100644 user/plugins/admin/themes/grav/app/utils/toastr.js create mode 100644 user/plugins/admin/themes/grav/css-compiled/fonts.css create mode 100644 user/plugins/admin/themes/grav/css-compiled/fonts.css.map create mode 100644 user/plugins/admin/themes/grav/css-compiled/nucleus.css create mode 100644 user/plugins/admin/themes/grav/css-compiled/nucleus.css.map create mode 100644 user/plugins/admin/themes/grav/css-compiled/preset.css create mode 100644 user/plugins/admin/themes/grav/css-compiled/preset.css.map create mode 100644 user/plugins/admin/themes/grav/css-compiled/simple-fonts.css create mode 100644 user/plugins/admin/themes/grav/css-compiled/simple-fonts.css.map create mode 100644 user/plugins/admin/themes/grav/css-compiled/template.css create mode 100644 user/plugins/admin/themes/grav/css-compiled/template.css.map create mode 100644 user/plugins/admin/themes/grav/css/chartist.min.css create mode 100644 user/plugins/admin/themes/grav/css/codemirror/base16-light.css create mode 100644 user/plugins/admin/themes/grav/css/codemirror/codemirror.css create mode 100644 user/plugins/admin/themes/grav/css/codemirror/paper.css create mode 100644 user/plugins/admin/themes/grav/css/featherlight.min.css create mode 100644 user/plugins/admin/themes/grav/css/fork-awesome.min.css create mode 100644 user/plugins/admin/themes/grav/css/hint.base.min.css create mode 100644 user/plugins/admin/themes/grav/css/iconpicker.css create mode 100644 user/plugins/admin/themes/grav/css/nucleus-ie10.css create mode 100644 user/plugins/admin/themes/grav/css/nucleus-ie9.css create mode 100644 user/plugins/admin/themes/grav/css/prism.css create mode 100644 user/plugins/admin/themes/grav/css/pure-0.5.0/grids-min.css create mode 100644 user/plugins/admin/themes/grav/css/selectize.min.css create mode 100644 user/plugins/admin/themes/grav/fonts/forkawesome-webfont.eot create mode 100644 user/plugins/admin/themes/grav/fonts/forkawesome-webfont.svg create mode 100644 user/plugins/admin/themes/grav/fonts/forkawesome-webfont.ttf create mode 100644 user/plugins/admin/themes/grav/fonts/forkawesome-webfont.woff create mode 100644 user/plugins/admin/themes/grav/fonts/forkawesome-webfont.woff2 create mode 100644 user/plugins/admin/themes/grav/fonts/rockettheme-apps/rockettheme-apps.eot create mode 100644 user/plugins/admin/themes/grav/fonts/rockettheme-apps/rockettheme-apps.svg create mode 100644 user/plugins/admin/themes/grav/fonts/rockettheme-apps/rockettheme-apps.ttf create mode 100644 user/plugins/admin/themes/grav/fonts/rockettheme-apps/rockettheme-apps.woff create mode 100644 user/plugins/admin/themes/grav/gulpfile.js create mode 100644 user/plugins/admin/themes/grav/images/favicon.png create mode 100644 user/plugins/admin/themes/grav/images/grav-regular.svg create mode 100644 user/plugins/admin/themes/grav/images/grav-small.svg create mode 100644 user/plugins/admin/themes/grav/images/logo.svg create mode 100644 user/plugins/admin/themes/grav/images/transparent.png create mode 100644 user/plugins/admin/themes/grav/js/admin.min.js create mode 100644 user/plugins/admin/themes/grav/js/form-attr.polyfill.js create mode 100644 user/plugins/admin/themes/grav/js/vendor.min.js create mode 100644 user/plugins/admin/themes/grav/package.json create mode 100644 user/plugins/admin/themes/grav/scss.sh create mode 100644 user/plugins/admin/themes/grav/scss/configuration/fonts/_support.scss create mode 100644 user/plugins/admin/themes/grav/scss/configuration/nucleus/_base.scss create mode 100644 user/plugins/admin/themes/grav/scss/configuration/nucleus/_breakpoints.scss create mode 100644 user/plugins/admin/themes/grav/scss/configuration/nucleus/_core.scss create mode 100644 user/plugins/admin/themes/grav/scss/configuration/nucleus/_layout.scss create mode 100644 user/plugins/admin/themes/grav/scss/configuration/nucleus/_nav.scss create mode 100644 user/plugins/admin/themes/grav/scss/configuration/nucleus/_typography.scss create mode 100644 user/plugins/admin/themes/grav/scss/configuration/template/_base.scss create mode 100644 user/plugins/admin/themes/grav/scss/configuration/template/_colors.scss create mode 100644 user/plugins/admin/themes/grav/scss/configuration/template/_variables.scss create mode 100644 user/plugins/admin/themes/grav/scss/fonts.scss create mode 100644 user/plugins/admin/themes/grav/scss/nucleus.scss create mode 100644 user/plugins/admin/themes/grav/scss/nucleus/_core.scss create mode 100644 user/plugins/admin/themes/grav/scss/nucleus/_flex.scss create mode 100644 user/plugins/admin/themes/grav/scss/nucleus/_forms.scss create mode 100644 user/plugins/admin/themes/grav/scss/nucleus/_typography.scss create mode 100644 user/plugins/admin/themes/grav/scss/nucleus/functions/_base.scss create mode 100644 user/plugins/admin/themes/grav/scss/nucleus/functions/_direction.scss create mode 100644 user/plugins/admin/themes/grav/scss/nucleus/functions/_range.scss create mode 100644 user/plugins/admin/themes/grav/scss/nucleus/mixins/_base.scss create mode 100644 user/plugins/admin/themes/grav/scss/nucleus/mixins/_breakpoints.scss create mode 100644 user/plugins/admin/themes/grav/scss/nucleus/mixins/_utilities.scss create mode 100644 user/plugins/admin/themes/grav/scss/nucleus/particles/_align-text.scss create mode 100644 user/plugins/admin/themes/grav/scss/nucleus/particles/_visibility.scss create mode 100644 user/plugins/admin/themes/grav/scss/preset.scss create mode 100644 user/plugins/admin/themes/grav/scss/simple-fonts.scss create mode 100644 user/plugins/admin/themes/grav/scss/template.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_admin.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_buttons.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_colors.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_core.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_custom.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_dropzone.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_editor.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_errors.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_extensions.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_fonts.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_forms.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_gpm.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_header.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_jqcron.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_login.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_media.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_nav-toggle.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_notifications.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_pages.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_phpinfo.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_remodal.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_tables.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_tabs.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_toastr.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_tools.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_typography.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/_utilities.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/modules/_base.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/modules/_bourbon_essentials.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/modules/_buttons.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/modules/_colorpicker.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/modules/_datetimepicker.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/modules/_input-range.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/modules/_scrollbars.scss create mode 100644 user/plugins/admin/themes/grav/scss/template/modules/_toggle-switch.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/_bourbon-deprecated-upcoming.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/_bourbon.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/addons/_button.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/addons/_clearfix.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/addons/_directional-values.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/addons/_ellipsis.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/addons/_font-family.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/addons/_hide-text.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/addons/_html5-input-types.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/addons/_position.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/addons/_prefixer.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/addons/_rem.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/addons/_retina-image.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/addons/_size.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/addons/_timing-functions.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/addons/_triangle.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/addons/_word-wrap.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_animation.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_appearance.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_backface-visibility.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_background-image.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_background.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_border-image.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_border-radius.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_box-sizing.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_calc.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_columns.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_filter.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_flex-box.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_font-face.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_font-feature-settings.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_hidpi-media-query.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_hyphens.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_image-rendering.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_keyframes.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_linear-gradient.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_perspective.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_placeholder.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_radial-gradient.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_transform.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_transition.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/css3/_user-select.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/functions/_assign.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/functions/_color-lightness.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/functions/_flex-grid.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/functions/_golden-ratio.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/functions/_grid-width.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/functions/_modular-scale.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/functions/_px-to-em.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/functions/_px-to-rem.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/functions/_strip-units.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/functions/_tint-shade.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/functions/_transition-property-name.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/functions/_unpack.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/helpers/_convert-units.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/helpers/_gradient-positions-parser.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/helpers/_is-num.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/helpers/_linear-angle-parser.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/helpers/_linear-gradient-parser.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/helpers/_linear-positions-parser.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/helpers/_linear-side-corner-parser.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/helpers/_radial-arg-parser.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/helpers/_radial-gradient-parser.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/helpers/_radial-positions-parser.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/helpers/_render-gradients.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/helpers/_shape-size-stripper.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/helpers/_str-to-num.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/settings/_prefixer.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/bourbon/settings/_px-to-em.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/color-schemer/_color-schemer.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/color-schemer/color-schemer/_cmyk.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/color-schemer/color-schemer/_color-adjustments.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/color-schemer/color-schemer/_color-schemer.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/color-schemer/color-schemer/_colorblind.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/color-schemer/color-schemer/_comparison.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/color-schemer/color-schemer/_equalize.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/color-schemer/color-schemer/_harmonize.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/color-schemer/color-schemer/_interpolation.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/color-schemer/color-schemer/_mix.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/color-schemer/color-schemer/_mixins.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/color-schemer/color-schemer/_ryb.scss create mode 100644 user/plugins/admin/themes/grav/scss/vendor/color-schemer/color-schemer/_tint-shade.scss create mode 100644 user/plugins/admin/themes/grav/templates/config.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/dashboard.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/default.json.twig create mode 100644 user/plugins/admin/themes/grav/templates/denied.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/email/base.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/empty.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/error.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/error.json.twig create mode 100644 user/plugins/admin/themes/grav/templates/forgot.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/field.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/array/array.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/backupshistory/backupshistory.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/blueprint/blueprint.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/colorpicker/colorpicker.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/column/column.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/columns/columns.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/cron/cron.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/cronstatus/cronstatus.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/dateformat/dateformat.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/datetime/datetime.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/editor/editor.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/fieldset/fieldset.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/file/file.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/filepicker/filepicker.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/frontmatter/frontmatter.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/iconpicker/iconpicker.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/iconpicker/icons.yaml create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/list/list.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/markdown/markdown.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/mediapicker/mediapicker.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/multilevel/multilevel.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/order/order.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/pagemedia/pagemedia.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/pagemediaselect/pagemediaselect.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/pages/pages.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/parents/parents.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/permissions/permissions.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/range/range.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/section/section.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/selectize/selectize.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/selectunique/selectunique.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/taxonomy/taxonomy.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/themeselect/themeselect.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/userinfo/userinfo.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/forms/fields/xss/xss.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/installer.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/login.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/media-list-content.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/pages.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/backups-button.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/base-root.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/base.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/blueprints-new-folder.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/blueprints-new.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/blueprints-raw.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/blueprints.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/dashboard-feed.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/dashboard-maintenance.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/dashboard-notifications.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/dashboard-pages.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/dashboard-statistics.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/feed-block.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/footer.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/header.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/javascript-config.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/javascripts.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/list-sort.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/login-form.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/login-logo.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/login-logout.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/login-twofa.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/login.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/logo.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/media-list-wrapper.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/media-list-wrapper__list.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/media-list-wrapper__list__filters.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/media-list-wrapper__sidebar.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/messages.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/modal-add-package.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/modal-changes-detected.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/modal-reinstall-package.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/modal-remove-package.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/modal-update-packages.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/nav-quick-tray.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/nav-toggle.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/nav-user-avatar.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/nav-user-details.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/nav.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/notification-dashboard-block.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/notification-feed-block.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/notification-plugins-block.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/notification-themes-block.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/notification-top-block.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/page-children.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/page-legend.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/page-move.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/plugin-data.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/plugins-details.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/plugins-list.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/register.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/release-toggle.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/spinning-wheel.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/stylesheets.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/theme.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/themes-details.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/themes-list.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/tools-backups-titlebar.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/tools-backups.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/tools-direct-install.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/tools-logs.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/tools-reports.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/tools-scheduler-titlebar.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/tools-scheduler.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/userinfo-avatar-credit.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/partials/userinfo-avatar.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/plugins.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/preview.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/register.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/reports/security.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/reports/yamllinter.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/reset.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/statistics.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/themes.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/tools.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/unauthorized.html.twig create mode 100644 user/plugins/admin/themes/grav/templates/user.html.twig create mode 100644 user/plugins/admin/themes/grav/theme.yaml create mode 100644 user/plugins/admin/themes/grav/watch.sh create mode 100644 user/plugins/admin/themes/grav/webpack.conf.js create mode 100644 user/plugins/admin/themes/grav/yarn.lock create mode 100644 user/plugins/admin/twig/AdminTwigExtension.php create mode 100644 user/plugins/admin/vendor/autoload.php create mode 100644 user/plugins/admin/vendor/bin/picofeed create mode 100644 user/plugins/admin/vendor/composer/ClassLoader.php create mode 100644 user/plugins/admin/vendor/composer/LICENSE create mode 100644 user/plugins/admin/vendor/composer/autoload_classmap.php create mode 100644 user/plugins/admin/vendor/composer/autoload_namespaces.php create mode 100644 user/plugins/admin/vendor/composer/autoload_psr4.php create mode 100644 user/plugins/admin/vendor/composer/autoload_real.php create mode 100644 user/plugins/admin/vendor/composer/autoload_static.php create mode 100644 user/plugins/admin/vendor/composer/installed.json create mode 100644 user/plugins/admin/vendor/composer/semver/CHANGELOG.md create mode 100644 user/plugins/admin/vendor/composer/semver/LICENSE create mode 100644 user/plugins/admin/vendor/composer/semver/README.md create mode 100644 user/plugins/admin/vendor/composer/semver/composer.json create mode 100644 user/plugins/admin/vendor/composer/semver/src/Comparator.php create mode 100644 user/plugins/admin/vendor/composer/semver/src/Constraint/AbstractConstraint.php create mode 100644 user/plugins/admin/vendor/composer/semver/src/Constraint/Constraint.php create mode 100644 user/plugins/admin/vendor/composer/semver/src/Constraint/ConstraintInterface.php create mode 100644 user/plugins/admin/vendor/composer/semver/src/Constraint/EmptyConstraint.php create mode 100644 user/plugins/admin/vendor/composer/semver/src/Constraint/MultiConstraint.php create mode 100644 user/plugins/admin/vendor/composer/semver/src/Semver.php create mode 100644 user/plugins/admin/vendor/composer/semver/src/VersionParser.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/LICENSE create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Base.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/Client.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/ClientException.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/Curl.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/ForbiddenException.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/HttpHeaders.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/InvalidCertificateException.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/InvalidUrlException.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/MaxRedirectException.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/MaxSizeException.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/Stream.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/TimeoutException.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/UnauthorizedException.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Client/Url.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Config/Config.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Encoding/Encoding.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Filter/Attribute.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Filter/Filter.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Filter/Html.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Filter/Tag.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Generator/ContentGeneratorInterface.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Generator/FileContentGenerator.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Generator/YoutubeContentGenerator.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Logging/Logger.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Atom.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/DateParser.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Feed.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Item.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/MalformedXmlException.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Parser.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/ParserException.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/ParserInterface.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Rss10.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Rss20.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Rss91.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/Rss92.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/XmlEntityException.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Parser/XmlParser.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/PicoFeedException.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Processor/ContentFilterProcessor.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Processor/ContentGeneratorProcessor.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Processor/ItemPostProcessor.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Processor/ItemProcessorInterface.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Processor/ScraperProcessor.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Reader/Favicon.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Reader/Reader.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Reader/ReaderException.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Reader/SubscriptionNotFoundException.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Reader/UnsupportedFeedFormatException.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/.blog.lemonde.fr.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/.blogs.nytimes.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/.igen.fr.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/.nytimes.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/.over-blog.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/.phoronix.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/.slate.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/.theguardian.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/.wikipedia.org.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/.wired.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/.wsj.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/01net.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/24.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/444.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/888.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/abstrusegoose.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/achgut.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/adventuregamers.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/alainonline.net.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/aljazeera.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/allafrica.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/allgemeine-zeitung.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/amazingsuperpowers.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/anythingcomic.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/ap.org.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/areadvd.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/arstechnica.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/atv.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/awkwardzombie.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/backchannel.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/bangkokpost.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/bauerwilli.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/bgr.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/bigfootjustice.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/bigpicture.ru.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/bizjournals.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/biztimes.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/bleepingcomputer.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/blog.fefe.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/blog.mapillary.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/brewers.mlb.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/buenosairesherald.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/bunicomic.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/buttersafe.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/cad-comic.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/chaoslife.findchaos.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/chinafile.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/cicero.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/cliquerefresh.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/cnet.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/coinwelt.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/consomac.fr.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/cowbirdsinlove.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/crash.net.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/csmonitor.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/dailyjs.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/dailyreporter.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/dailytech.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/degroupnews.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/derstandard.at.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/dilbert.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/discovermagazine.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/distrowatch.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/dozodomo.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/drawingboardcomic.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/e-w-e.ru.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/economist.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/encyclopedie.naheulbeuk.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/endlessorigami.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/engadget.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/escapistmagazine.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/espn.go.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/exocomics.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/explosm.net.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/extrafabulouscomics.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/factroom.ru.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/fastcodesign.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/fastcoexist.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/fastcompany.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/ffworld.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/foreignpolicy.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/fossbytes.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/fototelegraf.ru.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/fowllanguagecomics.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/gamechannel.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/gamestar.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/geek.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/geektimes.ru.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/gerbilwithajetpack.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/giantitp.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/github.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/gocomics.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/golem.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/gondola.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/gorabbit.ru.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/habrahabr.ru.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/happletea.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/hardware.fr.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/heise.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/hirek.prim.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/hotshowlife.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/huffingtonpost.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/hvg.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/idokep.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/imogenquest.net.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/index.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/indiehaven.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/inforadio.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/ing.dk.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/invisiblebread.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/ir.amd.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/japantimes.co.jp.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/japantoday.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/journaldugeek.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/jsonline.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/justcoolidea.ru.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/kanpai.fr.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/karriere.jobfinder.dk.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/kisalfold.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/kiszamolo.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/kodi.tv.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/koreaherald.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/koreatimes.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/lastplacecomics.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/legorafi.fr.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/lejapon.fr.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/lesjoiesducode.fr.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/lfg.co.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/lifehacker.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/lifehacker.ru.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/linux-magazin.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/linux.org.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/linux.org.ru.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/linuxinsider.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/lists.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/loadingartist.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/loldwell.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/lukesurl.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/macg.co.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/maclife.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/magyarkurir.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/marc.info.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/marriedtothesea.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/marycagle.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/maximumble.thebookofbiff.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/medium.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/mercworks.net.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/metronieuws.nl.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/milwaukeenns.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/mno.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/mokepon.smackjeeves.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/monandroid.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/monwindows.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/moya-planeta.ru.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/mrlovenstein.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/muckrock.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/mynorthshorenow.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/nakedCapitalism.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/nasa.gov.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/nat-geo.ru.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/nationaljournal.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/nature.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/nba.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/nedroid.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/networkworld.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/neustadt-ticker.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/nextinpact.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/niceteethcomic.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/nichtlustig.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/nlcafe.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/novo-argumente.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/oglaf.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/onhax.net.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/onlinekosten.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/onmilwaukee.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/openculture.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/opennet.ru.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/openrightsgroup.org.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/opensource.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/optipess.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/origo.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/osnews.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/pastebin.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/pcgameshardware.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/peebleslab.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/penny-arcade.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/pixelbeat.org.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/plus.google.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/popstrip.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/portfolio.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/pro-linux.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/publicpolicyforum.org.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/publy.ru.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/putaindecode.fr.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/recode.net.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/retractionwatch.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/rockpapershotgun.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/rue89.nouvelobs.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/rugbyrama.fr.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/salonkolumnisten.com create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/satwcomic.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/science-skeptical.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/scrumalliance.org.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/securityfocus.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/sentfromthemoon.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/sitepoint.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/slashdot.org.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/smallhousebliss.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/smarthomewelt.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/smashingmagazine.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/smbc-comics.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/snopes.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/soundandvision.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/spiegel.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/stereophile.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/stupidfox.net.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/subtraction.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/sz.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/takprosto.cc.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/techcrunch.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/the-ebook-reader.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/theatlantic.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/theawkwardyeti.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/thecodinglove.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/thedoghousediaries.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/thegamercat.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/thehindu.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/thelocal.se.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/themerepublic.net.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/themoscowtimes.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/thenewslens.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/theodd1sout.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/theonion.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/theregister.co.uk.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/thestandard.com.hk.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/theverge.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/threepanelsoul.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/tichyseinblick.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/timesofindia.indiatimes.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/totalcar.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/tozsdeforum.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/travel-dealz.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/travelo.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/treehugger.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/treelobsters.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/tutorialzine.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/twogag.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/twokinds.keenspot.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/undeadly.org.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/upi.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/usatoday.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/version2.dk.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/vezess.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/vgcats.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/vuxml.org.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/wausaudailyherald.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/welt.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/westfalen-blatt.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.bbc.co.uk.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.bdgest.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.bgr.in.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.businessweek.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.cnn.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.developpez.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.egscomics.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.fakingnews.firstpost.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.forbes.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.franceculture.fr.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.futura-sciences.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.geekculture.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.howtogeek.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.lepoint.fr.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.lesnumeriques.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.mac4ever.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.makeuseof.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.monsieur-le-chien.fr.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.npr.org.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.numerama.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.oneindia.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.pseudo-sciences.org.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.sciencemag.org.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.slate.fr.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.universfreebox.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/www.zeit.de.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/xkcd.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/ymatuhin.ru.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/zarojel.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/zdnet.com.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Rules/zoom.hu.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Scraper/CandidateParser.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Scraper/ParserInterface.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Scraper/RuleLoader.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Scraper/RuleParser.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Scraper/Scraper.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Serialization/Subscription.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Serialization/SubscriptionList.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Serialization/SubscriptionListBuilder.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Serialization/SubscriptionListParser.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Serialization/SubscriptionParser.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Syndication/AtomFeedBuilder.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Syndication/AtomHelper.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Syndication/AtomItemBuilder.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Syndication/FeedBuilder.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Syndication/ItemBuilder.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Syndication/Rss20FeedBuilder.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Syndication/Rss20Helper.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/lib/PicoFeed/Syndication/Rss20ItemBuilder.php create mode 100644 user/plugins/admin/vendor/p3k/picofeed/picofeed create mode 100644 user/plugins/admin/vendor/zendframework/zendxml/CHANGELOG.md create mode 100644 user/plugins/admin/vendor/zendframework/zendxml/LICENSE.md create mode 100644 user/plugins/admin/vendor/zendframework/zendxml/README.md create mode 100644 user/plugins/admin/vendor/zendframework/zendxml/composer.json create mode 100644 user/plugins/admin/vendor/zendframework/zendxml/src/Exception/ExceptionInterface.php create mode 100644 user/plugins/admin/vendor/zendframework/zendxml/src/Exception/InvalidArgumentException.php create mode 100644 user/plugins/admin/vendor/zendframework/zendxml/src/Exception/RuntimeException.php create mode 100644 user/plugins/admin/vendor/zendframework/zendxml/src/Security.php create mode 100644 user/plugins/email/CHANGELOG.md create mode 100644 user/plugins/email/LICENSE create mode 100644 user/plugins/email/README.md create mode 100644 user/plugins/email/blueprints.yaml create mode 100644 user/plugins/email/classes/Email.php create mode 100644 user/plugins/email/classes/Utils.php create mode 100644 user/plugins/email/cli/ClearQueueFailuresCommand.php create mode 100644 user/plugins/email/cli/FlushQueueCommand.php create mode 100644 user/plugins/email/cli/TestEmailCommand.php create mode 100644 user/plugins/email/composer.json create mode 100644 user/plugins/email/composer.lock create mode 100644 user/plugins/email/email.php create mode 100644 user/plugins/email/email.yaml create mode 100644 user/plugins/email/hebe.json create mode 100644 user/plugins/email/languages.yaml create mode 100644 user/plugins/email/templates/email/base.html.twig create mode 100644 user/plugins/email/vendor/autoload.php create mode 100644 user/plugins/email/vendor/composer/ClassLoader.php create mode 100644 user/plugins/email/vendor/composer/LICENSE create mode 100644 user/plugins/email/vendor/composer/autoload_classmap.php create mode 100644 user/plugins/email/vendor/composer/autoload_files.php create mode 100644 user/plugins/email/vendor/composer/autoload_namespaces.php create mode 100644 user/plugins/email/vendor/composer/autoload_psr4.php create mode 100644 user/plugins/email/vendor/composer/autoload_real.php create mode 100644 user/plugins/email/vendor/composer/autoload_static.php create mode 100644 user/plugins/email/vendor/composer/installed.json create mode 100644 user/plugins/email/vendor/doctrine/lexer/LICENSE create mode 100644 user/plugins/email/vendor/doctrine/lexer/README.md create mode 100644 user/plugins/email/vendor/doctrine/lexer/composer.json create mode 100644 user/plugins/email/vendor/doctrine/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/EmailLexer.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/EmailParser.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/EmailValidator.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/AtextAfterCFWS.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/CRLFAtTheEnd.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/CRLFX2.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/CRNoLF.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/CharNotAllowed.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/CommaInDomain.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/ConsecutiveAt.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/ConsecutiveDot.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/DomainHyphened.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/DotAtEnd.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/DotAtStart.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/ExpectingAT.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/ExpectingATEXT.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/ExpectingCTEXT.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/ExpectingDTEXT.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/ExpectingDomainLiteralClose.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/ExpectingQPair.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/InvalidEmail.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/NoDNSRecord.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/NoDomainPart.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/NoLocalPart.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/UnclosedComment.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/UnclosedQuotedString.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Exception/UnopenedComment.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Parser/DomainPart.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Parser/LocalPart.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Parser/Parser.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/DNSCheckValidation.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/EmailValidation.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/Error/RFCWarnings.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/Error/SpoofEmail.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/Exception/EmptyValidationList.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/MultipleErrors.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/MultipleValidationWithAnd.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/NoRFCWarningsValidation.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/RFCValidation.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Validation/SpoofCheckValidation.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/AddressLiteral.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/CFWSNearAt.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/CFWSWithFWS.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/Comment.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/DeprecatedComment.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/DomainLiteral.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/DomainTooLong.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/EmailTooLong.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/IPV6BadChar.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/IPV6ColonEnd.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/IPV6ColonStart.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/IPV6Deprecated.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/IPV6DoubleColon.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/IPV6GroupCount.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/IPV6MaxGroups.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/LabelTooLong.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/LocalTooLong.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/NoDNSMXRecord.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/ObsoleteDTEXT.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/QuotedPart.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/QuotedString.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/TLD.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/EmailValidator/Warning/Warning.php create mode 100644 user/plugins/email/vendor/egulias/email-validator/LICENSE create mode 100644 user/plugins/email/vendor/egulias/email-validator/README.md create mode 100644 user/plugins/email/vendor/egulias/email-validator/composer.json create mode 100644 user/plugins/email/vendor/egulias/email-validator/phpunit.xml.dist create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/.gitattributes create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/.github/ISSUE_TEMPLATE.md create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/.gitignore create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/.php_cs.dist create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/.travis.yml create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/CHANGES create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/LICENSE create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/README create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/composer.json create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/doc/headers.rst create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/doc/index.rst create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/doc/introduction.rst create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/doc/japanese.rst create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/doc/messages.rst create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/doc/plugins.rst create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/doc/sending.rst create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/AddressEncoder.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/AddressEncoder/IdnAddressEncoder.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/AddressEncoder/Utf8AddressEncoder.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/AddressEncoderException.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Attachment.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/AbstractFilterableInputStream.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/ArrayByteStream.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/FileByteStream.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/TemporaryFileByteStream.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/GenericFixedWidthReader.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/UsAsciiReader.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/Utf8Reader.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReaderFactory.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReaderFactory/SimpleCharacterReaderFactory.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream/ArrayCharacterStream.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream/CharacterStream.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream/NgCharacterStream.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ConfigurableSpool.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/DependencyContainer.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/DependencyException.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/EmbeddedFile.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Encoder.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Encoder/Base64Encoder.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Encoder/QpEncoder.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Encoder/Rfc2231Encoder.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/CommandEvent.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/CommandListener.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/Event.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/EventDispatcher.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/EventListener.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/EventObject.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/ResponseEvent.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/ResponseListener.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/SendEvent.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/SendListener.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/SimpleEventDispatcher.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportChangeEvent.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportChangeListener.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportExceptionEvent.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportExceptionListener.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/FailoverTransport.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/FileSpool.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/FileStream.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Filterable.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/IdGenerator.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Image.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/InputByteStream.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/IoException.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/ArrayKeyCache.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/DiskKeyCache.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/KeyCacheInputStream.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/NullKeyCache.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/SimpleKeyCacheInputStream.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/LoadBalancedTransport.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mailer.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mailer/ArrayRecipientIterator.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mailer/RecipientIterator.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/MemorySpool.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Message.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Attachment.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/CharsetObserver.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/Base64ContentEncoder.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/NullContentEncoder.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/PlainContentEncoder.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoderProxy.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/EmbeddedFile.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/EncodingObserver.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Header.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/Base64HeaderEncoder.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/AbstractHeader.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/DateHeader.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/IdentificationHeader.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/MailboxHeader.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/OpenDKIMHeader.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/ParameterizedHeader.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/PathHeader.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/UnstructuredHeader.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/IdGenerator.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/MimePart.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderFactory.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderSet.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleMessage.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleMimeEntity.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/MimePart.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/NullTransport.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/OutputByteStream.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/AntiFloodPlugin.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/BandwidthMonitorPlugin.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Decorator/Replacements.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/DecoratorPlugin.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/ImpersonatePlugin.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Logger.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/LoggerPlugin.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Loggers/ArrayLogger.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Loggers/EchoLogger.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/MessageLogger.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Pop/Pop3Connection.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Pop/Pop3Exception.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/PopBeforeSmtpPlugin.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/RedirectingPlugin.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporter.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/ReporterPlugin.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporters/HitReporter.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporters/HtmlReporter.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Sleeper.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/ThrottlerPlugin.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Timer.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Preferences.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/ReplacementFilterFactory.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/RfcComplianceException.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/SendmailTransport.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signer.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/BodySigner.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/DKIMSigner.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/DomainKeySigner.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/HeaderSigner.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/OpenDKIMSigner.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Signers/SMimeSigner.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/SmtpTransport.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Spool.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/SpoolTransport.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilter.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilters/ByteArrayReplacementFilter.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilter.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilterFactory.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/SwiftException.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/AbstractSmtpTransport.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/NTLMAuthenticator.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/XOAuth2Authenticator.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/AuthHandler.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Authenticator.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/EightBitMimeHandler.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/SmtpUtf8Handler.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/EsmtpHandler.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/EsmtpTransport.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/FailoverTransport.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/IoBuffer.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/LoadBalancedTransport.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/NullTransport.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/SendmailTransport.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/SmtpAgent.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/SpoolTransport.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/classes/Swift/TransportException.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/dependency_maps/cache_deps.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/dependency_maps/message_deps.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/dependency_maps/mime_deps.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/dependency_maps/transport_deps.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/mime_types.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/preferences.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/swift_required.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/lib/swiftmailer_generate_mimes_config.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/phpunit.xml.dist create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/IdenticalBinaryConstraint.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/StreamCollector.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/SwiftMailerSmokeTestCase.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/SwiftMailerTestCase.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/charsets/iso-2022-jp/one.txt create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/charsets/iso-8859-1/one.txt create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/charsets/utf-8/one.txt create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/charsets/utf-8/three.txt create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/charsets/utf-8/two.txt create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/dkim/dkim.test.priv create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/dkim/dkim.test.pub create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/files/data.txt create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/files/swiftmailer.png create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/files/textfile.zip create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/smime/CA.srl create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/smime/ca.crt create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/smime/ca.key create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/smime/create-cert.sh create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt.crt create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt.key create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt2.crt create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt2.key create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/smime/intermediate.crt create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/smime/intermediate.key create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/smime/sign.crt create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/smime/sign.key create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/smime/sign2.crt create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/_samples/smime/sign2.key create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance.conf.php.default create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/AttachmentAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/ByteStream/FileByteStreamAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/CharacterReaderFactory/SimpleCharacterReaderFactoryAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/DependencyContainerAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/EmbeddedFileAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Encoder/Base64EncoderAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Encoder/QpEncoderAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Encoder/Rfc2231EncoderAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/KeyCache/ArrayKeyCacheAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/KeyCache/DiskKeyCacheAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/MessageAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/AttachmentAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/ContentEncoder/Base64ContentEncoderAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/ContentEncoder/NativeQpContentEncoderAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/ContentEncoder/PlainContentEncoderAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/ContentEncoder/QpContentEncoderAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/EmbeddedFileAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/HeaderEncoder/Base64HeaderEncoderAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/MimePartAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Mime/SimpleMessageAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/MimePartAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/AbstractStreamBufferAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/BasicSocketAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/ProcessAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/SocketTimeoutTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/SslSocketAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/acceptance/Swift/Transport/StreamBuffer/TlsSocketAcceptanceTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/bootstrap.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug111Test.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug118Test.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug206Test.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug274Test.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug34Test.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug35Test.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug38Test.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug518Test.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug51Test.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug534Test.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug650Test.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug71Test.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/bug/Swift/Bug76Test.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/bug/Swift/BugFileByteStreamConsecutiveReadCallsTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/fixtures/MimeEntityFixture.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/smoke.conf.php.default create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/smoke/Swift/Smoke/AttachmentSmokeTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/smoke/Swift/Smoke/BasicSmokeTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/smoke/Swift/Smoke/HtmlWithAttachmentSmokeTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/smoke/Swift/Smoke/InternationalSmokeTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/ByteStream/ArrayByteStreamTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/CharacterReader/GenericFixedWidthReaderTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/CharacterReader/UsAsciiReaderTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/CharacterReader/Utf8ReaderTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/CharacterStream/ArrayCharacterStreamTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/DependencyContainerTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Encoder/Base64EncoderTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Encoder/QpEncoderTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Encoder/Rfc2231EncoderTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/CommandEventTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/EventObjectTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/ResponseEventTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/SendEventTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/SimpleEventDispatcherTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/TransportChangeEventTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Events/TransportExceptionEventTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/KeyCache/ArrayKeyCacheTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/KeyCache/SimpleKeyCacheInputStreamTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mailer/ArrayRecipientIteratorTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/MailerTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/MessageTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/AbstractMimeEntityTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/AttachmentTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/ContentEncoder/Base64ContentEncoderTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/ContentEncoder/PlainContentEncoderTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/ContentEncoder/QpContentEncoderTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/EmbeddedFileTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/HeaderEncoder/Base64HeaderEncoderTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/HeaderEncoder/QpHeaderEncoderTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/DateHeaderTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/IdentificationHeaderTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/MailboxHeaderTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/ParameterizedHeaderTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/PathHeaderTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/Headers/UnstructuredHeaderTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/IdGeneratorTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/MimePartTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/SimpleHeaderFactoryTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/SimpleHeaderSetTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/SimpleMessageTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Mime/SimpleMimeEntityTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/AntiFloodPluginTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/BandwidthMonitorPluginTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/DecoratorPluginTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/LoggerPluginTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/Loggers/ArrayLoggerTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/Loggers/EchoLoggerTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/PopBeforeSmtpPluginTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/RedirectingPluginTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/ReporterPluginTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/Reporters/HitReporterTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/Reporters/HtmlReporterTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Plugins/ThrottlerPluginTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Signers/DKIMSignerTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Signers/OpenDKIMSignerTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Signers/SMimeSignerTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/StreamFilters/ByteArrayReplacementFilterTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/StreamFilters/StringReplacementFilterFactoryTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/StreamFilters/StringReplacementFilterTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/AbstractSmtpEventSupportTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/AbstractSmtpTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/Auth/CramMd5AuthenticatorTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/Auth/LoginAuthenticatorTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/Auth/NTLMAuthenticatorTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/Auth/PlainAuthenticatorTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/Esmtp/AuthHandlerTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/EsmtpTransport/ExtensionSupportTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/EsmtpTransportTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/FailoverTransportTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/LoadBalancedTransportTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/SendmailTransportTest.php create mode 100644 user/plugins/email/vendor/swiftmailer/swiftmailer/tests/unit/Swift/Transport/StreamBufferTest.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Iconv.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/LICENSE create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/README.md create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.big5.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp037.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp1006.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp1026.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp424.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp437.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp500.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp737.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp775.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp850.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp852.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp855.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp856.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp857.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp860.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp861.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp862.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp863.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp864.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp865.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp866.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp869.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp874.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp875.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp932.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp936.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp949.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.cp950.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-1.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-10.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-11.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-13.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-14.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-15.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-16.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-2.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-3.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-4.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-5.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-6.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-7.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-8.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-9.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.koi8-r.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.koi8-u.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.us-ascii.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.windows-1250.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.windows-1251.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.windows-1252.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.windows-1253.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.windows-1254.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.windows-1255.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.windows-1256.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.windows-1257.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/from.windows-1258.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/Resources/charset/translit.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/bootstrap.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-iconv/composer.json create mode 100644 user/plugins/email/vendor/symfony/polyfill-intl-idn/Idn.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-intl-idn/LICENSE create mode 100644 user/plugins/email/vendor/symfony/polyfill-intl-idn/README.md create mode 100644 user/plugins/email/vendor/symfony/polyfill-intl-idn/bootstrap.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-intl-idn/composer.json create mode 100644 user/plugins/email/vendor/symfony/polyfill-mbstring/LICENSE create mode 100644 user/plugins/email/vendor/symfony/polyfill-mbstring/Mbstring.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-mbstring/README.md create mode 100644 user/plugins/email/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-mbstring/bootstrap.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-mbstring/composer.json create mode 100644 user/plugins/email/vendor/symfony/polyfill-php72/LICENSE create mode 100644 user/plugins/email/vendor/symfony/polyfill-php72/Php72.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-php72/README.md create mode 100644 user/plugins/email/vendor/symfony/polyfill-php72/bootstrap.php create mode 100644 user/plugins/email/vendor/symfony/polyfill-php72/composer.json create mode 160000 user/plugins/error create mode 100644 user/plugins/form/.eslintrc create mode 100644 user/plugins/form/.gitignore create mode 100644 user/plugins/form/CHANGELOG.md create mode 100644 user/plugins/form/LICENSE create mode 100644 user/plugins/form/README.md create mode 100644 user/plugins/form/app/fields/array.js create mode 100644 user/plugins/form/app/fields/file.js create mode 100644 user/plugins/form/app/fields/form.js create mode 100644 user/plugins/form/app/fields/index.js create mode 100644 user/plugins/form/app/fields/media.js create mode 100644 user/plugins/form/app/fields/tabs.js create mode 100644 user/plugins/form/app/main.js create mode 100644 user/plugins/form/app/utils/keep-alive.js create mode 100644 user/plugins/form/assets/dropzone.min.css create mode 100644 user/plugins/form/assets/form-styles.css create mode 100644 user/plugins/form/assets/form-styles.min.css create mode 100644 user/plugins/form/assets/form.min.js create mode 100644 user/plugins/form/assets/form.vendor.js create mode 100644 user/plugins/form/assets/object.assign.polyfill.js create mode 100644 user/plugins/form/assets/signature_pad.js create mode 100644 user/plugins/form/blueprints.yaml create mode 100644 user/plugins/form/classes/Form.php create mode 100644 user/plugins/form/classes/FormFactory.php create mode 100644 user/plugins/form/classes/Forms.php create mode 100644 user/plugins/form/composer.json create mode 100644 user/plugins/form/composer.lock create mode 100644 user/plugins/form/form.php create mode 100644 user/plugins/form/form.yaml create mode 100644 user/plugins/form/gulpfile.js create mode 100644 user/plugins/form/hebe.json create mode 100644 user/plugins/form/languages.yaml create mode 100644 user/plugins/form/package.json create mode 100644 user/plugins/form/scss/form-styles.scss create mode 100644 user/plugins/form/templates/form-messages.html.twig create mode 100644 user/plugins/form/templates/form-messages.json.twig create mode 100644 user/plugins/form/templates/form.html.twig create mode 100644 user/plugins/form/templates/form.json.twig create mode 100644 user/plugins/form/templates/formdata.html.twig create mode 100644 user/plugins/form/templates/forms/ajax.json.twig create mode 100644 user/plugins/form/templates/forms/data.html.twig create mode 100644 user/plugins/form/templates/forms/data.txt.twig create mode 100644 user/plugins/form/templates/forms/default/data.html.twig create mode 100644 user/plugins/form/templates/forms/default/data.txt.twig create mode 100644 user/plugins/form/templates/forms/default/field.html.twig create mode 100644 user/plugins/form/templates/forms/default/fields.html.twig create mode 100644 user/plugins/form/templates/forms/default/form.html.twig create mode 100644 user/plugins/form/templates/forms/default/toggleable.html.twig create mode 100644 user/plugins/form/templates/forms/dropzone/template.html.twig create mode 100644 user/plugins/form/templates/forms/field.html.twig create mode 100644 user/plugins/form/templates/forms/fields/array/array.html.twig create mode 100644 user/plugins/form/templates/forms/fields/avatar/avatar.html.twig create mode 100644 user/plugins/form/templates/forms/fields/captcha/captcha.html.twig create mode 100644 user/plugins/form/templates/forms/fields/checkbox/checkbox.html.twig create mode 100644 user/plugins/form/templates/forms/fields/checkboxes/checkboxes.html.twig create mode 100644 user/plugins/form/templates/forms/fields/color/color.html.twig create mode 100644 user/plugins/form/templates/forms/fields/column/column.html.twig create mode 100644 user/plugins/form/templates/forms/fields/columns/columns.html.twig create mode 100644 user/plugins/form/templates/forms/fields/conditional/conditional.html.twig create mode 100644 user/plugins/form/templates/forms/fields/date/date.html.twig create mode 100644 user/plugins/form/templates/forms/fields/date/edit_list.html.twig create mode 100644 user/plugins/form/templates/forms/fields/datetime/datetime.html.twig create mode 100644 user/plugins/form/templates/forms/fields/datetime/edit_list.html.twig create mode 100644 user/plugins/form/templates/forms/fields/display/display.html.twig create mode 100644 user/plugins/form/templates/forms/fields/email/email.html.twig create mode 100644 user/plugins/form/templates/forms/fields/fieldset/fieldset.html.twig create mode 100644 user/plugins/form/templates/forms/fields/file/file.html.twig create mode 100644 user/plugins/form/templates/forms/fields/formname/formname.html.twig create mode 100644 user/plugins/form/templates/forms/fields/formtask/formtask.html.twig create mode 100644 user/plugins/form/templates/forms/fields/hidden/hidden.html.twig create mode 100644 user/plugins/form/templates/forms/fields/honeypot/honeypot.html.twig create mode 100644 user/plugins/form/templates/forms/fields/ignore/ignore.html.twig create mode 100644 user/plugins/form/templates/forms/fields/key/key.html.twig create mode 100644 user/plugins/form/templates/forms/fields/month/month.html.twig create mode 100644 user/plugins/form/templates/forms/fields/number/number.html.twig create mode 100644 user/plugins/form/templates/forms/fields/password/password.html.twig create mode 100644 user/plugins/form/templates/forms/fields/radio/radio.html.twig create mode 100644 user/plugins/form/templates/forms/fields/range/range.html.twig create mode 100644 user/plugins/form/templates/forms/fields/section/section.html.twig create mode 100644 user/plugins/form/templates/forms/fields/select/select.html.twig create mode 100644 user/plugins/form/templates/forms/fields/select_optgroup/select_optgroup.html.twig create mode 100644 user/plugins/form/templates/forms/fields/signature/signature.html.twig create mode 100644 user/plugins/form/templates/forms/fields/spacer/spacer.html.twig create mode 100644 user/plugins/form/templates/forms/fields/switch/switch.html.twig create mode 100644 user/plugins/form/templates/forms/fields/tab/tab.html.twig create mode 100644 user/plugins/form/templates/forms/fields/tabs/tabs.html.twig create mode 100644 user/plugins/form/templates/forms/fields/tel/tel.html.twig create mode 100644 user/plugins/form/templates/forms/fields/text/edit_list.html.twig create mode 100644 user/plugins/form/templates/forms/fields/text/text.html.twig create mode 100644 user/plugins/form/templates/forms/fields/textarea/textarea.html.twig create mode 100644 user/plugins/form/templates/forms/fields/time/edit_list.html.twig create mode 100644 user/plugins/form/templates/forms/fields/time/time.html.twig create mode 100644 user/plugins/form/templates/forms/fields/toggle/edit_list.html.twig create mode 100644 user/plugins/form/templates/forms/fields/toggle/toggle.html.twig create mode 100644 user/plugins/form/templates/forms/fields/uniqueid/uniqueid.html.twig create mode 100644 user/plugins/form/templates/forms/fields/url/edit_list.html.twig create mode 100644 user/plugins/form/templates/forms/fields/url/url.html.twig create mode 100644 user/plugins/form/templates/forms/fields/value/value.html.twig create mode 100644 user/plugins/form/templates/forms/fields/week/week.html.twig create mode 100644 user/plugins/form/templates/forms/form.html.twig create mode 100644 user/plugins/form/templates/modular/form.html.twig create mode 100644 user/plugins/form/templates/partials/form-messages.html.twig create mode 100644 user/plugins/form/templates/partials/form-messages.json.twig create mode 100644 user/plugins/form/vendor/autoload.php create mode 100644 user/plugins/form/vendor/composer/ClassLoader.php create mode 100644 user/plugins/form/vendor/composer/LICENSE create mode 100644 user/plugins/form/vendor/composer/autoload_classmap.php create mode 100644 user/plugins/form/vendor/composer/autoload_namespaces.php create mode 100644 user/plugins/form/vendor/composer/autoload_psr4.php create mode 100644 user/plugins/form/vendor/composer/autoload_real.php create mode 100644 user/plugins/form/vendor/composer/autoload_static.php create mode 100644 user/plugins/form/vendor/composer/installed.json create mode 100644 user/plugins/form/vendor/google/recaptcha/.github/ISSUE_TEMPLATE/bug_report.md create mode 100644 user/plugins/form/vendor/google/recaptcha/.gitignore create mode 100644 user/plugins/form/vendor/google/recaptcha/.travis.yml create mode 100644 user/plugins/form/vendor/google/recaptcha/ARCHITECTURE.md create mode 100644 user/plugins/form/vendor/google/recaptcha/CONTRIBUTING.md create mode 100644 user/plugins/form/vendor/google/recaptcha/LICENSE create mode 100644 user/plugins/form/vendor/google/recaptcha/README.md create mode 100644 user/plugins/form/vendor/google/recaptcha/app.yaml create mode 100644 user/plugins/form/vendor/google/recaptcha/composer.json create mode 100644 user/plugins/form/vendor/google/recaptcha/examples/appengine-https.php create mode 100644 user/plugins/form/vendor/google/recaptcha/examples/config.php.dist create mode 100644 user/plugins/form/vendor/google/recaptcha/examples/examples.css create mode 100644 user/plugins/form/vendor/google/recaptcha/examples/google0afd8760fd68f119.html create mode 100644 user/plugins/form/vendor/google/recaptcha/examples/index.php create mode 100644 user/plugins/form/vendor/google/recaptcha/examples/recaptcha-content-security-policy.php create mode 100644 user/plugins/form/vendor/google/recaptcha/examples/recaptcha-v2-checkbox-explicit.php create mode 100644 user/plugins/form/vendor/google/recaptcha/examples/recaptcha-v2-checkbox.php create mode 100644 user/plugins/form/vendor/google/recaptcha/examples/recaptcha-v2-invisible.php create mode 100644 user/plugins/form/vendor/google/recaptcha/examples/recaptcha-v3-request-scores.php create mode 100644 user/plugins/form/vendor/google/recaptcha/examples/recaptcha-v3-verify.php create mode 100644 user/plugins/form/vendor/google/recaptcha/examples/robots.txt create mode 100644 user/plugins/form/vendor/google/recaptcha/phpunit.xml.dist create mode 100644 user/plugins/form/vendor/google/recaptcha/src/ReCaptcha/ReCaptcha.php create mode 100644 user/plugins/form/vendor/google/recaptcha/src/ReCaptcha/RequestMethod.php create mode 100644 user/plugins/form/vendor/google/recaptcha/src/ReCaptcha/RequestMethod/Curl.php create mode 100644 user/plugins/form/vendor/google/recaptcha/src/ReCaptcha/RequestMethod/CurlPost.php create mode 100644 user/plugins/form/vendor/google/recaptcha/src/ReCaptcha/RequestMethod/Post.php create mode 100644 user/plugins/form/vendor/google/recaptcha/src/ReCaptcha/RequestMethod/Socket.php create mode 100644 user/plugins/form/vendor/google/recaptcha/src/ReCaptcha/RequestMethod/SocketPost.php create mode 100644 user/plugins/form/vendor/google/recaptcha/src/ReCaptcha/RequestParameters.php create mode 100644 user/plugins/form/vendor/google/recaptcha/src/ReCaptcha/Response.php create mode 100644 user/plugins/form/vendor/google/recaptcha/src/autoload.php create mode 100644 user/plugins/form/vendor/google/recaptcha/tests/ReCaptcha/ReCaptchaTest.php create mode 100644 user/plugins/form/vendor/google/recaptcha/tests/ReCaptcha/RequestMethod/CurlPostTest.php create mode 100644 user/plugins/form/vendor/google/recaptcha/tests/ReCaptcha/RequestMethod/PostTest.php create mode 100644 user/plugins/form/vendor/google/recaptcha/tests/ReCaptcha/RequestMethod/SocketPostTest.php create mode 100644 user/plugins/form/vendor/google/recaptcha/tests/ReCaptcha/RequestParametersTest.php create mode 100644 user/plugins/form/vendor/google/recaptcha/tests/ReCaptcha/ResponseTest.php create mode 100644 user/plugins/form/webpack.conf.js create mode 100644 user/plugins/form/yarn.lock create mode 100644 user/plugins/login/.gitignore create mode 100644 user/plugins/login/CHANGELOG.md create mode 100644 user/plugins/login/LICENSE create mode 100644 user/plugins/login/README.md create mode 100644 user/plugins/login/blueprints.yaml create mode 100644 user/plugins/login/classes/Controller.php create mode 100644 user/plugins/login/classes/Events/UserLoginEvent.php create mode 100644 user/plugins/login/classes/Login.php create mode 100644 user/plugins/login/classes/LoginCache.php create mode 100644 user/plugins/login/classes/RateLimiter.php create mode 100644 user/plugins/login/classes/RememberMe/RememberMe.php create mode 100644 user/plugins/login/classes/RememberMe/TokenStorage.php create mode 100644 user/plugins/login/classes/TwoFactorAuth/BaconQrProvider.php create mode 100644 user/plugins/login/classes/TwoFactorAuth/TwoFactorAuth.php create mode 100644 user/plugins/login/cli/ChangePasswordCommand.php create mode 100644 user/plugins/login/cli/ChangeUserStateCommand.php create mode 100644 user/plugins/login/cli/LookupUserCommand.php create mode 100644 user/plugins/login/cli/NewUserCommand.php create mode 100644 user/plugins/login/composer.json create mode 100644 user/plugins/login/composer.lock create mode 100644 user/plugins/login/css/login.css create mode 100644 user/plugins/login/hebe.json create mode 100644 user/plugins/login/js/2fa.js create mode 100644 user/plugins/login/languages/de.yaml create mode 100644 user/plugins/login/languages/en.yaml create mode 100644 user/plugins/login/languages/es.yaml create mode 100644 user/plugins/login/languages/fr.yaml create mode 100644 user/plugins/login/languages/hr.yaml create mode 100644 user/plugins/login/languages/hu.yaml create mode 100644 user/plugins/login/languages/no.yaml create mode 100644 user/plugins/login/languages/ro.yaml create mode 100644 user/plugins/login/languages/ru.yaml create mode 100644 user/plugins/login/languages/uk.yaml create mode 100644 user/plugins/login/login.php create mode 100644 user/plugins/login/login.yaml create mode 100644 user/plugins/login/pages/forgot.md create mode 100644 user/plugins/login/pages/login.md create mode 100644 user/plugins/login/pages/profile.md create mode 100644 user/plugins/login/pages/register.md create mode 100644 user/plugins/login/pages/reset.md create mode 100644 user/plugins/login/pages/unauthorized.md create mode 100644 user/plugins/login/templates/forgot.html.twig create mode 100644 user/plugins/login/templates/forms/fields/2fa_secret/2fa_secret.html.twig create mode 100644 user/plugins/login/templates/login.html.twig create mode 100644 user/plugins/login/templates/login.json.twig create mode 100644 user/plugins/login/templates/partials/forgot-form.html.twig create mode 100644 user/plugins/login/templates/partials/login-form.html.twig create mode 100644 user/plugins/login/templates/partials/login-status.html.twig create mode 100644 user/plugins/login/templates/partials/login-twofa.html.twig create mode 100644 user/plugins/login/templates/partials/reset-form.html.twig create mode 100644 user/plugins/login/templates/profile.html.twig create mode 100644 user/plugins/login/templates/profile.json.twig create mode 100644 user/plugins/login/templates/register.html.twig create mode 100644 user/plugins/login/templates/reset.html.twig create mode 100644 user/plugins/login/templates/unauthorized.html.twig create mode 100644 user/plugins/login/vendor/autoload.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/.gitignore create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/.travis.yml create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/CHANGELOG.md create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/LICENSE create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/Module.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/README.md create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/autoload_classmap.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/autoload_function.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/autoload_register.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/composer.json create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/AbstractEnum.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/BitArray.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/BitMatrix.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/BitUtils.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/CharacterSetEci.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/EcBlock.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/EcBlocks.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/ErrorCorrectionLevel.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/FormatInformation.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/Mode.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/ReedSolomonCodec.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/Version.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/BlockPair.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/ByteMatrix.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/Encoder.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/MaskUtil.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/MatrixUtil.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/QrCode.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/ExceptionInterface.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/InvalidArgumentException.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/OutOfBoundsException.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/RuntimeException.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/UnexpectedValueException.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/WriterException.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/Cmyk.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/ColorInterface.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/Gray.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/Rgb.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/AbstractRenderer.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Decorator/DecoratorInterface.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Decorator/FinderPattern.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Eps.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Png.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/RendererInterface.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Svg.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/RendererInterface.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Text/Html.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Text/Plain.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/BaconQrCode/Writer.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Common/BitArray.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Common/BitMatrix.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Common/BitUtils.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Common/CharacterSetEci.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Common/EcBlock.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Common/EcBlocks.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Common/ErrorCorrectionLevel.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Common/FormatInformation.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Common/Mode.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Common/ReedSolomonCodec.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Common/Version.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Encoder/BlockPair.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Encoder/ByteMatrix.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Encoder/Encoder.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Encoder/MaskUtil.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Encoder/MatrixUtil.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Encoder/QrCode.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Exception/ExceptionInterface.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Exception/InvalidArgumentException.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Exception/OutOfBoundsException.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Exception/RuntimeException.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Exception/UnexpectedValueException.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Exception/WriterException.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Color/Alpha.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Color/Cmyk.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Color/ColorInterface.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Color/Gray.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Color/Rgb.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Eye/CompositeEye.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Eye/EyeInterface.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Eye/ModuleEye.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Eye/SimpleCircleEye.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Eye/SquareEye.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Image/EpsImageBackEnd.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Image/ImageBackEndInterface.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Image/ImagickImageBackEnd.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Image/SvgImageBackEnd.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Image/TransformationMatrix.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/ImageRenderer.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Module/DotsModule.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Module/EdgeIterator/Edge.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Module/EdgeIterator/EdgeIterator.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Module/ModuleInterface.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Module/RoundnessModule.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Module/SquareModule.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Path/Close.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Path/Curve.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Path/EllipticArc.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Path/Line.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Path/Move.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Path/OperationInterface.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/Path/Path.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/PlainTextRenderer.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/RendererInterface.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/EyeFill.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/Fill.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/Gradient.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/GradientType.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/RendererStyle.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/src/Writer.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/BitArrayTest.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/BitMatrixTest.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/BitUtilsTest.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/ErrorCorrectionLevelTest.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/FormatInformationTest.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/ModeTest.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/ReedSolomonCodecTest.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/VersionTest.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/tests/BaconQrCode/Encoder/EncoderTest.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/tests/BaconQrCode/Encoder/MaskUtilTest.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/tests/BaconQrCode/Encoder/MatrixUtilTest.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/tests/BaconQrCode/Renderer/Text/HtmlTest.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/tests/BaconQrCode/Renderer/Text/TextTest.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/tests/bootstrap.php create mode 100644 user/plugins/login/vendor/bacon/bacon-qr-code/tests/phpunit.xml create mode 100644 user/plugins/login/vendor/birke/rememberme/.gitignore create mode 100644 user/plugins/login/vendor/birke/rememberme/LICENSE create mode 100644 user/plugins/login/vendor/birke/rememberme/README.md create mode 100644 user/plugins/login/vendor/birke/rememberme/composer.json create mode 100644 user/plugins/login/vendor/birke/rememberme/example/action.php create mode 100644 user/plugins/login/vendor/birke/rememberme/example/css/style.css create mode 100644 user/plugins/login/vendor/birke/rememberme/example/index.php create mode 100644 user/plugins/login/vendor/birke/rememberme/example/templates/cookie_was_stolen.php create mode 100644 user/plugins/login/vendor/birke/rememberme/example/templates/login.php create mode 100644 user/plugins/login/vendor/birke/rememberme/example/templates/user_is_logged_in.php create mode 100644 user/plugins/login/vendor/birke/rememberme/phpunit.xml create mode 100644 user/plugins/login/vendor/birke/rememberme/src/Rememberme/Authenticator.php create mode 100644 user/plugins/login/vendor/birke/rememberme/src/Rememberme/Cookie.php create mode 100644 user/plugins/login/vendor/birke/rememberme/src/Rememberme/Storage/DB.php create mode 100644 user/plugins/login/vendor/birke/rememberme/src/Rememberme/Storage/File.php create mode 100644 user/plugins/login/vendor/birke/rememberme/src/Rememberme/Storage/PDO.php create mode 100644 user/plugins/login/vendor/birke/rememberme/src/Rememberme/Storage/StorageInterface.php create mode 100644 user/plugins/login/vendor/birke/rememberme/test/CookieTest.php create mode 100644 user/plugins/login/vendor/birke/rememberme/test/RemembermeTest.php create mode 100644 user/plugins/login/vendor/birke/rememberme/test/Storage/PDO.php create mode 100644 user/plugins/login/vendor/birke/rememberme/test/Storage/tokens.xml create mode 100644 user/plugins/login/vendor/birke/rememberme/test/bootstrap.php create mode 100644 user/plugins/login/vendor/composer/ClassLoader.php create mode 100644 user/plugins/login/vendor/composer/LICENSE create mode 100644 user/plugins/login/vendor/composer/autoload_classmap.php create mode 100644 user/plugins/login/vendor/composer/autoload_files.php create mode 100644 user/plugins/login/vendor/composer/autoload_namespaces.php create mode 100644 user/plugins/login/vendor/composer/autoload_psr4.php create mode 100644 user/plugins/login/vendor/composer/autoload_real.php create mode 100644 user/plugins/login/vendor/composer/autoload_static.php create mode 100644 user/plugins/login/vendor/composer/installed.json create mode 100644 user/plugins/login/vendor/dasprid/enum/.coveralls.yml create mode 100644 user/plugins/login/vendor/dasprid/enum/.gitignore create mode 100644 user/plugins/login/vendor/dasprid/enum/.travis.yml create mode 100644 user/plugins/login/vendor/dasprid/enum/README.md create mode 100644 user/plugins/login/vendor/dasprid/enum/composer.json create mode 100644 user/plugins/login/vendor/dasprid/enum/phpcs.xml create mode 100644 user/plugins/login/vendor/dasprid/enum/phpunit.xml.dist create mode 100644 user/plugins/login/vendor/dasprid/enum/src/AbstractEnum.php create mode 100644 user/plugins/login/vendor/dasprid/enum/src/EnumMap.php create mode 100644 user/plugins/login/vendor/dasprid/enum/src/Exception/CloneNotSupportedException.php create mode 100644 user/plugins/login/vendor/dasprid/enum/src/Exception/ExceptionInterface.php create mode 100644 user/plugins/login/vendor/dasprid/enum/src/Exception/ExpectationException.php create mode 100644 user/plugins/login/vendor/dasprid/enum/src/Exception/IllegalArgumentException.php create mode 100644 user/plugins/login/vendor/dasprid/enum/src/Exception/MismatchException.php create mode 100644 user/plugins/login/vendor/dasprid/enum/src/Exception/SerializeNotSupportedException.php create mode 100644 user/plugins/login/vendor/dasprid/enum/src/Exception/UnserializeNotSupportedException.php create mode 100644 user/plugins/login/vendor/dasprid/enum/src/NullValue.php create mode 100644 user/plugins/login/vendor/dasprid/enum/test/AbstractEnumTest.php create mode 100644 user/plugins/login/vendor/dasprid/enum/test/EnumMapTest.php create mode 100644 user/plugins/login/vendor/dasprid/enum/test/NullValueTest.php create mode 100644 user/plugins/login/vendor/dasprid/enum/test/Planet.php create mode 100644 user/plugins/login/vendor/dasprid/enum/test/WeekDay.php create mode 100644 user/plugins/login/vendor/paragonie/random_compat/CHANGELOG.md create mode 100644 user/plugins/login/vendor/paragonie/random_compat/LICENSE create mode 100644 user/plugins/login/vendor/paragonie/random_compat/RATIONALE.md create mode 100644 user/plugins/login/vendor/paragonie/random_compat/README.md create mode 100644 user/plugins/login/vendor/paragonie/random_compat/SECURITY.md create mode 100644 user/plugins/login/vendor/paragonie/random_compat/build-phar.sh create mode 100644 user/plugins/login/vendor/paragonie/random_compat/composer.json create mode 100644 user/plugins/login/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey create mode 100644 user/plugins/login/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey.asc create mode 100644 user/plugins/login/vendor/paragonie/random_compat/lib/byte_safe_strings.php create mode 100644 user/plugins/login/vendor/paragonie/random_compat/lib/cast_to_int.php create mode 100644 user/plugins/login/vendor/paragonie/random_compat/lib/error_polyfill.php create mode 100644 user/plugins/login/vendor/paragonie/random_compat/lib/random.php create mode 100644 user/plugins/login/vendor/paragonie/random_compat/lib/random_bytes_com_dotnet.php create mode 100644 user/plugins/login/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php create mode 100644 user/plugins/login/vendor/paragonie/random_compat/lib/random_bytes_libsodium.php create mode 100644 user/plugins/login/vendor/paragonie/random_compat/lib/random_bytes_libsodium_legacy.php create mode 100644 user/plugins/login/vendor/paragonie/random_compat/lib/random_bytes_mcrypt.php create mode 100644 user/plugins/login/vendor/paragonie/random_compat/lib/random_bytes_openssl.php create mode 100644 user/plugins/login/vendor/paragonie/random_compat/lib/random_int.php create mode 100644 user/plugins/login/vendor/paragonie/random_compat/other/build_phar.php create mode 100644 user/plugins/login/vendor/paragonie/random_compat/other/ide_stubs/COM.php create mode 100644 user/plugins/login/vendor/paragonie/random_compat/other/ide_stubs/README.md create mode 100644 user/plugins/login/vendor/paragonie/random_compat/other/ide_stubs/com_exception.php create mode 100644 user/plugins/login/vendor/paragonie/random_compat/other/ide_stubs/libsodium.php create mode 100644 user/plugins/login/vendor/paragonie/random_compat/psalm-autoload.php create mode 100644 user/plugins/login/vendor/paragonie/random_compat/psalm.xml create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/.gitignore create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/.travis.yml create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/LICENSE create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/README.md create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/TwoFactorAuth.phpproj create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/TwoFactorAuth.sln create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/composer.json create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/composer.lock create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/demo/demo.php create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/demo/loader.php create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/lib/Providers/Qr/BaseHTTPQRCodeProvider.php create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/lib/Providers/Qr/GoogleQRCodeProvider.php create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/lib/Providers/Qr/IQRCodeProvider.php create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/lib/Providers/Qr/QRException.php create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/lib/Providers/Qr/QRServerProvider.php create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/lib/Providers/Qr/QRicketProvider.php create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/lib/Providers/Rng/CSRNGProvider.php create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/lib/Providers/Rng/HashRNGProvider.php create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/lib/Providers/Rng/IRNGProvider.php create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/lib/Providers/Rng/MCryptRNGProvider.php create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/lib/Providers/Rng/OpenSSLRNGProvider.php create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/lib/Providers/Rng/RNGException.php create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/lib/Providers/Time/ConvertUnixTimeDotComTimeProvider.php create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/lib/Providers/Time/HttpTimeProvider.php create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/lib/Providers/Time/ITimeProvider.php create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/lib/Providers/Time/LocalMachineTimeProvider.php create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/lib/Providers/Time/TimeException.php create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/lib/TwoFactorAuth.php create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/lib/TwoFactorAuthException.php create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/logo.png create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/multifactorauthforeveryone.png create mode 100644 user/plugins/login/vendor/robthree/twofactorauth/tests/TwoFactorAuthTest.php create mode 160000 user/plugins/markdown-notices create mode 160000 user/plugins/problems create mode 100644 user/plugins/sitemap/.gitignore create mode 100644 user/plugins/sitemap/CHANGELOG.md create mode 100644 user/plugins/sitemap/LICENSE create mode 100644 user/plugins/sitemap/README.md create mode 100644 user/plugins/sitemap/blueprints.yaml create mode 100644 user/plugins/sitemap/blueprints/sitemap.yaml create mode 100644 user/plugins/sitemap/classes/sitemapentry.php create mode 100644 user/plugins/sitemap/hebe.json create mode 100644 user/plugins/sitemap/languages.yaml create mode 100644 user/plugins/sitemap/pages/sitemap.md create mode 100644 user/plugins/sitemap/sitemap.php create mode 100644 user/plugins/sitemap/sitemap.xsl create mode 100644 user/plugins/sitemap/sitemap.yaml create mode 100644 user/plugins/sitemap/templates/sitemap.xml.twig create mode 100644 user/plugins/taxonomylist/.gitignore create mode 100644 user/plugins/taxonomylist/CHANGELOG.md create mode 100644 user/plugins/taxonomylist/LICENSE create mode 100644 user/plugins/taxonomylist/README.md create mode 100644 user/plugins/taxonomylist/assets/readme_1.png create mode 100644 user/plugins/taxonomylist/blueprints.yaml create mode 100644 user/plugins/taxonomylist/classes/taxonomylist.php create mode 100644 user/plugins/taxonomylist/hebe.json create mode 100644 user/plugins/taxonomylist/taxonomylist.php create mode 100644 user/plugins/taxonomylist/taxonomylist.yaml create mode 100644 user/plugins/taxonomylist/templates/partials/taxonomylist.html.twig diff --git a/.gitignore b/.gitignore index 7fc058f..3baddb9 100644 --- a/.gitignore +++ b/.gitignore @@ -23,8 +23,6 @@ user/accounts/* !user/accounts/.* user/data/* !user/data/.* -user/plugins/* -!user/plugins/.* user/themes/quark/ !user/themes/quark/.* user/pages/* diff --git a/user/plugins/admin/.editorconfig b/user/plugins/admin/.editorconfig new file mode 100644 index 0000000..3b95e6d --- /dev/null +++ b/user/plugins/admin/.editorconfig @@ -0,0 +1,17 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +charset = utf-8 +end_of_line = lf +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space +indent_size = 4 + +# 2 space indentation +[*.{yaml,.yml}] +indent_size = 2 diff --git a/user/plugins/admin/.gitattributes b/user/plugins/admin/.gitattributes new file mode 100644 index 0000000..e3cf70c --- /dev/null +++ b/user/plugins/admin/.gitattributes @@ -0,0 +1,8 @@ +# Linguist Normalizer +*.yaml linguistic-language=PHP +*.twig linguistic-language=PHP +**/gulpfile.js linguist-vendored +**/webpack.conf.js linguist-vendored +**/js/*.js linguist-vendored +**/js/*.json linguist-vendored +**/css-compiled/*.css linguist-vendored diff --git a/user/plugins/admin/.github/FUNDING.yml b/user/plugins/admin/.github/FUNDING.yml new file mode 100644 index 0000000..e84f52b --- /dev/null +++ b/user/plugins/admin/.github/FUNDING.yml @@ -0,0 +1,8 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: grav +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +custom: # Replace with a single custom sponsorship URL diff --git a/user/plugins/admin/.gitignore b/user/plugins/admin/.gitignore new file mode 100644 index 0000000..125b54f --- /dev/null +++ b/user/plugins/admin/.gitignore @@ -0,0 +1,14 @@ +themes/grav/.sass-cache +.DS_Store + +# Node Modules +**/node_modules/** +themes/grav/js/admin.js +themes/grav/js/vendor.js +themes/grav/js/*.map +.idea + +tests/_output/* +tests/_support/_generated/* +tests/cache/* +tests/error.log diff --git a/user/plugins/admin/CHANGELOG.md b/user/plugins/admin/CHANGELOG.md new file mode 100644 index 0000000..dd8dcaf --- /dev/null +++ b/user/plugins/admin/CHANGELOG.md @@ -0,0 +1,1713 @@ +# v1.9.10 +## 09/19/2019 + +1. [](#bugfix) + * Fixed `Badly encoded JSON data` warning when uploading files [grav#2663](https://github.com/getgrav/grav/issues/2663) + +# v1.9.9 +## 08/21/2019 + +1. [](#bugfix) + * Fixed regression with files in admin not allowing types other than images [#1737](https://github.com/getgrav/grav-plugin-admin/issues/1737) + * Fixed preview link for non-images files in **Page Media** [#1727](https://github.com/getgrav/grav-plugin-admin/issues/1727) + +# v1.9.8 +## 08/11/2019 + +1. [](#improved) + * Better support for `array` field into `list` field + * Attach `_list_index` to fields within list items so that the index/key is available +1. [](#bugfix) + * Fixed 2FA regenerate for Flex Users + * Added missing closing in language loops + * Fixed issue with nested `list` fields both utilizing the custom `key` functionality + * 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) + * Fixed issue with permissions toggle [#1702](https://github.com/getgrav/grav-plugin-admin/issues/1702) + +# v1.9.6 +## 06/15/2019 + +1. [](#bugfix) + * Fixed regression issue with `parents_levels` defaulting to `2` + +# v1.9.5 +## 06/14/2019 + +1. [](#improved) + * Display error message if GPM class fails to initialize + * Better append/prepend logic that was breaking some layouts + * Default `backups` to an array if used outside of tools + * PSR 7 fixes + +# v1.9.4 +## 05/09/2019 + +1. [](#new) + * Added support for `field.copy-to-clipboard` on Text input fields +1. [](#improved) + * Only invalidate cache on creating new/deleting page to speed up the recovery + * Updated language strings from https://crowdin.com/project/grav-admin + * Use `plugins://` stream rather than `user://plugins` [#1674](https://github.com/getgrav/grav-plugin-admin/issues/1674) +1. [](#bugfix) + * Fixed admin cache to detect moved and deleted pages + * Fixed avatar URLs with `?` in them being broken + * Fixed issue saving page with language that was not exactly `2` or `5` chars long [#1667](https://github.com/getgrav/grav-plugin-admin/issues/1667) + * Fixed admin not detecting any existing users when Flex users are being used + * Fixed issue with append/prepend not respecting `size:` + * Fixed issue with `unset` on file fields [#1427](https://github.com/getgrav/grav/issues/1427), [#1670](https://github.com/getgrav/grav/issues/1670), [#1982](https://github.com/getgrav/grav/issues/1982) + +# v1.9.3 +## 04/22/2019 + +1. [](#new) + * 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 + +1. [](#bugfix) + * Fix for homepage admin preview [#2426](https://github.com/getgrav/grav/issues/2426) + * Uploaded Avatar removed from user's yaml when editing the user [#1647](https://github.com/getgrav/grav-plugin-admin/issues/1647) + +# v1.9.1 +## 04/13/2019 + +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) + +# v1.9.0 +## 04/11/2019 + +1. [](#new) + * New `Scheduler` configuration panel in tools + * New `Backups` configuration panel in tools + * New `Cache::purge()` option in cache drop-down to clear out old cache only + * New `Tools - Reports` section with event `onAdminGenerateReports()` for 3rd party plugin support + * Added support for the new `Flex User` object + * Allow admin forms to use `Form` classes + * Added new `Logs` section to tools to allow quick view of Grav log files +1. [](#improved) + * Improved the UI for the Parent Page Route dropdown when adding a new Page / Folder + * Use `$grav['accounts']` instead of `$grav['users']` + * Improved image background overlay and tools + * Better unauthorized user rendering + * Update all Form classes to rely on `PageInterface` instead of `Page` class + * Removed `media.upload_limit` references + * Improve error when upload exceeds `upload_max_filesize` + * Delegate Dropzone for checking maximum file size and avoid uploading if not necessary + * Low level unauthorized user handling in `base-root.html.twig` + * Refactored "NewsFeeds" and "Notifications" for better performance and to address CORS issues + * Flex user profile now uses Flex Form + * Moved dashboard `notifications` logic to server-side for increased performance (1 request instead of 3) + * Refactored feeds logic for better performance + * Better logic for delete action to support Ajax. Fixes Flex lists + * Cleanly handle session corruption due to changing Flex object types + * Implemented [ForkAwesome](https://forkawesome.github.io/Fork-Awesome/) and removed FontAwesome + LineAwesome + * Various default admin theme improvements and cleanup + * Make new System Config layout responsive [#1579](https://github.com/getgrav/grav-plugin-admin/issues/1579) + * 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 + * Improved usability of `System` configuration blueprint with side-tabs + * 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 + * Regression: Fixed lost user access when saving user profile without super user permissions [#1639](https://github.com/getgrav/grav-plugin-admin/issues/1639) + * Fixed `Page.menu` displaying in edit view rather than `Page.title` [#1642](https://github.com/getgrav/grav-plugin-admin/issues/1642) + * Regression from beta.8: Deleting files other than from plugins/themes fail on error + * 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 + * 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 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 + * Added `merge_items` option for `field.selectize` to allow storing custom items [#1461](https://github.com/getgrav/grav-plugin-admin/issues/1461) + * Better handling of unset in uploaded files [#1427](https://github.com/getgrav/grav-plugin-admin/issues/1427) + * Prefix Backup/Scheduler titles with `Tools` + * Regression: Media settings have bad layout [#1529](https://github.com/getgrav/grav-plugin-admin/issues/1529) + * Fixed Direct Install Uploader, failing to validate the uploaded files + * Regression: Editing interface does not keep settings properly without manual intervention on each edit [#1527](https://github.com/getgrav/grav-plugin-admin/issues/1527) + * 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) + +# v1.8.18 +## 02/12/2019 + +1. [](#bugfix) + * Set default value for `show_modular` [grav#2362](https://github.com/getgrav/grav/issues/2362) + +# v1.8.17 +## 02/07/2019 + +1. [](#improved) + * Improved Grav Core installer/updater to run installer script (if available) + * Added `unauthorized.html.twig` file that was missing [#1609](https://github.com/getgrav/grav-plugin-admin/pull/1609) +1. [](#bugfix) + * Fixed direct install deleting backups and logs if used with full Grav package instead of with update package + +# v1.8.16 +## 01/25/2019 + +1. [](#improved) + * IP pseudonymization for rate limiter [#1589](https://github.com/getgrav/grav-plugin-admin/pull/1589) + * Add option to hide modular pages in parent select [#1571](https://github.com/getgrav/grav-plugin-admin/pull/1571) + * Added `admin.tools` permission [#1550](https://github.com/getgrav/grav-plugin-admin/pull/1550) +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 + +# v1.8.15 +## 12/14/2018 + +1. [](#improved) + * Fire `onAdminSave()` event during `AdminController::taskSaveAs()` [#1544](https://github.com/getgrav/grav-plugin-admin/issues/1544) +1. [](#bugfix) + * Clean user post to ensure dynamically added form fields are not saved + +# v1.8.14 +## 11/12/2018 + +1. [](#bugfix) + * Fixed Grav core update potentially spinning forever because of an error which happens after a successful upgrade + * Saving in expert mode can cause `undefined index: header` error [#1537](https://github.com/getgrav/grav-plugin-admin/issues/1537) + +# v1.8.13 +## 11/05/2018 + +1. [](#new) + * Added new `|nested()` Twig filter to access array objects with dot notation syntax +1. [](#bugfix) + * Fixed issue with complex lists structure and nested dot-notation [admin#2236](https://github.com/getgrav/grav/issues/2236) + +# v1.8.12 +## 10/24/2018 + +1. [](#improved) + * Updated various lang strings + * Removed duplicate lang strings +1. [](#bugfix) + * Fix XSS checking when empty content [#1533](https://github.com/getgrav/grav-plugin-admin/issues/1533) + * Fix DirectInstall not working [#1535](https://github.com/getgrav/grav-plugin-admin/issues/1535) + +# v1.8.11 +## 10/08/2018 + +1. [](#improved) + * Change usage of basename where possible [#1480](https://github.com/getgrav/grav-plugin-admin/pull/1480) + * Improved filename validation (requires Grav 1.5.3) + * Updated various lang codes +1. [](#bugfix) + * File Uploads: Do not trust mimetype sent by the browser + * Fixed file extension detection + * Fix for HTML entities in page slug [#1524](https://github.com/getgrav/grav-plugin-admin/issues/1524) + * Fix for port in backup download links [#1521](https://github.com/getgrav/grav-plugin-admin/issues/1521) + +# v1.8.10 +## 10/01/2018 + +1. [](#new) + * IMPORTANT: Non `admin.super` users are now subject to XSS validation in Page content. Configurable via Configuration / Security + * New XSS content warnings and integration into page save + * Added new event `onAdminPage()` which allows plugins to customize `Page` object in `$event['page']` +1. [](#improved) + * Use `Url:post()` to get the `$_POST` variable (allows common security checks/filtering for the POST data) + * Requires Grav 1.5.2 +1. [](#bugfix) + * Fixed redirect to correct URL after failed login + * Fixed issue in `filepicker` where missing images would cause a loop to try to load them + * Twig 2 compatibility fixes for macros + * Updated `composer.json` to better match Grav 1.5 + * Remove `package-lock.json` as it was referencing an insecure JS package + +# v1.8.9 +## 08/23/2018 + +1. [](#improved) + * Make order field to use context, not data + * Switched to new Grav Yaml class to support Native + Fallback YAML libraries + * Minor fix for `file` thumbnails display + * Requires Grav 1.5.1 + +# v1.8.8 +## 08/17/2018 + +1. [](#improved) + * Support URI Params and Query attributes in Login redirect + * Added support for textarea value type in `array` field + * Added some new lang strings for Grav 1.5.0 +1. [](#bugfix) + * Support params and querystring in login redirect + * Added field name nesting with tab field + +# v1.8.7 +## 07/31/2018 + +1. [](#bugfix) + * Fix for deleting 'extra' media files [grav#2100](https://githubcom/getgrav/grav/issues/2100) + +# v1.8.6 +## 07/13/2018 + +1. [](#bugfix) + * Force `html` for markdown preview [grav#2066](https://github.com/getgrav/grav/issues/2066) + * Add missing `authorizeTask()` checks in controller [#1483](https://github.com/getgrav/grav/issues/1483) + * Add support for `force_ssl` to admin URLs [#1479](https://github.com/getgrav/grav-plugin-admin/issues/1479) + +# v1.8.5 +## 06/20/2018 + +1. [](#bugfix) + * Fixed broken folder attribute on filepicker [#1465](https://github.com/getgrav/grav-plugin-admin/issues/1465) + * Added translation for system.session.initialize + * Slight updates on new translation strings + +# v1.8.4 +## 06/11/2018 + +1. [](#improved) + * Including EXIF JS library in the modules dependencies to fix orientation when uploading images +1. [](#bugfix) + * Initialize session on setup [#1451](https://github.com/getgrav/grav-plugin-admin/issues/1451) + * Force a `null` order when empty in the post request + * Fixed some 2FA form styling issues + +# v1.8.3 +## 05/31/2018 + +1. [](#new) + * Added support for selectize plugins as options in the selectize field +1. [](#bugfix) + * Fixed deep linking in admin after login [#1456](https://github.com/getgrav/grav-plugin-admin/issues/1456) + * Fixed Undefined property: `stdClass::$image` in v1.8.2 [#1454](https://github.com/getgrav/grav-plugin-admin/issues/1454) + * Pass media order when calling `task:listmedia` + +# v1.8.2 +## 05/24/2018 + +1. [](#new) + * Added custom object support for filepicker field + * Don't allow saving of a user with no local account file + * Controls for `list` field were not in sync between top and bottom +1. [](#improved) + * More subtle `fieldset` styling +1. [](#bugfix) + * Check if `$object->blueprints()` exists in `onAdminAfterSave` + * When creating first user, check `admin.login` not `site.login` + * Fix admin login redirects for multisite setups + * Fixed issue with filepicker field where images wouldn't properly merge with the current value if in a page header + * Fixed media delete for streams + +# v1.8.1 +## 05/15/2018 + +1. [](#improved) + * use SHA1 hashing of IP addressed to support GDPR rules [#1436](https://github.com/getgrav/grav-plugin-admin/pull/1436) +1. [](#bugfix) + * Fixed 2FA form showing up even if user has not turned on the feature [#1442](https://github.com/getgrav/grav-plugin-admin/issues/1442) + * Fixed previews of images in Pagemedia field not properly URI encoded [#1438](https://github.com/getgrav/grav-plugin-admin/issues/1438) + +# v1.8.0 +## 05/11/2018 + +1. [](#new) + * Moved 2FA authentication to login plugin + * Admin login now uses login plugin events + * Added new decoupled `pagemedia` field that is no longer tied to just pages + * Updated plugin dependencies (Grav >= 1.4.4, Form >=2.14.0, Login >=2.7.0, Email >=2.7.0) +1. [](#improved) + * Added support for JavaScript `bottom` block [#1425](https://github.com/getgrav/grav-plugin-admin/pull/1425) + * Added better typography styling for blockquote and markdown in `display` field + * Vendor updates +1. [](#bugfix) + * Added missing MarkdownExtra strings [#1385](https://github.com/getgrav/grav-plugin-admin/pull/1385) + * Updated `blueprints.yaml` with missing `step` attribute [#1415](https://github.com/getgrav/grav-plugin-admin/pull/1415) + * Fixed preview target setting [#1430](https://github.com/getgrav/grav-plugin-admin/pull/1430) + * Added new modular string [#1433](https://github.com/getgrav/grav-plugin-admin/pull/1433) + * Fixed Firefox issue with the Regenerate button for 2FA. Forcing the page to reload + * Fixed jumpiness behavior for Regenerate button when on active state. + * Prevent the prompt for unsaved state when Regenerating a 2FA code and trying to reload/leave the page. + +# v1.7.4 +## 04/02/2018 + +1. [](#bugfix) + * Fixed a bug for page copy caused by last release [#1409](https://github.com/getgrav/grav-plugin-admin/pull/1409) + * Fixed collapsible `list` option [#1410](https://github.com/getgrav/grav-plugin-admin/pull/1410) + * Fixed a minor typo in a label [#1397](https://github.com/getgrav/grav-plugin-admin/pull/1397) + +# v1.7.3 +## 04/01/2018 + +1. [](#new) + * Implemented Resize Media and Resolution ('resizeWidth', 'resizeHeight', 'resizeQuality', 'resolution') + * Updated Dropzone to latest +1. [](#bugfix) + * Implemented workaround for required text fields [#1390](https://github.com/getgrav/grav-plugin-admin/issues/1390) + * Fixed highlight color in Firefox [getgrav/grav#1949](https://github.com/getgrav/grav/issues/1949) + * Fix for bad redirect on saving simplesearch (possibly others) + +# v1.7.2 +## 03/21/2018 + +1. [](#improved) + * Table CSS improvements for use in 3rd party plugins + * Translatable `add_modals` button labels [#1388](https://github.com/getgrav/grav-plugin-admin/issues/1388) + * Check for `SHIFT` key on editor save shortcut [#1383](https://github.com/getgrav/grav-plugin-admin/issues/1383) + * Fixed User permissions responsive UI [#1379](https://github.com/getgrav/grav-plugin-admin/issues/1379) + * Optimization to stop admin for looking for pages in disabled plugins + * Added configuration option to choose if you want to use new 'inline' preview or `new tab' +1. [](#bugfix) + * Fix redirect bug when changing admin route to `admin-*` + * Changed Twig `|count` to `|length` filter [#1391](https://github.com/getgrav/grav-plugin-admin/issues/1391) + * Fix for page preview when `HTTP_REFERRER` is not set [grav#1930](https://github.com/getgrav/grav/issues/1930) + +# v1.7.1 +## 03/11/2018 + +1. [](#new) + * New built-in page preview system +1. [](#improved) + * Added `CTRL+K` / `CMD+K` shortcuts for editor links [#1279](https://github.com/getgrav/grav-plugin-admin/issues/1279) +1. [](#bugfix) + * Automatically redirect to new `admin_route` after changing it [#1371](https://github.com/getgrav/grav-plugin-admin/issues/1371) + * Remove bad-shadows on alerts + * Fixed notifications titles not html escaped [#1272](https://github.com/getgrav/grav-plugin-admin/issues/1272) + * Fixed extra horizontal scrollbar with `Editor` field + * Fixed `mediapicker` field in lists [#1369](https://github.com/getgrav/grav-plugin-admin/issues/1369) + +# v1.7.0 +## 03/09/2018 + +1. [](#new) + * Added styling and lang for **Route Overrides** in the default page blueprint + * Added clear cache permanently to quick-tray [#1353](https://github.com/getgrav/grav-plugin-admin/issues/1353) +1. [](#improved) + * Added option to toggle between `line-awesome` and `font-awesome` icon sets [#1334](https://github.com/getgrav/grav-plugin-admin/issues/1334) + * Added preview from page list view [#1250](https://github.com/getgrav/grav-plugin-admin/pull/1250) + * Added `Add` plugins button to plugins details page [#1352](https://github.com/getgrav/grav-plugin-admin/pull/1352) + * Added support for `default` and `options` fields in taxonomy field [#1364](https://github.com/getgrav/grav-plugin-admin/issues/1364) + * Added support to limit parent field levels [#1298](https://github.com/getgrav/grav-plugin-admin/issues/1298) +1. [](#bugfix) + * Fixed issue with custom logo text overlapping the sidebar toggle [#1334](https://github.com/getgrav/grav-plugin-admin/issues/1334) + * Fixed issues with minimum PHP versions in resource upgrades + * Fixed issue with default lang translation in admin [#1361](https://github.com/getgrav/grav-plugin-admin/issues/1361) + * Typos in `Tools` -> `Direct Install` page [#1345](https://github.com/getgrav/grav-plugin-admin/issues/1345) + * Fixed bug with frontmatter being killed when in `Expert Mode` [#1354](https://github.com/getgrav/grav-plugin-admin/issues/1354) + +# v1.7.0-rc.3 +## 02/15/2018 + +1. [](#improved) + * Tab optimization with fixes for 'onpage' tabs + * Stopped Chrome from auto-completing admin user profile form [grav#1847](https://github.com/getgrav/grav/issues/1847) + * Added a fixed `ga-theme-17x` body class to help styling compatibility + * Outputs an iterable field as a string if `yaml: true` or `validate: type: yaml` set in blueprint +1. [](#bugfix) + * Rolled back JS to known working versions [#1323](https://github.com/getgrav/grav-plugin-admin/issues/1323) + * Fixed missing translation in order field [#1324](https://github.com/getgrav/grav-plugin-admin/issues/1324) + * Fixed UI issue with last drop-down in button group [1325](https://github.com/getgrav/grav-plugin-admin/issues/1325) + * Fixed fieldset field outdated rendering [#1313](https://github.com/getgrav/grav-plugin-admin/issues/1313) + +# v1.7.0-rc.2 +## 01/24/2018 + +1. [](#new) + * Moved to LineAwesome icons rather than FontAwesome (still compatible w/FA 4.7.0) +1. [](#improved) + * Simplified open/close nav button + * Tidied Tools panel and added translations + * Tooltip and new icon for site preview + * Updated JS library dependencies + * Changed CodeMirror editor to use sans-serif font for readability +1. [](#bugfix) + * Fixed z-index issue in fullscreen mode [#1317](https://github.com/getgrav/grav-plugin-admin/issues/1317) + +# v1.7.0-rc.1 +## 01/22/2018 + +1. [](#new) + * Added support for markdown in all form fields for `label`, `help`, and `description` when `markdown: true` is set on field + * Changed "made by" to Trilby Media from RocketTheme +1. [](#improved) + * Lightened tabs in new theme + * Sort languages by key [#1303](https://github.com/getgrav/grav-plugin-admin/issues/1303) + * Add limit to Parent Levels [#1298](https://github.com/getgrav/grav-plugin-admin/pull/1298) +1. [](#bugfix) + * Fixed alignment issue with language drop-down + * Fixed a z-index issue with fullscreen editor [#1302](https://github.com/getgrav/grav-plugin-admin/issues/1302) + * Fixed missing background on register [#1307](https://github.com/getgrav/grav-plugin-admin/issues/1307) + * Fixed some style issues with field descriptions + * Fixed an issue with `File` field losing download size setting + * Fixed distorted thumbnails in `File` field by using `object-fit: cover` + +# v1.7.0-beta.1 +## 12/29/2017 + +1. [](#new) + * New lighter-and-tighter admin theme developed +1. [](#improved) + * Added simple value support for list field type + * Added checks to automatically hide collapse buttons when there's only single value in list type + +# v1.6.7 +## 12/05/2017 + +1. [](#new) + * Logout of admin goes straight to login form with a message (that then fades out) + * Added `sl`, `id`, `he`, `eu`, `et` languages +1. [](#improved) + * Added code to use new `GPM::loadRemoteGrav` if it exists in Gav [grav#1746](https://github.com/getgrav/grav/pull/1746) + * Add vertical style for order field [#1253](https://github.com/getgrav/grav-plugin-admin/pull/1253) + * Added classes to pagemedia field [#1274](https://github.com/getgrav/grav-plugin-admin/issues/1274) + * Fixed selectize field not properly updating value when `option` is provided [#1236](https://github.com/getgrav/grav-plugin-admin/pull/1236) + * Tab layout tweaks + * Updated all language files with latest from [Crowdin](https://crowdin.com/project/grav-admin) +1. [](#bugfix) + * Manual image metadata can now display in pagemedia when auto-generation is disabled [#1275](https://github.com/getgrav/grav-plugin-admin/issues/1275) + * Removed broken `home.hide_in_urls` code in `AdminBaseController::save()` that was throwing move errors + * Security fix to ensure file uploads are not manipulated mid-post - thnx @FLH! + +# v1.6.6 +## 10/27/2017 + +1. [](#new) + * Fixed issue where sortable media in expert mode would reset frontmatter [#1252](https://github.com/getgrav/grav-plugin-admin/issues/1252) + +# v1.6.5 +## 10/26/2017 + +1. [](#new) + * Added ability to **order** page media (requires latest Grav update) + +# v1.6.4 +## 10/11/2017 + +1. [](#improved) + * Use system PHP size for upload limit rather than `system.media.upload_limit` or `file.filesize` plugin options +1. [](#bugfix) + * Fixed Dropzone timeout to address slow internet connections [#1239](https://github.com/getgrav/grav-plugin-admin/pull/1239) + +# v1.6.3 +## 10/02/2017 + +1. [](#bugfix) + * Fixed chart labels not parsing HTML [#1234](https://github.com/getgrav/grav-plugin-admin/issues/1234) + +# v1.6.2 +## 09/29/2017 + +1. [](#improved) + * Removed extraneous files in vendor folder for smaller download package + +# v1.6.1 +## 09/29/2017 + +1. [](#improved) + * Added support for Latin Extended fonts [#1211](https://github.com/getgrav/grav-plugin-admin/pull/1221) + * Added collapsible attribute to lists [#1231](https://github.com/getgrav/grav-plugin-admin/pull/1231) +1. [](#bugfix) + * Fix editor not clickable in list field [#1224](https://github.com/getgrav/grav-plugin-admin/pull/1124) + * Updated Google Font URLs to always connect over HTTPS. [#1106](https://github.com/getgrav/grav-plugin-admin/pull/1106) + * Fixed fieldset field not allowing to properly save when contained within a list [#1225](https://github.com/getgrav/grav-plugin-admin/issues/1225) + * Fixed Video markdown syntax when drag & dropping in the content editor [#1160](https://github.com/getgrav/grav-plugin-admin/issues/1160) + * Fixed headers drop-down in editor to properly align + * Fixed fields not working in Microsoft Edge with Selectize.js [#1222](https://github.com/getgrav/grav-plugin-admin/pull/1222) + * Replaced a left-over "is empty" check [#1232](https://github.com/getgrav/grav-plugin-admin/pull/1232) + * Fixed headers drop-down in editor to align properly + + +# v1.6.0 +## 09/07/2017 + +1. [](#new) + * **Added 2-Factor Authentication support to the admin!** + * **Added rate-limiting for "failed login attempts" and "forgot password"** +1. [](#improved) + * Revamped the toggle switch CSS so it's more flexible and works better [#1198](https://github.com/getgrav/grav-plugin-admin/issues/1198) + * Improved toggle/button alignment on Page edit view +1. [](#bugfix) + * Fixed an issue where icon-picker style was hiding field elements [#1199](https://github.com/getgrav/grav-plugin-admin/issues/1199) + * Fixed https -> http redirect issue [#1195](https://github.com/getgrav/grav-plugin-admin/issues/1195) + * Also check `/.` for home route [#1191](https://github.com/getgrav/grav-plugin-admin/issues/1191) + * Fixed administration being broken in multi-site environments with plugin overrides + * Fixed lang-switcher broken in MS Edge browser [#1213](https://github.com/getgrav/grav-plugin-admin/pull/1213) + * Added custom `form_id` attribute for modal forms [#1216](https://github.com/getgrav/grav-plugin-admin/issues/1216) + * Fixed partially cropped line in Markdown editor for MS Edge/Firefox [#1219](https://github.com/getgrav/grav-plugin-admin/pull/1219) + * Downgraded Babel libraries to v6.x for compatibility with webpack [#1218](https://github.com/getgrav/grav-plugin-admin/pull/1218) + +# v1.5.2 +## 08/16/2017 + +1. [](#new) + * Added a new icon quick-tray in side navigation that plugins can utilize + * Added ability to set and retrieve temporary admin messages +1. [](#improved) + * Allow different field to be used as page label in list of pages [#1122](https://github.com/getgrav/grav-plugin-admin/pull/1122) + * Updated `en` language for `cache-control` + `clear_images_by_default` system settings + * Allow sorting of page based on custom ordering [#1182](https://github.com/getgrav/grav-plugin-admin/pull/1182) + * Search for pages by slug and folder name [#1183](https://github.com/getgrav/grav-plugin-admin/pull/1183) + * Allow all page data to be used during `onAdminCreatePageFrontmatter()` event [#1175](https://github.com/getgrav/grav-plugin-admin/pull/1175) + * Remove single quotes when slugifying title [#1178](https://github.com/getgrav/grav-plugin-admin/pull/1178) +1. [](#bugfix) + * Ignore missing Twig files [#1169](https://github.com/getgrav/grav-plugin-admin/issues/1169) + * If from is already defined, don't override it [#1129](https://github.com/getgrav/grav-plugin-admin/issues/1129) + * Fixed SelectUnique field not working with files with spaces + +# v1.5.1 +## 07/19/2017 + +1. [](#bugfix) + * Fixes issue when saving pages without a `folder` element [#1163](https://github.com/getgrav/grav-plugin-admin/issues/1163) + * Fixed mediapicker field inside lists not properly updating the value on the target input [#1157](https://github.com/getgrav/grav-plugin-admin/issues/1157) + +# v1.5.0 +## 07/16/2017 + +1. [](#new) + * Implemented Offline mode. Notifies in the admin when disconnected. +1. [](#bugfix) + * Fixed fetch issue throwing error when request not completed and while unloading the page [#1301](https://github.com/getgrav/grav-plugin-admin/issues/1301) + * Fixed ordering when > 100 pages [grav#1564](https://github.com/getgrav/grav/pull/1564) + * Fixed Lists issue when reindexing, causing Radio fields to potentially lose their `checked` status ([#1154](https://github.com/getgrav/grav-plugin-admin/issues/1154) | related: [1d55ffc](https://github.com/getgrav/grav-plugin-admin/commit/1d55ffc616125047f245efe9f2180ef2c16b4949)) + +# v1.5.0-rc.4 +## 07/05/2017 + +1. [](#new) + * New `multilevel` field, useful for defining collections definitions, metadata and other complex YAML data [#1135](https://github.com/getgrav/grav-plugin-admin/pull/1135) - (EXPERIMENTAL) + * Fix plugins hooked nav authorize not working with array of permissions [#1148](https://github.com/getgrav/grav-plugin-admin/pull/1148) +1. [](#improved) + * Add badge to plugins hooked into nav [#1147](https://github.com/getgrav/grav-plugin-admin/pull/1147) + * Added `field.outerclasses` to default form field [#1124](https://github.com/getgrav/grav-plugin-admin/pull/1124) + * Reverted back to textarea/YAML for `media.yaml` image options + * Fixed color of textarea fields in admin +1. [](#bugfix) + * Fix for bad referenced to `shouldLoadAdditionalFilesInBackground()` [#1145](https://github.com/getgrav/grav-plugin-admin/pull/1145) + * Expose Page Media instance to Grav Admin JS API + * Fixed mediapicker issue where newly added list items would not work + * Fixed issue with min/max setting of list collections. Removing a list item would not refresh properly the count + * If folder is empty/not sent, fallback to page slug [#1146](https://github.com/getgrav/grav-plugin-admin/issues/1146) + * Escape the URI basename before using it in Twig + * Ignore missing Twig file in the Tools page + +# v1.5.0-rc.3 +## 06/22/2017 + +1. [](#new) + * New `Admin::getPageMedia()` static method that can be used in blueprints + * Added a new `mediapicker` form field which allows to select a media from any page [#1125](https://github.com/getgrav/grav-plugin-admin/pull/1125) + * Added info metadata button for images to view EXIF and other useful details about an image +1. [](#improved) + * Pass original image filename via the `AdminController::taskListedia()` task + * Various form styling improvements + * Provided an option to control how parent select field displays +1. [](#bugfix) + * Fix referencing DI element when not initialized [#1141](https://github.com/getgrav/grav-plugin-admin/pull/1141) + +# v1.5.0-rc.2 +## 05/22/2017 + +1. [](#improved) + * Remove save button and save location notification on Config Info tab [#1116](https://github.com/getgrav/grav-plugin-admin/pull/1116) + * Allow taxonomy field to just list one or more specific taxonomies if the `taxonomies` field is filled in the blueprint + * `File` field now renders thumbnail previews of the selected value on load + * Use new unified `Utils::getPagePathFromToken()` method rather +1. [](#bugfix) + * Fix for undefined `include_metadata` error + + +# v1.5.0-rc.1 +## 05/16/2017 + +1. [](#new) + * Add support for a single array field in forms + * Added Prev/Next support on page editing view [#1112](https://github.com/getgrav/grav-plugin-admin/pull/1112) +1. [](#improved) + * Improved full-screen editor for better browser compatibility [#1093](https://github.com/getgrav/grav-plugin-admin/pull/1093) + * Added ability to choose how you want the preview button to open [#1096](https://github.com/getgrav/grav-plugin-admin/pull/1096) + * `base.html.twig` now extends a `base-root.html.twig` file + * Add month+date indication to the stats graph to avoid confusion when there are days without visits + * Added `min` and `max` options for `list` form field [#1113](https://github.com/getgrav/grav-plugin-admin/pull/1113) + * Remove page metadata file on deletion of media + * Improved layout on pages list for pages with long titles [#1102](https://github.com/getgrav/grav-plugin-admin/pull/1102) + * Added option to make custom "Add page" dropdown entries [#1104](https://github.com/getgrav/grav-plugin-admin/pull/1104) +1. [](#bugfix) + * Fixed issue with tab widths on Pages overlapping non-english toggle switch [#1089](https://github.com/getgrav/grav-plugin-admin/issues/1089) + * Added `vendor` to ignores for direct install of Grav + * Translated `field.default` for `editor` form field + * Fixed an quote error in `en.yaml` + * Resolved z-index issues with mobile nav and pages form elements + * Fixed issue with file picker where the selected file preview would not show + * Refresh page media on media upload + * Default to config file slug if translation is missing, otherwise use translation also in the tab title, not just in the page heading [#1039](https://github.com/getgrav/grav-plugin-admin/issues/1039) + * Fix language toggle button in admin top bar visible also in fullscreen mode [#1110](https://github.com/getgrav/grav-plugin-admin/issues/1110) + * Fix for editor padding [#1111](https://github.com/getgrav/grav-plugin-admin/issues/1111) + * Fix tabs inside blueprint overlapping above content [#1115](https://github.com/getgrav/grav-plugin-admin/pull/1115) + +# v1.4.2 +## 04/24/2017 + +1. [](#new) + * Added a new `Content Padding` option to tighten up UI padding space (default `true`) +1. [](#bugfix) + * Added back `Admin::initTheme()` relying on Grav fix [#1069](https://github.com/getgrav/grav-plugin-admin/pull/1069) as it conflicts ith Gantry5 + * Fix for missing scrollbar when in full-size editor for Firefox [#1077](https://github.com/getgrav/grav-plugin-admin/issues/1077) + * Fix for overlay of Add-Page button in full-size editor [#1077](https://github.com/getgrav/grav-plugin-admin/issues/1077) + * Better fix for session-based parent overriding root page parents [#1078](https://github.com/getgrav/grav-plugin-admin/issues/1078) + * Allow support for `Pages::getList()` with `show_modular` option [#1080](https://github.com/getgrav/grav-plugin-admin/issues/1080) + * Added `[tmp,user]` ignores for direct install of Grav [grav#1447](https://github.com/getgrav/grav/issues/1447) + +# v1.4.1 +## 04/19/2017 + +1. [](#bugfix) + * Reverted [#1069](https://github.com/getgrav/grav-plugin-admin/pull/1069) as it conflicts ith Gantry5 + +# v1.4.0 +## 04/19/2017 + +1. [](#new) + * Added ability to add new pages/folders while editing existing page +1. [](#improved) + * Initialize theme in Admin Plugin [#1069](https://github.com/getgrav/grav-plugin-admin/pull/1069) + * Use new system configuration entries for username and password format + * Reworked Page parent field to use `Pages::getList()` rather than logic in Twig field itself + * More robust styling of admin themes page [#1067](https://github.com/getgrav/grav-plugin-admin/pull/1067) + * Fix fullscreen editor height [#1065](https://github.com/getgrav/grav-plugin-admin/pull/1065) + * Fix small UI issue in the editor with `codemirror.lineNumbers` && `codemirror.styleActiveLine` enabled + * Fix UI performance issue in the dashboard [#1064](https://github.com/getgrav/grav-plugin-admin/issues/1064) +1. [](#bugfix) + * Fixed issue with parent not working with custom slug [#1068](https://github.com/getgrav/grav-plugin-admin/issues/1068) + * Fixed issue with new page modal not remembering last choice [#1072](https://github.com/getgrav/grav-plugin-admin/issues/1072) + +# v1.3.3 +## 04/12/2017 + +1. [](#bugfix) + * Fix for regression introduced in the automatic page template switch when changing page parent [#1059](https://github.com/getgrav/grav-plugin-admin/issues/1059) [grav#1403](https://github.com/getgrav/grav/issues/1403) [#1062](https://github.com/getgrav/grav-plugin-admin/issues/1062) + * Fix issue with editor field in lists [#1037](https://github.com/getgrav/grav-plugin-admin/issues/1037) + +# v1.3.2 +## 04/10/2017 + +1. [](#improved) + * Added new 'parents' field and switched Page blueprints to use this +1. [](#bugfix) + * Fix for regression in h3 style in the Spacer field [#267](https://github.com/getgrav/grav-plugin-admin/issues/267) + * Fix missing preview in page media for SVG images [#1051](https://github.com/getgrav/grav-plugin-admin/issues/1051) + * Fix missing check when reordering [#1053](https://github.com/getgrav/grav-plugin-admin/issues/1053) + * Fix for editors not getting refreshed when changing tab [#1052](https://github.com/getgrav/grav-plugin-admin/issues/1052) + * Fix for mobile tabs in page editing [#1057](https://github.com/getgrav/grav-plugin-admin/issues/1057) + +# v1.3.1 +## 03/31/2017 + +1. [](#bugfix) + * Fix for `Undefined index: file_path` error with Direct Install [#1043](https://github.com/getgrav/grav-plugin-admin/issues/1043) + +# v1.3.0 +## 03/31/2017 + +1. [](#new) + * User uploadable avatar (still falls back to Gravatar if not provided) +1. [](#improved) + * Improved tabs CSS to handle long titles [#1036](https://github.com/getgrav/grav-plugin-admin/issues/1036) + * Fixed `step` in range field [Form#136](https://github.com/getgrav/grav-plugin-form/issues/136) +1. [](#bugfix) + * Fixed issue with exception thrown when `copying` and `moving` a page [#1042](https://github.com/getgrav/grav-plugin-admin/issues/1042) + * Automatically calculate the *next* numeric folder prefix [Core#1386](https://github.com/getgrav/grav/issues/1386) + +# v1.3.0-rc.3 +## 03/22/2017 + +1. [](#new) + * All new `Page Ordering` implementation. Completely revamped and will only reorder with folder-prefix enabled. You can now reorder all siblings at the same time. + * Added a new `Advanced - Override` to allow option to display pages by folder name (default) or Collection definition + * Improved `range` form field with touch and counter support [#1016](https://github.com/getgrav/grav-plugin-admin/pull/1016) +1. [](#bugfix) + * Cleanup package files via GPM install to make them more windows-friendly [#1361](https://github.com/getgrav/grav/pull/1361) + +# v1.3.0-rc.2 +## 03/17/2017 + +1. [](#improved) + * Do not attempt to fetch any notification if settings are disabled [#942](https://github.com/getgrav/grav-plugin-admin/issues/942) + +# v1.3.0-rc.1 +## 03/13/2017 + +1. [](#new) + * New flex-based/js Tabs system for better flexibility and improved UX. + * Added new **toolbox** with `Direct-Install` option via ZIP or URL. + * Added an option to reinstall a plugin/theme already installed [#984](https://github.com/getgrav/grav-plugin-admin/issues/984) + * Added a new **range field** [#995](https://github.com/getgrav/grav-plugin-admin/issues/995) + * When creating a new page, automatically select the Page Template based on Parent Page Child Type [#1008](https://github.com/getgrav/grav-plugin-admin/issues/1008) +1. [](#improved) + * Page Media field now is available when folder is created, not just markdown file [#1000](https://github.com/getgrav/grav-plugin-admin/issues/1000) + * Separated user details and avatar in separate twig to allow more granular overriding in plugins [#989](https://github.com/getgrav/grav-plugin-admin/issues/989) + * Nicer layout of themes list on wider screen + * Editor full-screen option displays title/save options [#948](https://github.com/getgrav/grav-plugin-admin/issues/948) + * Use native OS highlight colors for the editor [#977](https://github.com/getgrav/grav-plugin-admin/issues/977) + * Force admin pages to set `Page::expires(0)` so it's not cached [#1009](https://github.com/getgrav/grav-plugin-admin/issues/1009) + * Added support for up to 15 tabs (was 10) [#954](https://github.com/getgrav/grav-plugin-admin/issues/954) + * Only reorder pages in the admin if collection uses `@self` and `order.by` + * Improved configuration tab sizes when you have lots of tabs + * Modified default media select size from 150px x 100px to 200px x 150px +1. [](#bugfix) + * Fixed rendering issue with Chrome and sortables collections [#1002](https://github.com/getgrav/grav-plugin-admin/issues/1002) + * Fixed issue with removal of file that has been just uploaded and stored in the session + + +# v1.2.14 +## 02/17/2017 + +1. [](#bugfix) + * Fixed bad bug with `GPM::install()` from a change in Admin v1.2.13 + +# v1.2.13 +## 02/17/2017 + +1. [](#bugfix) + * Fix issue with validating page when switching language [#963](https://github.com/getgrav/grav-plugin-admin/issues/963) + * Fix issue with quotes in Admin strings used in JS [#965](https://github.com/getgrav/grav-plugin-admin/issues/965) + * Refactored `AdminController::taskGetUpdates` to use standard task/response [#980](https://github.com/getgrav/grav-plugin-admin/issues/980) + * Sync Admin pages blueprints with core [core#212d35221a9bbcc242508ba49a551b3f6e62af8e](https://github.com/getgrav/grav/commit/212d35221a9bbcc242508ba49a551b3f6e62af8e) + +# v1.2.12 +## 02/12/2017 + +1. [](#bugfix) + * Rebuilt the JS bundle to address various JS-related issues that cropped up in `v1.2.11` + * Fixed Firefox Network Error issue when updating multiple plugins/themes at concurrently [#1301](https://github.com/getgrav/grav/issues/1301) + +# v1.2.11 +## 02/10/2017 + +1. [](#new) + * Added lang strings for `CLI_COMPATIBILITY` which is new in Grav v1.1.16 +1. [](#improved) + * Allow plugin to set custom 'authorize' and 'location' in `onAdminMenu()` event + * Updated all language files with latest from [Crowdin](https://crowdin.com/project/grav-admin) +1. [](#bugfix) + * Fixed issue `admin.super` or `admin.users` users changing the account when saving another user [#713](https://github.com/getgrav/grav-plugin-admin/issues/713) + * Fix issue where non `admin.super`/`admin.users` users could see other users profiles [#713](https://github.com/getgrav/grav-plugin-admin/issues/713) + * Fix removing responsive image from page media [#111](https://github.com/getgrav/grav-plugin-admin/issues/111) [#952](https://github.com/getgrav/grav-plugin-admin/issues/952) + * Use @2x & @3x fallback images in the filepicker. [#952](https://github.com/getgrav/grav-plugin-admin/issues/952) + +# v1.2.10 +## 1/30/2017 + +1. [](#improved) + * It is now possible to manually specify a format for the `datetime` field [#1261](https://github.com/getgrav/grav/issues/1261) + * Allow to see plugins and themes list without internet connection. Also add a more helpful message in the "add" view [grav#1008](https://github.com/getgrav/grav/issues/1008) +1. [](#bugfix) + * Fixed issue with downloaded package when installing a testing release + * Allow non admin.super users to change their account information. Allow `admin.super` and `admin.users` to change other users information. [#943](https://github.com/getgrav/grav/issues/943) + * Handle removing a media file also if it's not a json request. Was not working after https://github.com/getgrav/grav-plugin-admin/commit/6b343365996ce838759d80fa3917d4d994f1aeb4 + +# v1.2.9 +## 01/18/2017 + +1. [](#improved) + * Added lang strings for `ALLOW_WEBSERVER_GZIP` in System configuration + +# v1.2.8 +## 01/17/2017 + +1. [](#improved) + * Allow the ability to clear the cache if `admin.maintenance`, as stated in the docs [#908](https://github.com/getgrav/grav-plugin-admin/issues/908) + * Added lang strings for `DEFAULT_LANG` in Site configuration + * Added lang strings for `NEVER_CACHE_TWIG` in System and Page configuration +1. [](#bugfix) + * Fixed saving the configuration if not `admin.super` + * Show the clear cache buttons if the user has `admin.cache` permissions [#908](https://github.com/getgrav/grav-plugin-admin/issues/908#issuecomment-270748616) + * Fix colorpicker validation when transparency is set to 1.00 [#921](https://github.com/getgrav/grav-plugin-admin/issues/921) + * Fix html markup in section twig [#922](https://github.com/getgrav/grav-plugin-admin/pull/922) + * Fix bug in deleting a file uploaded with the `file` field [#920](github.com/getgrav/grav-plugin-admin/issues/920) + * Fix for plugin throwing event-based errors when plugin is removed and no longer available to process said event + +# v1.2.7 +## 12/22/2016 + +1. [](#improved) + * Fixed an issue with non `.html` extensions not setting application type properly when fallback template not found. +1. [](#bugfix) + * Fix plugins and themes json calls after the introduction of [HTML fallback for templates not found](https://github.com/getgrav/grav/commit/364209a27da0f5dfba5fde9c4b07b6d5844cda47) + + +# v1.2.6 +## 12/21/2016 + +1. [](#improved) + * Added a delay before reloading the page when a plugin or theme get installed + * Fix prompting to remove Grav itself when removing a package that requires a specific Grav version + * Remove cli-server exception since we now have compatibility with a custom router in Grav [#1219](https://github.com/getgrav/grav/pull/1219) +1. [](#bugfix) + * Fix issue with array field and `value_only: true` + +# v1.2.5 +## 12/13/2016 + +1. [](#new) + * RC released as stable +1. [](#bugfix) + * YAML syntax fixes + +# v1.2.5-rc.4 +## 12/07/2016 + +1. [](#new) + * Added a new `permissions` form field, used in the user profile to simplify editing permissions + * Added several new `onAdminAfter...()` events to allow for more 3rd party plugin interaction +1. [](#bugfix) + * Updated admin-user-details to allow longer user names in the sidebar [#879](https://github.com/getgrav/grav-plugin-admin/issues/879) + * Redirect to a 404 page when accessing nonexistent plugins and themes [#880](https://github.com/getgrav/grav-plugin-admin/issues/880) + +# v1.2.5-rc.3 +## 11/26/2016 + +1. [](#bugfix) + * Update class namespace for Admin class [#874](https://github.com/getgrav/grav-plugin-admin/issues/874) + * Fix updating/installing packages from admin + +# v1.2.5-rc.2 +## 11/19/2016 + +1. [](#bugfix) + * Make default value work for filepicker [#859](https://github.com/getgrav/grav-plugin-admin/issues/859) + +# v1.2.5-rc.1 +## 11/09/2016 + +1. [](#new) + * Updated to FontAwesome 4.7.0 with [Grav icon](http://fontawesome.io/icon/grav/) +1. [](#improved) + * Always delete image alternatives in AdminController#taskDelmedia [#814](https://github.com/getgrav/grav-plugin-admin/issues/814) + * Use Media class to retrieve files in AdminController#taskGetFilesInFolder [#842](https://github.com/getgrav/grav-plugin-admin/issues/842) + * Increased specificity for Colorpicker field to prevent 3rd party conflicts +1. [](#bugfix) + * Editor link button doesn't prefix links with `http://` anymore [#813](https://github.com/getgrav/grav-plugin-admin/issues/813) + * Dashboard Charts now always refresh no matter what [#753](https://github.com/getgrav/grav-plugin-admin/issues/753) + * Use rawRoute for parent too when saving [#843](https://github.com/getgrav/grav-plugin-admin/issues/843) + * Avoid different output when users exist or not in password recovery [#849](https://github.com/getgrav/grav/issues/849) + * Fix login to admin with permission inherited from group [#857](https://github.com/getgrav/grav-plugin-admin/issues/857) + + +# v1.2.4 +## 10/22/2016 + +1. [](#bugfix) + * Fix for accented media files [#833](https://github.com/getgrav/grav-plugin-admin/issues/833) + * Fix for `CTRL + s` not saving in editor [#832](https://github.com/getgrav/grav-plugin-admin/pull/832) + * Fix for missing REDIS translations in admin [#1123](https://github.com/getgrav/grav/issues/1123) + +# v1.2.3 +## 10/19/2016 + +1. [](#new) + * Added new `onAdminCreatePageFrontmatter()` event to support plugins such as `auto-date` by allowing frontmatter to be modified by plugins. + * Added a new independent `cache_enabled` option for admin plugin (default is `false`). Should fix various sync issues. + * Add an `onAdminData` event to allow plugins to add additional blueprints data +1. [](#improved) + * Handle errors when a resource fails to install + * Page media and File field images thumbnail are now properly proportionate and 150x100 + * Added the Codeception testing suite with an initial test +1. [](#bugfix) + * Fix [#1034](https://github.com/getgrav/grav/issues/1034) redirect of page creation procedure when system.home.hide_in_urls is enabled + * Media (Page): Do not extend parent metehod for sending files since Safari and IE API for FormData don’t implement `delete` ([#772](https://github.com/getgrav/grav-plugin-admin/issues/772)) + * Clean up POST keys containing square brackets, allows for regex ranges in routes ([#776](https://github.com/getgrav/grav-plugin-admin/issues/776)) + * Fix [#773](https://github.com/getgrav/grav-plugin-admin/issues/773) allow filepicker work inside lists, respond to mutation event + * Better error handling for Feed when unable to connect + * Fixed UI for Pagemedia note when files cannot yet be uploaded ([#798](https://github.com/getgrav/grav-plugin-admin/issues/798)) + * Fixed Submit buttons getting disabled in case of form invalidity disallowing to submit again ([#802](https://github.com/getgrav/grav-plugin-admin/issues/802)) + * Fixed issue when reading the file size setting if set to `0` (in Pagemedia and File fields) + * Fixed issue with `file` field in collections that caused unexpected duplication of items ([#775](https://github.com/getgrav/grav-plugin-admin/issues/775)) + * Dramatically improved `filepicker` performance. Data is only ever loaded when the drop-down is on focus, as it was supposed to be. Image preview of a selected item won't be rendered unless the field gains focus to avoid wasting resources. ([#788](https://github.com/getgrav/grav-plugin-admin/issues/788)) + * Allow `filepicker` field to peak at the pending uploaded files and optimistically select them ([#792](https://github.com/getgrav/grav-plugin-admin/issues/792)) + * Fix [#821](https://github.com/getgrav/grav-plugin-admin/issues/821) issue in saving a page to a new language when the filename does not contain the filename yet. + +# v1.2.2 +## 09/08/2016 + +1. [](#bugfix) + * Fix [#767](https://github.com/getgrav/grav-plugin-admin/issues/767) Add styling for new HTML5 input field types + * Fix issue with checking the package dependencies when more than one package is being inspected + +# v1.2.1 +## 09/07/2016 + +1. [](#bugfix) + * Fixed `tmp://` stream issue with Admin updated to 1.2 before Grav updated 1.1.4 + +# v1.2.0 +## 09/07/2016 + +1. [](#new) + * All new `file` field. All files get uploaded via Ajax and are stored upon Save. This improves the Save task tremendously as now there is no longer the need of waiting for the files to finish uploading. Fully backward compatible, `file` field now includes also a `limit` and `filesize` option in the blueprints. The former determines how many files are allowed to be uploaded when in combination with `multiple: true` (default: 10), the latter determines the file size limit (in MB) allowed for each file (default: 5MB) + * Added a new `filepicker` field, which allows to pick any file from an ajax-powered select box. The `pagemediaselect` field now internally uses the `filepicker` field to live-reload the available files, and to show image previews. +1. [](#improved) + * Better error handling for 500 Internal Server Errors, when Fetch fails + * Various notifications style and other CSS fixes + * More language strings added + * Added `clear-tmp` to cache clear drop-down + * Unified JSON twig templates + * Better error handling for 500 Internal Server Errors, when Fetch fails. + * Updated vendor Libraries +1. [](#bugfix) + * Curl fix for invalid cert errors with News Feed + * Avoid requiring `admin.super` for ajax calls [#739](https://github.com/getgrav/grav-plugin-admin/issues/739) + * Fix showing HTML in notifications, in the feed + * Fixed broken page type filtering + * Fixed `beforeunload` event not prompting to offer the choice to stay on the page in case of unsaved changes + * Fixed click-away detection for preventing loss of changes, that would get ignored in some circumstances (ie, from modal confirmation) + * Fixed issue with `_json` elements where nested fields merging would get stored in an unexpected way + * Fixed composer dependencies missing error message + +# v1.1.4 +## 08/14/2016 + +1. [](#bugfix) + * Fixed Firefox News Feed dashboard widget layout + +# v1.1.3 +## 08/10/2016 + +1. [](#new) + * Admin notifications system. Admin will pull and cache notifications. This will be used to announce important updates, security vulnerabilities, and general interest news. + * Ability to disable widgets in the dashboard + * Added news feed widget to the dashboard +1. [](#improved) + * Updated FontAwesome to v4.6.3 + * Use new List functionality for Media Configuration + * Get fresh media list for `Controller::getListMedia()` rather that cache so always latest. + * Add translation strings for the new system.force_ssl option + * Reworked List UI to better handle drag & drop sort. To sort it is now required to use the left drag handle [#724](https://github.com/getgrav/grav-plugin-admin/issues/724) + * Lists now features a new YAML option `controls: [top|bottom|both]` (default: bottom) which will display the "Add Item" button at the Top and/or Bottom position relative to the list. When the Top button is pressed, a new item will be added at the beginning of the list, when the Bottom button is pressed, a new item will be appended to the list. + * Lists now features two new YAML options `sortby: [field]` (default: disabled) and `sortby_dir: [asc|desc]` (default: asc) which will display a new Sorting button in the list allowing to automatically reindex the collection based on the given sort field set. + * Lists now features a new YAML option `collapsed: [true|false]` (default: false) and a new UI/UX that allows for collapsing / expanding collection items, allowing to better managing long lists of items. It is advised to always put as first field the most significant one, so that when a list is collapsed it can be still easily browsed. + * It is now possible to sort Array fields via drag & drop [#950](https://github.com/getgrav/grav/issues/950) +1. [](#bugfix) + * Fixed issue in Admin favicon URL [#704](https://github.com/getgrav/grav-plugin-admin/issues/704) + * Fixed issue in `selfupgrade` where the package would get downloaded in the wrong destination + * Hide tab when user is not authorized to access it [#712](https://github.com/getgrav/grav-plugin-admin/issues/712) + * Fixed Lists issue when reindexing, causing Radio fields to potentially lose their `checked` status + * Avoid overwriting a file when uploaded with the same filename through the Admin blueprint `file` field type if `avoid_overwriting` is enabled on the field + * Fixed issue with Array field in `value_only` mode, improperly displaying the key when no value was set + * Translate the description of a blueprint field [#729](https://github.com/getgrav/grav-plugin-admin/issues/729) + +# v1.1.2 +## 07/16/2016 + +1. [](#improved) + * Forcing limit of upload files based on System settings +1. [](#bugfix) + * Definitive fix for multi form submission in Microsoft Edge causing the Save to not work [#694](https://github.com/getgrav/grav-plugin-admin/issues/694) + * Fix issue with calculating the `theme_url` with `open_basedir` restrictions [#699](https://github.com/getgrav/grav-plugin-admin/issues/699) + * Check for null payload before going on [#526](https://github.com/getgrav/grav-plugin-admin/issues/526) + * Redraw Dashboard Charts when collapsing/expanding the sidebar + * Fix for `cache/compiled` errors resulting from page media uploads [getgrav/grav#938](https://github.com/getgrav/grav/issues/938) + +# v1.1.1 +## 07/14/2016 + +1. [](#bugfix) + * Fixed issue with forms causing creation of new pages not to work [#698](https://github.com/getgrav/grav-plugin-admin/issues/698) and [getgrav/grav#934](https://github.com/getgrav/grav/issues/934) + +# v1.1.0 +## 07/14/2016 + +1. [](#improved) + * Added the ability to login with the email in addition to the username. [#674](https://github.com/getgrav/grav-plugin-admin/issues/674) + * It is now possible to sort the Plugins and Themes views by 'Name', 'Author', 'GravTeam', 'Release Date', 'Updates Available' and 'Testing' releases (if in Testing Channel), both Ascending and Descending. [#583](https://github.com/getgrav/grav-plugin-admin/issues/583) + * Prevent external links (like the Preview button) to trigger the "Changes Detected" notice [#689](https://github.com/getgrav/grav-plugin-admin/issues/689) + * Added a filter field in Plugins and Themes list views, to allow for quick search of a particular resource + * Added new `Enabled` sorting option for Plugins list view +1. [](#bugfix) + * Fixed an issue that prevented removing more than one page, in the pages listng [#672](https://github.com/getgrav/grav-plugin-admin/issues/672) + * Fixed toggleables in lists that were always loading as checked even when not stored [#688](https://github.com/getgrav/grav-plugin-admin/issues/688) + * Fixed Fullscreen tooltip in Editor displaying off screen (when in fullscreen mode) [#677](https://github.com/getgrav/grav-plugin-admin/issues/677) + * Fixed inconsistency in the way selectized fields would be rendered [#692](https://github.com/getgrav/grav-plugin-admin/issues/692) + * Fixed issue with Save in Microsoft Edge [#694](https://github.com/getgrav/grav-plugin-admin/issues/694) + +# v1.1.0-rc.4 +## 06/21/2016 + +1. [](#bugfix) + * Fix for 'front-end' shortcut showing in mobile sidebar incorrectly. + * Append progressive number to the copied page title. [#394](https://github.com/getgrav/grav-plugin-admin/issues/394) + * Add field description to forms [#667](https://github.com/getgrav/grav-plugin-admin/pull/667) + * Fix clearing all cache [#658](https://github.com/getgrav/grav-plugin-admin/issues/658) + * Assign the correct ordering when saving a page that didn't have ordering set before [#628](https://github.com/getgrav/grav-plugin-admin/issues/628) + * Fix issue when saving a modular child folder as 05.somethin and being reset to 01.something upon save [#628](https://github.com/getgrav/grav-plugin-admin/issues/628) + +# v1.1.0-rc.3 +## 06/14/2016 + +1. [](#bugfix) + * Fix for Gemini Scrollbar CSS breaking layout in IE 9+ [#644](https://github.com/getgrav/grav-plugin-admin/issues/644) + * Fall back to english for UI language if admin's language is not set [#641](https://github.com/getgrav/grav-plugin-admin/issues/641) + * List field has the wrong label/field width. Switched to "1/3 | 2/3" like all other fields. + * Correctly set the page slug on page copy. Avoids having two pages with the same slug [#394](https://github.com/getgrav/grav-plugin-admin/issues/394) + * When copying a page, if there's a page prefix (used for ordering), update the value to avoid having two pages with the same order number [#429](https://github.com/getgrav/grav-plugin-admin/issues/429) + * Fixed size of dropdown text in responsive views to be readable [#647](https://github.com/getgrav/grav-plugin-admin/issues/647) + * Fixed issue with checkbox in toggleables getting submitted with the form even when disabled (fixes #646) + +# v1.1.0-rc.2 +## 06/02/2016 + +1. [](#improved) + * Cleaned up the Page Preview CSS to make it more 'standard' [#634](https://github.com/getgrav/grav-plugin-admin/issues/634) + * Added a legend with the Page colors explained [#637](https://github.com/getgrav/grav-plugin-admin/issues/637) + * Hide email output when sending forgot password instructions [#571](https://github.com/getgrav/grav-plugin-admin/issues/571) +1. [](#bugfix) + * Fixed "Data type `System` doesn't exist!" error when activating a theme [#635](https://github.com/getgrav/grav-plugin-admin/issues/635) + * Fixed issue with custom media types not deleting on save [#633](https://github.com/getgrav/grav-plugin-admin/issues/633) + * Fixed issue when saving `List` field type in plugins + pages + * Fixed JS error on login/logout page due to jQuery not being loaded + + +# v1.1.0-rc.1 +## 06/01/2016 + +1. [](#new) + * Major improvements with the **File Upload** (`file`) field type. Now fully supports themes, plugins, configuration + pages +1. [](#improved) + * Updated with latest languages via [Crowdin](https://crowdin.com/project/grav-admin/) + * Provide security options for single tabs [#615](https://github.com/getgrav/grav-plugin-admin/issues/615) + * Disable double clicking on Save/Delete/Copy page actions [#611](https://github.com/getgrav/grav-plugin-admin/issues/611) + * Tweaked the avatar alignment in sidebar [#592](https://github.com/getgrav/grav-plugin-admin/issues/592) + * Added page name to delete dialog [#511](https://github.com/getgrav/grav-plugin-admin/issues/511) + * Enabling / Disabling a Plugin doesn't trigger the expand / collapse details anymore [#614](https://github.com/getgrav/grav-plugin-admin/issues/614) + * Added hover on plugins list rows to match pages [#619](https://github.com/getgrav/grav-plugin-admin/issues/619) + * Translate media configuration [#608](https://github.com/getgrav/grav-plugin-admin/issues/608) + * Use raw routes in blueprints to better support multi-language [#798](https://github.com/getgrav/grav-plugin-admin/issues/798) + * Updated NPM modules dependencies +1. [](#bugfix) + * Fix double "Removed successfully" appearing when removing a package [#609](https://github.com/getgrav/grav-plugin-admin/issues/609) + * Prevent removing required plugins dependencies when removing a package [#613](https://github.com/getgrav/grav-plugin-admin/issues/613) + * Show page title in Delete Confirmation modal if this information is available + * Don't try to uninstall admin/form/login/email plugins + * Only check for updates if not `admin.maintenance` or `admin.super` [#557](https://github.com/getgrav/grav-plugin-admin/issues/557) + * Always submit checkboxes that are not checked and force a 0 value [#616](https://github.com/getgrav/grav-plugin-admin/issues/616) + * Fix encoding in tooltips again [#622](https://github.com/getgrav/grav-plugin-admin/issues/622) + * Do not show `move` cursor for Collections that aren't sortable [#624](https://github.com/getgrav/grav-plugin-admin/issues/624) + * Properly handle Collections that specify a custom key, rather than falling back to indexed list [#632](https://github.com/getgrav/grav-plugin-admin/issues/632) + +# v1.1.0-beta.5 +## 05/23/2016 + +1. [](#improved) + * Set sidebar navigation defaults back to "Tab Activation" and "Auto Width" + * Custom logo text is displayed as first letter in small sidebar view [#829](https://github.com/getgrav/grav/issues/829) + * Copied admin-only blueprints from Grav core to the Admin plugin + * Allow `field.label` to have HTML in it [#601](https://github.com/getgrav/grav-plugin-admin/issues/601) +1. [](#bugfix) + * Fixed Togggle field with doubled `checked="checked"` when `toggleable: true` [#579](https://github.com/getgrav/grav-plugin-admin/issues/579) + * Strip HTML tags and lowercase username from login/reset forms [#577](https://github.com/getgrav/grav-plugin-admin/issues/577) + * Fixed issue with version numbers not showing up for dependencies [#581](https://github.com/getgrav/grav-plugin-admin/issues/581) + * Fixed editor tooltips in fullscreen mode and tablet devices rendering [#566](https://github.com/getgrav/grav-plugin-admin/issues/566) + * Fixed issue with `file` form field not functioning [#838](https://github.com/getgrav/grav/issues/838) + * Fixed issue with creating pages [#595](https://github.com/getgrav/grav-plugin-admin/issues/595) + +# v1.1.0-beta.4 +## 05/09/2016 + +1. [](#new) + * Implemented Quickopen functionality to automatically open / close the Sidebar when mouseover +1. [](#improved) + * Better error handling when `obj->validate()` fails with exception [#594](https://github.com/getgrav/grav-plugin-admin/issues/564) + * Improve markup of update and add package dependencies in update modal [#560](https://github.com/getgrav/grav-plugin-admin/issues/560) +1. [](#bugfix) + * Fix for admin translation filter (`|tu`) not substituting text - [#567](https://github.com/getgrav/grav-plugin-admin/issues/567) + * Translated "Publishing" tab text [#561](https://github.com/getgrav/grav-plugin-admin/issues/561) + * Fix invalid argument supplied in foreach [#563](https://github.com/getgrav/grav-plugin-admin/issues/563) + * CSS fixes for editor button alignment + * Fix for forgot password not finding anyone + * Fix UI issue with update button on a package page in Firefox + * Fix issue with update button when automatic check for updates is disabled + * Fix issue caused by clicking "Check for updates" multiple times + * Added missing translations + * Fix for Themes with an array of keywords [#823](https://github.com/getgrav/grav/issues/823) + +# v1.1.0-beta.3 +## 05/04/2016 + +1. [](#new) + * Added a `|adminNicetime` Twig filter to show 'nicetime' in admin user's language + * Added a `prepend` and `append` field option for text input type + * Added a WIP `onAdminRegisterPermissions` event + * Added several new languages: Arabic, Danish, Greek, Farsi, Korean, Romanian, Thai. Huge thanks to the [translation teams](https://crowdin.com/project/grav-admin) +1. [](#improved) + * Fixed UI issue with Backup / Update buttons positioning + * Tweaked placeholders color in login/new user panels [#542](https://github.com/getgrav/grav-plugin-admin/issues/542) +1. [](#bugfix) + * Fixed several untranslated strings + * Fix the version information after updating Grav from Admin + * Fix a Twig autoescape issue on Plugins descriptions + * Fix for showing empty drop-down with only one supported language [#522](https://github.com/getgrav/grav-plugin-admin/issues/522) + * Fix for visibility toggle on new page not working [#551](https://github.com/getgrav/grav-plugin-admin/issues/551) + * Page tooltips usability issue [#496](https://github.com/getgrav/grav-plugin-admin/issues/496) + * Fix removed title attribute from editor toolbar buttons [#539](https://github.com/getgrav/grav-plugin-admin/issues/539) + * Allow Incognito / Private browsing to still function in Safari [#527](https://github.com/getgrav/grav-plugin-admin/issues/527) + +# v1.1.0-beta.2 +## 04/27/2016 + +1. [](#new) + * Added `grav ~1.1` to dependencies + * Added a persistent message if you try to run Admin 1.1 on Grav 1.0 +1. [](#improved) + * Used locator instead of `CACHE_DIR` + * Added a better way to get Admin version + * Show account page for users with certain ACL [#524](https://github.com/getgrav/grav-plugin-admin/pull/524) +1. [](#bugfix) + * Fixed Editor Preview using wrong parameters for the ajax call + * Fixed toggle for stable/testing channel + * Fixed blueprint JSON fields + * If not logged in redirect to base path [#445](https://github.com/getgrav/grav-plugin-admin/pull/445) + * Various autoescape fixes + * ColorPicker CSS fixes + * Fix for translation of admin login [#500](https://github.com/getgrav/grav-plugin-admin/issues/500) + * Fix list not applying `toggleable: true` and `style: vertical` [#518](https://github.com/getgrav/grav-plugin-admin/pull/518) + * Fixed issue with update for wrong plugin displaying on plugin details pages + * Fixed error with the **close sidebar** toggle in some browsers (Firefox, iOS Safari) + +# v1.1.0-beta.1 +## 04/20/2016 + +1. [](#new) + * JavaScript Rewrite. Admin is now built in ES6 + * Lists can now be nested and 'fancy fields' (such as editor, datetime picker, selectize, other lists) get automatically initialized so they are always available no matter if you add or remove items from the lists + * The Editor has been reworked to be more flexible. In fact you can now pass any CodeMirror setting via blueprints, through the codemirror: attribute. The buttons have also a new API that allow to add or ignore buttons and behaviors into the toolbar from any plugin (see grav-plugin-editor-buttons). We also added the headers buttons (H1-H6) and Undo / Redo buttons, due to popular demand + * We introduced a new colorpicker field. You can now add more colors to your admin plugins :) + * Along with the versioning support added in the Grav Core for 1.1, the admin plugin can now install dependencies with the same versioning requirements as the GPM CLI commands. + * New System configuration field for toggling GPM release version (testing/stable) + * Several new system configuration options for new functionality such as `Process frontmatter Twig` + * Ability to collapse the sidebar to a smaller icon view if you need more room. +1. [](#improved) + * The default Grav theme has been tweaked and in many places completely rewritten to ensure that it's as flexible as possible. The primary reason for this was to ensure theming and customization compatibility for the upcoming Admin Pro plugin, but a key benefit includes greatly improved mobile compatibility. + * We reworked the Datetimepicker, you will notice a new refreshed UI with a much better support for translations + * Tabs are now persistent. In views such as Page editing, when switching tab and saving or refreshing, would cause the tab to be reset to the initial one. + * When editing a page in Expert mode, the frontmatter editor is now more friendly. You will now get line numbers, undo/redo and YAML linter. + * Behind the scenes we have reworked how the form and toggleables work. This added a lot more reliability and consistency across the whole admin. + * The Pages view has more persistent states. It will now remember your expanded/collapsed states as well as filtering. + * Lists can now accept a custom button label with the 'btnLabel' property + * After login to Admin, redirect to the original URL called + * Admin now has an unique cache key compared to the 'site' so pages can be cached independently + * Improved the layout of the User Profile page. + * Set cache key uniquely for admin so cache does not colide with site +1. [](#bugfix) + * Fix for modular preview - [#254](https://github.com/getgrav/grav-plugin-admin/issues/254) + * Fix for long content and page tabs - [#441](https://github.com/getgrav/grav-plugin-admin/issues/441) + * Fix for clear cache after adding new folder - [#393](https://github.com/getgrav/grav-plugin-admin/issues/393) + +# v1.0.9 +## 02/11/2016 + +1. [](#bugfix) + * Fix language translation files + +# v1.0.8 +## 02/05/2016 + +1. [](#new) + * Added a logout button when not authorized to access a page in Admin + * Added the option to hide a tab from an extended blueprint (https://github.com/getgrav/grav/issues/620) + * Many new languages and updates to existing languages from the Translation team. +1. [](#improved) + * Check frontmatter for validity prior to saving + * Add noindex, nofollow across the entire admin theme if no other robots headers are set on a page + * Allow to hide a configuration blueprint section / tab and still save its values + * Allow to show user defined blueprints in configuration + * Updated FontAwesome to latest 4.5.0 version +1. [](#bugfix) + * Fixed an issue with user registration on Linux caused by `glob()` possibly returning false. + * Fixed an issue preventing Admin to work correctly in a multisite configuration + * Fixed preview and insertion of images with non-lowercase extension + * Fixed an incorrect number of pages being displayed in the sidebar in some cases + * [Security] Don't reveal Grav filesystem path when trying to delete non-existing images + * [Security] Fix PHP error happening when uploading file without extension if the JS dropzone uploader is configured to allow empty file extensions + * [Security] Ensure correct escaping in various Twig files + +# v1.0.7 +## 01/15/2016 + +1. [](#new) + * Added onAdminDashboard event + * Added onAdminSave event + * New lang strings for reverse proxy toggle +1. [](#improved) + * More robust YAML file checking in config folders + * Removed deprecated menu event + * Removed old logs code + * Used new onAdminDashboard event for current dashboard widgets +1. [](#bugfix) + * Fix for missing access checks on config pages #397 + * Fix parent not loaded on admin form save #587 + * When no route field is added to a page blueprint, add it as page root + * Fix for wrong page count (will show dynamic added pages in count too - Need to fix this) + * Fix for IE/Edge saving forms #391 + +# v1.0.6 +## 01/07/2016 + +1. [](#bugfix) + * Fix for forms appending `_json` fields on every save + +# v1.0.5 +## 01/07/2016 + +1. [](#new) + * Added a pointer to Grav's contributing guide + * Handle the optional logic to strip home from Page routes and urls + * The Configuration page now shows any blueprint found in the user/blueprints/config/ folder, thus allowing to add custom configurations +1. [](#improved) + * Allow the nonce for a POST action to be set in the query url + * Add a fallback twig template to use in case Twig cannot find a template file + * Modified update Theme and Plugin buttons to use more reliably markup +1. [](#bugfix) + * Fix additional `on` parameter when saving plugins configs that contain tabs in their blueprint + * Fixes for the `pagemediaselect` form field + * Fix an untranslated message in the logout form when `system.languages.translations` is disabled + * Fixed a hardcoded `http://` reference throwing warnings under HTTPS + * Ensure download package has `.zip` extension, just in case + +# v1.0.4 +## 12/22/2015 + +1. [](#improved) + * Improved File input field for admin + * Restore file inputs functionality and process form via JS if no inputs found +1. [](#bugfix) + * Fix for the image preview in the file field on multi-lang sites + * Fix problem in form code introduced by fix to allow file uploads + * Fix redirect in deleting page media + +# v1.0.3 +## 12/20/2015 + +1. [](#new) + * Added `pagemediaselect` field for use in pages +1. [](#improved) + * Updated various languages + * Check for method `meetsRequirements()` prior to using + * Enable `file` form field to be used in plugins and theme blueprints + +# v1.0.2 +## 12/18/2015 + +1. [](#bugfix) + * Fixed issue with user edit page causing error due to individual language files + +# v1.0.1 +## 12/18/2015 + +1. [](#new) + * Moved languages into individual files under `languages/` folder + * Added a check for PHP version + * Dutch translation added +1. [](#improved) + * Let forms work with file inputs + * Various file input improvements + * Language updates + * Better checks for existence of Popularity JSON data + * Add file processing to admin forms + * More Admin Pro integration fixes +1. [](#bugfix) + * Set form to multipart if it contains a file field + * `cleanFilesData()` now returns just the filename + +# v1.0.0 +## 12/11/2015 + +1. [](#new) + * New built-in admin registration process + * Added security check to `section` form field + * Added new RocketTheme font with various icons + * Add `onAdminThemeInitialized()` event to admin `Themes::init()` + * Force timestamp on CSS/JS assets based on `GRAV_VERSION` + * Additions for Gantry5 support +1. [](#improved) + * Force lowercase `username` when logging in + * Hide markdown preview except for pages + * Added a notice if you don't have permission to see dashboard + * Updated admin login page logic + * Return "Invalid Security Token" instead of "Unauthorized" + * Throw exception if you used with built-in PHP web server + * Updated languages + * Removed `noreply@getgrav.org` default email address + * Use new methods to disable CSS/JS pipeline if available + * Various code cleanups +1. [](#bugfix) + * Handle case when email `from` is not configured + * Fix tabs support in plugin/themes settings + * Fix param separator in page media Ajax call + * Fix favicon base URL + +# v1.0.0-rc.7 +## 12/01/2015 + +1. [](#new) + * Display error page if page does not exist in admin + * Removed Beta message option and added toggle for GitHub message + * Added functionality to support Admin Pro plugin (in development) +1. [](#improved) + * Added support for Markdown editor in lists #239 + * Better Markdown Editor API with dynamic initialization + * Various language updates + * Removed some unused variables + * Added admin check for pages existence + * Prevent the admin to cause an error when an Ajax action is in progress + * Force translations to be active even when disabled in site #299 + * Do not reinitialize `Selectize` if already available +1. [](#bugfix) + * Fixed full-screen markdown Editor + * Fix modular preview not working reliably #254 + * **Nonce fixes** (hopefully the last of them!) + * Fix broken plugin enable/disable + * Fix issue where `_redirect: /plugins` was getting stored in the plugin configuration + * Replace default them service with admin one + * Fix saving array fields #304 + * Fix missing translations when default language is not english + * Fix title variables not translated #310 + +# v1.0.0-rc.6 +## 11/21/2015 + +1. [](#improved) + * Implemented logic to detect when offline and suppress Ajax calls + * Added nonce logic to be used by JS +1. [](#bugfix) + * Nonce fix for updating themes + * Nonce fix for deleting pages + +# v1.0.0-rc.5 +## 11/20/2015 + +1. [](#new) + * Use **Nonce** mechanism for form security + * Added Hungarian translation + * Add support for Markdown labels #271 + * Added support for Markdown Editor in all the things + * Implemented save keyboard shortcut (Ctrl + S / CMD + S) +1. [](#improved) + * Better error for "Internal Server Error" when accessing GPM + * Updated French translation + * Updated Russian translation + * Load Gravatar image with protocol-less `//:` syntax + * Improved header UI in mobile browsers #265 + * Dropped unused version of JQuery + * More visible Preview link icon + * Hide **Latest pages** if there are none + * Improved toggle to better support different length strings +1. [](#bugfix) + * Force rescanning fields when submitting a form #243 + * Set default lang for pages on fresh session + * Escaped values in `array.html.twig` + * Fix saving in IE Edge + * Fixed various typos + * Fixed JS button issues #370 + * Fixed JS error in private browsing #272 + * Fixed date field border + * Fixed multiple instance of Markdown Editor #285 + * Fixed Spacer CSS #267 + +# v1.0.0-rc.4 +## 10/29/2015 + +1. [](#improved) + * Changed admin menu event hook to `onAdminMenu()` + * Minor improvements for admin page location + * Additional lang strings for Grav 1.0.0-rc.3 + +# v1.0.0-rc.3 +## 10/27/2015 + +1. [](#improved) + * Rely on context-language for active language + * Improved some Russian translations + * Only show login if not already logged in +1. [](#bugfix) + * Disable asset pipeline in admin only + * Fix Editor cursor insertion point when text is selected in some actions + +# v1.0.0-rc.2 +## 10/23/2015 + +1. [](#bugfix) + * Reverted lang redirect code. Needs to be reworked to be more reliable + +# v1.0.0-rc.1 +## 10/23/2015 + +1. [](#new) + * Redirect to non-language URL except for `pages/` +1. [](#improved) + * New language strings for new `system.yaml` fields + * Improved Russian translations + * Improved compatibility with PECL Yaml parser +1. [](#bugfix) + * Redirect to correct page if you change folder/slug + * Fix issue with Asset pipeline not being disabled in admin + * Fix for HTML in text input fields + * Fixed various icons in headers + +# v0.6.2 +## 10/15/2015 + +1. [](#improved) + * Use `title` rather than `menu` in Page listing + * Wrapped language strings in double-quotes + * New language strings for new fields +1. [](#bugfix) + * Fixed issue with IE not able to save pages + +# v0.6.1 +## 10/07/2015 + +1. [](#new) + * Added the ability to render front-end templates in markdown preview + * Option to disable Google-based fonts. Useful for Cyrillic languages. + * Couple of new static helper methods used by new page blueprints + * New `fieldset` form field (thanks @Sommerregen!) +1. [](#improved) + * Hide editor buttons in preview mode + * Improved support for admin when offline + * Use relative URL in Login form + * Added some more missing lang strings + * Improved German translation + * Compressed CSS files for improved performance + * Only get last 7 days in week count calculation +1. [](#bugfix) + * Fix saving pages in local-specific languages + * Only track 'human' page hits in statistics + * Responsive fixes for 'wordy' languages + * Fixed delete issue with array field type + * Fixed some hardcoded `admin` references to allow admin path change + * Fix for issue with lang code being added twice + * Fix language name in admin buttons + +# v0.6.0 +## 09/16/2015 + +1. [](#new) + * Support for custom markdown editor buttons! + * Added Russian translations + * Added Japanese translations + * Ajax session keep-alive when editing forms +1. [](#improved) + * Added missing Italian translations + * Added additional options field into the pages form field +1. [](#bugfix) + * Fix GPM errors in offline mode + * Fix for duplicate status messages + +# v0.5.0 +## 09/11/2015 + +1. [](#new) + * Responsive layout for mobile compatibility (thanks @Vivalldi!) + * Added page type and many other new filters to Page list view + * Added granular ACL requirements to admin pages + * Ability to define page date format + * Added `onAdminTemplateNavPluginHook` to allow for plugins to hook into sidebar + * Added YAML Twig filters (to and from) + * Support for nested metadata + * Added ability to disable automatic update checks via admin plugin configuration + * Initial Spanish translation +1. [](#improved) + * Check for existence of a user account + * Various language additions + * Refactored form fields to remove duplicates from form plugin + * Improved date picker + * Improved display field + * Add page template type to page list view + * Various UI fixes + * Added some default field 'focus' to save clicking + * Only allow "Add Modular" if the theme has modular templates + * Updated `chartist.js` library + * Updated 'fontawesome' fonts to the latest v4.4 +1. [](#bugfix) + * Fix for "drag-n-drop" of non-image media + * Fix a fatal error in GPM when offline + * Fix a z-index bug with tooltips + * Fix a z-index bug in lang dropdowns + * Don't allow deleting of last empty array field + * Fix for images with parenthesis in filenames + * Fix for page title visualization when not set + * Fix for cursor position in folder/array fields + +# v0.4.3 +## 08/31/2015 + +1. [](#new) + * Added Japanese translation + * Support for independent file name and template override +1. [](#improved) + * Improved slug generation using `slugify.js` + * Allow the `title` twig variables to set the page title + * Improved Page media handling with several bugfixes + * Prevent error when there are no pages on a site + * If all updates are applied, show "Fully Updated" text in dashboard + * Better preview link (requires `rtrim` filter from Grav 0.9.40) + * Order all plugins and themes alphabetically + * Removed duplicate language entries +1. [](#bugfix) + * Fix for redirect after saving when multilang not enabled + * Fix for deleting responsive media + * Fix for HTML encoding in markdown field + +# v0.4.2 +## 08/25/2015 + +1. [](#bugfix) + * Fix for current admin lang not showing up in page lang dropdown + * Fix for incorrect NAME/CONTENT lang keys + * Fix for incorrect site link + +# v0.4.1 +## 08/24/2015 + +1. [](#bugfix) + * Fix for broken **Add Page** - Doh! + * Fix for empty site link when at root + +# v0.4.0 +## 08/24/2015 + +1. [](#new) + * Multi-language Page support!!! + * Admin languages configurable per user + * Toastr messages for `check updates` + * new `tu` filter for admin translations + * Italian and German admin translations + * Added a save location in system and site configuration + * Page metadata now uses flexible array field +1. [](#improved) + * Allow subpages of modular pages to display in pages list + * Open external pages in new tabs + * Reworked `visibility` of pages + * Use `PLUGIN_ADMIN` prefix for translations + * Added link to gravatar.com to avoid confusion on avatar + * Limit page count to 200 in ordering field + * Fixed various Safari _flex_ issues + * Use `rawRoute()` for page links + * Minor `param separator` fixes + * Various CSS fixes + * Improved CodeMirror to force spaces + * Added **Selectize** dropdowns to various forms and modals +1. [](#bugfix) + * Fix for `Call to a member function path() on non-object` error + * Fixed dropdown z-index issues + * Correctly set the filename including language if set + * Fix for empty taxonomies on page save + * Fix for page not redirecting properly on folder change + * Fix for table headers styling + * Added missing translation strings + * Unique page counting in total page counts + * Fixed JS warning with page filtering and deleting + + +# v0.3.0 +## 08/11/2015 + +1. [](#new) + * Show current date in form date format fields + * Added a new **check for updates** button to flush GPM + * Added session timeout configuration for admin + * Added `isSymlink` logic for Grav + * Added new `phpinfo` page +1. [](#improved) + * Improved toggleables + * Support `param_separator` for Apache on windows + * Logout now goes to interstitial to provide session messages + * Updated hints and improved formatting + * Encoding URI for images in editor preview + * Create user `system.yaml` and `site.yaml` if they are missing + * Open external links in new tab by default + * Set edit mode to `normal` by default + * Disable CSS/JS pipelining in the admin +1. [](#bugfix) + * Fixed form submission not working in IE + * Fix fatal error when deleting homepage + * Prevent admin plugin activating when the URL of a page contains partial route + +# v0.2.0 +## 08/06/2015 + +1. [](#new) + * Added multiple **clear cache** types + * Added back to themes link when adding new themes + * Properly handles visibility and ordering and guesses best option on new + * Added new templates field with support for custom (unsupported) template type + * Added new display field for displaying simple text value + * **Update Grav** button now works + * Added spanish translation + * Added german translation +1. [](#improved) + * Improved page order handling logic + * Implemented 2-step theme switching logic with warning + * Force `modular` page class for modular template + * Clear page cache on page delete (ghost pages still showing) + * Clears route on page save so changes such as `slug` are picked up + * Fix dashboard layout in Safari + * Added tooltips for official 'Team Grav' themes/plugins +1. [](#bugfix) + * Handle modular page templates on create + * Fixed Firefox JS error for arrays + * Ensure we don't change page type to empty and save (causing page to be deleted) + * Fixed some minor CSS issues with editor + * Fixed link to RocketTheme.com + * Disabled fields now stay properly disabled + +# v0.1.1 +## 08/04/2015 + +1. [](#bugfix) + * Fixed GitHub URLs + * Hiding toggle for disabling Admin plugin + * Removed extra text not needed + +# v0.1.0 +## 08/04/2015 + +1. [](#new) + * ChangeLog started... diff --git a/user/plugins/admin/CONTRIBUTING.md b/user/plugins/admin/CONTRIBUTING.md new file mode 100644 index 0000000..ef2bc6f --- /dev/null +++ b/user/plugins/admin/CONTRIBUTING.md @@ -0,0 +1 @@ +Please read the Contributing Guidelines of the Grav Project \ No newline at end of file diff --git a/user/plugins/admin/LICENSE b/user/plugins/admin/LICENSE new file mode 100644 index 0000000..f7d4bb6 --- /dev/null +++ b/user/plugins/admin/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017 Grav + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/user/plugins/admin/README.md b/user/plugins/admin/README.md new file mode 100644 index 0000000..430509d --- /dev/null +++ b/user/plugins/admin/README.md @@ -0,0 +1,111 @@ +# Grav Standard Administration Panel Plugin + +This **admin plugin** for [Grav](http://github.com/getgrav/grav) is an HTML user interface that provides a convenient way to configure Grav and easily create and modify pages. This will remain a totally optional plugin, and is not in any way required or needed to use Grav effectively. In fact, the admin provides an intentionally limited view to ensure it remains easy to use and not overwhelming. I'm sure power users will still prefer to work with the configuration files directly. + +![](assets/admin-dashboard.png) + +# Features + +* User login with automatic password encryption +* Forgot password functionality +* Logged-in-user management +* One click Grav core updates +* Dashboard with maintenance status, site activity and latest page updates +* Notifications system for latest news, blogs, and announcements +* Ajax-powered backup capability +* Ajax-powered clear-cache capability +* System configuration management +* Site configuration management +* Normal and Expert modes which allow editing via forms or YAML +* Page listing with filtering and search +* Page creation, editing, moving, copying, and deleting +* Powerful syntax highlighting code editor with instant Grav-powered preview +* Editor features, hot keys, toolbar, and distraction-free fullscreen mode +* Drag-n-drop upload of page media files including drag-n-drop placement in the editor +* One click theme and plugin updates +* Plugin manager that allows listing and configuration of installed plugins +* Theme manager that allows listing and configuration of installed themes +* GPM-powered installation of new plugins and themes + +# Support + +#### Support + +We have tested internally, but we hope to use this public beta phase to identify, isolate, and fix issues related to the plugin to ensure it is as solid and reliable as possible. + +For **live chatting**, please use the dedicated [Slack Chat Room](https://getgrav.org/slack) for discussions directly related to Grav. + +For **bugs, features, improvements**, please ensure you [create issues in the admin plugin GitHub repository](https://github.com/getgrav/grav-plugin-admin). + +# Installation + +First ensure you are running the latest **Grav 1.6.7 or later**. This is required for the admin plugin to run properly (`-f` forces a refresh of the GPM index). + +``` +$ bin/gpm selfupgrade -f +``` + +The admin plugin actually requires the help of 3 other plugins, so to get the admin plugin to work you first need to install **admin**, **login**, **forms**, and **email** plugins. These are available via GPM, and because the plugin has dependencies you just need to proceed and install the admin plugin, and agree when prompted to install the others: + +``` +$ bin/gpm install admin +``` + +### Manual Installation + +Manual installation is not the recommended method of installation, however, it is still possible to install the admin plugin manually. Basically, you need to download each of the following plugins individually: + +* [admin](https://github.com/getgrav/grav-plugin-admin/archive/develop.zip) +* [login](https://github.com/getgrav/grav-plugin-login/archive/develop.zip) +* [form](https://github.com/getgrav/grav-plugin-form/archive/develop.zip) +* [email](https://github.com/getgrav/grav-plugin-email/archive/develop.zip) + +Extract each archive file into your `user/plugins` folder, then ensure the folders are renamed to just `admin/`, `login/`, `form/`, and `email/`. Then proceed with the **Usage instructions below**. + +# Usage + +### Create User with CLI + +After this you need to create a user account with admin privileges: + +``` +$ bin/plugin login new-user +``` + +### Create User Manually + +Alternatively, you can create a user account manually, in a file called `user/accounts/admin.yaml`. This **filename** is actually the **username** that you will use to login. The contents will contain the other information for the user. + +``` +password: 'password' +email: 'youremail@mail.com' +fullname: 'Johnny Appleseed' +title: 'Site Administrator' +access: + admin: + login: true + super: true +``` + +Of course you should edit your `email`, `password`, `fullname`, and `title` to suit your needs. + +> You can use any password when you manually put it in this `.yaml` file. However, when you change your password in the admin, it must contain at least one number and one uppercase and lowercase letter, and at least 8 or more characters. + +# Accessing the Admin + +By default, you can access the admin by pointing your browser to `http://yoursite.com/admin`. You can simply log in with the `username` and `password` set in the YAML file you configured earlier. + +> After logging in, your **plaintext password** will be removed and replaced by an **encrypted** one. + +# Standard Free & Paid Pro Versions + +If you have been following the [blog](http://getgrav.org/blog), [Twitter](https://twitter.com/getgrav), [Slack chat](https://getgrav.org/slack), etc., you probably already know now that our intention is to provide two versions of this plugin. + +The **standard free version**, is very powerful, and has more functionality than most commercial flat-file CMS systems. + +We also intend to release in the near future a more feature-rich **pro version** that will include enhanced functionality, as well as some additional nice-to-have capabilities. This pro version will be a **paid** plugin the price of which is not yet 100% finalized. + +# Running Tests + +First install the dev dependencies by running `composer update` from the Grav root. +Then `composer test` will run the Unit Tests, which should be always executed successfully on any site. diff --git a/user/plugins/admin/admin.php b/user/plugins/admin/admin.php new file mode 100644 index 0000000..0ecc2d0 --- /dev/null +++ b/user/plugins/admin/admin.php @@ -0,0 +1,1014 @@ + 1000, + ]; + + /** @var bool */ + protected $active = false; + + /** @var string */ + protected $template; + + /** @var string */ + protected $theme; + + /** @var string */ + protected $route; + + /** @var string */ + protected $admin_route; + + /** @var Uri */ + protected $uri; + + /** @var Admin */ + protected $admin; + + /** @var Session */ + protected $session; + + /** @var Popularity */ + protected $popularity; + + /** @var string */ + protected $base; + + /** @var string */ + protected $version; + + /** + * @return array + */ + public static function getSubscribedEvents() + { + return [ + 'onPluginsInitialized' => [ + ['autoload', 100001], + ['setup', 100000], + ['onPluginsInitialized', 1001] + ], + 'onPageInitialized' => ['onPageInitialized', 0], + 'onFormProcessed' => ['onFormProcessed', 0], + 'onShutdown' => ['onShutdown', 1000], + 'onAdminDashboard' => ['onAdminDashboard', 0], + 'onAdminTools' => ['onAdminTools', 0], + ]; + } + + /** + * Get list of form field types specified in this plugin. Only special types needs to be listed. + * + * @return array + */ + public function getFormFieldTypes() + { + return [ + 'column' => [ + 'input@' => false + ], + 'columns' => [ + 'input@' => false + ], + 'fieldset' => [ + 'input@' => false + ], + 'section' => [ + 'input@' => false + ], + 'list' => [ + 'array' => true + ], + 'file' => [ + 'array' => true + ] + ]; + } + + /** + * [onPluginsInitialized:100000] Composer autoload. + * + * @return ClassLoader + */ + public function autoload() + { + return require __DIR__ . '/vendor/autoload.php'; + } + + /** + * [onPluginsInitialized:100000] + * + * If the admin path matches, initialize the Login plugin configuration and set the admin + * as active. + */ + public function setup() + { + $route = $this->config->get('plugins.admin.route'); + if (!$route) { + return; + } + + $this->base = '/' . trim($route, '/'); + $this->admin_route = rtrim($this->grav['pages']->base(), '/') . $this->base; + $this->uri = $this->grav['uri']; + + $users_exist = Admin::doAnyUsersExist(); + + // If no users found, go to register + if (!$users_exist) { + if (!$this->isAdminPath()) { + $this->grav->redirect($this->admin_route); + } + $this->template = 'register'; + } + + // Only activate admin if we're inside the admin path. + if ($this->isAdminPath()) { + try { + $this->grav['session']->init(); + } catch (SessionException $e) { + $this->grav['session']->init(); + $message = 'Session corruption detected, restarting session...'; + + /** @var Debugger $debugger */ + $debugger = $this->grav['debugger']; + $debugger->addMessage($message); + + $this->grav['messages']->add($message, 'error'); + } + $this->active = true; + + // Set cache based on admin_cache option + $this->grav['cache']->setEnabled($this->config->get('plugins.admin.cache_enabled')); + $pages = $this->grav['pages']; + if (method_exists($pages, 'setCheckMethod')) { + // Force file hash checks to fix caching on moved and deleted pages. + $pages->setCheckMethod('hash'); + } + } + } + + /** + * [onPluginsInitialized:1001] + * + * If the admin plugin is set as active, initialize the admin + */ + public function onPluginsInitialized() + { + // Only activate admin if we're inside the admin path. + if ($this->active) { + // Store this version. + $this->version = $this->getBlueprint()->get('version'); + + // Have a unique Admin-only Cache key + if (method_exists($this->grav['cache'], 'setKey')) { + /** @var Cache $cache */ + $cache = $this->grav['cache']; + $cache_key = $cache->getKey(); + $cache->setKey($cache_key . '$'); + } + + // Turn on Twig autoescaping + if (method_exists($this->grav['twig'], 'setAutoescape') && $this->grav['uri']->param('task') !== 'processmarkdown') { + $this->grav['twig']->setAutoescape(true); + } + + $this->grav['debugger']->addMessage('Admin v' . $this->version); + $this->initializeAdmin(); + + // Disable Asset pipelining (old method - remove this after Grav is updated) + if (!method_exists($this->grav['assets'], 'setJsPipeline')) { + $this->config->set('system.assets.css_pipeline', false); + $this->config->set('system.assets.js_pipeline', false); + } + + // Replace themes service with admin. + $this->grav['themes'] = function () { + return new Themes($this->grav); + }; + } + + // We need popularity no matter what + $this->popularity = new Popularity(); + + // Fire even to register permissions from other plugins + $this->grav->fireEvent('onAdminRegisterPermissions', new Event(['admin' => $this->admin])); + } + + /** + * [onPageInitialized:0] + */ + public function onPageInitialized() + { + $page = $this->grav['page']; + + $template = $this->grav['uri']->param('tmpl'); + + if ($template) { + $page->template($template); + } + } + + /** + * [onFormProcessed:0] + * + * Process the admin registration form. + * + * @param Event $event + */ + public function onFormProcessed(Event $event) + { + $form = $event['form']; + $action = $event['action']; + + switch ($action) { + case 'register_admin_user': + + if (Admin::doAnyUsersExist()) { + throw new \RuntimeException('A user account already exists, please create an admin account manually.'); + } + + if (!$this->config->get('plugins.login.enabled')) { + throw new \RuntimeException($this->grav['language']->translate('PLUGIN_LOGIN.PLUGIN_LOGIN_DISABLED')); + } + + $data = []; + $username = $form->value('username'); + + if ($form->value('password1') !== $form->value('password2')) { + $this->grav->fireEvent('onFormValidationError', new Event([ + 'form' => $form, + 'message' => $this->grav['language']->translate('PLUGIN_LOGIN.PASSWORDS_DO_NOT_MATCH') + ])); + $event->stopPropagation(); + + return; + } + + $data['password'] = $form->value('password1'); + + $fields = [ + 'email', + 'fullname', + 'title' + ]; + + foreach ($fields as $field) { + // Process value of field if set in the page process.register_user + if (!isset($data[$field]) && $form->value($field)) { + $data[$field] = $form->value($field); + } + } + + // Don't store plain text password or username (part of the filename). + unset($data['password1'], $data['password2'], $data['username']); + + // Extra lowercase to ensure file is saved lowercase + $username = strtolower($username); + + $inflector = new Inflector(); + + $data['fullname'] = $data['fullname'] ?? $inflector->titleize($username); + $data['title'] = $data['title'] ?? 'Administrator'; + $data['state'] = 'enabled'; + $data['access'] = ['admin' => ['login' => true, 'super' => true], 'site' => ['login' => true]]; + + /** @var UserCollectionInterface $users */ + $users = $this->grav['accounts']; + + // Create user object and save it + $user = $users->load($username); + $user->update($data); + $user->save(); + + //Login user + $this->grav['session']->user = $user; + unset($this->grav['user']); + $this->grav['user'] = $user; + $user->authenticated = true; + $user->authorized = $user->authorize('admin.login'); + + $messages = $this->grav['messages']; + $messages->add($this->grav['language']->translate('PLUGIN_ADMIN.LOGIN_LOGGED_IN'), 'info'); + $this->grav->redirect($this->admin_route); + + break; + } + } + + /** + * [onShutdown:1000] + * + * Handles the shutdown + */ + public function onShutdown() + { + if ($this->active) { + //only activate when Admin is active + if ($this->admin->shouldLoadAdditionalFilesInBackground()) { + $this->admin->loadAdditionalFilesInBackground(); + } + } else { + //if popularity is enabled, track non-admin hits + if ($this->config->get('plugins.admin.popularity.enabled')) { + $this->popularity->trackHit(); + } + } + } + + /** + * [onAdminDashboard:0] + */ + public function onAdminDashboard() + { + $this->grav['twig']->plugins_hooked_dashboard_widgets_top[] = ['template' => 'dashboard-maintenance']; + $this->grav['twig']->plugins_hooked_dashboard_widgets_top[] = ['template' => 'dashboard-statistics']; + $this->grav['twig']->plugins_hooked_dashboard_widgets_top[] = ['template' => 'dashboard-notifications']; + $this->grav['twig']->plugins_hooked_dashboard_widgets_top[] = ['template' => 'dashboard-feed']; + $this->grav['twig']->plugins_hooked_dashboard_widgets_main[] = ['template' => 'dashboard-pages']; + } + + + /** + * [onAdminTools:0] + * + * Provide the tools for the Tools page, currently only direct install + * + * @return Event + */ + public function onAdminTools(Event $event) + { + $event['tools'] = array_merge($event['tools'], [ + 'backups' => [['admin.maintenance', 'admin.super'], $this->grav['language']->translate('PLUGIN_ADMIN.BACKUPS')], + 'scheduler' => [['admin.super'], $this->grav['language']->translate('PLUGIN_ADMIN.SCHEDULER')], + 'logs' => [['admin.super'], $this->grav['language']->translate('PLUGIN_ADMIN.LOGS')], + 'reports' => [['admin.super'], $this->grav['language']->translate('PLUGIN_ADMIN.REPORTS')], + 'direct-install' => [['admin.super'], $this->grav['language']->translate('PLUGIN_ADMIN.DIRECT_INSTALL')], + ]); + + return $event; + } + + /** + * Sets longer path to the home page allowing us to have list of pages when we enter to pages section. + */ + public function onPagesInitialized() + { + $config = $this->config; + + // Force SSL with redirect if required + if ($config->get('system.force_ssl')) { + if (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] !== 'on') { + $url = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; + $this->grav->redirect($url); + } + } + + $this->session = $this->grav['session']; + + // Set original route for the home page. + $home = '/' . trim($this->config->get('system.home.alias'), '/'); + + // set session variable if it's passed via the url + if ($this->uri->param('mode') === 'expert') { + $this->session->expert = true; + } elseif ($this->uri->param('mode') === 'normal') { + $this->session->expert = false; + } else { + // set the default if not set before + $this->session->expert = $this->session->expert ?? false; + } + + /** @var Pages $pages */ + $pages = $this->grav['pages']; + + $this->grav['admin']->routes = $pages->routes(); + + // Remove default route from routes. + if (isset($this->grav['admin']->routes['/'])) { + unset($this->grav['admin']->routes['/']); + } + + $page = $pages->dispatch('/', true); + + // If page is null, the default page does not exist, and we cannot route to it + if ($page) { + $page->route($home); + } + + // Make local copy of POST. + $post = $this->grav['uri']->post(); + + // Initialize Page Types + Pages::types(); + + // Handle tasks. + $this->admin->task = $task = $this->grav['task']; + if ($task) { + $this->initializeController($task, $post); + } elseif ($this->template === 'logs' && $this->route) { + // Display RAW error message. + echo $this->admin->logEntry(); + exit(); + } + + $self = $this; + + // make sure page is not frozen! + unset($this->grav['page']); + + $this->admin->pagesCount(); + + // Replace page service with admin. + $this->grav['page'] = function () use ($self) { + $page = new Page(); + $page->expires(0); + + if ($this->grav['user']->authorize('admin.login')) { + $event = new Event(['page' => $page]); + $event = $this->grav->fireEvent('onAdminPage', $event); + $page = $event['page']; + + if ($page->slug()) { + return $page; + } + } + + // Look in the pages provided by the Admin plugin itself + if (file_exists(__DIR__ . "/pages/admin/{$self->template}.md")) { + $page->init(new \SplFileInfo(__DIR__ . "/pages/admin/{$self->template}.md")); + $page->slug(basename($self->template)); + return $page; + } + + // If not provided by Admin, lookup pages added by other plugins + $plugins = $this->grav['plugins']; + $locator = $this->grav['locator']; + + foreach ($plugins as $plugin) { + if ($this->config->get("plugins.{$plugin->name}.enabled") !== true) { + continue; + } + + $path = $locator->findResource("plugins://{$plugin->name}/admin/pages/{$self->template}.md"); + + if ($path) { + $page->init(new \SplFileInfo($path)); + $page->slug(basename($self->template)); + + return $page; + } + } + + return null; + }; + + if (empty($this->grav['page'])) { + if ($this->grav['user']->authenticated) { + $event = new Event(['page' => null]); + $event->page = null; + $event = $this->grav->fireEvent('onPageNotFound', $event); + /** @var PageInterface $page */ + $page = $event->page; + + if (!$page || !$page->routable()) { + $error_file = $this->grav['locator']->findResource('plugins://admin/pages/admin/error.md'); + $page = new Page(); + $page->init(new \SplFileInfo($error_file)); + $page->slug(basename($this->route)); + $page->routable(true); + } + + unset($this->grav['page']); + $this->grav['page'] = $page; + } else { + // Not Found and not logged in: Display login page. + $login_file = $this->grav['locator']->findResource('plugins://admin/pages/admin/login.md'); + $page = new Page(); + $page->init(new \SplFileInfo($login_file)); + $page->slug(basename($this->route)); + unset($this->grav['page']); + $this->grav['page'] = $page; + } + } + + // Explicitly set a timestamp on assets + $this->grav['assets']->setTimestamp(substr(md5(GRAV_VERSION . $this->grav['config']->checksum()), 0, 10)); + } + + /** + * Handles initializing the assets + */ + public function onAssetsInitialized() + { + // Disable Asset pipelining + $assets = $this->grav['assets']; + $assets->setJsPipeline(false); + $assets->setCssPipeline(false); + } + + /** + * Add twig paths to plugin templates. + */ + public function onTwigTemplatePaths() + { + $twig_paths = []; + $this->grav->fireEvent('onAdminTwigTemplatePaths', new Event(['paths' => &$twig_paths])); + + $twig_paths[] = __DIR__ . '/themes/' . $this->theme . '/templates'; + + $this->grav['twig']->twig_paths = $twig_paths; + } + + /** + * Set all twig variables for generating output. + */ + public function onTwigSiteVariables() + { + $twig = $this->grav['twig']; + $page = $this->grav['page']; + + $twig->twig_vars['location'] = $this->template; + $twig->twig_vars['base_url_relative_frontend'] = $twig->twig_vars['base_url_relative'] ?: '/'; + $twig->twig_vars['admin_route'] = trim($this->admin_route, '/'); + $twig->twig_vars['template_route'] = $this->template; + $twig->twig_vars['current_route'] = '/' . $twig->twig_vars['admin_route'] . '/' . $this->template . '/' . $this->route; + $twig->twig_vars['base_url_relative'] = $twig->twig_vars['base_url_simple'] . '/' . $twig->twig_vars['admin_route']; + $twig->twig_vars['current_url'] = rtrim($twig->twig_vars['base_url_relative'] . '/' . $this->template . '/' . $this->route, '/'); + $theme_url = '/' . ltrim($this->grav['locator']->findResource('plugin://admin/themes/' . $this->theme, + false), '/'); + $twig->twig_vars['theme_url'] = $theme_url; + $twig->twig_vars['preset_url'] = $twig->twig_vars['preset_url'] ?? $theme_url; + $twig->twig_vars['base_url'] = $twig->twig_vars['base_url_relative']; + $twig->twig_vars['base_path'] = GRAV_ROOT; + $twig->twig_vars['admin'] = $this->admin; + $twig->twig_vars['admin_version'] = $this->version; + $twig->twig_vars['logviewer'] = new LogViewer(); + $twig->twig_vars['form_max_filesize'] = Utils::getUploadLimit() / 1024 / 1024; + + $fa_icons_file = CompiledYamlFile::instance($this->grav['locator']->findResource('plugin://admin/themes/grav/templates/forms/fields/iconpicker/icons' . YAML_EXT)); + $fa_icons = $fa_icons_file->content(); + $fa_icons = array_map(function ($icon) { + //only pick used values + return ['id' => $icon['id'], 'unicode' => $icon['unicode']]; + }, $fa_icons['icons']); + + $twig->twig_vars['fa_icons'] = $fa_icons; + + // add form if it exists in the page + $header = $page->header(); + + $forms = []; + if (isset($header->forms)) foreach ($header->forms as $key => $form) { + $forms[$key] = new Form($page, null, $form); + } + $twig->twig_vars['forms'] = $forms; + + // preserve form validation + if (!isset($twig->twig_vars['form'])) { + if (isset($header->form)) { + $twig->twig_vars['form'] = new Form($page); + } elseif (isset($header->forms)) { + $twig->twig_vars['form'] = new Form($page, null, reset($header->forms)); + } + } + + // Gather Plugin-hooked nav items + $this->grav->fireEvent('onAdminMenu'); + + switch ($this->template) { + case 'dashboard': + $twig->twig_vars['popularity'] = $this->popularity; + + // Gather Plugin-hooked dashboard items + $this->grav->fireEvent('onAdminDashboard'); + + break; + } + + $flashData = $this->grav['session']->getFlashCookieObject(Admin::TMP_COOKIE_NAME); + + if (isset($flashData->message)) { + $this->grav['messages']->add($flashData->message, $flashData->status); + } + } + + // Add images to twig template paths to allow inclusion of SVG files + public function onTwigLoader() + { + $theme_paths = Grav::instance()['locator']->findResources('plugins://admin/themes/' . $this->theme . '/images'); + foreach($theme_paths as $images_path) { + $this->grav['twig']->addPath($images_path, 'admin-images'); + } + } + + /** + * Add the Admin Twig Extensions + */ + public function onTwigExtensions() + { + require_once __DIR__ . '/classes/Twig/AdminTwigExtension.php'; + + $this->grav['twig']->twig->addExtension(new AdminTwigExtension); + } + + public function onAdminAfterSave(Event $event) + { + // Special case to redirect after changing the admin route to avoid 'breaking' + $obj = $event['object']; + + if (null !== $obj && method_exists($obj, 'blueprints')) { + $blueprint = $obj->blueprints()->getFilename(); + + if ($blueprint === 'admin/blueprints' && isset($obj->route) && $this->admin_route !== $obj->route) { + $redirect = preg_replace('/^' . str_replace('/','\/',$this->admin_route) . '/',$obj->route,$this->uri->path()); + $this->grav->redirect($redirect); + } + } + } + + /** + * Convert some types where we want to process out of the standard config path + * + * @param Event $e + */ + public function onAdminData(Event $e) + { + $type = $e['type'] ?? null; + switch ($type) { + case 'tools/scheduler': + $e['type'] = 'config/scheduler'; + break; + case 'tools': + case 'tools/backups': + $e['type'] = 'config/backups'; + break; + } + } + + public function onOutputGenerated() + { + // Clear flash objects for previously uploaded files whenever the user switches page or reloads + // ignoring any JSON / extension call + if ($this->admin->task !== 'save' && empty($this->uri->extension())) { + // Discard any previously uploaded files session and remove all uploaded files. + if ($flash = $this->session->getFlashObject('files-upload')) { + $flash = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($flash)); + foreach ($flash as $key => $value) { + if ($key !== 'tmp_name') { + continue; + } + @unlink($value); + } + } + } + } + + /** + * Initial stab at registering permissions (WIP) + * + * @param Event $e + */ + public function onAdminRegisterPermissions(Event $e) + { + $admin = $e['admin']; + $permissions = [ + 'admin.super' => 'boolean', + 'admin.login' => 'boolean', + 'admin.cache' => 'boolean', + 'admin.configuration' => 'boolean', + 'admin.configuration_system' => 'boolean', + 'admin.configuration_site' => 'boolean', + 'admin.configuration_media' => 'boolean', + 'admin.configuration_info' => 'boolean', + 'admin.settings' => 'boolean', + 'admin.pages' => 'boolean', + 'admin.maintenance' => 'boolean', + 'admin.statistics' => 'boolean', + 'admin.plugins' => 'boolean', + 'admin.themes' => 'boolean', + 'admin.tools' => 'boolean', + 'admin.users' => 'boolean', + ]; + $admin->addPermissions($permissions); + } + + /** + * Check if the current route is under the admin path + * + * @return bool + */ + public function isAdminPath() + { + $route = $this->uri->route(); + + return $route === $this->base || 0 === strpos($route, $this->base . '/'); + } + + /** + * Helper function to replace Pages::Types() + * and to provide an event to manipulate the data + * + * Dispatches 'onAdminPageTypes' event + * with 'types' data member which is a + * reference to the data + */ + public static function pagesTypes() + { + $types = Pages::types(); + + // First filter by configuration + $hideTypes = Grav::instance()['config']->get('plugins.admin.hide_page_types', []); + foreach ((array) $hideTypes as $type) { + unset($types[$type]); + } + + // Allow manipulating of the data by event + $e = new Event(['types' => &$types]); + Grav::instance()->fireEvent('onAdminPageTypes', $e); + + return $types; + } + + /** + * Helper function to replace Pages::modularTypes() + * and to provide an event to manipulate the data + * + * Dispatches 'onAdminModularPageTypes' event + * with 'types' data member which is a + * reference to the data + */ + public static function pagesModularTypes() + { + $types = Pages::modularTypes(); + + // First filter by configuration + $hideTypes = (array) Grav::instance()['config']->get('plugins.admin.hide_modular_page_types', []); + foreach ($hideTypes as $type) { + unset($types[$type]); + } + + // Allow manipulating of the data by event + $e = new Event(['types' => &$types]); + Grav::instance()->fireEvent('onAdminModularPageTypes', $e); + + return $types; + } + + /** + * Validate a value. Currently validates + * + * - 'user' for username format and username availability. + * - 'password1' for password format + * - 'password2' for equality to password1 + * + * @param string $type The field type + * @param string $value The field value + * @param string $extra Any extra value required + * + * @return bool + */ + protected function validate($type, $value, $extra = '') + { + /** @var Login $login */ + $login = $this->grav['login']; + + return $login->validateField($type, $value, $extra); + } + + protected function initializeController($task, $post) + { + $controller = new AdminController(); + $controller->initialize($this->grav, $this->template, $task, $this->route, $post); + $controller->execute(); + $controller->redirect(); + } + + /** + * Initialize the admin. + * + * @throws \RuntimeException + */ + protected function initializeAdmin() + { + $this->enable([ + 'onTwigExtensions' => ['onTwigExtensions', 1000], + 'onPagesInitialized' => ['onPagesInitialized', 1000], + 'onTwigLoader' => ['onTwigLoader', 1000], + 'onTwigTemplatePaths' => ['onTwigTemplatePaths', 1000], + 'onTwigSiteVariables' => ['onTwigSiteVariables', 1000], + 'onAssetsInitialized' => ['onAssetsInitialized', 1000], + 'onAdminRegisterPermissions' => ['onAdminRegisterPermissions', 0], + 'onOutputGenerated' => ['onOutputGenerated', 0], + 'onAdminAfterSave' => ['onAdminAfterSave', 0], + 'onAdminData' => ['onAdminData', 0], + ]); + + // Autoload classes + require_once __DIR__ . '/vendor/autoload.php'; + + + // Check for required plugins + if (!$this->grav['config']->get('plugins.login.enabled') || !$this->grav['config']->get('plugins.form.enabled') || !$this->grav['config']->get('plugins.email.enabled')) { + throw new \RuntimeException('One of the required plugins is missing or not enabled'); + } + + // Initialize Admin Language if needed + /** @var Language $language */ + $language = $this->grav['language']; + if ($language->enabled() && empty($this->grav['session']->admin_lang)) { + $this->grav['session']->admin_lang = $language->getLanguage(); + } + + // Decide admin template and route. + $path = trim(substr($this->uri->route(), strlen($this->base)), '/'); + + if (empty($this->template)) { + $this->template = 'dashboard'; + } + + // Can't access path directly... + if ($path && $path !== 'register') { + $array = explode('/', $path, 2); + $this->template = array_shift($array); + $this->route = array_shift($array); + } + + // Initialize admin class (also registers it to Grav services). + $this->admin = new Admin($this->grav, $this->admin_route, $this->template, $this->route); + + // Double check we have system.yaml, site.yaml etc + $config_path = $this->grav['locator']->findResource('user://config'); + foreach ($this->admin::configurations() as $config_file) { + $config_file = "{$config_path}/{$config_file}.yaml"; + if (!file_exists($config_file)) { + touch($config_file); + } + } + + // Get theme for admin + $this->theme = $this->config->get('plugins.admin.theme', 'grav'); + + $assets = $this->grav['assets']; + $translations = 'this.GravAdmin = this.GravAdmin || {}; if (!this.GravAdmin.translations) this.GravAdmin.translations = {}; ' . PHP_EOL . 'this.GravAdmin.translations.PLUGIN_ADMIN = {'; + + // Enable language translations + $translations_actual_state = $this->config->get('system.languages.translations'); + $this->config->set('system.languages.translations', true); + + $strings = [ + 'EVERYTHING_UP_TO_DATE', + 'UPDATES_ARE_AVAILABLE', + 'IS_AVAILABLE_FOR_UPDATE', + 'AND', + 'IS_NOW_AVAILABLE', + 'CURRENT', + 'UPDATE_GRAV_NOW', + 'TASK_COMPLETED', + 'UPDATE', + 'UPDATING_PLEASE_WAIT', + 'GRAV_SYMBOLICALLY_LINKED', + 'OF_YOUR', + 'OF_THIS', + 'HAVE_AN_UPDATE_AVAILABLE', + 'UPDATE_AVAILABLE', + 'UPDATES_AVAILABLE', + 'FULLY_UPDATED', + 'DAYS', + 'PAGE_MODES', + 'PAGE_TYPES', + 'ACCESS_LEVELS', + 'NOTHING_TO_SAVE', + 'FILE_UNSUPPORTED', + 'FILE_ERROR_ADD', + 'FILE_ERROR_UPLOAD', + 'DROP_FILES_HERE_TO_UPLOAD', + 'DELETE', + 'UNSET', + 'INSERT', + 'METADATA', + 'VIEW', + 'UNDO', + 'REDO', + 'HEADERS', + 'BOLD', + 'ITALIC', + 'STRIKETHROUGH', + 'SUMMARY_DELIMITER', + 'LINK', + 'IMAGE', + 'BLOCKQUOTE', + 'UNORDERED_LIST', + 'ORDERED_LIST', + 'EDITOR', + 'PREVIEW', + 'FULLSCREEN', + 'MODULAR', + 'NON_MODULAR', + 'VISIBLE', + 'NON_VISIBLE', + 'ROUTABLE', + 'NON_ROUTABLE', + 'PUBLISHED', + 'NON_PUBLISHED', + 'PLUGINS', + 'THEMES', + 'ALL', + 'FROM', + 'TO', + 'DROPZONE_CANCEL_UPLOAD', + 'DROPZONE_CANCEL_UPLOAD_CONFIRMATION', + 'DROPZONE_DEFAULT_MESSAGE', + 'DROPZONE_FALLBACK_MESSAGE', + 'DROPZONE_FALLBACK_TEXT', + 'DROPZONE_FILE_TOO_BIG', + 'DROPZONE_INVALID_FILE_TYPE', + 'DROPZONE_MAX_FILES_EXCEEDED', + 'DROPZONE_REMOVE_FILE', + 'DROPZONE_RESPONSE_ERROR' + ]; + + foreach ($strings as $string) { + $separator = (end($strings) === $string) ? '' : ','; + $translations .= '"' . $string . '": "' . htmlspecialchars($this->admin::translate('PLUGIN_ADMIN.' . $string)) . '"' . $separator; + } + + $translations .= '};'; + + $translations .= 'this.GravAdmin.translations.PLUGIN_FORM = {'; + $strings = ['RESOLUTION_MIN', 'RESOLUTION_MAX']; + foreach ($strings as $string) { + $separator = (end($strings) === $string) ? '' : ','; + $translations .= '"' . $string . '": "' . $this->admin::translate('PLUGIN_FORM.' . $string) . '"' . $separator; + } + $translations .= '};'; + + $translations .= 'this.GravAdmin.translations.GRAV_CORE = {'; + $strings = [ + 'NICETIME.SECOND', + 'NICETIME.MINUTE', + 'NICETIME.HOUR', + 'NICETIME.DAY', + 'NICETIME.WEEK', + 'NICETIME.MONTH', + 'NICETIME.YEAR', + 'CRON.EVERY', + 'CRON.EVERY_HOUR', + 'CRON.EVERY_MINUTE', + 'CRON.EVERY_DAY_OF_WEEK', + 'CRON.EVERY_DAY_OF_MONTH', + 'CRON.EVERY_MONTH', + 'CRON.TEXT_PERIOD', + 'CRON.TEXT_MINS', + 'CRON.TEXT_TIME', + 'CRON.TEXT_DOW', + 'CRON.TEXT_MONTH', + 'CRON.TEXT_DOM', + 'CRON.ERROR1', + 'CRON.ERROR2', + 'CRON.ERROR3', + 'CRON.ERROR4', + 'MONTHS_OF_THE_YEAR', + 'DAYS_OF_THE_WEEK' + ]; + foreach ($strings as $string) { + $separator = (end($strings) === $string) ? '' : ','; + $translations .= '"' . $string . '": ' . json_encode($this->admin::translate('GRAV.'.$string)) . $separator; + } + $translations .= '};'; + + // set the actual translations state back + $this->config->set('system.languages.translations', $translations_actual_state); + + $assets->addInlineJs($translations); + } +} diff --git a/user/plugins/admin/admin.yaml b/user/plugins/admin/admin.yaml new file mode 100644 index 0000000..fddc858 --- /dev/null +++ b/user/plugins/admin/admin.yaml @@ -0,0 +1,47 @@ +enabled: true +route: '/admin' +cache_enabled: false +theme: grav +logo_text: '' +body_classes: '' +content_padding: true +twofa_enabled: true +log_viewer_files: ['grav', 'email'] +sidebar: + activate: tab + hover_delay: 100 + size: auto +dashboard: + days_of_stats: 7 +widgets: + dashboard-maintenance: true + dashboard-statistics: true + dashboard-notifications: true + dashboard-feed: true + dashboard-pages: true +pages: + show_parents: both + show_modular: true +session: + timeout: 1800 +warnings: + delete_page: true +edit_mode: normal +frontend_preview_target: inline +show_github_msg: true +pages_list_display_field: title +google_fonts: false +admin_icons: line-awesome +enable_auto_updates_check: true +notifications: + feed: true + dashboard: true + plugins: true + themes: true +popularity: + enabled: true + ignore: ['/test*','/modular'] + history: + daily: 30 + monthly: 12 + visitors: 20 diff --git a/user/plugins/admin/assets/admin-dashboard.png b/user/plugins/admin/assets/admin-dashboard.png new file mode 100644 index 0000000000000000000000000000000000000000..599743e6e9149d9572257670ce92a2fd3ca1426b GIT binary patch literal 241372 zcmdSAg;Sf|x;_k)QYgiX6p9pgic{QOf;$u_p}0eFX>q4`a7pmsE-g-QcPZ}f)-T;> zpWiui_S-+;n^}{|Jd-TB*R9umJz)T48H|_2FA)$BFyv$<)esP#b0Q!-^F>90Kk1*% zl0iUtS!XFB0g#iBpa3}811)XL5fEg<5|dwOsOu8<9(%E6d?P?56+f26L8WL#0mNeR zh~rWu5UBwwnbuIXG$bn`cVyKoR3$aK0)xaVuF*J93)er2X-pnGOX92ca=SkGoesJe zFmAhV-)!|7zDA(ekdmqk>%M9eY@`A0|cii`R&VqRe%&t0ZsUU;>mb z{bqW-KJyeW)U6x+e){c~_%eja^cjLwZh8k!WwoksP@Qs}C_M^-ZctAYVc7F^Z&Y*c zcTJ)RpxzI*@dCXc%;O92KCr7k(fc9zivlaZSt7*tZs%@SO#sL_NX@;3LwaRAyp7o0 z_#?iaX(iZJRTD-#GrT zCi!4Ugd22~w!WRz_+D}NAwd^MeQ;fIL&c$qn%XUVj`DXt!&U`S$A(!oFi6Fbku8+r z8i&&itkdvb{%8dMxwHzq!i^cL9IzDXZN#d6l$uP2C(_;6(x9u(42#6Pk6UMpL8nnY zC&Qy$q1x}AZ^%WyCFWc77xhRdXBxo?ecX5oES2>T=4H|$ zBixi8=nWrBKJ1;9y}kWZAx;G$`u6ps=!;4U^w0q83Q_D;MB&x&#)$59k`rTk9mnN=h~e=Jnw915f^f64dc z6=M8-(%NmP%+E^15b2The<}k|uD*WFe);w}ohaVt=Y&7-9iF*-ZC+)M4fH*E`RZ%T z$5(+Af|3D+u>_wGQpKlZsk;1IvPJ3Nh6m#2e4@u#lfeD_riOqqFg%B22SEdaG(=f~ zFxwh{b%DJX6rAloN=OvYUqM{@0`zm@Bgz4K$WQhYK|YM(fb&)FFPsK1wSUO0O5Y%P zKWjr*_@#YLduy~6+;fV!&6m_6R#)(Ju?jRON%L#Ufc8GW{N<_torxbS7g-RLH@U0=} zOX#e4i`)TSbex9l7PX4nD~7K%X&UmyRED%d?^?A1fcI(+>M3PE)O88~#SV(Uip8NF z7FCRM;Rh<23Q4iN-mmIam7!Y82kH!FiNll=5x`3y& zyja*!NZF^-v++*Xl>s9sbu6WZd7fY%ZC+@e5JL#V7^A!gC5k^vpExg#KTSBzU`Tw( zbErAZxMoK$KrdBqp(d>+)5@%-tj5BcZG0KxqkCT)ofaK}sSg2ce;cMU)R~dzm3J>X z5?fMU!V&Um{U{W$Y}Xp$3B9zu6TW+MCvY*ci}eP8(emmGiomO3l9v3E37=iv3$;6% zyNaB0lhB;56MvKBUny~os-gByl3B2X$KUol*m$XmEM4N z!Oe;SiZVlkLu*6RAnsI*H0w0Zq4PoOp)4H$a|??TGb8hn&KmQZq|_uYmgcgLOco_B zB~B%v>5AG2?h#L@YYfJ8&rqGWt-mJUaslkB zcyD)XlV$GL_f+|{Sfa3#ID{a?Jz6W;rq`)gK>0O<0+Ogaq-+n-SJ_rx;e8C?obmvl zdv3dJ+q0IliYN0YzthH>`7|R`e*MNOQnp9BN0YY{l(isVuT?*C#Cl|Ujd$edIqUh! zbMnip;rCfTGaNrlXF=lV2G0E&~+lKW4^xJFi2J zNkqIva*V&O6t*}2cKTh1Kuy7y{XUxs!2O=5g84)@Ru!NJupM=%a6TDdt;4pF)#BrhTr*qkgi(M;?#m$${!WjbrlMU z+lu=TX8~LX$_%q+JyOEnS?OxXaB+KzxhP%q61AtWu*aCOn9@`pI?6jbuNSXNuRmLh zST8`Ez)hlCl$})Gpy8qW^?fZKlP+oyExp=V`M1G#<8$ZZA`w+Cdgjn=MK) z75G?&r9TTS7yU^lIbz z=3~|C>V(!BpVVJfQv;sK_pBlnNP2NqxjqG_u!qFQl0a?EGTO3XgU5a1d+u&);nFDM zg?MOkJ7c@O;YrgxQa6&x&&Nx${p;V~Zo{tCXHXy*&Ai@h8?TMns@NDA?waCSPw!|$ zlnOwfKPau8@hev)Xez_QCoVOZ^X%5n7jqNav(gA zmvTs^o&D)&OFlDqaMe^r?L+C^9Lu)s_Ss1P@OB2dC08Q=Mze>^dn?yQe-B99U>xAhg3b%m12d^3iE{ z;7L1B+YE~S1h_RDA&KCHJYC#YJM)<|{4P5wJ6P(u);nerQT#nBjQip2!0f8Ga;!r| zFRNIXQ`p@*>^H~zx*et`>s{UfdzO{XHjy~0J%ATTYyE(R^gE2sdJnA;0TAN0UJ&O;g3vn(tb2(-LypihkV{04An>7oL4-!$ z)hYdgGEbBG>bv5V5f*|sI>O2~j=5Q*)B}<`41Yo7Y!-_uW%6X^u@8Ac!K!Ns4KFK|IKK;s07{x_4y@p?M=c?`5v3xJG=aeC+BQKD=<< zk#wPvw<9MRp26p@LW%hBP;-$e0}=bhsJGK~$G0}UpcdA3U`R8>%MIubyiFd~nkv!G z@ms1Me1ah1Affsr{Qq!>PEp4KxY4$2sWYj zvmewcXv`D{NdGtzB@osiJ&&^ZN70k}({@7f|M)BTLr3M+P(1z^WYuHYh8{k@6_cC4 z{St=~Q1E=XnEpbu+d6!-Iua;~fc%dm`aP1S{9-9%hp}d3G}S@tw}I#Xd6<7aDHKI= zWV7k1MkOjSi1sZr-eR<(+7anU(K6y|pKLDfX9L6mtcH z6TD$+YIj;{`GUKbD>VJN-ng732==%0$#4aHj))$!6QSf~BSUWa9LY{>E4>k{!-cD2 zR!bzT_|N~t)<#|vpJbvTj;fT-8wwRdsANu%^0bMwQ?V20nva|vl9Kr6KO!Kp%TW*q zn&dA;x_IF<;#AW2NLeYyeWt^;mE4fd!TBc*fD0{vDp-{ITbFFjyB}0j%93_QrD3jd zL@Euo-}Fa@qC$ZSc6T9Ie=z~k3p7df8}#}^hyC3e%CX>OquE^@oH>{PCiJrPZr^`E zUEBVJ23s4YIon`upmr zk`f!|^I$?hwl<*EW|6hsfO8v1ckS85VVzz6qstGwh3S0?jDJ>WxDdrD-l~q;X2{;_ zF0t49=uBZOXz2zTG(0wy5yIFs8j<#U${Uf5Cb#`(eH0bME_85=&S^O0Ofaq) zI6N{g^gY}QGKYSSV@`h(pK@fxs#pBTKgHd7wPsx&@wff_h!gt}aY6{2DH2@dXhc_b zJv>t5b3K@Ms?p9zB~&(6cI{w5heRXoXlUQ=RBHRRvX1{vn@*K}l>8ustrRVm4-T__ z>SU>IW>P+!n>w|D(*GQ?7Rh-ygtgAL-t2um+}jn_+I861t$j}NH#ynhplT1IYmSsJ z!tBiPHzs+TVU`)nd{4HFGdE>w`qA&RnZP7{5C~KF(yRlP3JL z#1K%s2m;PR-Qj11wak`zm)VF<4wDrR?%DCxnr|NW6WFQ_S>G!^X_?2>=+@G_KRkHp zQs}g4fu9U1*Yv9R+oY0Nq8`Z20QjUsZq7#K{Np@Qjk$b zyF)EspnhSCD98Qm+-m@npXS!<5dD!NrN8c0<5hsea{-8_mbsk`klfiQG{ttSC3kD8 zd@t3k*=^7_^K9((eYFvo)o_jm3R&9FBuT^_z&(&fZv1>6v`}lk zZBe)HAqP4y_A#IF(P;8)_kC7Q&!Bp(qAB(_Z9zcN4DsJF&i#6d-=E4ZPx2j|3(`$1 zcEGqJY&tPedgdvV=oUV7C~(W4L?e(S-8TA4{PH7w6*kLidtfzKN#De>u_Kb`pCh$s zb}=qCX(W{8yK$8}nE6mkFIB!IB_a^kP5Wde*O1ARENAq*I;%>CCi+`SQT8|D?2N3r z@@CqCyf4AO$h1*Du@0BDAT!Z$Z`V9t z`{!^uO!ENlv|n`Ztp&bh?4uyeej!B8SO&{5)dXJ$aQ*eRH8hcOLq1rVHpMddYIPK3 z7^cAIgN_1JO~Lr0)k-5F@+D3X9T;v!SBv+Ex|kRuK0bb8Cep}4pS<%P&h@N|sVOB5 zgj(H7-U^^Jr80XDI$OFDdWA*}`7(EjH(42!vuIZNd7`X8EN+2k^##(YY&OS=`)MD# z8OncUG666O|B>QEF;bsE(M{~a!IAA>Pvv2~>@ufE#A!N~_wY?6=+6~|GdjzI2B_J@ zp!?O5zbrhu72kX+{J3dWx9d?-^Ia)X&PKV!yO2G1Q8K%sA?4-Evm)gs{)Eg-<+A}v zB!wXJ1SMB-^Maw47Qy*iXTkz7SXE68H}xJzUngKCut1F|jKb=uR|$ke5&;^v@h&Br zYv_1|q!}p6+;UuuENg)LZvko`AbM++A@uDaAv30mGJ6YO-!;>c^%@}7>(2CD9F-y~ zo@%BjxGn1@G&x>1b>&g}g zlD3gzCYwT>oQpipfvSz(sVvPVohUHbk^IG$o$K$Z@9vj_F~?fAMq6Ka(o5U*lIf6q zzz!uxs=R26Ah#l7`0vfJ{@I+t(+(+et{g>@a8~o9AzqAG^p;RU9SN6>!&{mCTbjUp zPsedtkQt3$n%U9_gDq<{EMn-bh9A(Y&)dTS7`!Kn7Mb%fxLKSTUSNQhz-Swt2qin` zaCVe95f=pmXNn9L6!2Brs$RA5)VDkLvKDJY%OOoh>6#+$10$L+s`F-UkKiFxe|$`M2E4DpKCldWUH zu$&$nrx-0Q7miCcA9_c%Gsd!B(`0_&JEb`dn@vcvTq80Q2-rAKi4JomK*xKf`z1-_vwyoH#_Q}D%F|o#-%pQRrd_D>_4edZZ$HG_wcP??!^4;$<-!&2I3nlSuhm6FR)aiK zl(qzqiml?cWyngW>Xt&&`wAfWk7E-}Dw7lV3_zGvF*e+xTsr(3?zJ*dM>Kk-wbH{B4>t_Y3!U^(8v` zZuN-pdcpc-p-PtU)0Pb$>%DHfiO}Zemg+*C?c)oaxjIWtie%h9Cxd7y?%&h;_G3-1 z`x?`(i@E0LO{c*mhW8}vnA~pHWk2zdO(Xn!uMKT5$np^X?SqP?R!4tIaJlYjr1AQZ zT^`S5?ae^R?~pc~8HG!Nw~(>0LkW>KAG}%9{83Ydny$0i&3XYNnL@i?v4petq3r=` z>gn~q&XOA!&ERx1qb3)IsJqXv@d@$uG2bzK2xDzOaN@t)$zvI?jZ!wND|VvQ@5wYSfnZ|#~n|>TPm+2B;a%Xp6WF!<(XTPF6ki-UY zJDm3*;3~)hj07xH(kolfloiO3c}(g=Lv65xE+~Y~2df!LUJsz{s|cPpF!2;ufhw7d zyC|^jkz3l1*ADOA8)1j~Akny-h_ae%K&8iYV&Zxi`l$1}H2#XJhdIC?%^#yOrCAxHs|$kJ5k|z`w*P({!RB~@`BwIDq26p} z^m6G+y&8yNHC2pXrdu7XReHkuSzaV3^I5&w*qeL^WGsc<_zn2y*B8kIbH?>I_kpb{ zMPEgnINjPgaVfAZkUKn9y60$28z`_Rke%w;^7)6FMyKCI0h>K@x@HG|IM}$z}WmhKJYkd5%?JPg##>PgMtyGJu z(8f&P$4l)z(%S={hf^o)^7CyiZ>`HnQhZSgFj~U)dE?tI=MFTw1f#6GCC3!c>m%FQ za1T%;^_X@Cs&czEj1%}q{&?9UF%fO7-In|o%L%YKK4lh% z^`|YejleFMz$QK+Hp|UC7{>NEd9gv2o8^*7t|inI-1HtImf|z$p{ZS8QWM@SQ$WK5 zDLaFW7=Z7bNslw0o@s8sNezy*T;#aTSrQ=NGM8MVYOD3ScD504pNP>2vG_zR4rX3S z`mK=cNJmXeWEo~%F~WK^WaFD@=GAWh6d+%PuG6Q;vqv267nakYCQdn0wpv#pbc(aW z3F40#Ddt>ZLoSII1?lOv#kCjl{eC!)Dw?s|msha!v7RoKW6`h6ueF}3%5J25pxF-S z#OiA#jVPvm`ig?VQB_H?W-v-H&|1D(1_5wv8nq zRb|HQHynq>7{4{566ZNW&blb~$nTol>uVrJm@!YCOC@7Q;gFA=!snR#j@iItGqDE- zfv-z+Ki}`B+WXcyGT@!s@f=kULpdIDF;alT@-?*msi`uJL-hg`Ge-EX5Jy2jM&zkM zWU0`Es%du%6zNUv_l5Ml%6wpFJw}A~R;`z@53wWJ$diGzV5sL}K18z_-^OeTHabpS zhyL(x2wEQ&lL;>%Xk-Q4csj-IbG#G#)3x33OW2Fs5|((b7=iOV8&#qh0C#O3XJ%m- zcsyR4C($jk({nY6<${IfdZcgCBMEFC3}zOwSn0I5Ogxj;3yAY2wN5xqLtYW89e-h>!6bE-nW2;tcj4H12uEJW;cOyH8*O|(8 zV-`6$(Np&%V%l@C(dr)yfmZ##1#cxs4Qj3MYb_^wrsAD<=`@UUU{gecrzz}auhi!T z6{}@#&+K}P+Q;JP2Q9Goc9h;TY5&zb(f^Zo%v8@6Vx8NE&6SUtIew z$g=Rk^;bboQBhGjNtcD@OyMdjlA{>K;>b3L*B;zU<`t>NeATUC3Lae4u!O!(_nrC1 zxupc+dDDJ;cUhfz!)?-mY~<0zAUYViky5|{u|Atmj%pu=Nt$Sd$0e2|Fk~pf5}~t$ zmhcSlrsSi!x;ah^6$=oydiim?o7w5_NqPZ+eCr%BcpliHnn+*T%r1vN8pymv^uUsjZAiJk5-#!5=8v6@ zE+_iJ`grz8=ko9d&+;^VrO@#Xac^l~5hhov(y7Che)>4$(m^OPmewsYRs~(jMbs8n z;a&0I2g!+4t}t*N zbrSBzlVs+V*fo9C%RdB%1RIN^*R{y}ZZe~9b-8x9``AO!v^j76`PYT&{LZAU9dy#tK-t{wP=Qoe*p8P#6I^e*y+0YEPTFeQ%mcF|#8F3P z=KXn{GrC>07dn(a{ixBrw%%j64VgcEEu%N+vS%PR>XV?4x9lR+G`=As7f+;NEV%%G*m$U@g+V1yo+(6+;1=Za$Hu0@L(rx!?@r z1~*tkNRJUvU)@dg%H+Rwv{!S$QpW(L4TbvdM$$*}xG7ljUXnRQl1| zZ@a<0nR&mPkDWT(EVdc1^v!RgJooX5-F}PgM#+SbnD^Ghz&SC$Lo!=j>B|=CQu)&z zSTRU^Y0QlT672MwqN^sVcEIf`QontEaT9wEk#eC941U$=L_o?xeJl7SwyLU1ym73? zaw0MnR0RQR!jl^&#)<&Z2i(x9k!^V7gBMO`-}nsGzhzPsWO&#r%PFg^Fq9>i2$$Lv zGv_*Tbt^WamSi8eRZgm!GqQM;B&#>(h=-hiq?;_1qxJ&AmQ$ox?=1%Vn1_mU94c>u z52#WX6#BT!MGxaFKjnY0lmME`YoD2}01nM*rnBR}iLV!(9me$!3`W5gzl~)YG_kR? z<;-)Y*OIRtgQJ()a0*0BSGsb zmn1WJTmIAhyqzD>88vkd&s_N)nXObOc)v2S=Lrj)A5^1cW>{;Fs$+>rofEPZV1Vl4 zQK@HEyd3AYQ4cw#TET~pSA%J_JEBN_%k=Xy`&vg}g{P@rV>jF^dcB%`bQlYBjzY*% zpTfX#jwiQqUgq{?PEImLo*6&c(51YHzV)H@<9!elazGzWVNb~@Jhj~RTbZkE@w&D% z(@a>})_%~plfiVu4pl+g^iTo$spt$%zGei9@aCuYY-$h`9|Fwc&fqwN8I3Hxv9obb z4}S6Dq7jjYYKr9BGtvs&MSt%UT=HhXoyounJES197}~p4myk7QbmX1irAUXs(FfSv z6L%4jD@kVL?S&cNKJPXn=iAM0c&v2!GG?Uuj}Y(aYZbwFZ3!*`gnc1%T&SP^$7$b z;hzKRY&peaMg-mJ?HNCW9R#AYQs~+}JzlSz?_J>vU!Ht%cCPb)dq|Xx&IHy^;X<#y zHt}F1`#KuUxcl!kMAr6uWNP0GH)t5bGyQ$!6Yt(T(vF*Ae#Fb;xGvXy^RXoJ0fv}~ z7Iw@KQ`lT>kQKRdzUO6?<$4uO!a&xCPnPuwwhJv$R@2sf;#-Foy**nOzqZ#4RhRTG zE?SdMbw$jL!}pHQJDHV}E_d&*PaI5Xr^>#I?jcGBHqp3OBoQ(eDdj-5pJL!E+l@xxI;qVL)z5%KlfznMz%2=}mI;+H zH`1Ja^(+#>uX2)D^vCn%zJLB1_*`{YIV+CAho&#+e}G!aZ=xY~+p4EcVHYXcB0KW!L78=>= z2^{Ma3v9{6tjiUYFL{pbv#lthYuSNGNs>=-&t`VM1uPXRTOk_y`D%M!7?Z1>Uy)jl zu0CmGh}^#>spj}jA0+bff&ChbKSh7FQl$Yd|4$Yc>N3mnrVlr#8U_Y$ktJ=^Xoc4z z{?)#fp$sr;^^6Oxf)_k7y#s_oir>CF7~NeK-@#}-(A+AaTrd$TZq5nIls%+FZ;i$- zMwT{4<8mE_J+}<~IlM1a2a)YY68FL$Ayx9>K7Wj5TaY+4u2FboLZn$R9P za$(#nS`y(k5+`q3RHOEHu}|jxjR)imfne0A41QORTH+2buY6 zC#8R-7;Q+mb$UD~(_beV&d$y-wCTuOS>!@ES)EDxzKWLO{x~NsaYtF_H$|n+S0nJV zTRj$MXx^2(SPu0YBfVZyfC_u!(Exd~=~iw+QQqojIZi^ZWm=W%S1u7+Zzs#7=Q`P1 z<>`2eq~FXeb%tC&M5XcE@p9YwFxLv*5k1u_V7?PnWSIH_%HUctL10KVxBLZ)r4SZw z7s&F8(pq-F&u|Pp#tK^Z#LQQP3U>cS1&;^KEQ;2zoWFluF{@V-ujO~Slz@)!9yYK% zQE(p|o$t1JJ#{E79_Noih2IVRQMWG?4%508ZTGwxO?ylk*CfT zmmD%uepA2r%%LGr^es01h}ZnCdywz0-Q%F^!CsI6@b-SOT!}$JrCx+WmKEGVT&l-5o%L$E%}K{#TkH2Emy(0$&ZT~Rp+%;`|!d6FCxaXKSe{Y zTNzem1RiIBqo|MHK@rtw4E-Z{kL{0=a!kLoJ3n|~5YACmHyl%dlIZ2qCUr)YEBh@gIkql{{# z??9}GY=IM{OXO2~$+WFrQR%*p?2 ztMTt8u|vI(XrzJ?jCEw?`YjXEC>2@<0ux9FH+}LrI2dReOH039zZqep&z-z@B_FS1 zV-no5Xt1vCC@n25iXNg6ep4;STA%eskTzAdr{i<(fk-sm+*VWl9~@i0oSLTb+LPI? zv@I1HxBL3+EjCuOGjUE@(f_I6-~Ow9|8{@-FeXD@5JKij|G6s0xAOM(_F|B8WE5Tv zmV*onGX7N~Yz`z(?2P4MWc;*3s6x7oS72qBiByEJD`as32T%OMK5?T|5AAcDlL<9n zukuWvDoD!AB?C;I_2x86?-@w6&u6&dFq(R4vYg&?%K^sOxo6%>gM+1^Dj`}vp+gVj zFYH-4w=u-jp8_y>sq?|AZZXcG8|FBI^%;GBMDVm(MK#NR`in9cr=>2r`I8mhI-V9bRC+GLSy=csx5V9JX1M0WrRFe7I ze3&sp-uvb!9xYfLCAS|ISP?wR6ZVLOzI`!;mglE|7(kWi&rFk?tciNL9DfE7);jD! zL88D0A$Rzw4CIsIFiJc>Mc;N0o@hvi9rR3;8wz;d{0cb?f4p+&DP{~I)-H6KiVknR za~2xwlO)6oP#b65v8>$9O>G=BVD&g1+Ye=l7mNB?iN$LQ^gt;1(k;W zy)>6b_x>WN8nl1lYE4?Ki~pu0oJt~OX|C_unUqqjMvFFNjf5B}ZmVnCpKJN|#MRD0k1-cYktK==j8Vc9u zHUUTPEsct0$r zU~SKK$dM^kCWDrotqp54NXv;?UHnA8E5Bw9)||+8OFC7 z<1)R=@ZAupIlzcm4fMlnJm-vioTV#yawUchPA7bkTfXjEbO2 zhKQE>2)m#EX-qM@t8j$__=9|t;a6{H$o3sf&Gz$cgc6!X@t|A+*L_KoDYOD$#I9~w zIOTr`J2)5*PS|BL|E?3rI57bOz8UC@S)YUURxIPN~1jFA1AfCRW1x zYV#nEMZX>}lvW$bYX=Z%8MA9dS~65gd)3x$}zz5)b>`+QhYsnnfIjA6tQ zsgo%46t$6~2)nK>Rfk|6&NqIaE;HTOwid#wgr?`Ck@ksUv#q^Ebhc%hNU zU%T&+WwXh{d>_YKOPnZ@^NN6-H<9A-_No4$H&-jRUoa^!FpwhaGl`nI`d1>UW|bN& zq(nIif@SwakH;O7fA?h8!VrW@dM1`Sbi^nGkt$Da7x$0TzPzn|=h-kOFlqbRnC(fp zEJ_nsRX!4%k$`S_P|uV(u!`)F~3{URV)X^>gs#Tl!Cp?l&Y^9u&#)s zc8sAHSm*g&HiR-ZBSYyd+#9up4Sy;Iv>&>xvv^T{kIXTy5DUkaq$%8%-8G|_%U}F^ zN4ZjPv&)krfExlcc4)@P_7PmzGbx)*i^ialnTYn^4mM-G7kEQbyx)T_QmPSo`V|0a zAU5qQb@EUvNa-a1=JZHYT|coU`^2O-KY}w;zp<0_#(7OR+){Bi1LVC|s)=z1dTqfBzT5I5h{oI0$A+bFsav|HRh%arq z-HPYW`??vwc%~*A&Ly;yfhK&7*}SlKo{19wWdQ_aN+pU&q4%wrKcNwhQi)pd88!8~ z$J?qD^a3|%=zoqUSJ#)E750u1a83o4=&;JFl%T%`Jylid&t34lS!!aj|GN?RpF{-> zS0rWPR7O0M_@r!Pg~a;mT{n2!hTqeNCYBNO>vcal$0nDWSo=pI+bQ2dr=q-jS-sW^ zj%uaNOPvRt|0{|A$Ff_MrO4hl_0%gjg!c-%n+)fu-CnBoGVE-6&KD{7Rmlzwx^Pld z$9#ZdX|YXAtmU2If+k>FF_nV`z2SfB=!=@;7Ur98$up^Q($PT2@0jJy2_-$}BL@wD z!=OirT8mA4%ZP*&%egN_s;oWmwc>fU3(BiXI1+i2pU+v0WU>hV0qFmE0Cth%zkj#f zpDr7FD-$c+120IrY_ZE2TvueMxhVGWyx0dgA^2qFiG@PPYNR2dAY%x(+Mq+rK85=7q*UylU zlqOwmq3mpk75$I=AUHHk`JG0ik+!$1U!s{zs&a;-V|-b%hla%F29yA;Ow7;E%SbYCAskA5|&$`VH5$iwbt_CflAz`&b$?5K< z>Gu|7^Llv_%*4yQ+%CoE;_b?uuUi!hG==c@-Il#?K}g795(klKo-nvCIDO z)B-QG2AiD(zNh|&izyUDawATy8tA*I5mu{I091akeXaK}`p6RgNL%mw^m0p*x=Ya+ zTGm9H33tJ(VT~=)XVAJ7S9?)|BX|KfT|&dB#)(Dc}rXd_see1Hs$uiOn&CP z+lfMyjy2tiC1Uf2u^EQ;65bcd3A-L}eG2W6S$ri9aELdB4#6$Z^5vWfnQ zE!On{u^_ByR?w<);khQ*bZKNUGb6@GW*pAaBcHjIjYusQaBIMRM1s2*&wF?>_f&N@ zW-I##$3P6|Oi6$9!W|xe|0|35U!U+bq!gH$nU0-FlYU8f+L0@9wxV?0b33N8GPX$l!unCc~O?$d+J1G9)+^PQKJ=8oe%qQRo@3kfmehG)O z(Hs+XbW)1$7$MDLQ8H$EZg0+Y)ZaWC{4%%@tI5DzoYg|}>*4Z#W4N4DXcCCL^+o=L zI*Ckv)rN^w|0WgvuY>%X{T)!O_(Pdo-7_`Z6{R@ZE~3!|4vaFHhyb5!Ix|mM2%=#NB7h2s%^cfp7lM6#C?Lh&=cGD|4d#D4UjwK$PNx zi?Q=^5i1O?1&m?-OLAL$50H2})TaM2g#bpykLSzYcQ@NZH7*lkunz!05VXe1P|svp zY&}qIyhLiV1MX!Db(dWB<|=tEh1$qyc3?=?e84N7w1$s#hl30h&F#jy9PhdGXwdS( z)T$v{Q@eYaN=1%CHJ^?1bV)e3GwukDU9*ES-HO#s%quB?FJC)XRHgc8EFY9?U)G$- z{3k`u0U2kuLwxI5UeZ|3LoU@$aY;`BBezs{Tw8HRuBl$@W%lWO4P8w6{?y<~_kudl zXqSh;g9o)}b_?`Q#x=cO@c|gyrbqu zr#(mJ;bzeI=IyB{!v71{@Glfd$OL6`-=w`yaH8ID4%?r{7s8X`){Bk_4T!R>Uu}`dqas`DL$Qc)rev8O_wF2o9MYpi zd<(jLyq>$b;QW2D9ru4;ra+AmMP#Fa$8TQbm*MiScy%!&5s=2HV~vTXY}s7kYOr7! ze^aPUKQ>;BQADCFR8l8C&!{(;fY=y7gwY=Re(mSG0C%dRxoQ$a_aRMcq?BYh1dHCZ zUB0lBiykt{1a14dw#LCW^@kXj&`()BLs2cYIn`!JLd;bmGPI$aYyY@yIA3L6G6Oca zHFi2RF0@!Pr171;;CI;ph^B%ReZ>$X^0*m3G#;=xyB%k8**zfZwRsnS zXy5wWT?)kL)zB}1q|!T04rkH+`8|ke7bGK>54=d`K`&FC&Ka#n6wkj>67Hd7evi>i zwVRmOdRpgT8s!;kG`_E4bi}5JkBZ z>O)yGmTM!-t5e^+aT)&5$}%AS2J7TtoE)r(;Y2c6Z8kvisl@-uX9Ud(c+g-UX!HJ` z9g{ygQWGl}qN&LQ0&y($7GZ1>o;Fl%>ubB-f{h@-jN2apu!U#TUxT{+9v+3`X@14M+P*$kkdwQLxy(MlS2fM` zX`ImMi6kZ0SUen@c$Sp;;zPrGmwh+sSU#3&EsK$~{ahY{f6jA%#QSFm11;)px;k{0 z?+BEdcoWM~U5)7ogr4W(%QERRM~iHv1Y@G=46|D3qfp$S?D-(mM)z6ab=&BIr z>y()I*CWeamOogiYiYUW`5GAs3!TlX_mHI}VR*hjnyvhf`L<@IMk}d%U^#=^>eGwb zw4|gSFNb9*-W5+m{0&0nL@(}qaKX68cE+Jj8Jt<^GH(ePg;N%eb}Td-Ogg30I4y)n z=!Je7r>Cb&KGP9>{J0_G3!3Q?CD0lAwST&zhIV`&_LroX3{7X(#BDyc7tFLGl+>lj zG^+JY{HOauwB`c4r9h(8AUetmHjCk*p}cDmA}Ktbz8d~fNJC*CpN$OW;;qZYw#%)# zL=?@e)90aFsR$~kvf~!sc(Bs_TqO$*7l_MJu@l-9*yJX}{X_eJ@DNJVJo z(pOB0_=%l-KcT+y6NfHE%k`4Vb)+uE%FBIsOrH*K^s{rCeTKI_E?)e_J`4W*PR4Y~ zckg}#zxwC+_Dzfe@EXmABB2ND6#)eaab5DO%7xS~^Ds)B^6nwe9lPXHZ%m#o*tIh3 zIJqA$OSmt(l1Gv7{#5JZ(&lqH!ESxL@^ZO6A)%uEly+Y+5Ru*BxK8W2RY#usq4@2NY%iWR^J`#`A;>Xhv&%7NY%<@lEnOjSv;283{3y zcS3hJoHf3W(n|-7EFGri!S2g%#6Y|+GEI%B1VH?52Y_;ueiP|3y*kv->pud%UQDGp zUUbGxARWZN!QJ{P)M5W>WSA@D=T{WuAq4LGlyld;NwA%T8^(KudrAP623df(uV3Qz zrul{TtLA{=Jx==7sqGf@oxq6le1T)%P~oQwbU5|0J(*VMUikJRLi)FUy`6h$v)71G z=kYI@Ot*`O?hdb``w;dk!DVeC#Q$5~!jV?Drj(4Omtlm)C3mWoiT3;k8o{q83ke-y z+TCJN-QV9)QDtoWAa*8VH+@}Z&o|rw_17M^V&)m1A@_mPZ?b$fW987}#aq5K z0r!CYt-EW17%V3FmnT_6oFe7~OyZl^vD@eAZGH^y+j#Adffgi?1}jMZMn$E_9s`{_ zxaNW@Z`h=6v%_A@t?R+qtD-SQV3xVz*t-yS79DJk~Dyb+N$&1?*U( zA0Z6~H}t}f7ZZhgwS)dY;S~PQZPDkcUL?FIBlJUquUdxvBQWENR;^QIE`zD+43rm88*_Ct@i7OA#rmkWtbNvWREo%~Xq1th7~f{GyE2 z%Q5wM`tq5YxO4dD7?@3y0MdGtEPCx(!uPIBhXNY149tve?+-qE-bHBEQ1#vmKm2-C zzCTuLdBSiR)fN$srA`T*OK)?*ipr{OT@2K91HKeuuOStB=y&3e)xXWP<@0WtjJp>& z*+3cO2)L>UP0dKPad@=a(y}rT$ly5|%$w3b#2TvIQ~0*^(~x-djm#9KtKWvlTVD4U zLwZM`Sm)C>QAH`g-EP-rShSQ925651=BLyxHzrrxm&%CSO1<#-3v4mcTCK>V?)nW$ zOWYC;@0`=rhjS>2AJ2j29HzH{zcx!^a@-*{`BK)`&l4JlK7nZ_IFoB3GBVIlV;>w8 z_?<~8Y2EEIlsJ=*S+4Ip7TqGZ60Zm*#K9F2gzV}|7SKSjw%?SBVwV;q+3$2yN89UD zPuKI=SCmv#RE1qFQ1jTYUw=Iy`rMMQ{2;{xJ_v*AY!|kmGzy)r?CLM?u7#4NW1c8K zt0?)=gmm4U;_Y;xqo53y3f|@qPu5uCX>&3)yNht{d~^Sh=sTS5f!V6nN{PeK?Diqd zHw#~Xh9!g}!xI)pJy1;J@(HoBll{=rXVtY3p(*mWql>z|@6nEF+ zUZiMnT3iDZcb6cc6f5pf+%>qnOK~SSU*7xOpT50oJ%40nCG*Uju`~PZv&W#Enh^S0 z4263pXFdjL^aV!vJN+S>Eg@6OmO(qEj~_Mc{=!}U*Kue|@h}MTXjfY|BEcQQu%VJBje(HeW}(~o1ofWHN);;BE2P}H3OtmIg=8r6ArX6=vm*6 z1k5&F)F{2fI*o-E?v~r`K(wQW_q2nh9-0D^Du3#B&CGu*^KmQ73!;R%BX?DVH9^Wn zCB7TyYjXZx+}InJp5Pu!S~6Q8o+<-Nb$WbQ8~Gi2ars!;D!=5!P~~PXP{(U_S_K>b z#aZpH1*yoL>p!#_&jo&12S?LYe|C;a%VX@4UZ%;fjJZJ+hNig{k738U)h^bmFbjqT zL6&2-O9$3gP{&#-L+XyN*fo0BDbA_$-qO~TBfb5%RU)Y&1CjFWJ9zS+Y$ z`?wVba=0GOXtcN;X;m2^2NrHe_q>vnOyfb|8EZp{D;K`&s}ZwHoJ6s+H4Y&n;Vai-wIcgqCPzvVn!+`2n4gtMGG zVFOTBbX?6Py$QLa;|h96c2@FzcS`JoPg#>_>rjfMmH}JBqenl=#kS9Kc4+)HZi#q( zPcmsQ#Y(JQ6X+KR{1-^_zdpAJu3yap_816qb5(X~UGV+ATm7ZC`20x(k3C}CAT^1X z98ziz2RZ%F%I>iv>=E(S7uX~SlI6FWco#oygC%s&!O0tn(&J>11Tjs3j++tWENNnK z6mW(Aa7XE`Ha-`nNjfvXWVhgFjZ{+ln6rJ!VL6uC#y0aaNp8ofP@V=f|LT3!$I_>& zmAbJh!8a4va|;iLK_!0g|DgrIxegAD+|MDAAJeksef2(`Ig~!(LrIz)Kx3u8%y-&$ z1nbr_&pF$w=Rgy$-l;;VN4HGs4d>b|zgv^)Tf?8dYPfjztFo67K&e(?2dv%?MT(7X zI@hPnZVtY^;d_(pX}YK0UiVdrJ%jq$d{sBzb9Pn(3ltZ7%KRdO#gJIB!!-45FOZ#< zosel)q5RFkO0nJZscoJ1{hP~pv8AHQhMNRgW<`o#TN z;FIh-!+8epfaw`g)B8X zbDASVkAo=k9~H8NZYgr}b0@Zv^(FSNW6B$kZW^hKArtxZoHnyDK!AOI!2#?#{wXIP z;+3K(eE90=i=oGja~yGp!}~-)b|#0b(8E0xQ~a0rLk;`eO6SfM3Q*h|Zc7RA=P>U1 z%x=TiGAlkTI#N$wS6}6}aRelr42O|$1f{BW2Dy_)amXh#QF@S5`w_2DX@uDhSX)nM zb8~ayX*(o+L!6;s8ozFs$FaUT`gJEd-&SR2mX|-+cE4Z?8#^N?`suu%)T40VwTv%T zDvGTd2gLq2uUQN)Mv&Po^l*{$?x*OGy4>~%3w$UA6`Jc9L<4vFm(z|<E{q*QaJ^TzuieBeQK=4lLvFIP*I#X^BvezHEK8ytb3f8``6yps{K=$n*jP(w zgw|$(IbP_-3L)-{8bBL`73CS%dFjrKRoMLVfi)XiyIP$Slq9>aU5^na9Ct4 zVz_M|{x+$Q#Y!nvxpuS}| zJZp8ZRe1K%I(K4er!Hs6^Xw-|cv5{+-L~+JPRxUnBwA}KkYr}91i$w53Pt<|r1+^a z?d{+x*{!?kLaM-iIbO*M7z*Q#edBDeaD3``MK28Wh;b?1nCq@2+74mx+u;uxU3x;! zv|~HTx$UXqcGN+@5~!ha=FcN6nRSSzHjlk3yu_U6@aws&_QOSl(ARTA(yuBTgpA^&AG;s&z)bzfi$G zyeBGea~mU3s(za~xNrE{_|RvCtX;k^P144q($FH>PTyjFq_sCEhJncA{Nv17( z!{>KczkOJioS;h=hjsCA`~hrxyX^Dy5q?N!_bMZIVOVn6L8`VG%dAf7ma0kc+Q?(> zsX9FocfDH~age(fCif1ygGj&pwdA*x*=tCt@E%znynEM`jq?WDlDqb8|HbbDph1r1 zgirQZW+W9jYxgR3Qqqglys1K|Af&hws|}4%TC(rJTNB6Qw_oFZmH4^#sMo>ijy6wb zN#S3?lYan~pAgTwt>qyaHR-^DsS$Iwc&+q4%*HQb-h^+=EDPPa(yfXP-Y2u$imFy3 zKh!09S~~373}XYXF-;bPrOLjWXrmQEATml`En%(7ENnfni(Khbg>om|VZ^Wi2!Oiz z>QHz7GgZg*&YT0ajZO(#ynC#b0yXy4s!L9$J^)|#mtS%>1@s|2WiA+{_=ADR(?xO- zR=bAz?}rUm+g;>k!!I{)SFGspczZ|ALer=XTs9skBnJh;fXpsNREKkAnj~W14~RX^ z-I;%S_Uc}Aeyb!dmda=G={u;~mA`u3ar}<3*X0DjCpfv~AH@Px*+*I)VN>PU+QiMr z$|LqI9Ek)t1(Ix%4^_?Ks2-&q#21K(6SibNSS3<<4Ln9EJ=KuaSf^W}#d&LoyfnJy z-3GvF-eS1JaI8N1*ztT8nD8;9a-3vMvlL>@N*YZDf(>SKsRXk^!NdUFl`fcm*S1og z{gp69;S<6AU^8!pFXUGab2FDw1{;kkM9ba9bnZrzP-pA-D*RU&RA<)HXwWL#Y9VOq zH!P9YX{9f>CkeZ-`O7-t{eiq;n$Ek#_t(`yP7Ev7^+zV|=EZ3FBVSw3gc2$+&0_UY z@^|h@AX!b$N(h1uMkF3vX*E5As;5LMPr~st6L0Y3>$A>vel@3b4{^5|DlNIO&f9O> zEXAs;nRdS2SS zCGXt*!tvWNNh0j41zM^qj!ry|+#@ZMUX&29F@L7g_hh=7%IHkq$*noNeAh$#&q+Qp zJsRs-ifL|13x}@D6z}tvn?1)r6NXWMHW}baqb^Mbbl-pJfe{JiXG&Hi4(DsPbsRAO z!ZL|P{%GoUV@(VgrqVaCL7VPl;yDhrBvttsv-wJ3p1=yeY4pcAj`P*_-vEwep-Ioe zpFcx%Yi#*ro zQmMU3+>eKqhJfLy6)YUgj&T;XU{qZxXF=aSmFTR0okE$o9f{pLymcP@w`! zgz35nda3WyeVKGDdn)>mSqo1yvA~V7ec0OgaSB#>`91x1U_il)jWYveK2}B(PWjk& zSZz-Y?ST=Oy@JTj3t&)XPA^>VQ1g4fJ`ZP&z?6BOg z3|~V0W>Pk6bE((94pmyL|HycxyIE(2{*V-ipDV#PKgnWX?86*XTeyCd5@>O+Ws5JT zW1Y}2I$stb%&-bzHkae4-X1u+k#~E(o+cpf1S~*ff@ZLqw#x=6&{Y?LOxTikdOqmP zxTJ*Nq?#p_1vGu5p6`Ix6alYIAse4eC#VToqU|(?3=IdO?GrzexX(R_8l*OVcAjIb z4?TBdsu6}=KlQ{C2iKheRuz^jR}D9~Z-584BvrC~Hc%8mNLUPm=;LxmANA!1QQek! zx!2tsw0N4Wsl@N#zqg^#KPmx@waUF_oD_?W?J?&_5>sl5Lb1uaTwF<|^HWt-Q1U#7 zjv7F}MwY=6pVM=Ux{17p9}17x_mAF40fY=Gyw=#Zp|SBzW&*&>rSRt!ly}k6nLmcT z%7-wQqrdEqZ>hejDE}Qz*JN}1+C;cV`_%{6gIP0x;jmG=!neV`!S&q1$|-;3&@Gzp zvvfAgO^MiN3bF-6CEo-3t)|#5MV=h*m--k^*sWE~Lm&IZKt@J$gMR03N#%oa_g9Vm z)t}oboNjmZBewSFNqqnr4h}#c5=JWeUuph)BJ`}SHXQbN;w2!8egg>mg8OBvb5puE z>fv&8@O+)MIM$m<4sQ9HYmDgZ`MRtdfzpzL{i{@UaWXfqJbdP6j_B|8oPw{rL`&onKjk0q;v~l{OH&^SUhqWglnM*p|?MiddCR1!Y6ZTTinGkz%{kK}oS=Qjrgn9H5nS0HpzaUTOxQXVj4C)} zO$q?KWU$5vl!bd5FW) zOjy3o2zBI}O&bSG$v4t>Q)z)!b#Lw7hnbD^_@?HD zaaS3Ax1JR8&FXFY7V!79Z{z$rZV7_VF8!4@(^T=KR@^oYDW8;|gS~l^fEot;_XE$g zz=xKE9BMbFd*{Ra{B26?CavTYrbPg83OshyD-Ls0!t!@-p-K7h;BaLC&p1^Q$`FzJ z?k{r4DiZMGqzx&0Pp9Fs))VP$tS>~HAq)LjjUo8l>w3)M76S8JYUJ*{zN!{t^(2aQ z=L|ed=W(~(HO>g z6vX)dq;wI8d?sP7TJHX_N-RC|qs$z+G$?-V8~qt(eWpTwc6e)mlH1KO3t*EQqsX^dcO(^M$E>Ft=Dn%=6 z1YYEP`VmIbq5MVp7~;qcbK87duU3}ztsQwT(#;*->eZ(B2a;1zmB&xR)MTJM@~Rji zQ^q&69kOe1a_iKkwXOF2u%a!ApVZqmtpHGIPw?d{;$vYA=}UUgwL;uIUM&zKVHR&P zuzDcQfs>_vBu-gx5f`mzpO?cJy}IeNHV zO}c1;?d<_uZ~ovPXi$}@@pyMkkD?zusK=jb=<$21se>u5Q2? z=waB5>fBPCvM9t4u(<_wkO>FyM(2LvK91#Gf8hR|s0HB;qVqJBdz=H3bDaGz_;{wu z`o@TfV!p~3rzQ?OFI{5|Oy7Rk{mr`jK?v({$fs3e#rvGt`*w`~qRrbC8Ss!)(dXT~ zQ`$PVlPx_O0$X0Co8eX?f#kjmMqla=Mhbnu$GKVVYenSX;AK|%%JAC+=vSl5A)A+k zMZ(Jgxc8!7s6w;wlSz0I^n?0f9>tlxS)cddpQD(P64{h13yr{Gb{N(qp?)>=Nu>cb zM@x(v-+L&yJC6+mb&AhNG;r#m1NQE9mT*?^FlqfG*Lx5N0i zGa&V=V^ad>7%Osrape&}s2{-3J2v-mw*AiRu|o{Hwe&^>j#kTD6(zWsQb60AT371M zU0?qQzo4nwnCxoi66jP)!hxRYpjT-g<}Q<2pJS@56t_+{EjF_rXM;D4ea7Gi_HyOa zA?UWZabmiiH?yH3D!F*hH?-8u$A&pKNk_~2kWbWmEV?@jW$KZw*pBtPi`y4utYypg zd|#w)X1g6VH(zs**spm@NO~pQ(RkJkGz)=)Kh2 zs)Pz#idVc@QKu38j$ec@wx%ZHu6fUgh5?&M9<+n&hlrZ?{4zdU#O>@!%4^&$tN1y<#ndWo+7U#m`QdlMEr4a`%>w3qtxXwK7^ICOV@msZWlEXY&mBEQ>10ZdSToJv zXCEDY;+C0jKFDk}Gdy4&jr;P>a4vIKc8lUbc$v~SA6nB;H1MK_s=jMHg>=#@C&Cqy zK*@n4C1O^OTpO-&Uq-Iw?>Q^E3F5< z1PpO=;1Oo;{*ySv^yy%Nk0(CaYV&%zlGJ=l-Xr3VK23~Pl)M6JgC7 zm?=DQJ;F=un|*p^y6)AWfZHgn#Bt(nWTYU6nWgiGj>cneiv!qfvnMy>yFPC0IZG(w z$pdVed^7{VmJCaI0YBXbN_3I9febgA-*Iqmak_mr6f(O<7kULGe5h~>b#NtP{nQeN zL%6O6;NU>olQCrXR}YYyOVdi~DqCv;AZXo17QU#jcds_yVto7(H+W~8SKsnh!!TMB zGqFXpSkIO;!5m`CvVhWOqw;Ug%@^wORFs%j$Xp2aW-@aPfzR}NH`xQDr^gsY+Z5<_ z*>Kj=ndLH3CE7$LkY(Fpf!H$if*(WE1ZcU6MFdQRi^<}^G3yqs?8BnaH!V> z1%x+TxcksY1hPjNY}SY)vh(cO6g>#D9XXNKz7~GN!QBqHp0WSK5 z64;T{l5C+78sO8E;kzKvkl3$~LIeMh&t+a!!#wKSii8wq_$DvH`*=|?b~6}S)Ebtm zc};c=gf4}^EJtl=cRg&0#JYq ziLFtAaQfm-bG?*=AI#)^d9G1~Vf1wcvf|emzNRg>bD5V&rA$UpJ4K}h(}=CI{HoW` zwZML-%_pcmaeHQ1ei+^=t+JMa-7ziukqxDGxln2 zM8>rYKnxGC3>cF!nh}i6ei>0{%oCvRHMZ)@HGcg*3ZB!NAU}Ap)R;`A_Zur*xnkD; z-TBn)>BZ`p>+Z+VHU#forZj&~L{esU!*kVB1c4$I33-CeHX7a&>7-iMy~$YJQ|EnA ziBUKaYwBZSToR6GftTT+D7Iq3&+jb{ML!?KE~`MDZ^gah#m#Bq;*87J!E#qF36vvg zq*pX9=#^eNinmD~v6z)an?8^H-`;+N$W3YUG_5rhX{TRA7NmB^ohUuQ2#&!zn?yN2 znY`gJ=)GU+xt|oAhXoKcHO(W@c>qsAGsfA|&X-`)a0N3xiq*H!xh-FM=e}ta@#mw# z*^kopk30Geu%iXUWePZBXdG9!TRODEu9V@sI5UTvvd``BjS-po=7;IDh&#G&_O#Uu zS79_<_Zlmie^JkUGuw!oW{f$6`t`0_Cj7l1+I6-}tVh_a0Q1vhC6L(}W(_hqIBI^Y|*}>?3cAyF1b*S30TFt8>3ataX=Zk!%o*DKf`DMxwCKIjVFKuh9kn z>Jtj7w9hYOmCwH1kLB9BrPxS*ajtc|we`#MhEFvDY+dNBL5_1OM>xGnCu+_&aAs~) zk*srMwpJm4m_)kG5r-lQexN_xK82*+U4!;*K|P=FQaa_mMkXB@VdCb5KK#M3C*ZJy zlG%s?!SvbqHLyk7QXrWfflcYi+A?c$qLW-`bNexNI-b(BHunYu71i)Lk-suZ+)-V* z6-oNMFTZjLy13}zc{HkZXOY5uTTP8&In=jjeLlEoq`(m%SxHz|3b3+fGuHd99_SQ6>`f=ba`L<6@ z+_mXlvZ0qQ7C+^3wWYksqfGz(-DTT@+S5%36GHOiFH4-EI|?trcY*XlC_KzcEFi8T zhQ2}sW@vPnvJy`()=z6C@L4~mMV;#tDskwG1n@uYgqMwmW+=U{MM>fG#HKi_n#I*{ zJzTUUy`QK%=KXLJoO%5|KmW!z!?ECFnx-dTD9zhYyK6n zt&H*sx&4$+R*OKYF&|DJ;t&MJ4;qtsoT5m1CSy0pfKsnWqRrST*lPnDT!kmDMYs-k z3@wiqQ6@uR&7>|{x#}4}jfUp8#8nzGLR%sgY$o)tgWa7457jrsyWtXGmPbv2wDir; z;;;X`50)OdPZfy&a;FN#KMkNlP8aFEXnqnKrT~}5|retYECx5*~&`;@Ar$b6k=bhp{ zKeu^P-XJ|-D98_2`m|lhx`*vN7h+wvpQ^R$CB@JJ$1<|!Q`+iY=I*6rn!yEV*$c9T zcN)rC1rjtkH9KIt14&r+KA3}loO_j0c&=CpW^a3%#Y65(Bt|AMi2?16p8 z(|OMmcufJ95&=JdQW_sPK6!x+d=9sK!3hNn3>R$=t`qPmBh(mD=WnLC=^uC@9=oaQ zaCMlSsoiygA9e#rb-cceoD`Lz{d|kM96)0(M^j0(Q;?tjYSdt*#XDjyIlp2x8xtin!_OgsNT})1 z1*YpHu@D)Sj_q?md6>*Q)(SFjb$*YV+X8g&8UQ6Q z_MvYHdO~FDo(`Wc2T$B-=ayBC9Ld_ZT#^q#I94n)YhV0!*|u~#7OcBTPJpJYfX>Zs zVI;?|g9$>PF^QIz;movd)RNq|igR{uU!@v=P8m8^?!}WTS}%K`7aiecXH!%^uhrMhi8Rp=c#?kGe zw6V(>eOvc|Yckg*C1_GfdC^{-;g@#GhND!Y$0k~c_oJCm&4P~1fy?&pU(8?R$@oDD zLZZiG!zb)YeqxB*y^&DhP1mzz_*R7CebO$Cz{L&T)6w~`=U*qA)Uw~sjME&IBMAU) zTt1ns@qXE!B@`;C#~aa{=wxkuP*f7!;@6X^)9QAr*_*4j-Is#O#{+rZU!M&$+4O&F zGv2&M4#*(Iq?K<;JAKTs1StQNpROs6IR%SKpxftnug$liP>zNn56QroIkcQRLd`Hq z+4wmX|@32j_YX zFl4-2fBj)ST*L@s&)_Q8a4dgf5&bB(EbsJ=V)KlFHT&s)hQ={hx0*QnfgLe(h3uz& zLSh1I_ie!7qHZrMSd3AvDO}zpzd8YIcqZLYSy0_&XK=6$Q~OJU%$wliFNxV$G!Pn_ zqR7>T=UoP#Qz-C`_yQYIM#ue_2J| z8(O~R{eq<6;=Z^EL2UYG(uhM&2CBD*uJJ!vDax~h9j|dS-OtVH_nnq((vqxs;oL5S zt;)@-H2W3|ILUx?wsj??dpZ-=FxeT??)3#HyxPDYjm^Z36;6z4B?HMh$G|~Dv02t!3)#bbOXnxz+v-ynrq1usOc=li9 ztADVt)}!HD4o^L>lD0v1Ln_IWbs)5(k^<7ygglpgY*^N!xZv)hRo(f?zEzrxkJL6D ztpoP~(K9YS z_g~-Wdrxht)9^3U?xk|>4>&)Iv+aEMuMYiJ*bW{5U{n-IvZU!k_j@X*yl#hY2TF`A zBjsi~w;M`A^6~Uf+7NTS8Rou`ow+F1Q`ufK5)FAXu&BqAx9e$(_i%&9bBtQ=;Uj{{ zOwxNbNI9I9y!?sv%ZkdzD!I^{Ksx0Nw^4^gZ=p%AJAZLs1>38C`A7d`|G+=A;YmC* zHYZ)O(doJ0&CeXuhY83)-FMx8i7MVVpKdS6DpHj8mAf2z#1W@%k3wL`%~sm0q5|fb zLQS-SRTs}*Y1A5TSqTw%7YqcELE8nlN28Ow@)IEdTNaGOC-V+h^{!wFoj~uV>Idm% z{Ad5hXZR0VeH%YQ2zVK+;eo|lyrU>oy#wAc$T5S8Q!LUTB{kFeY|+g*{2Ds<>bQn0 zi3l1>8yOiXlQDgYi8sHFf(@rXp4+E(CzG>u?B4ikS*E29xWxL!I zSPc?iMc{%E6fq!ZoPwHQg^ndi2A0^_jwWt50 zQ3%0b^5Gvc;Ck0OuZy)>$unke+^pL3El7gBCJQCICA+IVN60s7oOT^jTR&5g&H8-T z>&z5ze?i9Q6rw7x^f7576gYC_!uWlV#rt$i>vtV-t6GCg>RA%A7d3kwkjTLO5^Ha8 z=BJpVBKA-Uo4gs60GdMn*!$9{(napp4++)c@jlR~?(R0to@6jS9=dGo?(Tj8E#v60 zdr9#3G5?o^S7qpx^QuXAY1c1qB}3woyi9vcs>SW>$RAERCmmeXVhr2lOY+^Vfcw+7 z@JRQtr;3Nw=w_2i?{G-1&+k>L)DM@WYqu8yOrkiQ!J^Bazg$EB0|Q;$N%XFwdt%< ztJ-6+YC}Qpp#P$9ZndT*)L|_)D9}OiOi$<^e6@cJU3lWMmb1MW*it)1d+ONHz3e!B z*ttNX88aJPi^aa1K72W_K)dJfOXp{`+y9{ns0L+!E&j62{(LlI72&^YLy6mq{FvE% z{wyZ@*Z5OfQf``b4W2%UbB6*rkkI{~NQ^P6(9G4f${82$^VdwqQE6o`kJFBM$k^S;2*{WFiV7%^MCd^g1Xo-)U3_mWBW|E@i}3|n}q z-=pzlTBFP40t0KQAXY6@G1SG&_~ggdm~c5{o&ouN#JJnKa4u}kcF4o zcQBT|q(;%GQH=eEb{;q&s$;m^Fn>mY_md0lDt_5aoyiB2KX%%4PK4v{Egl8}=rJOh zG^;L+-5Zx-D@4B?olOG&_y-qeKLl3u?Jc4s-3|eM^cY`E3N~}p7pHDs!94sOLYf*H zbXP5Qhd!yp#P&NINq=ezJA!8c*N!GEBNO%Pa=!-4jm`1XbJ% zz%v1p+tPmb2OC|mBit=byT1XZHyq6e>w^)W2h116>a&iv}RMiP8rjM5-i(;P)entQHWM5~7c z{$WzJDZY(iROJ(1xGPx5(Cg0d;0puu6L2d@A=0kWe$TL#M$B2F;y*W=AIWP{a3@y! z!vOM*^ljM*5~G@{wv3;gnMos#fXfWATTQ-0M@H-?j?8d(J+hveox6q4Bmi3;Jp%r3 z6~sgI7#CoAKOcv_WV-t}8Ibf(=5a>6YAksHX3{KHKLb3t@ODc^c1G<8eN<=zONmVQ%HxR~)DV8Jo^ABEt0F$?W*X#*RYN z0tY8Y4)t5~r93U&BL37FZxB4K+^w1~1ZUiB-Z#Tk2Ni6w?iCPe%b{o%JNvIbWMpQL zIo68hRTb;Is0gtAq1{g3L~4&)cbDOoT9Y@TLR1b ziJRzum}1|P(VZ?J3uC7SrOPY~5aVr@_Tl)rXXvKlZF3CyVadZLa|zua{;+JmS4PLo zb2SYEBh?U`H^_YU#gjQqQR^N;aH(%1{o@+k29mC=BYuh9h6FeF>c=g**tXA<J% zATOIsc2f|rtGo6VI(2W3^JgY8!&!btD2cd4DKb_`a*~qxx87^R?Ypp(eaPQ=g9ax* zRz}eH{G@yPF_sWLP<;K{7vkWM-5?9%mqd@Eqmyo5Hz-saja3(Bsafh!c{lKVzY|~V z3%CB#FSVNvnv?zf8Q$;%4y+gY^?MLN5z`Kk{BN!IYZs@yB>QmbUB^%BQCWO6X#(8J zO_`G%XWO*?7D61=Sh0gQYZTT?g3Bt=FZ0e+4$BR%NE6KbH8g0yd&df|wU=Jy3HNu3 z3VQEi`C>!}6M5`>o;kYMEC6l$_5KixX84@UXOWjOGoty}Xk-Y#ZEm9mHopF?8u0lD zfUiRzmOSk|&2saU9u^Ij{Tw2U&54dok@DiC1rg9q~=ITV`5IRBJZAbv`9@cHh8yeQB$!x*xw(k{Oh7*tHdX>Dya zCL@W6unFV*A(8Cn-@P8?`8jqs`L)D|GR9eUgjYy9xtcCLV}A~OFk7O}wtD39&n{Ou z?Gj7>VWk73nR@gN(ki%2pS+!LN0k@o9t0daseND>O8Hc}p4&_0+Z9r>z+@1ODn=VH z*i(XUTbQue^j(4)Pl2X)9(=7t_TVPi0DAi)rY={K45>h!VZAfKDH)?zH+8T9%seL5 zcS?=dKIwES%N*8!?%5U1u!{+=mp*-rC1wAsl}ipb`o9_L8F~)==T`r`mzHzdt?%im|WALm1Z4 z@bZUcRGVHr+)4R9fqc;30cKm^0g@lZ|J`vD(L(15l)KBAB+lQm^0Ly?8sUyPR~bB5 zJ(}hW&cTZU3E;k4(k7Zf3Krrk(KE)gEWB0SD`XlK*y}QihZ%B2At1pt!4$|8;l- zDN}VskE(mng@>z+x{3-hUnu3a1RK=EXl&dr|FEcc6BzJ@WH2?krbhb?|0~FihNw)D z*;U-b29I^!xaUR*)7q+sHpH1738bxOTv)GbR;Y}Au9y=l=g6@shnB9QpyDciaABP4 zF<7!&p7eIWx!!+NiKL6n@67<*H;o}c@GS33;JI|$+flfA{ijV>5%I8Di4R5oJcHni5TH6|^m;;jyD%C30NJTAy!u&%_BddPTakgXO%{ z)VXYmM2Z4sfdCee+lOcq5^)`#K+E53T0({2aG0|&YmPiFz9GR9v&5mBU?7paiHVvf z%3?>z(W zKR;``TPfAi9Je{V60&Hu!Nu56t6)_mdD&=GYT9Bt@A82NQEhc=IUI%eBx}Fv19o@b zHwD1Yx(ci~Z5ZzAZ=)F#E8G##QtR10v_p{vg+k(lIIskteN`KQ!!3|u^6?{qLRQQhXCeF%0@l2WB1xc9 zAY8!lW=;tdQp1Pz#bA;;9OCx2=!X)|kJR>cNC}Umjyo64NaU^R6=kblJ&$m1Pz^Bxr+|t@*o*g#G02TXf z@MeGcx-nSL{AWZTjvQFm#F)>WlKveCEsM7vmwn?M(pEQBP!xG&E?8G)CywxJNL*R-X%eZ= zqKZy9Sn%r+_p+Dtbg}-*OUVjMe2Zie)ixV$0vx!P@ZYUz8>SO6s&Z_CH|1n}cV#HW z;3!DLv@O#*s?aPaEL=zdy^Mu5*x3xZBaet0NUE7E#L#zX!siZ2Al#N00+Reomiv7 z5AU}xz>eS=4x{#62NYUlKh8HD>L*E%uV_w-71I6Ttj&z9&1Vhwr>?C@vhi>G3N@_f zV^mNj8;^xPzEw(nH#IeNw*Be2mKTzlNk5UVl$a|o99Ll?1sw!Wn8nX{;L36EG;Zd2K6gD_wQtO1!f9EO=Cr{6A=ZEkC85Vg-`;$)clNX&T%JBti zlkqeVa$F92@n7j|-rV&^w`p7OYk`u(!sJXcZf5rF#`nPQO=Yt5yr+En4|F(8r}k=8 zRaF5*`fiZP=_%-R$$~=a=|=CsvCkb-{R4$7R7;6hh0Au?7;w?01jraN_1RFZX6KpJy?$$)Op z4WazUF5b3^`*PRG$hzptlQw4Uf`4;z{4%6{jm==%YJ*NE;q9rF-6&bAKo{|Nb*hOn zu^c?^H4V~+5fPZQ*=-;~8H_^AhbBt0jdVoa*ruGY#*rd$fv9AL2W zXich&1QO}9SkIJlkT12mFV8tF*8|^nD>PzP0S{U7Go6JbW@1R)yRyzEo^F-U+u7mQ z{jj!i0jj>-H?-bsUM-qTV^3$e5Hos#V4lKBSo_?*&C-w0tj9PMg%geQutGll%~t<& zSbCj*r*LoSAMg_zH zms=rmh{SOiOtNlVTKNJ7`t&b%1ybUoLbnP-Iv6>$7D3K$bLQEm`vczX1&QnhnE?gD zWDjuZH3Tm^5Tak?OQP_yTQ2f!@alI%-=(7v%PW&w2c_(Zdrz*#U>IAvep5Uaa#%Au zTRdk?-5;-n_^e4X0Q!pCA!8 z^;6bor{fqq0tO0nIGZ9(0Vfv4>`2wY^S?7nr*QC#Od7bqY z2|hUUHA3<~uwq8Rf^fvgdSJihQZp0_yC^LCLL(@ZKJZRmql;5%;H)DD2Fh{7(2|53?X&9AN%+Z`VNw zPBa{i^%ZjKKN*D)x z@tlboHo7Rs*seN%*3&lk*??-C-du%*xp~LDiq#%^S(xs1;#Y$G74KkRTLqqAO#Ywd|}3j zozHu&pfy|uGA`W?EKXb=!Sd;@gyS#ar|RTEC}u)U$Hb^#&y){A58N-b`n}2g-Jfv$G*6AJt{CS$QjNex6 zq-|Q;=D>kUm|a-C{mX&UVO@_WpA)>$5_3@7OYWG1CuQidTSLa4Al{@`c|pVb+}dmz z)Z4mg=(<9mYeGOvWh7>uwz5tDqm*8T+3w%Kr~$c!WReR!9R#ND;hf zPGKzF*Lp+s@@|wpGG^Cr%Y1Yv_N94r0ztc!PNfSC=~9~+Zd2_3tCK}NZC#J|u>wJu z@Pq7OHA`yrNpspdRcGVKpo(D)ur`jq!~09 zZ(^~zkK$`PvGS=5P2TM)@=ui0p55pL6J+HY#HmYuL0mn45$d}k!^JTo8D-?0T0q<2d}l)?!hYEL~sbWP%^`jUx!i-n-bf6QGMM)2QA zmLEI}Ffq^w`UFqQdOe=|wI_FBhKGN7`PiZeGQ}Bbrv^LZ+0hj2n9ZCxEK=rwjOkSR z^>P8*Ki@6jdi9qyGu>2ny&@6oYj))66cqD9Hv}qktyT`G&E57u_7xwx7aB? zfI9N5J4|UaTZ4r5)g|<#(pcN>*37v?CJ`91xlQ!C;sa^rbT=kv(e>|dFTb19FiMq| z=-;^q&m^a|83bnus?c*r@{zsaDpp`*DvHzq?tOho*EPuFDTzLBuQ|_6D%c(GwiM`W zqd%Gaao6A#>ykE(s0uqA5pLuuI?94Nf0p{g&L%^5vY$50sZ!`Vn;I;YvtZcZWNCH9 zmAM1==(ejseM3W2FN?cd3GXK~aGh1l>=xkn8SvNbO?Exn9Pe|b`N$+G0FU=I{kQA< z9b21u?k9S_@m5d|i>IXTLS_}Y5#mEsFEGSk4b>CQon>zsm8DNUQ7v3G`gEcRuV zF<%>pVvQ5P!Z{LhVZm~umKAXMzudQ^$!i$Avdb(C`Div9^ ztmOzkPxi-nh-hJ`UY?XpgZ0sMlbC;-4rHcEF)P>E%$Wx$48?m0=(~g053ZfeW_u4j za`P%S>goLaWJK<$p8vsolztb;la;Xu$m$O+CLVRn_=Q@IH~>7nNQNB*xaO!1Z~r(n4ViHp1o5_)&NDGeTF{PL@LS7@@X?LCI$aTb46m-^Q%Sit0hMz zVvcHsypd%?DQprNa-Qd5oi8Slc0@SxhvNEANQE5h3Z&j=@P7Rf!8#E5J{6e$tYGFO z1&@7Ag>2vBO}-dzMNKJ!c04F88MMP-Vmv25b=bX}zOp7PHd9MSvL-&@tTcNDzITnrd&fAG97sPDyP=qtsR0&^ zD44gycz?qd&9z!cm~PiA`wWhdYHPpJ7d z=Kt)Rm3*`4CIc?Cr0f$7-sPoEqB%D0ufB3m7et766=Qd=w)L`#@?gAZ__qFys`y11 zp0;9PuLA+GAbIBI4iT|RRkh740Kn1gX{i?)(7`i3TO8MP@5RvP$4M{tvsARHFCM9A zl!}*}_lsQUE6)y9b@g{NlU5wPtliyoJ&Y3=MN0bIYD$I6(+@v075zts0^9yV6-LX@ zksTi#I>2}RX2OE9J&JGUk7|CM+-H7WqjFeP;eR2hI~@3QtUYJ4Eb;&7`VMF~yS42^ z2tw3|AbPYQdM^_p(M#0Ph3LH#45CMm-UZS7=w0+KYLw`G)KO;){wMEw&-b14o%63{ zS(fE7&)#?4_kG>hwk))@t4}YdLhUu;eEc!Bsz0)1jmRH<#=w-->RXX8_8H2w(m6k_ z^*Y|rp_`3NsID8u{OkQ8>c?}$ya4{!wQBD;m$jN$r$Hec;lacc5BF1ZwuU5p?@buy z;Kpt)cjo5R8L${Bx{l`j(T=rf6-QI`3mQA>mPgQ?@zqs zxGJd8EE@=OEW;aC^!ty-x;~{QsOqTDxF#nqtpyng=c(^W5-M1_clxW~PA+kch&?5$ z9iMV#<=fcW{FWZ7K4Sx|@B`9je~8rUvNmaD=C}u>qhDJuGT7vob!gjfPJG~LX&e@p zFPD7Jol}~Zp9r0t-I&galzeZhrcE&jilUiWY~4;w64rZ1ml7uOV!R7oF8FDvj+wzF zOnP%jng7CJH=wye_wFiwO8vY0qCmsI@!r3tFb|1=K3rI{ttdW2;2V7&wK8f7nDt0g z3Kdvwujcd}SXxsGwPs(Mm_G5Lvf4#nQJ-G#5zfBK@$H z_w1Cz8$O5?=M;}&+HcF`u9@=;egLw>oo4j5^Q^u+_0b?xRwvV|LZYGy>-c&Dq(V8O z^S7#D0JT^(7TEF4Ve7dmqGCCN!7zwnq0HBNenT~U6eAh!w!eKT=1bWzO|Xh^sYpByDT*8n*8nxE`10AIoL<#IL)`P;Dg|%ulfB^@L8YfE9 z7!nw`7~!*>*ySt6(6*C^nwsSwgyYZ1OZqs&TVS&`_9kMf4+u32`YZGs6;pvbBTK7S zgL0m_iMMODU3s*|+gFvBjD)F*H=NM_%-f|OQNQ|P>spOG9dT%R2=kOaMvC?#ZGY|1 z70nxPWcf7Al!oui&>duW;XVs`pZ{ne?tMFv!%~A=b1A~O1R6?taf%aQ#IN)jalfd% z!xIEf`dD!(htZLcWos2@KTl;c(pp$#bpQ+bAoTe}EqEPMFuGK?QG>tSvb7?0E}Acm zNr{p+wY;wBXF5{^b$|M|R@kJ=pxGlfbXT^;rYbp2@1~;2*O|Kwnancr6zE25uU#c!H)Ak_pZ<2AzZVMS4aOO9Hr#Ed?chup}!SwFkzehJ7RA3Kc zoEJ~joopt4)P+v&oGWFCy_1v1jV+@nKK8ajgAuAWw$3c_C?+YAE6x&{lwIc)(SNu3 z_|3*Z%kr6Z+r?+nv1$sCi`6*4n&0M&nbj0B0n_9ND$o<}GB=XQJ@SJ;MeP6m;^f3u z8Ll~EovBdA6c|xde8;IiG%P9z>+}*vm#rY=OG`^LRWriPPv%H^?em@Y-4CK+Y&jFP zR;d+R(MR$F_t2H?<483Vz+>DhG>)MOj?^t`yXvlje)CNq9tWacROehfNmW@X2i8~D!o#vs@DLnf;(a-fAzGR&>)LP$SgPy-iQ1a@gf_PJFxt)~- zV$~ZrI&WC4a{F6=%`LNfSm6?J-LCty}JJS z^)w;}E%{ZWBYEJ0FX~(fv2u_wAX+41)d(4NkBUk0icGTAwQ?BgsWi5ZN%OtSv+?Kr z{tcIII!N#?W=)i3S(7!F^YJIKhTq2vZ)JZ%bDgtXdLgQ6ziCWpsCMJ`o`T1tds8#U zM9(rscN-YZZ`{&^bZ*zB`{eZ%a|tD+qgms6gUt|=8o*ZCA3ex7(z#G*+^ZJJnA@13 z&Z2Q&t^qH3BAik8wuoxm#NZpPBR6pn$SBm{^K^6Hxtj9lm+WSV;#b~tpBfSF%En(M6y`<5@3JkO z#@|Cn_|iSLZr@p4FYraDTDM=;C2iOWc0;>FOYfSNzwvDB4INeIPS{;8*$br98x^Ba z3+^?98Dn?1KjE8w6i^}_jgPG>*L~0KI}8QOVMR&~*P_-d#u&?_HS}5tEYA=NEp2FO zOE?k9LUt3Jo)h#H;5F!)exs(L&>|R2YsAmrN%t_AK=E^;*+PRHiAr~C$y;0kMQ-hs+u9ybZ(RIi!a}zihT-?AEitQ5>|8g{|St3vPN^w zB@5~{=i9pT-by#eBSX<&vkX5;Te+l-*|!}R4F_2i!f>PfIE#$uk04Ie$l!+IMX%4# zuWNla{6!36wX$x0VdbltN5;z2MA$CqF^q|~|B#t*r$HeYdcAXZo zvSRUx*Y>c@_gQh2(@oGvTr?e}(`)Lhgr|#U_xcrQLtEf?qhD|E(`c1JR|fMi*~oNk z$jh%c>rLAq2Ph0vubaj?CmnonHtB1sHmS=(LR$!U&{Idwi-SsZYHwFkCuzK?U-}|@ z0w@g(DS_!t|RTRDze(lF%GjI=fy`L%TN_Og}zsP!ZWMOuDPad%T` z1D>2oeYSsFgs1l$Zt;)`} z-o}%+HIhL;i$ZQY?a0T{uCiMfwo1I~nua+FG8*k>^Zx=VV6-0#DHDSC@s8&QC zbpoCnAFs|yk&}ziZCPF$Xxu`hx zD4X7VKu6)g=bTKwf2x5)e2K=s9hJf+I8mKC*-#!VK1AF<)Xj@p_Q6(p#H%GIGVRHY*B3qCb1I79CrV|JC)>KGNr z6iHmSl9Kv_LK+OF;1#XMDzV+%GxmOsFO__e}rpHvTJEJx55_ON0G%?-nm)G5I z&ek?j)++VJh_0`XqF38WVv1;=TLD4EtEZ;5^*GmWDbD8u19A^a&5)!pUUvfkzH5|I zG{_Yf2~G5o66_XP4R^NmAFZg$#va^xXt;}zob`pjy=*f*Ofj3<);p5GE|nwuH}s5A zHqlNxcE{`Qey}fH{`ecRLobPDVt~#%E?4zE7#R8B*rpuKoRgHJgy2c6lgTaH9Q=0u zD<&b&nyW1F#E(sUgPbliolo+ma~{&sIpg3K?Y%eCYr(Tlq_}+HA<J?aNKG$L%01>>O8VVsG3t97}YkVS9`$T!m) zbz)A*FyetK%zZkT8~y5Qaq(V+rH3DSlN^of?_nMeVRe2JWKFqi0qmxTa~D?tb%DLz z7jfOhzqL@omh=E`nQ|uah-q>+eqK4TToF>|?m~{dPtfh+Gk6#Xx3!(^Q~x#^2kzte zLhbI73PVZen}`h%60pk~MdFpXhQ4(JBj(IZC>sUx`^EiPs-des`aOaR+7abJf_co; zqcN{)pvks)Y#brcFYSo8QQ4E_temckWbswO-;#U7%O?X_%WsQohIzvSSU9c z6a?E$STsdFD`Bqq(6v{0DLb2CYiHG5S0wvuG)srgJ^M`|rMkro|A&ea%RXoMf61v| zqdf?_*E8JxI|5c?ixuFXV{AfL^u|nFG@_)7GGl!wMB1^o5%*!h)lRRl76#EEtG|pk zD_1E?;(8aavj?YrVM)S|&&JS04dy8hb0=MqnT zbP(hDTXj_)2IkTz(A#58%LmjyIS);?+}uNF#v{~V=lnsSZ9>48R#|8MY&5uL={I&) z$YY>dDm_Sj>yV-6*i&yh(S1_wG@Z)-_9@BZ*eVlgNtMXKB-Z(IEdjGL<|4o8Vka^Y zvzquMt$u)%zADiIFMl;!;LU!LVR_(N)|rP=DzwnHB_ig779klCyZvWHAr6g?wr5DI zp52z|ws)3t6eFf`EZ8RE6B5XWrb$?}D41lBz(tGQ3SC*8AJT2+sx=-xg8K{8DT3*Y z>VN0=47UKH!YGt@;0Xj0pzg88}Qs4Pj?lSM3 zrm*as?NZ-vxqxeC(`s+{KOA&E5+ z)%O=T44xuSMReF_I_J67R4_T_wJZ>BOo{Y4`JBWNR9H~%ajFuBcC@vO zVy@{vh595c{IXSFw1iVeB(2Q_@o8>ppYM*ls47^~8BB;%ffE7NiC$E;x-37Ad zCoos5${{}LW9fx*(#vYK&Yv?P3DIHyS`3lNrY7FGDyyY7)H5$xngE9+CB&o{mw)~a z1T^|g?@%4`h%QR3hp&>pghj65Y{-+JLOL46z!2EOnI8;0bI4kVcIBfd3X_f` zG1IUGs0|igVIUfbaM2mmmtR0avs_mnYQqPd$bu~sg}S6WV8<#&g|Ct-+q>h<4U$hj zo7{GJy6$;lDfv$!nbc=b)Tg4J74mJtHw|T66(hZoyG|wD06u_y{GELvLyt|?~o+UFYb*7QIAWfB!{eTQ`Cd3(1J z7oEf)FCJ6B>}kkb@hCEmN%;qPP67dlsh=s!`{m{DyHG+>j<%gNcmc?eV}X_~(`RNj z!lH0{f?K&;tnv1!elWe&Y+Vn^Kstn$?(w4vJ}wzO@EPNptkb3U%(Aj{q_5FFzNm1v zs34O$jla{2J#eKW-TSlX_5LaRXSK4TIEngn6SN^uipuk2Y{WAzy-~4k+|#eR0NA=9 z-3cub<4T3f3uQ?k>V306xfv<2^fd?vKOr?$2OOk2T(f{)Z;S2yD0=#(>W+@Dl}4F0 z#r*xB$1P%Vc!BFlL149$6EB^Dnt98n>S@Kw2*2EaTlpmTA&K*T zcA}+~MxBrREPK4GtrAJ#ZF8T-z5=N_mP;LqVT-3Bvr?-liVRDuuEOxYKFGJ;IRt zd5^+lWu#JRnfZ-c2b;_U9sNu*+h_!MgV2Xe>B z&?;cXgSiD)m7A$k61&nDj&osJzl9uka;pu7P(#>w%t!q=EyD2LNEa%h+d-P zt36JJsvo~OF|26*3D&jR^0~}l3OD?u0r5P)Bmbrj1E@A90o+D?n$uGb2sX@SG=6?w zI8M3jEh+n_L9CRQPrT2k;yBMC8H6A1PR4xGV97k@75vuDhwXQ5PD5pP@u1sXd)vJs z{6DCBHRtJOH`BKnglg%1Q-yLt^}avkFC*{jW$?P69A{#Ubpq5%mj3AvnCQQEt$r+J zCWToYvNn&AWx4RH`CCp1i=A@{9=?~5p3JzR4xzYTBjT!3!uy!#g4{g+0IyFtcDZ36 zi>Fo$KQm3kdr~Ee1zsY)%w`UOsesEhU$jQTsOU#=J6CaKXFJnf=z$G)X>M|wk_ ze)~i-_N?O+mh{}NyM-q4K;=YEERVy>zE*o(tzfhLZi`fKo7U_=PBGUSoay_%VQy;n{fGx$e1vS^#~g-NAbflf>!9&0=cPh~K7zOS{2%1@P9Jh9{c6tkD-f~BV( z^B5sDCrdX!a=sI!$wve*)E=wjEKkP1D|k|}xt3o`^6sAa<|4*Bnwd>>^;|M~&ronD$BAC-olX2l#O7o11Av1Kml=V~hfOEv` zvBK_TPYFFuYbL_sQy#3{jH0d!dgE2$OUsl|+rA%WjkDG#eGY~kx<_@?z#mmnx)k}9 zL}g6rHVdQ8Q=rxB1PB*6n#bkS_v&PQubdFyOvm8Hk!Rb;p|k?VAFnvQfA(J#C;$7v z#zPK&&A9Z=q3n?a0nHymV}*L_Mwq?aSc!hx>Uy8~SZQAwH`VB9)xMrO3pANnvyRPa z5iRm>*y*IO6wBvD>Km}Ugj2+--QV8ak{_rcN)dMrR`2@3r5Q&0rqp?}lRTXv*-qT+ zC}rZa_uEcU?RLtibp9Va=7Pd$(j_Tx3W@2~aRCcJSDU6!Mq5^?nw}~b@ttz|iP@@5;-4G3`G7#%(*V4#xgop+=jZ3!A#WKJpb5vUR?`cx2+! zcpYI`jXRT0zT{&cR%+P(QyioIMNDFcT&Y0eSRW*0m@`M?9!MuJwQ563PK9=F-cXD# zgsR?rFm}{;vFV#!dGpqLXzvQgt#=g5>$1_qmRrwtur$4kt@ybcWFCPz)COKw#Yn3+ zL=J=T-EJewgw$Jns59%vT6Q>3mCIM&ww(ZHs2vBwy-{zlK&qb|l@~ zW_0dd)ZF^sE%zzj;EOG-z1M%w0Sx1?mq<6<2^ixGKSN8+IU)w_`T+SB+No$CJuCVzXa%_ORtVS~(p4Gh1y& zxp~Eihh1-$W!e;D>4%R76Bl`PV_O>JE}qZ>xDU3GF}lvs^lVu2D5pJ2&Z|!`nAex8 z5yto4{8ST1eD6bDE*%_|ydw8|ymZich$baV_E;x>sy)riS zRjRKLUb~XS1Fb6Ah>!#;XRsTT8Wt(BtAo`z)~LW-#jbg6XII{p*@4rhLrATUwteX#pvIO*#Oj?i-|80XD%(!IwyEit?w$h|a7 zYU7`F>R_(To2LzZZ?ge~QXLyboldK3QE;h+#NE&=dJDgzka74@V#vx+L+sZ%7oF@ zdby+qfVr{;?6(`?eOmqW4&_j9L{iSu@PXx4k>>-48kcDf2wVGImtkbG=Q)S(*L1UT zYp28dWzi}3YVGyv;^N-WND6+tuRfd_1_hxdB!$5Mz7K=W3Mz{HrRGNR5d^lPa_UE0 zUy<(7t(Bt$uIsAK)RA_*cSg2XXl((xp0FR7Zb#ZWl_|6D^wZ-LyYlDFB&R}t5|252 z^8D&>v@cq_)AovV|4B1|C;=cA4U@kmlVFp&WUgPTAChdkVF~7I8Vb8=^bGUkd(lrRasSRbXFl7DaU`|MM=oTDPal?~xwiu$F-4(rPy0jjZsTDgThi4Q5G8HbmX0SO%`O-QoLQ_t+LnPWtF=#JLUnH3CevO0KXzOO2`SH^Qh` z%}vQU<0AaDD5$JX;|B6!uM~4aY%J8ySu`liY%=Dssf-@=uP69%Ei4q0ame9yyA}*2 z@)t6t$Vc$NZ8Tj-q+4=m0)VA}YN^!BS$}rdwfcx9B9+@y<{g1CM<^oXz5=EX9wr+ANY?xvI+Z1yt!{kye%i0hQQ_ zeD}2ZKF?O$dN`gLvkx7ubGSShp14kb2= zl`PtRkGz)=qi^4hmvrmIS`8FV9@xTUYoBSbj%JX-;Z7sui5zWL#XBGpe%Hq%CQ;g0 zAGlhdkvwD)*>OR{DG4jtH6ie{p=KFjOYXON^k(yx>ADNK2nVo3aZmx}RF2y0SWSS= zHg`-%Ib)1czuXM=jkHPYrZ+2DQgtp`{^SD>KpE|u)_2#`3!T5XzBHPj2^f8uHG9;SemdRD)e5l|$`s7G7eycdU(vcP=`f(HPP=TAbcb{Ae|2;<$vgely>#7ygw>G}t7JQCQ%u;U@ z+r7B8rMyJkAm*vhdd*yW<6jj@GLl?W+-3Dec$8SHm6+PFqp#P3>E225TYfdIpA6pT zwc6EbY^@dF-Lol}woO|H=!{%!Cw|2){u|D|;~p?D%ri2AE5I*vaH05>CvPg$_8~@}Fp0zdCQ<+18x z28Oql@O1k`98SWkT+IdqMv&R3b|vdObTwEs=+L4O2L>rlI-i5OC+#LD`gT38pVMym z2V(9QHu~qQpU1`R-Va6*-taTYqwgd=UOD8^%coBhsRflF=k=#6%q4PzE3TqnxKOXy z#t4FI^MP{QnUp^G;lH&cVqTk}J>lW0v}9Y3kli<+e?bm41nXc$Sef@AyZRL&c{*<I~uAMQ4uG-8H5RkBI&IKjAYAhw&k+KT)hey9k6_-E1JO{MvIf&c{1zGNSem3bUB^^q-|_pyIa{;RNTs*MahziQb@V%HC3{|gcL z3oej?U86L7q(^Sv=5kGL-nVc~X{$jx#oMI#yM8@gS0-qnX7@s)@L(b}rQaMw5II22 zWq@*6f!hAwR;_o<*ym|gU`!;D;hGUEDYQ)lGU5~C;v`JE{CS{Kt&LaG3Ae(EA?Tbk z9*3O_#)qxv-Gezqy?mKKB$({@VZfh&ja`@Xv5&lDhPR3?jsF_gI}0^)knlNA;5qN~ zoJvn!*+gh9H>|$2=ZVWu(|EbDR{bOL>CtDZ(J*y;SD8GtlG9}8NY|O{@%t6aFb8L1@-ZuoP@5m_K-d>AEYUPc=8|G- z?i{llCd2;zZ{Jl7)iBIKJp>H7y+tZmlLK13onD_Lig>kVlU)bTqO?bYjm;=Rq)#7W z6^Su?+)JoicscRh{Y%Jb%cu{#mZVkssdK&$tNFrTD}UQ(#X0z7|LlUFFGJ^}u;d2%31M?!R`eJn&*hhg0{^Aayvr{Ip=jVv zc!?=>>(~0M&~L`jDH{WO(L(e0ij4nXItu^$iU6wxlbteHEUMRwbf`%BfMXIz z@@p1x67!71S?79PdD+fM!)m7}UI7RkKp5ofQM825vmU}r7T{`z z_2VN>;0R}asKAdsC)SxUn}`lM9uC7Cu6ka+y?8jgs#cYv6Ha&!HQQG+1x5Svc_r&% zr6p2EfLh?cPA~w&{>)}>yHt`f!|XBjNo5JP8eOK#RrkrX_X(qySsfKv+$Fk)f0hj~ z(P}9y8YD?^X|ysQCOktQK4~6_cNd>$K6kb93}e|lPW}znkF?yJJ_fpFFZ7!jhX32- z)*m;E{@YmKKYQaJ8G(S$lcq#jWNQ^`3bPt%$K!#(i)D!d z184vv^4FL2gT?NXABwX6d+-7vvTkVJ)CUGQ4(=Qx&VQzLUoXFiv2^HvvMf;Xxt8uf z_V8IDI(KW9*%#`<=fYn4HUC56kc95S8Cp;(t2+yx=BNltVEoS~1<{!e+zt&UxPjrn zs&?Q zH954^|D+mujZf%+Z6FcX$?{S7G7h_8@)ZD%JXl+m05;)Pp@YRBzZq}a(b~u{;uQ;- zYC&Pa^DXKBP!oR%1sdJ=)wwQ|l+@j!aY;&CJYkAzI!D=zTM0LxF{5CS` zwtn#+>)g>s+g)Or>^a}p#x%18XbiS|HZ=fe{Q_%eCFZ62{DWYgr6_vA|M*k@GO37` zvIOGkxir&9n#{S}o1#7 zvjI3ua5`Y`bga~LyBJvJOVF!*GB@~d)7XA-uk+m%%*nSQ=940)c)dOVr^`wCX{xMI z43UNMxI#$a13BTB5%mALOcpe6;2j#2+7-2Zv~ytV+mMb?8GR)DYKI>Pgh zB12yLJ&*@A$d=OmUqz1T$Yy$NzZKAiP4G{v_*dx2KYl*L2a>hxJ|AQD|5Nq;-@d)k zIB|Be&`#RD`~Ug)-@kc%N5i=?J3KtZu}|&(x%NL*;D7v%MN)?!DNjks-~vWR!2ez0 zzr>E4fIokC-Dhj`=f&Lk{5?e5N=iCT{~n+3P-0qfYIH*i32hy^Y>3kSwf5K4G?lEq zi{cJ*t*RJbQd&PJ1OcajGgmb4*gcqg==ncH_KOTXef@)d+ee`>C{KC#_TR7O-}a8i zm2H2-vA#mzOL;cL*i4z&)Dw6^pVZfT_a+KhhX()7FFKT77)8g5A)HK;8i_dq3jTHp z{t$@{Dta%c#RF2(r3VRl$#V|~w9x_gaYti>|8#Dq4!R3vPul%^UyZZ~`Y%iesP3v2 zvkrCkxhE*)NoVKIb_b3AN%e9@f|fxh>599rfNXP$Y_6ty!sE{1lbHs%i2_24BZi_@ z6OppdqJ)2o{fygRVO>9;w6MHQ&r~?tz`(2T69TUN&r!X7UbK|n=1eMQ_j!!-D&od# zun(B>kKyb%0;WXt$CUb5JJJ4Dg6wD_3wzQ1eZdqKAFu75TrimZZzBW#{2($UrFWdF zqWd0mOkzr_2XU)Gg+eB;#G+k2P<@oxqagP>v0($;84abs%Y!#{j=O^<|6COA6SSfk zT4C}0-t+ESV5_jdum${O8QJZ`4pCJXzjh)fVX(5QhIXiY8K`Giolfiuk+v+T+Z##2 z3e-%wZ7fny$AgAvM!UP=!gnndL(nny#K<)M0_6@c(X$QoeTlB#801`(@^7=WSA5i< zf9gy5ix}kBjnZ&u8|b8EdaHebBB?pGvt7pK+{vimcAJmrZ~g_BT{!nY>(Oo`{!=GB zwNw{ZTYnK86nS0=i2(cGW@3$vNOx@OK9CgwH7N#?4;qo}wmTjwDIODO^$} z;C;SpWv8?h-RL}6gghi>*gPpfaEl34M=cJzNYc2Vo@c4P+wWTMW5J|)QE<>sgK$bf z(j_3ZL&VJiVUZu9O0VxAonc{H1uJq^5=R%i@Je#$% zOYvML@50Kn8jX8is^y=*b}jKR1A^$zL;o34Hdv2NmaG;9?PLqfGg`a~^mom?1!|qD zAO`-e$d@O^J*a!DPh3cn+g!g=FGSa2Jobh>LA%Dk$jT=>8#(C`Eowzdzm=b4F5Ayz0e#I06zWE8gd9GJ3^=4R2HlYOt@^u2at272GH@+krt7T@kyVN`n`n*V z1YuXmfIsFT$7F$`VsC|Zv(l7tyg&Lw9)HdIld_%2+6nLNs$30+&Y?uSTdM;jZEHrn z`4d^bI7B2tDMz9k4Ir3nq1Dr_+peeOHNKS#7}v@j<4Vw@Nb0TcTJ{Nq%Hm z?S4NWixu>)7#hMrMEcsw(d|)GPOlGDhxfPZHP~NgbRIa$E78!5dQeL#KO}l)gFfFT zT5I5w=HZQ9*M?~##l!LY>f<{B>tp3MZ|j_Aw+xfIjXEG65W;f315}sQ?QASYd}ZBg z14n$g>%8URS~~lE()CqBr*CNK7mr$>VxJKecKQ#tsP@`*0p4*+-C*q)e-%_T)o1=0n(7q%8A1Z*QQGs9eKrnN}!IGwf zuXIJ%H-5IP?Dzg~B42HFKF@!G0^-YfBEWj1VJ}gm?L9|6eJ)8yTQ_qjORGk#yL|uL z@7y0T5Pi@GQ5o*)-tHqX0$z0zm-faAHGaaz=W_mbFrtbjs3GI z-VPPH9zt;4paBAGhs5X?WcajWn`sVIdDn4?N37HCTY0yCy)LcQ_bYzYbsXY?KhL@y z1o$P~PiV-`d3O^Sulwg*nU;W5PCahLSzwmQ#P&?A}F;x?BXm_?>6r9$7f`9 zo0x!JTs+9p?LGly{6XOH?|F&KIp4$i+sQW4)*8NC%hYYq9Ik^x5N4c`VH>d*at=bM zIP1&lyA~Wv{SU8@FJg2zXV@EUKyHWmw(1Fw*D60p2sC4;-79Qrdb*xPe->)Wi$C-1@#ne*++gGic}%SaeBK2x2-- zPk)^@VN#XsU5AqQwuH6XhYS4n_DXYxKLE)1+L%p0Z4Fx|1oc;0Lnd75-#}AJuT0u# ztyImmqZFd_w=fyuCf9%LJm98)&+IJjq$?5EH4heP6q$KpltS?0TuN5nZJ$1tl?##_ z|MKHrxMdEzy!ff7J2WTS1F{YB2brq8Zl%34xDMYl_Z8HD$ zDACGk?lSN;FOUx|vTmGFmBKu?2XsIz)kp8M0m9n@f4_5#juwFrTCJt?9Pg169|IMv zrQ3Pvz`Mj@U$at{-$($G^M=%9y&miQvnNrcH?}C5D98CIFVIPzau$n(JQDq4C(RCJ3JIq~Si+31f0_sVLu51H$=N=9(Q@41G}*z3ze*RJg;+H@ zF-F;wNh5)L`Rmhz$Zw>5XO*stNaK&bLNaYWTp(ampZWNYMZ4wZcNyJ%i}b%SzoP(g zzZ%G~ZN_|nR3OPvpm?96N=-q`hW#$r#Vin8#@a0dN}v2kU9M0&&;H2L+?N`}IbPeA zq|-%pXQm94AudXjzXIu;AK|!bgTlDK%5uS3r0gvJq*4CY^&ok};{Ek2qf&fDaqlqW zTXa^N{^);r?Tf51@%Md+5J8BA^wNSvpCYBz!O5gJH8Q$ETa=j4ED?Re($xjU*Ewho zk@*M#l&Ok3qIm!kf{?&Mn`hK zOAp^ZE;!5WS|%b(xUP5I4$CF%mfq9gg#vEVR^L03OhnnmTZm@3(cijl?n?={?#P8# zgaB11gUz2>0VfUCN|KL>%ty92`}MiqX~eHoe6O@(M=gLxli~AmYpZnG9@IubF7tx& zT3989eu?|aUuI%{M-EB{&1x$wbr7+|T1$=lG+J zK=uLn_1GPeIbU*u8!r@RH1C~DEPxGt_1T0U@Fn-(bhK!tXt+B_TxlA$nx}+M>St)$ zwXs^@eo`=r2uuFRy@mNKjSx}Gk6Xf0b@R(M;2(;0V~HB4t#JR$r}UyvgJ+y^H1GOT zhmCGuTsLRhxI~H}A|@+$B>ACnJ%!iMg^4fq>S+M~w-H+G&%oo+;#0maihn51{t*PZ zz!q?#cyEUJ6dxb6azGAL!)n~b)7#?7RjzK&Y- zxi>^X%gmi@ALQ2++<6Nfi=b{5Uc&qQgT)N*bK0;xaFFYl%63)FxMAoseNM0L##gAuj}SA=4AIvCv*Jwu*etv+9CSoZwmrp6+KfP>OQg8K>d z=b#&m1#gayCjF+KS#%rMR%oDUtWe>}r#wE+KZbeyS4QDX6G3e&T|eVk-giO7B!gR! z$d^y%7{~SOV^y?E8Gq|2R2Sog8ij^Bh{5E4KAiLDrCYnj<+puMLZD&~*fC9cAX%Rm z^6N5Wp`75@jX}+KkU0G9wVJE87N8j!GOt5iO?Lc)T&5cR2pL`9Q$|?#lKPWvtgX4N zgK?$Hx)aka4RUz#OsM}>v@_CIe`UI-S3eilE82MW+Pi-huNS<}95%o4%fcZBF{knh z*BPTCi{hN)G@+@n3wfpxBhF=+CwPA^?3+C|`Ek;XIfx82{CGX<716U}W3$!IM=qiH z@E(wRa_}E^%7={ibH#qy%Z9n<%?RG8X1`%9r?liXXr}=iJ}K1-ov9J*2E@c9e^tA| z{y&k$9P|vNK;oJVE6ZjYr$#%Fm`X1=mo)C?y9wgUWDFec-XmcIT)&}poJ5?(O~-{v zTNNDf^XP2rTJReGRFdFYxkPN|-b6?rK2O_;asf8LOk5Dl1;n?G*Rm_X0~|kPh}gpp zq&<%jjxKClUd_(Wjqd^sfLP(FgjBk-yfj&K3j%DsT*U<7nFMV7o@9zxDjCL0NA0W4 zQLH5472V~is$A@o&K8vq)^Nb#GtA>ID8r!Le|#KLmi`QSr{F?xV}j!B(#h#Usp zTQ5vG@FRYa7SbBxW-{Vd*-WhX?arlC(FVv7h#=p7LG}xHCH`19zDq)xp>(bO3#8%& zUu`BY-OR3=VmE3Kk#>Qw#rcvY zEMe49kurz<^iQFiGa0+#gnyqvMbG1#Dh}b}nU37{n-_G$;ZTH0R2qm3K9<$ijM}g^ zPd$oJZoSJ~yxK6)$_A#28T|La_?pV6GwXOJ3mXuvet3>#X!gu@5)aJ zdOnww8O6Sw02hF-%3c};!}BnspZl4O5YtIY$Y0qV@`+2?9gsL}7x0WJ8wXCBO^S4K zZPW_+_bzm?*6p43;TnYrl0JOlT9d?;HvlrP|K_w5+dLFe)ni*d&G&Yrb5^te0f#S3 zY+_)X$_57u?i;B{c~^bsq|vNY(9UIlSG(x@r8}oI)c%D)b-8cUGHatm`xIXw=TqJD z=HrGrr+JCy0TO{Wx~#Gy3umz{$yC_UE6|p-7wp|NJ?KvyZYnN6TMpPm%vDL7D==a0 z)SLXHqvIbKW7&G8JqkIy$>tL@$Q$;rleVSh)rUaq7}?->DSW!#2B_dErQ0B{QU9xg z@CKN=`?gTEPiXpujn{*@rb{)eVQ4x-mSqlu27~ABNz|wA6*sZe2yOio zw|f~!?Y|%owXbD&M-f%d=oTq+LIw(oe_91tI~2iu4trjS=jB0Tj5Cf^B2vHl=7B-U zaT-g>LTxyjP)=fMg)b^LgKS|2h3FJbX3|UNJ+lK}!a|Go+-YZhKac zmFHB~HUfnkA_X$ys#*xPn}eK%$sT~NP;<5)x5Yv8As1#cq7S3m$hg98>(5)EN9yJSW9ImMN%CWt?*^0d)8~kX-1?)jV7~0S z%1MIlv+Iepo{*omUfcDjCY#FItwlO@>iqjEcZ<)dd&TVMk!fFcEnS%$ZwFHuwV{nV zZ$4nSSxm82XACzPhz^*qX(^xQxGmr+I51*H zl6Ta8g#x|}JM+BGqHg66E+@`5HJhFLLs?8l?P8)eM@mk5hbia`K|byL8g9_)S>4tMp&nqO~+9jNZ&ifyAG0}cfAwfbo;(< z097=(arfK1HQjaRjgVDEBS1FGF#;xb-YrgWT33r6NdDHfvCxWiM!a2R|f zNP2+YzMW;P<+`qDJ#W}|q!3yZe3MOfTe1lH8l`s z>Vf2UzZ`K3zKa9J6qYum&FP`+>z~05x9|twab@ebj=lSKDUj7bi>`nOeqer?@;lAT zW47&f<0n*X404!NfQ9o70Tpiz5udc3i<@spcZ5-I~I9ON5r5r1()whcVanon-f$UDP zQmCFdUDWxuDK+~U@pOpTs3>2{Q$4i7`ay#{UCJ0sB>9P#m9&)AyR_Hr;9&VmZ zT=rkioa6#JZnv5h?+FYZB_C!if`OemNK$w1E+jeFUgHZvP{edl{NGjIBe07RK0isO22+$N)a@W}(Nf@2qQZ6ms+a`TKB|Fq4WtO;-)QaeMy zrL*&9Z%9L1mnlFpbs4nyiDev;VweY_;QEy2tIoztXXYi7qc!_iF-S9o#qzRn1U^%f z6G7VADu!NrS!QqdUZ0qjVq7-&B_c22q>mtFDBHFMPjj=gKOuRGat?yy+8GNT38{PE zwO*(he|obv%4MyzSG(ENnc%pfrT@lHM2hFH$LgCw_~!S&rY{qh*a|*=w5q{NQQuA) z;q_E6u4eNeh$;Ezh;ZA&@BHk)1vUk$+9XhO9k4Y+D)Iu^mA^Uka8<*?`V*5!`sGLS zXu1JDya|p&7umthe!W2`93xfB@G%OYdO`-DuH3qRb?-%~y;()c~MW>Z6(C^Scd41GS5*7@btUZ?(FaBnq@ss2ECw#9%j|x z;E^f#4!VmAGWYEtenM^qU!K2ZM1s3~JRq)4+e*@1BKUlf-Uq*?;8;|FWsD9EXA^CM2JMF5d?8FD<+cq8Qwe>Vns4{`d&--y$d0e$z%Z zI$ToMl>>fCEzzErO~|nIgqat8dL58?6=Fgsepb)jJ-b>%0fx_xgqZkcrmy@;(6IgS z6L`0-?lF04q2E=cvEA7r=Pk|i&I|dV?XVEWi@$dVN40E@@;&46b72OTte8}7J=yV_ zJ=vjcx?YD)Vcwyq-T)=$4b{-YXU(b42sHDht)?^JhRoIZIgimhelVPHk5 zE4BXz4}iRG72@Nhv{|{pk-AfUNZcdfPptB9_Z9$RH*C=@>Ep-$PJmu(Xc%nPS?PJaxnGQ`0x;Ducxk|&yB zcjR*DXULql&$Fo_iF4h@b+1jsxvN6(T;jW*v2oViE>*zKzLbpi()*9N)_i-zkS5Tc z=`mIQGNUK3p>m;7d>EY|51m2+I$-?B+7=w4#Gdkj-6?TRU3Jb#y7PVDSjuDOcj~kp zGXgtG$s0`1(s^20x@&JGn9|5Xm{zG?KaEh*%; zX(s0oHLqT-uVoRpDyw17Wrv6q;>6FU4taW}nPdw*yk?#}I&gY1?f6JEx<@h6oBe2K zPnpjbDTcmASq?>d52LM80lTo3PYKAQ)N;V4n z8w=5v7|OCzHnci1qXINcy3KWkp#0hsm3=Mt0O;~&XU#(KqOYMdtdYCHd zW*Rlcby`t(h>|+GOKNf3bLPtEBSW>fXn*$vR-1kVknGQnniFp0wd~q1TwYfCI`UsY zGpLnXEa>(&acIJgB`+5whPDGKE_j<1qj^hh_OWo!Fl51=fcvkt^3_jHJQIBb?<4*-Seu>XN+CXY z-WHsUUgiH{hpLle$!IcFl>rYbAH((}YzLXO%~oLZ9ks9xYHad`?qDIEAHlQ}W?QyW ziB7*8B+tfNwNMJV^AY)tumMxZVkic@iq(y7i4(ceO@n9}U?LzQY$tDiFme1Cn3)Iq z6&G^5z`gxY?7RF=`qdW-CJ*E2Vn52Ly!f=LEBp4b_oyi7*72ZwXOE%Wz z-k{sj$(11Mn^4>}UTm713Es8|!*|MvHI1{Wn~PfK7-z)6K976Y$n+NvX?&5YmhaFS zRZu+NLxlSl#Srp*o zZs9MUZg~>CuXemufInv=J|)5VlwI73zeufVU18;E zeZWkvV2kv{u@lXigs>&EKL4r1U-*B_pB!lZth!;qLQ&XlG`HM|jskO68j~E^5_{IP zm$G^bBpE~DkTcW2>p-^cxM9V4VxioG)+H%B!(WBWbIp$iN~K%9P6=sX#~nP@vA5e$ke8%b9uA3crcIBMbM=x6(rWB z*YD9VV{O-iO}^L?71!@DM*NI=^koJ-TmeER>-uuq&j0n9Wlc@0CKC}D7HcpI*cL70&%w(S7d*;p~b zABn%ugnxTt^{p7Tk=O>MLu@+k#4~d@T*Xdp??k7Ab5}NY5KP{Pom*A-d0zCdt7^UH zr=w$fYG?fS2s29ib0myME5v>Axrk7Ttr}cTBUC*R;go+Nk{oVJ|7(_8PwC?Ai#ig;lC8`o|9=msJC)}W3L$S@~; zFqOzbsb%eKx4ZF*wQ;RQ8Y45oGNbavAiaWuI9Ux*Y6m|<+OqV-DJH7}s1r5asFN3l zJT4!LQ@r)TR9@U*4CY;WSAcl!Zs3TPLvHLfalOCE9GW;Iy4AIK+Ny+ZgMCHr_%}^` zm+Hk689#1YO6Vz!COexm@i&QVu$mP_rVZnGrjNp+h*Bzm;_BV}2a*}L#|F%gDwJP0 zb917@<*(Au5~(r9NRos7(Hvnu&#hv7Cw(Yg)LN$^pPc;L)QY%tJqUn&!X@u6f!&}@ zStU~X?3Cy3lcNY9#{h#E(YPTeQBO4GoV!a)MYXIHZ2D8v=j#`>lW{Fetls;23onCP zCQL#IqMOYP{XPAplN5{Sr&Zpf3_ckKgGmj$8y2BEC(om+(83P9C9c33T`}|xijoUK zvS+$NLV#_OK~CV1J9v)?>JQKPln(}H$!$Cofwt1e3RNq0x&vX`jS9cI?H7T{Q6bRax&Q zCS5#^^mj&nsTu3kaq3xr@GP8Tkgmy%r(ukW))g`v{1W?+ln&;t7b(A6u#~uyHofcy z{Wss<^PzyZS#h?F&8;A?0M14N;4JpatPGo+gI}G~^n~csRZ{r+p<+VTZvm}RplrO0 z43#9{8*inMnHVMQ9~%)4{2iP#bK|UY&$stgDWbxbs3%|E3D^RPNzaj|xqscqMs%oO z{MgG23P>CK)s{>wf7u)R8{047L(^!W&9BzY9+JCPFs@f|+(FM0ck)iJ!q@0NwgzQ^l<@BOUO%K$46*ordB2rIh268o5vZF#RsE3Hjvj0 zs~OovBqVxw(Lm;h7eproQG~r#PGX#|SNCV5-OpbDHY|)whmGpUz5K@h46yL>xoL_X z^d*1Z(=TU)MF9_t!xRJe-CTB~Q8=Fwrb`)n5v_F^Gq-RvRfR7lOhwT2zQ^lUg$kI=LM(s5yZ3HHA_M!T9(JU-_?rQm?fz*SDqTc3DPwj0})I0_|jb7E}3cT8#|&1;DuJ~&6er&!eh<-= z5&q^ha+6GnY&5zv4MZC+sB3cUC}nYqFF>UcSA*$C6{@$5N|XV#obpdt_>!^<{ys#g zwf~#$pDkK+4j{5vRZ`Ie^Bbi~`nLqBj$|!FWNM2Ye>p4HA!E+k{^|YwRhxy2ikQaqtalrtK~Y zn``Yc{Lgl;SBN(UZ6I^!8&?sN-3QixsU6TfSd1=^^9gB~-WTUBTU7u(vHVrjwLme@ zO3Rg8Bwvlyy?T4P$$I#Ci8%en`KQ#OZPVzbG5d0F!4MGrd4#yfW=cw=J=u_nF3Qed z^weH#ZpX1i`Kw|rHs4d1!s5tAQAf(eyyZ*fl*sy1z!1Qe?AKb1S0V4^A$dVK5|0Lg z*t0Jh zA{7ym8CXl7JSTu3{(^>oul$M)f!ffpdHkOIo#~Yv2>UT1K)g5~fcuJ!G#FJsm|N8u zPbs9+9de!*ye$&n213~(4*hID=y*3H;l{o!6`f>zLErP;B#&c}y!0rV%zswd zW%4RXG~)il%Wd1b{}|~R=J{~F?xw9xzsdtZ(yVM*i|JXb*w>qy&#)2#Zm_5W@$zGB zB+U06nk~ucUP6h#KwjHk1K8+syk^KMQ7Xtmdzri?xlekz-N0u7}`B?X>@SWwrpCH1qR78O}2%I&YO8 zh*lowl{hK?c*{rUd z1JzlUqWdz9$D7nzpY3mTK4C?M`Ssjzpp?$Etc|MV2=0 zDm^;44`nu?T*04bQ@#ALCM)S96}@sqD6AK;?jnRrY8Lf4r_Ry7HZf&{qaBZ0@_G$2^a1V1LKcY1^CVLygUO&Mx97Rg4=k_+4fci&a%LQBOq z;(?HbBuw*jUlqCSvd@jsMCUY6H~KBczEi~KG}2P{4Pl+(C2uW1&ExQ2-7qA;KeiD z1B-%!&m;npDh-FSzI4H!_&zj{{i*WfyaCH)JnvJ&rjzo66a^)kYohN@N+7b4q@4o4 z{34tcYhGIU|QiE7^@EnN7E4`s?}g)qp{#dGIDpAOjOsU@6M|(eU)e z!Dhe}QoA@2_^^T~QSFiO`waVo?+h~r2RTP@~ByrXbTg)RIDDrCxNa~=(tuyFp- zzn%VIt;7qD1o+ZC0Jz#Yn5XQEnx+wSWy&uWvmyDKW(8Z?(KxG^q_4anE zM2<`3OuN|u^6D7TF-8We&9*pz#{;3}(Wig-n^IpOm1q?c2wvq!-`(W7{N<&=D%x&z z-L8o!OS?NHjM_I`q~o|jKCz@HA>(jo zu*&G);~PJMzfZV^MbPs+ym;WF(+P4HX>IZx{j?9EFmTE1y$H!6DlvtE z+?zXj>nEvMMiGcKO(Kn+BhiD+7$F@CDt(R~^gf}sH>ZgvYlRz&8vh+ISO2j74;;N| z>N--ylnBP?K2wIX#;X*|nJ5VE4upVUuC^V%h)cP7!9Zz^?Lr5njvar=ETn(?GrzLv z^me*x0-|k8^fBgb;?fYu;(d_AF6L_eX&guX|$Rabw@G>C=K% z9~Zr1N4V|r>erfmN1ihY4YQQw&gO1z&E!cKSGOWxilBaJQckIV_rpA7Kf+ei$=TDk z@Cs8X%LqmoJw@`40i;D(`ZK3M-i{jS57ri`|dE__1M~^c^PZ-(` zssr3zauHquKSNL+17NPSI?Evief>7E+hr>4c)I|QW0vH?t<-*p{-5in^BtLKmv8V8$;KJzndFy*Ox%2h=cgquYO;Z4_aJg zjQ9CL+fyyIdb)PU^ZN1UYK+U<)RmDnwM9P(eS`Qn_(S=${kFuCcON~4H z*d~c3H$Jh0nU|>I0ezbH;UsyNf3^6P*LTiN4pBR>mNEJ2OXS}@I0(AYGlKzu21eDU zdQx`th^hwap7%X7(0F;ygaD$YtFG%hvGeth)ND$c;`%s zm>Q`68Y4xKN3u+oMil4Z*8zpP-_~v)tYc+_w3V-l?HsB?zD*Sr3Z-Th$j7HvvU}2~ig~O=$b5Ru8K@fhl(Kxp_$tS- zP;|Vt1EJgU@zJYD)7yQpm-cQGwA*AHh!)d+zjB>o`q9fvAQenHniza7-nKbi!+I2g zy4$+W7#ijZMo{iyUSZ*`nsuBT?LprGo&tln3H{8+72#j9f;k2T20R2_Wp@Q!Xbf;1 z1YH?}lEEgy+Ah~?szo4lFvSYdo|^fn^C7SehTcqHI{tdK5@0Ha6-9|U>447}o>?Q{ ziB`X&*UAsaAdob)1gw#j7kvp9-K-lzGl9@UUA%Ual8DQe?iWPEffO{MW|Q2>Gt3&x zKV5A!9*k7KT#G8qsGT1nVe0n&@z>p7Xr4~A#J9n|1Bn=^ZzHTwINVeqF%=vyuGe_| zXUw&c+qbnImSgSQj5KPI+1ORqrwS5A#}_fsSw|mnyZh<+D;H(Jg+>7~Yp+u?f*ts& zHDi^Fia8n4&*z+(fin(v^Bf1wtMbnZ%gQ?HKK636rb%b# z4~U};oUlz|27%RgQBUW2(SqwhXmBJ{9G&d0guX&rZWhrc4@adTV&C}};VWYT{AA;^?5~n#WnF8X zK3(ZR(*Yy<+*W_0JoXq&zaI3U>5UhzFOiS@w>RkbYDBm@9~ zqJoKDwd%vO3_)B(KxFiE^?UMeuit;IPgg_B#|oKropRl`ZLMr)RS=^jrpcH@Qi!rp z)@*}PO?S6cFsuQ<+6D4`_%1BOaO)>YP`1nDDSa+J$Jur&ua?zxmHHTtyMpWnra}oK z_alytttfEb2hrfqL&AKW0~h3RnJTdD$La}f!%Lm@&o77YbZJVSxEI0BALAwF4fLKR zo&ZgPeGwnrzkc3`O0qza)8Df`dN+=w9A9J|uSJjfbd9NL+f9}(e)^R(x$wv8+hYOV zwS1fxf=2h(eMIItDO52p$j}QdI{zgS7c-QA;kl5bJL7&i$h+LFboza<89Eaq%5}>Z zgI&vDV)CLe*$^kghw?N8vGwj7#ga)MCXPs!>ZTi+pMZA$UE#6hYJC^4ju#c z^Xxw}3RZj{u7^ID*Lezj@JBf+_~|!QZ0(PBRF%))KjeGA*h(?=b`?{zT#yqKb~l9g z;;bMV42Z>)ZiFYe6>vRihsSF(_9s*)qL@-!My94ZnLl6wyKR3sOhanY*FS#^=E+)V zwhKcRe06J!IRQS90#4%enp6K*%7wO*;R(BE7bnj04;;UC#t306f`i^phyzLSdp~9~ zA?iC}+e>;?t;%E zp=#8#W-qkFaOCKyBIjLfw%_H>CNNQqGfE|!_6oV7+J2XlL~$4k385W*Q587WN1iQK zQvD3xf32pfxPGwL%*1D53<-fk^mmMCjrPa|ix}pw?4P#u+RCwr z@@=$=L$@}Ls$(8#rIrfohL}mtaG4vp9TwYda@{dzhf73>5$jU>y2Zzo2z~QKrjn$} z{NH6aA`;v>#jz$hs8t}mMTTz~W#HvD%Yd$kcrdTh?O-G!)-|N6KXjIOi3bH$#yxm` zU#$$M4SDWbKY8{izScJErA^ZPRWmh~UTX=|+WxQKPDHY^uxR%@ReKxU`l+maqi9TN z=;KgDw|4~Q(an)?A_?|ebM4*9?=o(YTO66dv z)WRxLFf*It>AyLw*ob1QZLyU8>B^Ug*SsC$y)L(=$c5@$d6*kBn~d(<;ksE%%T4DL zqvsPBH%<`uZqLopH`H7Tl;-$+D*gS$6ipqUl#^3r_*bOZ)br>{%YN9jqaxp^^U_dv zByc%X0u|!U>y4iB&zN`DSl;m-(Z&0?k4 zgl(ueHqRR~mqUJHHokS(6}8j2d6Wkf=h%t!vl~OPVZjKYc#xfRQHbAv^WXo#apYa_ zLt6un5XEnG;T20W$B|~pucbIO-G($8k4VG`;RvzH8RyVJC0HzpqV7r@IAc5){KIy9xaJ@%6?7)GI+YH7{p7h2Fo^xW zo$y!LmRA#$uyf_`$>@yKE^cev4xGSbnBw41`xN4TT*?@tDQNkw88b={Y1cZ7oQ71V zYTD$ywH!L;VuxCTLCUW=3@X<^2#B%&-t&p)|7zVE0(aU0PbQ|t92T|i(hw0MTo$qi z&*CAtB;BNzipaf^-_vKpLQeB)ndIW33+WmCGR7d}%e zU4DxtA=UcMy@2-dkPAh^b*@AhW;%Sos8_MLfSt(3Q9(DE>39I^kpAf}vJRYA$zdBz zZXW$EtNBqp)y!C#wA*;xRG|O#WXy*`=buph2Lo{%QH}zxLt&DIe}z>4X=T@%YP#Hr zfOcGdZ>!eF$%rl@ zRF@0L-r|eElUQgOOq^l7?*IU0K+cA=WgR!$rE~)1KT&6)>UY2^n&uObeFXA$AWblK zVb5$lw^_KfSyMDI1}C(yQ$Xb>m(;Uw{PWy75+UO=1yf?d4|>mtUYyF zJ}Q)8X6VQa@hjy0>aSJ2CkME)VM!S#!HjFy-($Hiw;ob#_tvFtMA{UDS8P#6>Z8m{ zReovLlYuTQsWklke@Ie2h#vU8a2~a^A^%F4mpo7m{eTc2Eft}9ucMV#s*>Y$cP@u}7tLwN)cGx{AO#|+ zK?XAiR^XW4uj**-eiHy_Y}ZC#;6*y*f!ExC`EdBGZjw1oC}-FK=Y`W)K9vhY@f-O0 zW3u~ifr7B#tZ(6dS9`IyWm_KykW0R`t$cEwmQhEyvnPg46S^rM((nMK|0q05`z$$6 zk|m<%y?D#}p4S|q)2rsD7|e?N$bU~ymJ_k>3u3No`51c!qRMxA7`_pOz)G~V2#aeL zpKg|ktbg3#aWXez*IT;&+OBUVsY6oL)g6AF^hG+B{r*p4R{T7EdI|4`sP+@zE?=8} z*{YgDQIt%fYo2=aj-YWP5s?+qq;&EKH?oRd8j zB`bS$2!~ZHa8Z@n6u_rPmf{(lB;B%xP+>FDN!> zcCPsvZ_Q9&SEwbJp01$3<-O2F5P!G?Jpmxk-JmN6)K=PE+Tb(CLI#;PuoJ5wN>U$fG!yzi}} zAg7bN`TBBp`DGeN9&)lLI)}peK1}5|qjmrjz?e+{^%#=g27~i_HoO1%KE5KKm}x}# zy<}2y$+X(H3XG#v?J#bnWYp^T=OhpQ?0Yjlpo%f@0my|umBvx?zn8l_;ga#cN{ef3 zcIBOqAopY>$+KHOtIqdiDe$O#Hk5+nzv)hCKDyOkeRKlf0xFGSNOEUSuZ~U-c}}%goAQr!^tZRIWI|)o zhDG%C%wx2{i_C%F@Nyc;8qB}pCH}HNuUzsW?72rJl;D>$(i(ilh%FeSsgE{#nvnC$GM{{-_c%1Zv zo67U$x`orpoh9hh2QQS&4EGfOawcczb~W<)Kg550Ir^Ke5ZYRnoH1(*za>n1dNPrA zlarR5^aaK+j__$j=5|{iVRX%FulK>eC>S!u4fSDCZAm-%Vsxx}db&IJ-ZgUYWcU3j zGjE%~S7KIe6*Z#gWd416kk0v%lD`YgB)!zVuD|j_dHv3XMJ&cpyq!cX=p#cLH+R=H z=tz`GvcH|v>l%HI8V*Cc8c^%|<}`2_T_^p;33D*!w~=6_YisiX>#J-dV|%3*R*P#H z!Y$H{_|ZZ)G*1{rtRKb6Ns<98m>B&PJ05pD&Bv7}+wbuE-GX|TCg{Pc;DwwVWPj_# zWUGe}w^^?0PaP>Meo~(cE6ew)O`tX5g{K(71y+V^#w(ueNX@R*7_@T{w9YHuYWwn` zY6<4O#VS_S0|##f13AW58Ji!BUSR#?JHs!m_7`23&WNcWU<2t?({Ev{2bkdmE6?QZ z!o|{GbPyVL$E1Ig$lD6~^*Kb>X7FJa6C88cXgtDVWe<-bU{d408Ml`Eqz6>-_0=(I zgq_2BYjmYTse~}Yc+b^`q8@4S2Bdq9OQIbdVn{5iSPlTf3?lT8hJAY z8^!B1W|#%pDk^I6X&!lPl^ku=yr`_cd*_Z^NKsthk?AUYR$vtRF@iB!P@Dg1++%$t zO>GVIGFYBTU$M|lVkC5`|_-Wfe<{EfKj5BmWGBVT&DnHMeQb7iC?T38} zHLx*L^#e(Sc+k)ybYlm05RE)VZXim|uI1Z)11;X)iy{xlQ~m??P|5r}em+*d7!4s^ zC$}Hg#fF#`Ic0F5Xr?X4IhsGY#Fe^79S0X;FHgmyIYg6Bn)rOhO28@+Cz5cghihC+ zJ=fp1TMV{+P~Y@pjJZ!7{jJz5=#gtTTF=GjTO%#d_tF|GL4P+l$1x@Z@anSzwtuI7 z3oC1t;fBBfC?LMuFn^x?cuI!VTjv8t&~2YyNQFY6UA)11-XBwCUvC1^BCV8zqQa)) z8hm%kgIOO45TYJp)zNL#Xoob*5%p@c`zO76D)N(Y)JiF#b2oNR{jwE#p+qicPlwJN z<$e9JKH!zTz5|6Swdfv zP<3ug_)o`WqdB4*tAf|jJ9Q*|%asRh=04fWz4u(fWKXx=q=Q^37-h2tq7jT!2*fHA0a7X_D;#f}Jfr!4#N zqc55OwYt6~uQ961pPxYT{nF7H$s4ztS4X!Rxt_k86-#{SII0ZXIa#h+xVF-vSe$a% zA#I*<7P}GHD*oX;9|H}(cA4kMOeS@)=UK+}$FPq8+)zJH6shOn8pqm{%T@52E6AFO z66t29a})AA@yUi@tWq?W@bYFv@F&qMm_Tkx%h4=V@IR|*)W&9Kfz5Dm(CtENj-$J% zW2WP<%2?*|`OP%ZRw#ITI5wX0UYMAPMLuWdYA9mv!EH{KAMbk$iA?*fCH)S#!8;*` zLf-rs!yhPGDw?6{8vRfp5*s6-AQXx8S=FejA3bWN?&5sjT)p(J?ZAl(v>}Abmhdaj zjscjL#udag&+=`atk`$B&m!8cYJ<>m(oB$%Re&}Y7qIL8RhZ% zGyy1G14_lErv7qrCIu#G+UA#bs&f_=YMJV?@q@I;7M(QR5exJJhhQzKbx@N@nea2=<+82z>z&3_DR)0;K?T=jQBU(F&}=5&ut=Y4%a z*)To}(_YE?@L&rahaSdOCk~zzC_6v=jO^IiT(u~mGJ37WfiXbM2amhDUXtjQmV$fM zc*=Ot{0yKaiC`?~XUe7EwLoUtsd7DnxJ&DUK03{rT7L(TJi+OuXWz@1C+5$;8o+9C zte0XV>VszF_0sgCj&?WPS)P}?cOUC1z#KGAck@g4ka~vPxK*vhaG6n}8O=LBxqA{Q zw(C!-fexVrUWe`R9juWwU5r_kIue z#N1?XN>%+33lEO$+wz0u_aSTi=D@3Je2$8TUTdrqmDs5;g92NsOuao(gW%X#CZFCH zF;2{|FV#^mMK~8}*4~ZGq~aW&1h^un7*&_U#VRc$bV#@=F|k++sRI(!Jb`>Xbis9# zSG#_0dfI z*=SWtEPA0+)0gMX@r~|E5X2?DtuN~0uElYb%cDoAj(!!> z@L2A!h+`TaEBObeU*Cc2KPH|2kp*&Im>1(@8+qiKdH*B_`uq8FOA%jNTZZ{QYfd@y z0IXc+C}>6*+WiHm54SrnS&8e2y0EgPykwT}UKfPzFH+27`iv;xyjSZ;x;3O%8)0atFP#XsS%<94dS|x>hx6}Tzcgid%VXdXX&tANF zd>-Ln=4$uzX#8n8*~+6M`b6{jF2|O-HI@FVb+MUbw%gNR9Fy1KqVyax)9yH*Uh6bi z7xoTT?VHaSq3Tle{H}ft$RpZ50#bhbpDcj3dgp+M!=KhtvDkIAWXi*U0R=#@Y7sB` zR|{%QC$1;!$aT|*!k4`2$C2&XRMpn0WPk&|FP~8s*yV;d!T(n{jjfhB;gfR^-gsV6 z5i#dF`^n08Mbeu9GpR|yk6~BxgeI8kFOs=xU zh#t#nbP=>$#8|Ex@T0DdxHcjQ(_k`DBfj&?*i@>TU$dA@^SmOJfM#LKs9y#3Rh`Rc zdG`1bBFi*o^XPiMhC-s$?F==->DJk}o0pxGE6?^_VLTqAu$u4D#Wms6^^ao%;Q`9x zsR%DI-VyR65?}Y`J%Bml?_@0j(yrx>uHql9(830GTFA2?LUg?vDN5~UgM@y~CuRv{ zKMO9G{yZ@57HcMsu5izB@+RM{Ve%t3R98 zxAbsIoEr@%kEFInQPn8oj0?we@OVgOs-Aj3;or&Y-_wxJcnCg~NF zT^qX*?1hf0OWk#YdUU7XV8@-q_lE}UF7biUJ@O_2mWNVO^LP%=jGeUjeZBS{RF?b_U*nMj_(S@-N!#Tg$AxZT*|b)5>RH(StP zwsnvpe%Cl_@-uJA4P0$lfj^FGnn^!^5VszkcjvW4KKv7q4_A_>S>6x+ZJ(FETOTpHI{x0NrhVYC@;$d=>3}zE3PI`CBkRo_uxXM z@E4L%;kiEQa7?NX)_X9IO`7n(IEc4T8wF`gh_06Qi1&HMV^;2d_2@5IVj{eeCk!b2 zpU#_|zoI}H!lJeL0o`hKBdp|)iaEHx*eN?+FuD5_CZ#1Y7>+6yrW@`yjVqV|DtdJ6 zxz?fENEtDktT$Nc*rA_B(1GPMa4y}hpHb=*FfOrOR|NR&h}_Bba;i8|>*4B}Tb+uo zamk);p|tyI4L*pG<4oaQ4&U+`&KD~fv#eEl( zGj6diiGErmev=5#krFmnwYCe=lWkVlVuj)^D(~1rS|NfCKX*PT)P!Vu;Kt|IRM+rf zFLUB|QIeBR%;S@6BtLE~6bp_epivq5O|dlF(T(cH=xZAtZ_>7GS+CG?9xFYKq?k*p zPFxle-S-4f$V;e^j;SygjR`nBG}`eCnF(-b@vFMlWhH zw{{7;HO*zJ;S2_l`XBN-C;hqxn+xm(dFH0byAN(N5#_PlQt>d@6fw5EF%1~h_kcp~ zHhW3)bWJoX#nE*;a~rQ>-mW>;AH#(v{hd6# zx-{uW^UorTo2KU zaKLb(sd`eXj*SBOwAND^-#&=z>P!NRAcSG%FoEik8Cfnh*@6RUNdLmPXkqkh{@bFR zmar(&2DJQ))HBkH$zn-71&l<{qvdSKvg?D`R6# zRLeZNs`N_7>AtQ0KPvm9=c_)zoe%FC7e9om6t11{%lp5hh8{hn<3(^gL{=-98ck|; zgT@iOl|BG$;uMxpjqSX%?cwaJm0l~#k7KX;^YBZeOfuP2yD!=U_lFBMwU`APYP$qq zd#*GVSev=mEu*fTjMGYp%}?q5n%Ll`yt8>iZdYuqgUV1bfM$kREsM@igdX)!x)oVb zT;0VZqVCxZ?8^Glk7dhkICl@Vv@AjxwHNbj12wSp>k9Bc{uVRt`naG(EEP@@_+|c+ z?1pY?UJYrI`&J2R@;!wz0g*OJk21F`%rtO_DZTVw zr?$i&>!%$#=#aLo1F;6cDj_z74OVC9!kaN#`|EFOA8jqzvP54lD$NzWgsVCr)rd@k z1szC_fcFcsLQPQ$)nc)1Soh}n(im%Vr&!v5R}JS&o=>{JAP)P7l%5;GjB>h8ldJDg%|1W-20qGD00ZB<|5hWysA|R3i(l9}~yV+=@rJK>+ zDH0P9>F$tGBc(KB!v0dW$efK#jC~#zPfL5J`q=22=vGJwYE%RM6&mHL zIeN$zgM*(K>OqTRJLcLVc9WP}a~bNSunWWMhuEd3J?54-rBsX6otHDNiB7lF)PKy- zLs+5sGq<h8m(f*tu?@(MrN-$@J+MswI=4#iw-}~# z2!w8}(LDZ4>=6)5viGb=s|EWizc;(!+cv9S$s>M_FDvmtN+Ax$dkStpSx75B@J5*2 zhsMVNsjKlyV~XTGM^q;)x3a`uffTb=2-#Irr(?HN8>gEn4HH}*=<{}OP52VI?&b41 zgbe6mdNd|tn%^Gm+T;S|l(bY-w6gYosERI6%;3|6X8(uY?tA}}elZo;e+`ilIYZ#b zPAeh{RN<_+#m@f+Srse&$|?U-_Xt&TW*-)D;zBe{eWLjzGj!+mZ_td3Nm%yNGFfyz z2!C4%(xvHVKBxWP9RApQB2c{>JOQ&{rg=rUUmFhDg0!UzrdDABB0Il{zWXZjm5?&* z-8o(kG~;i{&BTV%+R_3tvdxof?=!i=)9`PJJi3?Vmf~=0nVh;*$yO(>6@H7a`(jMI zK`ZUbFaxXDzD zZv&GPv%r4o4A0(Z?OK0nlF!I40p%>AigrA-;G+c2^WS_*`0}e9;>yQn=*?KVAr$L+ zw(#Io3kX(2Bo!+LxN;k?kF4ZEj!RUG@TfZ?!tGuYFeqq#oa2bTl8) z_y{=;!0=&xFS#62U#pD%dl5o-I+r(XMKYU_?oMFcjd^IJ2 z{pbjZ;#=u!&4vR%|6F$I!wLvu=@(iZlBToGi-c<5G$RY=8uJd6z)uP8(d81@Gs)gK zh0uozf1Lh*4p5I<3{~A}f3tKh{Oc602iNBt!9KZzUJ+rx(f(%?K`W`T`=3#S4Bjnu zxZ&Q@x19v%4}Q>F<>d&m5r`(99z41Ad~jRHB9lLe%Ar~B{BxD1Cu=OQfI8A>G~fCu z6vHZF9}nK?YSXMm-a#xc=LL_#bt&nk3EGArC2atIi~?|#=+@cq4Nd0HmdxnUZzz{I z#zeXcS43aAL#3V9@Xs2f62g@c6a6B36CKP$UiRN}nK-%1T&2~=RpQ(acggp-W5McH zX&1a!1>KSf9D7cL3-7baS^*j5I6(<(K zRd~kUvE+dzuVLBfbjL~7wlr(Gf{LTyKNh~#Da2XxQB-ujcY7+X5eKDOH~=-Om$y9~ z;Plq;2i9c;?N@F5H#l{S65y`Js7baAc}95o0+V9d^=#m063QtCC9;y;hv4`!7bf8` zI-9ceCIZ$X7w99+Rt~+V z?DAjFLM#LRbx^1XqJB{+|HX8py3vaO+eOj+Ry1we3G{dW=3Aas69tg1CmILZq8xWb zHHXj%QnY3Sd+=l8b0CkFF3fg^)~foo)A=PeQb76Ht%pN$*KKT*r4OY0 z$j-_syBnE^9Yn!d`IvbMO{k$)ry6RGH7L6)sO8v{==N&G%u4w6*<)V;sD zydaXsb3$(w4_Wgq6f4*}b+fy>qs%Ns!?*G&6M@KPvq7)$f|qxb@-NUWMOnF4RNdo0Tz$4uBRBV=6_8LQa*_Jlv(aTq_fe_b-HMoJi}D-H zC0xS^xwYa9aRQ{0VW|IqGG`J32@1 zF1^YxU7^%RcDs$0%x+uw*TchVjHyCFf-b*|L{tJ%%Oe1S9o)`8ye$umEY{{SVQ6$b zg@7*_8fz`GI~(Y$q-3yOe%PbArZSI#VE`>@#<%QCf}Jt7r9Q!-zJoL!{RI!~{ip-n4x_kl?5@uBjFatxA}O&GVjy@?=iUyC2OD%VlO>96|n} z4o4uXh=Dek>?$a(xEO59gNH(#|ECkjv6R#ZZtfppzTG3d``f8I3DT&dV?ovKNUQK@ z#hzFh#^Y3}(UTL>+b<-2H#bVv9Rr;DDMn#^j&Oc4#{|L-Lc7(jte><-$ zf7NlYJ!AO+)}05IYR6vft(o|3!)>)c`DubA8ss#@h0Dkb3?r0uT|C()z||Fz>`k96 zgu%-kU>s6u;cie-yTv~5*bnudcsDdW82bfcj$o8~4x@goTO+fTUchE)9vfd|$X=Sj zV%D%gi*kvi%_QG!)k%XyYzgyk&t`gX(RT56+CHrLuB&orVd7F0qNq<`djH-y46nER z&Jew#4eBlUvlL)kh~b^V42?s(QOkPCx|o}*73-A=;&<5C|GV_Jdrg;=lnfIS< zUGj1Q=NYE!oFQJN_0|{1f6pzpzimuI!GMi^{4+6B`M;72LCA>s zfUFmBPFC&ly67s@0?KLorVMAMB!0YBnfqf zYCAzd5ZV8yTbQhnAU6VVLZP&VyM#olbfNU3ge-R3ecPn$7-eg6Zhn4kp|0(7!~y^& zgbV4r-cAEzRWUvT&f7n}mJNJ2oZ-|-!Q7TY1|i3tYE~@bCf#0eI08uqnDN*qxZ5$C z8;Rm!;%8vk(Fv=r7C>I3y@&GO;y=o1!f`aI*B40bZF!on(p5|%lz{u((TlR3U&QJ^FjmpdEWz5zG7;7}lv|Go?7X`S< z@M@9{Z|+xuhOoCIQf7LxS+MWVfqqYE&HK0AP?4|Lw)p_D9-1dFu-b`HQ5Z!gqFZvKSlLr~nsLOSOA42UV9=V|zWfC2!%@D^W)bu~6cLs}|Sf#I@P1ONU;Y z@bx;0#nXFChbL?Jh(Ky+zDuj~Qe($$cnG7UiH`^RY}}3?wsPzJ8KdllxrU1~ogf#! zwbycEjW)50jg!!3#{U><9nb6mJ>Q>&7I)X0S^;ju0=5qIaM~8%s@SLP5LFqsXw+t@ z(Q+yq;9o8D*hotg_XX{ZPO#`7{+xfpJ;37LYz$hWD}G8x@}G+A=wnmG;A6_C!r=-J z+%^=_RRo2~p7Zkd*Zkf|3Mt*>nXa>*U_q3qK-tbs13n+PX7lQ`uAWa26&ITOvo~GZ zdXo^GdO85|D(-DQV4`MZo!WE$>k~nTVJL#k-CAvyQU*RfxSca7Q#qOZ*fg&nl#WK- z1cMJK`lwf#;!Vh)?`N^8{V^V7=jriS3wt%{Fjf(}*Z{X_3*XJLg`YH7Zai$-Ef~`K z?l~Ii{~}eGhC@d{4pbfz;THDn;x*zc9ZhC-J^Re_mnN*r%*d&w8>JE8noC}q?tSFv zFU!wJ!9InF7iKF~ZF%m?qR@_%EnI*M?q9|Q&QJLgnrD{vHnqip{EGERzS8B72*t9x zjnMe5{8nA}8$5ysRW`|CYdWjFBbAc!(l&e64J2!QEM`wV<$HgvwVjgDPNz-jjLvKD zKY=?HVB*#%FC4LoqD2cUtHHfb92RFumW`|juY69~47&UT z51N+~{W?@QTQL>QD@dMn%cWw2h)|A*HqL%WYu;gr z7*g8E+-=SH@KVSk}5%}r1n&!BfEAgrSQbJm4IK@;IE9Lq_A8y$< zuVI~95tIx9BY<1|)GS7E$28!YN0kH2l(!5brh;&Fy{{MNwA`#f8zEI$xqaYll0aLO zZ1Lx!sQ4jiFHVE{t{r{tJzPJ>fZYE^uq5ay3WH^W`Q`fVEDa z%NUKg53r}q4TNAX$}HGF+nmjXll$91qx)#Qu0m9~%QaZ=@p;ndX-%(tQk_*M1Z z13Xw49fT++Q@wnH7KvmTWj@|k=~G$>x%t={(CJF@q3!W*MYnfJn!1v9bL=x9`t z<9aL5P8j{irmq!29DH~3QdNc%__L%2vWa5Nu`>y!f%TpJgfj)XKV5$4_~lM>o-m zz-a?K!A*HFQku*Q_d|bj9~=@J)vKo=tJdh-;mkOuO|~;Ka}Fal=W$0HLLS@l-t440*Co_8EIeyL3r<*w`J3#Zv%%g$q`i}j6ktczJ#7)e9JM9f} zP(ce`s1N$VCd3td0R6-9-w(G% zj|m*vg2|+an)im{ZRH3U|E&*7Tj$aB7mjjv)-*BV0>a_2mEPKnrqqg|kg*Ag1p$E! z`>y%Ds*m%^{iU=?F#GR1dJaiP*?J$a4cdviSt-u?+;i~k68|%{iq)UGl^?}F)S)To z0ya~zEO6@$BT;Vm$0O|&=53LuHj)Q9?=6P<2=?w}+DiHGCP4o((?Ht>05k@uy!I~h5TsRq4EBOSMvuM%i? zYie#bZmXBN-ObD1%~_1-HYQ!xoCx|QrS;@~F3m=0CTqPFw_NsIcqH0omr)N9=7_2- z`=k{N+WFnL9n>SQie5f7Zgk2;!P|MXOEC@y7B*NrhfkP(d8!Xw+a^Y1ncAg8>#~7b zSzxIqwBNcCG)FaFMO|WDi2{)z_U+>X4!%LnZ(3vLrETf{C@BMwd1!=#kRSzU)B|Az z4w)`pX+o2_dT}R|h^W~w3-4Ly8iU}^_1-@zoH?hmWATn0Hk^%Y)i%#k#f6nHv*@I_ zUUJ5Lil#RTT>b!T@GZG`>h=9%Pu$oqL4u}A>aYaI(iK{D3Nm-+LUDhT?Y)ha*0JML zDd{dvYPZch8w4jH?1x39RTHzg$$K{wa1Vj!SU`d7hNzz;y;XU_B`oc4Ln~MSu3>Z6 zb{_zNnx%zZ0207e=!J9G+9ov3GM~zk;Xclm+A_eLvV{Ho_f|rxkyDp^`QY})o@_9> zL(Z4pzE?WZ?KD4FElES#A|x-nnFdvD`jpccIK3h8;CN5_WN#<_kvC_Ml7jbIT{?#~cCUZ$k#VDSy{O*=zuZd0_ z&^jid8O*8xy4(v@RQ`^4snL1`)B42SCM#mpeZ7CaJZsgNzti~GYKRJR>0NJsaE5C! zz&G^*!vhI{1sDzSJLq}L4~3`o!d{}f#0M8ZTii6FLkxZ23Pjfunt}I$iz8R5GG|n6 ztl*4I_*+I-raRw!`!Fv(i&ZQYrX>d`Nbc% zj2(g({qmIGN2Sm415G@+5UX4al79=DtCL_^t7=u@?%hfSd*Gr) zf=LdTZ<;6G`el3@b&cu}OyQPBH~>J@hCi1-!ZIqC+PoH^HOP~r+dI_bIk1kReuT3M z)_K$)rwagmPrMVrzS_~n&dU;@hDWb9=1LbMnF7A&xS(9!MjXM!G?{IyUIQ${{bF2C zX!pn3c1Ec6J(amkn=|7@d3dYK7gxg0MSNMT7Ec33$B$xlQQ=$7{awE2x(rOISA*yX zqGDsm%tY#`WNqK4flJiRAG{;1O<5#;lbn39LldBI!7c1>g}0VMKNPZe1FudN=!_;f zj4U#*?-~0w`<|ygu?@^u3fg)KaJ_ijmQ6J|e~H3a-g`#jA<6aKIu*(uRthyPTHuDJF0dg~3^TN>ydd(dZTb@I?B>`lw1D zmK2)I5J1x2mX^Mh8vKybY^eaR@AuItLYyyD(7tjP+El7ITy@%4)t7VW<+PwXuBb`r z6}k3tH zW<3!X4Ad4A0x2W>sopL#Gv8CTuG)TuRnho}Z4uA3 zKaXEqrtW;C2TE=ks`o{i+?V%Kfm12ikMEy~Zq&e`ZHFi48amjsBMky+EI+C4v4O<9 zEd{qLK;H_6f&V{^_d2#_(X`-TvLFnfxWW>aF+e>7ycT z4OwMpl8GKmnI?7FPr~$W`&v;FXWv70HnJjyVEbjc0y3^<@7yEOY3CLeh(6ArZ4Ka@ zS6J8?BnG0b(q)L6sdRrFh}CPpJKq)l{p6MpSH6$WSNZu~3g4`@f3Q#gPk>#Jv9?dW z`1pP%3Jnu~ffA4sEbu z;Rpqf`iVKKW!=yRFgjzIB_X|pD1$*Nx87F;dcj@-dN-Ko0*^YqW$gVHO z*I(v!M)xhHTbY=m8FRH)-XjeQPsDeK86-e&#`{;FOS!6-9;$C3gfnXzsm+pgj_ ze}C%%5OW}A&`2;$m{FDoG8LXjPEjl<QRA?v(K&zKu~v%-8Z zA$R~l?vD+27z)dhvisw7uOtK>Ed<;uPI)8B)tQS~6-2@*lbXy0s(1%qNs>}AA^W0Z z#kC}=gm%a%`lv5r?9 zodb1mvvODbBhg&+cU;(^EOJxqe-eS%E%kOruQG-;G0+kh-G+JgUqlBC#?VHasrLDo zL)kIUXNkMU3U?0WzSQjS@CQFE%9zA+l|a5;yH*iW8OWC9oN7hG?v7Iz6b5~_fq)o3 z*Bs%*iQe@-gYK5AEc&BU5x+v4lq;JbJdpWZpdXs>+huv9`Bh`wM9sO5obHyf>~P4t z$@H%({3Gi&^sugu#;Jr2U*C4S^Xa0!`qPdW)*~gb^OYb$UH~dMgN()rX4B>m-HSJJ zyp0&h0m$&idiZPGIA`2uK2%X+&Dt(x6}72H{X@kxZ#(*;)`R`G(W(3nV-%zjLXw9Q zS0BR>V8Q`{oNyJ;vN>OU2zms3Q*+8*pi=?eFR2dPyaiI~T2ek2+ZAe^#fseI(|1_P z+mZ-jdNKyIT=&gMhZ8KeA?*Jsc|(#O-ag-!Ssq-*LnPVGkFuoa~7od z=4(y~#{e)Ab#}Mn=DnJAjUjB`H4yq@qlgLjmBE2P&Cx&)q?&fKDxluGd-b$^P@#yq z2EHsPwXJmB4X4K&YRQ3)O#CM8r^pHBcy@V>WF(NrEc4%2{D`-J%r zcP8?L8nt#h0sZx?c4hy~-%EUiP6$A8;x+u&4F zAwJ`3*%24xVSfdY?Jv&wMe(0+Zs|ioMX1w1KpXQ7s-~ObH3?d$G1De1ldluy;(5TO z*(cYf!%vRrKvW&=2T4ZD&U5Z^BNmA5J`477lCHbsyO31|Xf=7;55vc$R2_XAQ*ePk z!QJuqGp{a>ot(U1jmO8UU`tWP0nXlB1gpDvJX#wQ7PaHWkt73qk4|GL8rZma&<09b z!A*jKGTu{nh@Q&Sx3fCsV2fha@hf*YcrTUC^38bPzm+C78^{imjQjaE!KyJuR*rCOiYLT3-dekaIf(ck)fo-EyZ%2=1HjrrYzBSf#g6DwLk1XT_aAq;2v^>@E?z=`ifkesHMwL5Ok$7Q{FYMm1$yq9fu+ zZ_pZI4q zIP&<~0h+&b!KRrQ(kWfB*nt0O>4!-<8jlT+GQKI4L-3E5`N3_%Sa98OBOO7N2q+?= zYxJfqPPR;`fn3@pV)iQ!wVrVnD#Jm1=-8Aql=6+b*PNdGQj~0bY>s(?$YvsRr`XdC zUZ%lBu_R%!8ONIJB#bH8{5??-XLjr0zYIu23?yR%Fh{$r3DEu7s6@a~G6aVerh~V5 zUUZm#G|gPPT<+|9z0;n14LD^*ZxMZ|vx4Pjf!F zJ;$5JU|MlXFEYEncWDN_19UiT3fTa&EFLlRRR|JYg3szK6%R}Npxs9&hv zWusKvRZaKMOo!R|dK0bF_Uf(y`5!3D-fu3*qPFw_**cT+%>A&LlOF8RCJ+~JB20)} zkwsF2kq~m^0MO2>hQ^n$M4Tl!gZeajG^5}=?2Z_ZY0ty2m{MJT-HgXrpiuo$bM-vy z6Iw<)TOY)v_kh^Q{?;FRM??S9*!}^Sk6_6`-BH%>qXlE+N#?b&{TM?S#A9&7g@*?# zriXoh0lR2+N}{q%s~zR=`%YH*?LO89R0)4kFSg#g=C=B!)>T^{xs5c^<2=CX&}a*tE|sm}`E1SXf_$M~fzF{bX#* zv7+nkx-k&dOehKEEE12S1IW<|o6AXGQJ^;U+RIa_jnxjWG`#*_Y5=Pf^ttaYa3wql zn7JhMBf#Q6F=gt*^=pwh^#`Zx@6~r7pfU$WsXXBLMQ5q*)NNzRz~orW9zM?pUB#8( zn1ABHRwo7}>gUIqXfEn}=!*Lz-;djkzRJY)DC(YIHfg57Uk zf5sl`SiCK;ebaqknP>VNQ_bl{<>=oZ7s7LJCI3@VRRv#?Ogmo(AdUoFlg#HJHQsO6 zrTB-$$8Q3jG{Xi;M*}Pt9c8pXZg)@)-wnwVt`cqp4UD*{ zpf|4R$*?FVtP7cs_uWIAmFm_&+uKE)kPde?k`EViBa|x*C_*L#Py_dH3I z`vg8({Lk6ID=`2)G$2|A#XqC6I%S;}Oh&7RiHZ&+C%wuFLtmTgTJc+n9M-W}Rzshx zK+C$PD|jYu@06L%MOqTq!bVnu2G7AfhRVmxiJU@vY%X4B@Tl5+>Hs z>3et+PukdXDyE}J>$sm+9fh|*v9s7=qVS1PrIJPbnft*(LF_^4ALH>okMrBHs4`zC$Iv46W&I5gY_40!isIGu6))uvLUZ@YXkB||!R{!)ArGIv$h zsaWAyzg*}KF7C1}K&v%j(mKYN94EFu$b<#S$+5A$u%oUwV4M0zi_e+6U4jNsUGX_S zgm=?hl%OtmbDhb_>61GK^tyJKI^Vpkpul`BZQ_NR?}4{HM@t3ST?BtwmO&~cn+l;K zMyctn3u&HBi~8x~TrpJx6zDU2-cJAKE)%r;C(%zuM@r;!ILD`Y%CC`NWATY$ZGiR6 zK{ES5UKPAJoz+5klT-{)$mKcXh>az?N1CxeHkhjZlGSI zQ1T?xC~bJx-JB_v#oem(C-nuj?XNly(`dm=6QmR+KKgf$!!yTQqnINqgZ`0}vou)sG?KjJ!r>rPbO{*#v#q%4&L?CFqfuwD zDHigS;ua_XdLL6MVkRJtDUc5*g4kF&Wj^#akAOwxJyw1Df$#Irf8ggRM*dn=$7XQ& zjq~ANSirMc={r4M#F)f0@LVJwLa$;swT=Xp5=F`!R5jcO0OemrUMW#a8c1kcG*qW) zh*9UE%@jz-?%j$%x>;(J?lTvF)-Ri1!JXAU=;ChvghtdJp)#HAY{+F|&tt3q-jEtF z+;+w>g?Ub$Sq+E~&Y@rqULR$8V^#1T_Xsq#iR-O*Ae0pBkKrnvI~R z-jJTu%VKx@ysX>xmyF{?mIYGp3=PBz;UB zig_{u-Rf`9uf&MGeytqH9GlB=?+xk0gkZGF{kw&hm-ryl$i_L)bmG$d62m^g&{t-6 zD)$e9b>W-FSUW=sm4Q7r(j0IB(|h&sOU-XSc7$}onYZ^B?|P^OwyOQ5u_<$tCBcHr zM@EpP#V1zF+iXuH(XAPrp%qp=tdTwM_LR#qgC1L4gKqE=F+wXzK6rJTm+B+K8aPT6 zkB@ghcq&c~6)Xp2@|chJT%^}I(^I@A;~@mT88r7k{yElNf}GwVwDxlj8v%CT{CmfF zrF{5HwJ9C8mcMUX2vIK)*aE8ELVOS7WZeW)CZ`uURp^BHJnVHwz@33w|757%1O;Oh z4#}r?DiUtW4u`Koztlr6n!)HLpwzsS=UXM~_9WFo2*AR%FTc7Ki#`LEV+$+wr0X9Y zy%`JtXQygI{%Dgww@aDmIaZsPL9k9Bone)}gwwp5vs+sYmD5()sj8cd(O2XM1(w4+ zc-BuCm79HknbRM^?)A~&`+sP-3auJ%tV(`hsb)WO3+76b`N9=mGV@=3qAxbUIu zWDNdvADQ6jG|#G&qbNuAau$<~K@b)6>|K){MeA&qzrY7LWtF7;{+NTgF`~3Ko}Atc zI_E?)2-Iy4kW<`^7W^3~CIO^w*83jb1^pWV9NseSl{rZnjhNoeEfhv1C&^%D)^=K(Ard}duxJwV~3MDzD{SCaY{|1eeoY9Rmr$S^r zqenAe);wo`o?iW&oq~9xsx+X3WX^TMAJ;}2NHmu(+p=z6&n~EZWtQ!_zN!;l@Tkmc zb9N+J4QOo@x{h-DH9>J)?qchJC7gkLHOa}{-yUHA-;(&=N8)M{nQYxcxM4Cl9y{r7 zJU*!5<0&dY+oun1&U=r|b_Oe>JR_|B4BKmKslQ6VM46C=%C9`AHb*zH=u0l_3jVPG*t9bnpbOdgrs@)oT9{jD6*h-)|t^ zs#qGh#Yk&sqI0tD9}&x zjY{{%AQU6x(=hN_dI(-6^J`vk@27_RFX#J|0DK+q#I}#FBey_tMso4Ou=m_Do>Zgn zeD5fKOFY-ed50P4(?8a>lf$%=$H}6pP(0M-rKloBab>xo-FSrEG?kY9Dn{jr;`8$V zo~`D8UFwSt$1m3^ugjdNdz=y-gG@AUss^A$<)I1J?9HnN%Ok=j^)Cv2@{`5a2c=yL z%XV(WgDpRUN+z-6wYi&Cl$4yV-Y3#~k#=rz2UyKh#u(4{UH6|$SYdxh-hQ3fTyE^N z_?CnZBGs5*o~W&L+Lw&d80$h2CV|PsaFExXGXdQS=6*zUgpZfGlY)~rmrm}7QglV8 z2nB$R^8{}4gQ2BZdJN7%Bt*gt%C9l_Kmk(JY&YkVs~H45t7B5&im~#El73x=C0WD6 zN`BGN$6zc=jKwM@D!9?*^-q?uOoMJh!+e=jH}$xR9H&JkO+7G>V|wmeyqv*^L7OtB(#`Hx^WOsXKRM7Sn5gmJm=mgs^b`>>ivZ8%!o(^IA0C)Pu!M5KX)+OxmD zzCcF#KKTdDy0L6W|0@H>>jXYcW9!A9!~(Zn63oNgPQJZ<#_Zc8-yT0C5Uk zW|lJGM1CuK`cmK2b97HwNmW&v?d)#o!GdOsYO_iO3r1_zmWB*R=Z-7CDxr*fO5R)xJlqdA9_15YVLTUBn~qFj~Bps z%8<6jyAgfc!)?XqMS7SqH5Z)$}g|vGq+Er zijIH{7v4*wsxJ?af}GfhTf&Oa$=r(qhJS<^5T&?AXTWxTVQ?US&%5fx&pT)CF>}-F zD2kEo=pVmh)5LX07#LO69Xfld8h$T2=`cgx+#;<%2@k4J3z%#Sz;$W17YEeqBMeg868RkOBXhDNIMq&z zLd$0q$5YaQuMSf(TJDdF{af8XiD$yD2EcLq`xH;9wxNTun{62e#OZGBOpJOa$GP=r zO2f^C`#=x6(e~QO*3nt10s|KhoVGBKxTBGz&0b@Q!1o^LMmJhcIHjC6!sTAnp_sO1 z{MYbodv{o~*H#1>8(2!9;6M6g{B^eV` z<|NC55US2Q{EhVwL@wa@-aO`rc!%2EN>4?MQRH~;%5v@g%Cyc?No5_&TNr5gq$`M^ zDt&lhaa*iR!YIitb#)RR_b<3Qmn>m%_9^zS3{P=eo1RU_@Y+3ubMMc}R;0GzKA_|y z^6*W=ap5~9XXS6-AP>~$gxSBB(@DQLUACV0P#O8+3ojcbN+@`jOo)R>^Td9(uw$!n z4-n=ZSQ|I2e)rj_==XU(+0q8=ake?SCMZmCjw4jmT_;NF1tV_G<)qeRRh#WOQ#W7V zR@9O0U=?|xc7C39=-ZzDG;m`+XP*ze9BYt=2`=)!`iEdpjK@?>$N-O_n|8=4{>!z@ zOd9etD|(I`$6KV-Nh-3HtgYjjiOWm$d2|`PVZpRV<;nQ~obl-aJiYFx`Wkqj_D$0; z-IR@>)eF$&RHWs}hWw9lIQCdYI6VOfZejvV#X%pxq!y)zn6xQkuBIYiNF}Ii?|ApG zifRl;)^)uVl0>T_$H^unl}gvxWXK1rk-jFjXzC?mqLaq(nC6{eO0sntuW?lbKHmAM zw(-UNIb4(^!a|P)%8mP`d;_dWepqE4LMD9}CbanZ8Pb{-F#e_!n{~L2pMKGj_*$xU z1ehK7Ty|~}C`|mI1A!=uOK`Mf(ZQ(Q%&tm`@;gH3;IMs<>Pyq15f;~orma{WZarA< z-s|Zl%n#KkNc*%6unGA+9tQrp)f8$i^WOjh1$NpSNxxyQ3luNJ)b}MnRu0^HBtC-R z&wjfcy7vWZN7*7gHKCHXLKAgW9)=Q-E~i+?b<`pqB-yPJt~%VqKX zkcV>#%-XQH*^X-)ilZ~$_QmnvU5?`1V3vC3Z;z7^r}n}lK-9$mVq!vu zEA8?u0iXwn*lLW!a{70BRaZ!p?~L^yTMjnt54W5+O>|s_Z&l?k4_gwqX*T*$<`wPV zgHhFH1`=e`=!dB~PpTpeQEkU3*>9OsRvci=4684rBvdCjWEONot_t*buW_X65uf(m7?`|Nzs*J1v@wdlQ$lJJ}9i`td^iM4|5~6zL4P` z9c2o9NyYSE-=)TjqT}_{+58#rZ1l~Sj9J@+nOW;!`X?BEQ%zv*s4C~GSN#@M<|70!5`)0WJYjy(B=)vN6=__NW3XvyHc8h~NBnN(y9 zE&8+CEY8=u5ccA$v6(62L&Gih#fJpqmlC{XII;L&I$$Ldvy#v)TqV}Ed4U5{iFY`O08Lr0msN|)so7ql!q&uO# zAmYU5rN2Pw-1FB7_H-t;vt=gyhy77k9Zy6_cI(xw%qAs77{9rVX!({bG-%~<+~0s) zWlAXHgWwwiySxXetLn-;MeioA|5Y>A==7eevVTYM%MdZ?eS5G2Q<({=&8RAt`nBCg zF#$pE=;$LkGKK$Is^QyTV7^i6w{C1f_TpiPP=T*{KnonO2ml040*$ow^Xy@+P0>B? ztgl@qXO|5)(L*~Kw=+hZ&!J@GDOFfm1`x51(o3jQ~o>Sqb)r=L{Sc_kn$X+ZwCO59L-7&`9 zV!D7gl{|6v0mssOFSJVR>h zs`@q7Eb5Oc0xGaR`v4+b1b3{l+_GA1h)lZ8eu8>F*GSm-B-~*Hkfg2n-`YqG9Rssr zmw!4RWq9-40m@&6?Rzv-F3eN-1Tha*U zLN(j{D6X_WVCtORa8WUFvHj!M%tt}RUN=1Fw_D$apNdT;plq=@JtON`D%QJEVIen? z=neT982Dj`-Gf$`5a-w0^B{ZSn8BM@MR50$XkKt9y4<6cCF#v*IWyph=0<7DOk-dQ zzxR$}Y|CObWvM)RLf9FteCuA}Elqx6qoMjIwFodowl5S0USe*QyvG0$YS2WdrT|4y zk+({^SUgPNS;7(LKt@C$HDKXik}K?XD_Q`eLIS6tiuqdHyEOTbSX4AJLT`{6*L7xT z@b=WF688SdGD{W2ty52BCW1SBM+b0SjG-3+8VrD4<@9Rmg%i+kVaex6^Rf8lyvpYwBG z$9cSu(-bl+82jqv1F4CsJXaw)l0l(7c0@!R)KpHuO_6N_7)?l zmWzu+W!y@VP@BBYi9!dtMqZrizk4`HEHgyzX{b3hxJ~0mzv-gf4%_v|i5u%2FXudD zX|D2sf6|&ycPpO|lHDX!&kG{XfFKCP9~jM;fKRgfKl3NRA9iWr$MfWoX%T`$@mp_N z@DeO?fo0rXuv(5%xUliS_9xY^iab;K_zg-i#VVg8yNrOoUP%u$SBB5O zf~ni~_I`YeLz1&@GtBt=7++G|evrTY>d`M4BTk?GiQvzQUv%A-=~y8Fm;o%RQueBL zSrz=zNb4hPC>&JQi0--5$GuFjStSVZlfHLvT>EnoFD8E~Qe#F&MoK3syL(jR?l*bA zR?Lo>vV=K3Vf#nMSO&ZNwZ3n4snCgiYCR^ZwWvj>Y#V8QOvS>2C3w zBJT9gU(icjJgZYbg{BFeSAsZuo#A~AErQnSt-l}{im{S`g!YZj>XMhZf9VjF!lJp+ zk$rt)O*C|2Aj-1wHcj(rBhWRWTScMlDPfebJ>vYPgzi%ZYAz$=S|p$@r)+wOfElatXRbNhDu_T1gWPNp)~244?EzdrD7W}ipM<~CYh=IBBk5Ob`&;IB%M8?rVh{)W+fma>1kGVo${(?xv!rWIu=e~ElWTyz?PGK6 z{9Sj7ng)O6V|s4bC#X}hqdr7Srt340gW)4rSbm^pC|;wDB>dgGH8%47JykdvSw8u7 zaNu0n_?sZ{1Vq64cqS`7>yvE`yK*ThsSPpwXbie{a<~R!&#Ula`ugXZKGm;#^-qQ5 zjdI#QQ(2Jd(kW4hYCXqzjE-uIe)4!{Z|@C)Gx^`l{XGhinmK)hoC9h=79+T?%V4{q z$`lkuF+&l#tx~OaWzS-_`dg&psb#t#l)gN~b~msE__U!FQQNp2dalG`bJc}MA&zjh z`@leTQD9Kiav&l6j}HY0DYrpZvVRDI+wQkP{}QP2?3Q={NcD|>+1bF9+ zNVEurn0K%r3FB^9a99*#ucqR$L(C6PlyMFk6^0jVI%GUS z_IG#J=mA$}<)1Wvak*s<%Y1M*(%IhkbrOt|B1)9IXS+YniX=vTv@=or5~NIMkfS`6 z2a9LXAX$rdV+SX#GwGFms5S7)q zTCR`H5$j?LMcmM)WYEbYe`zeO`?~ zYY`d&=Y9?BGnrX@I`+L&e*-%~`qNER&|-j;es&?EHEx|b-YNGh?gxA*KG9H$gZV+v zz*?G+Y!nlGQQG6clEOTxPNE_EI^;zkY|H2SrPUsXD84t@_*!%U>;-`uX0=;{!*&Cc zIdTaUxSA-CjI`XeH1A~Y-6Fi)-xay*L&)=-OBZ~&G~j{S5br!C5H=f9uf z(}-*K?|nC>H}hmAsZ=|W-XH9@H~V9_&Kn*(-7%=0?m&0}C;oO)N><{(p1Gb-!TLgL+Q7e|!S zDWWM+AA+jYN5%VCjjBYnVT1J0+en1)IFf)~Ibs+K#zW(kh0702V(8XUfbl;2f%Y0J z5nsRs!nka6>>n3{m|{rJ8S?V>ML^X9$%CQMj*s~ch=7i+vH@q8jILuxHNFFy7vuwzU(XS!bqNWqe?d7;x%p%$ zKG;lR`rf7UucdL%zxqCvHeYj(s(k_AP$3r`x2Z9AtIaUhi_H{t2tB2RO^?yK{ekTe%BmuNlu*nz>5#cG7@UBH#%e!`v@I{W0TiO)3 zzpHPBLayLN#7|=_;E4A@_|YR6>yLF4F0v1Hc2S+-R-|X1`r4C1wTZ-%Zyp(p`^ty2 zRL&bJTt1v&3FdsUoF;TmZAZdJrydAIK7lz-)%II~!3-*GByzVRSom+<@7g&0-#_ek9+6c5mqBqMgRO= zT_`X!(e#JnpkNCam>`-#;2NS^&zq+Nv%Ik}|9A<>ua# zHOkGa0Z0qXV0S$FCGG9&p>>ZZ!ZREY-Zso2?~k+Vrxj-*o`(?+7ZJzFcJl@)&pwPW+ZFug@NGfKWz( zV!a~a~d)XxQkwjb37YX75g|zNaO8Q z-?C*_%e5y@IqH&>>puxVbd{HSU8c9JDKaSpH0S^ig5|0()N-g*jh&stWQQV=zZn^b z->`f5$+B$L=ppx4*Kv0yL3arwhG>J&IPC)1ca#_f%m7$dL?Yw2I2xf*8nwcOOy_Zr zoMD<-xFN3eSGa_=k+M(645H?bS!7(l*E`K=>H{y9c~F($b8bm6P8NgqV~?GR3_>Y@ zaM|WQ2*jlI$2^I9`C73KwStk`SGtVXp3p7ZW?v zMK7J4Sd@kQ01~IJ*3@HqvVax6Jj{j0?jl9Cd?_z8&(1w9Q1MLSA8+K2yO=3j<2Rce zZ z18Us+NK@H87C4Wg83FO_XkdlGg3CB3Bu?>cD5fT0T$E4f;g$wF%yabI>~xralNA$= z0MYqZV9F%&VZw?-w#9D+a^U~|o<`;$DeC?%O+^NiLx6&QSC^VzKyg$vF7?Gc=Fk}$`ehpqkDTL&91iY)tMU)`n z{O$7(iz`Bhh2{Z6h7e9{${S6aj5w8i4g%F*;6t327>IXvUqaAYEQ@mh=8YBNBkrzo zkS1bRue7mYh2>?T@hoNdavogloYtb7=}oCS9I5Gkig%hT9}ls!(tfuvS`sRUg+Gr7C>~ zbH)c0jmMp-I&>|DVb;HEi_Qk6fxs^b<=dG~A9Fu(^XrBxoNA~BeGKvPeYyKXoohNV zc9o@?IPG=lIGm+Ssufh)F(|H(8$(MGavGKp59^Tj)~8cvNIH{iFt-YSjl8z4GXSD{ zZuv2QSGR95MZ|N^RC{aA)%##2->r?8@^8SlO}+0DeSp`J(W6bbm2+h|`_*R-s!a0C zKtE)=q}!tRI}@JhnGTygx%fvB;fp-op$Yw^f= z&F!FD<-jO#wrAR#LE5V^VzH|@*|jLDkwOQMjmT3pe-AEeq;Kqq&X`p zveA~B@%}`p9Ss|s&I!fzy&adk4e61pl%^wFl@=7{T)LW;nZqj_p(u;z@^M){Mt2VsCY0Y)aJh2>|X&82?JVyoEgASu#?X*Tfcklhld*HhHFdV?&IT0L_@cV?|bV5 zxHFO}aFdFD!|Rg1`QtiQ0K4t1>x!ZkcKT87IC-zV#a71nc#E>^m8H z&(2!1QGk83gY%-FO5VsM3eg*&al*|2Ila_>&&}Z}?FqTg60i@lflqd?&7Niz5xG~v z$$5CsHXhqWV@lSG0mCqyA*9PFTPLflu&2^Bs`si7{`>Et>P1lRyn=2<~( z`bN~Ha$e)0N!U!FAP6+0B3|$TL?In48hF~rQ-|G)hT+20s8Wk7mhwwvu}OwbQn}s) z=(Fh4s3Q+WLCu@S-BA?LgGs3lTO_~=4Bgo9s2uQ)WlL0tyR7c*8gV?8m;Zoyj8 zE(?PFi;IX_D8UDVbOUR$6Lzdk`rTuLu}RQ`(#jT{+3uHeZmT6VBm~s7?a~`F;uidB z7!dGrTHE2;F1TEY#vCrTy_JoVyM;J_H=wesp9eERXFa14l5Q+0FapQ9T-(k zCZ`Q$D1kL&>j&Lfu8eWzE55A^`|RBAH~RXO&I>Kn0MVeT^z>XSlFWdE;wzw_w|6?2>ZaR2jE62ou*sOGEylBn!?6r;oozbZT@u27--^<@0hOq$! z@yfeR=YO=fMi#ub_@&9QS$yn?_HeU;t&eg(z9;uXhFd9v{+w=e#1TBcO&4O+`3bJ-8zx{m5c} z8Z(BxWBXest_C%%Nor?X`hJwXNhYgq-rbY zAIXs{pyZNJ@egg;0fkAaJ5NwLS6(yhBV1xuU%_Oq_%f+iyJ@8~DY21|tlD1{Qr-jyI$LFU6FY{~;T}*3Hib;HmrZ8gN+mQL36m?(SY`F1* zw73H@!9(wbnPHyr?ea|OtC9n)nUpVl)weeFTfW_s_@^}8)#OWCAD@*vr>H4`G+ts$A zIS`ss$S9J@r~(O$ta~8Fa_sg7|s`wZ1tZ=Xl0-kzz!x{1rZPZlC{PzYrUzL8e>}#(sx89 zfTzAJ^49%M+du`+%jf8~8tgd>@}`>0c5euw1m`6;dW5lt;f&_w15KwZ3pq^MJFWb^ zfd9TD6quCdgBT~^gzoe0W=B=1yEbD2F>4`5NlGSEUdSE_PO-OT{Ws=6Y0AnUkE4#Wd9q=2 zB~5ifiu&3ZH5Zp3UdQ58+M4Q|&(DO0nEHU!XYu`fm!s6*68*0f)=9m$^Mz&!uGu_7 zzU9_ERmRuK|k+;Y(8BPiTg9>MoxdXPMctlZWRMhvxCki9n9jgefHUG@D50QMYw;dhJ?*Qczl3fXcTU0kB&)XY{ieD{ z!+!6XL#B)Llg5L0=}=dY<9_*=?>mif-~4od*HK4Edb!+qjg#|*e|69Wy901m6mrHv z%pyGKuJd4g3=JAHZJ8Xui4;po5dzJa{#c$z+1Rj8OP`d08Ba6Z)dQ89M( z(c;o~;dTF;l3c6Xz82L%cwcLiu@9&?o#mMYQ`RR>*gsxmB>zKQRrgs-d_ZprfYDS; zzu5?X$3I;sFUWX~NeLsECb&q1#<_J5oVBu^+xLP4_0X55mg?7;!}vEiU}h6h&qW-| z+&U-gX?y;DFv>d6>>=`3Lp9o9#YbtV15HA*+}!=AgL8#A>$&?FksyPKkqGl8=cg^{ zObKxVa!;EZu7_#M>|3momOWw-O@m6zWOwuqMcOy;&n^aFPLOmF>dT#=DYBWRIU97h7P$^8JW!<^> z*8ICa2E*YvCe=@Inh~zS%46a|vpUV2=ywJ8ovbAlF*CKE>o<{u=W`YX&|I-@%&5#t z=R0Pj_LEc^l=4~E#fSE)z?^TGsCeKHfKpIk;MO!0+thZns!*M1kRvZfnm?aaj8z<$ zG+$3oOh=VQsMY3uHMRO1F(PNad@VJHPQjrgp*1w}s3suqh>@Tib>?>9AOg8Hrc)6r zW3uKtXLwv9M|u3eMtmAz{|Cw z$e>`EH1z~J(=vK%C}p6VX1IvdKJIU5xgZ-JWJgN%0}yB8P|i?07iH1wH@vtE!|C0+ ztQW?g_ZOE6AJ{l72pu))Ou5}+A^IvAWWQUrFb!yx`Fu%@9s3|GUSOOMT!2Fo&nR1x0+y<+QDKxE z-^Ypnio|13YN&EIq6z_5Nib7JcSa(ppjWZZOC97aSlqR}_pA9&*!$xKhzJdWcbhHvT3h#E0oRT%7`erb$a!abS zE2J%^R!@*_TO6^!QWsvFV2G$o}j6&UKXf@V|V z$_|h-Ntdyv_dV;g-x-qeoV!L$h6~Ks9f{;8M8p+Gf+pPmttB`}>CH0Ce9q)b<{mM8@u*NEE8}(-&10gg zEMS4$fQQkM2H0RAx8zj@vn5XP#gUEt%RP-h}zfpUO?^h9*Vv; zvZI_WXxslDgZM)w#{YuJ{-v+?!^Ua%F3Kklh-7gCp=3E?#7!XxALt4z^Cf19LvArT z?I;Pg>r|Q?A&|s3+~A_HbqYIo^Z92x9!2MQvC=r)5ptE^@48x}3%-C8I$}A1dZ(=C z`($82C!gu9Sw=A}8{=T|IEc-m-&t$iAiL&3XN7g`3tx(Do1>oX}P=7`tP? zRU_oe?>~O&=KMRC4!+AOJe#I$#1401)R>8aX+&l`ws zW@Y6)Co=6 zuafIe#PPYFer zLa@UzKo>okp&GQ?HH_bdioT>6k#J%y^mee*H9|y^+-bwi*ofQkfVD{3MDVD|lit2k z(Nt3Td-h^;Zy(^4LB6prsib>6YG9is7QAXN-XWrw>L+Kl>_2)XYU{ldzo~G{u?2jH zkDuINav8Bw4)59@+t|XBA#pcn((a%c^3&9{u1|#(Fdym&$AZjxv#B5b2ZIS(JxztI zU>gx`M1qqiQEY_|P-Qw18b*m|g%k4>Pe-DeH>Ii!?~<9*RoL$Pmjx|aHZV1K+ejC< z8}XhPX!7a@a~#?UOeTgtG5=V0VG;Su;vQv<@MpEfVYh!pQ_sKDBCTHDeQ)4G5R*G~ zmV*$UVHOSJg;I=&42OYG#go206uRQTv%fb@VD&1FJ=G~KyJ#=yP}W}s+<^62XbWnj zWBZ7d@AMNPIlM+PA{Wv{YCc?u2DqHI%6G@<-3Oi+RVW>iHItot<`~FV%^oarl7zW{ z_3z9attWP-vLUIl-Ogi>5G3VReL0J5?_%S_bgK1-cK9NlTtUkC`XN$M=<`{(CHlWW zm#HVs_83IX$A7|jiM6*Q-Upq460<|YH%FNz-wD~0wkzY9AhKi zN9m4;gv?$&@L03JpQm=URzzo5h1^lFX~(fn#%=tv&-M@8S$&#C%%`9T;(`~$Kskf3 z;mW^J7fSSSyk(#znqQINK0wm{o{`B^wqN%OGHy?LaU zx!l~)b9(h+i%$&3ANihdv2Lo$qc2~cEFh&AZi{jlC^!(6{5T@{NOb&Lj%>`*&4LF- z^!b4W&*kom7IZ5({DduE20Rvg@EnQ=`oi|R;`dg7dBFOcRb#mxCh7?FJNkxiEYIgZ zO713AuK+R+*r%C1u)1!Ls}zVz3N&*uIq(`xmJMCG>BRQ0v=(`NEJRR=J(z| z+G!3rFl{bryMwU)6{Y#%*PSBLwD%Wq#+xFE$9kGz;~XFiU9pxA)4zz{LskqkvmKbe zdglFLNb{>k`j@1s{~l~p?xiKK$IJayFVo;vGY^wOGk)G*`w>So>Kd%IuoBX??TKN+ zu!7BU`+Ow1&GOC)FTktWt+pXb70Y*Z{*@Z?Jpzd9(*8^TW6M137U(83$R?%J%bZwS zsF%`iu8^3gg(JDAEa^wmRo%Ug71*Hd`m8cWFEhRsh|@zof7hvTKuz!wb$-4>1@@w; z<8W{z?tm_SsMTG=(`X%e)TCMXM|H6N8m+aKE#z^IvqCcH0AQAV(M3ma14Om8tt%`YOAan(3fBhO=`ykkI93=VnDzpOYCn zyZIE6B(us(yvDark(?152)S6L9kP^#fN{Gqzxj-<+eZT256|BJYncVv;!PzXp&K&u z>q-;BWwqo|Qw!=&D#hP%JLOt2B&Im(8-XmxFjO(4MHW4LTPLY@O+fL$Iuy2uCdf5Z-mcX z^EBH!^MB3_d;2Nz!5ObgHQ5K_d)0d{{{={z1cC`Rxmy8}!0FO2(CGf%!+7>pebk4! z5m2%4bg4S9bn3k~zuJr2=L+U`_D&_&6QetPaZO`JvLiWva z9r^4Y+~@CLDZ`E#bIY4%Kkp&GXQxAd#vmXHxyEvh?N7~h!*wZEVPT6ZgWQ^L?>j&K zy_{=#Vex?Yq~3b%u|qO2+!|q!^-k29nw1aQx@jrPE0zLVZdOYbHGfhxnk@h!BykL) z$+K-`HD+DlzxOUJ<4n^e=(>lwbZ(KQuv z5qc$2T5dYLJ#78x97#6fFT(3QUq8$Z?SVz3^rP@+?=?Q?lPt4TE`aM^Ct-BMYU&xj zewU+Dub)9G@Ue-5?vktShXE*YJ1gb(z?32XmALYjNroI;M?hGZS47**cNoIyxSVg- z=9lWtErL+R)SgVE^Y^&nisTpx0A^6e*kQ4GLIi!&&3Tod%6_b?@WnX_*HT||6Ci0i zNyyhk1mfH~edK)lN>jNED(?7^4!YA#*v?0@CsEktOw~kBR=`3IcvuigKwW_3VvX0H zsm>w=qh;s!=dv@hj(b|1hPVXch0~1Vy7VP^-6Zty#Ig&oy#78{(Z=raf(m^9-Sa7q z(-jWl%hdzLu`FqV69^&@_6b(6xiASFDtEiOKP;Il;MI~aGX4-!uG7l8unw&wF#)<% zcn#C9+G_tzu)9T)@7#*Lb3?YZhKBq?Ln2a#y5?KrkFno11nQ97EZavuD?@cYdy70= zmA;?bl2E9MZ^ZKBvFcHdtGU z(Hp8RRGCY(nfWYTU7x?gQ!qm)S@KE$)^gG@(Qy&pqt*WqfD zb`Y0#{=SnshdRj}E)seB`#8oS2D2Lv-sEFq*np0g-Ne{iK*;f?&JZig)&-{WLFd;Z zF_bq}#cUv{GN!ADx#bc^2rGW*G4%%lZO3wmu{NXBR2UbS=E*{ zO4;aF%24=_&ga_i;mr+2V>)^Rkm+2d=mme_qKU;&wu+D{Y`jlEra@sQwl;k)f-K4E zkJ&b*sU#u5@ytoy&Blb7Qq8r49BDlY=f*L-b~>oWSl&g%SX?$_Nd>>jmo*_*R6l6{DLXM_YDq^d+X0Ed#kz2;uA#vGMS1qjCD(=RYY3tYUheP%f z)=U7Cm>xJejb~JGe@gwEs$eQR+o>IGOpDpe=N~Y1GFHE1ulUPRVvm3|#)E5rCyZ5> zen!h(MZapSz3d=gsrdG+b?gP^Yd|jJ)S%bqaPnOo=U`mOaOdmy`3`@^Jq(2LBTC}L zklaYkckjvuwtYw%>q`o381BJ=%F{*QL9OS$u!Gm2m%WRJ{zsAc1%UMz!D$X+@!MAP z<|pd@*Z)0YUMEr^{^L_dxK$#*phsrq_SSNoT209G&Rw{>ey@5WY77XYL(SPUy=+dudw}lLv3EZZ zP3i@cK(+wfM}s+e+&PO|?|!x4Ru_ZOS~xT9XJ=rnspE9DZy^QE-NeGTO%L%lskcFp zfA*eR=~p8;v@Rcu`!&?86K4e}k7b-lUE(y9iH@(;o`<6tnerE^%>YG|aL6vs1->Cs zsEqbQ`5-qNb5a-sjLk&h>1)P#t*OMpCq>dG#*8$&uE)Px>`=P*!IY$^i0SIOKd#Q( z)*o2yQsR1b)G1IJNHCo;9kKfeOb-1LMojXl!Hv{zG3Sg>EA>Ju3R)eG*iFHG86<7^ z*2%&4gzzUQ9$n<}LqZi82wgyYbf4s2f_{k7GPT8~4tF!_p@S~lO0%yVtg zVQz(q_Y}%TG;*A43|Bp#U-JymanEW(qWH}-yN0$>jf35xC8Cvx>1Q478v*qvLUCZt z0=A^K-e7}pQanI@N$T17PV@(z{(C-L3TV1*ViB}D|n2ib!VB1wa7nfLxab=&AF%W#qK~4o4oIsoKJ4Y zLr0Av4oL*xmeEBVd617<-d;5oDTu0bo2D!clhwFV9@hJ|7&Yn)7vo>~HN zVjBIfbA)xrO826~{t~$8V;oep2Izorxz{iFvQ);ze;t-s?s&=VCCpWPajH$6zO6ZJ zVb(X)ul38E8FI)q2!pNgdHVMZIv{|B;umFN_!B$^CFG+>vmI<&TU!Z17pOGi*{A9o9d>Of^ zBTNBd%K24>8#duP3YizSuX4vQkrr2UzZ$4N_Iwt8i9B3i;S1aX!2>GGdNq`nn}Z+B z9y;~&ZP94QS?F7(9p|G?_T0Xo&o|><*tcfO*mrZ5$_1+{e;w8NXRXvl@9f$;3PD>XJvo#IE6k% zA72TG2MbSW!;fP+*z~sHrd|v^09~&y^A{U$x1X!CI7mI$%OGe-8FdkwYVp6Y z%ha{bxI(DH^&$y(t8bBX`|np?U3|~(1YOs?4)zuVBg0cjROG5Ks0~S8b3f~JB!@I# zB-F`KuZ2td@MOc!-Tgf^{T6#vWmTgvE({`R{UlIgy!rk_q-eVq{kYuQ4$QJ4e}&3G zps-;TMDdee5m;{^hbHV+H5C%8T;FE!2vh^OBrkH>b^i?l-#@oz9?Rj ziJus^X(GvGd&W>h%sU2EwQVG9b+jSxJNQ zf9D1%esckokxaFE7BzeLL*yBHath2MnUX+M`4|}#_FvNwX8q9fziRRH+qG8yyVSBn zp4_fLv(9?`DVi+C_s4tR81?^O7C@(}G0va7=}AsdM*cOre8w=#{NV+c4B3J z^bhJ}M%d8@^BZUTNGmV6Ci=L4>>x9%?7;@LuKjpI=n0Zh4ktwNfl`N`!c9y=O|2^5 z>vmYXJ7*@ahnzoJXbNh~zNtCX^p7_HRW5@#uvkK%dbJbco$PayD;3dn&39N(Bk8g) z*~B3iwVG>92dVE;Eqay&Nzqu119K2U@uXmIqhgi zDFy%TK;8mQvWG3?DWUx0i81D1#@!jL_|9C-iEw0YpMC2}&8;l*0LIdvz&WUw@<(Px zZ!6wa=3~dpzcmEfUhq;iTF{ToSiu-i{_K^r9z)%=7n>FT4lGtra-Urx4@s+GCc?@) zI4CqX6=Hwn>T+eKuyO97@B#RL6nmaasSr`{!;f9>5ZYC`_E6VRv)=gnf-?M;&kHx0#ONhdiU$ z3RHbl*`#U3mzZ(<@3 z2_4Cme+0GRAPX~ha{GnxdoR?NpiO^LRQM*0P%6F|*9u^uGuoKGocu{t>xEGRBKYE2 zXoIcre(AidBI4jN8&~I#op&`vhYd)>TSGNAUqPV0pCGaim|d`+9Whk>=Vwcf1c9^# zad6>d?7^KSd{T>RF>+uSs_@6S8$3Npd^jC=myb3`mmo2b>wcrjV`Q9Q(K0+26T~Xj z`rzNTw{dR@Flsbwk>()v_B3*@*4#94EI+8Althwc_77f`)V`vuyCx~-hu46~kGyI| ze_&o}4STgEi!Q^eAAf}mO0^n2Dg6YU)c;J;3;bSwA|;N0*>Q%EJ$reoxEr!pcXrY{ z2zha4Y(TO%aGezmUBauJVMH(9$$xjbA`4*cU;rmWdpSu(!GXK79Kyjy)3ydbPy`dxCsp|JhZrifrd(P+kt>rkIqn*KM(zLhdJnGqZb`rJy!OMMnH-t3 z`aW%xE=1_$a*IZ=<_)3Q$1Q-JB5vToWmwec?o=nSH3&V>r*ve?4(V61JxBTmi-L4y zqtEZc7aImkmGpSrb09#A zpb4w$VHpMJ@t6Fm#3#Z$oeA$LjT!$1U@~w)$Jz#MXjgN~VS0XO04AwgkRt2mu;5Ck zxSWb_txb|-O-8oH#(PB2`ha4cS39dhl|_sRrn_}DHB4c))T_b;ZnV&NQXf5|kBtQ* z*W4=^p70j!oZsb{Ue4027~>iCusVB>4@5x_YO zUGOV{=QQaik(9sl%H2y!Y~&N*^wbOJ{tXWStahnh7J*;&cE?Dcu-@{JLlSlq=r~~@ z?sK3YaSjxSbXS(T@fqOt(La2d6yB)vjq^QuY`Tc|IxZe~uI2kqCU~!JU%Nl z1Th)8 zq4&fHaMa+hE2l9CtF)RV`5?7xh5UuLg_nH(Fhi0OHbK38yLD6 znpDcN{l_$HJGK8@@|2X&UV8Au+ppodrhU<{93vC6~OjK zeHiBp3)>#5h?yluq$f z1wkpX!`z`bMkCP*VSJgJ3hvv0B8AlsO$u=e0lGz0-Jx9h$4Y~Uw1=2>>VxxVeo6*`DSOlHT%Y{K#UJ)R{_kYwK18lttoV87(P{C{FW!v1nOou3#N z`q`hud#ZpIn(R28ijZDa-`Szcp4hg{`IM&gW95Cj<>mP|hB$=`TVpVO5<)L+XX?B7 z$ErtgulnUw9Ql=G2@HRtuOQrrpNg`DzNxh|Ywb15k^#>u++?}#@oC&(_(1dNNxb`$ z;@h~$B|?p^QC zIHDM8^L@51td}-dk)umvwi;Aa9xNt}VGhe^9>ne}@9Um@vn_{j$D0ZCC%QdLUf*g~ z`*AesaWEC2*D%8y@}WCaPVgDY^T8M8{Y#^NOQZnULYHC9#S^frm5H+o;eSntfJmHO zIcnY|5!+k_A~@Y)ts0^vzeFKo|o5|oS&+R$nQ_7|rhFC#e@z%5R?vueLD@4so=RNq5n3W?tZYryd zAT`U;)O*q2;lHY_5fz9ufux?F^q1o;IBY&Kw3L(vSU7SvpEbWApO0PQAf{BoEp__y z+b90ii>M&VK<}uY-fAyEgN%*&lA1mkBsWSg#XD|Prqj8`J2WpsOXzrI*Pkr9mG{j( z5B;t`3#rR*-#>5V_%pQx=`neOif!i&GZh^d`8GfOZ+@KjC@9o{X*jFR&Ea`+|Ea#G zahp1Ru%7XB@5ouHuB9IJh5(>J?fJ3Ti7QdZy zh&D*|ao%P4Z*na9IWL&>_)W05F#)TJ@wmRy!lC%Bi`fF}z$p)+Dc)e>3O-j=erOfh zE9->d2*5wG_Mf;^mIV~)F@g+n_7-5w87R2V)N^bZ6E^gniH6-NDQ(ph>VO|b!oH*D z7H``d<>L2Z_=V2VZk_slMZ@Rkhbg~P|2ypQ7LtW4&dD_~wa@N>iy)zd zfJieS0)lk+s3;)_3IY-WN_R>#Lyt&zGjw-%cc-LuH$x4Rhxa?@{NKO!Ue8`n-Pb*D zu{Wf)^H|5(VL+r^HElmWqP)EN?}TKvFZ95LZF9lk&Sh`*7m(tcZQKJ~V@wl9Y~1+v zJJYYqJ?Yugft^QdpnjcxMIYnPE0>l}?WL%Yt#tTtYv24qhV6BYH|hb_JDdT1h>qau zBxzUJ7ZJK(5U3CdpNNnX4B10`122#BM1EJuyZg5Km7SX^1U*-wgVGSDdvULW75f=I zKmV-Cc3z%y>%FUt+HS}=36N)BL!|ftI@j~%#gl7oYHXmOIyGy$a$0Hx`CA2>fVyjgZ-2cos7<#Kiy!e$z8q4f)?~_$D*q>AKNk z_#>C+gr2sf=2IVx!=+arRJcdG3cdFp2&bm{WtUBDJYE{V1~RH>tv9XFZ*`c;^tZ9I zi8E~4mA^YQ2EJWgT8Hwb=p-1%fb4$4Lg?+7zD6W$Y|I-(GmXFV<(7Cbo{eF@s}M&2 zTR`RK9EpqeSgDs@^=T4twNGVgX5ttjlA2=$O;PVVlvGdZ@BiB!X(xQYOqY6s-eA$R}71G^-Rm|`4JH}k=|OO3zv-f$H4Cn^R83_y-@96T#+c$-MpiOl-v*W z*~zm#{ns^2swX#cEhebiCZ|?3|KBN_*j*xx($6oLSa~Q5wo-O}%)eR_^qW`JxboZ# z+fR9<$9}%_E?YV#Zlu|h8fo1ng3EN0aai%4L~%gmOyK3nrKjRGSt91e2t6=h3OZqr zse29WtQbTf`~D|W{>u!iWto}pM$C7hclP!~NQ7+>^Wt_f^(-0EGV`vz(NZRuMb~ar4eT!aRT_fZ%@hN%f=Gh-f+_;_1|Y$#B`B50Um7}bPBw-qdmkeY4L|p zp$dOHw#0BgO-r@}q4x<9Sqr$Q7h&pTepj+nshB?`wE(jJw8WQ`wQfTfvSZ4t7(qxW z4-}r|xsZ7}A#zyFd^rbq-|w^DJrOay9*aA~r#--^z9Wq=n7M9{AiMc$xjpV|*VA8X ze-m;sPmy4~4%_`*yD~#3Hd9zEH(Z!vd^jVW<2Rn#dn9066=c!5`|O^Bc6qnjGnIa{tH$QBO4Z72y0x4eWGX zT8W`5>p)bZI3h|hF=yEa1V!>~eG#6w#2G?Y_Sn``?jh^oOfdQY+QY#B3HYz#A!z$7 zdSBQM3O`(Gs$AXw2LFeE;VfWHEa~PNzQ(rh)V9 z+tVw2==E^adHaQ_2Twmw>(=(_SShOQr9ukmC*8Y)|M~_83qdje-JAX74p4GLd1`dV zrUS(%R!_0{A6rYFl51@x8n~7^yx6k%2~Pw8^=7G3>`o4RWyQeW$`3p&TmrN19d9vg z+~O@7=ojh>MBA3ZdW+}%Q6Fp9gTnTI;He>hA#T~CGSL8QlDcHoOe09QUCf}=rHDbz=c>IJW4cCn%3t@O;($EBmEzT%=gU_`Q*goaK)Q3gf(mGhohUa9#xa+hG%Z+ zJFw;3v-pDfcGEBtx;4kHplX|`WKudZ<%Bzq9-TaF&%8e0ee;Rot69PZ{p*bQ(+tXO z@xcl_M0$y@J)@XkTnt>oRHJZ8oVwIF6k?;Zg)l`oth@d zMaI{Nv+huCv!`S+j30Mz#Leh0^MpT%S0e*m(0^r-9C`yj=+C_{)PRZYW`kI=p8g5R zqHqSlD{9eu!=3LgQ$NT-M{C0A2SX65+C15 zd~_e3XK#sB5mOQr#8-&zMSx5D79N%G9y zp#KMnD!lO>He%%fwm@|$U#bPq^h_MJI99F%VM1cwZ10J3Tm~x z&m*_Og$2huhI!>+sREY8-WxY9p)piK>7C7B?D^GJNWVb=Oj^q{^cDG?2n{^A z7E@nzf^IJ=JDrGRIM+MXYW=cN&3L>NDbv}P{8}vo#=ldCzDr;mj#k-|I1~Dt>8?Yx z??!hnv=sKfSE<=~e`3V=&WVX!U}Tmq>fW!Qp?|-?NxkoQqIAfGKY9GJ>nf4#qaiY0 zYA@RRWx$06imKV%TkrU3&zBA}y;$^HY6G{(EXY24aPS8zNBfD>Q)>0 z<=vu&r?MKhZfj{1Q$$J8GDd*c(;mr!r&YP7?)RA*N4eDBz0e~&js>(`d5<00Yn~Gvav3Zj-;S>K$j+;hhA5^!+|@ug zJbV#*o_vW{nq|3DmuawGioXQLiKhu6-}82Nxx!;bVRbEL_+I*ARD8zEjevy zK^q2PDha30Arh`c3hZ2Sw6b=tWQ;ENoFgYm4N7yxi@W56F<3@aSj3zXj7?*@s;H2920|)aFWEaT?;n+#>dl5AAuTD?GKr zFdjiB!kHMDj-_?Sn^6XQhXt z+pXh)?CKmAa0=~|r)`5X2ua~ou(ij!+OIT@JMy3BZz&iWp?p~e7Ip3?z6_GDu(g{9 zEFmZJ_KhESzcs#E*M4*dzNdig{1KYq(v|%uBLj;c02M=%Bk|FiMi!a16OWheZ$p^G zg{zdphW-uQX~wcA?&XelO4jhKJS~*}U-d~s>ZiHFVjmlj2y}}9oSE~{V-nbs=eGxb zA|p31ozf}3d7x>-FdvW3jIK-m6u)`>%RyBMslS51xSgsx9Lqu36SJR)^P6CMf0T|e zI$)SP!A)O0UK2$8Q~$Gq^K|QUv92J%9`SVNk%48;gyX|^p;>D*_b7NX4I6J{vgUt7 zQ|oAuNXgqPHBB8M$$R*5g)c__&xDtyWyiwrXG$Gn%fG|losj8_{6wZ&q1g&q;=hUi)Qr_6^V@Ys3-Z|6EMFAh4^ghwg3`8m|A9g#nWIKM0o>A=s!%^4SnGt$4sAiX0 zOrRU^gEkMY`3I}V`;8aSxLy6?C58DN{@=I%+U@x$n4`XAcf@yhJOvF%Mkqnn#9w83E2zNUH_{$|gpG?Hn7YQiEZWp0ywa@kfS7+X$pf+rNW6iDNCv-jOllB6pFP;fpMse556?GB9gx#bo( z_k!$ND&SQ;+F|J#;PP7S*W&Bc0|w{irV<`rd%Ev7=(#CFg|aE>r)as|HQcC#8;%kL zbT-pL*5$uW$$nB01&&|Jy;y!wm3YC6e`fk*K}tBm%gbx_PN`s5>HB*-i=C3>)bvVE z##-uupnh@we^PYtqEu%q=D%XrEqlDyS<;5Zn41uV?Faa`eZdL+@^@{w*qAiIU&RBq zSDSlR`K>5J*S`|5p(A@a}g_^mnC=DB!kBt7>5*Rw{~>y`yn zEW0@9g&w3sM9nRAT@U>vzzH8Z1#>4KvX|T3eTVpnvUY8mJjrZ#eaJ~Pt0emwLR?0U<4bx)E+mM z<-zVzm@soJ>}i^?%w6{Jt>^SY6>NtLL=!=G%us4Cix>0bYC~HU!>8|(kNRutCdWvk z2045)AmdPp7Gan+c&du`ipln)#uh?P6-6+!W?*wweKyGQ@9e|!gFi&@r8jSO-cvGT ztf*gH!;ful;w-1X5kT_E>Sq6Y-!DPNsk$zEPEqz-bJSGAm2Py)XHAY^Zj72ivoWgn(991kNU1BmqA4p#QY1!Y8gk= z{d-@n?nqmH$cE@K&$+ADPQ5z6ht{MrsneJD86ARjXoL|5RP{#!CgHtj^ zTvuaWQI{Xjuc5LiR?7i0a=M2Yss=;5l)j0$U#{#I@?K9xa2{Py57ru-VRRX^aFMuL!EfW^ufrgHJ55e_++u#jk5m z^G5$@N}`Y$Ocj&}c(Jz~=&mn$-M=^g@ZKFpzcFBIuD*becR(0%ZwIW1_TF{_FKGH9Fh?CbGYH%kh{AmNiMs?~JN&x3%x8LZ z94(q0aWhiH=pjH}_+0>pB@qM-9;}&zfYDv9!u4zT29J*CvzQ|CUOZJJdv#5erT>Lc z_=ow})P11~g*gf~s-66=ch z%yqTtk?3Nhqw@hbS}`j(o=|2 z>+HJHw>)LatDu*j)h#&{50@^tmJ+v2%i_VF*Ywp6yWCA^)Du=be5owCOW+FD7nKMA z8`d8$ZW-)nzsq?7x3c(Maay|j0T^xH}{53T#$oFG)fS!AL@cx?n=woP? z+DKc`K3yoDu7VzV3;ZBrbnD;0FU|(mC$|pgZl1aatn;2O0U-1+j%Zedk2(J;PUd%; zZcwX8RnG^j=OZN<$>she6Xl_f(KDNu{vJ9o>B$8k zAiF7(gLga|HDsF!w1r)|5>`JxSnIr**9I@HNfG3O%Vp!GrP>wbG2`uViD@@Ed}yy1U<{+1Lcg7FTJTDa91~a6u8@;A>%2974Va35%tSD@ojrcaN78X^^?r;B_5_kwT><&=063- zl){Xqnb8+MP@bPl!$NIZ+iC{Yr5$yO9S0m9Gwb2wR}-f~TFC1~8n%;}m}`RI**e4V z@jqE>Npw+IEVS+HLFG~5xa_jmT)9@;NKDJNoxXsG5r3Q1Q(PPv7WmSIKOceznPeft zBkX&YxInXI&{e<9RWfq;ec7u5dz+rzbapzk{I9`&dHEl$vub2$Vu)ZOS8r!8@L97^x}Ompx3`aVgEZnDTa38u;(O^&CP)!Nxb+K$ z-(V8G7kOSZoSlKlGJ6l!)|d1gHzXP;&N8+5|XtNR03JKsNw&U0p6I zx3+uu#IDuds+--cstf>u4mblV|4plYeC9eLQUNYoaX=RsC-n3ha0h+Lf6BBD$Dzk- zRh+8J5q)H=^JnZ0jo5>66FBJe-S=atM`Jm=k+L*7)8ngylC@XbQ1C`3QMb+3n#C1F z8VRoO@Oc+J3URZEm4Ys2;=|v_8h|<4(0^-%KStizr@^ftKTe-L2GogkDh4Q+`x>Vf zzT!=IL9^qHm6KoO55r`$CJ3Si)on_&t84yihG`?WhoNu&X!(r z@`O^ed;t|E)QB2QazU~B_lgD9#F`6ZQb?#3BBM`?;K?t*Jpl(L9YW;b>E4cwEBnS9 z>avdFE2VibE!`qFr6ss(UyP0OT4@T4=hF21ZTQR7FF_Ncxzo#xeY80m$8xZB1EDqqJ!{uyLXO13`o&tcWYI&BLp%-tSOADl-o$5`R`~enXsJ+w>3a3a*|+;V?w$`DKXz!{R%PPrpw#7EBqv0+1; ze`WBoyb~up)`D?u65r+B7!lFT$sA9K!`(`f(nm8cZw~4HcEwbhF~;1G|Kr&EORzrX_o! zA1SjppFW&kB=|GY6)D+g(+$mr2hIXo*o8QdYHRVq-5*5stW7i{xU>o3I5z zGbJPoUw=GEl)EHnc#Xe=$66t;BT#_w#k)oJ0F-aY7oomj>UnVQ3?};kppA(&+@AS% ztv%9ZS_*SMAFfb}gZ8YgQEvK*nX&iQ!+pzrCZx98kpOi$b{4yit%=9*oqO6Kv<36p zX?uUDKLh@eNmg4lp*h_Vp}Sb;b*4ny^sEZ+R-~{-> z+S1lKwxRuwq}p|i(+P$5uk3?XnLaOs3@{}=vPpqZ0C+L zBh<23&Zf(9uWjm%R;2`9otJ>SbAoNW;l)qe?sYEPa}QHAS_l6{G5bJo$jl$N!Y}ErWEz&U|ooNV2x`ihVZ( z=ITSZlbD#!Bm8%+J99CJM?z(FaL$zUC~_)!aSFU+x;Myx%FMo^?`Bjk#ROC!-oCeM zwx{daC_lA3ubax9sK$6TViaf}@{-bFRW|VqdUVe=3&#taZ5ftw7T;%YX3)B^aM{vz z%3a5)stO3Jsxz!6aEtKr(|RcWfVTzE;@NNbdq3_CEmK)*F;7gsEfj_feA}?4a@;yQ zBSBmrJW zdF9yKD)Fj5z)u{IW(!9Z&|_3zMTGwWzc<4%yjV45oW;C){=_)6lE{0*ACmJ5Heq`m;)ulTM58yf^;H7W4ndSoS~f5#TVFj@DyFht24u3$pDZaYG5CoNGTv; z%*gQWAi*luV6pm_RM?V2-m?Pj%T7+}#`K3I{`xUYuM4aA|AumYoY_!Ru%#1Z-Kt7q zj2fSizI>s1AQ+4Dj>YI)FqUpNdGTDja2tBo_@N!1-=GZAs?P$BzrOv4T3TM^0WZKC zSJ0@LUAzsQeqi~JUl~PdCp&)kx!$z)U|vCKcx-4u%}EcA@>=VqC{3H^7@k+~k)bd) zj$UaAdkU{$^5fd6R*lJv~0kB5=~cS@sy9QabySfcg}T-oqS z@?VVqi`r!F5gC|}D0a}U=abX;)tWG|c30F;(}K-Ohr$e~up*YyW~-87CRIy?$Z3L_ z)woT=0r6Y;DKz*z;U%OABo0wxopX0RFoC3JBnh)K6Z@-4VrUr{V^}u<1ZeVPj#w0{ z)8ns{xske{1kgC!CnJ;KL*OqFqUAI9K{chE2X&6@$teHm8H8r= zcc)G7l73iSX`2o%`3)B$)F6_NnLkXOe^kq?8Qp%6l;CVc1nP(h zuG<@JBljxSnA_m%sG}|Vmr_#7ve?DQlEme$NPC7RUvX#QPTwokC7*>Ih#z}*igeL& z_wrImV@tBR+|%5jhW+!pA#f-wvt0n!aJffBFjO0)@V1fMx5xMkVVIINl)>uls@ur& z8iJjH?lM~%J?dQjD^;R!aOd{+<;DZ4ee&);YC~qj<_%|lMX`I_nO6XvIo!`8VTl-@ ziKZJj)<9(F8L@2ttdWAnibYcIgFb=BZ!g!A-9!|dgiVq@ohw*bZyz9Zg(*_<}sD+hdFPgJV`lf~5y!t#H z&!)r+?h~-nkIpn)Id&vjusdAAZmC>Pk`uy?>I}XZtOLR%7q88^1^_wX!>2^8fzP0I z;(kRtuTd<&-E6i_W%T~^7jU#@M<~Msk}W@y@bQWZ=D;Ln->*l1@#8TPJdY&o3-2H= zi0KS{^5s0@RI%&v4-1Yk!RNP1dC==V2-rx!%3Xe&+K+=aHWV1;C=KujkL*$_+PO+r z3-qj8<2ko#_$&GjnV)*&5g$545pe0{wgq@ya@=2dN8-bgE>_G>9tOP^rbX~&o9K)e z4)^}yic0EP+x=w{cqv)^P?s^x%#86jv5F>^#Dqb%F*2~jI(Af{(wAKU{3iDGXj`S* z-}S>Muor^Q5jwSGM2?;GLXzVaOVWBC(eR(|t2WLfFpz-PNS2h<>q%c{8j2Xq);jKygtF-x`9T2@`Iw zG)U86hI!a@@%`*R(+10*df#v!^ui_x6D3%anoxTbi?{lodHR8Qw;{o{3Xy{iXU*Rw zJ)7gTYd&G~HIO;;HdJ9ZR9BO={o-QCInX0&jM?Uu;Y=xJW;;2^(SzmYi>*I|9UJzR z^v?V(Ha0o~Kfo@_)42HzZ^rC}{)>{}Ekkp+irH_GD$7|D2#i$5&6a$_dt@Q`#@9@( zVoxDKP4Qcn!IvEFZsx(vK6E{Lf($%yL;+j=$icrY9#ozocv0mZjC|dO8$;c|X-Xck z>7S0ITL5Zwps9nf)Xt=2t?(u2@qXkJFeJOr5b%AaeP;RDx_uodJ9gD!jJ*LX_1ko|SXk{HcpYL_IqFC0L<`Z7Oo+srHayy0Uf3y(CS4 z(HgTGZ#9V8F6dxhyE`Sjk5^~e>#Le-;^oJmSBdXoz{#sndC$_QKb|q1`)|f^hQoa& znP2$br%Be8Ikc1(ijyu<4ua)iJG|OkT4Hc(mX=-P9lL}&VA;qvS#+C6M~%jyT% zi8YW}JIyg6H}3~cN*AiYZE<-c9+7TcK_AO<86wlNE$?Yk%;J1=xaML7)^`GBXQ?)O zbkZS+T&Zv{=P}XOMafiE}qd;N>od`|~v&#vKr!v*v%{4~b+Ta7p_` zB$^&cTu%N;!`*f)zoj=E`}HYUu~NSyU9}~TPJtCb63O1kh4GvJ}ghs=Mun| zi6ii31)2QGIzIB=MM6;Tu3{%mq6}S-tbeo&{Pg8nfO(U<+B%19!M+85Fi*MuyuSFY zS_3CIxRKC8&I$We1j;XQJb_kYMp%d$7<`^HW>a0U@Qxop_hC=x#(u_6jJz$HHH1{= zOl(k5g4yXDEncS0cO5;^?>=K!2bIf$)qdj+nd&J14&26VJ}e&DIh=3(*bbYs|0r}5 zVglbvcjI`JtygcOu_6oiyZ!j-Q@Fl+*PVJmY%#6p#m4m|wn+&yp&(c|h2KZdhRf7&-ub6so zzddFhQz-Y0*LNO&uWu$~dJvN1%jGPeyB6i3?*vFlle< zQ)xM94hZ-yE9Gt)>a+eNxM&yP=-}ScvMC}i^Dc>v1Wxt=*d_8RmPVQ4j=q#45%2+$ znZ5M^>!3u3Zm4!tl=Psm-=ymX8lXjb*+WniorXgZ0hsN>4&Tan?N)e;_j8-4s5ktX zp9Q#ulA?bUBLG_Az{3sqE8wd~J5lx#{Iaa&k(8Mox>+4BhjHvjRpOj`Iwd3bD3IO)@6k4vfuE-#||!2&J)Mxhp*yv~j^9 zddN9@^cVW5M+@q`Wr+DMi#!0w?e0GJ0q`C*?TKckL+B)(q|et`b*U3e!5hI9Pe@u` zYnMlzmfPJ;KvDV`KI6wHML~DU>W<7$@DoWrpMDs+0=duTZ^ixFe}g_fJdTS59c#c& z-P*o$aqVt?MMArhJoH?&e0B|rhw4YYCkqF@43Fh|?72TW(p_+P_czILWoO3-;+?WT zee4t5_+s>$$cBZcgtzaXJA6&Hhe4xx?bLEGKvkuBrV38*!(~1JiPA-m{If>FEd_N{} zzZNMWp>gT32$J@iCavbB)R(NUwVguuvfdCcQGNr4pZ6veUNUuqCTDxvoKIG(tMcQ!FNE(C_7@5@ zSY)l2l;C=v$6mNTg5I5hnK+I955zxW=J7UTgp<(A=sAm8h9+#>;#~@EFSS zB{~#}>3YmBk0J0hx_e%NRnI^uXETT|zKga{V&YxzG#t2afM!mzyr37Amg!AZgyE9O z(s{f&PBs@ifGQJv88{h^aAd5!YFGm$wj0#DRNYg}Ka(;_W>0KXe^Yg7#QG`t=kDIS zdu>I6Ni%$2Hc3Q1YzQZ&F>KCh1%WW3h9sfxK0X1cbqH3%hKWuoYMKct@iRZ&=da;EuIwEHRB`KV3vu>e;f}8t1@~ z_2)PZ!3yw99r}wCNf{i65dTo{7&>eh_>Y*a#QA$~tyC9*zv^gmgbL>*Sj2B%`Q;`j ztH}4=XU{)6g4=6<9wjA2xE^REI<~7}Fs~_@5W+^g=H{<$gYA~n``>mT?VM0Y{lzgU zyX+g)n1eUKyxbl|W)1c?l(orfWhi|$xiEI_bJip(+CDM=d13zEe>zRb=t-7$ew33J zw#4V*90qX_{U3)?YZP^@NR{-^0-S~(tG$0Ke(O#1JW)(xmDB93@{Nm8Xie2KV%-p0 zG?9Gza3Rp4hj|naW-opxaS;{>enb60I70c2zZ}%1kv{?kAO(N$|3x|ggixM_4D+dU zkn`?J#^z!#X6#MnBsl@qY|j*2o?U57`no>eq!}<*XlSWf-+)&re(R%sf+{?Zgn*dy zJtdXk_a+yCW%K`{pN#>1`b-kjJ)Wk~z+Y$~jX}Zut5I&c(bRJ=iI8 zh(`R12&{F#aI1awy*|kTk#i@ekH%Rg+EkPFR!qZPO-dF&Gkdx1hfA$kn;y(oUg28t0Ejb<;`kLyhwNzD={({j9p1!br$$?E~ zOQ5(4qus2FNJ^{spNKItxcSX#f?VAktV+90Rco}&Vf5p^0deF-gW)-ahtSQO_r^Mo zhxdf)qPIf_({mTWdDfVu$C#O!Q*VZS=S9wf;o`@hH(_e-HuJ7`PzAv3OcKdh`HDrE zar3-k{bEs6hbwi?HZbuwV8E4WC+LItHV5t&cfkg~;k&T7-05!ri$sdi(Qv<5`|zQe z?H$-<_KNrSjIo)MgQ7*8NXviae#v!wLV1TdeesStBGC))FZmd~wsy^S_6?GBR_uDS zMea)(`TM>&U5Moa(XM}Yz3xtv_70)Dk{X|u-d_SSh)?4oZIVsCuGFSMbOS-*ek_w< z*+v($pGFzI>jdk4%j$K8yXmeHAd|6Jf0(J0%SgcV%pw=<;vJ<{$HmCkZQQc2a{g@E zYs}*VvC|}V_~O4~K~FlxVtauBcvU9o-F!+;=*nh~<5W_3-4Jy~VKL#xo3L=Mnb@;PtGCr#qS2 zOQ6%$LRkJHrC1Vfvd(!zmx2?SY(!3C8rir6OoJ=ogINzQ!~i-(XTiVj%QRZ`yD%a+ zns5rxIlR}IivJ~Xt%n|?DJD9cXxFB+>b;TIeC%D?Z%t=4u2-dw^{hN&R)c{slb}Tq zoS9U!2ugt|=w`0T{@I?^WKxt?`z*cRor9gaPvXbQMIp73d&#rcl|Zb*z{_6-VHZ5gE!We zCd~p%zPlqnFvq*Io%61NtoZ7;Mv_W)@cunZlVJ*^FPu)@-ox`2zFID-q%<xCWK&~(gj06fT!$RtAZ1&D3b@7endG|Jy ztR@lnYI2)s?;o7`G_opkS1~P%T!_&?ftzCycaJpfvv^J}sk@?3zc`~Kf7B+eS65PN ziryYRL!7jCAh^v34TF$?{S_3n}Vf4$o>y9fyY+D}|QaVxVIWiFjVJ}L=sF46~xDJ$~F#7spI`XX| zt>MdY<5zI`bWMRX{$!TzuCD?G z1G5KxIX+d=e%B9m?c9QZJ1fZH_KVL6Fn{)$GkUYZt#AMz2ET+HPTeiZ9s3OqsSeJ` zr_(0_CL@3;H#z;~PyMp?nNjJZkQ_q=9yV8-6E|Tv<UzCGB9iElwug1Yq?1^L}?~u2Ebz`y-nRc zpr9~upMNvROh^arb(XF_xNRC8AOE6@02xS46ve(LDVDk76ZcqW@f)H&g_dwpI7zummZfhDJcIPH70WVI`#w5Kzbw`f0J z!gkcTPj&&gGGc1$zVTZN9oO%T+rBmk|2VKr<^5EUm~t2JmLQmQckFAx6Jl9@gh`jU z(pi;$uW}XHk4HB``k&Q{!8^YrT{@S(9axiK7>GmG(qg$AK?pl)74*VE8O zI^*cbYsqIkDaKufBh^>V#8$pIjU=|g@vjtq$Fk1fuKBG{o&e+K*7pK~pCNx);r~_C ze3tt}-Y4AQd-G#D+J0g+(JyM>yS(vLv&?OO_CC^SUa}I2i3bwU-r3v;{55YquqvB@ zRX-UfB=;B}a3+-fFdSZ<9e(jhyVJr5Y20O@_A$GCfc{ox#n=9iSN*xJ_()_8rfL&F zEj?%i$nM&Z!oyrlPB`_4VjVXo5DdVaZR%h#;fPP59|);0=DMyS)jSypPOm>#aWt%4iw=8^J^r!1w?EGgHA04d09vX%zmq_;NTt+$lD`F1 zoktd64~`Dh={R(;448{rEN@rwvvXM{)Td>}cI+IW-p21@cH*M<8e6;Om*LVM8`Hq2az%pIYr9fI`&8jB{Y!_$}W;w zlNzKEdbpc*E1`}~kD}LrcS$JIJ=eSCd(vP{B6li3I%{t?W?B%PTKTcR$%tve30ptr zwA{~8_4O}}d7;BBX9YOPV!Zffo{Voyi{?Nw?^(YUT}|43klZ5| z@VB$)wu4d#Q}~;+o9MBXv=JM*h>+*A@`<*Ydn-T|zewXiwVoe=J_{LdekGZ10HHHN zlT0+K#cMB*=Kfane@>)!+fuTJHF>=EEm2A!k+Qnt<9D5e2R1h^9STE)NL}h@EwPCo zjENr~STXjyf7DMN;n&)do3j_RvaFqAfh^ zhCR?IjCzY1sL+x6Q!NiQ$f}KXJL_~6bKHma0C~}j92kyi%+Dcgq#8qX>KXX0VP6o? zDPk7Hh|OLGmm>a6N=Bc!U1o53U_1T+mfk4y;ejKQR339 z%z*HM!G9$83UYf#K`MmDG}q5U9GID&_YYI5hEkcQD7#%mpQ1uSJ=`NBT58YJ(d}Ll zR0UbC2UObM(bg+I=M3izNx=+_d*!K={gO$?nSuL_UYJQftn$d-cEG>LJ0|`dWqy{f zLbF|x^X35;DI>wA#narhw-^RXK zYYhNc&qeNaqs_ENN! z=$}rWARbf&mx+ZQHbr~k(Nulu1}r0fKjYKq@yH9U)Hcicdb-3MIu4RZV-c!d3MmIa zJ@uwxyEiibgPQ?9ekiOWj||ytpEs-k8({k7-7X0^~?_THemM^Wa3rr#M<;lDB`AGWD;*IA)7b`C#MRg=Haf2S;*ZoL?nAvqShPF$v^xodg9tHRK3)2E|e z;}$E-xc1s-LCtj>CNvi{q|T88`YZGtCDXbGorm@=ci02l(JwWT0*?f{=lo&Eud?{J+R*c$(9nmR2)4;m{DSYq?n`w9R^Ye@INNF#-H6{-xusM$&i@o^m zLmeS-){hP1wwta#^PY@o_FFoINIU_Jk}X3Dh~gYdw*lFd5(susne`QbQJwF}Fg3%l;Ws?EJSMF)Ts0C$TQU zpCkSh^E*VvX%rGCYaPr#bSl@I>*4M&G!{wV^F9{nPQD4Kv6XEk10zlQTJK;>zxIZL z&KJ`5dtAeE+4qJi69Fq#A5NEBl@1-5zZfY#F1|$=%Wjj%c_V3?(JnuM9jZ3X(4aQn zCr(amWL}sc8A^gWzT&y3Cy}Hn2s#OiSAWg{j`Ol20bXK_*wj~W5DiMtu~5y~3vzX^ z!BTZZ7R3<~aNe*_X+v}WJq5=N7$V1vCo$bR?96t=(_Am(POo0S0Pgu%su1rMTRi9* zoPl>0zoKkI+FzU62n zq3kh2`5LXZg|(4*Kgl(P<9!HmW_4G7VjD(M92S6aoVwRoFOLqCt3Zc9Zn z#_p|KB8W+EitH^l|7F%&5XJ?n8Gv5|tE_<@&e51+-=kGbJW=~}T2bU> zEnnAx^OfSJaMoUC8GI0KHH4U}4;jSku1Vo_=bo`{VjLMd2rBA--O@Y8obnC(R!|x> z1PdirA7(~3GTNcC+f_{X@x^ZfY_MhwB!^GJp}UiOMt_87%-^3!(g+q1c)KZt){3P? zW#1Lx^#}cJ&Y51De;wqUh`%j1&k$AG`g3TM=dCO&WMhA?XxK-b=5>QbJ0~j)=`}@>E!v*sHIdc)65D0f$w5H z?iIb-ag2%$Fk0iA-4Z}DBiL9f*J0I4NqO%%pBY9}A3L+C59t~4d^u1*w6Sz%at-F0 zW05FMbC{}6_7`n>?6ktc_GEs^=g$~i>fd!kS(bXU?jim)Ft^El~MfWQdpW^{MQ=o;IZ|K~Z^bzYqJd-J=l z-QWBEezJ7tsR+qwWCZvioWEMgOY_UvM7>decSw*h1{olz9>Vb=^&}m{B~6KbaW&@W zH2Agm4?zR7S|sUen27BAjT3~~==EuIcck>MMCXzswJ+^q%Y_dgI&a09J9p<5I^X7X zsYRIAtJ6ol7VM2Ol{Fj44Xjz;F`=<+iWrgvOGbX#F&lfnchOUym}78r$!~Zs>!DKV zdQ~S+PC6i`pp=|3NZi*ym|*AYTUdD7iQDYq3piSVwYD+aH3Rd|PlT_yAkp(-3jJf;(nv<5gQ5)F9 zwid0|W1ljl$kkdVR)T8jG4=1LnHKS;DN3NnYiro(x|&aRxG=DzDxWhEG4oE8ZW*ck zNx(0jmk3GLy)-y%mkE6|OjSB}PqCxTbYmX=t$Q!6Wki0q|IGLi2DT60anPmO(sd`c z7H=Z2(SMOT`*2PgAz86ihSQJpMJS!)mf8XB@Bc`qSt3raM$)Yo_8TX}|1glOhTt%) zThX8K_xm~H9d;eprmfs+_X1S$pFsN>ejW=o>Y^s}_g*JSV080KFY|h(fZl`z*F@94 zx2Vy$sO{7-wEM3K+dpP#a)NF@S_#Pcm5KQWsNha^6N*0|KbpDYALkNe%h2u8=3;E& z*fyB&COTyO3so~%Y#bNa4(QvWXYw33%1({y6JCE5EAD%VSnmUS+r6nbEk`*$*ZHW+ zZtG+<%63NGTXWi2(_p4-T=&r=;_O>+O5m?a=bR#WcX}|_9~HVlEqx-EuQ9ND#B?9~ z{->{qQ;^Dy>>Sng{`_*)y@~_0vd;BVPC*twkxXF}KGBex8jD@2ge)}a#}6*bfj%AO zR)s^Y@dblWd^&+0?J)%)*XmXL0;4A5<^!4Z-45sLiX( zjhTs6rD^`@YNSpcXi2d2}W*_!up=Oq5;xUl>5N!k#al^dZFyEAw_>#+x8$sPnPFt36g? zlu8_u--WOs$4<@7wv@D*FqX~1)~zJYi;&rZboHl26r2>>rse}SLJ z>5~etXO}CYvRp4)48hywX`olG@mffpvYER)J*|LjB%zh^cQR}mZ4F2HoK!E2kG*0O z)|b7Yrq=_$>9E=uYy%xzTY<$r!?V6L+tSHUN<Pde4i}&Q9i?y!Ss)B#OHHwNt{F2&$HcRZXMvLnMbylACnr#aZDLngtvb-;x0wV z8ei`vs{P6Ii#Nad?qa8xeS4|U>C6IA+_5qJlTKt%9*YzqDk#n;kr~FT>l3l6bo12u zGPm)iu1}GHDygh)JTOhBb<3u{@1EyzM`$D`MZ<-QJ6S{%qgSc8^oTkmcp4Rf7118$ z+1Q4$JxMgM^-v5F&9LD2k&~#mx1il!tMA{R!7f**&S9H7Dyz&<=G*j2 zpLnde+LCaH5+u|oQFOzoH{KW&b!*3Ki%}e39N&TvAECgA??rz|12-bQIf?qn09vA( zbrpHKG-hS}KvuT3Gd?8S8Fle_IlqjB29ypo+c#kq@+h`qTMtD(SQpsbHY>|3RHV=N zBj&j^p-3UhkTN~6ypI;x2j|qDFKrlEURj+(9q-19B=0@!pO@WVqu>`HxFa%0n^ho& zwZzZh<(=N;P=mF{cS|mpiOr)a#1KmFEXXk}3L!G1QeEl{QyZHl?j#Tow(7MNuUGiK zT^T%WkqHz{FTd>IFC$jan|8kS|4Msh8g|R@)ne(U*q~zRJMv?$^HsdAVa=%uL6vhp z1?|g`4zB^`-;NB1R|B!sN52`2W$+`~2koL)Pg&EEjRL8LHUer>M^NlL4l4OCCl40+ z{06p3mfC=){AbZQ#ed7O4ZJ~0P+b|bR9n71ur=Rdq5vChLxFZaXS35u=WHxBgWoCu zoKa103y}ureJL;&@XOx2%q9t>YT@23>;(b0I3$RIdo5^w@2%L2;dlQLt^1>1P3!{_ z7uYs7lB=Dz<)3?DZWQsAr7^K1fWJaDkn5r0&Dy###a(qMlFg+Ut*#8C%!-XR{KWF@ zOw$i==4Vq$H;cr&TssuFEq91SmW;@UKTNl|A<+WUF6p}9c2Bb__)BUfn?|ou-YPn* zy|-+o3u?!q?pA~_l`JWbU6ViCW%^%9T{`~hzm<}JZsl*Pzm_u0mB8Fl*4t`D=;olO z6x&#t#m5uTb~f^FQAAofd9U07mZ52tZwzVAWho=rZa;?p-Jk;#SCD&1q(Y_&#no_F zE)VP0YpT6RK{HN|c{f4bi;vMoIN~i_wwDe8PtMyN$6uNcOvTf92K?&4nkbe@jO!{^ zIBe}4jec{`K12LfuKmxKMZNd|ZTKo#N^D~ERSw9|v9ar{z$n>LkCd4a{Xj?UgW#yP zf|%fM8@aAM0xl`{cG^?dy~40QHYgYGHl#QK&|;hZ>Pjm3HJ``i`zVS;?iS0}?=-X{ zC&$kB_g^Grw=X|a(FvXh?T$0|HNbgPbS|$hnE*bbEKi0+Ys+YkfY)I* zzTj)E!w^=Mq)^N4y>_1S8C&5R1Mii>)PPUoyNG8+tKr>qdr`%5*u=9l53sur7>Ih9 z2Y`|eUrv0Rx047SVc#ctDt$%^eY;PV8mt2|F)QWLMJ`m)Ke(JPN*1vG6*nP%;3B7f ze%+NUZxXlb@MZTcP5!iYrfG8Dp=bmLp(6q)v23u?thAf`?w)8L*4epCzW#3)?iK=U z{@aC_gpKhm#9C9ab-;}JqQzzwy{n%{DBT|z2fs@m;pr@x_06a>cDzDlL6wP`QL5Cv zBw{z_^W*M$a;^7lPkqt3hwm;re$m0hZ!h^z4twg9;S8*&Hr?_wmp`cEONp9Bc*(5~ zSQoBEXaIq$u7TTGb{NKST+K)OYQz;Zu5*JKy&l?Eb_yXL3@UR&!66z{m!OU2cY0V6 z5P@r_0sQ#Sw<_M2GEPjT*RqYY$EEF0UR)|eg0artd1oT;s@6J!o)v$M%JU>VFGe9W zIViUcb0~R2%}m1f-f}2##hL1Xu-m`3!J}+tylo!U_Ri~Z+{#%x@59c5n8?UVN1su6 zt(8%3Der`|SDXd`|1T8{o*P5ppIQ0lE6A9crJEx z)|PQp&ypwvc(UIHNg(cfiFWlodCkyieU2D)xpryfi<}ftEB*{U$|4<)%fo-Vi!G9& zL7L~qb1(nnYj(tKWlf!PI5Rj9);O*@5r`A@QVh50@VL?kb52OE~1-A3Nj{ zp>fGkr_>+PU{0MRPb4ll%OZzEl9}LOq0BqSJXheo#vl;lW}PmekZO>=p+d~TDsoq; zeK;aFg2?W8juODVT&dy>mW=wKLUlvN9jI`CQaR}^-#H1~-AntP9;nKrfU z*JyIcZmDTfTdf?3)hPiUn*fu!T;y)5?E&l3PZc~&=w2Cp#ZH10$=&q3tjN{tvdQW&6OYM)wbqNM>{h%o z?QX-jD*lF@XYPgdZT2m&JbResz4>Zn^2S8!hR=>1K}@PDLfU9vg8%Fz>09F4MX^)q zT9#ClSW@&~=y>}f;CYRrx~Va@Ss%|6q#1lfeaL4&N?wz6?#W3f2yk!hP%_~zFRcxk z<;!>zE!cR$_y~Uqg2=K+-x$B;qqEWQapWI&e>*b9QVq4?>*p3n2}@@^p>yLsBr^** zYF4Y0I{oSP;QQG-g~iq9T$V;H;FyyIkx(08#BJ&$V$U9lhWN8gFYs*e}> zkH6@Bw2&OP1a!B)j+!j+P#I7i-#^qK>)Ke(!5QI2R4oYlsHTF~8jp$S^F zFd12O?xOPMw=ZAEuMZr(4k;c_eEH5sMrG3CjZh1+)zsaY8V5hEHdYz>;E9kUbA?oRzPgxwRhQFu@AR~!!oFCI@u8SU z=nO8U*GRuarX<^Fc~oBjTH}nn^%i=@dypH^=JZ;;zWckwTu@7L2*LhzdQFFpvx`e* z*BK+yiC^RBuI--3^M3$#4U7Ljz-}Wz%;5VMvruDJYC)%G*Z#2vtlPRTvZ(I{dsZI8 zpM$Tg82}DmTQ}4tVbh>`a=4x2YqIGg-@9rKZ0RD}8P2yobn!!*Sjx&CBx_c_#i_*Al}?))J1 z#Sc_bhq}wln~yg922krDxygIN%wU;wkEZd;tZ@Oe?ikSgi#rY=vM3z&U|#q(Iw4fb zaNFU)(;^U+X3gPc*70t?vb<-Rd=;w&_#ZEWdEX?`tpFmWcuecwILifdk!+Il@1j*L z(x*G|7x%6wZJb zBo^@?MPjSfjo%O4g$WMQ7?#ddI4QdaxJHRe5~nfOKri+(bVn-@gL(E`lkIgV-evxH z6{4rtC`fym9Wf)2RllE9-t&%)V0C^!`ZN58Kp$rse&x^V^<@l9XdlU19N6Orn5MhY4#p<-9!vsgHwmvhQH- zYi$`5=dP1v26^-oFN8&!X?^ko01LA259Yx84nHLn@zO4h_lLQSI8tZdlPTsQ9K@A@ zDq~-HQ>}$j@zDjb$lh0}4oSIyb9qeJEwJ*GiF6Ug z5Zd%KqK~Y~#sibTQ)dJ;bu#P+1dc}Kpjg-pT!TL+SfQmQ>>PefsPDNbuq!TqcB>)6 z*FAasl0hR0ALunYox}40{rLp?xEV@Aj-OY+TT~-ng#qX>5WT=UmJB;`TU@sIDP7FD zKUtB-}fjs}ksD)b-{1zsGd|4*zE)Pv>HRk(>DYpTS{tj?%~t#DKpy z&5yXpS;g8Ot7gt?5}L@nJD<(J6)<^LVnVZzLnx(jH5ZbcR5@%%%}+f_^4Iy(4`RYYJzb;HrSQLwKUnysItS zd4u3=Jr`O~9p`LUF}7EB^~Pc25wa1zb#e%8C)mjx2Xx9$R`r7V+O4n zeo9o)Hv2W3wmtpmcg>4Irxq(hZp_T6{R9niV z_2U6|mZU+H2^Hm4it&9t1ymshCpY`k6OQ)4f5^2bsiGF?PFv?c5YR%?yc8PG?Dm<_w)=cjtfcSq-3wwx&kCaWi zRGO`p%0r=OEb%U7nq!UAnJF;jR;6dv)f2%8(%LpY*mu?{VeZ*%pK+XY|DJ zoO=Q){yJy}pRJ%ehfaW9r=dwS=B=rrhggJW4jcb(T(<6>aE&<3M>BfSP)h{uCYB77 zFkWxTOPgYQV$=dx;t!jm0=muBnl|j7{R}E;7p)||4IpptyvYCjbN*NM%Hqo%S2G8yd>~qK(EMp-%HNmR)>^<*`1B$v<JJD*ReyyYr z@ajdr<2r?vP2FcWlx#MG=6?n`4NJTTz|T=;51j$;VVu3oPd5H-nZ3e*t$&Yc9N{*9 z6?|HKn$4jIVb7JSpV{gbSmVOQB!ba0;?3KjPrd&jf>t!*e)}8*o{3^*-oXfZBoV}c z6_7wYN~Ty)`@3MF_%M1-R5{!GbzFHH&%&{lk!W-X4VRL7cT+6sN-fffQG3lu1w{zFm3XAQWHYJK9{p8Z?&)E#C++&b@HO`4L?+rJP zmBZxyPpW9UL+EH|+{?E$zVwNk`eJ92SAsVR3FOyT>0?Y&xvq+}Qu@gT^!EYw{wGP! zFCu@%Fj)uDN#ELTG<5XJCT0l$?~6ZH(c)RZuJ_9}K!m>PP}}A~dhWw=_cktN12vc< zGzEs8$<_KDP;=o`gMzYBJFnBf2S)GEPA@J!r!3aT&5zZ4GZajS12hw~WUD8rI=5_Z z_$gzYpxSiKL38&G$f%;7qyZ)7Y6f1Pj2fLPxM|#x$uQl^LLH(t+S}5SVo4}+P3iT_ zj?%(kNGy(itUVSfgc*@w`aKzz%q5{Z32g9D?WQ_`HZajVUd)%TBN^Ar@JaTePxxl5 zyIQ1W*^=vHP;2w=6lA8M2nQ?y&5pMI%`t(|k5QBbWcFdblcFNywRN4NB{Hq5Xa#S1 zHd#(u85LQkmD;oLRZc_vR*JIRwBW7;jjT)MAmV#v6h;wB@hL}`{WeyD{4g*pR$o(v z`*R1JNCMP-5@lgJSnx)(BR>`IAmYHcuJ5N>%{j3F(9mP$AxB`P9|!50Z0s+dn(c?k z?P$fuE*=5f57ohNCdc8zWP8B1d3|jTYE*J=b}kgD{e@JtJ0D$5d8Zff&vcASyWRc| z-7Es*pHB;56e>4ZAv(&qAJU`hZ>Rpc>Y5p{?Pi4HsxtuqEUDIn&&^V{L7tBtad|7j z^={Vtj1IncC-))ubtm_hFIazN1Y%d7M%?r5!BOImGur)6ns`iSQ>2l#xYnCu-1;tn|qpv(@BO z{w9*?Jmf*PzYLZRn zaqudWOQhl%z6x;A0RDy|`Q4z3Oz1bBB2%4K+N#xYxE-V80Wgb2z1Stw$v@e_$$O#) zvbrXZn6m|FJc}`6D=?9a5sAj1szJ@oN1cSwzvAb}>`A705$`HHpVia?ULwQrUrii_ zk>gmd$l|MXxDk`=xK%{@`S`}0+z_F~%A49M){-MQZGfc&X_h%22{YMkbtPlVWYib0 z$L2th(Hz~@HDAx0qfdd#1mdT?3S7VJh3oOV`)Vn^EsTHL;~hvQ(Y9D{MZWJfm5Akk zi5)zTRe(5m2nQ#-dt8l=S|S+uQBI>HURo;n*1j)SK2Z@nVs=~{r90wCA{F&I4B{I= zI{GMD-kHf^_$_9S`Q#0hGQtr*?@tcwevB&MjTF#D!BZAhfI3(>BB3}*1v-ENn=MZ=QQU5rIm1J|=19%`4 zwE^Dzz^xYW`ZKqN^twpko)&PGvZA3DZ*+cnnwU?mfM(O#%bn?R*$n(Hzdrcm+VQmz z#eG^-z>Tzu-Xd?GzDCJc1)*~fQgQZAFLH8=YYkeg6p~Z!`Qay>Z!MW1&)9hl6Bg!O z$8@;WJ1ayPwPgU3Q38H8Qf(3so$_JbFXwb+9p;%!$bFuyid5X%Hf;UB5}=er zx}C0qM(Tl(or+^T9rvRQt0L3dV^|1CMJpIa@sSMLDRE@^*`!AzpD8S5eR!+7EL`q>Mt1%=D?WQQUvCMEMtIkThl zT@TmHx^)Y901kBJk>--M%uLPeg^=^k&L{=)`6|V@kWVE-z@$pP(ZHAV!HVM<*Z@VY zmPky%CFAW4lwYsAa_bmUw7F9~LRO4iPZA{5M6* zMT7V>t>jLuoGIs~ETFZwd2EF?$>>$mt{~l4GQ+U)$&|lz?|E#fhK#;>k0*cx#OvDT zIg3Z>`pJWf10sr1RpQLJSAH@yLQN*ko8tyoT=XFqs!<C3ZylKI-`Mui!{%FbTx0q~+WUmL2 zLiuipZec?>6&K#_L2>t6~mS@fQ4(6 ztX5LOmc}j~`mW)>P_L`pSR}6Wj&3F@WM%WUT{Q8;`?Vtd^sa);U^Le?pu2zZsVn$z zz;|Yw9nty=vLWePFJMFdGS+hv#D;VV%A2Ns=U(V|LV@RZfK&|aW8LbBIM9*+mNThL zKKz6}x;FrBDEi2-wpRb$lTE1YBICu@`jWFKdaN-f)@bvHbpjsAS_=2{vfJ;}1()&^ zKh1Z(cR*NVFur9d8Q-iw3|512wf0|plYyyWv+Rk03;Y{>G-9{(|01KH%n#`!1( zU-#G*u)bxwoC%V30`5%tmK4#m+Mk^}NZij&fpw824$plfgSYu_2EOwD`m6w(037>3ISfSULX4aXnou(b?U+i{zQHqDo82L7xxz-K<6r;i6f`{yrHfcJDAQ}cP)mDLxn31_5{@ap65Z` z3eU5_@QKGCo->{Qd0{RY3h{OuSJkafyIX9Jkt<@1VGbXGFefRu(m^ZR_*Ce+W3_Ol zw-Rrin{Q;-A6jp$3j9qUsDK-53kV37;xk{>u3N7cjIGl4ero4|60VNC+|60_cXW{o zJQ||OgB5N)zHFK=c6(A!$xwFQ@H`_>2zR~zUGU@PH*piSx1g-uqeHDM0dV!C-YSM7)6+@nkiC(1pXh8!7+KM^$H=YpVf*+3rZJS9d zH(%ppy|Zn&G!?e2c=5mwBkIp<^p5!`;~r~fYKzPD)4udg&T%TN(FTltp2`Z{rbt?6 zd@!Q5pq0R?U#rNqzKN}}#~k9Tj2i4QR%IZr>>>$=`7^zd?nr;DNI&>aKc@TE#gPU8 zuw9cBXza7~X+GOG`b8jYmz^p`bPZ>%oY&xsghAee|IIeqz|))eDt!n%DPU!m8i( zR2}C7h&`ocUBj|UNZ5<%Xx6+^v`0aDmsK*X(ByZwr7(L$J;P4^7!d!#Bpq2j_S(qT zPkJ__9WiMYcq8uT(8jJ|CjC#J6;IVs5C zQg6c#c8pm?JqYpGQAtHObh4&0C$@z}^Oh)@f%Z5YFCMGs6*8)Ta=@Dqdn=Db4Xyyi)R==|Eyr$F|OlGGE|dhF{)#q zkJ8Y4!Q&@ZNZV+y95*9Z^oA7OLQkX*lQXobqj8{@P!*S53Z}DWZM7NHIkrq7ZKS0~ zbcynjG>Wrt@^vRk8i`{gj80GL5@RCs+%l$lg{F(_sh0?#A z3RTHV;cCX#t{3E5Yvi10_lz$?E$^eh)Zaag>&_6T({>I!y3wk=5)oNKRP7N1fNVOB zEOHuobZ88$=^Xw{mc~8m%P)Zr>F|)77{hVT=Q-7F;|&9&B@Np5%+;QPNS2>0JJ>8a zC%s$v2+}4cV698lyXz+s2gR3dwa#V(n6#X-DU9XohfOsVySYcwzw3U*J7+ z&ZIHWJl?Txq6?6?ike*lm$ofz^qkA$Zjz`&GEemlB~kKyDt9xtMR;IhP@z4g8)xAmzBx#s1?^@+8;p(nl zkKpUj?lTgIWN?U*h{(93VbisMG%U&T79hQ@J~|LeXU$Q7O5&1GFEiZ0mQMBF(OPZZ z{ zC~ml(+&*ALzUc?ATwO8UBq;9s&OcQ6=lX-krOjZckLyC=w_|k$FjWV=JAAvz`12BGHEwlit9^S)9D7{gw(3|EN$T&2hv)D4OLir&+XjCgGoj zqqh>R=R;2#df+>#->-NuSP-71LE;`Y<#sVGEPV_jsFCr5Op`oZaqCEY4z_Mx&T?oWEr3J#Fsh1v@*FK>X#GMyo6yV8)!=ao~9t*!0CwR%ei zYSY59@2cY7&-c^=mQW;k;1)z}h>ozpv?6+LB>zCB>*+s7Bd0tDNPeS~l?A3!L27yD zLLYCk`JmOV>rAJ{pUf5SZ&nnHn5irD?P(P5ahT>E2~V~Ay|BBP2_bMTu6_4Ml zt-m}Bq$UR^sGszhmv4l3+edA*LCsL)$E{25qruGm=i(%*DuJYK!7|EQ>wHrhe;8)R zgs5(;Z&pAgf60G>m7}^}!FOqs6x5?kfQ=hKg(Ui~rjuX>@wfLMx}@H!|3o{s1Y#Fc zcc=gGd&3IOIv3n4i0Zy1TVkt82d0_p*HYY2jxKBcPgxH~JYKcpZNpM*)(zmil%$h_F+lBZ6^` zy|?u?3bpiEvXO%%?!8VXW0*wHR)e zz}e5oteen!23Ar)Q|uD_R#vvS?$@txYKjTw1;w(0-`=owQZT0&-3cQqamE6?fGK5$HW{xv)>6@88MGe@*Skz z@#^7XoJB+jqTA9H6lwELipeD5axh3rXGs|DX#mtT5fu4^qvzYsEs0En&3)0yyavO);Y}4c4HNM1J*rQ0{8TI>>}Xc^#|LJ`RkVqNZ+_O`&p+tR_g> zm%81b1Cyk3ed!lmV5mHi9lJ;l5`H|j5=4lQ>~vYla2ZbG9}!l9oD8IIfWWt8H~rJC zw9}Bl&SaY<6hao9I7rOz)UXjpv^nI^B=ZIpHiDlMsWc>-`sfLUl75CwikLXfz3dgg z%D6bq2O;lr)EsUXIZqdlQI4uWkT%|ce3ANaWM*h5Ii8w0v9anDKqo>&RGSwE9}00Z zjxNDg9(EILGqYH0+h6U=hYT9->yB;v(Fa!s%VvlVeQQrIhD_D1v}`WtjXPWKS;bG0 zdU`(Yt9d?gT;$ND&g?5|$_ zE#P`TC;G>Hve|1Kzhxm>RJ5rHn>rTUBAuK#6mMwv0Csk5q7|_A)-Jq?d$i2!j2Vag z-qg*_xvrk7DU(H^e@h;(S%4}jsg1w(ebn@H8ERuaVJ?x9r~v0KbgW@wF%Tppea+3m z7XRMdTy1)RBXKHxXl&!c0q-}s{LX)=dvuv2;>>o7J5IbVEI5g37N>H#^^F;>ooEtM zMb{tXf_SO@m$>`HoJ|=gGHy^?bh@9tjJi3n~QI4RqShbB}84a?E1F z8K{27F>h|p$;^qa_60XJXt>=hcsVyv`JCovnQw;v4oV;SzgYm&8Ur07=4yu8q0B`j zRw}P`Yu505zoHf1#KUAD#$hHTL{76++*?P8cbHk2>74UBc(Cx80?D{x$g$Rv+ry_|AU49UQMS9{mGh|DMZH`VmC zxaaE+|Kf+G6Mm;y$1&q{w6%3eUgSPXV@+(q8JXLwPKyeuB{y7-47+vcWujmI&h^v9aT4vU#t!GE#4@85q@i*)S>K5@K3 zN;C?$F>gtK`(-=*f!=iwp54OO`(!HQ*_e#BCLb;TMQ3!j64C+o;6}>f0ZUKl*_l!1 z-p%_ccT@F2J8T`dTY>r2J|?_7DSL+JNT12n{X#(V-QjvP9`f$bKxJHr$CpG__iFHi zWSyXnr#r4RxL}`)r<+ebFw?NS{N*!__uMi2Mrezh!DFcTne4U7ERW-J+qal;cshBC zzflGsiTlKpGCHb08-zpT$lW)B@zJ3zXSMn^8*rRw=ir+L)J80Kst!QN7=$RP-O^Gt zI-WuVpx{y&cr}-s2DIMai@P#7RcqW#B{>~zl{n2x*5_)xet1==?QLYJ8noFI-9M|K z*}H6jQcKYKc|n;o{1g*{NFw`Uqa_)pIIP$D*1hwC2C1nneY1`MPq3o6*L|R)rSVAo63=6$}Iqo1i^`VO5l8|A7~sl5l0d=Ho3>P^ZIspG6d``o=x z?qe>W?q{I6uU*-6Tr}s7cX$g0biB-tPvk^jC02f`u9l2yD}gnA&Z5I5U4|W3Ip#%7@(i?H8j`Oed9VlX&Eq{v9oXd z4U-qSulrSFvd({c4?-nRLB_sq_l2NQqO-LQFpADzZEe+OMz{U260*~@X&9A4Xm~;1 z=ZbO1ezsSejoU^s<8e=-$l~JTInjt!K<_pT@oDxqh_z+)Mm_twWbhl~+02Rj%_u%v z`Ka+2`{wZY3nkDUc5=bJX14!jtv{`4xN|p2Tf8(Ky2=V$Q3d7 zgSf-%fxh7+%>y!FeVU3Nt1B!AnYxd!oy>5+-^mJPfWHI?GM??>C-{U}nqnCTgs}G1 zRAUQA0{bNfri-tRV=XT~N6QU-Qkn|0C>e_Hx`tD9_o)VTPYHTq`&=1>-m?NGG}zJB z?-n2jp#m$(kzw}K7C>MFEMV8cX7nDbh1pH#Vo z^7$_^G(8JhZuf1qkVi;1`4Do9`eVW&f%jK!gOl3e`Eld9{LPYtNB`~SE0bRRFy>oW zNRM?bS0eP7k{jMcto~^2!lAn!T#V3c%)7WU=V^72@YaT4<1oDT(Yf)ZIbRL}eH%AF z?C7$gL(fz~@$Qe3AJ8S8=+NLORHF~Bj$0Hee0ECkmrOi&pMDp^Rjs`y$?mAq`${&s{Yhi_qEFqtI8hlQt+c}msx)&AknROP?R%fo%fo7R~ zPMxFv(kj+`I%AsIZ+%2tsFC5`HDSvA~rVM>N1kOlIr__jVxZH?ZMMA zRGXlcw+!^8KD|z2WEHs)>5zO_uGOdRbD3ig^y3jMfY)=!s&aA>hAd0aSRN-a<@@#1pCOV`^)*8FH(J4fjsF4y!>=P z$X5n(y`J666uq|oh+h@>azxCb1<1dQESlbrQ<|C#Cx=;0Ag3aY; zm$Fh3bNVdjZ_44!*FnG-AH$g!$sOdwd_76~7u-L<#`e#^ovhQ!eS!$^3n)|a#s(-< zHFKq_tK%Ad)CXG`^4nPdJAcC?VA!xnLGQy~RSC~+vhn0E8VE7EwDBSY(;c*{o$fny zr-r;#m!QO!onhSVncuo3MM^r-@J?k11lHJW)~G8ddUWJK;pEXade@^P&>w|^otlrr zd6UkLahu=ujkzTMi~;B0J2r~$TOaSmsGyIutd16Bq{0(lIr2=u8f%4|Tr-hLvuuVy zSr81dM%N)BclFK2U`5<+6xA%&@%9D672*B-1^=r+%E&(qfn~BMNiwOCHz>nN?JCrxW9?hR>R=cLcHs|BXFa;RvHoayB+(&|0 zPrhkCsrR0g-|cvUA-lvy&`1}G#Iilz#@k<&NzKjTUm;Y%AAo$c4FVY^@FGrcOIayt zGfhl?)KwnQaI$5VkKvSQwkmZLodg%Pfvf+5&vM`lg@p8*n=mx1ig>kDateAm8q#lm zc4gg*?Y-vAh8V^q$gO81GX^vDSeB8=m3@|PE>updp||ICIicBMHdiau2{&1IOQ9}u zPg#SIp?M#1otAETubRb#J+g-o8*%{UdSBN&&CM9TN8Ji7feukZCMe#c>yiv+w0+vW zS|UB-!@j@e)Z9Y_*X%(x4*X^39Z4+eBqPAB?p}TpkQwGm1JRBuHFB*~W))h}8>6lT zzZx7$d~jgj$J`>&TINr2eI<=jvi|^&d7k`3#Gt~^qhi7s+O{5fAza${F=@D+A@H*0 z4>@eDS-($e`O4Yz_rpieI)~R~nTeKu2&mCJ{FNJFyth4aWf+zm-d~RR0+rG7bejwF z`2f{2p1u5)tX~SIVE9=XKc{(xt zRM2O|5RBqtFZjd(?@hSzgd5_Bp#nSzUWUjBK}v^drc`=AZQ7VCNmEp*OAro3D?AX{ zaz+-mt9|=<6Z(XFXy|{5XxTfCdDbfE|G4}YuX!2s4-eQTp7OJPm@-G`dzzeSX0Sjw zn|U1)-95oP=cYyqM|yqCi;3}OgLc~?jU-#iglDR{-y^S0V!RKRo5x$G?gTxj%`Kne zn0vzB;m-$t6)3sJ=JesE&Ark^PM*)oMh#0zSM1j_gCg@3*#!Pm^K3`Fv; zxb=w>zxTR1T~ersaX{`uFIJuv8Q_i7hVsUInvlxe?-mN2grzEIqNP9+KopntSlcgLW{_*4B2 zv$s2*-Ud*#F74ExYumMMT`O%Mz%Uhx3__l9+!u75^l;l2B0kI+Yf=bn{D>Slp#p zr3ZWK>nP6tsY&@2`M2YC8GX`x+l+usTdhWe;i>#T*vyItHqIfsbu$@B1vj%9+}54J zLlhuTF)_^d{A61oF!?9=@=q}vTPe9xmU#QH{^Ny7+_@^v^w-HTk5yFO+~B%d2CB%g z>Jj&b2mc?sz5*!DWoa7-1WRzY#oZkOEKYED3&Ab8dvJ%~?(PujSzB)-s*Zom(?;8=7$bNciT|J6`C0Od=x@w}!dkpjRCmdCrR3ZO{^SWTjBX zr|%Gw$XX*qZI{%E_tDjuJ60>w=f^eJWo<7gbb*|_&daxkD%wYHB^CEVeddxiD176w z&4IJ2ttLIUj=r1W9J~BhH~HxeGF2vdz}nz!F2wLkA|5Gob*UB75Dco+;*Euxu1t9P zVT>dBE$*0mGt91qBU0$)G-n+*d0h5@NcaW=YZ=C=ZxiM7JTm-Lmfs;JeUUQE%s$Zr zD6#rpPBzg0M5UVhD0U|HWSKISC7=>??ww>k->I7a2#=)dB^z*%>qLLVBwk!dCq#K- zGw{F=dUt9VS7gVB1$A~qrq&fcG*sMU)KeAK5G&FI9B_U)3yN-q0M$$oCfL{}^E$uJ z6Pi2EtnAl7WJ`lN5^6omt=*@W*a4t^A-f8ZR#>EUO#>@G8SFIHYtpxvbCD7M62qA%J09%$R&7x0T=XuvK5rBJ{;v(TR;(*}Ohh9g- z&8mYwWR8$c{XBRQ!jdSb#Y?u@)AFo0DXcPriM_BNctct4I^dKD- zm%90-v!qmhlAgEhQ5Wygr-6FMc`5G`_BI2Jo=^2lV-4$=y{XxvZMSw4#(STrLB$D^ ztTob3GU%ju1ax@#m@@R|pW6_)dH7G1wVK>FQ=YA>3@U)XRSL`A$WD#r8+G76Rkt z@CL=YB{E@lM>VGT#1{bVF@pN^TrD{IeBxh5lA=9X1OR~&jLSV^({!nd=c)7OK+bsr|M$CHB(st?Q|fr*RJ1>*}Z=r2r>-Y6++egQ@?uC;qJ zop_X_=RBSXv&Hxr;kbUa-u4v3p&eUveh? zk|#mb9z8fnN1b(@aX85ln@F!KwCeMeH@ReIltU?lBki)}j=t>P|G@Dn<8mQ!MFa@!KosT2;Mso~34IT#6Euw98S2yf0QH`<^|m+^TOJh1*IFC9i6GQB%^{UH!Bkota)#UxqX?miLD8$W=>nnw6!U z0nB=yE$WH|(}lP?qQ~52oUWlRMCtGZ4paEb#?=P0{_2>iXaTLZ_=ee!@xF!A`2!~N zkMC2OJ_hD*NwJNp2r6sUrt1a>1zPTmi)g^Gx zVK5~V@Q|V)(QYvRL{TpA7+BY-l!<;jA=oYL4bwUkvR~wRH1fb3k#)ki!rPVkc+k5r zXi%O&t2XDBCn~3fup#*vHH0ggyqy1hk2)-73Ba zhWB^(btLz6oIXF_%S)|5O;L|@C~G*kUi@r6RulQ;4~tysL`6-#t9HfL2hdca>_8t3 z4ojbvgR`Phz0wx)X2oMYt$N`h`xI?SnY`W=sgZR(KKU`JY=ORD#X^R6bcQ%Ud z4t6dH#h7XSv6flrWPAN<8)pN`Brzu`RH&d+qLlvVqM8Z73eGCLT-SE6;L~KWDG9Q$ zmp2+^a-_;Pdnr`mz4goBw;hS>3{!Pj;*+5f5eh;6Js+DV23YTGIR)a!?#u==!)-H# z1Oujw>2Yee^V5a&kBC-Ke&)YdaO2y8IkW=wR;2aP? zg1p)+?uSE)yoWsXGl<*sZU*!`YvZpdXYD=RkEx`RyVs0~E!dwd$M9uI^Y6`O(CV{t z%|KLdCwx*MGxa6-J0|mnkyG5NF*-n5`tzgfmy5^72HQogOBsESy7nFA2TcB#aAMh^z;u$%|G5%-5?KobwwqvL$^7qp~U>mMTM)kHU& z?G=SiabIfg<{09?ESO8K+jANq{u1A^KO@=ZKk&$R#-Z7hVxN1AgC^*iV~BCj8MvBc zsZP^}XK5Z%c&^{&aV2?IVxRl)%1hmbroSO83VSSic9~$pM|eyQ?1ruN17m&RR7vw^!1uk)5-4nAm%|NpDo~=gRfDNgrbf zUtl7c9N9n<2|FRkKjb|_GLo9?DV^97D&m=w4gaxAp1vmUY3&x(3nc=81LU`UjHw|& zf)<4M^>i-7-Q3+NM-%Z=^YdpMWnh$Ugo+o!v2N*EI-;0-?o*S<5Q2clfb?og)e0hg z((rW~C2ozUgD2~jnim13H&^vIhcJB+^&LREmq8i#`691^X!G;_-F@fHp80t&-sCCr zf8O*OK4iRBI*IXvM(sAur{dS0zqFu?B0C_Sv~v0}{+(PrD+fzPkeD^<;59}0O}On; zetZc$4=Uh(+-KS$Clh(fAs3m})w^Ek#k2TavVa$+SQ01@kbgh6E>Ppcj@MYix8TX8 zO9?K{%ILAohsG<#eXy`uwx?NXwa}0ohLUMV$)K|fVfxl7fAH!a@X&ujKtt;4Z4}XY z<99lxyp4QR)9drcs2)%#Ce2>xIlf>4jgn>$t&w}lQqxdTy2VqLsdVE!=;O!P5!XB# zqOGQc2i@Rtf#t1uro#ucuu|9z*aP$-A7e-z5pEVOjsmuEUsL@h>F1woE6~-$OKpp= z1uq~`Y&juycS&uM>_6~^35vtN89|fh&!&mlo6OHH2^8}L56bdH?7Jh;hrWlh!R$@_ z>dZgpRV@w>6Dh-gpYoX5$E=|H|3|eP1@Xzu8CprlTPYJtzj*K5S5LbJju|q#Z~bo8 zimqSpaczwI$aK@bhRy`6BnqF9;Q(dELiP;68{s1d5XX?oK0UsNS|8kzuz{+G{R#L- zq7cwaNe}@k$BUfQxNyF{Q}AY0A1uZsHqEG+J~dY>Wt`Q%ZJM1ioenQV$d?Ma8GdOuExff0c19ihZI!~2Vf+q|on5Zfj_@Nm9hO!)PD!Gt_a*;5jr=RlIaV_t_dRd zXsSWS4fv#5T4v!_FrltoIoa*-3MuqvE%?!Y2liPVHf7dB&m}GoiwXtr!TkJ3E4V1$ zO&8crk>+arV!0<&Giid>*|%=V8ubrYDuYc3#87l`Kb4lN7_m1j={x1Qv%$8~b)#rl z-g7gs`H^ZEun^65cChuqr1nC!UvS!m!{&*TIXffmBBsNLpOc7>L8*Vy>r*K zN1z@g4E?|w5d5g~HoEhsBoaM$l}TsG>2W+$?;iHI9$ZsG7!-OmB1?f;zor6Jm?Y(0 zHmz6Bal|}9JYCt_8T~k@sf%(t>4~b}7Vi%LAzwotHN|fAJu~604;aqez{4}c1!LG4AY^f|-pr3YCHG5<~eRKF* zRdF%-93G2_#%%wbwhUMeTs{!SzXl5j23j<=#E1Ni8|qwAu*J@X_K^(Jz6mmaB_rl9 zD40mZ-n^aY!#aQ0MTG+l2olh;Fa_bzx-fflp4`w_|9{nM51Jj)|1r!xA0UuC(v5X09X`+G#Mu@b@yd zkVS}4256-M#G#*Kk7NL${_+PIznDf;z=#X zXM4{Sb&K&SQ3J5vazd(nloKd5jzg1ZDIm`csp3GpNqO@U6g^8ZEfVw>uy_+Mc|J1p z*K+>{p?rN?(7{75Yr}0lBR3IbU43X>j6>Y#2ujbA_UV9RcNXp#BCJy<>KPeFc&54u zyN_9<2JZvGP}R>q`|KQZ(8qV;O#r}4sCBqMRA08Uzb!m?@_7!v=N zPVp=)hUYWFCZ;)AC3XvAQa3g@a}%PPh!e! z@AG+Z#JcStgF-@s2Zf9bApHm)G}PDKF3yKEmYuNojPc~IxH6vWY09STeRB6emuuvW zjK7c{*pi+tofYrhy^5iq#0X&0#P)+EG5NPFVJNR7Mr{L07)-3Bc|v5=)TGY%Slwb> z4G4x+?{v9zS~Ew3Trz)iqZ96ZG;Fz85^!_ba?n{g9W@1AmNNm5WN=j0MBo0)ALBtj z>EYJ+OTIA;{zfL)vsVG~b?Aa=oF3@e5VGVD1}5l`q`Y8`7NIjs(mIWhP?Q9~2&OEM~)4t~+-mq-#jJ|_8@^qt(Js4=4DbhJq_L`sDnivM;G1XO{E)LI@rxD_ILh)d})QRMzc5h}v zG@|z0T#1C7>kcOe94{Vf*GU;mf{1oo_*9`j!*(yXC8-+ z*_#>1AmDV0{)bcAt;hoOC?ULKWVCJn`y3fL;&Cb(DR@@=G{-rl*o*t+JQ}|5`V@Be zj*u0LaY9A*;RCC4X}o;_N~@zs#fFa5PUZkPrX{u@0gw}uS9|`49G9ewds*beeX?wpom93@@>gn{%LD(cKjFCfP#v+HRtlepZPX4#8>w4J3-;KY;`P-Yi< zKdAZ12+P3xKF^VC4Dv6>ap@)|OH_E$=j6}A z3nrUqNauO=>$0a-w%a%Jw3``$Zf+EW3`mx3muJ{N9O9g}ZA>b;@9%Y_R2}h$hQJji z?^0tj2vmYEXPpgHtI{)->l<4g^Zalk>8V4n>pf3_VzPjUw9X$UI2!sYnwALx@o$tE zB~@5xDy#b>-YiQz?gx|7PCs5=&MSd`ZK5DnP!8p1X$~!F=Cx}4!raVdF^u+d=C*6^ zMLh92{ZsqnA=QCdTIAN|4tM89%>FSRZ&CBWO07^qy^`)OlnGt zvfNZn1YeoK+MXu#cwy#@9<{YK*xk*VOp<4Oz#17)V(y8aP zX+722U!aIRJ4ZBo2#S>YR=T6T>Sbu&7l|*cOsOlgzHSiTD?Qioxb3mf)^gmY8gXie z^c$m}q3|8RuaYwI%U2ZAdDziNk=1^!808=;-ueK;m*g=?3qDC^kIi3S%XzRM3IM)1 z`Yy;j*v^@ibq{9?>RXJ72lfz32CJF)uQ%HX)|cROA%)Gp1GAPBM|JZB2n15l(IF@( zB(m`&b?$qGh**IAc!vzGF1%?IIIs?T-?gpVxGHnB&`=;RkRg4!%w;lHX6oX;w$iej zpuU=afu6#?-@1OW1ANRpZa-0^Wn^S|*~{~fOZ?k0`olR!PQ9uUOx`2T{tz>as#n;S z+4!n@TiC5*$UF3?e7SV0$~5@%zPFwtZfKveh_0I$W`Qxbk~-(hX-4`^i+b`Y@08o# zEk|DLm(~@+XUy{TCBYmxVU`JC^ir!~A5p&gc5yvN|4mZL&(AMD2BnA{FOp`6a%|LI zxkyLGbo9q~noZkKU-0Ne&R2<&^74qx%u{Z!H$IRvE~^@qYca&eop0G$qXF`H_4ST} z!^7kN8%F>cRl5Iwocptf%!B(@CfpeCHeo3TohM2PYmc4H?_`dE^j5=xpSNMti@sm8 zMYTvjco)U#Nu~WEj8e4~P{uvqIF)*URmH#p{N`cR-S7&^Y$|ags-g`mMw}-HR)^D? z79Z49tv1M|p&Kfb4B5D`LptNUiwsb9K9-VjlN^7)< zDud+=(jd`*D~cbn&ryTGn=x+#lXyuowxa4`i%6%VH4!y-fi_vF@lslx!diqeS^kN_ z4-3rHiMr3}Aw>1BP-9OYAQ|pY=iFa(T=q#{2ANy=o`oTtotK%9EG5CDY|!55d0j`| zs;Q_<9@w;s0KEBvL05ZXWD-b4K2PUN7bj2P^Di5Z*#B2sUcfoB93`bVH~Xq$K&F@Cq*b)1;E>==m5x5(XwP zJ~311aydF={AwpQ1Ur&YcDdOp=X&KSztA#;l6C9@S~w5v^bsJy(L>*{J;@|FAha;iz|V)zBRXb4$Bk2*+)c_B~kO#u%BQ z{ws=N1@!tlJCvDnQI1$QCFjt8HKbuHOUW$ClEe^ zep700?!rVbI%DqqiRar-Heg|b?+qePId0i;K0CiG_$m>lWM%cr=@3O8;C+$8f-?%v z+x(8&A)pCF1sjbRwNy4?U2-=j5kTG#iduDVGHORLp1okh7De}qd4$XQSjlM?-uNKr z=mO2?s65jZeQ60zWh5kME7UK(4B7HOyeW>uw_tZ)S>9+hBe59#u+)+g*jzA>s%}c+ z;Px>%8uAD40OmZI*gM$~$uJZ#m+3%aw|h&4uwH>m)bbw1$zW5p%BLlvQE2??N4*UG z+=vK-^#b2gY}qE*jqbfG3{NU2zx}d6K?TUOadT@qHZs4-dIB-wxlEWzNl6(+4nu(s zRa3JvgS3fN|54~30eAMmABK(z2?_KX zx&{}ec6xIU5fSttgDz5soB9iM_MP*pkvVS2-wWDb6G8IJhS0YF;FhE5H_&A~KFkO4 zaxC>g3?&U+DWh822srn?3p41N(pA2j7j|W?tG`4fTFEJ9)t*VUOg=j9 z31F@SS7=8c5}K;(Kz~SqcBc@ZI9!#@FZqhD3WJ>St)O4ipOu5HY82sw&r|8L>w#w8 zDX6a1E#!LY-rA?|jA)7}bDt_%%zs$;ObS0d6?~I#s z4wHU(mqgu2jgBzE2krTN;UPo$ZfY2oNeSzu7i%o36}Y`wm#ElR0#$@%Q8B>lzBmpc z^=?zeHd7wV-dpSMpDcX&*|e1`a~c1|--=XUjcB6rYp$CPGEY@)a3L6*w^i7`@N&dc&Ei@kzC=DLDL=KVjC zQO~a#FNMQMQY{7ry}WHGbEt% zx+6?qBNv`SSKa-`^b+)k^zUiM>C@_%WJivW{6H6F|Hx~cA%SX-SC^Y@oMKbgh%3RW ziN%YX-LF16UWj;n<6)v-n0B*@tvz_g5clnGsQ=c7atwU>Q9&Z{f5tyBOxdqw=XILv zKn==g+)c{PHLVfkUmoZSy0G8S;DW3-U-q<}tAi6{o2pwtEP(lq3c)BpuTDv9^gS^h z;f775@=J3+mC}}77g!d)C)TDy(dbXi_8=EkcyEOhxl0IMHW;&0V^55>oaPeIT1mQ5 zSbz7(6*@)vRtN7G@w&*P@JcyBqnRN=4`flNMYIyHWes%vBsEkPAN13yoTk<9F5m1m zSI?znSngx!(ePGm!M^PXSalcft$oqBqafP5c%vwkpng-=NVT?gB%3p#_yZeb_sUod z@_rmUm|{k}eq7!zrqX|lr%h5^YQ9R);xT@jq;B4GX$^ zv0pf54~tsIU7>v9p>jglJ41o7W&YG==a70$$%${RVM(|^&s#xE z6Ll%h5pB0|6W1j(9_Wuy4`%h|lGjz*O2uEM?ZmSLv|FQL@)x|5z$Y-ua>*WwvppO?-MUu!>WWB|>5T#|#12c;Sc;p&PG11Up-X5T^NW)$+wh`-zA^ z3h)7P(c^|qV?a$7PJZ6%Wxkrkh&sk{A+oG@3PH#LBb;PJ3HVkWXwYe+kyg_=cY(>) zIog^O0y2Cyq;BqB?Rm2T(`+Vsr} zNVo{}E6kWnXb5d9uH7eSJ3CTa_|j;wNH+Zq16z*5m(z(>kNj8|3>VEPoVCA|#c!K@ z4N=I%VZ+5@W%4t4L5Ep0gr4N}(zKRipNz_W?-+d0%J^z@q_sG^ZGQ=REcTIm6MRCMk;?UG#A^~TSy`V2CGo(?`Qg4g5t;vicsxi{v&ZTyW`=q92ufu6 zTm%01nlI`qCO@I;w&qSsNsSKYts)tXSEWVK$nq3nzJ!01A?U0J?`5@+#QNZ9;D7ce zJ<~F3DjSXy3Uj80@4-k8m7m80<`P_A59rEBP*4siZeK~o+BTmZU$XmwQL&OCo_1x- zYcwW@-y6{A5B7kB&}akf_~7JA+G~E+m%okd7pZQI0bX-M4@=F zQr+{xaVtBA<9>*aj)tErc-#6R(mp)gVyW)Bdu}o9(R-fb;_Q=Hysnx4{NV`rCZ9h7 zZ9Iu*g|QQ%|3hK?c;O-rW}=Zyj3?L2ts8^`UqVmLh=@;09H>nALSF~rA0$putGGwJbjqsbVsR@GIh`25NJxbL+f|2$iSB6R| z^bN>}RqLzc;SS|9G4i(j_g~4(-t~*(jpwih!oJ*F+21|d z5+hs`FS*ND5St58CnMGu4GdBY{^mR#G`2~$VDEK5B4h;L)|135nF?})3QqD|43;Q$ z-G=*b`dA^&OgM2#(EcgBJu{$MocMAWH+4`e4zj&{d$G3X{^x+qAniA{JB~~8Oqdj! z`J$OKC&`0JND(tQL{{Z7qqwSQE?qVw=(ai&+=5dl;*({!p>Gq@iPxvY-^L2$Vig@p zfx!a09i?h4pgx!UvX{t3O=(=?JnbG2)ruDf?Yi|;{HlSMmsdG={Sie^43Du=gF`d7 zE5qm*=x9>&Vu8~sFok!ua^sEK-fT$~YLq|!i{5Z>0>gP-_}!n<3qr$*8TV5I@Cs7d zk0l4X#kQJmugQgC0I(*;jVuBXe_rNjkK*UuFI1Ztkz4A5PW963)EN}LNgyE|y_1eF z&=7IPss$C7j&`C8^p4QunH{X6SES<35(g!vpol%nP z6{~`vkihiZhj|5cr_W(}y3KEAxJao3h?>mME~R%x-%Leuu)_yfu0y{BuhhUnU|PeH zJ9W7InY7gkc)u6a9U`oAJ_k6XS5DB^K!58Ba>B3TWcRi;U2wX<$QUkJ!T#dW|9P5* zG9uBMUp%*_vgI7qr`(r9%9}Xx1rX87-C>u$3gX{W(b3AG3eQVJ=kD->l8cMQueTB~rdA>x3sB8%+|k<44tW}|i-^?qR$f+D|GZK(1fR`p ztfHeP?sNBO`JRWW_otGx=Kit(d%9d|#OupQ>1<5cYdWFAd_^5Sai+)Sn84^6CLeI$ z>*Q`F|L&r7+7X(OlsjoF=8>{pQ*U6se*^bj50zkYNyu6j3LN4^!RMR>XP61_G3YG3 z0iTI@&4V@%3|Hmep?RPE9Id|-r&UYOzW4Z!09Ly6TQ(r%$jPCfo%-cgLeAi_$K7;VUt7X3VKU8Hf>G+yyoA* z{~9e6`ggeTL_-PlgBpxF4hK|bq{DA_lAQKq!-J)?3(20v;+WoV+(RDOFA?@fJ`VDi z>$<@+v7HR1CR3f+$D^FrONuCy2Ex2l64I2dXq*hQPslvtfmO>WE0 zpVVAmMI>?m(5eYXBsGA0JIzlrNk4pufjom&c$5cJq2OE6dswgXKi-@>LFxFOURi}KQV#3gAcns-Hn!vQir8Se7?79-VQ0rv0UV} zpm5q7?d8scPvOF+MvZZb|K}`#$qbzx4D5p>?vH|P(4yfMgFi+0JMq%Q3KHr!cO|tt z?gHFs>|_?-&8BZw;4K6x$QjU7u)|4EoZ?(%@s*?ZHX^>v6h`k0 zXEDr6Q>0gN+t@HQTife{_8N@_2WLMUD{%cBtAHcmjg=ExO-~{h7Oo&Y&`3C% z3l8ASZ#k{;!}D)!r3MDoQ(bBwI(rO4r^^h<6XI1TooDNps&@jK^g`470!Ro;tlvTq zzR?s6ZzQN|Zu4WZ^w8rde3M}$G;gmriL}!W{rM*rCOSArlr0FPWt`Xs&PRzsr*|BU z<(H75jRYnEHpMSOi@J0TspA`Zr*3bb+@@G~y*GPpAxKysUmjVlR_c)<34tRGqva;qF6~C66KNdTNgdGHzb_&7;BsT(i3B)Z7t;fJ;gZt;CrJ5C@Y4n&1u+E1Iv!Szm4|x z5grpzQP8TWp!ukH>se=w9w~DurJHN0`kk%SsuhSR{ov_2ZAywL#IXEB;DyE=+gnYR z6TGQRP|Z6hI!m{1KS2>V=o*Ff&@xzMOvKS0MxbDs8(`S36|g-WD@p6FVGF?zPQwh+ z(dLaM9vd16z0~a;;&-Cz4!C1Fk~c*dG8>(IxER?NAs+$;Uq|J|wMM^ZM`XXF5`c6l#k1<^S52~ z1Uvzb-l^Z~n2t8vc;^TO1arz2Z*OjBN?+yfT`Wgc#Akj@9Fv8T=Rci3RIZOo zs@CUsg>L(NXsYG>4tcpRaokw4h2BNK+AA{#h}Rww`}h)?O}!UiQ@_$iIe1k4JOaQ1N4>WKX{9D}2yeg+usRkf!m1 z>A{i2s|7?13b}KR#-l(N+WaDvVOAk&=)ujzf*mRA#TV0=YyHMs0T#;$kj-zUA+>a` zd|NseaSV_T=Oj?|Ueri)i8C+PsIN(XbUc5H@cOLitGTI}Su{>TMH8^V-DebiNy3M- zS9V8$qg0-twDKQMAp0M?Cnj0Xj~x(T(-P!UN*TuVHJ%xUh-neK8UZ+A}G%VY1O-!y*m z>?z0?DBSUR^fPjEBeArXdT=I?SGuQXiHU>O~pXz%n5hg;6G8;z^>&FS2JJ z*_8E^f7LHqofAW<7euR-RyDd>DA7L=2~V)?9n;f2Oeg_G&G$W8Nwb(nj-BO_q63ru z3r5$EV(-&({$nxZI;^VWAHiwk#6SeZD^u$wl&~LLTeSfiF0mwsV^HI=l*p(tchy*W zw1~qbhqE+IPj*a**j3xskP8xlr4*Ylnnfop&l}J81NUpebyRY|N)U0%UHq{tFWH_U z>&rdHA>x2(hD8s2^vM^gQMf@rH&lm(UG;55`momR;Gtwmz>6p4T@uDW7Eiv5s3?%{ zg(NR)?P%V`1{x4e>|zYQ2c8q@aU=>@2MAFe?vweT#k?co*j|yma$~63yq4$vW1wx!_oDRtfw+`%)N4?-f1U>MXPO&0~(OX~fu@xnA zkRg`vBUU@9YnGV5_b8izn|XQc>2?@<(_DAm&%GJV?2gC%(HER$OWuR7MMYh|_)c~` zmvR=B(Xw|3@GfPGXh>Ubrc_*QZ^Or&({lg$N3$J@884(;sPwk+UadYA0UUdxAcCc? z9L`cK)*0*gSr~1?FoYfgBVN*clb95p!+my?)%Z^Fg18XWh3N?0veQl*hH=L*MVfMa z(jm)YW&@kDjF#sH&7GAVFR3JhdXn)DctZejAWU>^Waq9o{6(7iURC@(93qcR%J(#* zyp`9jPdQ&yIHAZF(s*Eu$)T+5mU-(7!d=Zz?|{cj4`Ag>ib^TZlm<41PJJJcj&eY# z2YkG$hENVzw{$L=ax(N7m)5r_v|mw29esfRrgYv?c%iz86jJ!P;7y#q3`{G3mv5!w z_SUXI`M_c@N5kBLK{YIIQlgRFkrX(Q!|V4stBMH*7G|QXYV32W`}MKadYQg{+4cVU z;b8YL9aGl!=k8&TllF|Wv-7>Os+~D?%%$JGdVW|Ug7gg?jqaM^CCIdse9%TrLpfG% z8i}wryvZerP+9$b9_@Ng3g$8c-a%yUpNoPuwB;fizfG=X5-z49rVV&JH^@&KapI77 zBWQ{rpB#u~7@c8snOt6ccWc=x=o+;R3!G zo9ak~#3}4`fymy%q{DokEg51xQM)HGVinuGZ#4FGnuc+?n76BD>n+Z8jvvOiZbivD z?bgE@T&eRpg2^}z0JvwN`++))k-v&=WXBtB=MmaSUsZEs*{|{S&Cea(1_XMow%i7f z7uxjE8+IgV4fVli-X-s$&0Zi@;cp<^!X|=i@G9egIe__Fi~vZmg9P`Q<#3mw)6p>% zq2o6Az{H}&#-h$ZYJb;MP#{h?^;Y?#LF-ov#R>f_P*+sCQC&NIDr#;YSEs9I3@ zii!TcUr*ZVNwy>BD2ZG|Q|rKW@MV}PUJ_4v;O*7N4E9_X4=hoY+C)7huU1#4OB2W< zb$ljJV4zxUxvR_*^e2Aw-hszpSl0pOq59(P{D+bcYgvov8m$xw*Fvw=JV@{m?+y|T zt;`AvpRVbX`QnMhbTt+BdQ+41>$B3tp{G2@&I`$|U8Bo^7T`n-y-r& zjnPt(@*B|F&T=0y_ca6*ta6>CK;mfPlio4xS)gBBdWu+|-ltNA3 z4E>SL^qO3KUwPoz0|ZBw3-Hli7^I437Z-;-SE5&{=XvgEbbXc+9G4r^Cz(1JRfm?s z-Olf@vz}lZtno_*y@p2SCVohwn?2scT&%zXrm77@%m(vAO{^zC8`p;uk)+*UhhMec zV6QwrfPPjvw%5Pkvf#BNjf<*6C%)W(}!AX4^eTH_Wf+bf_lVHL9 zclze1=<|jEp|WM4)eLr51s?}Fq1LSJxDFq1P2r~`quEmkni~rj*tLQ((>6u_fV&4Uv7FOv?Q!*y zvOa20R1}#8xA%cFh}j&^?W!;p_g8NKsSf6Il?)F@O!5;u`kqG$LWM>s0PHe$a+i~N z(@}X&*OfL?CJN_c8Swr|H}fU{A)n*4XGe8)2y0zE#qMPoPc_&a}EN#bj~UAb;GT0qEj{g})_V0_z{ zr|TB@8Mli5mXo)pQcqEF6maA%=-YAnxwe&&=(4v8b-;1GzgzJirb9rE5i6)_N(RpJ zWGZUJ*LFeY%NAI#|4#lsPt>F^T>Ew{hitmYMII06O%HBpn#*Z2HO|P_(cAEPERL;z zw?0N|jmn9%>hqMi`xu#EIvIf+`WaZmGxbP)KYuiU*U#`Uek z#~(*WV*Jf6o24rFY=fKF`Ka`KnAfLN`o(0A|LI}=f(?o4t(yK3Vz^BUrr^)wzZu+f z*QM~lC^M!-${0`T>79gC-%_np@Q8=gGK#;zs&`|j1q!NKrFKUwD=Vw{k8cLxBNZgV zlNgJ(=+u;X5E*+bG+X>8HC=hk#vw{eOY?Ug&(R-FOQ@)`d}grK_3xS5?-Ogse*7d# z&(N4+i_`Pmb80r)?1l4*qA-_dmazHGr!UR>rbVLsdg&cUQX8X^|)y{2qx|wK>_F z=6e+pP^JI0Vg6TU;<;E63jWuN9yQDNDRml%$^!p($iKh8CJEijS5i$)_eXgBuTrt# z0R=b&Kd|mc#Wq0n5iWn|DQ&S&bH_8t{nM4H>-m? z82$_vx_xz1{x8!r(u0hQwg8hyuayFiU{``F@5rjWFS_N?EnP zpyAG7Ute9G8QeeMM68nbc!myK;{?D|DWFSroB5nAx`Xt1D6(WDqL$PY6 zzj2Yn)EezbJ}tt-96y=)*#q-8Tj~{{5}6eHEH|4}R?imDLYKHk^ZG1#I_#{tE+;l| zzwUc;|6M{Bl%{yc6OC6Dxx>)#7*&ZKkP<~1b^)I1Qjo6Rs4=1P?%S_vItV+k_? z)Zab=3wl3wF+wPEJz}Si`6^SI7j$pVm*luVC=zXG;|+)W_t!=wvn!iMG%7*e;HJ)G zHB0_r=DLQ@eEYAVD&l=*UiBrBd*w2NG)3})>zt9j|CTz~j><=@UtiX#>4#eKWZ^wT zm}>{I6`H;>z3Bg^i`A7C((*iw11MjaS2l=bP+0bs41faRXF@_8=f8y*Ct!f{;M8G4 zL(ck7TLc&JT6t4-Wz+Z9rIDonYz`TM|DNh#ecRIN`yrF$6-1NUiyT)l5wcY8EQL{g zw69Y$>6HFK2Cze$^E5l*GpF;^b#r}55s&t_U8c%qSKf}#5-eQkXzL-24_moehv9(@ zLW6`D-Cq%X3a4i_-+-=_h4G(eyiR4f@2MwN39BnV-FcH8oY4N3M70*Ffte zFq6!G1Q!hsOaoBBb72Va6;Ncq*eZolB~<;}dHC_d?>ZP|_#L*E6otCY$=SmF)u1}Q z@%;Djs$z6nID#nKZ@z||V3_UEqqWB9mZTTRFZpTk~%xLh=yV4Kn2j61< zVnt^LJkE}=3u6&g{OfKRc{7T5F#Vl-(9AX5gez&1V2NLwZm&D@3W37zT zlXMW3BardeDCSaWtlR3$!sEN^ym51eHvT}l&uSm&Dc)9Jv0ues`OGW<9+q4-+u|{_ z*uv46dw)2T7``kCDw*}f2_d#S>N9YvEW?ihEG-leSx*O3L7DG=uMuSrzSHF%5g%uOk>_)@ht;OW7eqDlkCSK_u5Xpi94_dNycA z>^JOGyv4)+0}&md6qAdQ^SWEq=lX>Ulx8@Im9YE%TCE2_Q$PkVICmO~_{@QxDDjOd zUTG`rYwKF`!27MwcDO6>l5Pze|&meEx%M;NH@U^kUY@v+UDH z#Ps;RJ2QVY0C$tTZS&rvGOcV8U6g;rbL#LmW*(Q0TlJnbBO=ZolNa9TFC;s#foxzD zjsy#F=ciU~YfBp#sJMaCQ~q2<1Ef#z(7vd zQ*_r$!V43d=UaJ`$G8v*toj(7u-(caFNXiarHDgEYy$Nt|MCCKCK zeWA}6=&66VMgJ1-(>HG&sLfpP0XBEA^M?RfjTe+g)35ROFBU3oYuRY30^>Ive#B=Dkq=BH5em{+uyj5BiUEQB_cor!FyW zrfNASw)^t@JzTCo8tM)BtCc+l`?pB_FTL~ok>kg!9X2LG@=u%OpW4Mce)k=)7Rr=2 zF}2mVL_+WXJ!9l`@U~2d)#mE8A+Z0Gd87KaMzg~7u2xkhkL3?!9`di|mqL@s|J_35 zX_E!?q79;G7LXjXN(-9CyG|?V^W%S#$No~aJb?rrH{;#R8|D8-0V=>k z%YpiaPyV-5{n6_G_UPFS)J0aF9m4&~1O88(0hMe3Sh%LT@Bf3o|C(&n;Wg1e1ylQf zL;G*rLtPkvc`EPVqW?mj|7-fzzrl|D8ea1$3;&~6{z=xMkoX`zJI!19+!P z+Z6Y)y)JvHOtC%&`GRa3) zm}jNP1T8iLRNFb(L#8)U?em<$KSKw2@eBzA_0K~+Sge2l@b{AI;63eQFmp!~b0+#0 z$Mrw!LL$ItiLqvJ$Wi@~SVK`Dl6g0n^seejM6(i#&ZiJuKAS?0h!j1^`L$a0?>+$U(j5MsF~+jovAsf_zC=*zR3wl z9yj2!$U{6nUX(I?Ye#H2tRUZ;%%5PoP_5K2hP>HMv{?8kKNCEWTS-bx+=G#ol_ijU zGb!&*_W+bdHO%_9INtSq9;rFr8(TS0@imwNz zucY({gkZSQ)VTUGvoxTjb*Ewb(v5B*e=)CS(JXHebF=)A2C1aHyUb^r-x)zTprEq# zAfS=TYTc4oIXqlf?|g&xCC7f*aRjvwUlK4fktEWJ+MlZEY#0A5=^amTGg#U)AU8ml z1?QB$+`POvO~)-pr{j8e87UR2f0a#TvhLSX9~M8!83avjuv1yg|Zh5#{CO-EIo0z@cYj3rKM}ztL|E3xoSi zMMlH=B%F{h$Y-_V5geSLHo`BZEEqn z1OFQD_znjb{FPN0qT6oIki&t9+fV{yqV9;8vxclJ{9GlXly@#rtCM|u%VMqgxhbk+ zW@g5Pk{B2F7n!<%fCIGqh9EC5NOY_cH7xToeTtHT!uKVs{ECWi;zC8yV{s{*wlT5O zkB^UR#jvS>%YJ@-o>x%N9|!%n;jM}TqT&-4VHL#naA@6VLVTg3skvkwu=EoRug;1q zg0-or$gQvmy0|in@PhIWwit*#W6tRHtPuo$`)s3c-au=;-_txzd@1r7hzWh|yK8k5(y=vGMWw-aj=pH78r$xt(^?AHJlN zHk~)9z&*^HR8Cr5n3U8<P~4w(NE?o2q~_Pv zdB1)4&Zsx+*Ja}hrx?&O>xc~3)U^^O3dEqC6StmA^DpSdxBxr#WI=AOQgC# zXQLfNMnvpO;sT9lG+k|xMv&PjVYMoLd|mH6yFBfH4I9L~S$XkKc+nqmOU@dyy%`fu zJ?{_PVlWy9P0_KKZk{?D6L!ztUQ?;mANPFcr%s36r+$Amvyvxmca8dG8qgb5FU<@t zx1(rVg@wcC_(jKdhqIy7WytO zO-_~($cVHbCrdQgx2UPLxww{dXcD?}P}ah~3l&R`wLdyHaa8tPxrR@nDzaW!D>5B)ku!(9G&U_dQGWWcy|Ch}abF$2FtRQvHZXNCm@N zTf!y${QM?SvgS-x!w8Dk_fb~dFOPx!H0=N-_i7f*bEq^T43B^W!Nbb=4hJ%uY=usxlC(x&h)Dcq8yezQask_01aG$rOr8Sp*sIcG!-|Ky;qObPQ zD(E+oC>3$q51^XlqVss}6=s=10EdCuu0NM$tZlkoCpR9>F9cPqHP`vJ(oyC90+PUS zr`>S3jXv2A)MTHGxIZTbthBgNV6xfx!(eeJ;FHGN>q@CMJDEYd(>B!_jA-sp=HvI( zlW*h0>xwxVjJU-6z7M5WIIpB=Ups#01BQ&}pb&AF;ThyA%BTyNA(@SeqPi->%WSW_&}1 zQgEfu5O)lpUQ=8@Ip_jWz|nhff10!WT(?pNc1_nSTQrt3?!JK-#+wdUC{ay1Us!A* z_m>B)sP1&{#v7nGcje`ox|OC_77aO+^SUg6%XZ%;BDQEJ^(D3e2{-%rxbei?)@dtx z#?p;OZcm!g+%>f7g3{t zeWRxxZtC&%E^%e_PVp^f`(q_B8s`B@=6L8gr~@QtXsQOH{PsXkQ}RsVqj@9MxY`vr z^4K$2^=D2o9owmbsiJa~!S=ZxqxmZFOGBHzYg$``w5_}rtNyjGXD;7qJp~M?X4f`cVMfzCm zGfgKWqLFIeBG+58K3JcIPsQSQ@MnPLlD&vMbZ<7AK-!WVmYHd2-O;dRhtU|w*Z{9xIUd9tnlO`p373%H~cBbYU#V zAI}%5FXuOY)KNJ`{QDFaPr#;I>^Azi@{*#&-M?=H>DT&vrSgREyI<6IHqSl$1$k`+ z98TsJ@XyhT7G~93G-DB%xqBrLn4}@qj7o>>8490 zkH^h7=Go1SLmWU z*GR#MTx+rNj8-JTf9->uqGL8gKKWNUqh~i^ge==7kecVTM!5H zhvJU)UUi}ezJVA5VyUFEgk!+6A;rg+H@Za!K)D5EeH$BUq3}pzvxhqV#0EEeF&6t} z*b0B(+=}&hww%8ydZEd&Frm~B8htadb090n)TX}D^15HEkViP zB|()xEZ@NC>Aj^f1`JHzoo2>LPq`kvhra%RvGn8zz#)1E-aB4BRj5Q>+b$z&AbHOtqB%jYZ zA6r_oU&)se7Z+E-C-kYt4JG}RZm2iEaadfLQd5GOsWmV*BE3MITU8}-G(b8Zdp_6V zN}TNe?AR1)sMV#eNwxOsT%?tQZuUe%`&~@7#7&Qjj8J6<6jWX&`gG@1mz`Q;d7hqr zf3`fvy$5;*@V`8)NI2bXAsg!vp+&F19z+1j({qlKF zLGjyCTrSs2$!ww|vGoD7=KkqhJl@z>$0xfk9O&Kk2HX%W1n8scY^@?k)sKxZ9o{Z6rjKYaX;&0p-qjUDxv)DSy_3iJtJ6>hNJAhbBrJ&K zRB@Y@F|bI!vLS43P~RC&jyqYnJnKmZ^Hp<~B7jlmoU&Yz$+sIVGdsyGzn_%FxL;e#h}ih~5Im-EAs{hW-(P;-QiwzdLciu?0Qe^^p6nvb8~nOg$w ztD#tsy^Yt2c(5F+PA4cB9*uM`^CDEy)gMEtHf2YfDfGpJfz6p~Jhpcr)RvBV!Ae_M z=KAetC9P!c+f{r<`|WL2t%d#%uYSzy-zvk~S^5bh!*H5c=9rXR9cH)C8CZr8 zlmGtm?6uv7mxjpC+1J-InDA*k(FHF7%MS)q(OJ2>hu!>V{U$CoUxm^Rz>`tcHaaa< zRK9*W67>?49iRAlqNBfD-fo1Rrl@QT{g8l|f%}%{J&|0w-=y6|cK`hFo&Zf@U4UNy z{?e#PYY%;2PcdfkXST{;j;UviB##?I~AZe^d21}Y6k5^4icIULdwECkr)uct8RbZJVJ!Q~w5wYeg;jw^~Z86*Y2 z8>_%(SXXIxiLtqHNDleQl>wGR=(A`aL|eS8mDk z@_6-Q;?BIC;1QrDGd~@qS765~Q%=3Nynlk_x(yTfq2n)iG{Yx1&btLxPWpUUopC*BJvEDXAyRv}a#X$?ka zo&W@0ZayxCR}YrKvf>2uw~xZ$>!B<;#jSnXlK=&Kow?9s+or4o9TNCN)ofFsDp+Q| z^dZ|U&w$(Qk)_&iGl^B}bWu_Mo$Pgv+w`<&JE6mZK;p>%g(jm@DGsLj}X*f<@~@B@_0}V0_{A6$LqYuJ5#Ce^j4wO6=Bd zh0D^eZmOxu-d~-^N^o#4inw?5*xs=22B;3&v#k)yilx8cL{clAd9zHkdZ6UD6K0r}&k;BsSAoIKAGlXY1Mhbt8JQ8e$racCruJ zC92g4nl5L04ciHYw}LdvsBi88rPQ~wBCSWh6Y@PU*74!!#z9I`c%xe*i#QW>TAM(6+u|-=Vw-KL-k7W5`QF5F zSxpLXWz;AOV=2FG_Q=EM1lZ-H5TMcNhLNSZDCLz7&)WyEvozQ40&bIx_&&S+anVPx zpV`);!1T|>Mm8|NkDhpRAUeGt!Ur2oU^mB87!DqEh`K+F?WVw2S%vDK7L_~VraZhx zkDeC5Uypzc*FcY3U$E|vYJ>N)MN11z&tIn1O39%EwA@sRD02Hbv9YnUS?^|bU}t7` z&QhF@H&0K-&$q}G5G3LC16I#~2uNkuj1q9e!-@!K%zBmt;H{AV9F<-Ctfbzpik2_7 z%4Ra1*e`v(h&U7rL`N#Sri59J(KJJ5)O?~j`|XYwvo${o-Wrn*R@DxZbvOZpSqXhU z3vIP@<;tRNeVoUb9~lXyYA~c|jpNLUnM$K@O`P^ZT zw|VSy>w<21>{gp3FF1-v)Hix767dh6`;Gzv)iouB+xRM!xN7-L*YoK6?4IC?U42c& zQDNI=PsbW(`(6a^*yXQt1~Sq@8#~!BH~LS8z4L4)--6tx zhr6V2W=0O!`_Tj-@P!Agmqr{enY^p*sD8{3>-0!JM1{U?yI3M$$J$HLG>kXKO$V%> z*cce9#`YTNGANiwdV6(?Qz{=bKIdLf*nD};2*yiDKSw}BN7vERHW+NJt5c4a28{<2 z-L}>A^z?uhtLgkd?z;M1DpNigOsd4Rrg9}0SBdCajC#B=i+AJ{`~@gVPes13$M+u- zYNaX{7e~ps9UYOK9C;yw(MMyRQ=2c|1Z7CPyxj}87=_=a5pznCzB6*-;@sD3m%F^!$2Zs-9&_Whj|lZ@ix4i+(<4D>CTx}kd}4s zjL}q9$}itZ%*CI`FPA^z6VR86RKOsMDu1_zfH5UoF_(z_><>dqS-PM$apja?G2RP9 zcQ*->(ozs>M1kA>Q1iKA(a#RwuHk7g{Yj&G;?Q6x4Bq9Dk`*h+Xg-K3C@3hZtZdZD z;(Y9$vwvWKzI9|%3O<&xys#qSkY2opfRHfWX-=ZpVm_+$tFagl1c~Q7eB9*bKl|bTf?0j$M{|#Nx+z*I`<6cgW($KxHw+ zdJNnZCB;BD;ln2!<$)mc_F2>eKCrx;wkONdMYg=_rO^0ICJ##by19$x(PDk%!zP-m zxxXt66jX<}k#cZNDLp9&VH&70-)cU!T_Ug-I`bfvj)cLid5+WNq(ba+=Eia+OXjEww@ zWTH%jk{<~abBnGj;_DljF&xyfR1cYA`ZCC&xM|z?inUh&e#0K@`^IOW^PM01(DQD{ zpVy}bZ&e0;+fwH(BHv8ZO#S}wAHVv?gPSx@mqaVKz&y{NLI3gZKMx|nSDdi_7|ZPf z^ljpUy#dkla?8piMAnE>kzE2xuSaUONHgt)$;U*GfcR%umnz$Tn_uRw z@Xt0%1KSvr9-An;bY81=2x5%vVyESgwIgSC*-(ZL_Eep3LA)-%vg7~*B}UvE8q334Fce8g?5Tl?%(nD7f}C0{|I1h!RKZBQvX2DA5QqQ z1Yw@8!ESpA+t7c3^sf>A%ooLzNsy+kpUF|wApfs-uj28~hqN23QF|$0M{NGaynP>EYq=L9Mk!`ER*sJ9|yJ-E}Z7 zS*iXqG5B;GX6W@_*6o3CDgf}dw1UkalK&@eUh&`tAW@=~onRj44;=r*%->?k0pMri z)92)z|3cd+kCoT2PGEjAiTs-||L1tppbCSR0)n~!g}5MutM;#7HS%Xb|2Iw%Yx@K+ z6sPQ%(SJ_!ZwtD`1it!zDEo_F{vXQzM*;l*<}y$H6rz2GzgQ{{`|TOKyzaEx0Kqr= zgvWc6r=knP(k<^#0&G1({aFXX;xkyX!p;}}BisLAPO7(P@q2vf_^&TL?+M{r$purM z9&#(}XU@oVBftffkKf(+JY@YJMQv3X5U~s8@R=iEUm4wn7<6&{85M((yB3EP0`uQ~ zHOg?IBdA$h2nuLK;xNS6<=yLYrUwP}`@+KkiZD5EhZ+-1l3yVE!X`GvzQ>~$0c~sT zaz^u;pb&<>Xo&yXhW_H9RgzBt6n}4Drwh0;v1swd9X|-!FGgj(Y~OnS)WT&`G-x@V zSRX$!=}y;R-NsY-$^ z|9(E#zO_=2CXzLk* zR#>966e54l=X`pcV6OQk3>1theC(-xYkh5szPR+rn)8HWg&52Vax>*ZM|UX2)X~zd zNut#@4Je2ww4fA?iZwqzv9$K-YVBv7nC_=%zKoXo#*4Lc#&kBvdUn1P^AUB9S>oA7 zli8wjdbhDN$VF6SBv#(pciPa+g1)|Vps#De>OL9aH2O_x=99|%_Jr}H1yHezoGX`( z>vCSl_k=l|AVUcv3?&Em#vyF@t{iY|jR-8hpmsfky-kATK$t1b+ow9bJX1QHt64kr zTOb)zazYF)X+D_l*B4Fw^&;wR(TN<%%?OAcg~2Qxu{PniWcv5u5(dBbBnAS{7+hYf z=d8#q$FKBvt6PFt%%8_vf+bu}-#Tv0IXZ;1@tW6}BvB;R^2Q7;eccZAH>Q-wPQan& zI*SGlKR@Oo z#@Ac5E?P+$uvRPOfvyvpPzwYaS+8%NQQP&kmXJ87ojG=KQOL+Bko7sNJsL|E9D1I1 zB3CBNJ{R#h+Rt$rjkU>UnGR>t+l%e^j;o4DJMjy6L`zP3X z@9Iu4%`)@YTrGc4EX94Bm-W7``e;nXoH8XUbOlo=Zyl0Ne;$b~x7qRep}_Q|i&$9n zdQJNit{YTRR8Qp6<@tv`E(OzsMNrKF|7no%Y7MCPpp{3eI)ka{B$$%YCBjGQ}T~z{MZ7qMWVXE{j)L)3J*HE-s&%Lv?Y0ELdh}yFl ziMr?s4Ua3)(4B}mI-dqh?O$?l;?2NYm|pjvJi)U(gE(IbHPO%}N>M#slpF9Hyf;fI zIbtD7)84jpIj!0QR3HP)TTkAhZ2s8qsFqF^Mwn<6;<#cd3=Q_t>@$cNUv(d3jHa7N zGj614Hjt&bzA!yj3Dd!D20W!;jS$^#G-XOtU05!Wko$4xaG@*}3)}p9vkq%$s@8x(WYchSC=0+{h$gZ_Q!H!EM2RE0J zM4Y@(6UOh;RbjS*iwdz8iDbW8)|rjP)UNO%MM;Q9@Mc{yzcU*%f(ujaO902*N8T(G z0UFTke$qp&mk6Q@xMtzZQ?*Z-Z6d#}9@E2xZVS!h3+7Wj{41A8{UkS+!%B)dg^o?d zdc%W~_#Dp@mWjydk*FC+=VU7k`JJk@^?AoiXNmJ=3#b1}U2&5OxhV?TO&P#^NL>@X2-i_zeTJm@%b1oSJGafhis61Zn;x=jRG!Tc;{Qlx%Y0tjrkE``;pS>xn zmBimT0W*LLZu1W3yrStyDk%_=KVu$Lgxlq$uZDO>Oi?pjg0nG@p(D^xLKkYzb8DJ- zQ|ya2(ffH@XY0WMdjd^$FdN8U;tq4H!-ncYb}H;)Y9#fB^0ij9vlF&$j`*?_>A}dk z?`|U3vEKJCkNqmq(W%|QK#Fs;Ccr*A46X6u`Dn?kIgwZvTIJ;cZ@`YP8jWc|w-9Y5 zq6)^?QKQ-rLYWz24HGMpdy1nHs?!l`7oxUd)dvRU1X&V!VgF9Y zAnSbEwZ8p?zl>8;jl+PmIB;x*GoxQ%h9U_$p2Zv!zPfv>9+soqOpUR22!4IDKKyMi zA9qvM1!tfso9`D4?3qEf^;l2`DxcNmiyljjpwV4Z0(WZW)n#EY0W-6^X$gGY=ezOa zI=@wnUje&3j<#+;>QAmtHt$+w7mgg&LR!DLKR7gEw4bbVm+liTS(YFp#`Xskqn_j8 zQ<$J)lvnP^11&Qn{w^c)mdfTlH6C~$9G4f z3S^S)QOEv|UJomCWUv|t&YdTvwbpHS$rHb}k~Fb5nvh`vjLa&G5AR{t-R|!*1RU=R zIje0%2d+Kqmm`DsnhsLQg z*6)@}sKF2BFk=le)v;53g(FXSe&)qPj{z;Wder1b%~lP z*5ioLY+9kg{s6C7^~;gKQ2%f=OHpH99r!^g!g1?_9IS3{%cg=6*tc5B3`P0z@oe$j zfHaUAYD=wvs*mQl8f?OuOP@zR3}5ZmxxYFets#CjLV#Jd^2QUSqp`0(HYm&swH{%L zR^pmiU!*;S!9VVR&~}B_2p$7xXyiHxPxUiaiO%>{=4N&7jzf~(Lbt$NBYpL_J@bll zMbVwP-{6aBaC}Nk5+QaBRk#{<91c{gD*mIo+JjpUFaC1yvHV$@&dd}@`_MrxG-7~S z6>;k#{wFxXi!=K^1g!Bz|M*fWF&!!Hf0=sTGUc8Q z|A<=-YLOf&c}yq^XPt!Po!1^1)-TCBph~)J3(0KP@bG=x_|$k#f-3LVz<#ZNKgM`- zFub|%jiFA)njGdMaO^0TUkuYQPY&u3>+^-eZbO@99U^dD*%wdXccPw1$JG;orR z7GsH*GE{r|5qm8>;43uTg^u&*$X7WagkQdk`5=;}z zYAN0(Omf3maJUwDOV10od*iv*;-Y@L-%)zjK>Yg<za$%%DPMeZ6v-su`RsADb)9tfv~r^Nc09@9g`ncK^P@C><}lB)1e)o|}OLB*#S_;~rzoHApT?mf|bq^=I24hg_8Y ziwHiVV0+K@4W+}c$vaoQHxjFG|u$wpAwaR{Tk^YxPl@kAuO zQX9(e#bfz==@+iL$U%Dx)4C|89gGvOd}Qfie9LpI;HFb=wiJJYmqH`(0;dMw7KkVJ3v$!^+wpX&T6 zvhx{}-6qItWpDJO(U?N}56(cACO6Z>dTET-!>H@?N#w?0|KUS))i1-87lhCGKQm)5 z^jDvggH}ecj@0lf!Lq|>%-G|~2B8MtkL`(EZ1z?hnfhD%p>kb2&HL=2Rvde62nZ9R zns--=`>lRunNJ$AS{}x%#J7Dk;91e6OVgsBQ6)Ln)7uiU0UIIw9#f=D$qGj}L0>_D zvA(S7@9XMp@8=(H;@$iBgD?JW4x@f!`T*ynkf>EZh~vSNbQX}vrvI#>H5mPk80LHS zPit4d3n*QnNANvDw+`yCT=JUcJSxZ8rvf@*jqP7m3`1UVT zQWBCdQY9_2WSUeUMEI&|Lqlt%097j_;sO6-V7oLHJH|Xxyo7zoKMvK1HTv3SH=k4Y z?66uGJS-ZxH1BrvXv^vW|C8RTKMHt;@H89-vt`_-J~op$hR9HapjK(*Fl~6n`a*C> z^(wC=e}?110m4Fwlr|AIPbU6b$;cpPpY_8^qmall8C;{jLou$!oA}e#WnujWDz)I4k5Vg-~}S`-7_a*uH>;M+C7H z<+Col;Lq2a%I9#{YFO-fxMn@+ZQI>Be5qLEDly6aaxI`s_EMD1kCD_&B-x$nkhQD3 zb7tEMcA^KTn2RSC!-U32^8y9JdQyaNQ88#%QL=}*V{0qeRnf9N0Oy(1eINGnq=9`g z-h?IV`*N~@c`oeFVGtv{Oec8gr=cPgWJT3;7JSBfK6vGd+rlIaYM#INIR4>NJ_}w= z`^HI2P-&`xORe<%s$TMrjIGeGTfby5;I>MzIHu-$2KXKQd=7UVZh08b_G#=~3%Vcv z^c8Uj&>dW-q1UbTmKBV&()0N9r3F<}7BcH!Y4B8!*=i4G=_78!Q5S})+j^5qaq2KU z%8)>CQ>kMQWM9tF1dNpIG2=ccoJlij9^XYc^4>XivL%f0fMOs`e1NZv)>6=Fv*fbo zQLAs_z)b83%b-bqCk3x3G6Q#aptq#AUx>a{PVO8Z%b0R-VOjjVGrvs48KHC|4p)&1 z7W<+(GgD=bejBupO?0wEdkg;UmJD1R9*!hV-`r%PgtvdGLK1b`C7q|EYOZzd{tf|S z#Pjs=oj?IGu6GZgP0rT~6z^GRXX~zs2DjyRA=Q~&oknszSeQ7a= zu0)ND=b@h@*ze?=Mi$icNCcd#H-OWEuM084ffMNhV@cN?ArzwCX~K=4;is?dyCw3r zu_2{benI>?@cz;Inf#f9cDhfPJxG!q_i?)gA>I+{91GUm2Sl&8I1a}G!P|)=$EGEuJ60Gs$Oc)?jU28a zesK?@4-46!I#uk2^=n(^!;BuvTUk zy6~7KQ5@f>Nk4qeO=f4|YY`-Z=we%Tb{yQjHJivdOd0wZwFmWSb4u-lgAJl=Rt-$a zev@Y{vkRBHPTmd|1gNk2+?FSo468A(o7`@#itjcpYdto^p29ZZM4Cva%r&GFxc z;$3d#*2KR5{;{$NA{FZ1)@Vx%^TzI&=D;7%MT4?HLxs#yNI%Af)*$_GE)qvaC|QB@ ze$*8m;^)H_mVa=u>W6{hrL*&MbnN~wkwm>^xOyO;N1E@c#;5F2Xsx#mDznvQr07uj z2v&4Z81D|DEaLt9c;EG7RIuB1_qp0H6BP5S{_4}fdAYrTs?bqt3SvL7fiT0=9v^(U z^dl|NFZ0dGy(2AftG!1?4c!t-WojSfzFF9+upD3t)!u&WBHvnv>hAad<~7(97+V@q zjb4jJYduht>@TzQR`yB=!t4`XR~O;=I6A$$*=&Uwa!s|+aRQs*ys%*09-=X6ikyG3 zkz%Zg51W+&L|&Yug5^Q?@5q=QXx#l$u~Jl7W@^oms<@(1%1{4F7dadetl3mEZbfzp z>7khV)Mt{&oS=xA)OhR8N5}fRh~zIZs)XDo9HX1Y+KwKE|O zow#^5^@Qx=>)I}}pnPj13x#8{9g^OMw+F~bNI&l$f0AUs{oaE9c0-fHLD(n2H{tWJ_0TZ|3d$z<-&a6>zii6P5XwuOONc$KK zc!^@~=1r*P{HF{F!7TjTdUUOjI|TNR>wSb@Y>4>Jx~EaJ%OJTg2$Q=J#U97qAi3yH0%qK;^c#1*jyGtXJ25|l3Q5B)X+)lmzP!8oeMys)I zRiPyJ@nB4#w6TG=#PC2~K=yZyav;u|95Gr*KoY4ZYy)Bev7&vNR9<_B>@1Vth1a1iV3M zIBZl&qu@mpA2xFt@1GQv6Rhfi7wZH97f$pkY8{p(3v3phwyXk^+&rhcJ0uL#pPTlA zhOtUX>Ae=X3vuY|eP!xDk5NuHtY47PXcsF%_E4|0ae`4lQ`nx8jJui`r;7yE@)5;; zvoT-_feL<$e1J6{qJH}$pD%~kTK)M`V8nZV86_r+o}}#eOa!`#md6tA{vRW8mRlje z?b5L2UUcnN&HC-KuzAnsV`dhCt#e=mM;RV$<~6^|?A68P0RI*x8^yq;s;LsUd&VI> zOwz`vsu|97{1y}R*p7o0A2nGcI&&~F)AwOe z@5N0}I#$_kBM_Y+$MxqxIiJwV+TD+88IuFu@>bU4AWqj1zCAd!OlrrG!r?_s!J_y* z1`8>HWq#=sbVy;TISZsz?i2yLAIzDnjc-)27`W^Xg$35NCykqtRA8EJly(;H9i@jb znw?LZZluABW0MiK5F%7^W5Nqx8e38wkHx+Gov_Ex9l38dd+CCUwo@CD*wq>FX;p@Q z2>D(8xY{Gy@Seds_zKiaED>4jEG-vc+B`~boa8=1Gm;l>a0f|X(CVgD30G~b>lG5P z6=32qIXkJ73-Uw8SJkZP%@H;`E3)X%`}!nIo)#Tqh>A!s@#TKL!CUa{OY>~Tr7=e) z*RQC=1-?#e_rTVO>lu+LX$f8{Os!7;4LAA;oL29HzQAtYkZX^ z@RfV&G4}No*V(iR$gF^1kbBDt_u2XCgn&3@oL`Z0j=~kpKAe6So#4(PUq5T}+56+q zg>XDS9G-jaz*ZIF4)`%!AbuOFY`WDhDJ71rrK`!7O;$l(T_3YMXSb11{x*;RQrZom*x6*WeuT-2U8!!80(pm}n>TahH$uph~ zFaa)!3L!lF;eF#uxa?oxUJjF+n_769h@|}$So7cg*@99QJa+|5j{3DYZs+FQAO((L zbAl?s+ulVH>!4vcXDt6f>`LshJD-Q|ZzPYo$YtC-^*qiN>x`(G5-#fF+f=yWeMOLmRs1f39GfQzg5Y#SniA^an>M~thlR_Ktj=9O(!;;Obd$$Fb6Lf5d_oEg^GS)VpTQ!`*K4s;L z)E+8Xwe435!A{~#B2-i zkuizQCyHcZqwW(cOuJxo-0_j)U9oqa2_^JZNQcb6FXN!m6l<;V`tA~l-`PiXasIIC zwL=*b#v1V+R7|UB6p%YiH~Ky0lHf00xeeAmc5cjeJc6i%nz$mi8aouId6>CBu30VC(Q$5AIW{a9M>vN3K8j5)K-=_BnO5`KM^cMK}FleGvVSQ z)H3(EF&J%?z;5ABgPd?Br^fppo7+7PP@!35h%xiVsaLEEUr?nS2ccSEqa{X zPBoiU{C!Z3_Sv(!aU4e-N$jx%ajuSN**|vi7t5xl8LbM1xV`Ts+Zvqdj4nrF+D`N1C${l zUQ6B7QG9RonL)0gQ=eLBtU*)_9vw1xt^M12>I~gD^TQM?Q>7DA?g^i{{GStb(xgDs ztjWOJPrGx;q^cu$>uF>lLnS8tc_HoGXqiF0F^7#sUmz?JQAFA=6v@fTXI7ma-Ueawpuoi{9!o4HNyYMf@gn& zQfHtaM8O_&c8e4GZoJRN&6%rQC8)+K6d^#U6AgRT!jEO6Xs16f;yC0SET!g`k;~jl zqUN1u^c&m=YJ4KHkNH1_aPRN6)k{7L2qwmi=%LCc{Z!3uBHFM73L;*V1F!l@?eNK% zWS?pC+f~*Ft`D2cEI;1lU<>Vk7gW8&nuM@LPCa^LyR>*4??|{idJtwAB5Sznpy@!0 zw@t38ZBhx=#H78dt8;&9)XYDmMT%FEnuzSzP%0`kSXBJZYsZ1BM9m(zl^RbJwgY#I zN?)j>ug7{i^2}|xx89PU46l4iyxgHqBmN7f^stCM(IUvPk|YMBB(6lG+80q$=sn$X zGZ6~zn4|A4)13v@h+n#VVI)++*-~v1im4BhwlPkEchbPdJTn=so_mPdH(fabIlR$E z{}Mrs=A*PE_Nrvk)(Yp@Z?Rqxs7UBC$kB{i#b>o$OCWl!g?(jYT#T$hLpl9AmZ39| zwIoyHKxgaGFA4Q9*vpTr@_S2}iAk*ch%>4v!OD=b)g|5Fl3e76!m18RHX%B|C2YP* zZbB6+Q+mAy{zvQ^y1i{~R^w&A^s(dghc8cXz3$iJTlu{8f=8rVRdH&UT%g$~$eg(} zeKaSE<501t=O@o>YKTeef&N7k^S*uwPgZWN+>A>cJq(>KthJdNw!|`)M3b%>4IlnK zW(NVuv8yz&oG#KO$YRV%aA)0cz5`0*2+a+;V2htxh&qRj1?WUM+O6?kLS!w^8cIqZ zuqem`?T&uJQH|jwsc@U37V)gun^gC`YIEb;BsPgn{s{wPY*GZRFJC##KfmvV+}-d@ zlsf)P!1y~FJ7qzBFt4Oo&5gk%SJoNGGo}rL4z^43g03+#JIl8$SV7fkpY_z>=fXXv z!UPLkxi;WRl~qJKR_X(2JHDL{P)t}fvc)c>4$dkO@CRw8_JG9?-l3Xxs-5|T0bMCMU5layA|%+y?zS!gXTz9Ov7!eQIb1p_pWWK_gp!^7QmZV~rKBk7Pm-Su)6b{|GH zqeGE^3^^JnrX1k-TcT)N8l=1wZqm(*0yA+@a%%xD_Ly(xAP9SU#+RMNg8ngfDBH|p4bO4@nT*9A5td)6 ziRi>dcal1&i5G42jufTr&G`Kr3eS?22l)f1hAHf}M!63au1?))*Bh#lXhSEn>^A{l zOtM1p%@$qb6Wm~6U?M!9oCjj9k|{o^b?CuJ zTR@#X>gIBaD?NV|=purno-1^E!}i`9GG1Mniw!g5cCN{B&iajsZ^cDg#ChP(<~M$s zT6&mdI5VazI+YIVs}XedL~h61ukte&JJpGURU9^Qmv_ui5(Xk>GCT4^tq_K~Iqull zX30R}S#VTa5p(R9dIKXk#5<+vYy$m$4W;JY`+3&kpY)mOP(gZx=Rs_F8N6bNUNLt@(m zMLhM1X%$Xjx({JIAs-3FU66j;N2c_ zw7@*zZtW9g1xk~L66x9OkO*vRcq7XtSSJ>B^bM<;JABi~9xBscrQhAmqUuIgx$bs5 z{`onab@)oQO{Z9R+VK%8<74U*kyH*x>oP`WILn8zyz;%!ZddK69!ruI=>Gx`@N2+=ZEi)CUS3A zHmNy4UKuNh&8IebqHE$1E4Q3!Re0s7hp}w=ORG6qr|Wdr);*-m#Hp^plIBl3$RLas zti#~hfEqbC^U%wShyF~T#hEQjuP+i!tDSa4&9R(~^6Hr0Pb>x^YM-7|y71WMU?Hl0 z)eoyWaGo{(y7(cL_2zN)dy+PD=BPb>R}7;DEB4M!mk>Vr*XbM5_FcgMw^3^e*lue# z(Jof`Y3Fi#Fd_L!%hf*5Uuc~c6iDA(+XkeJLsfgS&$}c3Kjz*tEY4-y8ciSxmf#TF zHMqOGyIXK~8h3XO(0K3!cZcBKxHj%iaEIGjd+)Q>Ip4Y8{d<4CPgmDlGHX_KSJfC} zzLOFjLUU!`wksp#BgBt=y3WUUqU3fkCgbu$)36zd=lD!M#FoDiFOtlHZ`F}DjV-0* zPL@gZM7R2B0E|#luX$>I)inGwlX0}DO5A+gKwz2vJMzgX)fv{9uZDq0asF<_WeYG7 zYOUMjmOanhpdFAqp7A|tXPnR`$>2A5P?=+Hh#7sHY-^*fFli@2iceO8er`xvQb8G` zzr+c?=a)4oXK`QB7T=0Oz)1_KR@B->7Cm?^PmD^)i8|YFir577QfP!W`qr}1fd46oj@$E<$+_6^s%EYb za8={m!bTIl7QC0(y1GQma=z@w);m^BmGGNOR3YX4S3W21e!{F~ky8mDtrTuY?wY`^ zm^=^L@)qY}P4Cj$qm$)ozc`5?2pX%gvd+$?i&Y+i6bwp>}%7{C=6T!4uZ|8l}CXO^3{o1NX@uB{6>|B#~AHm zit&o>_&jC>-d6`Uz*dLmOdi){U9UdTd(Tx=V1T^O!qE6#t$b47h(?AQAUra8O|Ap0 zy^Mj;@0h5BBY1;`o@?Akmd8x%Ln!j4fdY0~pVXd~LN4L+xZx+(ZeP zKshe;M!lY}K1*KWMF=wfp)GNd|}Rgd;p*|^XF;lhXZUGV1@I{pL}*cc+tgxVke$$el%#usL+ zDf%A6rly6~G=V+0+n@xWi7p8e*`x2kAzDVZ($9`gzWlL|-TwaceQmW5 zHzU+}7U1iss3ly{dmWh26NeDQ=xKa%=7syAIxfe=K&oct%&@F=#$04@N96IFRhc4@ z-@1_&O5*-1Z%kVl@#$UL+hXlJJVXk!tDAkmEUs#gohC9xj^a3ub3rVL_;)K$!{R_s zdGpkT;kEeJF#VESA^&>NV8=dL1ZWV3A%YDgX?NCf+kmqHz!@%8H6LnXKTGS7$_@-- z=$~W)MGZdvq8}+Yrpct#J##nFs*glH=POuJ0rr~ij#Ka!>il&&eQy0Q6k5=y9^dsb}7#F+xf<3+A z4tF}z;DQ8UPzh6w`3u_c0E`}SHkZ#`_~b;)-iu9SjMLJf_0Y!g=&zBTt#S485<=i2 z3-ZN!kISB17&}QXny2U{DdT84DG@s&Eh*oGHg0^y^;Q~RIR~3du#25JVCo4(gtgNz zkHWDJIlng*^onYP)?M&*H?wD$tw_Jb*7d)*Kb%w_@dk%06wQDUW3b*zE2U0z5n!X( z;jOjps(ZgC*@&th%-~Xh`^Fe4ImTi0j>+~dwB+Trir{X?n*G#b9+xWC*Vm7#WO-lq z0bk2FX5A6nW58!wBK$W?myyLh+kkcB(nZMcRKXP(5YmuqaA zvv~2qwXKDC?Hy+v236LUYr6Bk)UWMZ*Oo}2|M#MIvF3kpl6#YvYNJ=bfd^9lM7dT=SISxrZRfgVoO1vCAEgzdz?ivH2D4wThWr<8gv?~jiz z=l5vbd@~#|RW4IUmS>!c#Q!1k>33b)cT|M46!&CqfOs76XUD4ECh__K0uMy;XYnkRohK_m5~EeL1v*uoZmIGYj51~Ze3F5Yya74uq@ zuRf?gx?RgQ4uar?9RTdu;$EMxOme#&=9jl1j=yUG98k$77*v@Q;_;@@*-lVTahbKu~r~aV*26~aC$FF*cu^1~9)s%U(zSKw8<`h^EK(w30cPoy1` zk8-k*)_mA;Px4RYvuf`(HYV8v00m3h8P`W_2GeiT`cr|3J_K zAor7`lxJ9L*LOB;4cdQr6N>WwY!v_IH|4&C6%`8`Ayv?42$Hx;{zY^~&GD(~-cyGh z4Dwm;aLDb$B;zrF)`G2Ek2#TOh4336U zlpX!eSNRvz`=7Kd>0Eu-k~A#_ECBg`1GN9o53HDLF3bwKY6%{AWI}n!s6!BL}u7&?ik2y5e z%T`y`)usKC=1G!2{dY4BAXjk*G)!3r|FefVu&mZ|vQSV^-rC~k>i;I>OlZQPV_>k& z>G6DdEM#MegEw0V|37#^|Li@096}`0gFC$VpWXcr{pT-I5grC)@gTq$Z9(}@!~fUp zhtd%4QVZ(L4rF}(CmHGQN;$tkY{L5`4e%FN;GYBh-|C$C2DwB4ke7_m{J&;_vH(E)cvt{t~3$+t;S&tOC{{A;c%N_iP8Ekro1TXhx|QL!2J3 z}6&cM9B zY-#}*RJ65v8x*oHBHij?ks5Z5ok-ySi`w{a2fkwpc<|u9+QOeH`pf*Wlu&dcf!j|~ zlv2*&^n`6~gOCmAQe(moBz+=#ULFN`!82ZtWj6VgF)-1{t{vm0glK)r4e9MP~3(kN4x=9O~aENiz4OuxEePq7trWsL5!g(x<< ztF*}S*NYUMJhxHGAnv5*Vp?JFC|RB!3fM>ufAcs(WKBz3M4_ejoSmck$`64F)!u#Y zMqNzu)HEwwpcFVAP8_J%_Xrl$1fQ_ZIPuB@!+)wbTlJhXEg|v3KG1!r0ViYvvO~Dm8m&vvfHu$jBtlf*Wiz%6uN1HX|Sg|l{K zQuJHSwEbvp?MkgbXnPS9Wcl*6L1lq!CG*uyH*i#^PIzh>Nm^4A7n|n+{a~7=p`o;N zen)wlnT-6}|Ksu6NSWK*=gR_W-qciC&SL$>e40nwKa8VBKpVgwvR3^T`QOp{vfk%2 z%S8~j%D?gY%Bc$f6R(d1C--~6qw~e$Tfxb=Q#m~!xsKB$^pQCq57fw+qX0eOFK|-P%uzuTq5%zl#VHhQ z8DRPT5fby`35to?WIoF<@-kDFvSQlAFNBkE(Jf!79%jpK-{hf+XtS~@CNo6QeE7{p3mRA zZB|i*Tijnz!fG#)}V**IjF}yVHJ8K zygQx}cPT%Hb|sluLwMAs!-yg9*U*`|{YY7z=G&z@a%zde8o%OrQWEwgWVuF~op_hP z-!pVIAyOG@Va7?`RTH8)cG9EY(pdqIg1v%Mp+O; z6T`2*JWy!8V{$n5Z!lX?JMja6mp?M4?!~cm0~kouJUT@4+TM(z@yOr0oI19&p1ad6 zWhzOH(u$K^57Pm6H7N|eK-rj$)p4VxemK7rd< zL|1$X=C#mAjZXP;lg~>dUNSlRDacaL4xrD&W|`y5pPc}#YxR8imhMn(lzfkJne(5r zRw-raappirysI7C&qpUa5zMct(EXOZwOLB5dxlv_3bqCZzDKrv*XMd_N)x9?H<%bF z{0z5YN+(f{exv-VBr81cMn0LlB!{bi%YRx)<;fP9XU*R%N*$@eIqsOUT%b=@+Qr|F z?l3fS(qkb#6%>8KGVy~D)^6l^!5yIl70bSgDO>z66Jo3HYZtAjN6&2OvyEHC>f^2D z#*L)K)GOe48aG*2%B7&JyLg@2VEqFB*Yhax`HHo5!!; z6|dAC6Q9|a+Jxi0#OWfHItGLu3p=Ia)?$C&ENdQjSyUVjbE5UE_04a zJFtB%1@H2VB$~YGJ+)S#iSjqC50x-KjpqR!S&3HtTsS8meO}IwKOF)cuc>E0d&X^V z71F~heXYxJBTYvZX6R!rPCGc!PQUl53GRmby#=CmU`Q!0zDl^&C>nOs_tI2g1_hxW z|1wVUY921&_ej{@3p3awh>AZeaiWfJ$U|?y`cz8fhCSK2BgO9-G^sPqjZ=@tl zjMF&bFlcXQl>+tDTaUL}I^Rg&Y>=QmH?SPUFMGS1>&{$+7yXFF?sh#7?)YEqR z^HgG<1}tAFx`f;*dc|?FB4r>9!YJp>^%;0(dEUq_z)&<*R5(ZJE!dALZyNjlL-q={ z#wED*U2Kz<1CCrDo0R!Dhx>Jnm_0Fmv{~}Yp5_i?z7E$O%!rtiFU2{` z%dCaQVXif4` z2yd<|e@eXAOarRx0ol90d39)hXH#ieTQt?K^VxFt=V-NUryF8zjq~KGDD@Zm?uY!~ z$FsT_XzUsWF10101>2~S+2lHxgQ*{z`eQfbr!omCU33L9dlq%AR+P=o?cBaLe=wRh z_eXPoHp8D#ziw~T+#l_P6@s@DkK|cM%*3_j$x%fVPKcw-EBS=|%UF}PdMND~Qo)2k zDrkvbLF95g$AQIuIXsHy#jr6{80A`%$@!xKXW4?XJJ)<;x^Q%G{9v2%0R*qE-zRHl zV*g<1@ga~Xzr#0TJZ0dV(F>s$8{QjXjv#(d5v_{P3VP~=a7xJ!0#xsnW$79bV94X& zIq(tL31!L})s;2yxwzERPvN{M<#KN-a+elz>}v?3fKNnPLLW_|@ST>yMNareL+M)T zUgB&Z!=EQiJqiHuE?fo(YzXd@G`EZfP;O}=gs|2RJ?>fDEAry zPnSCpzR2BwAlGND=$6rYm$#B;_HtG4Gg^bLUs}ueh%|yWf5R?}x#!~}mDdJAFFzqc zl@zDq?mcW0i}HF~B4MlRTb~=wFq(2de=_FgHZOH;!w1#lBTHMZ-sG%#fhmrPeXmv0 zWkyZViN(+eYS|k|75@o+1x1Io~&8jcv0lFR?TG z*(D%LUd$wY`w7n;KL4}uT_Xy|@&FGq-Q&ApOZbL1R|`F2*B3igHx_xrv^{N~aNyb* zC)Fbh{7zsLP3LbD(v{~Lm8FdIpUeAJu$|+Ak_4F3;_2UtQCLuujId+cFv}EDUq!~0 zo$Y&=UT@7?<*pzI8Y_vMH*r1Eq7W@VXnk47wE`s~cz;fx_orF_rWe<0f{QxbN9klz z9sk?>qkflox75=l8i$wUZu{Bz$=g3`$?dp~YF#^h*2t(xFLh-A$_}Wk6?8(;De=ih zpG9rfXZKoq08NbCOnspY4sygc)6&k>kNwNq{0+(LNxjej%vm3LiiK{r(qtRMZ%&BB zH-4ImixtvpbY#Cm#t7o3XJJV{tnb`jQPLnzzDr}iT$>&6e%&T1E37BoOm)FDO>I5; zCMVEyp%nRh6Xr=BHe839_yWKSN4ZHKM#6zfIM6tuaN_-~w6&U#g#IcsSre}!F8_}v z$|N_{`^!{4H#L#SD5UnzF>k%#=-5LWxNIJZkM@+500!sShA@%GTlb>P^MhbVxBMPw z0unAuZ+%ysko%aX0e)!1mF(7}4M}gpgmf1Y)$CRyDe)biIN)N1F;Ls!wX zaA8f2pYsgYR#(QHdb14_saOOuNZpn_@q@dlq~y7X?Au=>ASXwoqXI`!&CJKWZ!1_G zE6yBz1C9s0bq$QBeBt2XlfCRag?zOdrRK`kNFb7kDdQb4>J@EQ-qV@e&z2X!AT#j@hwr@bJH6VPu^Ei%(U$sZ(o{2Lkzamo zKu1R(OfF^kCZDDNxod|UhOG@q=oCW^bxFy8&79e_=LO?G*V)c%*Dzlc1UFmnq(BK> z{Ccr@tX?wov}zcAzLEg4nkKisjAoMVj*pC`9+%ZvB)4UHCv^|W`z>1=PX*~k3P5n_ zjWGwfcKY&7tNi$B%Fm?{O`8ZC5^gyb4I@{}E0QWJQ5GW>E;Gtm=fu2-n{y(cQ^kTE zefb%~Qj2fZ8{3{=$}R>aefi7XN~G8rf(M5iYy!f8aa3<`)htsT37PYfAA7?;T7wfB zUg$|~Eo9r}#;N1u&akcclP=Xr^JC(N;8q)~L!=_L&{)0)?qM2&rva!3+t2-nHSHy zaOUcS%M5Nar+$}%U?|1vbbJdxvnd=Qh!waS<6Hg6l{Pii21!n_(vOX)yy`rg~{ z3DpR#&(A(fBI_i)`&iB#T0fc(TWmY4Nxz)QXjW&>m_?mpT&b7yu)fbL5(|nri8DIL=&X2app_)4Q3y!eUQm&A-4Urt3`P{g12 zQ0foq_d20LK$XSe#gCxvyNILl#F|W+^kY#clXST1Qx=0~-sv<^*?dY_2Bp*`3GYyH5_Zk>9yKLIs)Ah*LN8fXwH`Fms?_TmPg1-{Kx zvMO`b57{s?RGE8{lOA$UDB5eFl5M#Dow`EG<)Xt=Mr+S5hd45oEvy~8?->zsGI3n2 z%=BcH>$~27sl(NIoas13`y#j3zxMi_^q3!%UZ=U7DvcQW-rA8vW{#)Y^;1^3QE_lvz>$P zv>Xq0C}uCsYxJoxIt?D^EPD+4)SnF))x|&Jn(XSed4DTgX_^fO>NK2)1|MRE|KyOi z$UvqJ4Z11hFl$<>G6mDySjQ~00V3<-zLfru`<}8%9ir(bv{IiNd-wj2D$^#T1u5hZ z|Beo2FrZ|i)Q^(uJei=zYRK$>rztAaag}H&jHpL)=otCW<0tY_Ij#L+Gk%rg3#}4BBlU_?B%lqb}&1t>qL+f4@7+i0-+|b9R&3E^3 z-O?O0y+`4xm>o?sy=g772wgqp(>AQJ&gqSgdqGTu;fuH)U-CY*eE&dpbX9Mq_Ayr%K}_+ zroq&2ev>a@12!`UVrwh%TZKN~EG9C;%a->X-sI5SG|0_m;=wx_zbEN3BDzqfx~I`k zw`4QiY{DU-Cbe0y4w>85HsX`EMt55AU|}YIL#;RWv&HV@ zmJOd7zm{um4E766MODY4IWlW|1aSMP?q@7pe!MHu@Cc6ecQsQm(;6g_b-p6cBCplya@xn zG=J6&=78EFy4A49e#PXHs{TQt6iNqew`9uiY%W*r&KVFnL%yP)B^I})`R9+V^!y{U zTKGp@6y})HvNH)~``x`Eq|4(M$m7t}7azCo}rUE$jGREt%8&{oI&6O!Zp1^WNq!mkIA=7a*^x9HX76TD(Z-nr!Id0;XYq$Ko6A2bxFTvolwG5i^ z?*qGmps_TShS1PQT#oJNC!mT?vXeIx2pE~-4DHaAyIY>}bp z%$Bx2Bfdypw`H)17Py#J$~}+`6B#knB5aoWa+D1&MbL+v&|gh@Wobj8PzdoV5DHpO z+RaWsgml?^<8A=_#H7aqpU)R16Im!>!$BI(ZEeY;ZX7J#K!Y!A2TvlxVZRcRd{<)* zzRqX_J{QMJS%>arB!wX*-XmzFjobLWcJS#5Q&7h885cYq{YXWw_f#aQ%CUNp$-Mvv zzc#4o{B`+f!TRpzR658(i|V{p*<>r-omAgxZz;GjnQ04VXz_D4l}GsD?^$VNDbCC5 zLZ|us)ESG(_c^b$8f%^@$4fN|bNQFKzXy@0-%g~|dy!M03dYPS5wg&Q!CpZt*A;!g zwFkqE`k4}uF)2eRMJH=mHp?P3v}HnBkFE+js$x*nmoz)oLn(Sl0tRzw)u8h zM^3S?k0W{|8Q`V1VDN!0G3&QvbRk zSmz38K)=pgjN+Xx(}EA|ZvY9EkBhu7oPwFmG00tYB~Bp>N533epj21_GGJpYBjLyZ z7}Jyb*LYmtxCr!e(cok-{8o@-COvLb`-H9c!aV#-Rzl7SKIXU$RP^fgSn>0E@u2j4 zlnt+w5*@1?dtfhi)blgT$piLVZp`aYE%1{T?-rjgpi&y2XX(D}6UrN%6v8vZBIP8` zvke54(Zwm5=+gLkI*FbXFhJFPuSRW(W>=@A#+08WpS5d)9gpq+Ha@2f!Qli zKUUBg?lq!uQV~*p3<}eRVue@6rt6L~nT2ZPniVZmEzwX(9KDi`C6d%n9~Ak!qYHmV zTkfBl?R6gKom2dDK?@!tr}1UIO^5>F9!25+=o=r3>uX@U>AW1weI~-g8Ks1uWwh-G z4%<>C%9l*F->Gu~n(aYLIhkRPLwiQP#YRPiyE#3PrAq?f;_|@Rg4Hv!|D1Vw>lYpkW=9%CoN! zIxgX{2i{9idVxrS{7@=&$0*ZbY!($`Bm?|)A=d1$eg}3!*VUSVtLaGi1+1E#+vhyz z-3o;yM`%)%?90vDW{vzoyrjQyo%w z=w=d~`fX2fL^4oi$@C%a5aTiGDE^kzF%+29h z*Z;xn+V*%O12CcK95(>Gp4!b*Kb7QsW5K?ZFfa_<)LuJTe}F`V6(4V|%sJSI-rSI( zJCn(IsUkF`kVfId`C!;9SLkM-De(9yV6+W&F(S6meUQq@k(Z$jeNVkl#>N&043|fc zWj=?6|J*HS3Wb}`T6w>w{rC-=-Q~)sFh=dXYre!HMco|_f23OWLtn4g1Q6rQHrqR`W&PB_L_wa~OuT#p_cvSYbhx-^u~RJqav>JU zt^ULq=d`Pk(=QoH1bi+4o!GEIz@#<-0>-5+>(i^F2EB;Lr$-C zJUbMfqjV(tcU`9Q5?1mzOK6xy=I}<@ALcjRTp}df{Vd!Ojc1uhzga=oHsRwKMYcM| z+ifvUb<>C31<`%1ektC$&;fqMTO8{UnBcItOFFx$ssseaxi5WdaVWAgISU$;x&0Q~ ze;MV48TiQiG^#!EWP3+2*)WOxqkPgshj1@L&p_nk+CTX+huATi!%!UnR&k39oTa$B z-xd3K12_VWpDM#88>WxA3v!!%%rie?FDS_4urC}#Pmcm$_)HWHmKDB;YR-LlzAAn1 z1Rk5u?a8aTw8Zd~Ycw)**R)m{m|iR@*nX~vv+WTX^KGX1YT{?rLXA6%{J6Uu8#|x% z2lZiIV*M9>GGhs<1_9DHS)4!FEWR?(pe zEC4(F&PRG2?N_7SUPGnC(C}4(_U8BVjw&i)Hy<+xl1998O_M3!pFFOveo6gKky)!= zWU0&dlH`&rD88kAVX{FSfExZdfu1?ugkHdw=RwfI`2nS&tWx_nRagN$V|lHxt|4lv zG-!fOl%;IeMu132ik#DP-M#N(PR4WV&t}ogSBxLC@3nWs8}o>RF^0H~rDo?9Mj_yu z(%&+CiWzZq^M<5(sPTzXV{>Bq@v}hTFa&1nj`Cx@?ADqm6{1J45dZu&hJ^A-i(V#d zYeE}!w=m6$=T;^ZdK={_6civ*DFenVGU*eTkf~=ASG5nV{er%EsBMDz`}P7)6spEn zmc*sEMtq1Q-3}o>Nc;* zJDW+0Zro*u4ffPdp69T+_Rm1&8T;Tcz_{k##nE`dTNCIQ)9DcC7{nZGl*LI6WW@VlC~Ued6!z_mTGq>jALmvAAZK3 z=|p2O-Q5!KxE3E6#GCT&=GYVJ~zxdUKg4=*Go53Qv^YdCn9p*8qx_eMjnD z*(*hEGP83G!a?2_eBut=pNkxZ<-J1lgTB`$T&zIUExpu`1jqN~iIYaQ^QVa;bH*}K zhqTMEhe1J_yFsoORm99EJB^cYlV-I@$8tUp+Dvp%pSOT_74K!Y&c)@D9K|6EQWm<; z%NW!&wleO_z3Qd?A4ux$`Q+Tc0EwAz2%)A_N)-yP3yHl4GXZCc^CawSqw=|$yH76% zM-ORXD&jYbGo9x_q_W%OsfG%RWm*GgD`I%?WXB#rYKQ0(+OC)7i{ZCu2}7njq+(0p zi|NUXrfI6X_R#QN**4Yl!f*zDZ=!Lbchul#LeVmJ7V)STY-;o4f{<%0?2!H)3y6x# z!bj|^^<_W#GP~ByFr$MoKb&r*%A4V{k;q0c@U%5o`0EzyoU4mnPPArHRDzgn#`bwn zZNZ2*v1hEGcYp%{Dd^WT1WKwhwWz`uA{{AsiW!)$5vPl4od;28>>Mn*Y8f9GkH+%G zZ~r-s711qFy!csfkCg`$tD6bY7dto=fy~Ki+Zz1rrOlYE$L76N`bcunmZ;;H4-kQv z_ae>=1Ynq-QVjooDjpE%=RIkv8hiQh^ArMRN_}32PM{-P(Yxm@oNzo^069$qvt(To z+8d6Umm3EtZ)*t0CYsMOf8lsHNGwaUJlt)RgNH$s3Q^Vg(TC~GElJz?`TmTeK|0Qz zm5wbK*vGulUjX)v&+=iP6#TE`dQ{5)v~rwPYdI|1A5Scec_vVB?RycEU3GC@WJz|HTuD zds(N3Yh_u2goxQzko9>l+^p?03Q%@3r`f7=!-8}%3v8S11wnQ>kxz|K6SYOj ztE5?WSw|>&%vBG%`ds+{y^j5rA3<(I4=GWIwp__lQhY$T_>*&GnLh zP5YGms*)NFzvsytqmhceVTrw0cR!fO8Sa^hw66IZJB)ky+hlh+Q-r5qkZjyIPAf!_nU3+fVj7tGl9&k;(=J$d|NTK%w<2@gfMLxY!-bIb6&wxy%C zC#MV3&uQ}RDI|TFKhDr;7VqO*tG7sReuDHTb>6*)3z@Gr79W<#0i`q}q>eNjOAOU( z$R=0r(IsH-&xBA>K9)?*Wf!%8ua08a?X z-jy+%{>saIp4k&{mravo}4a{vGfpv9R3MN^3!W4BL6Fam~n^T;; zJp~)%585MRFXC(x_KhCqABySe9 zPNH0|_hO+fjsqsnKL?G5dyU{*q>>Ilv==_gK1=($(fJlH=HDl+E9|}R>wop`(1FCg zXkWxs>GBh&v|>%^`dYA)HRuG}f5tE!h5Zd=A+uUa7&z^)l*xH-1BgUX(t`RW-oJ(z zwsg5a7-wtL49jh4hdbW~8*uul2yygVK(k+klv(g2GiZE1n}ALsVD_59juC&dT6LIA zw3g*?4eX{H*7y;Q`+onIQLzB}y$7N}pfS_CZcvk zw@9FOc8i^CU1sI_RmNeSIW>iam|H=kD%waBPu$RlD0n_ua1$>kU8Yzlj(YEtHR0HZ!y`qd<*l4 zLcNityXD%;CD7@2m#rhWBK<)R!sXDE2+LYStPK3kb^cUMfxqHvF;nU0MtZori_Z+T z+jF}dc-c0?sCE9VP}EVRw>pP4HZ;Z(NW}xE%)<}sey7Eqw~@W;D1XTcvUG)n$gvwN zjk$E#=eH~73gaC)Hdom4K04;!ErUBVDuEmz{c@E23YurJUa@-lt>sMEm?NUt)Ixl6 zYHg4_MauJPGbqP?*OIYr_c-d+$ad%Iz4*opSdi+=Vr9#WLx!nj=sg%G+#8nuit^RI zsBDA%020o}IG?IM{m4J==kTfoHT4xTY%r_m8BwH*D(!+-->Qa&9$=+YXSqIgcD9}v)5Z3yL?Jak zb>3CBpfIX1EL?#QD%4Zwnf&RtX&O)#=N)I5K^jowwDs2O_S@siS*FNE@Vo43tj|EL z5};N#G#{#y%Rr+(mbYI1Va^vt`(R7rhVg#q?CYvW&XMBHZzh@MeD|1xH;E;i_tYrf z+-`iwtsHTYJ?z}@2v|v;gfH%=ytV$1Is@kA3`lV7K?^362=99vRTd@loZ*vmIE26J z>-8Un>_rZ_Eg=20;?+>qBRr5QK0LNp>l3_XAbd+fmCoo`qYFdAPEVn%9FMi1G^Db< zTpQXIv(lI59y-CN{lk;9`bp=bB8fLwoxrIE_TqaTbW1X;gN z(5g>4SQQlAD;5=9H(fMO z97!8Gr1sPX8r;nevCCgILTvn};{SR`AiPyGBcR*9Zi1vc2onijoV^TGauP57j8XkZ z{r_&ppNAC=wCz1iqyW#(6o1~*-b;*MYPvGC*sKWfI2qscH^zXEP zTkuXa*KVanxzpDt=Lit;pRXNAh^zcwU(kLu&#tP=y-_`hw+i@Y_5Wr5zY`VFV5xvw zXeCy_ztjFPPJbsVp8U!9|N9bW%5PBX1^?~898ek4HKyHVWiiiY1_w;>f{kZN6 zo~PJJB<=8L)wvt&oM<`3jw=54%)fi=5KWvrJZgL#Yzcr2?fQby*UMNNkEdF9sRhU1 zO~lL*{8CyC5w^y-v;Xvtzo$2FobFSOV7rDGTUC|+ z-O*#wA#Ukg5I?sC8LnS&VS<|=Xp75p8MBMvmL>P@tR;V(%xo1hkM}TSd5%7oSh|$C zJ}#tUxfCc1IxdP+H|Wwqxk-hlTSQ#VICcs!ND&3*pNBi1VG7lfh~UaAFSpq|5bJIJ zGsFKi!%)as>OcSG9f~5bc-*R=WQ8z}TrZ?3hrWx1z4I1{(Im2sR#>Bq^Jx>(Z*R`1 zv%}f07|1#+`}P%?urm7SP(P)nRgu8mFYD>CzXBB>^H^VBr(+acrL&rrO_sB=HemjZ z{cM4zQcfoE1o*fNzOtJawZp|Q9VEEz)_w{pm~XoVI+=}QDiyYL_T>BygNT>>ff%s!b6RHv8$vGA^VLtHwugiP5orw@@-apfFkfR>qee3? z9!~4na5@^as2#7=sTsQ;UeTZh9A%Qd-{&Cp3>`YjH(Gw)%`xa3!6jKj3yc&xWY zani)_TT9=vJ2Iph(OQpiR)6tr-a27p-l)i)dS_eq^JKNvfIlDWr6QX(sr`E+|Gqid4U~(u}`hM?X>bA9{kHOQgC+dB39*V zoz`FO3|V#@=|pxernMh=d$+|b75PrDTlg^_`CWWveOBn^7~rC+|PeL zPkj4L6@jY24jY4RB_C(_B?!j!eooiJ&oy%U1kAt@8=dG&G|y{$-Jq+LnnV z;Fl9lCVrpY`tGV#Zv+|chk?Xg;coNL=!s(3PQbgtVIHzpA%0ftb?MkTb}o%{_A(8c z2w8T_wyOKf+20sa5cS%5osU{GI3_lp9wfDb*_{AxAu|pCQ2IAsAL>h)De!U|2jZZE$-W=z~89xMsrYn6)UUv_u~v4GB>Nx7guaq1-4O&wTH!Q zt=ssSTgdT!#cp<1DYI|iHo8m`Q2%NV>dl%qs~lo}2T?WnkUa33ok%s06qj7<)yTL_ z5b;#pDIZ@I%CjwvoW_bU|2+saHSB9Y&D$iaGg5K=I)V$LFSC(*K0C9gQ!Dn%L1&oU z=(?a>c3#{)7qDfSzx_sjd*=5VPZc5tv;E?19E18e1_UE(Xl`pW+$#AEOaTTkp)$WN z1enw9B8-u#@x|X;4NyS!HGOR~Cb=fEQ_mDt2HaPB5Y*3+=%6NkWD<6 zLb*F=zz>G4pBQp_o{;po_!)aqjKnb*7}IL{eB%vguc}~&LqJXlTC-agb=x~hUBK+x zHGSD3Y)s*LqW`!_V~tJ)h_RzOQn@sBaZ81_d4D*^Qh^daPof2f3J{%VRN;ji&#sPH z4wLSCLrUyZDH?zk9h4Vk>aoNgAKY8O2CIuBl{-@gbud@--D_IT@_q_FO-ne^iBXyUlnKpI4L|*O*XMiaB!YP;0I7r%6ZG*A%CtaH?7aHODxg z79~{2wtL)~?PY#C6Ae2QMux<}Dx$aZHV@sF_&w2&4Bx(%HttCI8de9hl`!xb;{dxb zsuzMc4kZr{J=a8=$L1%BLEeixh_5*Q=S9ny67nbHY_7rZwxmL2_<8a z7(FI_eO1FB_`ZgNhtg*pxg;uZm}hQHBY}EH8=OxYl(}9*#l&OuM;x7@RrW>(}TTO z^xi~6J;{77N2Y@7GTGc$Co)pE&bmGT@@IWdx+=SuhnjL8N{t!^IzB&JbLY7A>*Q=S zL-YzV7AdpxuJ+@djFx7~uO+Vk4`Xi~6-Th`Z3l-y(BKZkKyV2@xH|+78Z-ol;O_43 zB#_|lFt~ew;4TBfVUWT3$hqg9d(K_&x8C=!S<~ICW_MS0P3>L3XYWTM`EhGe3(ppV z#qU>jq1YP@&#zG}{CE%#me3vID$A7&Yb84LTGja`)uZnPPr07PHxSbpVdYaS3TD;2F$?6;^IO~lIQW9te=6p|`tr3@a<5tNq6vQ#i1 z!T9=;#ro%{rE2+oZ4|PUEasY=JB8gK;!KSh+a|fwd8p9O5ik~Xak|wbK6}0D2gW65 z2F2&)n~qkdCRGYhlWl$*A~>gR!nH^hlqJw$Mb#vV*u~DM*^pW8XE8^S!S0xtEojkP z9}|<%aL7B1lIKl_wc?y4SWmSaZov!b#OGwsOp9Vcp5X-Nq)aJHzJtE>| zDM7#MF|Wn+vM6wTsfPj9+h~1w;6*e4D8c!O(s0ZuFEbcXl9m5A`nqk(xq~+ObVbHk zK$#VIN8v3BtXE1)OiA{8j5Oy3mBwoYQFpDP1l7!r@5#*uNbq%Rs8u=q_aW;qWf~|d zGw1!?e@wBs@Ek0`nQimLOI3(IJVJV|&1ISFc-iCCHcqD#A3v{*iD_V$WqTTll zDsfp0kcW$9Jasp&#wkDo^P)MI01NWv&f5t9?}ILB0fk~DTvUMC2>fw~Fv1Ty=cWU)wVj*5+jEmTP* zdEz4V=dh7RcF5vJ`_zJH_vcEK-qkdHzM$~%vZ$@MCudxwa+g~Xc9cTlTDXDRd!9kE znigvOcGTbEUkTA8LC=!P{R`# zZ7v(+c6#KYga6R5?re&igdo84PQq--)~@&VnoJ>DR3tqFt|MtI8;S68hP`XAYw07? zW!7Uq%1+b|K@5(!!5xxqZ&?=}>gISWYlw%g2Vc#lF)l97K`X`dSVh{eX5r`%AlgNC z5IZbadDGPWO;I-DgZWk@QHMQ4GLJwWrpKI+Ywc)qiUkOu*d=z3mf-DLw7<>yV>p zD-7z+93|;e__PI1HcdR+bpD~eJP`WULXS_k134*&O=4Wc)mVXRu@{2h@MKH6sk@f{ zy$z|p-7=>Ik3N1qCxwPhd6AK=r|ze~*hPjOxp{3ge%ZW2n`;f{&TqJ%Lp&9FCX2|6 zndwI)*|Fe5_6IeKD_^!$!%*hvh8;dBUJbRbsZiZ zO&c0QwIV)g)pp2XVIzXr$SHE1x*ad~%c?%!B?g!}`lwC$E@mdvROqEB10lP|DL28A z>R4?;qXmwgW@J^$s{+%)tkNVr%syCOZPo7lT$L#faspwAj|?K>3%*6iD=Bo#Gp_Oq z*lpwAJ}ONPC8rmEPwlOClMlKcj3pYbw`2(}BjBv908;lIArmJhYlwoor)Q<%pKGAF) zYxaBgzfZ;5+kl{&$x0Mc&x^OXa3x3Wt4^_Z0Ad&=I?k>`IWOF>-7e-VhDXD5hMV0q zc%N*ifww2H9H+&1KP1s$f)x^Yw@>q5ll%dQef>+x`Vlr1@Ghp6Y6=yIi!xiOJLskl zZe#PJ7;hqKMvb!`Q&;;(-0z`+;NK3H2Fz`X0t+@I7TL4>Y5~;C6~(&2oS|;c?e4Yh z2JC+rccN)xhU#mG@A{oLIuKnS>Lw&!lbto^s{cr^qnNQ>sPw8LFn zQ*k_ZbX=!I#|NgalzM)QX1T~5@&(J3DMbK=TsSm^0+P5Ia?1AVoUcsOm}_}iH1@P} zyX#`?ieXE)k=+$5BV}=fc4>5<1@E&g+Y|!~pS(~2bgNYr3CZo>g3X#ni$BHPQGhH-=)`4GE0T9?rO=W)kz28}zzuPoZTpz1h#~}s$s@4c@ zz^d=)yYPxcAkR;Fw-$@aZ5e9s*Iy}i>eNege9UIG{dRIpu__yyPsw-Rtl3qQhxp~G zQp}RLsNUX*Xd*g8E-EDPKJ?r1xLab{5g~x<@ydMC3%!bIuOTJkekKm}m;)J6goO|` z8%hBSl5XzIaG_dA8GElvcK*y4P>+r0v@Uu(a8DJ32;cs;@(gc{Emva>5RTLN7QQ6*6%u$=7;D6RDHZe*fJ zO3)yY5tmwon{-!bRa5lh?n zyQfGendUNPsB>yWCh=k@;InP&DDW93il03&8h_B3XTg&{bIctRMomL_urp}obEEXf zVep~nEvKt4yEo(xSX7PO=|g~)p_`6!wxnVYb;yhaH4X)~!I>h;rCq_ioQ-?&;v{RK zpcg|p#ZmxnDAQP&_N)88$U@Nek4+EEee)V&ZbG~-DC1l!$|U@nCzqKEQLR%my}Gc^ z;5hfh-%lEcmvbAQYkN1j-F)30(R)+ZbiUK*p>_|?QbR;06Xu{WeLGW(3jtY)qk~w! z!OIVul6377eESr!$9l%kz^_38NYkAWXovdE&+%4*_vGuFncaH5S^S4%SLNG3P&1$} z|FwnK99_qSIc%pCdcZsh8`67bA)Y_vTjMv%&BUj>xog~OjV$)Mag{lRGQ9JJ!cBB7 zX*n^l&AGL_c4q?S1pWBL4BbUsWG8!4+1|>W<*Y|{AN;oj!-Z8vBa|o26n)0Qg+ERc zU$PZ_IGC%jZhYQawwms=$7;&r8(r2`We}_;A61ZBrS9$)gZ^sg9fqb@LtvVR=BH~u z&?}h8a7tRXb!Ji{t%RZ1y+p)kVnYir3e(NRb;uyG^AFQ|oyDdqRpEOmN{j7E3YETr zp^7p{E3n?&fL6>nG#GI-ZG9r%d6I-x0tJg5HdOU;R7B(${bH^A{%fmwo{z4l!wEev+k|f8bhshMzrXPQjSHS!6g2!JDD+YyToCqlcrR*Z zN2{1CuQw`{8`F?4{Hz{9hd@@Jtwa5Ef=$!-9I3LD0Kue^T6XyA-K~RZ1+7wk_ND@j zsrl|UBqc)o55d@ihxhQqdts&TV$wDYj^>baIc4V1k+CF)4dVi0Jn*CPvU_>qFyVh|?a$Vsx`(ETpBADqC&Yuvsuj>M4KpKlJ^A{3uaf(dOI z!JlK)PNjttBUNjpwiWUl-Vhlp`Un2{h_Tewo!2m-TK;q!=z2}B;Vy*Xm=+9oN>;qh zBS9y(j2;-*tg0kW2QiL_i)Yr!Gk3k3PZK(2nJ{JP?|U`d^*B| zIh(nPNfJ4z8|W)CjjFo31_nqXS0M;ne^%hNRFEG=+#t8?Yo@1#FQGi;22<9Es3O@! z^mZCM^^?%oJY6pWFS4yeyf&p*s!G;;F<_pIg7X2`5XpoFG*p#o*zMVc`o0pPWwLxX~DHuTl8(b>-5YV zFc26tu+^IPppY3%t??$WWzwgqKR7xar>uS?+Qep9?pRgfqT(={5yS{TxYc#g7_&rRgdWa ztmqgnpCm?D)wk@uHbOap0d>nPug%+5WJC67l@5|ky@42;ZOnuXm4>GWn4US;+RTk| zAKE1>U&s4;Nm)2Tz}}W55EkX;Cyn8vkJtT25ERzeDi=YLR(Kkmmt_8MEQGNJQW0}s zV;j6*F-SMttK&iVmO>#=W!v)Tg`PVIA{-}~<0kTsj8N*x%ZYmO0N$D9r=r0p!*CU9 z?=Mb1Wq7+~`44LXS($sd?*{6{Tb{vun>$%EeAJISyysLSheHK>X=@_c%Njdgk_u^i zVsj@px2^}1wJz4R7?hs!#8=-eJ%-;2?uf<5yde#ie@F#*9JWvH9E=XgKMSvp|E!96 zMm;&mdXvGwe@IEk$|GM1k272?prO#;K=p7ZLqyEYmA{}znrA;Xg=&j9P}8PBmB!o5dez*_T zkKYb`Szz4Y81B}cYk%=bEMw9*AS#=}F}7daNFOvhs6)B1Ge}-Jrr@9Mec5Jr0GOt_?X#PfY3vPO1FX8T?|EE#B?t6IU*5 zy%55?PW>Yq%3`}S#iO3){QYnu13wIy_o^mD=9AxFqkU z!!g3g(_*S$m=Vysja3qXN92AaLCfzGRRn z3h>Tr%VYF#0a$wvM}gQb_ItsBN`s5@H=3pnm`x?Xf%nOlQQU()8+q0l&`DHuEyC-{HKIOXZDC{Q$)l<%SAd&j_xzGyA*^4~ z9T2YyxyY+&&oiF}%THt=f8^1uQC28OUSuuuOxPRxhzPtr60!k`&z#*+qT$;$ zQfdn4?Pp_re8tUl8u4D4(aCA@BG)WVeT_as!f5Zz#oa#oXiA@zO^!e&@lg{yGnEh0 z@!b5qKnS0&nblb#>HHSM!S^Y6d+d%S<+{)n-^^t&%~Pq=S@i#e%| z*_VD((7AyLfV%=Fdc-lWHJ?Bckca|uUEff{i2QE2YgZpubr*I?3V-2IItz>DE=0IattcxwC?`oF7 zy6W2`xj9Kp!|$v@|J3goM(vIlYEMp35%EUQab?(qO9EN=7>1g^?m^nNtg}KWo^O{s zY;8!tE!EwK)_na;Xo;$3sc2)V24K{!Qp9fAR}HOPj(?TrJ}>xK>O!h?FK0G=&|~iN z%ioZ5dk<-s_i(-4T81}aIHW)ZBelrT9j|m&2shTXbk-0N95?jE-lxIhANww3O{l6I zVz`G~3>3KRH)wsB#)xMG;Xy@Yy17OE8$0C}_^R){qr~v))YgMDU?w(#mJJFyJ5@Fv zHk_udGwH>aY`D`J{Y1PoW|9N1c4=f3g-Xx<5aeN8b&nV5e_;i-d=qRX$AC7o@?O$Z zY4SBlsBbC=p(FvEN-}Bpn_n>!HRiD{zi;idMOggvejp97KWggazduRRJsypw0@l4p zZJz)1D?2veWROU44FnotAjlL|lOxo&*P2Xt=glPhr=;^Z_#>U9p{Nb8)!rv~Ax>{2 z(9D*7Xbi@_{rn5w(jla>D&YblifvN<3W`niRCm>pz`nH)Rz>VX%F=Ig6iUf-WgbLn*OAec~Q=ZhC= zf8~i>b5T6xfn*kAnQ9tJY3!}o`u1ZQv;tMVdzcn;VKx>B&-x+K?px#fvK+N?F-Jsh z4s)q2i(J>^C&h9#iliZ3EW){cCe9t_m9kR_X)k42P6C#^0sv3rW(yA%>~-kaLL4bB zewgDKPzN>eP#n7;`)h=x$=kK6y)6%jipz-{lx;OTD7}(pWPdF6L7q10v}|7_euz3R_M^u_H8%|Zbm&_Gs^UGz-v3}%jz5R3%izL z$!^dR2XT+3qT)r;8;<^C525K^|5N%@Kn(;DO8j}z8_R)2Gk30Gk@Xqz)KE8kTgkM% z?;@Ywl7{VL*pR9l*(OxumX?F~lEgGM4j5{(a#?kOs&4Z7&6$YNUOX(voq=xh0RQCr zL$#EXQ<}8+VyLk3^M;q&dh-X9%u~s-v$4XIqL20=9SVVGihXw$vN)4+?CP?wo~M2Y z|FVuNI!?uzI(gdC1+&=@L8)+HTOxuWX<1-s3PXd?XiaC`8Rk%-#~kMd+$=_^e(0P0 zl)Y66EZWe<>MtfI5-;gu9_3T=HJG1|FUF<0$ItlPkE;lng7x@T>m)Xol%R=z{o#(c z7hoyjVMPl(*n9g?Cntl`Z%Xpv@@*z0yakm625u`3@bmkUgiTpQNoti^pv3 z#?fjil}H@?mfcmmxt`tp1*@fMd%g;(74f=Mb{X9{!?8WRS#pe9M$=Fzj&rAE!xtDD z8e@B2jqSuj-b(24&SUst@>qTG?1Ty(m-U{<)W?^lNS9;mE4hqM2DBq!jcKKD#&BX) zA&ovBF{Q2@R?AC=c4kM5TS_ClR46~A|D6k97m146htfoOK*CB*n0mN- zNnzgYoqCAnrgS4lu#RT5BbSK3AbE;g^sQOULC7RFQ({niZa9;)sooQGSXvje0Ua;= zm(m?SK;U4$qhwg$7S@ob*ecerq~AQSrk6+-c0h{T83NgI zmV#$tpCs%)+(6uO+_)w@@6WE+!ZO(R>cX3t-fql&Sdvd9P}Q)8d%k&qz85LWZb4Ca zb21%2O$)Kfw>35akP&wMs~9_9O?MHYbS{MsVbJ-`gI>!(FG?*z(I|r&L(UklpgKCh z;p%(Y?>roogqmyu|N4)Zvpq?&? zjA5b_0QV4PXB=zI`y6Qu% z=8#08!eqTCpwEhoic&H`&|}48_;oPLq#?&Y)H~f%uHa8 zKPPc&gJ(03&5;gk-F&gZX^2Qo8RLWQVl8o4!Y1+!xF&Ab&%jVX?3yUKUU~a^ZlUO* z1bREs<2>nx#39=Bui?8&UcwhS9)FI)h6^U$Hq^x{Ar zHROyt2c4FTy`o%e&V9f+SnuD``rPim|Af27pb$>aiTFnVi^;i?qb+_p6@(A zi~EN%?S{vyEn<|&RQ5PN%(yoD@nBhhS%Mh)vkAIdkR(Vb)sK6SJsP?o%C8re8m6ZH zQ*MP#1y3sG&Hhu%Jeun~t^Lv~!(d%}h4x9;^wuxEdM^GoU>J(7{{^8fHxIA?8vP`W z_cR+k)t;qmp-25QEeW+ykgYCE#+cur&PwCM8k&>;0dmI!LC>l!_SQ?b;lPosbE(|Q zU0~hU2$SGSKR~F;G4|nF2!u2DH)5Zs379@r33k{v8SQAleTu$%>ibH~gTqiV$F}-D z{`1|uCOO2mnV3%Ewwe5k)PO%2k?UgFAEqo)sR{54^*1&M4;U_>tl(wqTNS%|f=41V z<&8;EooF>=BZH>z$`AOZfO;6M& zCCs&D>T_f+BR@1wYbsf{#LHYFtxKY{MtZB0s>j@W2WADxb(V;2Qm2W(GA|2bU$K_g zpTI^#dK8@j2J9(yY6Q7sv0e0c!z?sLExRFgWgoqTeh zbJF=BI%VHBFLFh1j;fKG9^cN>$2{XZk;t`qvtF%=P_T|4+jF(%KzqmQ9SF4*7Sg;D zsD&cemg~Pj1qD&(blkv>M z4)AJUq+tv@gVwFS+N=xuww0>tfR77l?u!`WRgL{zGXF3g#A66hi&Uy0Ne z3*H)rH0a;};9zS&%aI@+7=bshIA;+P?BxYkVIBn{`zISzu3-|YgxA=4H&QrF5fD{PI7t-b#H;W z&exTLzi05b=jWpid%p%Va^~D$tZ-OOz5);lAh52}2Z7DBuI^;hApp)66}Uvqgok>( z;ArBJ9WkER$NVRso!KTJ4ce5z46=o~5p?-W^7esV5b|Ye8qWPi6TWrK0T-oQWXJ8N zpK_tU5gmnR|5s!9dBo~jKcgtPFGPIXG^7JECF6rLNSaWL(RE#}k5nH6V=iw;M2SiBP z^e0RKmvu+%)1QpRq(Pr0oK}CN8$n9Y#5Q3AFR?__8NuXw3I{N0)5v44F<5cSKa#`H zwo&gyCask>o+>bs`XxVx#+HBZZiPW5cjfaw{6WR!f-PUZOQj#q-eR3!Yyi4pQX)Vt zmuSi9Mt7}-$oXV7F&HOz@M_+7kK@R#HBC6!w+~K>v4@JivD`(dVL2L^xLd@!eBCVW za4@4ha(T)&&hF^zCreitd-L|~$kLb5tLuFmYmfQ-y{EN_k_$3NuellGs$z{-r_^6a5pmj0o|Pe2!czQvn2zDB|2>TSCrDG+ZG-EsD!tm` zPm)NodlZ?LDn8*^hca6f3_I@L7c6*2zEAJIuNeHr>498`NxxNO_Ks+ypC~TQXs+9R zj-46z^h&XQZ}f&j!X$mb@`|R}p6ha|AzWnGk|%Fc@#A}RM)MAB^T448M~^GTpBI@2 zafcTO@fBFP%X8qM_OJ*8h5WnHx+X}rT^1y_>*-+Cc?Ye*CD&}E=oqnt z<|Bl^locv63WuslfcC^^am>b{2|N|3>Axm=!g zLvOW3M(XqSMi&dhMqIS@8P-+uX!B@Fu#z64ySd!1ALxD-&*8A_gqE?2r(R|3#-RlY z1ic_xTh1V?AD!0J@c3SV^F7F)Q~oI@jk)R zr_Z#uhrV)oL;yYJ({%~UVQJmO+JxZhc{Zzu4X?p&_CWflvCC2|A=I;MPQCLe)R>+K ze4}d`+#83s$ZNQP0JC&t+=S;_xSD5Ch6FHKa0D-qvVcPm_8jkjq6eTV$YM+iV=v(6 z3Rp&q#gSbZGz0kc6(%-BmR9ngZ;udB*lQSH_80@t(eG~a9O?$kVpZm-@xHtVK2qzB z4gZMxwsVT0NlWipYI2EcypWoe@K8bFU63(!%-bBQoo4VFK4!!YxaZ}(#N&*Sm~M*0 zlmwHvj0*5e`d{wVgz3VE8sI*CoT|Tap<1eYy688Ii4MrhKUZ3 z?P3OfZM|_1Ajjm6(;RJ2MBJk?R$|+LB`JJn4I{C_6-S@Wi2<%f_|Do@@3Lr4I?Z~| zXdvqbVJiUZ$)0prcP*|L`} zPHW(;TJY&6|2H?(s^>;NU|p3LmuCa$6;?XshSYn4`IE2SxyW=?bX+r=z(Ed6DZ4 za-bbuN?Obmg;5f*cF+y@Y-MVId=>cqV6LT|+T{WYBZ0rDL9riv+|Tbe>;7&I?D$y` z9mA2Cm1d8s27E!Tc(A){3-vD=W1KUZPW3I)mQNu*&@bCO50?*iY5XFKqeu4k>-;3q zs5g>HZmD-^UAxj3#1C4UO`nFyaF+plk0tU5 zLa~<1N4@}PNuQ+&OOZ^lfl-Fa+^RlPv6lkhb+hxZUWKzx!29=?o;C@=A|p}!y>9tCGwW`Z7Z1HT)9quvdzMsw z3uEm$j}s~+u%_LI6Z;GUdKu-XP2oacwZEvrMxSWD<(RT=M+nRuaZos-Z~vSlytf)7 zjzZYG?uVsfe$^xW0ROxeT>C1&%u)2yvFCPyQSE9DFq-FvRx zW$uyyUz!WrXI&m>r+B0@9f91h>rZk^*9xS}YCANPwJa&mY_j@;C0)>qnagH$+>8dx zMjT(n?UC_}F6Ly(Q-IJ8|E;7NeL)$mxS@Q|Y3>1yS6N`d2@@6jvM9HJw8exjgBNx| zD_SB=4!@H_1r_Jjg9iDFK)EdT+drKqZA3c~{trAqz+r_%KXirL?cAeTZHRDbcw@k~ zL>28?djCl?xl3;N0=UhI@LR!mx7=Iqr1)s20IWKMm zi~d1471N)3U7D_f3Xfj8cuviUznnf+uHfrr37#=T}kmMPt?wvb? z|4*z!YU4AtD5P+l%D4U?e^B$~HOQ2D(N|^mYb$8Ke8D4wOZ15|@`Rwp2J#sFhpGPp zpNc6E(?wr#oS|R;6hV)Mw>3@ItqZVhiTqC>~%J=Cn^2GOP zx$@16HUD*8HYyp&{nxE}=ZnnrU%=K28>PxwHQ=9B=jZ;t!M`3acdY0?h^M-NPjd+WP@DZdN{{#= zgviA%(j_hVH=yCKC1gT~FVYUCtHXH_PyAoB|7xxQHQ@0cHvfHz%u90$QFL&Pe}?2= zC;#Uj{*7s({|jN|#upioR{XEu_?H>~6}|U*A)Y*ra=0pL{u{9Rw^shAX$Ntde6w9N zkEMpG|2g=7xU#Dz?B!wnzZsZ0{tyg0Ui$pEn?9fd`in*hDaVp_Scske{7Mk`az(LM zm?Zgqxgmbkjtp2sPE*?C!1DhyNQz&L> zih$pJW80N6gQi)f_kaqyi4>`GFEh()U$jcM+OM`VqSCI`tkhQsc_Pfh?y`-iFX5^9 z{ze-zz&HGbrq*TktdY^NWj3#C0);Z5*fbS`1ISvP6g*4ERa-j9;P3r#{LY^&9{}Ge3$4&U!FpsbTE3@ z^p#MBgwAnZ*yE=6r4j-KGu!&F25@g`o9}F+KK14=y4rwwTlL!40RB2r<->*F<$f1M zwjWSzJA5?i=Z~4{;`;`f)RW9SdMN7diQ9Y4CBAepuf@|P`7Khza!HvUw@K3UE{|Mv zq1{Is?-&HAx~VwOBQZzvCzK$uQ&UuD2gz-In!F29+v9q9?<}uv;G#=Ee!M!$i@xA} z+B4%17bd}@plNf80@$y^wYbU_UWVI!#&jyY*LSIp-Z?6p!8JGdP#KIopW@Rcj6C00 z!8hN?_6!E9uVvOKg}P!T-4FCpxGtQgohC>8VKco89j%}>c=UiKl0#RgbDTIQj5yxT zx^(v#cz9a#H>pJRUN@mL*2S&DWWAqmXJRG`Gugjak_P z<@6k8=Xo>Yqicj-TIeEgpLUd_G7NWyup^smrUPtedltpZV2l2S4Q8c2(lR=>uWq%^2Q( zDgSN06Oi}BBgO;VOCdl*c4H5ZTUC2QS1A<^J{u>vU51bs>X8!OYPEjaZ?aGQFL%kPZl4q z=7}J^))KsowFY^|&8k)lNwCFpBWvP~>@~k$+=%Z9+ys_iy_i6OAK1|g%WA5)gL?m| ziApo~j#2D|tg3tA_{<{d&pZCYO|Nd18>(h3k{q@hG-@55LRUkF9!BYoV;Iv%J$$0` z5}0eK0^7FTbG0&jK%>R`>y|;`=8sm8t0|uGAV{KE1*0aN;iz90SnisDBALGG1aM3% z{-gRPpSi2Bk2Jk}qh|2hcE7>K#2}^#ziRMT$ba@Ojrn>wKF-Sw^S5(pV?|XRgdz^# zQm3thUh2Kt1~VHaZZu)Kh&nWUp4B**E2F(S8$8`Ja>;y;?w0V@)rWlO;0Q+N%sT|j zV{?2q|G6hyM4=XXso!oB1-ck28fq0bQYK#0t!y@LUfGw;MyG9yS1RW3lk>bYtQ zIRvrbSI%CD4%jTVV6o1b&l8BVG|;@0A?OVeY})Ymg6xueiLt*`urRDCN3hzrT86!q zU&^I*_Tt(8Iv-t@w9(p|+uxgX+^dF@h9o&YFHW z4UQt?POC%K_*OvfU=ZNaoFAzl+W-A)%NxnvaJx^TLpzNeR2CEhofS6n!)fmIDUI(~ z){AdAFCupc;<6M)kSgI=`3!MQo>8L?;mBVKcEQvSX9j9uH1w;fWW;1q9L zU$Qbm`M{1C3PUpSn!mK><)4%BA8u^}waAZMSxB{5lRx%azLTW#O-(!GnCDNPFX@xz zv6P95J1Ymz3ret^32b{>A6fRjCog(GPAvFA>0?~-9gS&ySR)oaoQ@M z#+rv?>HH&4rCfsTx!`Dd+toKQ=sjDO`M`W<7KGSp5xUsT?=(nj3fX(tiSDO8D;+55 z0lBX*e{0@pJDi{z|K@9fQva*2B^mU_(WBXn(D233v~#UbV$d}7I=ubMkb3y17v%EX260P5YXVGX5=wC*QBn>$Mu6KEr6g4K#=LwgxXsolMS!d)%C? z3W=3AuZ-n|(Ks@X{M8#q)bSB9PMp^zns>LZPU8Tyx}OjRxNj*{1EqryJr70^J$Ak~ zPSel*Fjibas@;9j|2bHyz&LKq)t3x2FcM>=xp(+KU+7XfKID+%s(lTLmC7RN(!9&b z`>>Pwtpf7k%VI8NQt93PHS9e`iFMB_Gyi52Qm=j<`0f;XC9&O#+zzF`TEJPP%)Sqk z3!&kpAB|3)joYJ-aDZ`v5BC^*52I3oJ3_|LUVFiiPl!Yo{#psbGGptx8O+CeVe&l4 zF)a=Tep`{4z=0hAS%FnhE0ig`<>6Vsi`sy|cEOZg87b6}YHUl)q65L4ZrsSj z0%6cEN_4<5=4ppGFdz#I!u&=EYQ|~RaW*l2TlvnqPSia&6dRGBiljm+zv>~-SzJ7R z9%Yzs$%xhFrIH5ZS@e3d<-tiV6YOcq>xL%M)1QNf<_Drz?s(!}?c-XF=>Dp}AkRzN zC%%3iW6m2P@%!7Wpu?u0r%6Rs`^?9`v<;s))C3Bu1_~yn-dC`dsXdto>1}>ojae5< z4D{-ix%lvgK%<}oY1$LOj%uy5ZcXW;{o05R?R?-8;6eD9b@hZ9xu@D3q28St5fQ>1 zU#eobs=Ku@eQE_Z%3iC;crTWB_1@%p_~97JBrbQ>w&&u$9nLUma0$ba_BWeg5&_%^ z9mKPa@4&B!Fj)ik=_gbYh)3Nr_AuEruPdBYcQuO|pq@(F*E${7ZIFuD#31WQ61Izh z^h>@Urg$xmI>{cfi!R*f`xy7Ccn~k9B)qh|t&Bk!@&I9ngQx<3LlDzfjHbQEw0Tbg zAP@g-FFRl@w*ku!EN0hRs8%#riAJfs;uCzhl=X-q{5ytIq0(g0Z*kF3d=Gq$mH;t1)p+^4Pw2tUC`WGyo z^OX79+0ml5PIN^3PpA7o40(>}LcJ#Lp@${0&JUEot>AL?R19b31nyB0cFL4yTOP=R z-)wrc?v3eG^>a%8VrzzBoh*%kCc$s}G?3Lf@6 zC8lkE=sI4?V5#dcdN*aOHx!sR$0rY$(IC)&BR5cQt;=F&@gDiDmYRiJ`XW`aw12YG z(rE-gr@d_|*xOWFf=2cDtVu3wr)}MB#Josy=#UC1ef^m=Ev-2=vDgDY7&zQK$YvL( zlM*4_;Ie(zI~-i5V$HHig!pTGMeeJUXx}!+=4*VOrjC}6TH-={*spm8uy#iG{6tsS z?Ev`Ze&W$8tz64Gp%ZsS{zMI~)CYWsW)|q!4%X^AhIm}RavB(Cz|C~#M^^$}@F3W69Knr<-#pW;Ff@$C7>5ThPjEZ+iyNC?+ttd?qbY< zF?`S4k+B2q8G!R~`|{Mr3e4t7q=*ltXW)M4mDlA01wI$-LmL}cwd(qny#}L=AUWpJ<6;=Nbp^{dwZVnWZ^G=5=GJhrN)UBNryXBy~>a+%vT19_E9Kz2T89_cE6bu@|mBq6YE7;Hxkf_Vcue)n?+wX1k) zLekf++c742a39{|mPVsL3Jeu^Hs^z{Z0kO8KkmKE5K2;aETORWPM;24R*JXOyj!gX z4Jn#>d*q`X4J%+eyrWBh8y6EA=zw?qP*Bk%|V< zL?OnioJO1^4W@HL+(?$g zZW+^k_i?*6cK22xWH%}u`)RUX@|Hf;gUhoVbbm$A@>cSWA9ZjF8^C~nTD8@_Kg_oM zk_OzHA%IGDU1iDNBe}ErTraUs!+m); z;M}_!UYH%7$^)8+w;M#M?#H05X4W2MgEBb0zGVwk$GyeB)w(_zSz&QG_??iSe^<-R zvFP0x6~zNf>?_n5o)}JOteKiFFR{kWzFO_<)JaTiQZO{^kd&5|9d($03_G;(=w`52 zFo~2CUg$80Mx3o;BjzKRuM^fw`cUXnHa%Rp0&d66i~k&J-(>0W{v<7Wd$vSRW@)fr zwl}n65^FgpycR}yDszi7{nKTiLuYQnK(|)Nwy54_NXT)Sr zmT+#m_?#_c74HwUTWnTTJz$XD*^FBcq{O6Sk}k*|0nztZIX{r8DYQR}xPCv^&|p_1 zc?#kTnbR+bbZ8x$b^(!`V`s1req{D#L*D0k9n|2?P%&|U&#I80=uBd?C1W#mdDJ;IH*Mi70)ia`8%Jia!|&5MqULz+i=>(2*lJFfhNa4QOUh;}&W za#I?kng(+4Edh#_Y|#-N#8T>&EgeYDG}+=h9D*7tYSGhQVsHFQ0LpLgQg3CGpg z|4|{nibt7tcxs^7dcAqtnIPb*>@4wgJRDgL;$B~5B&V-v*My6pi#rNAOq(HIG^#O@_qDxgb37D zaV6j!8^2TBZR&iM1tlc|(cJK5F|L(b)!pDS0_VTND$D07^MxsR%VWx=N#`Y8-up;} zdUsGMok-x8sw*TKx43nsjT~*StoxoWS0?C9$xg@Zg6sj?=^<-mINxavWEw&045Fyf~1y5X;}mDl(gh=3cs-@CQxJAPquwxuuJqg|1Z z`1B{Hy?HV|*-~iEI5BFITBm7^BW4rdp_WM!A$c?Pk7dhOFGz4~72oKa8WGLIIlf_z zx20QG6q^9q4reI+YeVGd^&{^w_T*ma724|~A^)3dYTOvx>|JXk((CTvREDB844gV) z?s<36*SIf$82JgbxZe9y`QSo^fqNA}hE-y%{w%eSiF=NkAC7`+>%{{*W^aZ^15|(H zqS(VPRnUHiz=FwUu=v!jg@DiQl!cDsi&h#S&iW{B-0-CQhdoKcZ7na7c@?q1hWp8= zB(Ycrevk@pTr}t85@~3?`d!?%ijpXt3?a(ymTUf52-!KxI^Vg6}CLt>05oETVQyHr2lo>xp*@SDL;y;o=4 z$%V|zCX+Qn6ckMZcmW5N!c9I`3T==2*ujcW*#>AGDo!t=OQS({v29StT(czHBs*QS z(wG~NB=5MKEzjOt8k=-}hqcj)__cVonK(vL;AOG#x?zYl7uo!)POf0IrlK~VJihfl z>fZZumI#*#xlIF97QEO!Bu9uB%Do=|gd$M?WuwEcnYsBT)x*;qeyN@pg5G4rr^fD! zyJ(v^@t@zYYF9D=Tq4g0D8zym!8Qs3Uly=la;$aZ4kNwG$Vg%NL49G3za7D} z8H9fL{}}rUpf|DBzQRFSs`<%SUEUSKr=>fG-uVyJs7@Q0*)l548;Bk|Kh*w$10vJ_DMOH zs0-%EsZndbj7xmEbDo5OTTz^{n3%;BnK@y_{j5J~_K;R*FpxewQQCU!3zYNL>*x!c zI#Hp6SY6V}Yex?!+KDzMfUSDkWWEZry2KyEHkcMjxKA{-$^&L?{^^K~gWQPH(hBQ~ zwSN61otJd)568;Ld%Xo6D{QM*afH2HOBcdZ=zQ02xtZ?X>pUn%Q^@}MUr z<#Tid!HMoZnVL76#mMeWPku!o;^&dSiHORKLx$>xYpB`+x#d)praR*5?%llPnnje7O44lduJ759PKF=f&L6e--G~V- z`rnk`UIUbxYyZ5ES{S3~D>&^jpeB5gvu)+O+Z1`d^g8%;ua2c4+=1?+4W+dG18&de znZ_gk7o=x3tJ4anoi;%iBHdk2^jGJ0ntKJ@h^_78-!;2=v$2X~RMlsmyt_-;Idr1> zGyW>!L@2vN*6{UIIaLUV@Ss+cu3+W84wC(SKP)V1?$a8~q4?f9T5^n}BC)6oD?0#t z?f!QD{6mPo;su&P4nPZRJp`-swRZ9)9 zkclW6ByC$_Lo9_lzo8Sdk&+$m<)Im+7m)ql%kx~j%J7WzO$Z}tWij1yPv~scpBaC?bL#41X&3!IXqwXfKY{Fig(S3>+y;E-k)cNen^(CR?p=C zrHVPjfHyf)dDQzKC1pjL8eci&8%IS7-H)Rw!3wU=FK9m}055IfYQo!1)GHPgA(M%p zs6G@fh0&V|f9VFNW+mx1O3UVs;fXZ*8;j5U9dG|0!LIo?nJ|F%t~2w5JSj#{()T^I zOULy={b9E6PI8U>HN!8H6fvss24{&&s@x@L=;qqI*G=Y=fj}9-ryt(1WNb+LOZkJs zyK>s=-$*go6UuhEVb8&Kmc$t~EoLd^!<|PFIPO2Qv+fWvj7mcs0(ZFwN<@4dV+#%L zLNkGt8iKf(vNB@Nh?9q2cJ6Y$t-e0=#ouJ@n&nwO52y1n6etGkJ*T2&20ckNkQ{Q@mm7Cu$YSu6R_V43fc#P%Q=-!r+sn+wALfHwm4d^sF@fFj$vpw2}(4WYsC)#VgTff$ZhY2EOLc zyJ2`(pc8t3)Y$<$+L$3DqAO%t&-f|;eIo}+ zw8NJqMdvGA0{lZH-9(KBkN#w{d)}j@@t|&>>XpiRR@7ct(k89N!Riy?EJW=`KzhpW1zP_saIH zl5o9;5+Xu{6e!}2>9JkJxK>f?%egGeSs80*TiF*G5G13` zB~2uA4sr&4KpmS5T7sP(LV!yPb}=PYFCtWyoo?2a5yM*Jv5J7yiAo&z-1&cpaBy*_49hbrP|deOZV?2n!`(ZW#4|(18Qm6q5)?QW z3R3gCsj$Ofa7nw#Jk9gzcZxUD0|}|LFy#&?u&O1j{;zD{8i?k>o_M{^5uCn<`+lR8 z7S;_V{M=WIL1=9VK1_~Qk9BTmhrF7)qK)j3Q%_RNMzk@U z`R?8R$YGX|lA03#hax7Vfq)ZptGCC~jz%R8h!RmM8u&-{gxk3J>{MBz0`|Nw;J)68 za-sK^L^J`3a<~U5jIf|6PKZHsz}pHwlIHeScE&+5P`O39V%_GI*<)bUDP*KMxfe5r9ss8v*Xk337=}JaUDvNxkHUJKr(%o~FCC zso;mq2i2T2X72tF!{oB!?mQ|PQL5-8i%he}1?;Bn3^(Q+kd-E&(t&yJ)&9yQR;UXk z=>+7~&ix{4Ir5<}fnj^Nv>uBGhCKe1KxW1IOuh)~y_d{XAh(75fpX#_D{-Q1o*#t9 zgLDx7nGkbQomc=$>(h3lNP>td8u&C;)V{Po;8vddqG-?>+eYeeRn_G!$x+S$KCF z5r@KruxpLcv=Zs;aMsGv@jJ*ak0jfdpLVxCu1TsebtjG7$8rM{jLBbg9P!(P6~A<{ z*}dY7uK@4)L~UNP8ZPN?6#IMOv6RPklh$y%_iuOc)T%(r-{Ir&<3W_M&+2L&?SztcApNSC(j@`tc(~{ z083xu;R6D`euUrY7rXTAmFHIxgw_Kk$VBrAE4uk!wv;$1;J*VCSi5j6qo^z!swzGGz7Tl*b}aA#(1rDR<5Tk+;G ztyd<2K5v)oj_Mq`Dv!wjCDM$X)qTX9|eN?}PqhYm+}KFJ+^`gJ}MEIOLhy?nXl zfkcVM|l&%Zr@0~Y$qNI@2gx{G|ma401Ho_E#HZ2hXu&pegWRvLuql&q6Dg{ zzwr9UjwaTu4mvKul}Oq{yTQK56F`e8AIGCEvg6jk{l8DnuNgx^e}JTzMb^<&+4Y)R zbCmGa()U^uI&1oN$zr@I!`9uKfVY&rMwhr&u6!n#PVe;|ds}OW40_h9{IQPR_bMsI ztSiWLP58yK*y7_tyUa2o>!s~xSVM1pDAB_O_U99LIm+@tCYGJtpZqcnz_r|A+u3&I z7#0a?qS#!j-YT_1#bqYy>kaVuvVL2=%2 zS3nw*STjl%MV4*Dx7Iaq+U;5i$(PUBIzuK|v2X6BFOxLSR<4k6udNk4u{61tB*va- zGF43II(X_J)?$o@C$ev!=^Ain;zOum1vnBRH6Z@SzX~F}TEFv>G|YS~lNiv(Az{_9 z7;r%epBh0JUF}`XZI3#xHZ61Q?0hB9(9dncFF~9CHNf0M1&)GmJZytxxxZ;m-nQZq znZMNC8{w^Do+gR>DT90blsof z0=Pm~dR9o(+2=TcQ4%SYLke6^owHh&ELOC^zaR|mZWnRL97y=+@4{hjb(%e~U>3H; zBZlB0v{Nzv0KW3j;4lfS&N#_*jMsM8I2yy)mm#vc|GIc~mCbW}HPMa7{Ns^D%C)Ev zV`|t}#=9XF%Gi>xygxI(uN{#Oobo;mRTFY>I>NIgPn8<(n-+pkVe{BpP;r+y3-?3G z9L`_y*R@FY1&!u%+p_#qOR-6d9U6n^Ijmcb;cX^kh^?@8dNc48n=L)q_a1*IQ)m42 zSH9Ql&BK5qrokoRX^3PiDJC>7Vn@;HRn<8lZ?#?si+o+-5!lJ&C0{|33P2F?aO>R9 z_}IKDSUP_ZC*8p5b-$#Fz`G|O_E+AYhSISetAUS|fRIC6V% zs>b)Y`|^Rl7Bh7k1sc|P2Ogc{Wp2{_-e>SXus;T&a0l)5MV|%tLbBc+@BJR3*yu$x z_UDN~t)nhJ2K0=8u5HC6kGW7;xP2#_THyJD41>tMa^>&vVHa?w?m=G@ z@L+B46gx9m+6Z>m3Isin;s5-iSgb6Zd@UXW#Ai8rElWR3Ij9BnRWgjbv;6v+k|AkG z5qAj%7bTWT!kN7deO9$*SY|MlW@ABivoPamC*?OKCb{&Ee3$(Lt_0z?kZIoKXHKIk zf@{Vj-4a`Xke*|CBHo};<&4`k*YLS2@`nkE6`V`2mUf;?Uc~31dFHoH4*i!yK_6+yWNWKMWwE_Z_n;6-`n~kX9g0?}tC;N-InT>a3|r%V>bNg<|zN~@1GBwc?_GHg9YRn%e&ite;ydv;HifJ4XU^)+F9@T(sy$>| zSlKXfoPf3;tuouY!#?Q0Kf;K=C;;J+>o`Ldov^ztWb5~$>AXGr+U?2yS$ zkUsWqSRGjCI*q)cPjullQmr|SR=MpsU9?dGEMZkgaHXvzJt|GV^E^2ZA=FVsTw zSWf~b0U)0_aWLd<4yKqonxrjy1}uUL<<-#Qsi}Pjq&(sqRjZ8gp`60U8+k_a$3ntcEen-UDf?qvfGzxbrxr|w#04%&JNZpE(I!{5 z_!P1CQlWBzv@JHCDXwQ-ZLVg%LKRz-;c}3&KUs7UAM`M2W^8h1ew;NfatSg&uK*Qw zEmhRUXFW#>9u)RD$b7e46XYGQcu$sI{F(ak{yh2Xj*?v%__m@1uY+;HPKueL4#Izk zGi3byfsU4{enww0&t)Fi(b$xh`={+=58DOTJ8}sU0JfqyoEzbm_ ztnF9fT-!RzAT0x^$IK_YqW`GRb^b~x{qwJqrD&#VXTnFa(V!UD%>CPubQ?fDZc4;v zmB?=kopGNvEj26*rRk`{QNA&iPx!|4M??JS>A;*>eV3}1I}Brle%n%fciNdAm9|*# zu}2MCfS{~a=A{O|7ZKz$XU3DC$^GX#G#mL6H|?>fl#6dfc7d>Zr-X5jC*~a926S5@ zNSscy7=0s&NR=JIS9fZ+O6#94jA#;VhVU(E)3%f>=kMYh)Y;+{HIk+4H$TbED`LGM zrhOvPuTrA&^zvYfE6mYjk(qfg)vc#hrd|8_V`j}S=G46t1%o$HpA40C3AJziC5UWK zL{~79?69@{7vmOmyVd&cTEs|h)c+iTG0ly?&Ilz_GSZSi4?TI|N6wL5;Kx?zDI5vu5bv3sukY3i;paVg~06+$_|4CdiapAzLZ1l+~G2YpTMJ>v^F za%`aF?+VI)^8+{exh$KSrrB#}#(Kd+^6#EH;;Mr{Ed=`Vqv` zWH&h{f_4zih(tFeQmo8?qn_?S^lPL5q;*k%X!thv#%+h7 z`!@98i)S(|AzOdg@|U-i%=a}X1=(BtpeZwz{!_nU8(H3}S^`^r6Lx_d%F70ah;*eb zsmdNS$KN1QIL@87()ukW8wC6NB6266?s2lR(tz-$owB*E=)uN;*wS9WpE`&JQ77|D z$Agvo=1(IZIOd|rD#2j~Yb$D5Qc1NO-~@~HyF4r#W|a_5AuI&>!^*N(;D9ETPs?Ma zqAXW&Ig&(0LAoay_J0CZM+O3`Kx(6cqsR6!D_uCjvAoP1iafJqgb`UCe9yMBTtDcG zVwv0lE8+V$-T)xdLmgZc;J0D|*40Ix-vS(ERlyf`m0W3%`c%-_OJZtv@VFM1u>)b{ZB|O5J z#KZ7hb%}y~KwV4iH1m0WHGjgJ{skLlw1onmg9ChBBZUQaKBzguw0lPeW)y`<>;qr3 z6wyv9rO}PLrYkoR_m30tVXSHUv(Rf3vSGz>*k_z39Qxn0&OL&GpY~kXUFbc(9f?6_ zm<_MexQAjCyLaWTQkjViNq&&5p7)g1*gG8YCdN~OwIVX2tuDGoH${#7cNlR#RXd$0 z?Ap%}KJB}-iV_~>nK)fvV9_oX)z2`Oe%V*A7EPtfozBgeCJ|&!;m41zmeXHD6}tCAW8Lbb7>*Qi44tjg^mpsq^PMGxSwfVq zdNC*Xe7ADiZ)a&f1EhX(hhSuI&FpJI{PvW4gO&$7=Dbpb#dtSrAu-TAako!92%bo+ zyKlk;FM&i~AyB0s_M%t-L-W)}9{KGz6$7WoW~MWF7LlkA`221!0ngY29d8#7cYkou z2xc)NUKP=jv{l@D*6lP)#lfQE%Ph~by2+%B%xyZ!3H0gJU`2hE zZrFptPsL$jbUB9smeWYNJXfF9&~Qs7mrHUM-Qr$YU+&875?k|&(Q6gCCa;=8c+%NO zLO3^3t_eW5-gfTiPki!rsol2wo}q*fU$+*euBP1$Qkd4JbQSe{CIb+ZGxEG5yl2(! zrLV`!7NYP~wlP5BIiNw%xQpA;nDy@cT^@F1rl3=#Ao6-ys3I{O6PgFfb~2kmdZZFW z|9($sLMh}BM+KQ>jL?#LrtN1*MC01uyD#Ilt6h0*&q`y}`LsA!H(M2yZX=Qso>xCQ z-j{RvJD-GzF34MPbuK_63Hj@!qiB7nZt)|AF6k%7hk-oDn-IBb@t=vet8?6!vW*!Q zZ$GT8)}busgn>vkAx~{?WGZderwGS6Y#j8iPmrd5qoJe2O!?ZO@~W&;ODdvJRJ$Fw z)xV-7HqF7{4RpaAVkY|%hTE<34)#|0fFv})omwV6BKSEzmG9@dMnB-bY5}^h;`5cC zejVfu`sO6P*|J)OM+}A(q;H-c@njN?2=NT`1=+>N64D)5i3pAq)ay9YO*5s{z7e#O zdPl&V5gYj#U(Y<}T77cqP1)P=_zAI%Ah`$*OB zVFa^MSjm=hrgz3Jg3L6YkIKXImCP!g{M&EyBvKx>^l{X@11HO!pqKETFkjYgJ$u^5 zfEU!;J(slUNZHK%Cex1;2nMA4J@VDPkR8e-N-SXij74J}8V;k77>M=RQbi`(H_jBQ zvV%K|;(igw!EQ&RI8&uhq$DmBRsK0F&A1uH3VeLPUFGS}_GRSPOi7!zg|>1&GG9L# z&A+u(l;S@pvjetH@OM7YKmO+@|JMj=R(mA&eM8R1^T{sE-g71e_yL1aBmCK)YvdH= zNVzP-x`rb93IAh!zbA??{iG2v8p*)&-)H;x_tt^`%o#|UT7;hSKLq)Iyy7K3N{0w_ zmkzqVc}%1zXSPu9P<&|pzdw(c{Rh4@`zuA}zwUR>eUuGxf1m(`pr@33GgfOe@#X^N z_>UOS-V$)8K9E|GXOb!@RTc_(KC{qFSIG6U-<{Xx|4Sl_8cxr~Ao@;RudqM<+xPhIH~0uW7Uf66 z4@PVLpYjj#mJJ+%dAk-1Yy7wM{`VD{h2l74es4wHoE@S?6@~6_UVQ=2N#AbrVy}lT z(F$>$j@uTY{E%~NHy*5@T&em>%Gq+&BdQdI|GAI;nV0?#1k!@{uVqkt0^l@7I9?st z3jwd;PdECXunAj%)P#ky7(&sjwEZOK-YnGzIPHyuA6_^f#4Wu;BuM<*l1O9zBVf$d z-{PF;(^5ix6;8U{WDG^lonf;6edg>atneIt_zmM6F5XowT%7d5r}pfY(vG0E%k)0~ zwY||_E9mLR@ATaK4`efkqz%ip3S3J;0Ukh z&3mi4k@%(4i-jf0uLX9QL^Gc4VLd=d*21;})VNP4)@Wh7j#kI4uOgnBtl{li&EP7Y z9%jK6#S*%N!}tIYirTOBKTrcBqodj6-=RAg?NV>F>AqHIHlhC3d`5uK(HzD7w;i)7 zO?Mi-WoGK6@&Xy#5|`uhaDQj#XK6Q6QGQ`@8i-zX_xL}3vCT=1Nr_KLBnks?fC8}4Smuc)b4vPPpGs%Lv|5Q5Hp z%ctE&4dwRfsB5d>7aq4q)mgqh3JXhheaH&IdiP9lW6`pyzN#rL$$e{$&dApMin<5V zNT{<8M>x3dzHf)XEg0HRMo`qx`=848FO@rdkAb%gX~Ld69s5TU2$jFry1IhZI%7%| zR!o>{Xd0d@AQS6XZdFW?=h*B^u87Jgd(j3?kWkjUKX+GEbB?Jn{6oeXno807bjs

4i{pakNm=S==v4;zQksZ`_$=4)}2_ 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 literal 0 HcmV?d00001 diff --git a/user/plugins/admin/blueprints.yaml b/user/plugins/admin/blueprints.yaml new file mode 100644 index 0000000..cffe0fa --- /dev/null +++ b/user/plugins/admin/blueprints.yaml @@ -0,0 +1,514 @@ +name: Admin Panel +version: 1.9.10 +testing: false +description: Adds an advanced administration panel to manage your site +icon: empire +author: + name: Team Grav + email: devs@getgrav.org + url: http://getgrav.org +homepage: https://github.com/getgrav/grav-plugin-admin +keywords: admin, plugin, manager, panel +bugs: https://github.com/getgrav/grav-plugin-admin/issues +docs: https://github.com/getgrav/grav-plugin-admin/blob/develop/README.md +license: MIT + +dependencies: + - { name: grav, version: '>=1.6.8' } + - { name: form, version: '>=3.0.0' } + - { name: login, version: '>=3.0.0' } + - { name: email, version: '>=3.0.0' } + +form: + validation: loose + fields: + Basics: + type: section + title: Basics + underline: false + + enabled: + type: hidden + label: PLUGIN_ADMIN.PLUGIN_STATUS + highlight: 1 + default: 0 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + + cache_enabled: + type: toggle + label: PLUGIN_ADMIN.ADMIN_CACHING + help: PLUGIN_ADMIN.ADMIN_CACHING_HELP + highlight: 0 + options: + 1: PLUGIN_ADMIN.YES + 0: PLUGIN_ADMIN.NO + validate: + type: bool + + twofa_enabled: + type: toggle + label: PLUGIN_LOGIN.2FA_TITLE + help: PLUGIN_LOGIN.2FA_ENABLED_HELP + default: 1 + highlight: 1 + options: + 1: PLUGIN_ADMIN.YES + 0: PLUGIN_ADMIN.NO + validate: + type: bool + + route: + type: text + label: Administrator path + size: medium + placeholder: "Default route for administrator (relative to base)" + help: If you want to change the URL for the administrator, you can provide a path here + + logo_text: + type: text + label: Logo text + size: medium + placeholder: "Grav" + help: Text to display in place of the default Grav logo + + content_padding: + type: toggle + label: PLUGIN_ADMIN.CONTENT_PADDING + help: PLUGIN_ADMIN.CONTENT_PADDING_HELP + highlight: 1 + options: + 1: PLUGIN_ADMIN.YES + 0: PLUGIN_ADMIN.NO + validate: + type: bool + + body_classes: + type: text + label: Body classes + size: medium + help: Add a space separated name of custom body classes + + sidebar.activate: + type: select + label: Sidebar Activation + help: Control how the sidebar is activated + size: small + default: tab + options: + tab: Tab + hover: Hover + + sidebar.hover_delay: + type: text + size: x-small + append: millseconds + label: Hover delay + default: 500 + validate: + type: number + min: 1 + + + sidebar.size: + type: select + label: Sidebar Size + help: Control the width of the sidebar + size: medium + default: auto + options: + auto: Automatic width + small: Small width + + theme: + type: hidden + label: Theme + default: grav + + edit_mode: + type: select + label: Edit mode + size: small + default: normal + options: + normal: Normal + expert: Expert + help: Auto will use blueprint if available, if none found, it will use "Expert" mode. + + frontend_preview_target: + type: select + label: Preview pages target + size: medium + default: inline + options: + inline: Inline in Admin + _blank: New tab + _self: Current tab + + pages.show_parents: + type: select + size: medium + label: Parent dropdown + highlight: 1 + options: + both: Show slug and folder + folder: Show folder + fullpath: Show fullpath + + pages.parents_levels: + type: text + label: Parents Levels + size: small + help: The number of levels to show in parent select list + + pages.show_modular: + type: toggle + label: Modular parents + highlight: 1 + default: 1 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + help: Show modular pages in the parent select list + + google_fonts: + type: toggle + label: Use Google Fonts + highlight: 0 + default: 0 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + help: Use Google custom fonts. Disable this to use Helvetica. Useful when using Cyrillic and other languages with unsupported characters. + + show_beta_msg: + type: hidden + + show_github_msg: + type: toggle + label: Show GitHub Link + highlight: 1 + default: 1 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + help: Show the "Found an issue? Please report it on GitHub." message. + + pages_list_display_field: + type: text + size: small + label: Pages List Display Field + help: "Field of the page to use in the list of pages if present. Defaults/Fallback to title." + + enable_auto_updates_check: + type: toggle + label: Automatically check for updates + highlight: 1 + default: 1 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + help: Shows an informative message, in the admin panel, when an update is available. + + session.timeout: + type: text + size: small + label: Session Timeout + append: secs + help: "Sets the session timeout in seconds" + validate: + type: number + min: 1 + + warnings.delete_page: + type: toggle + label: Warn on page delete + highlight: 1 + default: 1 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + help: Ask the user confirmation when deleting a page + + hide_page_types: + type: array + label: Hide page types in Admin + value_only: true + + hide_modular_page_types: + type: array + label: Hide modular page types in Admin + value_only: true + + log_viewer_files: + type: selectize + size: medium + label: PLUGIN_ADMIN.LOG_VIEWER_FILES + help: PLUGIN_ADMIN.LOG_VIEWER_FILES_HELP + classes: fancy + validate: + type: commalist + + MediaResize: + type: section + title: Page Media Image Resizer + underline: true + + MediaResizeNote: + type: spacer + text: PLUGIN_ADMIN.PAGEMEDIA_RESIZER + markdown: true + + pagemedia.resize_width: + type: number + size: x-small + append: pixels + label: Resize Width + default: 0 + validate: + type: number + help: Resize wide images down to the set value + + pagemedia.resize_height: + type: number + size: x-small + append: pixels + label: Resize Height + default: 0 + validate: + type: number + help: Resize tall images down to the set value + + pagemedia.res_min_width: + type: number + size: x-small + append: pixels + label: Resolution Min Width + default: 0 + validate: + type: number + help: The minimum width allowed for an image to be added + + pagemedia.res_min_height: + type: number + size: x-small + append: pixels + label: Resolution Min Height + default: 0 + validate: + type: number + help: The minimum height allowed for an image to be added + + pagemedia.res_max_width: + type: number + size: x-small + append: pixels + label: Resolution Max Width + default: 0 + validate: + type: number + help: The maximum width allowed for an image to be added + + pagemedia.res_max_height: + type: number + size: x-small + append: pixels + label: Resolution Max Height + default: 0 + validate: + type: number + help: The maximum height allowed for an image to be added + + + pagemedia.resize_quality: + type: number + size: x-small + append: 0...1 + label: Resize Quality + default: 0.8 + validate: + type: number + step: 0.01 + help: The quality to use when resizing an image. Between 0 and 1 value. + + Dashboard: + type: section + title: Dashboard + underline: true + + widgets.dashboard-maintenance: + type: toggle + label: Maintenance Widget + highlight: 1 + default: 1 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + help: Display dashboard maintenance widget + + widgets.dashboard-statistics: + type: toggle + label: Statistics Widget + highlight: 1 + default: 1 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + help: Display dashboard statistics widget + + widgets.dashboard-notifications: + type: toggle + label: Notifications Feed Widget + highlight: 1 + default: 1 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + help: Display dashboard notifications feed widget + + widgets.dashboard-feed: + type: toggle + label: News Feed Widget + highlight: 1 + default: 1 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + help: Display dashboard news feed widget + + widgets.dashboard-pages: + type: toggle + label: Latest Pages Widget + highlight: 1 + default: 1 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + help: Display dashboard latest pages widget + + Notifications: + type: section + title: Notifications + underline: true + + notifications.feed: + type: toggle + label: Feed Notifications + highlight: 1 + default: 1 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + help: Display feed-based notifications + + notifications.dashboard: + type: toggle + label: Dashboard Notifications + highlight: 1 + default: 1 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + help: Display dashboard-based notifications + + notifications.plugins: + type: toggle + label: Plugins Notifications + highlight: 1 + default: 1 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + help: Display plugins-targeted notifications + + notifications.themes: + type: toggle + label: Themes Notifications + highlight: 1 + default: 1 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + help: Display themes-targeted notifications + + Popularity: + type: section + title: Popularity + underline: true + + popularity.enabled: + type: toggle + label: Visitor tracking + highlight: 1 + default: 1 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + help: Enable the visitors stats collecting feature + + dashboard.days_of_stats: + type: text + label: Days of stats + append: days + size: x-small + default: 7 + help: Keep stats for the specified number of days, then drop them + validate: + type: int + + popularity.ignore: + type: array + label: Ignore + size: large + help: "URLs to ignore" + default: ['/test*','/modular'] + value_only: true + placeholder_value: /ignore-this-route + + popularity.history.daily: + type: hidden + label: Daily history + default: 30 + + popularity.history.monthly: + type: hidden + label: Monthly history + default: 12 + + popularity.history.visitors: + type: hidden + label: Visitors history + default: 20 diff --git a/user/plugins/admin/blueprints/admin/pages/modular_new.yaml b/user/plugins/admin/blueprints/admin/pages/modular_new.yaml new file mode 100644 index 0000000..85aa7b0 --- /dev/null +++ b/user/plugins/admin/blueprints/admin/pages/modular_new.yaml @@ -0,0 +1,52 @@ +rules: + slug: + pattern: '[a-zA-Zа-яA-Я0-9_\-]+' + min: 1 + max: 200 + +form: + validation: loose + fields: + + section: + type: section + title: PLUGIN_ADMIN.ADD_MODULAR_CONTENT + + title: + type: text + label: PLUGIN_ADMIN.PAGE_TITLE + validate: + required: true + + folder: + type: text + label: PLUGIN_ADMIN.FOLDER_NAME + validate: + rule: slug + required: true + + route: + type: parents + label: PLUGIN_ADMIN.PAGE + classes: fancy + validate: + required: true + + name: + type: select + classes: fancy + label: PLUGIN_ADMIN.MODULAR_TEMPLATE + help: PLUGIN_ADMIN.PAGE_FILE_HELP + default: default + data-options@: '\Grav\Plugin\AdminPlugin::pagesModularTypes' + validate: + required: true + + modular: + type: hidden + default: 1 + validate: + type: bool + + blueprint: + type: blueprint diff --git a/user/plugins/admin/blueprints/admin/pages/modular_raw.yaml b/user/plugins/admin/blueprints/admin/pages/modular_raw.yaml new file mode 100644 index 0000000..abd2193 --- /dev/null +++ b/user/plugins/admin/blueprints/admin/pages/modular_raw.yaml @@ -0,0 +1,101 @@ +rules: + slug: + pattern: '[a-zA-Zа-яA-Я0-9_\-]+' + min: 1 + max: 200 + +form: + validation: loose + fields: + + tabs: + type: tabs + active: 1 + + fields: + content: + type: tab + title: PLUGIN_ADMIN.CONTENT + + fields: + frontmatter: + classes: frontmatter + type: editor + label: PLUGIN_ADMIN.FRONTMATTER + autofocus: true + codemirror: + mode: 'yaml' + indentUnit: 4 + autofocus: true + indentWithTabs: false + lineNumbers: true + styleActiveLine: true + gutters: ['CodeMirror-lint-markers'] + lint: true + + content: + type: markdown + + header.media_order: + type: pagemedia + label: PLUGIN_ADMIN.PAGE_MEDIA + + options: + type: tab + title: PLUGIN_ADMIN.OPTIONS + + fields: + + columns: + type: columns + + fields: + column1: + type: column + + fields: + + ordering: + type: toggle + label: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX + help: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX_HELP + highlight: 1 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + + folder: + type: text + label: PLUGIN_ADMIN.FILENAME + validate: + rule: slug + required: true + + route: + type: parents + label: PLUGIN_ADMIN.PARENT + classes: fancy + validate: + required: true + + name: + type: select + classes: fancy + label: PLUGIN_ADMIN.MODULAR_TEMPLATE + default: default + data-options@: '\Grav\Plugin\AdminPlugin::pagesModularTypes' + validate: + required: true + + column2: + type: column + + fields: + order: + type: order + label: PLUGIN_ADMIN.ORDERING + + blueprint: + type: blueprint diff --git a/user/plugins/admin/blueprints/admin/pages/move.yaml b/user/plugins/admin/blueprints/admin/pages/move.yaml new file mode 100644 index 0000000..89fa414 --- /dev/null +++ b/user/plugins/admin/blueprints/admin/pages/move.yaml @@ -0,0 +1,7 @@ +form: + validation: loose + fields: + route: + type: parents + label: PLUGIN_ADMIN.PARENT + classes: fancy diff --git a/user/plugins/admin/blueprints/admin/pages/new.yaml b/user/plugins/admin/blueprints/admin/pages/new.yaml new file mode 100644 index 0000000..d62c6ae --- /dev/null +++ b/user/plugins/admin/blueprints/admin/pages/new.yaml @@ -0,0 +1,62 @@ +rules: + slug: + pattern: '[a-zA-Zа-яA-Я0-9_\-]+' + min: 1 + max: 200 + +form: + validation: loose + fields: + + section: + type: section + title: PLUGIN_ADMIN.ADD_PAGE + + title: + type: text + label: PLUGIN_ADMIN.PAGE_TITLE + help: PLUGIN_ADMIN.PAGE_TITLE_HELP + validate: + required: true + + folder: + type: text + label: PLUGIN_ADMIN.FOLDER_NAME + help: PLUGIN_ADMIN.FOLDER_NAME_HELP + validate: + rule: slug + required: true + + route: + type: parents + label: PLUGIN_ADMIN.PARENT_PAGE + classes: fancy + validate: + required: true + + name: + type: select + classes: fancy + label: PLUGIN_ADMIN.PAGE_FILE + help: PLUGIN_ADMIN.PAGE_FILE_HELP + data-options@: '\Grav\Plugin\AdminPlugin::pagesTypes' + data-default@: '\Grav\Plugin\Admin\Admin::getLastPageName' + validate: + required: true + + visible: + type: toggle + label: PLUGIN_ADMIN.VISIBLE + help: PLUGIN_ADMIN.VISIBLE_HELP + highlight: '' + default: '' + options: + '': Auto + 1: PLUGIN_ADMIN.YES + 0: PLUGIN_ADMIN.NO + validate: + type: bool + required: true + + blueprint: + type: blueprint diff --git a/user/plugins/admin/blueprints/admin/pages/new_folder.yaml b/user/plugins/admin/blueprints/admin/pages/new_folder.yaml new file mode 100644 index 0000000..9db58f2 --- /dev/null +++ b/user/plugins/admin/blueprints/admin/pages/new_folder.yaml @@ -0,0 +1,31 @@ +rules: + slug: + pattern: '[a-zA-Zа-яA-Я0-9_\-]+' + min: 1 + max: 200 + +form: + validation: loose + fields: + + section: + type: section + title: PLUGIN_ADMIN.ADD_FOLDER + + folder: + type: text + label: PLUGIN_ADMIN.FOLDER_NAME + help: PLUGIN_ADMIN.FOLDER_NAME_HELP + validate: + rule: slug + required: true + + route: + type: parents + label: PLUGIN_ADMIN.PARENT_PAGE + classes: fancy + validate: + required: true + + blueprint: + type: blueprint diff --git a/user/plugins/admin/blueprints/admin/pages/raw.yaml b/user/plugins/admin/blueprints/admin/pages/raw.yaml new file mode 100644 index 0000000..788e9e2 --- /dev/null +++ b/user/plugins/admin/blueprints/admin/pages/raw.yaml @@ -0,0 +1,106 @@ +rules: + slug: + pattern: '[a-zA-Zа-яA-Я0-9_\-]+' + min: 1 + max: 200 + +form: + validation: loose + fields: + + tabs: + type: tabs + active: 1 + + fields: + content: + type: tab + title: PLUGIN_ADMIN.CONTENT + + fields: + xss_check: + type: xss + + frontmatter: + classes: frontmatter + type: editor + label: PLUGIN_ADMIN.FRONTMATTER + autofocus: true + codemirror: + mode: 'yaml' + indentUnit: 4 + autofocus: true + indentWithTabs: false + lineNumbers: true + styleActiveLine: true + gutters: ['CodeMirror-lint-markers'] + lint: true + + content: + type: markdown + + header.media_order: + type: pagemedia + label: PLUGIN_ADMIN.PAGE_MEDIA + + options: + type: tab + title: PLUGIN_ADMIN.OPTIONS + + fields: + + columns: + type: columns + + fields: + column1: + type: column + + fields: + + ordering: + type: toggle + label: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX + help: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX_HELP + highlight: 1 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + + folder: + type: text + label: PLUGIN_ADMIN.FOLDER_NAME + help: PLUGIN_ADMIN.FOLDER_NAME_HELP + validate: + rule: slug + required: true + + route: + type: parents + label: PLUGIN_ADMIN.PARENT + classes: fancy + validate: + required: true + + name: + type: select + classes: fancy + label: PLUGIN_ADMIN.DISPLAY_TEMPLATE + help: PLUGIN_ADMIN.DISPLAY_TEMPLATE_HELP + default: default + data-options@: '\Grav\Plugin\AdminPlugin::pagesTypes' + validate: + required: true + + column2: + type: column + + fields: + order: + type: order + label: PLUGIN_ADMIN.ORDERING + + blueprint: + type: blueprint diff --git a/user/plugins/admin/blueprints/config/media.yaml b/user/plugins/admin/blueprints/config/media.yaml new file mode 100644 index 0000000..ba55868 --- /dev/null +++ b/user/plugins/admin/blueprints/config/media.yaml @@ -0,0 +1,36 @@ +title: PLUGIN_ADMIN.MEDIA +form: + validation: loose + fields: + 'types': + name: medias + type: list + label: PLUGIN_ADMIN.MEDIA_TYPES + style: vertical + key: extension + controls: both + collapsed: true + + fields: + .extension: + type: key + label: PLUGIN_ADMIN.FILE_EXTENSION + .type: + type: text + label: PLUGIN_ADMIN.TYPE + .thumb: + type: text + label: PLUGIN_ADMIN.THUMB + .mime: + type: text + label: PLUGIN_ADMIN.MIME_TYPE + validate: + type: lower + .image: + type: textarea + yaml: true + label: PLUGIN_ADMIN.IMAGE_OPTIONS + validate: + type: yaml + + diff --git a/user/plugins/admin/classes/Twig/AdminTwigExtension.php b/user/plugins/admin/classes/Twig/AdminTwigExtension.php new file mode 100644 index 0000000..073aef2 --- /dev/null +++ b/user/plugins/admin/classes/Twig/AdminTwigExtension.php @@ -0,0 +1,118 @@ +grav = Grav::instance(); + $this->lang = $this->grav['user']->language; + } + + public function getFilters() + { + return [ + new \Twig_SimpleFilter('tu', [$this, 'tuFilter']), + new \Twig_SimpleFilter('toYaml', [$this, 'toYamlFilter']), + new \Twig_SimpleFilter('fromYaml', [$this, 'fromYamlFilter']), + new \Twig_SimpleFilter('adminNicetime', [$this, 'adminNicetimeFilter']), + new \Twig_SimpleFilter('nested', [$this, 'nestedFilter']), + ]; + } + + public function getFunctions() + { + return [ + new \Twig_SimpleFunction('getPageUrl', [$this, 'getPageUrl'], ['needs_context' => true]), + new \Twig_SimpleFunction('clone', [$this, 'cloneFunc']), + ]; + } + + public function nestedFilter($current, $name) + { + $path = explode('.', trim($name, '.')); + + foreach ($path as $field) { + if (is_object($current) && isset($current->{$field})) { + $current = $current->{$field}; + } elseif (is_array($current) && isset($current[$field])) { + $current = $current[$field]; + } else { + return null; + } + } + + return $current; + } + + public function cloneFunc($obj) + { + return clone $obj; + } + + public function getPageUrl($context, PageInterface $page) + { + $page_route = trim($page->rawRoute(), '/'); + $page_lang = $page->language(); + $base_url = $context['base_url']; + $base_url_simple = $context['base_url_simple']; + $admin_lang = Grav::instance()['session']->admin_lang ?: 'en'; + + if ($page_lang && $page_lang !== $admin_lang) { + $page_url = $base_url_simple . '/' . $page_lang . '/' . $context['admin_route'] . '/pages/' . $page_route; + } else { + $page_url = $base_url . '/pages/' . $page_route; + } + + return $page_url; + } + + public static function tuFilter() + { + $args = func_get_args(); + $numargs = count($args); + $lang = null; + + if (($numargs === 3 && is_array($args[1])) || ($numargs === 2 && !is_array($args[1]))) { + $lang = array_pop($args); + } elseif ($numargs === 2 && is_array($args[1])) { + $subs = array_pop($args); + $args = array_merge($args, $subs); + } + + return Grav::instance()['admin']->translate($args, $lang); + } + + public function toYamlFilter($value, $inline = null) + { + return Yaml::dump($value, $inline); + + } + + public function fromYamlFilter($value) + { + return Yaml::parse($value); + } + + public function adminNicetimeFilter($date, $long_strings = true) + { + return Grav::instance()['admin']->adminNiceTime($date, $long_strings); + } + +} diff --git a/user/plugins/admin/classes/admin.php b/user/plugins/admin/classes/admin.php new file mode 100644 index 0000000..b9bcd84 --- /dev/null +++ b/user/plugins/admin/classes/admin.php @@ -0,0 +1,1968 @@ +grav = $grav; + $this->base = $base; + $this->location = $location; + $this->route = $route; + $this->uri = $grav['uri']; + $this->session = $grav['session']; + $this->user = $grav['user']; + $this->permissions = []; + $language = $grav['language']; + + // Load utility class + if ($language->enabled()) { + $this->multilang = true; + $this->languages_enabled = (array)$this->grav['config']->get('system.languages.supported', []); + + //Set the currently active language for the admin + $language = $this->grav['uri']->param('lang'); + if (!$language) { + if (!$this->session->admin_lang) { + $this->session->admin_lang = $this->grav['language']->getLanguage(); + } + $language = $this->session->admin_lang; + } + $this->grav['language']->setActive($language ?: 'en'); + } else { + $this->grav['language']->setActive('en'); + $this->multilang = false; + } + + } + + /** + * Return the languages available in the admin + * + * @return array + */ + public static function adminLanguages() + { + $languages = []; + + $path = Grav::instance()['locator']->findResource('plugins://admin/languages'); + + /** @var \DirectoryIterator $directory */ + foreach (new \DirectoryIterator($path) as $file) { + if ($file->isDir() || $file->isDot() || Utils::startsWith($file->getFilename(), '.')) { + continue; + } + + $lang = $file->getBasename('.yaml'); + + $languages[$lang] = LanguageCodes::getNativeName($lang); + + } + + // sort languages + asort($languages); + + return $languages; + } + + /** + * Return the found configuration blueprints + * + * @return array + */ + public static function configurations() + { + $configurations = []; + + /** @var UniformResourceIterator $iterator */ + $iterator = Grav::instance()['locator']->getIterator('blueprints://config'); + + foreach ($iterator as $file) { + if ($file->isDir() || !preg_match('/^[^.].*.yaml$/', $file->getFilename())) { + continue; + } + $configurations[] = $file->getBasename('.yaml'); + } + + return $configurations; + } + + /** + * Return the tools found + * + * @return array + */ + public static function tools() + { + $tools = []; + Grav::instance()->fireEvent('onAdminTools', new Event(['tools' => &$tools])); + + return $tools; + } + + public static function toolsPermissions() + { + $tools = static::tools(); + $perms = []; + + foreach ($tools as $tool) { + $perms = array_merge($perms, $tool[0]); + } + + return array_unique($perms); + } + + /** + * Return the languages available in the site + * + * @return array + */ + public static function siteLanguages() + { + $languages = []; + $lang_data = (array) Grav::instance()['config']->get('system.languages.supported', []); + + foreach ($lang_data as $index => $lang) { + $languages[$lang] = LanguageCodes::getNativeName($lang); + } + + return $languages; + } + + /** + * Static helper method to return the admin form nonce + * + * @return string + */ + public static function getNonce() + { + $action = 'admin-form'; + + return Utils::getNonce($action); + } + + /** + * Static helper method to return the last used page name + * + * @return string + */ + public static function getLastPageName() + { + return Grav::instance()['session']->lastPageName ?: 'default'; + } + + /** + * Static helper method to return the last used page route + * + * @return string + */ + public static function getLastPageRoute() + { + return Grav::instance()['session']->lastPageRoute ?: self::route(); + } + + /** + * Static helper method to return current route. + * + * @return string + */ + public static function route() + { + $pages = Grav::instance()['pages']; + $route = '/' . ltrim(Grav::instance()['admin']->route, '/'); + + /** @var PageInterface $page */ + $page = $pages->dispatch($route); + $parent_route = null; + if ($page) { + /** @var PageInterface $parent */ + $parent = $page->parent(); + $parent_route = $parent->rawRoute(); + } + + return $parent_route; + } + + public static function getTempDir() + { + try { + $tmp_dir = Grav::instance()['locator']->findResource('tmp://', true, true); + } catch (\Exception $e) { + $tmp_dir = Grav::instance()['locator']->findResource('cache://', true, true) . '/tmp'; + } + + return $tmp_dir; + } + + public static function getPageMedia() + { + $files = []; + $grav = Grav::instance(); + + $pages = $grav['pages']; + $route = '/' . ltrim($grav['admin']->route, '/'); + + /** @var PageInterface $page */ + $page = $pages->dispatch($route); + $parent_route = null; + if ($page) { + $media = $page->media()->all(); + $files = array_keys($media); + } + return $files; + + } + + /** + * Get current session. + * + * @return Session + */ + public function session() + { + return $this->session; + } + + /** + * Fetch and delete messages from the session queue. + * + * @param string $type + * + * @return array + */ + public function messages($type = null) + { + /** @var Message $messages */ + $messages = $this->grav['messages']; + + return $messages->fetch($type); + } + + /** + * Authenticate user. + * + * @param array $credentials User credentials. + */ + public function authenticate($credentials, $post) + { + /** @var Login $login */ + $login = $this->grav['login']; + + // Remove login nonce from the form. + $credentials = array_diff_key($credentials, ['admin-nonce' => true]); + $twofa = $this->grav['config']->get('plugins.admin.twofa_enabled', false); + + $rateLimiter = $login->getRateLimiter('login_attempts'); + + $userKey = (string)($credentials['username'] ?? ''); + $ipKey = Uri::ip(); + $redirect = $post['redirect'] ?? $this->base . $this->route; + + // Pseudonymization of the IP + $ipKey = sha1($ipKey . $this->grav['config']->get('security.salt')); + + // Check if the current IP has been used in failed login attempts. + $attempts = count($rateLimiter->getAttempts($ipKey, 'ip')); + + $rateLimiter->registerRateLimitedAction($ipKey, 'ip')->registerRateLimitedAction($userKey); + + // Check rate limit for both IP and user, but allow each IP a single try even if user is already rate limited. + if ($rateLimiter->isRateLimited($ipKey, 'ip') || ($attempts && $rateLimiter->isRateLimited($userKey))) { + $this->setMessage(static::translate(['PLUGIN_LOGIN.TOO_MANY_LOGIN_ATTEMPTS', $rateLimiter->getInterval()]), 'error'); + + $this->grav->redirect('/'); + } + + // Fire Login process. + $event = $login->login( + $credentials, + ['admin' => true, 'twofa' => $twofa], + ['authorize' => 'admin.login', 'return_event' => true] + ); + $user = $event->getUser(); + + if ($user->authenticated) { + $rateLimiter->resetRateLimit($ipKey, 'ip')->resetRateLimit($userKey); + if ($user->authorized) { + $event->defMessage('PLUGIN_ADMIN.LOGIN_LOGGED_IN', 'info'); + + $event->defRedirect($post['redirect'] ?? $redirect); + } else { + $this->session->redirect = $redirect; + } + } else { + if ($user->authorized) { + $event->defMessage('PLUGIN_LOGIN.ACCESS_DENIED', 'error'); + } else { + $event->defMessage('PLUGIN_LOGIN.LOGIN_FAILED', 'error'); + } + } + + $event->defRedirect($redirect); + + $message = $event->getMessage(); + if ($message) { + $this->setMessage(static::translate($message), $event->getMessageType()); + } + + $redirect = $event->getRedirect(); + + $this->grav->redirect($redirect, $event->getRedirectCode()); + } + + /** + * Check Two-Factor Authentication. + */ + public function twoFa($data, $post) + { + /** @var Login $login */ + $login = $this->grav['login']; + + /** @var TwoFactorAuth $twoFa */ + $twoFa = $login->twoFactorAuth(); + $user = $this->grav['user']; + + $code = $data['2fa_code'] ?? null; + + $secret = $user->twofa_secret ?? null; + + if (!$code || !$secret || !$twoFa->verifyCode($secret, $code)) { + $login->logout(['admin' => true]); + + $this->grav['session']->setFlashCookieObject(Admin::TMP_COOKIE_NAME, ['message' => $this->translate('PLUGIN_ADMIN.2FA_FAILED'), 'status' => 'error']); + + $this->grav->redirect($this->uri->route(), 303); + } + + $this->setMessage($this->translate('PLUGIN_ADMIN.LOGIN_LOGGED_IN'), 'info'); + + $user->authorized = true; + + $this->grav->redirect($post['redirect']); + } + + /** + * Logout from admin. + */ + public function logout($data, $post) + { + /** @var Login $login */ + $login = $this->grav['login']; + + $event = $login->logout(['admin' => true], ['return_event' => true]); + + $event->defMessage('PLUGIN_ADMIN.LOGGED_OUT', 'info'); + $message = $event->getMessage(); + if ($message) { + $this->grav['session']->setFlashCookieObject(Admin::TMP_COOKIE_NAME, ['message' => $this->translate($message), 'status' => $event->getMessageType()]); + } + + $this->grav->redirect($this->base); + } + + /** + * @return bool + */ + public static function doAnyUsersExist() + { + $accounts = Grav::instance()['accounts'] ?? null; + if ($accounts instanceof \Countable) { + return $accounts->count() > 0; + } + + // TODO: remove old way to check for existence of a user account (Grav < v1.6.9) + $account_dir = $file_path = Grav::instance()['locator']->findResource('account://'); + $user_check = glob($account_dir . '/*.yaml'); + + return $user_check; + } + + /** + * Add message into the session queue. + * + * @param string $msg + * @param string $type + */ + public function setMessage($msg, $type = 'info') + { + /** @var Message $messages */ + $messages = $this->grav['messages']; + $messages->add($msg, $type); + } + + public function addTempMessage($msg, $type) + { + $this->temp_messages[] = ['message' => $msg, 'scope' => $type]; + } + + public function getTempMessages() + { + return $this->temp_messages; + } + + /** + * Translate a string to the user-defined language + * + * @param array|mixed $args + * + * @param mixed $languages + * + * @return string + */ + public static function translate($args, $languages = null) + { + $grav = Grav::instance(); + + if (is_array($args)) { + $lookup = array_shift($args); + } else { + $lookup = $args; + $args = []; + } + + if (!$languages) { + if ($grav['config']->get('system.languages.translations_fallback', true)) { + $languages = $grav['language']->getFallbackLanguages(); + } else { + $languages = (array)$grav['language']->getDefault(); + } + $languages = $grav['user']->authenticated ? [ $grav['user']->language ] : $languages; + } else { + $languages = (array)$languages; + } + + foreach ((array)$languages as $lang) { + $translation = $grav['language']->getTranslation($lang, $lookup, true); + + if (!$translation) { + $language = $grav['language']->getDefault() ?: 'en'; + $translation = $grav['language']->getTranslation($language, $lookup, true); + } + + if (!$translation) { + $language = 'en'; + $translation = $grav['language']->getTranslation($language, $lookup, true); + } + + if ($translation) { + if (count($args) >= 1) { + return vsprintf($translation, $args); + } + + return $translation; + } + } + + return $lookup; + } + + /** + * Checks user authorisation to the action. + * + * @param string|string[] $action + * + * @return bool + */ + public function authorize($action = 'admin.login') + { + $action = (array)$action; + + foreach ($action as $a) { + if ($this->user->authorize($a)) { + return true; + } + } + + return false; + } + + /** + * Gets configuration data. + * + * @param string $type + * @param array $post + * + * @return mixed + * @throws \RuntimeException + */ + public function data($type, array $post = []) + { + static $data = []; + + if (isset($data[$type])) { + return $data[$type]; + } + + if (!$post) { + $post = $this->grav['uri']->post(); + $post = $post['data'] ?? []; + } + + // Check to see if a data type is plugin-provided, before looking into core ones + $event = $this->grav->fireEvent('onAdminData', new Event(['type' => &$type])); + if ($event) { + if (isset($event['data_type'])) { + return $event['data_type']; + } + + if (is_string($event['type'])) { + $type = $event['type']; + } + } + + /** @var UniformResourceLocator $locator */ + $locator = $this->grav['locator']; + $filename = $locator->findResource("config://{$type}.yaml", true, true); + $file = CompiledYamlFile::instance($filename); + + if (preg_match('|plugins/|', $type)) { + /** @var Plugins $plugins */ + $plugins = $this->grav['plugins']; + $obj = $plugins->get(preg_replace('|plugins/|', '', $type)); + + if (!$obj) { + return []; + } + + $obj->merge($post); + $obj->file($file); + + $data[$type] = $obj; + } elseif (preg_match('|themes/|', $type)) { + /** @var Themes $themes */ + $themes = $this->grav['themes']; + $obj = $themes->get(preg_replace('|themes/|', '', $type)); + + if (!$obj) { + return []; + } + + $obj->merge($post); + $obj->file($file); + + $data[$type] = $obj; + } elseif (preg_match('|users?/|', $type)) { + /** @var UserCollectionInterface $users */ + $users = $this->grav['accounts']; + + $obj = $users->load(preg_replace('|users?/|', '', $type)); + $obj->update($this->cleanUserPost($post)); + + $data[$type] = $obj; + } elseif (preg_match('|config/|', $type)) { + $type = preg_replace('|config/|', '', $type); + $blueprints = $this->blueprints("config/{$type}"); + $config = $this->grav['config']; + $obj = new Data\Data($config->get($type, []), $blueprints); + $obj->merge($post); + + // FIXME: We shouldn't allow user to change configuration files in system folder! + $filename = $this->grav['locator']->findResource("config://{$type}.yaml") + ?: $this->grav['locator']->findResource("config://{$type}.yaml", true, true); + $file = CompiledYamlFile::instance($filename); + $obj->file($file); + $data[$type] = $obj; + } elseif (preg_match('|media-manager/|', $type)) { + $filename = base64_decode(preg_replace('|media-manager/|', '', $type)); + + $file = File::instance($filename); + + $obj = new \stdClass(); + $obj->title = $file->basename(); + $obj->path = $file->filename(); + $obj->file = $file; + $obj->page = $this->grav['pages']->get(dirname($obj->path)); + + $fileInfo = pathinfo($obj->title); + $filename = str_replace(['@3x', '@2x'], '', $fileInfo['filename']); + if (isset($fileInfo['extension'])) { + $filename .= '.' . $fileInfo['extension']; + } + + if ($obj->page && isset($obj->page->media()[$filename])) { + $obj->metadata = new Data\Data($obj->page->media()[$filename]->metadata()); + } + + $data[$type] = $obj; + } else { + throw new \RuntimeException("Data type '{$type}' doesn't exist!"); + } + + return $data[$type]; + } + + /** + * Clean user form post and remove extra stuff that may be passed along + * + * @param array $post + * @return array + */ + public function cleanUserPost($post) + { + // Clean fields for all users + unset($post['hashed_password']); + + // Clean field for users who shouldn't be able to modify these fields + if (!$this->authorize(['admin.user', 'admin.super'])) { + unset($post['access'], $post['state']); + } + + return $post; + } + + protected function hasErrorMessage() + { + $msgs = $this->grav['messages']->all(); + foreach ($msgs as $msg) { + if (isset($msg['scope']) && $msg['scope'] === 'error') { + return true; + } + } + return false; + } + + /** + * Returns blueprints for the given type. + * + * @param string $type + * + * @return Data\Blueprint + */ + public function blueprints($type) + { + if ($this->blueprints === null) { + $this->blueprints = new Data\Blueprints('blueprints://'); + } + + return $this->blueprints->get($type); + } + + /** + * Converts dot notation to array notation. + * + * @param string $name + * + * @return string + */ + public function field($name) + { + $path = explode('.', $name); + + return array_shift($path) . ($path ? '[' . implode('][', $path) . ']' : ''); + } + + /** + * Get all routes. + * + * @param bool $unique + * + * @return array + */ + public function routes($unique = false) + { + /** @var Pages $pages */ + $pages = $this->grav['pages']; + + if ($unique) { + $routes = array_unique($pages->routes()); + } else { + $routes = $pages->routes(); + } + + return $routes; + } + + /** + * Count the pages + * + * @return int + */ + public function pagesCount() + { + if (!$this->pages_count) { + $this->pages_count = count($this->grav['pages']->all()); + } + + return $this->pages_count; + } + + /** + * Get all template types + * + * @return array + */ + public function types() + { + return Pages::types(); + } + + /** + * Get all modular template types + * + * @return array + */ + public function modularTypes() + { + return Pages::modularTypes(); + } + + /** + * Get all access levels + * + * @return array + */ + public function accessLevels() + { + if (method_exists($this->grav['pages'], 'accessLevels')) { + return $this->grav['pages']->accessLevels(); + } + + return []; + } + + public function license($package_slug) + { + return Licenses::get($package_slug); + } + + /** + * Generate an array of dependencies for a package, used to generate a list of + * packages that can be removed when removing a package. + * + * @param string $slug The package slug + * + * @return array|bool + */ + public function dependenciesThatCanBeRemovedWhenRemoving($slug) + { + $gpm = $this->gpm(); + if (!$gpm) { + return false; + } + + $dependencies = []; + + $package = $this->getPackageFromGPM($slug); + + if ($package) { + if ($package->dependencies) { + foreach ($package->dependencies as $dependency) { +// if (count($gpm->getPackagesThatDependOnPackage($dependency)) > 1) { +// continue; +// } + if (isset($dependency['name'])) { + $dependency = $dependency['name']; + } + + if (!in_array($dependency, $dependencies, true)) { + if (!in_array($dependency, ['admin', 'form', 'login', 'email', 'php'])) { + $dependencies[] = $dependency; + } + } + } + } + } + + return $dependencies; + } + + /** + * Get the GPM instance + * + * @return GPM The GPM instance + */ + public function gpm() + { + if (!$this->gpm) { + try { + $this->gpm = new GPM(); + } catch (\Exception $e) { + $this->setMessage($e->getMessage(), 'error'); + } + } + + return $this->gpm; + } + + public function getPackageFromGPM($package_slug) + { + $package = $this->plugins(true)[$package_slug]; + if (!$package) { + $package = $this->themes(true)[$package_slug]; + } + + return $package; + } + + /** + * Get all plugins. + * + * @param bool $local + * + * @return mixed + */ + public function plugins($local = true) + { + $gpm = $this->gpm(); + + if (!$gpm) { + return false; + } + + if ($local) { + return $gpm->getInstalledPlugins(); + } + + $plugins = $gpm->getRepositoryPlugins(); + if ($plugins) { + return $plugins->filter(function ($package, $slug) use ($gpm) { + return !$gpm->isPluginInstalled($slug); + }); + } + + return []; + } + + /** + * Get all themes. + * + * @param bool $local + * + * @return mixed + */ + public function themes($local = true) + { + $gpm = $this->gpm(); + + if (!$gpm) { + return false; + } + + if ($local) { + return $gpm->getInstalledThemes(); + } + + $themes = $gpm->getRepositoryThemes(); + if ($themes) { + return $themes->filter(function ($package, $slug) use ($gpm) { + return !$gpm->isThemeInstalled($slug); + }); + } + + return []; + } + + /** + * Get list of packages that depend on the passed package slug + * + * @param string $slug The package slug + * + * @return array|bool + */ + public function getPackagesThatDependOnPackage($slug) + { + $gpm = $this->gpm(); + if (!$gpm) { + return false; + } + + return $gpm->getPackagesThatDependOnPackage($slug); + } + + /** + * Check the passed packages list can be updated + * + * @param array $packages + * + * @throws \Exception + * @return bool + */ + public function checkPackagesCanBeInstalled($packages) + { + $gpm = $this->gpm(); + if (!$gpm) { + return false; + } + + $this->gpm->checkPackagesCanBeInstalled($packages); + + return true; + } + + /** + * Get an array of dependencies needed to be installed or updated for a list of packages + * to be installed. + * + * @param array $packages The packages slugs + * + * @return array|bool + */ + public function getDependenciesNeededToInstall($packages) + { + $gpm = $this->gpm(); + if (!$gpm) { + return false; + } + + return $this->gpm->getDependencies($packages); + } + + /** + * Used by the Dashboard in the admin to display the X latest pages + * that have been modified + * + * @param integer $count number of pages to pull back + * + * @return array|null + */ + public function latestPages($count = 10) + { + /** @var Pages $pages */ + $pages = $this->grav['pages']; + + $latest = []; + + if (null === $pages->routes()) { + return null; + } + + foreach ($pages->routes() as $url => $path) { + $page = $pages->dispatch($url, true); + if ($page && $page->routable()) { + $latest[$page->route()] = ['modified' => $page->modified(), 'page' => $page]; + } + } + + // sort based on modified + uasort($latest, function ($a, $b) { + if ($a['modified'] == $b['modified']) { + return 0; + } + + return ($a['modified'] > $b['modified']) ? -1 : 1; + }); + + // build new array with just pages in it + $list = []; + foreach ($latest as $item) { + $list[] = $item['page']; + } + + return array_slice($list, 0, $count); + } + + /** + * Get log file for fatal errors. + * + * @return string + */ + public function logEntry() + { + $file = File::instance($this->grav['locator']->findResource("log://{$this->route}.html")); + $content = $file->content(); + $file->free(); + + return $content; + } + + /** + * Search in the logs when was the latest backup made + * + * @return array Array containing the latest backup information + */ + public function lastBackup() + { + $file = JsonFile::instance($this->grav['locator']->findResource('log://backup.log')); + $content = $file->content(); + if (empty($content)) { + return [ + 'days' => '∞', + 'chart_fill' => 100, + 'chart_empty' => 0 + ]; + } + + $backup = new \DateTime(); + $backup->setTimestamp($content['time']); + $diff = $backup->diff(new \DateTime()); + + $days = $diff->days; + $chart_fill = $days > 30 ? 100 : round($days / 30 * 100); + + return [ + 'days' => $days, + 'chart_fill' => $chart_fill, + 'chart_empty' => 100 - $chart_fill + ]; + } + + /** + * Determine if the plugin or theme info passed is from Team Grav + * + * @param object $info Plugin or Theme info object + * + * @return bool + */ + public function isTeamGrav($info) + { + return isset($info['author']['name']) && ($info['author']['name'] === 'Team Grav' || Utils::contains($info['author']['name'], 'Trilby Media')); + } + + /** + * Determine if the plugin or theme info passed is premium + * + * @param object $info Plugin or Theme info object + * + * @return bool + */ + public function isPremiumProduct($info) + { + return isset($info['premium']); + } + + /** + * Renders phpinfo + * + * @return string The phpinfo() output + */ + function phpinfo() + { + if (function_exists('phpinfo')) { + ob_start(); + phpinfo(); + $pinfo = ob_get_contents(); + ob_end_clean(); + + $pinfo = preg_replace('%^.*(.*).*$%ms', '$1', $pinfo); + + return $pinfo; + } + + return 'phpinfo() method is not available on this server.'; + } + + /** + * Guest date format based on euro/US + * + * @param string $date + * + * @return string + */ + public function guessDateFormat($date) + { + static $guess; + + $date_formats = [ + 'm/d/y', + 'm/d/Y', + 'n/d/y', + 'n/d/Y', + 'd-m-Y', + 'd-m-y', + ]; + + $time_formats = [ + 'H:i', + 'G:i', + 'h:ia', + 'g:ia' + ]; + + if (!isset($guess[$date])) { + foreach ($date_formats as $date_format) { + foreach ($time_formats as $time_format) { + if ($this->validateDate($date, "$date_format $time_format")) { + $guess[$date] = "$date_format $time_format"; + break 2; + } + if ($this->validateDate($date, "$time_format $date_format")) { + $guess[$date] = "$time_format $date_format"; + break 2; + } + } + } + + if (!isset($guess[$date])) { + $guess[$date] = 'd-m-Y H:i'; + } + } + + return $guess[$date]; + } + + public function validateDate($date, $format) + { + $d = DateTime::createFromFormat($format, $date); + + return $d && $d->format($format) == $date; + } + + /** + * @param string $php_format + * + * @return string + */ + public function dateformatToMomentJS($php_format) + { + $SYMBOLS_MATCHING = [ + // Day + 'd' => 'DD', + 'D' => 'ddd', + 'j' => 'D', + 'l' => 'dddd', + 'N' => 'E', + 'S' => 'Do', + 'w' => 'd', + 'z' => 'DDD', + // Week + 'W' => 'W', + // Month + 'F' => 'MMMM', + 'm' => 'MM', + 'M' => 'MMM', + 'n' => 'M', + 't' => '', + // Year + 'L' => '', + 'o' => 'GGGG', + 'Y' => 'YYYY', + 'y' => 'yy', + // Time + 'a' => 'a', + 'A' => 'A', + 'B' => 'SSS', + 'g' => 'h', + 'G' => 'H', + 'h' => 'hh', + 'H' => 'HH', + 'i' => 'mm', + 's' => 'ss', + 'u' => '', + // Timezone + 'e' => '', + 'I' => '', + 'O' => 'ZZ', + 'P' => 'Z', + 'T' => 'z', + 'Z' => '', + // Full Date/Time + 'c' => '', + 'r' => 'llll ZZ', + 'U' => 'X' + ]; + $js_format = ''; + $escaping = false; + $len = strlen($php_format); + for ($i = 0; $i < $len; $i++) { + $char = $php_format[$i]; + if ($char === '\\') // PHP date format escaping character + { + $i++; + if ($escaping) { + $js_format .= $php_format[$i]; + } else { + $js_format .= '\'' . $php_format[$i]; + } + $escaping = true; + } else { + if ($escaping) { + $js_format .= "'"; + $escaping = false; + } + if (isset($SYMBOLS_MATCHING[$char])) { + $js_format .= $SYMBOLS_MATCHING[$char]; + } else { + $js_format .= $char; + } + } + } + + return $js_format; + } + + /** + * Gets the entire permissions array + * + * @return array + */ + public function getPermissions() + { + return $this->permissions; + } + + /** + * Sets the entire permissions array + * + * @param array $permissions + */ + public function setPermissions($permissions) + { + $this->permissions = $permissions; + } + + /** + * Adds a permission to the permissions array + * + * @param array $permissions + */ + public function addPermissions($permissions) + { + $this->permissions = array_merge($this->permissions, $permissions); + } + + public function getNotifications($force = false) + { + $last_checked = null; + $filename = $this->grav['locator']->findResource('user://data/notifications/' . md5($this->grav['user']->username) . YAML_EXT, true, true); + + $notifications_file = CompiledYamlFile::instance($filename); + $notifications_content = (array)$notifications_file->content(); + + $last_checked = $notifications_content['last_checked'] ?? null; + $notifications = $notifications_content['data'] ?? array(); + $timeout = $this->grav['config']->get('system.session.timeout', 1800); + + if ($force || !$last_checked || empty($notifications) || (time() - $last_checked > $timeout)) { + $body = Response::get('https://getgrav.org/notifications.json?' . time()); +// $body = Response::get('http://localhost/notifications.json?' . time()); + $notifications = json_decode($body, true); + + // Sort by date + usort($notifications, function ($a, $b) { + return strcmp($a['date'], $b['date']); + }); + + // Reverse order and create a new array + $notifications = array_reverse($notifications); + $cleaned_notifications = []; + + foreach ($notifications as $key => $notification) { + + if (isset($notification['permissions']) && !$this->authorize($notification['permissions'])) { + continue; + } + + if (isset($notification['dependencies'])) { + foreach ($notification['dependencies'] as $dependency => $constraints) { + if ($dependency === 'grav') { + if (!Semver::satisfies(GRAV_VERSION, $constraints)) { + continue; + } + } else { + $packages = array_merge($this->plugins()->toArray(), $this->themes()->toArray()); + if (!isset($packages[$dependency])) { + continue; + } else { + $version = $packages[$dependency]['version']; + if (!Semver::satisfies($version, $constraints)) { + continue; + } + } + } + } + } + + $cleaned_notifications[] = $notification; + + } + + // reset notifications + $notifications = []; + + foreach($cleaned_notifications as $notification) { + foreach ($notification['location'] as $location) { + $notifications = array_merge_recursive($notifications, [$location => [$notification]]); + } + } + + + $notifications_file->content(['last_checked' => time(), 'data' => $notifications]); + $notifications_file->save(); + } + + + return $notifications; + } + + /** + * Get https://getgrav.org news feed + * + * @return mixed + * @throws MalformedXmlException + */ + public function getFeed($force = false) + { + $last_checked = null; + $filename = $this->grav['locator']->findResource('user://data/feed/' . md5($this->grav['user']->username) . YAML_EXT, true, true); + + $feed_file = CompiledYamlFile::instance($filename); + $feed_content = (array)$feed_file->content(); + + $last_checked = $feed_content['last_checked'] ?? null; + $feed = $feed_content['data'] ?? array(); + $timeout = $this->grav['config']->get('system.session.timeout', 1800); + + if ($force || !$last_checked || empty($feed) || ($last_checked && (time() - $last_checked > $timeout))) { + $feed_url = 'https://getgrav.org/blog.atom'; + $body = Response::get($feed_url); + + $reader = new Reader(); + $parser = $reader->getParser($feed_url, $body, 'utf-8'); + $data = $parser->execute()->getItems(); + + // Get top 10 + $data = array_slice($data, 0, 10); + + $feed = array_map(function ($entry) { + $simple_entry['title'] = $entry->getTitle(); + $simple_entry['url'] = $entry->getUrl(); + $simple_entry['date'] = $entry->getDate()->getTimestamp(); + $simple_entry['nicetime'] = $this->adminNiceTime($simple_entry['date']); + return $simple_entry; + }, $data); + + $feed_file->content(['last_checked' => time(), 'data' => $feed]); + $feed_file->save(); + } + + return $feed; + + } + + public function adminNiceTime($date, $long_strings = true) + { + if (empty($date)) { + return $this->translate('GRAV.NICETIME.NO_DATE_PROVIDED', null); + } + + if ($long_strings) { + $periods = [ + 'NICETIME.SECOND', + 'NICETIME.MINUTE', + 'NICETIME.HOUR', + 'NICETIME.DAY', + 'NICETIME.WEEK', + 'NICETIME.MONTH', + 'NICETIME.YEAR', + 'NICETIME.DECADE' + ]; + } else { + $periods = [ + 'NICETIME.SEC', + 'NICETIME.MIN', + 'NICETIME.HR', + 'NICETIME.DAY', + 'NICETIME.WK', + 'NICETIME.MO', + 'NICETIME.YR', + 'NICETIME.DEC' + ]; + } + + $lengths = ['60', '60', '24', '7', '4.35', '12', '10']; + + $now = time(); + + // check if unix timestamp + if ((string)(int)$date === (string)$date) { + $unix_date = $date; + } else { + $unix_date = strtotime($date); + } + + // check validity of date + if (empty($unix_date)) { + return $this->translate('GRAV.NICETIME.BAD_DATE', null); + } + + // is it future date or past date + if ($now > $unix_date) { + $difference = $now - $unix_date; + $tense = $this->translate('GRAV.NICETIME.AGO', null); + + } else { + $difference = $unix_date - $now; + $tense = $this->translate('GRAV.NICETIME.FROM_NOW', null); + } + + $len = count($lengths) - 1; + for ($j = 0; $difference >= $lengths[$j] && $j < $len; $j++) { + $difference /= $lengths[$j]; + } + + $difference = round($difference); + + if ($difference !== 1) { + $periods[$j] .= '_PLURAL'; + } + + if ($this->grav['language']->getTranslation($this->grav['user']->language, + $periods[$j] . '_MORE_THAN_TWO') + ) { + if ($difference > 2) { + $periods[$j] .= '_MORE_THAN_TWO'; + } + } + + $periods[$j] = $this->translate('GRAV.'.$periods[$j], null); + + return "{$difference} {$periods[$j]} {$tense}"; + } + + public function findFormFields($type, $fields, $found_fields = []) + { + foreach ($fields as $key => $field) { + + if (isset($field['type']) && $field['type'] == $type) { + $found_fields[$key] = $field; + } elseif (isset($field['fields'])) { + $result = $this->findFormFields($type, $field['fields'], $found_fields); + if (!empty($result)) { + $found_fields = array_merge($found_fields, $result); + } + } + } + + return $found_fields; + } + + public function getPagePathFromToken($path, $page = null) + { + return Utils::getPagePathFromToken($path, $page ?: $this->page(true)); + } + + /** + * Returns edited page. + * + * @param bool $route + * + * @param null $path + * + * @return PageInterface + */ + public function page($route = false, $path = null) + { + if (!$path) { + $path = $this->route; + } + + if ($route && !$path) { + $path = '/'; + } + + if (!isset($this->pages[$path])) { + $this->pages[$path] = $this->getPage($path); + } + + return $this->pages[$path]; + } + + /** + * Returns the page creating it if it does not exist. + * + * @param string $path + * + * @return PageInterface|null + */ + public function getPage($path) + { + /** @var Pages $pages */ + $pages = $this->grav['pages']; + + if ($path && $path[0] !== '/') { + $path = "/{$path}"; + } + + // Fix for entities in path causing looping... + $path = urldecode($path); + + $page = $path ? $pages->dispatch($path, true) : $pages->root(); + + if (!$page) { + $slug = basename($path); + + if ($slug === '') { + return null; + } + + $ppath = str_replace('\\', '/', dirname($path)); + + // Find or create parent(s). + $parent = $this->getPage($ppath !== '/' ? $ppath : ''); + + // Create page. + $page = new Page(); + $page->parent($parent); + $page->filePath($parent->path() . '/' . $slug . '/' . $page->name()); + + // Add routing information. + $pages->addPage($page, $path); + + // Set if Modular + $page->modularTwig($slug[0] === '_'); + + // Determine page type. + if (isset($this->session->{$page->route()})) { + // Found the type and header from the session. + $data = $this->session->{$page->route()}; + + // Set the key header value + $header = ['title' => $data['title']]; + + if (isset($data['visible'])) { + if ($data['visible'] === '' || $data['visible']) { + // if auto (ie '') + $pageParent = $page->parent(); + $children = $pageParent ? $pageParent->children() : []; + foreach ($children as $child) { + if ($child->order()) { + // set page order + $page->order(AdminController::getNextOrderInFolder($pageParent->path())); + break; + } + } + } + if ((int)$data['visible'] === 1 && !$page->order()) { + $header['visible'] = $data['visible']; + } + + } + + if ($data['name'] === 'modular') { + $header['body_classes'] = 'modular'; + } + + $name = $page->modular() ? str_replace('modular/', '', $data['name']) : $data['name']; + $page->name($name . '.md'); + + // Fire new event to allow plugins to manipulate page frontmatter + $this->grav->fireEvent('onAdminCreatePageFrontmatter', new Event(['header' => &$header, + 'data' => $data])); + + $page->header($header); + $page->frontmatter(Yaml::dump((array)$page->header(), 20)); + } else { + // Find out the type by looking at the parent. + $type = $parent->childType() ?: $parent->blueprints()->get('child_type', 'default'); + $page->name($type . CONTENT_EXT); + $page->header(); + } + } + + return $page; + } + + public function generateReports() + { + $reports = new ArrayCollection(); + + // Default to XSS Security Report + $result = Security::detectXssFromPages($this->grav['pages'], true); + + $reports['Grav Security Check'] = $this->grav['twig']->processTemplate('reports/security.html.twig', [ + 'result' => $result, + ]); + + // Linting Issues + + $result = YamlLinter::lint(); + + $reports['Grav Yaml Linter'] = $this->grav['twig']->processTemplate('reports/yamllinter.html.twig', [ + 'result' => $result, + ]); + + // Fire new event to allow plugins to manipulate page frontmatter + $this->grav->fireEvent('onAdminGenerateReports', new Event(['reports' => $reports])); + + return $reports; + } + + public function getRouteDetails() + { + return [$this->base, $this->location, $this->route]; + } + + /** + * Get the files list + * + * @param bool $filtered + * @param int $page_index + * @return array|null + * @todo allow pagination + */ + public function files($filtered = true, $page_index = 0) + { + $param_type = $this->grav['uri']->param('type'); + $param_date = $this->grav['uri']->param('date'); + $param_page = $this->grav['uri']->param('page'); + $param_page = str_replace('\\', '/', $param_page); + + $files_cache_key = 'media-manager-files'; + + if ($param_type) { + $files_cache_key .= "-{$param_type}"; + } + if ($param_date) { + $files_cache_key .= "-{$param_date}"; + } + if ($param_page) { + $files_cache_key .= "-{$param_page}"; + } + + $page_files = null; + + $cache_enabled = $this->grav['config']->get('plugins.admin.cache_enabled'); + if (!$cache_enabled) { + $this->grav['cache']->setEnabled(true); + } + + $page_files = $this->grav['cache']->fetch(md5($files_cache_key)); + + if (!$cache_enabled) { + $this->grav['cache']->setEnabled(false); + } + + if (!$page_files) { + $page_files = []; + $pages = $this->grav['pages']; + + if ($param_page) { + $page = $pages->dispatch($param_page); + + $page_files = $this->getFiles('images', $page, $page_files, $filtered); + $page_files = $this->getFiles('videos', $page, $page_files, $filtered); + $page_files = $this->getFiles('audios', $page, $page_files, $filtered); + $page_files = $this->getFiles('files', $page, $page_files, $filtered); + } else { + $allPages = $pages->all(); + + if ($allPages) foreach ($allPages as $page) { + $page_files = $this->getFiles('images', $page, $page_files, $filtered); + $page_files = $this->getFiles('videos', $page, $page_files, $filtered); + $page_files = $this->getFiles('audios', $page, $page_files, $filtered); + $page_files = $this->getFiles('files', $page, $page_files, $filtered); + } + } + + if (count($page_files) >= self::MEDIA_PAGINATION_INTERVAL) { + $this->shouldLoadAdditionalFilesInBackground(true); + } + + if (!$cache_enabled) { + $this->grav['cache']->setEnabled(true); + } + $this->grav['cache']->save(md5($files_cache_key), $page_files, 600); //cache for 10 minutes + if (!$cache_enabled) { + $this->grav['cache']->setEnabled(false); + } + + } + + if (count($page_files) >= self::MEDIA_PAGINATION_INTERVAL) { + $page_files = array_slice($page_files, $page_index * self::MEDIA_PAGINATION_INTERVAL, self::MEDIA_PAGINATION_INTERVAL); + } + + return $page_files; + } + + public function shouldLoadAdditionalFilesInBackground($status = null) + { + if ($status) { + $this->load_additional_files_in_background = true; + } + + return $this->load_additional_files_in_background; + } + + public function loadAdditionalFilesInBackground($status = null) + { + if (!$this->loading_additional_files_in_background) { + $this->loading_additional_files_in_background = true; + $this->files(false, false); + $this->shouldLoadAdditionalFilesInBackground(false); + $this->loading_additional_files_in_background = false; + } + } + + private function getFiles($type, $page, $page_files, $filtered) + { + $page_files = $this->getMediaOfType($type, $page, $page_files); + + if ($filtered) { + $page_files = $this->filterByType($page_files); + $page_files = $this->filterByDate($page_files); + } + + return $page_files; + } + + /** + * Get all the media of a type ('images' | 'audios' | 'videos' | 'files') + * + * @param string $type + * @param PageInterface|null $page + * @param array $files + * + * @return array + */ + private function getMediaOfType($type, ?PageInterface $page, array $files) + { + if ($page) { + $media = $page->media(); + $mediaOfType = $media->$type(); + + foreach($mediaOfType as $title => $file) { + $files[] = [ + 'title' => $title, + 'type' => $type, + 'page_route' => $page->route(), + 'file' => $file->higherQualityAlternative() + ]; + } + + return $files; + } + + return []; + } + + /** + * Filter media by type + * + * @param array $filesFiltered + * + * @return array + */ + private function filterByType($filesFiltered) + { + $filter_type = $this->grav['uri']->param('type'); + if (!$filter_type) { + return $filesFiltered; + } + + $filesFiltered = array_filter($filesFiltered, function ($file) use ($filter_type) { + return $file['type'] == $filter_type; + }); + + return $filesFiltered; + } + + /** + * Filter media by date + * + * @param array $filesFiltered + * + * @return array + */ + private function filterByDate($filesFiltered) + { + $filter_date = $this->grav['uri']->param('date'); + if (!$filter_date) { + return $filesFiltered; + } + + $year = substr($filter_date, 0, 4); + $month = substr($filter_date, 5, 2); + + $filesFilteredByDate = []; + + foreach($filesFiltered as $file) { + $filedate = $this->fileDate($file['file']); + $fileYear = $filedate->format('Y'); + $fileMonth = $filedate->format('m'); + + if ($fileYear == $year && $fileMonth == $month) { + $filesFilteredByDate[] = $file; + } + } + + return $filesFilteredByDate; + } + + /** + * Return the DateTime object representation of a file modified date + * + * @param File $file + * + * @return DateTime + */ + private function fileDate($file) { + $datetime = new \DateTime(); + $datetime->setTimestamp($file->toArray()['modified']); + return $datetime; + } + + /** + * Get the files dates list to be used in the Media Files filter + * + * @return array + */ + public function filesDates() + { + $files = $this->files(false); + $dates = []; + + foreach ($files as $file) { + $datetime = $this->fileDate($file['file']); + $year = $datetime->format('Y'); + $month = $datetime->format('m'); + + if (!isset($dates[$year])) { + $dates[$year] = []; + } + + if (!isset($dates[$year][$month])) { + $dates[$year][$month] = 1; + } else { + $dates[$year][$month]++; + } + } + + return $dates; + } + + /** + * Get the pages list to be used in the Media Files filter + * + * @return array + */ + public function pages() + { + /** @var Collection $pages */ + $pages = $this->grav['pages']->all(); + + $pagesWithFiles = []; + foreach ($pages as $page) { + if (count($page->media()->all())) { + $pagesWithFiles[] = $page; + } + } + + return $pagesWithFiles; + } + + /** + * Return HTTP_REFERRER if set + * + * @return null + */ + public function getReferrer() + { + return $_SERVER['HTTP_REFERER'] ?? null; + } +} diff --git a/user/plugins/admin/classes/adminbasecontroller.php b/user/plugins/admin/classes/adminbasecontroller.php new file mode 100644 index 0000000..3747dd2 --- /dev/null +++ b/user/plugins/admin/classes/adminbasecontroller.php @@ -0,0 +1,1122 @@ + 'There is no error, the file uploaded with success', + 1 => 'The uploaded file exceeds the max upload size', + 2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML', + 3 => 'The uploaded file was only partially uploaded', + 4 => 'No file was uploaded', + 6 => 'Missing a temporary folder', + 7 => 'Failed to write file to disk', + 8 => 'A PHP extension stopped the file upload' + ]; + + /** @var array */ + public $blacklist_views = []; + + /** + * Performs a task. + * + * @return bool True if the action was performed successfully. + */ + public function execute() + { + if (in_array($this->view, $this->blacklist_views, true)) { + return false; + } + +// if (!$this->validateNonce()) { +// return false; +// } + + $method = 'task' . ucfirst($this->task); + + if (method_exists($this, $method)) { + try { + $success = $this->{$method}(); + } catch (\RuntimeException $e) { + $success = true; + $this->admin->setMessage($e->getMessage(), 'error'); + } + } else { + $success = $this->grav->fireEvent('onAdminTaskExecute', + new Event(['controller' => $this, 'method' => $method])); + } + + // Grab redirect parameter. + $redirect = $this->post['_redirect'] ?? null; + unset($this->post['_redirect']); + + // Redirect if requested. + if ($redirect) { + $this->setRedirect($redirect); + } + + return $success; + } + + protected function validateNonce() + { + if (strtolower($_SERVER['REQUEST_METHOD']) === 'post') { + if (isset($this->post['admin-nonce'])) { + $nonce = $this->post['admin-nonce']; + } else { + $nonce = $this->grav['uri']->param('admin-nonce'); + } + + if (!$nonce || !Utils::verifyNonce($nonce, 'admin-form')) { + if ($this->task === 'addmedia') { + + $message = sprintf($this->admin::translate('PLUGIN_ADMIN.FILE_TOO_LARGE', null), + ini_get('post_max_size')); + + //In this case it's more likely that the image is too big than POST can handle. Show message + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $message + ]; + + return false; + } + + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.INVALID_SECURITY_TOKEN'), 'error'); + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.INVALID_SECURITY_TOKEN') + ]; + + return false; + } + unset($this->post['admin-nonce']); + } else { + if ($this->task === 'logout') { + $nonce = $this->grav['uri']->param('logout-nonce'); + if (null === $nonce || !Utils::verifyNonce($nonce, 'logout-form')) { + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.INVALID_SECURITY_TOKEN'), + 'error'); + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.INVALID_SECURITY_TOKEN') + ]; + + return false; + } + } else { + $nonce = $this->grav['uri']->param('admin-nonce'); + if (null === $nonce || !Utils::verifyNonce($nonce, 'admin-form')) { + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.INVALID_SECURITY_TOKEN'), + 'error'); + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.INVALID_SECURITY_TOKEN') + ]; + + return false; + } + } + } + + return true; + } + + /** + * Sets the page redirect. + * + * @param string $path The path to redirect to + * @param int $code The HTTP redirect code + */ + public function setRedirect($path, $code = 303) + { + $this->redirect = $path; + $this->redirectCode = $code; + } + + /** + * Sends JSON response and terminates the call. + * + * @param array $response + * @param int $code + * @return bool + */ + protected function sendJsonResponse(array $response, $code = 200) + { + // Make sure nothing extra gets written to the response. + while (ob_get_level()) { + ob_end_clean(); + } + + // JSON response. + http_response_code($code); + header('Content-Type: application/json'); + header('Cache-Control: no-cache, no-store, must-revalidate'); + + echo json_encode($response); + exit(); + } + + /** + * Handles ajax upload for files. + * Stores in a flash object the temporary file and deals with potential file errors. + * + * @return bool True if the action was performed. + */ + public function taskFilesUpload() + { + if (null === $_FILES || !$this->authorizeTask('save', $this->dataPermissions())) { + return false; + } + + /** @var Config $config */ + $config = $this->grav['config']; + $data = $this->view === 'pages' ? $this->admin->page(true) : $this->prepareData([]); + $settings = $data->blueprints()->schema()->getProperty($this->post['name']); + $settings = (object)array_merge([ + 'avoid_overwriting' => false, + 'random_name' => false, + 'accept' => ['image/*'], + 'limit' => 10, + 'filesize' => Utils::getUploadLimit() + ], (array)$settings, ['name' => $this->post['name']]); + + $upload = $this->normalizeFiles($_FILES['data'], $settings->name); + + $filename = $upload->file->name; + + // Handle bad filenames. + if (!Utils::checkFilename($filename)) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => sprintf($this->admin::translate('PLUGIN_ADMIN.FILEUPLOAD_UNABLE_TO_UPLOAD', null), + $filename, 'Bad filename') + ]; + + return false; + } + + if (!isset($settings->destination)) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.DESTINATION_NOT_SPECIFIED', null) + ]; + + return false; + } + + // Do not use self@ outside of pages + if ($this->view !== 'pages' && in_array($settings->destination, ['@self', 'self@', '@self@'])) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => sprintf($this->admin::translate('PLUGIN_ADMIN.FILEUPLOAD_PREVENT_SELF', null), + $settings->destination) + ]; + + return false; + } + + // Handle errors and breaks without proceeding further + if ($upload->file->error !== UPLOAD_ERR_OK) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => sprintf($this->admin::translate('PLUGIN_ADMIN.FILEUPLOAD_UNABLE_TO_UPLOAD', null), + $filename, $this->upload_errors[$upload->file->error]) + ]; + + return false; + } + + // Handle file size limits + $settings->filesize *= 1048576; // 2^20 [MB in Bytes] + if ($settings->filesize > 0 && $upload->file->size > $settings->filesize) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.EXCEEDED_GRAV_FILESIZE_LIMIT') + ]; + + return false; + } + + // Handle Accepted file types + // Accept can only be mime types (image/png | image/*) or file extensions (.pdf|.jpg) + $accepted = false; + $errors = []; + + // Do not trust mimetype sent by the browser + $mime = Utils::getMimeByFilename($filename); + + foreach ((array)$settings->accept as $type) { + // Force acceptance of any file when star notation + if ($type === '*') { + $accepted = true; + break; + } + + $isMime = strstr($type, '/'); + $find = str_replace(['.', '*'], ['\.', '.*'], $type); + + if ($isMime) { + $match = preg_match('#' . $find . '$#', $mime); + if (!$match) { + $errors[] = 'The MIME type "' . $mime . '" for the file "' . $filename . '" is not an accepted.'; + } else { + $accepted = true; + break; + } + } else { + $match = preg_match('#' . $find . '$#', $filename); + if (!$match) { + $errors[] = 'The File Extension for the file "' . $filename . '" is not an accepted.'; + } else { + $accepted = true; + break; + } + } + } + + if (!$accepted) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => implode('
', $errors) + ]; + + return false; + } + + // Remove the error object to avoid storing it + unset($upload->file->error); + + // we need to move the file at this stage or else + // it won't be available upon save later on + // since php removes it from the upload location + $tmp_dir = Admin::getTempDir(); + $tmp_file = $upload->file->tmp_name; + $tmp = $tmp_dir . '/uploaded-files/' . basename($tmp_file); + + Folder::create(dirname($tmp)); + if (!move_uploaded_file($tmp_file, $tmp)) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => sprintf($this->admin::translate('PLUGIN_ADMIN.FILEUPLOAD_UNABLE_TO_MOVE', null), '', + $tmp) + ]; + + return false; + } + + $upload->file->tmp_name = $tmp; + + // Retrieve the current session of the uploaded files for the field + // and initialize it if it doesn't exist + $sessionField = base64_encode($this->grav['uri']->url()); + $flash = $this->admin->session()->getFlashObject('files-upload'); + if (!$flash) { + $flash = []; + } + if (!isset($flash[$sessionField])) { + $flash[$sessionField] = []; + } + if (!isset($flash[$sessionField][$upload->field])) { + $flash[$sessionField][$upload->field] = []; + } + + // Set destination + if ($this->grav['locator']->isStream($settings->destination)) { + $destination = $this->grav['locator']->findResource($settings->destination, false, true); + } else { + $destination = Folder::getRelativePath(rtrim($settings->destination, '/')); + $destination = $this->admin->getPagePathFromToken($destination); + } + + // Create destination if needed + if (!is_dir($destination)) { + Folder::mkdir($destination); + } + + // Generate random name if required + if ($settings->random_name) { // TODO: document + $extension = pathinfo($upload->file->name, PATHINFO_EXTENSION); + $upload->file->name = Utils::generateRandomString(15) . '.' . $extension; + } + + // Handle conflicting name if needed + if ($settings->avoid_overwriting) { // TODO: document + if (file_exists($destination . '/' . $upload->file->name)) { + $upload->file->name = date('YmdHis') . '-' . $upload->file->name; + } + } + + // Prepare object for later save + $path = $destination . '/' . $upload->file->name; + $upload->file->path = $path; + // $upload->file->route = $page ? $path : null; + + // Prepare data to be saved later + $flash[$sessionField][$upload->field][$path] = (array)$upload->file; + + // Finally store the new uploaded file in the field session + $this->admin->session()->setFlashObject('files-upload', $flash); + $this->admin->json_response = [ + 'status' => 'success', + 'session' => \json_encode([ + 'sessionField' => base64_encode($this->grav['uri']->url()), + 'path' => $upload->file->path, + 'field' => $settings->name + ]) + ]; + + return true; + } + + /** + * Checks if the user is allowed to perform the given task with its associated permissions + * + * @param string $task The task to execute + * @param array $permissions The permissions given + * + * @return bool True if authorized. False if not. + */ + public function authorizeTask($task = '', $permissions = []) + { + if (!$this->admin->authorize($permissions)) { + if ($this->grav['uri']->extension() === 'json') { + $this->admin->json_response = [ + 'status' => 'unauthorized', + 'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK') . ' ' . $task . '.' + ]; + } else { + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK') . ' ' . $task . '.', + 'error'); + } + + return false; + } + + return true; + } + + /** + * Gets the permissions needed to access a given view + * + * @return array An array of permissions + */ + protected function dataPermissions() + { + $type = $this->view; + $permissions = ['admin.super']; + + switch ($type) { + case 'configuration': + case 'config': + case 'system': + $permissions[] = 'admin.configuration'; + break; + case 'settings': + case 'site': + $permissions[] = 'admin.settings'; + break; + case 'plugins': + $permissions[] = 'admin.plugins'; + break; + case 'themes': + $permissions[] = 'admin.themes'; + break; + case 'users': + $permissions[] = 'admin.users'; + break; + case 'user': + $permissions[] = 'admin.login'; + $permissions[] = 'admin.users'; + break; + case 'pages': + $permissions[] = 'admin.pages'; + break; + } + + return $permissions; + } + + /** + * Gets the configuration data for a given view & post + * + * @param array $data + * + * @return array + */ + protected function prepareData(array $data) + { + return $data; + } + + /** + * Internal method to normalize the $_FILES array + * + * @param array $data $_FILES starting point data + * @param string $key + * + * @return object a new Object with a normalized list of files + */ + protected function normalizeFiles($data, $key = '') + { + $files = new \stdClass(); + $files->field = $key; + $files->file = new \stdClass(); + + foreach ($data as $fieldName => $fieldValue) { + // Since Files Upload are always happening via Ajax + // we are not interested in handling `multiple="true"` + // because they are always handled one at a time. + // For this reason we normalize the value to string, + // in case it is arriving as an array. + $value = (array)Utils::getDotNotation($fieldValue, $key); + $files->file->{$fieldName} = array_shift($value); + } + + return $files; + } + + /** + * Removes a file from the flash object session, before it gets saved + * + * @return bool True if the action was performed. + */ + public function taskFilesSessionRemove() + { + if (!$this->authorizeTask('save', $this->dataPermissions())) { + return false; + } + + // Retrieve the current session of the uploaded files for the field + // and initialize it if it doesn't exist + $sessionField = base64_encode($this->grav['uri']->url()); + $request = \json_decode($this->post['session']); + + // Ensure the URI requested matches the current one, otherwise fail + if ($request->sessionField !== $sessionField) { + return false; + } + + // Retrieve the flash object and remove the requested file from it + $flash = $this->admin->session()->getFlashObject('files-upload'); + $endpoint = $flash[$request->sessionField][$request->field][$request->path]; + + if (isset($endpoint)) { + if (file_exists($endpoint['tmp_name'])) { + unlink($endpoint['tmp_name']); + } + + unset($endpoint); + } + + // Walk backward to cleanup any empty field that's left + // Field + if (isset($flash[$request->sessionField][$request->field][$request->path])) { + unset($flash[$request->sessionField][$request->field][$request->path]); + } + + // Field + if (isset($flash[$request->sessionField][$request->field]) && empty($flash[$request->sessionField][$request->field])) { + unset($flash[$request->sessionField][$request->field]); + } + + // Session Field + if (isset($flash[$request->sessionField]) && empty($flash[$request->sessionField])) { + unset($flash[$request->sessionField]); + } + + + // If there's anything left to restore in the flash object, do so + if (count($flash)) { + $this->admin->session()->setFlashObject('files-upload', $flash); + } + + $this->admin->json_response = ['status' => 'success']; + + return true; + } + + /** + * Redirect to the route stored in $this->redirect + */ + public function redirect() + { + if (!$this->redirect) { + return; + } + + $base = $this->admin->base; + $this->redirect = '/' . ltrim($this->redirect, '/'); + $multilang = $this->isMultilang(); + + $redirect = ''; + if ($multilang) { + // if base path does not already contain the lang code, add it + $langPrefix = '/' . $this->grav['session']->admin_lang; + if (!Utils::startsWith($base, $langPrefix . '/')) { + $base = $langPrefix . $base; + } + + // now the first 4 chars of base contain the lang code. + // if redirect path already contains the lang code, and is != than the base lang code, then use redirect path as-is + if (Utils::pathPrefixedByLangCode($base) && Utils::pathPrefixedByLangCode($this->redirect) + && !Utils::startsWith($this->redirect, $base) + ) { + $redirect = $this->redirect; + } else { + if (!Utils::startsWith($this->redirect, $base)) { + $this->redirect = $base . $this->redirect; + } + } + + } else { + if (!Utils::startsWith($this->redirect, $base)) { + $this->redirect = $base . $this->redirect; + } + } + + if (!$redirect) { + $redirect = $this->redirect; + } + + $this->grav->redirect($redirect, $this->redirectCode); + } + + /** + * Prepare and return POST data. + * + * @param array $post + * + * @return array + */ + protected function getPost($post) + { + if (!is_array($post)) { + return []; + } + + unset($post['task']); + + // Decode JSON encoded fields and merge them to data. + if (isset($post['_json'])) { + $post = array_replace_recursive($post, $this->jsonDecode($post['_json'])); + unset($post['_json']); + } + + $post = $this->cleanDataKeys($post); + + return $post; + } + + /** + * Recursively JSON decode data. + * + * @param array $data + * + * @return array + */ + protected function jsonDecode(array $data) + { + foreach ($data as &$value) { + if (is_array($value)) { + $value = $this->jsonDecode($value); + } else { + $value = json_decode($value, true); + } + } + + return $data; + } + + protected function cleanDataKeys($source = []) + { + $out = []; + + if (is_array($source)) { + foreach ($source as $key => $value) { + $key = str_replace(['%5B', '%5D'], ['[', ']'], $key); + if (is_array($value)) { + $out[$key] = $this->cleanDataKeys($value); + } else { + $out[$key] = $value; + } + } + } + + return $out; + } + + /** + * Return true if multilang is active + * + * @return bool True if multilang is active + */ + protected function isMultilang() + { + return count($this->grav['config']->get('system.languages.supported', [])) > 1; + } + + /** + * @param PageInterface|UserInterface|Data $obj + * + * @return PageInterface|UserInterface|Data + */ + protected function storeFiles($obj) + { + // 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)) { + foreach ($queue as $key => $files) { + foreach ($files as $destination => $file) { + if (!rename($file['tmp_name'], $destination)) { + throw new \RuntimeException(sprintf($this->admin->translate('PLUGIN_ADMIN.FILEUPLOAD_UNABLE_TO_MOVE', + null), '"' . $file['tmp_name'] . '"', $destination)); + } + + unset($files[$destination]['tmp_name']); + } + + if ($this->view === 'pages') { + $keys = explode('.', preg_replace('/^header./', '', $key)); + $init_key = array_shift($keys); + if (count($keys) > 0) { + $new_data = $obj->header()->{$init_key} ?? []; + Utils::setDotNotation($new_data, implode('.', $keys), $files, true); + } else { + $new_data = $files; + } + if (isset($obj->header()->{$init_key})) { + $obj->modifyHeader($init_key, + array_replace_recursive([], $obj->header()->{$init_key}, $new_data)); + } else { + $obj->modifyHeader($init_key, $new_data); + } + } elseif ($obj instanceof UserInterface and $key === 'avatar') { + $obj->set($key, $files); + } else { + // TODO: [this is JS handled] if it's single file, remove existing and use set, if it's multiple, use join + $obj->join($key, $files); // stores + } + + } + } + + return $obj; + } + + /** + * Used by the filepicker field to get a list of files in a folder. + */ + protected function taskGetFilesInFolder() + { + if (!$this->authorizeTask('save', $this->dataPermissions())) { + return false; + } + + $data = $this->view === 'pages' ? $this->admin->page(true) : $this->prepareData([]); + + if (null === $data) { + return false; + } + + if (method_exists($data, 'blueprints')) { + $settings = $data->blueprints()->schema()->getProperty($this->post['name']); + } elseif (method_exists($data, 'getBlueprint')) { + $settings = $data->getBlueprint()->schema()->getProperty($this->post['name']); + } + + if (isset($settings['folder'])) { + $folder = $settings['folder']; + } else { + $folder = 'self@'; + } + + // Do not use self@ outside of pages + if ($this->view !== 'pages' && in_array($folder, ['@self', 'self@', '@self@'])) { + if (!$data instanceof MediaInterface) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => sprintf($this->admin::translate('PLUGIN_ADMIN.FILEUPLOAD_PREVENT_SELF', null), $folder) + ]; + + return false; + } + + $media = $data->getMedia(); + } else { + // Set destination + $folder = Folder::getRelativePath(rtrim($folder, '/')); + $folder = $this->admin->getPagePathFromToken($folder); + + $media = new Media($folder); + } + + $available_files = []; + $metadata = []; + $thumbs = []; + + + foreach ($media->all() as $name => $medium) { + + $available_files[] = $name; + + if (isset($settings['include_metadata'])) { + $img_metadata = $medium->metadata(); + if ($img_metadata) { + $metadata[$name] = $img_metadata; + } + } + + } + + // Peak in the flashObject for optimistic filepicker updates + $pending_files = []; + $sessionField = base64_encode($this->grav['uri']->url()); + $flash = $this->admin->session()->getFlashObject('files-upload'); + + if ($flash && isset($flash[$sessionField])) { + foreach ($flash[$sessionField] as $field => $data) { + foreach ($data as $file) { + if (dirname($file['path']) === $folder) { + $pending_files[] = $file['name']; + } + } + } + } + + $this->admin->session()->setFlashObject('files-upload', $flash); + + // Handle Accepted file types + // Accept can only be file extensions (.pdf|.jpg) + if (isset($settings['accept'])) { + $available_files = array_filter($available_files, function ($file) use ($settings) { + return $this->filterAcceptedFiles($file, $settings); + }); + + $pending_files = array_filter($pending_files, function ($file) use ($settings) { + return $this->filterAcceptedFiles($file, $settings); + }); + } + + // Generate thumbs if needed + if (isset($settings['preview_images']) && $settings['preview_images'] === true) { + foreach ($available_files as $filename) { + $thumbs[$filename] = $media[$filename]->zoomCrop(100,100)->url(); + } + } + + $this->admin->json_response = [ + 'status' => 'success', + 'files' => array_values($available_files), + 'pending' => array_values($pending_files), + 'folder' => $folder, + 'metadata' => $metadata, + 'thumbs' => $thumbs + ]; + + return true; + } + + protected function filterAcceptedFiles($file, $settings) + { + $valid = false; + + foreach ((array)$settings['accept'] as $type) { + $find = str_replace('*', '.*', $type); + $valid |= preg_match('#' . $find . '$#', $file); + } + + return $valid; + } + + /** + * Handle deleting a file from a blueprint + * + * @return bool True if the action was performed. + */ + protected function taskRemoveFileFromBlueprint() + { + /** @var Uri $uri */ + $uri = $this->grav['uri']; + $blueprint = base64_decode($uri->param('blueprint')); + $path = base64_decode($uri->param('path')); + $filename = basename($this->post['filename'] ?? ''); + $proute = base64_decode($uri->param('proute')); + $type = $uri->param('type'); + $field = $uri->param('field'); + + if ($filename === '') { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => 'Filename is empty' + ]; + + return false; + } + + // Get Blueprint + if ($type === 'pages' || strpos($blueprint, 'pages/') === 0) { + $page = $this->admin->page(true, $proute); + if (!$page) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => 'Page not found' + ]; + + return false; + } + $blueprints = $page->blueprints(); + $path = Folder::getRelativePath($page->path()); + $settings = (object)$blueprints->schema()->getProperty($field); + } else { + $page = null; + if ($type === 'themes') { + $obj = $this->grav[$type]->get(Utils::substrToString($blueprint, '/')); //here + $settings = (object) $obj->blueprints()->schema()->getProperty($field); + } else { + $settings = (object)$this->admin->blueprints($blueprint)->schema()->getProperty($field); + } + } + + // Get destination + if ($this->grav['locator']->isStream($settings->destination)) { + $destination = $this->grav['locator']->findResource($settings->destination, false, true); + + } else { + $destination = Folder::getRelativePath(rtrim($settings->destination, '/')); + $destination = $this->admin->getPagePathFromToken($destination, $page); + } + + // Not in path + if (!Utils::startsWith($path, $destination)) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => 'Path not valid for this data type' + ]; + + return false; + } + + // Only remove files from correct destination... + $this->taskRemoveMedia($destination . '/' . $filename); + + if ($page) { + $keys = explode('.', preg_replace('/^header./', '', $field)); + $header = (array)$page->header(); + $data_path = implode('.', $keys); + $data = Utils::getDotNotation($header, $data_path); + + if (isset($data[$path])) { + unset($data[$path]); + Utils::setDotNotation($header, $data_path, $data); + $page->header($header); + } + + $page->save(); + } else { + + $blueprint_prefix = $type === 'config' ? '' : $type . '.'; + $blueprint_name = str_replace(['config/', '/blueprints'], '', $blueprint); + $blueprint_field = $blueprint_prefix . $blueprint_name . '.' . $field; + + $files = $this->grav['config']->get($blueprint_field); + + if ($files) { + foreach ($files as $key => $value) { + if ($key == $path) { + unset($files[$key]); + } + } + } + + $this->grav['config']->set($blueprint_field, $files); + + switch ($type) { + case 'config': + $data = $this->grav['config']->get($blueprint_name); + $config = $this->admin->data($blueprint, $data); + $config->save(); + break; + case 'themes': + Theme::saveConfig($blueprint_name); + break; + case 'plugins': + Plugin::saveConfig($blueprint_name); + break; + } + } + + $this->admin->json_response = [ + 'status' => 'success', + 'message' => $this->admin::translate('PLUGIN_ADMIN.REMOVE_SUCCESSFUL') + ]; + + return true; + } + + /** + * Handles removing a media file + * + * @return bool True if the action was performed + */ + public function taskRemoveMedia($filename = null) + { + if (!$this->canEditMedia()) { + return false; + } + + if (null === $filename) { + $filename = base64_decode($this->grav['uri']->param('route')); + if (!$filename) { + $filename = base64_decode($this->route); + } + } + + $file = File::instance($filename); + $resultRemoveMedia = false; + + if ($file->exists()) { + $resultRemoveMedia = $file->delete(); + + $fileParts = pathinfo($filename); + + foreach (scandir($fileParts['dirname']) as $file) { + $regex_pattern = '/' . preg_quote($fileParts['filename'], '/') . "@\d+x\." . $fileParts['extension'] . "(?:\.meta\.yaml)?$|" . preg_quote($fileParts['basename'], '/') . "\.meta\.yaml$/"; + if (preg_match($regex_pattern, $file)) { + $path = $fileParts['dirname'] . '/' . $file; + @unlink($path); + } + } + + } + + if ($resultRemoveMedia) { + if ($this->grav['uri']->extension() === 'json') { + $this->admin->json_response = [ + 'status' => 'success', + 'message' => $this->admin::translate('PLUGIN_ADMIN.REMOVE_SUCCESSFUL') + ]; + } else { + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.REMOVE_SUCCESSFUL'), 'info'); + $this->clearMediaCache(); + $this->setRedirect('/media-manager'); + } + + return true; + } + + if ($this->grav['uri']->extension() === 'json') { + $this->admin->json_response = [ + 'status' => 'success', + 'message' => $this->admin::translate('PLUGIN_ADMIN.REMOVE_FAILED') + ]; + } else { + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.REMOVE_FAILED'), 'error'); + } + + return false; + } + + /** + * Handles clearing the media cache + * + * @return bool True if the action was performed + */ + protected function clearMediaCache() + { + $key = 'media-manager-files'; + $cache = $this->grav['cache']; + $cache->delete(md5($key)); + + return true; + } + + /** + * Determine if the user can edit media + * + * @param string $type + * + * @return bool True if the media action is allowed + */ + protected function canEditMedia($type = 'media') + { + if (!$this->authorizeTask('edit media', ['admin.' . $type, 'admin.super'])) { + return false; + } + + return true; + } +} diff --git a/user/plugins/admin/classes/admincontroller.php b/user/plugins/admin/classes/admincontroller.php new file mode 100644 index 0000000..17e0b6a --- /dev/null +++ b/user/plugins/admin/classes/admincontroller.php @@ -0,0 +1,2394 @@ +grav = $grav; + $this->view = $view; + $this->task = $task ?: 'display'; + if (isset($post['data'])) { + $this->data = $this->getPost($post['data']); + unset($post['data']); + } else { + // Backwards compatibility for Form plugin <= 1.2 + $this->data = $this->getPost($post); + } + $this->post = $this->getPost($post); + $this->route = $route; + $this->admin = $this->grav['admin']; + + $this->grav->fireEvent('onAdminControllerInit', new Event(['controller' => &$this])); + } + + /** + * Handle login. + * + * @return bool True if the action was performed. + */ + protected function taskLogin() + { + $this->admin->authenticate($this->data, $this->post); + + return true; + } + + /** + * @return bool True if the action was performed. + */ + protected function taskTwofa() + { + $this->admin->twoFa($this->data, $this->post); + + return true; + } + + /** + * Handle logout. + * + * @return bool True if the action was performed. + */ + protected function taskLogout() + { + $this->admin->logout($this->data, $this->post); + + return true; + } + + /** + * @return bool + */ + public function taskRegenerate2FASecret() + { + if (!$this->authorizeTask('regenerate 2FA Secret', ['admin.login'])) { + return false; + } + + try { + /** @var User $user */ + $user = $this->grav['user']; + + /** @var TwoFactorAuth $twoFa */ + $twoFa = $this->grav['login']->twoFactorAuth(); + $secret = $twoFa->createSecret(); + $image = $twoFa->getQrImageData($user->username, $secret); + + $user->set('twofa_secret', $secret); + + // TODO: data user can also use save, but please test it before removing this code. + if ($user instanceof \Grav\Common\User\DataUser\User) { + // Save secret into the user file. + $file = $user->file(); + if ($file->exists()) { + $content = (array)$file->content(); + $content['twofa_secret'] = $secret; + $file->save($content); + $file->free(); + } + } else { + $user->save(); + } + + $this->admin->json_response = ['status' => 'success', 'image' => $image, 'secret' => preg_replace('|(\w{4})|', '\\1 ', $secret)]; + } catch (\Exception $e) { + $this->admin->json_response = ['status' => 'error', 'message' => $e->getMessage()]; + return false; + } + + return true; + } + + /** + * Handle the reset password action. + * + * @return bool True if the action was performed. + */ + public function taskReset() + { + $data = $this->data; + + if (isset($data['password'])) { + /** @var UserCollectionInterface $users */ + $users = $this->grav['accounts']; + + $username = isset($data['username']) ? strip_tags(strtolower($data['username'])) : null; + $user = $username ? $users->load($username) : null; + $password = $data['password'] ?? null; + $token = $data['token'] ?? null; + + if ($user && $user->exists() && !empty($user->get('reset'))) { + list($good_token, $expire) = explode('::', $user->get('reset')); + + if ($good_token === $token) { + if (time() > $expire) { + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.RESET_LINK_EXPIRED'), 'error'); + $this->setRedirect('/forgot'); + + return true; + } + + $user->undef('hashed_password'); + $user->undef('reset'); + $user->set('password', $password); + $user->save(); + + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.RESET_PASSWORD_RESET'), 'info'); + $this->setRedirect('/'); + + return true; + } + } + + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.RESET_INVALID_LINK'), 'error'); + $this->setRedirect('/forgot'); + + return true; + + } + + $user = $this->grav['uri']->param('user'); + $token = $this->grav['uri']->param('token'); + + if (empty($user) || empty($token)) { + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.RESET_INVALID_LINK'), 'error'); + $this->setRedirect('/forgot'); + + return true; + } + + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.RESET_NEW_PASSWORD'), 'info'); + + $this->admin->forgot = ['username' => $user, 'token' => $token]; + + return true; + } + + /** + * Handle the email password recovery procedure. + * + * @return bool True if the action was performed. + */ + protected function taskForgot() + { + $param_sep = $this->grav['config']->get('system.param_sep', ':'); + $post = $this->post; + $data = $this->data; + $login = $this->grav['login']; + + /** @var UserCollectionInterface $users */ + $users = $this->grav['accounts']; + + $username = isset($data['username']) ? strip_tags(strtolower($data['username'])) : ''; + $user = !empty($username) ? $users->load($username) : null; + + if (!isset($this->grav['Email'])) { + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error'); + $this->setRedirect($post['redirect']); + + return true; + } + + if (!$user || !$user->exists()) { + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL'), + 'info'); + $this->setRedirect($post['redirect']); + + return true; + } + + if (empty($user->email)) { + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL'), + 'info'); + $this->setRedirect($post['redirect']); + + return true; + } + + $count = $this->grav['config']->get('plugins.login.max_pw_resets_count', 0); + $interval =$this->grav['config']->get('plugins.login.max_pw_resets_interval', 2); + + if ($login->isUserRateLimited($user, 'pw_resets', $count, $interval)) { + $this->admin->setMessage($this->admin::translate(['PLUGIN_LOGIN.FORGOT_CANNOT_RESET_IT_IS_BLOCKED', $user->email, $interval]), 'error'); + $this->setRedirect($post['redirect']); + + return true; + } + + $token = md5(uniqid(mt_rand(), true)); + $expire = time() + 604800; // next week + + $user->set('reset', $token . '::' . $expire); + $user->save(); + + $author = $this->grav['config']->get('site.author.name', ''); + $fullname = $user->fullname ?: $username; + $reset_link = rtrim($this->grav['uri']->rootUrl(true), '/') . '/' . trim($this->admin->base, + '/') . '/reset/task' . $param_sep . 'reset/user' . $param_sep . $username . '/token' . $param_sep . $token . '/admin-nonce' . $param_sep . Utils::getNonce('admin-form'); + + $sitename = $this->grav['config']->get('site.title', 'Website'); + $from = $this->grav['config']->get('plugins.email.from'); + + if (empty($from)) { + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error'); + $this->setRedirect($post['redirect']); + + return true; + } + + $to = $user->email; + + $subject = $this->admin::translate(['PLUGIN_ADMIN.FORGOT_EMAIL_SUBJECT', $sitename]); + $content = $this->admin::translate([ + 'PLUGIN_ADMIN.FORGOT_EMAIL_BODY', + $fullname, + $reset_link, + $author, + $sitename + ]); + + $body = $this->grav['twig']->processTemplate('email/base.html.twig', ['content' => $content]); + + $message = $this->grav['Email']->message($subject, $body, 'text/html')->setFrom($from)->setTo($to); + + $sent = $this->grav['Email']->send($message); + + if ($sent < 1) { + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.FORGOT_FAILED_TO_EMAIL'), 'error'); + } else { + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL'), + 'info'); + } + + $this->setRedirect('/'); + + return true; + } + + /** + * Enable a plugin. + * + * @return bool True if the action was performed. + */ + public function taskEnable() + { + if (!$this->authorizeTask('enable plugin', ['admin.plugins', 'admin.super'])) { + return false; + } + + if ($this->view !== 'plugins') { + return false; + } + + // Filter value and save it. + $this->post = ['enabled' => true]; + $obj = $this->prepareData($this->post); + $obj->save(); + + $this->post = ['_redirect' => 'plugins']; + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.SUCCESSFULLY_ENABLED_PLUGIN'), 'info'); + + return true; + } + + /** + * Gets the configuration data for a given view & post + * + * @param array $data + * + * @return object + */ + protected function prepareData(array $data) + { + $type = trim("{$this->view}/{$this->admin->route}", '/'); + $data = $this->admin->data($type, $data); + + return $data; + } + + /** + * Disable a plugin. + * + * @return bool True if the action was performed. + */ + public function taskDisable() + { + if (!$this->authorizeTask('disable plugin', ['admin.plugins', 'admin.super'])) { + return false; + } + + if ($this->view !== 'plugins') { + return false; + } + + // Filter value and save it. + $this->post = ['enabled' => false]; + $obj = $this->prepareData($this->post); + $obj->save(); + + $this->post = ['_redirect' => 'plugins']; + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.SUCCESSFULLY_DISABLED_PLUGIN'), 'info'); + + return true; + } + + /** + * Set the default theme. + * + * @return bool True if the action was performed. + */ + public function taskActivate() + { + if (!$this->authorizeTask('activate theme', ['admin.themes', 'admin.super'])) { + return false; + } + + if ($this->view !== 'themes') { + return false; + } + + $this->post = ['_redirect' => 'themes']; + + // Make sure theme exists (throws exception) + $name = $this->route; + $this->grav['themes']->get($name); + + // Store system configuration. + $system = $this->admin->data('config/system'); + $system->set('pages.theme', $name); + $system->save(); + + // Force configuration reload and save. + /** @var Config $config */ + $config = $this->grav['config']; + $config->reload()->save(); + + $config->set('system.pages.theme', $name); + + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.SUCCESSFULLY_CHANGED_THEME'), 'info'); + + return true; + } + + /** + * Handles updating Grav + * + * @return bool False if user has no permissions. + */ + public function taskUpdategrav() + { + if (!$this->authorizeTask('install grav', ['admin.super'])) { + return false; + } + + $gpm = Gpm::GPM(); + $version = $gpm->grav->getVersion(); + $result = Gpm::selfupgrade(); + + if ($result) { + $json_response = [ + 'status' => 'success', + 'type' => 'updategrav', + 'version' => $version, + 'message' => $this->admin::translate('PLUGIN_ADMIN.GRAV_WAS_SUCCESSFULLY_UPDATED_TO') . ' ' . $version + ]; + } else { + $json_response = [ + 'status' => 'error', + 'type' => 'updategrav', + 'version' => GRAV_VERSION, + 'message' => $this->admin::translate('PLUGIN_ADMIN.GRAV_UPDATE_FAILED') . '
' . Installer::lastErrorMsg() + ]; + } + + return $this->sendJsonResponse($json_response); + } + + /** + * Handles uninstalling plugins and themes + * + * @deprecated + * + * @return bool True if the action was performed + */ + public function taskUninstall() + { + $type = $this->view === 'plugins' ? 'plugins' : 'themes'; + if (!$this->authorizeTask('uninstall ' . $type, ['admin.' . $type, 'admin.super'])) { + return false; + } + + $package = $this->route; + + $result = Gpm::uninstall($package, []); + + if ($result) { + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.UNINSTALL_SUCCESSFUL'), 'info'); + } else { + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.UNINSTALL_FAILED'), 'error'); + } + + $this->post = ['_redirect' => $this->view]; + + return true; + } + + /** + * Handles creating an empty page folder (without markdown file) + * + * @return bool True if the action was performed. + */ + public function taskSaveNewFolder() + { + if (!$this->authorizeTask('save', $this->dataPermissions())) { + return false; + } + + $data = (array)$this->data; + + if ($data['route'] === '/') { + $path = $this->grav['locator']->findResource('page://'); + } else { + $path = $this->grav['page']->find($data['route'])->path(); + } + + $orderOfNewFolder = static::getNextOrderInFolder($path); + $new_path = $path . '/' . $orderOfNewFolder . '.' . $data['folder']; + + Folder::create($new_path); + Cache::clearCache('invalidate'); + + $this->grav->fireEvent('onAdminAfterSaveAs', new Event(['path' => $new_path])); + + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.SUCCESSFULLY_SAVED'), 'info'); + + $multilang = $this->isMultilang(); + $admin_route = $this->admin->base; + $redirect_url = '/' . ($multilang ? ($this->grav['session']->admin_lang) : '') . $admin_route . '/' . $this->view; + $this->setRedirect($redirect_url); + + return true; + } + + /** + * Get the next available ordering number in a folder + * + * @param string $path + * + * @return string the correct order string to prepend + */ + public static function getNextOrderInFolder($path) + { + $files = Folder::all($path, ['recursive' => false]); + + $highestOrder = 0; + foreach ($files as $file) { + preg_match(PAGE_ORDER_PREFIX_REGEX, $file, $order); + + if (isset($order[0])) { + $theOrder = (int)trim($order[0], '.'); + } else { + $theOrder = 0; + } + + if ($theOrder >= $highestOrder) { + $highestOrder = $theOrder; + } + } + + $orderOfNewFolder = $highestOrder + 1; + + if ($orderOfNewFolder < 10) { + $orderOfNewFolder = '0' . $orderOfNewFolder; + } + + return $orderOfNewFolder; + } + + /** + * Handles form and saves the input data if its valid. + * + * @return bool True if the action was performed. + */ + public function taskSave() + { + if (!$this->authorizeTask('save', $this->dataPermissions())) { + return false; + } + + $this->grav['twig']->twig_vars['current_form_data'] = (array)$this->data; + + switch ($this->view) { + case 'pages': + return $this->taskSavePage(); + case 'user': + return $this->taskSaveUser(); + default: + return $this->taskSaveDefault(); + } + } + + protected function taskSavePage() + { + $reorder = true; + + $data = (array)$this->data; + $this->grav['twig']->twig_vars['current_form_data'] = $data; + + /** @var Pages $pages */ + $pages = $this->grav['pages']; + + // Find new parent page in order to build the path. + $route = $data['route'] ?? dirname($this->admin->route); + + /** @var PageInterface $obj */ + $obj = $this->admin->page(true); + + if (!isset($data['folder']) || !$data['folder']) { + $data['folder'] = $obj->slug(); + $this->data['folder'] = $obj->slug(); + } + + // Ensure route is prefixed with a forward slash. + $route = '/' . ltrim($route, '/'); + + // Check for valid frontmatter + if (isset($data['frontmatter']) && !$this->checkValidFrontmatter($data['frontmatter'])) { + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.INVALID_FRONTMATTER_COULD_NOT_SAVE'), + 'error'); + return false; + } + + // XSS Checks for page content + $xss_whitelist = $this->grav['config']->get('security.xss_whitelist', 'admin.super'); + if (!$this->admin->authorize($xss_whitelist)) { + $check_what = ['header' => $data['header'] ?? '', 'frontmatter' => $data['frontmatter'] ?? '', 'content' => $data['content'] ?? '']; + $results = Security::detectXssFromArray($check_what); + if (!empty($results)) { + $this->admin->setMessage(' ' . $this->admin::translate('PLUGIN_ADMIN.XSS_ONSAVE_ISSUE'), + 'error'); + return false; + } + } + + $parent = $route && $route !== '/' && $route !== '.' && $route !== '/.' ? $pages->dispatch($route, true) : $pages->root(); + $original_order = (int)trim($obj->order(), '.'); + + try { + // Change parent if needed and initialize move (might be needed also on ordering/folder change). + $obj = $obj->move($parent); + $this->preparePage($obj, false, $obj->language()); + $obj->validate(); + + } catch (\Exception $e) { + $this->admin->setMessage($e->getMessage(), 'error'); + + return false; + } + $obj->filter(); + + // rename folder based on visible + if ($original_order === 1000) { + // increment order to force reshuffle + $obj->order($original_order + 1); + } + + if (isset($data['order']) && !empty($data['order'])) { + $reorder = explode(',', $data['order']); + } + + // add or remove numeric prefix based on ordering value + if (isset($data['ordering'])) { + if ($data['ordering'] && !$obj->order()) { + $obj->order(static::getNextOrderInFolder($obj->parent()->path())); + $reorder = false; + } elseif (!$data['ordering'] && $obj->order()) { + $obj->folder($obj->slug()); + } + } + + $obj = $this->storeFiles($obj); + + if ($obj) { + // Event to manipulate data before saving the object + $this->grav->fireEvent('onAdminSave', new Event(['object' => &$obj])); + $obj->save($reorder); + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.SUCCESSFULLY_SAVED'), 'info'); + $this->grav->fireEvent('onAdminAfterSave', new Event(['object' => $obj])); + } + + if (method_exists($obj, 'unsetRouteSlug')) { + $obj->unsetRouteSlug(); + } + + $multilang = $this->isMultilang(); + + if ($multilang) { + if (!$obj->language()) { + $obj->language($this->grav['session']->admin_lang); + } + } + $admin_route = $this->admin->base; + + $route = $obj->rawRoute(); + $redirect_url = ($multilang ? '/' . $obj->language() : '') . $admin_route . '/' . $this->view . $route; + $this->setRedirect($redirect_url); + + return true; + } + + protected function taskSaveUser() + { + /** @var UserCollectionInterface $users */ + $users = $this->grav['accounts']; + + $user = $users->load($this->admin->route); + + if (!$this->admin->authorize(['admin.super', 'admin.users'])) { + // no user file or not admin.super or admin.users + if ($user->username !== $this->grav['user']->username) { + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK') . ' save.','error'); + + return false; + } + } + + /** @var Data\Blueprint $blueprint */ + $blueprint = $user->blueprints(); + $data = $blueprint->processForm($this->admin->cleanUserPost((array)$this->data)); + $data = new Data\Data($data, $blueprint); + + try { + $data->validate(); + $data->filter(); + } catch (\Exception $e) { + $this->admin->setMessage($e->getMessage(), 'error'); + + return false; + } + + $user->update($data->toArray()); + + $user = $this->storeFiles($user); + + if ($user) { + // Event to manipulate data before saving the object + $this->grav->fireEvent('onAdminSave', new Event(['object' => &$user])); + $user->save(); + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.SUCCESSFULLY_SAVED'), 'info'); + $this->grav->fireEvent('onAdminAfterSave', new Event(['object' => $user])); + } + + if ($user->username === $this->grav['user']->username) { + /** @var UserCollectionInterface $users */ + $users = $this->grav['accounts']; + + //Editing current user. Reload user object + $this->grav['user']->undef('avatar'); + $this->grav['user']->merge($users->load($this->admin->route)->toArray()); + } + + return true; + } + + protected function taskSaveDefault() + { + // Handle standard data types. + $obj = $this->prepareData((array)$this->data); + + try { + $obj->validate(); + } catch (\Exception $e) { + $this->admin->setMessage($e->getMessage(), 'error'); + + return false; + } + + $obj->filter(); + + $obj = $this->storeFiles($obj); + + if ($obj) { + // Event to manipulate data before saving the object + $this->grav->fireEvent('onAdminSave', new Event(['object' => &$obj])); + $obj->save(); + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.SUCCESSFULLY_SAVED'), 'info'); + $this->grav->fireEvent('onAdminAfterSave', new Event(['object' => $obj])); + } + + // Force configuration reload. + /** @var Config $config */ + $config = $this->grav['config']; + $config->reload(); + + return true; + } + + /** + * @param string $frontmatter + * + * @return bool + */ + public function checkValidFrontmatter($frontmatter) + { + try { + Yaml::parse($frontmatter); + } catch (\RuntimeException $e) { + return false; + } + + return true; + } + + /** + * Continue to the new page. + * + * @return bool True if the action was performed. + */ + public function taskContinue() + { + $data = (array)$this->data; + + if ($this->view === 'users') { + $username = strip_tags(strtolower($data['username'])); + $this->setRedirect("{$this->view}/{$username}"); + + return true; + } + + if ($this->view === 'groups') { + $this->setRedirect("{$this->view}/{$data['groupname']}"); + + return true; + } + + if ($this->view !== 'pages') { + return false; + } + + $route = $data['route'] !== '/' ? $data['route'] : ''; + $folder = $data['folder']; + // Handle @slugify-{field} value, automatically slugifies the specified field + if (0 === strpos($folder, '@slugify-')) { + $folder = \Grav\Plugin\Admin\Utils::slug($data[substr($folder, 9)]); + } + $folder = ltrim($folder, '_'); + if (!empty($data['modular'])) { + $folder = '_' . $folder; + } + $path = $route . '/' . $folder; + + $this->admin->session()->{$path} = $data; + + // Store the name and route of a page, to be used pre-filled defaults of the form in the future + $this->admin->session()->lastPageName = $data['name']; + $this->admin->session()->lastPageRoute = $data['route']; + + $this->setRedirect("{$this->view}/" . ltrim($path, '/')); + + return true; + } + + /** + * Toggle the gpm.releases setting + */ + protected function taskGpmRelease() + { + if (!$this->authorizeTask('configuration', ['admin.configuration', 'admin.super'])) { + return false; + } + + // Default release state + $release = 'stable'; + $reload = false; + + // Get the testing release value if set + if ($this->post['release'] === 'testing') { + $release = 'testing'; + } + + $config = $this->grav['config']; + $current_release = $config->get('system.gpm.releases'); + + // If the releases setting is different, save it in the system config + if ($current_release !== $release) { + $data = new Data\Data($config->get('system')); + $data->set('gpm.releases', $release); + + // Get the file location + $file = CompiledYamlFile::instance($this->grav['locator']->findResource('config://system.yaml')); + $data->file($file); + + // Save the configuration + $data->save(); + $config->reload(); + $reload = true; + } + + $this->admin->json_response = ['status' => 'success', 'reload' => $reload]; + + return true; + } + + /** + * Keep alive + */ + protected function taskKeepAlive() + { + exit(); + } + + /** + * Get Notifications + * + */ + protected function taskGetNotifications() + { + if (!$this->authorizeTask('dashboard', ['admin.login', 'admin.super'])) { + $this->sendJsonResponse(['status' => 'error', 'message' => 'unauthorized']); + } + + // do we need to force a reload + $refresh = $this->data['refresh'] === 'true'; + $filter = $this->data['filter'] ?? ''; + $filter_types = !empty($filter) ? array_map('trim', explode(',', $filter)) : []; + + try { + $notifications = $this->admin->getNotifications($refresh); + $notification_data = []; + + foreach ($notifications as $type => $type_notifications) { + if ($filter_types && in_array($type, $filter_types, true)) { + $twig_template = 'partials/notification-' . $type . '-block.html.twig'; + $notification_data[$type] = $this->grav['twig']->processTemplate($twig_template, ['notifications' => $type_notifications]); + } + } + + $json_response = [ + 'status' => 'success', + 'notifications' => $notification_data + ]; + } catch (\Exception $e) { + $json_response = ['status' => 'error', 'message' => $e->getMessage()]; + } + + $this->sendJsonResponse($json_response); + } + + /** Get Newsfeeds */ + protected function taskGetNewsFeed() + { + if (!$this->authorizeTask('dashboard', ['admin.login', 'admin.super'])) { + $this->sendJsonResponse(['status' => 'error', 'message' => 'unauthorized']); + } + + $refresh = $this->data['refresh'] === 'true' ? true : false; + + try { + $feed = $this->admin->getFeed($refresh); + $feed_data = $this->grav['twig']->processTemplate('partials/feed-block.html.twig', ['feed' => $feed]); + + $json_response = [ + 'status' => 'success', + 'feed_data' => $feed_data + ]; + } catch (MalformedXmlException $e) { + $json_response = ['status' => 'error', 'message' => $e->getMessage()]; + } + + $this->sendJsonResponse($json_response); + } + + /** + * Get update status from GPM + */ + protected function taskGetUpdates() + { + if (!$this->authorizeTask('dashboard', ['admin.login', 'admin.super'])) { + return false; + } + + $data = $this->post; + $flush = !empty($data['flush']); + + if (isset($this->grav['session'])) { + $this->grav['session']->close(); + } + + try { + $gpm = new GravGPM($flush); + + $resources_updates = $gpm->getUpdatable(); + foreach ($resources_updates as $key => $update) { + if (!is_iterable($update)) { + continue; + } + + foreach ($update as $slug => $item) { + $resources_updates[$key][$slug] = $item; + } + } + + if ($gpm->grav !== null) { + $grav_updates = [ + 'isUpdatable' => $gpm->grav->isUpdatable(), + 'assets' => $gpm->grav->getAssets(), + 'version' => GRAV_VERSION, + 'available' => $gpm->grav->getVersion(), + 'date' => $gpm->grav->getDate(), + 'isSymlink' => $gpm->grav->isSymlink() + ]; + + $this->admin->json_response = [ + 'status' => 'success', + 'payload' => [ + 'resources' => $resources_updates, + 'grav' => $grav_updates, + 'installed' => $gpm->countInstalled(), + 'flushed' => $flush + ] + ]; + } else { + $this->admin->json_response = ['status' => 'error', 'message' => 'Cannot connect to the GPM']; + + return false; + } + + } catch (\Exception $e) { + $this->admin->json_response = ['status' => 'error', 'message' => $e->getMessage()]; + + return false; + } + + return true; + } + + /** + * Handle getting a new package dependencies needed to be installed + * + * @return bool + */ + protected function taskGetPackagesDependencies() + { + $data = $this->post; + $packages = isset($data['packages']) ? explode(',', $data['packages']) : ''; + $packages = (array)$packages; + + try { + $this->admin->checkPackagesCanBeInstalled($packages); + $dependencies = $this->admin->getDependenciesNeededToInstall($packages); + } catch (\Exception $e) { + $this->admin->json_response = ['status' => 'error', 'message' => $e->getMessage()]; + + return false; + } + + $this->admin->json_response = ['status' => 'success', 'dependencies' => $dependencies]; + + return true; + } + + protected function taskInstallDependenciesOfPackages() + { + $data = $this->post; + $packages = isset($data['packages']) ? explode(',', $data['packages']) : ''; + $packages = (array)$packages; + + $type = $data['type'] ?? ''; + + if (!$this->authorizeTask('install ' . $type, ['admin.' . $type, 'admin.super'])) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK') + ]; + + return false; + } + + try { + $dependencies = $this->admin->getDependenciesNeededToInstall($packages); + } catch (\Exception $e) { + $this->admin->json_response = ['status' => 'error', 'message' => $e->getMessage()]; + + return false; + } + + $result = Gpm::install(array_keys($dependencies), ['theme' => $type === 'theme']); + + if ($result) { + $this->admin->json_response = ['status' => 'success', 'message' => 'Dependencies installed successfully']; + } else { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.INSTALLATION_FAILED') + ]; + } + + return true; + } + + protected function taskInstallPackage($reinstall = false) + { + $data = $this->post; + $package = $data['package'] ?? ''; + $type = $data['type'] ?? ''; + + if (!$this->authorizeTask('install ' . $type, ['admin.' . $type, 'admin.super'])) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK') + ]; + + return false; + } + + try { + $result = Gpm::install($package, ['theme' => $type === 'theme']); + } catch (\Exception $e) { + $this->admin->json_response = ['status' => 'error', 'message' => $e->getMessage()]; + + return false; + } + + if ($result) { + $this->admin->json_response = [ + 'status' => 'success', + 'message' => $this->admin::translate(is_string($result) ? $result : sprintf($this->admin::translate($reinstall ?: 'PLUGIN_ADMIN.PACKAGE_X_REINSTALLED_SUCCESSFULLY', + null), $package)) + ]; + } else { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate($reinstall ?: 'PLUGIN_ADMIN.INSTALLATION_FAILED') + ]; + } + + return true; + } + + /** + * Handle removing a package + * + * @return bool + */ + protected function taskRemovePackage() + { + $data = $this->post; + $package = $data['package'] ?? ''; + $type = $data['type'] ?? ''; + + if (!$this->authorizeTask('uninstall ' . $type, ['admin.' . $type, 'admin.super'])) { + $json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK') + ]; + + return $this->sendJsonResponse($json_response, 403); + } + + //check if there are packages that have this as a dependency. Abort and show which ones + $dependent_packages = $this->admin->getPackagesThatDependOnPackage($package); + if (count($dependent_packages) > 0) { + if (count($dependent_packages) > 1) { + $message = 'The installed packages ' . implode(', ', + $dependent_packages) . ' depends on this package. Please remove those first.'; + } else { + $message = 'The installed package ' . implode(', ', + $dependent_packages) . ' depends on this package. Please remove it first.'; + } + + $json_response = ['status' => 'error', 'message' => $message]; + + return $this->sendJsonResponse($json_response, 200); + } + + try { + $dependencies = $this->admin->dependenciesThatCanBeRemovedWhenRemoving($package); + $result = Gpm::uninstall($package, []); + } catch (\Exception $e) { + $json_response = ['status' => 'error', 'message' => $e->getMessage()]; + + return $this->sendJsonResponse($json_response, 200); + } + + if ($result) { + $json_response = [ + 'status' => 'success', + 'dependencies' => $dependencies, + 'message' => $this->admin::translate(is_string($result) ? $result : 'PLUGIN_ADMIN.UNINSTALL_SUCCESSFUL') + ]; + + return $this->sendJsonResponse($json_response, 200); + } + + $json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.UNINSTALL_FAILED') + ]; + + return $this->sendJsonResponse($json_response, 200); + } + + /** + * Handle reinstalling a package + */ + protected function taskReinstallPackage() + { + $data = $this->post; + + $slug = $data['slug'] ?? ''; + $type = $data['type'] ?? ''; + $package_name = $data['package_name'] ?? ''; + $current_version = $data['current_version'] ?? ''; + + if (!$this->authorizeTask('install ' . $type, ['admin.' . $type, 'admin.super'])) { + $json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK') + ]; + + $this->sendJsonResponse($json_response, 403); + } + + $url = "https://getgrav.org/download/{$type}s/$slug/$current_version"; + + $result = Gpm::directInstall($url); + + if ($result === true) { + $this->admin->json_response = [ + 'status' => 'success', + 'message' => $this->admin::translate(sprintf($this->admin::translate('PLUGIN_ADMIN.PACKAGE_X_REINSTALLED_SUCCESSFULLY', + null), $package_name)) + ]; + } else { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.REINSTALLATION_FAILED') + ]; + } + } + + /** + * Clear the cache. + * + * @return bool True if the action was performed. + */ + protected function taskClearCache() + { + if (!$this->authorizeTask('clear cache', ['admin.cache', 'admin.super', 'admin.maintenance'])) { + return false; + } + + // get optional cleartype param + $clear_type = $this->grav['uri']->param('cleartype'); + + if ($clear_type) { + $clear = $clear_type; + } else { + $clear = 'standard'; + } + + if ($clear === 'purge') { + $msg = Cache::purgeJob(); + $this->admin->json_response = [ + 'status' => 'success', + 'message' => $msg, + ]; + } else { + $results = Cache::clearCache($clear); + if (count($results) > 0) { + $this->admin->json_response = [ + 'status' => 'success', + 'message' => $this->admin::translate('PLUGIN_ADMIN.CACHE_CLEARED') . '
' . $this->admin::translate('PLUGIN_ADMIN.METHOD') . ': ' . $clear . '' + ]; + } else { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.ERROR_CLEARING_CACHE') + ]; + } + } + + + + return true; + } + + /** + * Clear the cache. + * + * @return bool True if the action was performed. + */ + protected function taskHideNotification() + { + if (!$this->authorizeTask('hide notification', ['admin.login'])) { + return false; + } + + $notification_id = $this->grav['uri']->param('notification_id'); + + if (!$notification_id) { + $this->admin->json_response = [ + 'status' => 'error' + ]; + + return false; + } + + $filename = $this->grav['locator']->findResource('user://data/notifications/' . $this->grav['user']->username . YAML_EXT, + true, true); + $file = CompiledYamlFile::instance($filename); + $data = (array)$file->content(); + $data[] = $notification_id; + $file->save($data); + + $this->admin->json_response = [ + 'status' => 'success' + ]; + + return true; + } + + /** + * Handle the backup action + * + * @return bool True if the action was performed. + */ + protected function taskBackup() + { + $param_sep = $this->grav['config']->get('system.param_sep', ':'); + if (!$this->authorizeTask('backup', ['admin.maintenance', 'admin.super'])) { + return false; + } + + $download = $this->grav['uri']->param('download'); + + try { + if ($download) { + $file = base64_decode(urldecode($download)); + $backups_root_dir = $this->grav['locator']->findResource('backup://', true); + + if (0 !== strpos($file, $backups_root_dir)) { + header('HTTP/1.1 401 Unauthorized'); + exit(); + } + + Utils::download($file, true); + } + + $id = $this->grav['uri']->param('id', 0); + $backup = Backups::backup($id); + } catch (\Exception $e) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.AN_ERROR_OCCURRED') . '. ' . $e->getMessage() + ]; + + return true; + } + + $download = urlencode(base64_encode($backup)); + $url = rtrim($this->grav['uri']->rootUrl(false), '/') . '/' . trim($this->admin->base, + '/') . '/task' . $param_sep . 'backup/download' . $param_sep . $download . '/admin-nonce' . $param_sep . Utils::getNonce('admin-form'); + + + + $this->admin->json_response = [ + 'status' => 'success', + 'message' => $this->admin::translate('PLUGIN_ADMIN.YOUR_BACKUP_IS_READY_FOR_DOWNLOAD') . '.
' . $this->admin::translate('PLUGIN_ADMIN.DOWNLOAD_BACKUP') . '', + 'toastr' => [ + 'timeOut' => 0, + 'extendedTimeOut' => 0, + 'closeButton' => true + ] + ]; + + return true; + } + + /** + * Handle delete backup action + * + * @return bool + */ + protected function taskBackupDelete() + { + $param_sep = $this->grav['config']->get('system.param_sep', ':'); + if (!$this->authorizeTask('backup', ['admin.maintenance', 'admin.super'])) { + return false; + } + + $backup = $this->grav['uri']->param('backup', null); + + if (null !== $backup) { + $file = base64_decode(urldecode($backup)); + $backups_root_dir = $this->grav['locator']->findResource('backup://', true); + + $backup_path = $backups_root_dir . '/' . $file; + + if (file_exists($backup_path)) { + unlink($backup_path); + + $this->admin->json_response = [ + 'status' => 'success', + 'message' => $this->admin::translate('PLUGIN_ADMIN.BACKUP_DELETED'), + 'toastr' => [ + 'closeButton' => true + ] + ]; + } else { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.BACKUP_NOT_FOUND'), + ]; + } + } + return true; + } + + protected function taskGetChildTypes() + { + if (!$this->authorizeTask('get childtypes', ['admin.pages', 'admin.super'])) { + return false; + } + + $data = $this->post; + + $rawroute = $data['rawroute'] ?? null; + + if ($rawroute) { + /** @var PageInterface $page */ + $page = $this->grav['pages']->dispatch($rawroute); + + if ($page) { + $child_type = $page->childType(); + + if ($child_type !== '') { + $this->admin->json_response = [ + 'status' => 'success', + 'child_type' => $child_type + ]; + return true; + } + } + } + + $this->admin->json_response = [ + 'status' => 'success', + 'child_type' => '', +// 'message' => $this->admin::translate('PLUGIN_ADMIN.NO_CHILD_TYPE') + ]; + + return true; + } + + /** + * Handles filtering the page by modular/visible/routable in the pages list. + */ + protected function taskFilterPages() + { + if (!$this->authorizeTask('filter pages', ['admin.pages', 'admin.super'])) { + return; + } + + $data = $this->post; + + $flags = !empty($data['flags']) ? array_map('strtolower', explode(',', $data['flags'])) : []; + $queries = !empty($data['query']) ? explode(',', $data['query']) : []; + + /** @var Collection $collection */ + $collection = $this->grav['pages']->all(); + + if (count($flags)) { + // Filter by state + $pageStates = [ + 'modular', + 'nonmodular', + 'visible', + 'nonvisible', + 'routable', + 'nonroutable', + 'published', + 'nonpublished' + ]; + + if (count(array_intersect($pageStates, $flags)) > 0) { + if (in_array('modular', $flags, true)) { + $collection = $collection->modular(); + } + + if (in_array('nonmodular', $flags, true)) { + $collection = $collection->nonModular(); + } + + if (in_array('visible', $flags, true)) { + $collection = $collection->visible(); + } + + if (in_array('nonvisible', $flags, true)) { + $collection = $collection->nonVisible(); + } + + if (in_array('routable', $flags, true)) { + $collection = $collection->routable(); + } + + if (in_array('nonroutable', $flags, true)) { + $collection = $collection->nonRoutable(); + } + + if (in_array('published', $flags, true)) { + $collection = $collection->published(); + } + + if (in_array('nonpublished', $flags, true)) { + $collection = $collection->nonPublished(); + } + } + foreach ($pageStates as $pageState) { + if (($pageState = array_search($pageState, $flags, true)) !== false) { + unset($flags[$pageState]); + } + } + + // Filter by page type + if ($flags) { + $types = []; + + $pageTypes = array_keys(Pages::pageTypes()); + foreach ($pageTypes as $pageType) { + if (($pageKey = array_search($pageType, $flags, true)) !== false) { + $types[] = $pageType; + unset($flags[$pageKey]); + } + } + + if (count($types)) { + $collection = $collection->ofOneOfTheseTypes($types); + } + } + + // Filter by page type + if ($flags) { + $accessLevels = $flags; + $collection = $collection->ofOneOfTheseAccessLevels($accessLevels); + } + } + + if (!empty($queries)) { + foreach ($collection as $page) { + foreach ($queries as $query) { + $query = trim($query); + if (stripos($page->getRawContent(), $query) === false + && stripos($page->title(), $query) === false + && stripos($page->folder(), $query) === false + && stripos($page->slug(), \Grav\Plugin\Admin\Utils::slug($query)) === false + ) { + $collection->remove($page); + } + } + } + } + + $results = []; + foreach ($collection as $path => $page) { + $results[] = $page->route(); + } + + $this->admin->json_response = [ + 'status' => 'success', + 'message' => $this->admin::translate('PLUGIN_ADMIN.PAGES_FILTERED'), + 'results' => $results + ]; + $this->admin->collection = $collection; + } + + /** + * Determines the file types allowed to be uploaded + * + * @return bool True if the action was performed. + */ + protected function taskListmedia() + { + if (!$this->authorizeTask('list media', ['admin.pages', 'admin.super'])) { + return false; + } + + $media = $this->getMedia(); + if (!$media) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.NO_PAGE_FOUND') + ]; + + return false; + } + + $media_list = []; + /** + * @var string $name + * @var Medium|ImageMedium $medium + */ + foreach ($media->all() as $name => $medium) { + + $metadata = []; + $img_metadata = $medium->metadata(); + if ($img_metadata) { + $metadata = $img_metadata; + } + + // Get original name + /** @var ImageMedium $source */ + $source = method_exists($medium, 'higherQualityAlternative') ? $medium->higherQualityAlternative() : null; + + $media_list[$name] = [ + 'url' => $medium->display($medium->get('extension') === 'svg' ? 'source' : 'thumbnail')->cropZoom(400, 300)->url(), + 'size' => $medium->get('size'), + 'metadata' => $metadata, + 'original' => $source ? $source->get('filename') : null + ]; + } + + $this->admin->json_response = ['status' => 'success', 'results' => $media_list]; + + return true; + } + + /** + * @return Media + */ + protected function getMedia() + { + $this->uri = $this->uri ?? $this->grav['uri']; + $uri = $this->uri->post('uri'); + $order = $this->uri->post('order') ?: null; + + if ($uri) { + /** @var UniformResourceLocator $locator */ + $locator = $this->grav['locator']; + + $media_path = $locator->isStream($uri) ? $uri : null; + } else { + $page = $this->admin->page(true); + + $media_path = $page ? $page->path() : null; + } + if ($order) { + $order = array_map('trim', explode(',', $order)); + } + + return $media_path ? new Media($media_path, $order) : null; + } + + /** + * Handles adding a media file to a page + * + * @return bool True if the action was performed. + */ + protected function taskAddmedia() + { + if (!$this->authorizeTask('add media', ['admin.pages', 'admin.super'])) { + return false; + } + + /** @var Config $config */ + $config = $this->grav['config']; + + if (empty($_FILES)) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.EXCEEDED_POSTMAX_LIMIT') + ]; + + return false; + } + + if (!isset($_FILES['file']['error']) || is_array($_FILES['file']['error'])) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.INVALID_PARAMETERS') + ]; + + return false; + } + + // Check $_FILES['file']['error'] value. + switch ($_FILES['file']['error']) { + case UPLOAD_ERR_OK: + break; + case UPLOAD_ERR_NO_FILE: + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.NO_FILES_SENT') + ]; + + return false; + case UPLOAD_ERR_INI_SIZE: + case UPLOAD_ERR_FORM_SIZE: + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.EXCEEDED_FILESIZE_LIMIT') + ]; + + return false; + case UPLOAD_ERR_NO_TMP_DIR: + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.UPLOAD_ERR_NO_TMP_DIR') + ]; + + return false; + default: + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.UNKNOWN_ERRORS') + ]; + + return false; + } + + $filename = $_FILES['file']['name']; + + // Handle bad filenames. + if (!Utils::checkFilename($filename)) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => sprintf($this->admin::translate('PLUGIN_ADMIN.FILEUPLOAD_UNABLE_TO_UPLOAD'), + $filename, 'Bad filename') + ]; + + return false; + } + + // You should also check filesize here. + $grav_limit = Utils::getUploadLimit(); + if ($grav_limit > 0 && $_FILES['file']['size'] > $grav_limit) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.EXCEEDED_GRAV_FILESIZE_LIMIT') + ]; + + return false; + } + + + // Check extension + $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); + + // If not a supported type, return + if (!$extension || !$config->get("media.types.{$extension}")) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.UNSUPPORTED_FILE_TYPE') . ': ' . $extension + ]; + + return false; + } + + + $media = $this->getMedia(); + if (!$media) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.NO_PAGE_FOUND') + ]; + + return false; + } + + /** @var UniformResourceLocator $locator */ + $locator = $this->grav['locator']; + $path = $media->getPath(); + if ($locator->isStream($path)) { + $path = $locator->findResource($path, true, true); + } + + // Upload it + if (!move_uploaded_file($_FILES['file']['tmp_name'], sprintf('%s/%s', $path, $filename))) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.FAILED_TO_MOVE_UPLOADED_FILE') + ]; + + return false; + } + + // Add metadata if needed + $include_metadata = Grav::instance()['config']->get('system.media.auto_metadata_exif', false); + $basename = str_replace(['@3x', '@2x'], '', pathinfo($filename, PATHINFO_BASENAME)); + + $metadata = []; + + if ($include_metadata && isset($media[$basename])) { + $img_metadata = $media[$basename]->metadata(); + if ($img_metadata) { + $metadata = $img_metadata; + } + } + + $page = $this->admin->page(true); + if ($page) { + $this->grav->fireEvent('onAdminAfterAddMedia', new Event(['page' => $page])); + } + + $this->admin->json_response = [ + 'status' => 'success', + 'message' => $this->admin::translate('PLUGIN_ADMIN.FILE_UPLOADED_SUCCESSFULLY'), + 'metadata' => $metadata, + ]; + + return true; + } + + /** + * Handles deleting a media file from a page + * + * @return bool True if the action was performed. + */ + protected function taskDelmedia() + { + if (!$this->authorizeTask('delete media', ['admin.pages', 'admin.super'])) { + return false; + } + + $media = $this->getMedia(); + if (!$media) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.NO_PAGE_FOUND') + ]; + + return false; + } + + $filename = !empty($this->post['filename']) ? $this->post['filename'] : null; + + // Handle bad filenames. + if (!Utils::checkFilename($filename)) { + $filename = null; + } + + if (!$filename) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.NO_FILE_FOUND') + ]; + + return false; + } + + /** @var UniformResourceLocator $locator */ + $locator = $this->grav['locator']; + + $targetPath = $media->getPath() . '/' . $filename; + if ($locator->isStream($targetPath)) { + $targetPath = $locator->findResource($targetPath, true, true); + } + $fileParts = pathinfo($filename); + + $found = false; + + if (file_exists($targetPath)) { + $found = true; + $result = unlink($targetPath); + + if (!$result) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.FILE_COULD_NOT_BE_DELETED') . ': ' . $filename + ]; + + return false; + } + } + + // Remove Extra Files + foreach (scandir($media->getPath(), SCANDIR_SORT_NONE) as $file) { + if (preg_match("/{$fileParts['filename']}@\d+x\.{$fileParts['extension']}(?:\.meta\.yaml)?$|{$filename}\.meta\.yaml$/", $file)) { + + $targetPath = $media->getPath() . '/' . $file; + if ($locator->isStream($targetPath)) { + $targetPath = $locator->findResource($targetPath, true, true); + } + + $result = unlink($targetPath); + + if (!$result) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.FILE_COULD_NOT_BE_DELETED') . ': ' . $filename + ]; + + return false; + } + + $found = true; + } + } + + if (!$found) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.FILE_NOT_FOUND') . ': ' . $filename + ]; + + return false; + } + + $page = $this->admin->page(true); + if ($page) { + $this->grav->fireEvent('onAdminAfterDelMedia', new Event(['page' => $page])); + } + + $this->admin->json_response = [ + 'status' => 'success', + 'message' => $this->admin::translate('PLUGIN_ADMIN.FILE_DELETED') . ': ' . $filename + ]; + + return true; + } + + /** + * Process the page Markdown + * + * @return bool True if the action was performed. + */ + protected function taskProcessMarkdown() + { + if (!$this->authorizeTask('process markdown', ['admin.pages', 'admin.super'])) { + return false; + } + + try { + $page = $this->admin->page(true); + + if (!$page) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.NO_PAGE_FOUND') + ]; + + return false; + } + + $this->preparePage($page, true); + $page->header(); + $page->templateFormat('html'); + + // Add theme template paths to Twig loader + $template_paths = $this->grav['locator']->findResources('theme://templates'); + $this->grav['twig']->twig->getLoader()->addLoader(new \Twig_Loader_Filesystem($template_paths)); + + $html = $page->content(); + + $this->admin->json_response = ['status' => 'success', 'preview' => $html]; + } catch (\Exception $e) { + $this->admin->json_response = ['status' => 'error', 'message' => $e->getMessage()]; + + return false; + } + + return true; + } + + /** + * Prepare a page to be stored: update its folder, name, template, header and content + * + * @param PageInterface $page + * @param bool $clean_header + * @param string $language + */ + protected function preparePage(PageInterface $page, $clean_header = false, $language = '') + { + $input = (array)$this->data; + + if (isset($input['folder']) && $input['folder'] !== $page->value('folder')) { + $order = $page->value('order'); + $ordering = $order ? sprintf('%02d.', $order) : ''; + $page->folder($ordering . $input['folder']); + } + + if (isset($input['name']) && !empty($input['name'])) { + $type = strtolower($input['name']); + $name = preg_replace('|.*/|', '', $type); + if ($language) { + $name .= '.' . $language; + } else { + $language = $this->grav['language']; + if ($language->enabled()) { + $name .= '.' . $language->getLanguage(); + } + } + $name .= '.md'; + $page->name($name); + $page->template($type); + } + + // Special case for Expert mode: build the raw, unset content + if (isset($input['frontmatter'], $input['content'])) { + $page->raw("---\n" . (string)$input['frontmatter'] . "\n---\n" . (string)$input['content']); + unset($input['content']); + // Handle header normally + } elseif (isset($input['header'])) { + $header = $input['header']; + + foreach ($header as $key => $value) { + if ($key === 'metadata' && is_array($header[$key])) { + foreach ($header['metadata'] as $key2 => $value2) { + if (isset($input['toggleable_header']['metadata'][$key2]) && !$input['toggleable_header']['metadata'][$key2]) { + $header['metadata'][$key2] = ''; + } + } + } elseif ($key === 'taxonomy' && is_array($header[$key])) { + foreach ($header[$key] as $taxkey => $taxonomy) { + if (is_array($taxonomy) && \count($taxonomy) === 1 && trim($taxonomy[0]) === '') { + unset($header[$key][$taxkey]); + } + } + } else { + if (isset($input['toggleable_header'][$key]) && !$input['toggleable_header'][$key]) { + $header[$key] = null; + } + } + } + if ($clean_header) { + $header = Utils::arrayFilterRecursive($header, function ($k, $v) { + return !(null === $v || $v === ''); + }); + } + $page->header((object)$header); + $page->frontmatter(Yaml::dump((array)$page->header(), 20)); + } + // Fill content last because it also renders the output. + if (isset($input['content'])) { + $page->rawMarkdown((string)$input['content']); + } + } + + /** + * Save page as a new copy. + * + * @return bool True if the action was performed. + * @throws \RuntimeException + */ + protected function taskCopy() + { + if (!$this->authorizeTask('copy page', ['admin.pages', 'admin.super'])) { + return false; + } + + // Only applies to pages. + if ($this->view !== 'pages') { + return false; + } + + try { + /** @var Pages $pages */ + $pages = $this->grav['pages']; + + // Get the current page. + $original_page = $this->admin->page(true); + + // Find new parent page in order to build the path. + $parent = $original_page->parent() ?: $pages->root(); + // Make a copy of the current page and fill the updated information into it. + $page = $original_page->copy($parent); + + $order = 0; + if ($page->order()) { + $order = $this->getNextOrderInFolder($page->parent()->path()); + } + + // Make sure the header is loaded in case content was set through raw() (expert mode) + $page->header(); + + if ($page->order()) { + $page->order($order); + } + + $folder = $this->findFirstAvailable('folder', $page); + $slug = $this->findFirstAvailable('slug', $page); + + $page->path($page->parent()->path() . DS . $page->order() . $folder); + $page->route($page->parent()->route() . '/' . $slug); + $page->rawRoute($page->parent()->rawRoute() . '/' . $slug); + + // Append progressive number to the copied page title + $match = preg_split('/(\d+)(?!.*\d)/', $original_page->title(), 2, PREG_SPLIT_DELIM_CAPTURE); + $header = $page->header(); + if (!isset($match[1])) { + $header->title = $match[0] . ' 2'; + } else { + $header->title = $match[0] . ((int)$match[1] + 1); + } + + $page->header($header); + $page->save(false); + + $redirect = $this->view . $page->rawRoute(); + $header = $page->header(); + + if (isset($header->slug)) { + $match = preg_split('/-(\d+)$/', $header->slug, 2, PREG_SPLIT_DELIM_CAPTURE); + $header->slug = $match[0] . '-' . (isset($match[1]) ? (int)$match[1] + 1 : 2); + } + + $page->header($header); + + $page->save(); + + $this->grav->fireEvent('onAdminAfterSave', new Event(['page' => $page])); + + // Enqueue message and redirect to new location. + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.SUCCESSFULLY_COPIED'), 'info'); + $this->setRedirect($redirect); + + } catch (\Exception $e) { + throw new \RuntimeException('Copying page failed on error: ' . $e->getMessage()); + } + + return true; + } + + /** + * Find the first available $item ('slug' | 'folder') for a page + * Used when copying a page, to determine the first available slot + * + * @param string $item + * @param PageInterface $page + * + * @return string The first available slot + */ + protected function findFirstAvailable($item, PageInterface $page) + { + if (!$page->parent()->children()) { + return $page->{$item}(); + } + + $withoutPrefix = function ($string) { + $match = preg_split('/^[0-9]+\./u', $string, 2, PREG_SPLIT_DELIM_CAPTURE); + + return $match[1] ?? $match[0]; + }; + + $withoutPostfix = function ($string) { + $match = preg_split('/-(\d+)$/', $string, 2, PREG_SPLIT_DELIM_CAPTURE); + + return $match[0]; + }; + + /* $appendedNumber = function ($string) { + $match = preg_split('/-(\d+)$/', $string, 2, PREG_SPLIT_DELIM_CAPTURE); + $append = (isset($match[1]) ? (int)$match[1] + 1 : 2); + + return $append; + };*/ + + $highest = 1; + $siblings = $page->parent()->children(); + $findCorrectAppendedNumber = function ($item, $page_item, $highest) use ( + $siblings, + &$findCorrectAppendedNumber, + &$withoutPrefix + ) { + foreach ($siblings as $sibling) { + if ($withoutPrefix($sibling->{$item}()) == ($highest === 1 ? $page_item : $page_item . '-' . $highest)) { + $highest = $findCorrectAppendedNumber($item, $page_item, $highest + 1); + + return $highest; + } + } + + return $highest; + }; + + $base = $withoutPrefix($withoutPostfix($page->$item())); + + $return = $base; + $highest = $findCorrectAppendedNumber($item, $base, $highest); + + if ($highest > 1) { + $return .= '-' . $highest; + } + + return $return; + } + + /** + * Reorder pages. + * + * @return bool True if the action was performed. + */ + protected function taskReorder() + { + if (!$this->authorizeTask('reorder pages', ['admin.pages', 'admin.super'])) { + return false; + } + + // Only applies to pages. + if ($this->view !== 'pages') { + return false; + } + + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.REORDERING_WAS_SUCCESSFUL'), 'info'); + + return true; + } + + /** + * Delete page. + * + * @return bool True if the action was performed. + * @throws \RuntimeException + */ + protected function taskDelete() + { + if (!$this->authorizeTask('delete page', ['admin.pages', 'admin.super'])) { + return false; + } + + // Only applies to pages. + if ($this->view !== 'pages') { + return false; + } + + try { + $page = $this->admin->page(); + + if (count($page->translatedLanguages()) > 1) { + $page->file()->delete(); + } else { + Folder::delete($page->path()); + } + + $this->grav->fireEvent('onAdminAfterDelete', new Event(['page' => $page])); + + Cache::clearCache('invalidate'); + + // Set redirect to pages list. + $redirect = 'pages'; + + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.SUCCESSFULLY_DELETED'), 'info'); + $this->setRedirect($redirect); + + } catch (\Exception $e) { + throw new \RuntimeException('Deleting page failed on error: ' . $e->getMessage()); + } + + return true; + } + + /** + * Switch the content language. Optionally redirect to a different page. + * + */ + protected function taskSwitchlanguage() + { + if (!$this->authorizeTask('switch language', ['admin.pages', 'admin.super'])) { + return false; + } + + $data = (array)$this->data; + + if (isset($data['lang'])) { + $language = $data['lang']; + } else { + $language = $this->grav['uri']->param('lang'); + } + + if (isset($data['redirect'])) { + $redirect = 'pages/' . $data['redirect']; + } else { + $redirect = 'pages'; + } + + + if ($language) { + $this->grav['session']->admin_lang = $language ?: 'en'; + } + + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.SUCCESSFULLY_SWITCHED_LANGUAGE'), 'info'); + + $admin_route = $this->admin->base; + $this->setRedirect('/' . $language . $admin_route . '/' . $redirect); + + return true; + } + + /** + * Handle direct install. + */ + protected function taskDirectInstall() + { + if (!$this->authorizeTask('install', ['admin.super'])) { + return false; + } + + $file_path = $this->data['file_path'] ?? null; + + if (isset($_FILES['uploaded_file'])) { + + // Check $_FILES['file']['error'] value. + switch ($_FILES['uploaded_file']['error']) { + case UPLOAD_ERR_OK: + break; + case UPLOAD_ERR_NO_FILE: + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.NO_FILES_SENT'), 'error'); + return false; + case UPLOAD_ERR_INI_SIZE: + case UPLOAD_ERR_FORM_SIZE: + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.EXCEEDED_FILESIZE_LIMIT'), 'error'); + return false; + case UPLOAD_ERR_NO_TMP_DIR: + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.UPLOAD_ERR_NO_TMP_DIR'), 'error'); + return false; + default: + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.UNKNOWN_ERRORS'), 'error'); + return false; + } + + $file_name = $_FILES['uploaded_file']['name']; + $file_path = $_FILES['uploaded_file']['tmp_name']; + + // Handle bad filenames. + if (!Utils::checkFilename($file_name)) { + $this->admin->json_response = [ + 'status' => 'error', + 'message' => $this->admin::translate('PLUGIN_ADMIN.UNKNOWN_ERRORS') + ]; + + return false; + } + } + + + $result = Gpm::directInstall($file_path); + + if ($result === true) { + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.INSTALLATION_SUCCESSFUL'), 'info'); + } else { + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.INSTALLATION_FAILED') . ': ' . $result, + 'error'); + } + + $this->setRedirect('/tools'); + + return true; + } + + /** + * Save the current page in a different language. Automatically switches to that language. + * + * @return bool True if the action was performed. + */ + protected function taskSaveas() + { + if (!$this->authorizeTask('save', $this->dataPermissions())) { + return false; + } + + $data = (array)$this->data; + $language = $data['lang']; + + if ($language) { + $this->grav['session']->admin_lang = $language ?: 'en'; + } + + $uri = $this->grav['uri']; + $obj = $this->admin->page($uri->route()); + $this->preparePage($obj, false, $language); + + $file = $obj->file(); + if ($file) { + $filename = $this->determineFilenameIncludingLanguage($obj->name(), $language); + + $path = $obj->path() . DS . $filename; + $aFile = File::instance($path); + $aFile->save(); + + $aPage = new Page(); + $aPage->init(new \SplFileInfo($path), $language . '.md'); + $aPage->header($obj->header()); + $aPage->rawMarkdown($obj->rawMarkdown()); + $aPage->template($obj->template()); + $aPage->validate(); + $aPage->filter(); + + $this->grav->fireEvent('onAdminSave', new Event(['page' => &$aPage])); + $aPage->save(); + $this->grav->fireEvent('onAdminAfterSave', new Event(['page' => $aPage])); + } + + $this->admin->setMessage($this->admin::translate('PLUGIN_ADMIN.SUCCESSFULLY_SWITCHED_LANGUAGE'), 'info'); + $this->setRedirect('/' . $language . $uri->route()); + + return true; + } + + /** + * The what should be the new filename when saving as a new language + * + * @param string $current_filename the current file name, including .md. Example: default.en.md + * @param string $language The new language it will be saved as. Example: 'it' or 'en-GB'. + * + * @return string The new filename. Example: 'default.it' + */ + public function determineFilenameIncludingLanguage($current_filename, $language) + { + $ext = '.md'; + $filename = substr($current_filename, 0, -strlen($ext)); + $languages_enabled = $this->grav['config']->get('system.languages.supported', []); + + $parts = explode('.', trim($filename, '.')); + $lang = array_pop($parts); + + if ($lang === $language) { + return $filename . $ext; + } elseif (in_array($lang, $languages_enabled)) { + $filename = implode('.', $parts); + } + + return $filename . '.' . $language . $ext; + } +} diff --git a/user/plugins/admin/classes/gpm.php b/user/plugins/admin/classes/gpm.php new file mode 100644 index 0000000..dbaafba --- /dev/null +++ b/user/plugins/admin/classes/gpm.php @@ -0,0 +1,430 @@ + GRAV_ROOT, + 'overwrite' => true, + 'ignore_symlinks' => true, + 'skip_invalid' => true, + 'install_deps' => true, + 'theme' => false + ]; + + /** + * @param Package[]|string[]|string $packages + * @param array $options + * + * @return string|bool + */ + public static function install($packages, array $options) + { + $options = array_merge(self::$options, $options); + + if (!Installer::isGravInstance($options['destination']) || !Installer::isValidDestination($options['destination'], + [Installer::EXISTS, Installer::IS_LINK]) + ) { + return false; + } + + $packages = is_array($packages) ? $packages : [$packages]; + $count = count($packages); + + $packages = array_filter(array_map(function ($p) { + return !is_string($p) ? $p instanceof Package ? $p : false : self::GPM()->findPackage($p); + }, $packages)); + + if (!$options['skip_invalid'] && $count !== count($packages)) { + return false; + } + + $messages = ''; + + foreach ($packages as $package) { + if (isset($package->dependencies) && $options['install_deps']) { + $result = static::install($package->dependencies, $options); + + if (!$result) { + return false; + } + } + + // Check destination + Installer::isValidDestination($options['destination'] . DS . $package->install_path); + + if (!$options['overwrite'] && Installer::lastErrorCode() === Installer::EXISTS) { + return false; + } + + if (!$options['ignore_symlinks'] && Installer::lastErrorCode() === Installer::IS_LINK) { + return false; + } + + $license = Licenses::get($package->slug); + $local = static::download($package, $license); + + Installer::install($local, $options['destination'], + ['install_path' => $package->install_path, 'theme' => $options['theme']]); + Folder::delete(dirname($local)); + + $errorCode = Installer::lastErrorCode(); + if ($errorCode) { + $msg = Installer::lastErrorMsg(); + throw new \RuntimeException($msg); + } + + if (count($packages) === 1) { + $message = Installer::getMessage(); + if ($message) { + return $message; + } + + $messages .= $message; + } + } + + return $messages ?: true; + } + + /** + * @param Package[]|string[]|string $packages + * @param array $options + * + * @return string|bool + */ + public static function update($packages, array $options) + { + $options['overwrite'] = true; + + return static::install($packages, $options); + } + + /** + * @param Package[]|string[]|string $packages + * @param array $options + * + * @return string|bool + */ + public static function uninstall($packages, array $options) + { + $options = array_merge(self::$options, $options); + + $packages = (array)$packages; + $count = count($packages); + + $packages = array_filter(array_map(function ($p) { + + if (is_string($p)) { + $p = strtolower($p); + $plugin = static::GPM()->getInstalledPlugin($p); + $p = $plugin ?: static::GPM()->getInstalledTheme($p); + } + + return $p instanceof Package ? $p : false; + + }, $packages)); + + if (!$options['skip_invalid'] && $count !== count($packages)) { + return false; + } + + foreach ($packages as $package) { + + $location = Grav::instance()['locator']->findResource($package->package_type . '://' . $package->slug); + + // Check destination + Installer::isValidDestination($location); + + if (!$options['ignore_symlinks'] && Installer::lastErrorCode() === Installer::IS_LINK) { + return false; + } + + Installer::uninstall($location); + + $errorCode = Installer::lastErrorCode(); + if ($errorCode && $errorCode !== Installer::IS_LINK && $errorCode !== Installer::EXISTS) { + $msg = Installer::lastErrorMsg(); + throw new \RuntimeException($msg); + } + + if (count($packages) === 1) { + $message = Installer::getMessage(); + if ($message) { + return $message; + } + } + } + + return true; + } + + /** + * Direct install a file + * + * @param string $package_file + * + * @return string|bool + */ + public static function directInstall($package_file) + { + if (!$package_file) { + return Admin::translate('PLUGIN_ADMIN.NO_PACKAGE_NAME'); + } + + $tmp_dir = Grav::instance()['locator']->findResource('tmp://', true, true); + $tmp_zip = $tmp_dir . '/Grav-' . uniqid('', false); + + if (Response::isRemote($package_file)) { + $zip = GravGPM::downloadPackage($package_file, $tmp_zip); + } else { + $zip = GravGPM::copyPackage($package_file, $tmp_zip); + } + + if (file_exists($zip)) { + $tmp_source = $tmp_dir . '/Grav-' . uniqid('', false); + $extracted = Installer::unZip($zip, $tmp_source); + + if (!$extracted) { + Folder::delete($tmp_source); + Folder::delete($tmp_zip); + return Admin::translate('PLUGIN_ADMIN.PACKAGE_EXTRACTION_FAILED'); + } + + $type = GravGPM::getPackageType($extracted); + + if (!$type) { + Folder::delete($tmp_source); + Folder::delete($tmp_zip); + return Admin::translate('PLUGIN_ADMIN.NOT_VALID_GRAV_PACKAGE'); + } + + if ($type === 'grav') { + Installer::isValidDestination(GRAV_ROOT . '/system'); + if (Installer::IS_LINK === Installer::lastErrorCode()) { + Folder::delete($tmp_source); + Folder::delete($tmp_zip); + return Admin::translate('PLUGIN_ADMIN.CANNOT_OVERWRITE_SYMLINKS'); + } + + static::upgradeGrav($zip, $extracted); + } else { + $name = GravGPM::getPackageName($extracted); + + if (!$name) { + Folder::delete($tmp_source); + Folder::delete($tmp_zip); + return Admin::translate('PLUGIN_ADMIN.NAME_COULD_NOT_BE_DETERMINED'); + } + + $install_path = GravGPM::getInstallPath($type, $name); + $is_update = file_exists($install_path); + + Installer::isValidDestination(GRAV_ROOT . DS . $install_path); + if (Installer::lastErrorCode() === Installer::IS_LINK) { + Folder::delete($tmp_source); + Folder::delete($tmp_zip); + return Admin::translate('PLUGIN_ADMIN.CANNOT_OVERWRITE_SYMLINKS'); + } + + Installer::install($zip, GRAV_ROOT, + ['install_path' => $install_path, 'theme' => $type === 'theme', 'is_update' => $is_update], + $extracted); + } + + Folder::delete($tmp_source); + + if (Installer::lastErrorCode()) { + return Installer::lastErrorMsg(); + } + + } else { + return Admin::translate('PLUGIN_ADMIN.ZIP_PACKAGE_NOT_FOUND'); + } + + Folder::delete($tmp_zip); + + return true; + } + + /** + * @param Package $package + * + * @return string + */ + private static function download(Package $package, $license = null) + { + $query = ''; + + if ($package->premium) { + $query = \json_encode(array_merge($package->premium, [ + 'slug' => $package->slug, + 'filename' => $package->premium['filename'], + 'license_key' => $license + ])); + + $query = '?d=' . base64_encode($query); + } + + try { + $contents = Response::get($package->zipball_url . $query, []); + } catch (\Exception $e) { + throw new \RuntimeException($e->getMessage()); + } + + $tmp_dir = Admin::getTempDir() . '/Grav-' . uniqid('', false); + Folder::mkdir($tmp_dir); + + $bad_chars = array_merge(array_map('chr', range(0, 31)), ['<', '>', ':', '"', '/', '\\', '|', '?', '*']); + + $filename = $package->slug . str_replace($bad_chars, '', basename($package->zipball_url)); + $filename = preg_replace('/[\\\\\/:"*?&<>|]+/m', '-', $filename); + + file_put_contents($tmp_dir . DS . $filename . '.zip', $contents); + + return $tmp_dir . DS . $filename . '.zip'; + } + + /** + * @param array $package + * @param string $tmp + * + * @return string + */ + private static function _downloadSelfupgrade(array $package, $tmp) + { + $output = Response::get($package['download'], []); + Folder::mkdir($tmp); + file_put_contents($tmp . DS . $package['name'], $output); + + return $tmp . DS . $package['name']; + } + + /** + * @return bool + */ + public static function selfupgrade() + { + $upgrader = new Upgrader(); + + if (!Installer::isGravInstance(GRAV_ROOT)) { + return false; + } + + if (is_link(GRAV_ROOT . DS . 'index.php')) { + Installer::setError(Installer::IS_LINK); + + return false; + } + + if (method_exists($upgrader, 'meetsRequirements') && + method_exists($upgrader, 'minPHPVersion') && + !$upgrader->meetsRequirements()) { + $error = []; + $error[] = '

Grav has increased the minimum PHP requirement.
'; + $error[] = 'You are currently running PHP ' . phpversion() . ''; + $error[] = ', but PHP ' . $upgrader->minPHPVersion() . ' is required.

'; + $error[] = '

Additional information

'; + + Installer::setError(implode("\n", $error)); + + return false; + } + + $update = $upgrader->getAssets()['grav-update']; + $tmp = Admin::getTempDir() . '/Grav-' . uniqid('', false); + if ($tmp) { + $file = self::_downloadSelfupgrade($update, $tmp); + $folder = Installer::unZip($file, $tmp . '/zip'); + $keepFolder = false; + } else { + // If you make $tmp empty, you can install your local copy of Grav (for testing purposes only). + $file = 'grav.zip'; + $folder = '~/phpstorm/grav-clones/grav'; + //$folder = '/home/matias/phpstorm/rockettheme/grav-devtools/grav-clones/grav'; + $keepFolder = true; + } + + static::upgradeGrav($file, $folder, $keepFolder); + + $errorCode = Installer::lastErrorCode(); + + if ($tmp) { + Folder::delete($tmp); + } + + return !(is_string($errorCode) || ($errorCode & (Installer::ZIP_OPEN_ERROR | Installer::ZIP_EXTRACT_ERROR))); + } + + private static function upgradeGrav($zip, $folder, $keepFolder = false) + { + static $ignores = [ + 'backup', + 'cache', + 'images', + 'logs', + 'tmp', + 'user', + '.htaccess', + 'robots.txt' + ]; + + if (!is_dir($folder)) { + Installer::setError('Invalid source folder'); + } + + try { + $script = $folder . '/system/install.php'; + /** Install $installer */ + if ((file_exists($script) && $install = include $script) && is_callable($install)) { + $install($zip); + } else { + Installer::install( + $zip, + GRAV_ROOT, + ['sophisticated' => true, 'overwrite' => true, 'ignore_symlinks' => true, 'ignores' => $ignores], + $folder, + $keepFolder + ); + + Cache::clearCache(); + } + } catch (\Exception $e) { + Installer::setError($e->getMessage()); + } + } +} diff --git a/user/plugins/admin/classes/popularity.php b/user/plugins/admin/classes/popularity.php new file mode 100644 index 0000000..7eef0cb --- /dev/null +++ b/user/plugins/admin/classes/popularity.php @@ -0,0 +1,303 @@ +config = Grav::instance()['config']; + + $this->data_path = Grav::instance()['locator']->findResource('log://popularity', true, true); + $this->daily_file = $this->data_path . '/' . self::DAILY_FILE; + $this->monthly_file = $this->data_path . '/' . self::MONTHLY_FILE; + $this->totals_file = $this->data_path . '/' . self::TOTALS_FILE; + $this->visitors_file = $this->data_path . '/' . self::VISITORS_FILE; + + } + + public function trackHit() + { + // Don't track bot or crawler requests + if (!Grav::instance()['browser']->isHuman()) { + return; + } + + // Respect visitors "do not track" setting + if (!Grav::instance()['browser']->isTrackable()) { + return; + } + + /** @var PageInterface $page */ + $page = Grav::instance()['page']; + $relative_url = str_replace(Grav::instance()['base_url_relative'], '', $page->url()); + + // Don't track error pages or pages that have no route + if ($page->template() === 'error' || !$page->route()) { + return; + } + + // Make sure no 'widcard-style' ignore matches this url + foreach ((array)$this->config->get('plugins.admin.popularity.ignore') as $ignore) { + if (fnmatch($ignore, $relative_url)) { + return; + } + } + + // initial creation if it doesn't exist + if (!file_exists($this->data_path)) { + mkdir($this->data_path); + $this->flushPopularity(); + } + + // Update the data we want to track + $this->updateDaily(); + $this->updateMonthly(); + $this->updateTotals($page->route()); + $this->updateVisitors(Grav::instance()['uri']->ip()); + + } + + protected function updateDaily() + { + + if (!$this->daily_data) { + $this->daily_data = $this->getData($this->daily_file); + } + + $day_month_year = date(self::DAILY_FORMAT); + + // get the daily access count + if (array_key_exists($day_month_year, $this->daily_data)) { + $this->daily_data[$day_month_year] = (int)$this->daily_data[$day_month_year] + 1; + } else { + $this->daily_data[$day_month_year] = 1; + } + + // keep correct number as set by history + $count = (int)$this->config->get('plugins.admin.popularity.history.daily', 30); + $total = count($this->daily_data); + + if ($total > $count) { + $this->daily_data = array_slice($this->daily_data, -$count, $count, true); + } + + file_put_contents($this->daily_file, json_encode($this->daily_data)); + } + + /** + * @return array + */ + public function getDailyChartData() + { + if (!$this->daily_data) { + $this->daily_data = $this->getData($this->daily_file); + } + + $limit = (int)$this->config->get('plugins.admin.popularity.dashboard.days_of_stats', 7); + $chart_data = array_slice($this->daily_data, -$limit, $limit); + + $labels = []; + $data = []; + + /** @var Admin $admin */ + $admin = Grav::instance()['admin']; + foreach ($chart_data as $date => $count) { + $labels[] = $admin::translate([ + 'PLUGIN_ADMIN.' . strtoupper(date('D', strtotime($date)))]) . + '
' . date('M d', strtotime($date)); + $data[] = $count; + } + + return ['labels' => $labels, 'data' => $data]; + } + + /** + * @return int + */ + public function getDailyTotal() + { + if (!$this->daily_data) { + $this->daily_data = $this->getData($this->daily_file); + } + + if (isset($this->daily_data[date(self::DAILY_FORMAT)])) { + return $this->daily_data[date(self::DAILY_FORMAT)]; + } + + return 0; + } + + /** + * @return int + */ + public function getWeeklyTotal() + { + if (!$this->daily_data) { + $this->daily_data = $this->getData($this->daily_file); + } + + $day = 0; + $total = 0; + foreach (array_reverse($this->daily_data) as $daily) { + $total += $daily; + $day++; + if ($day === 7) { + break; + } + } + + return $total; + } + + /** + * @return int + */ + public function getMonthlyTotal() + { + if (!$this->monthly_data) { + $this->monthly_data = $this->getData($this->monthly_file); + } + if (isset($this->monthly_data[date(self::MONTHLY_FORMAT)])) { + return $this->monthly_data[date(self::MONTHLY_FORMAT)]; + } + + return 0; + } + + protected function updateMonthly() + { + + if (!$this->monthly_data) { + $this->monthly_data = $this->getData($this->monthly_file); + } + + $month_year = date(self::MONTHLY_FORMAT); + + // get the monthly access count + if (array_key_exists($month_year, $this->monthly_data)) { + $this->monthly_data[$month_year] = (int)$this->monthly_data[$month_year] + 1; + } else { + $this->monthly_data[$month_year] = 1; + } + + // keep correct number as set by history + $count = (int)$this->config->get('plugins.admin.popularity.history.monthly', 12); + $total = count($this->monthly_data); + $this->monthly_data = array_slice($this->monthly_data, $total - $count, $count); + + + file_put_contents($this->monthly_file, json_encode($this->monthly_data)); + } + + /** + * @return array + */ + protected function getMonthyChartData() + { + if (!$this->monthly_data) { + $this->monthly_data = $this->getData($this->monthly_file); + } + + $labels = []; + $data = []; + + foreach ($this->monthly_data as $date => $count) { + $labels[] = date('M', strtotime($date)); + $data[] = $count; + } + + return ['labels' => $labels, 'data' => $data]; + } + + /** + * @param string $url + */ + protected function updateTotals($url) + { + if (!$this->totals_data) { + $this->totals_data = $this->getData($this->totals_file); + } + + // get the totals for this url + if (array_key_exists($url, $this->totals_data)) { + $this->totals_data[$url] = (int)$this->totals_data[$url] + 1; + } else { + $this->totals_data[$url] = 1; + } + + file_put_contents($this->totals_file, json_encode($this->totals_data)); + } + + /** + * @param string $ip + */ + protected function updateVisitors($ip) + { + if (!$this->visitors_data) { + $this->visitors_data = $this->getData($this->visitors_file); + } + + // update with current timestamp + $this->visitors_data[hash('sha1', $ip)] = time(); + $visitors = $this->visitors_data; + arsort($visitors); + + $count = (int)$this->config->get('plugins.admin.popularity.history.visitors', 20); + $this->visitors_data = array_slice($visitors, 0, $count, true); + + file_put_contents($this->visitors_file, json_encode($this->visitors_data)); + } + + /** + * @param string $path + * + * @return array + */ + protected function getData($path) + { + if (file_exists($path)) { + return (array)json_decode(file_get_contents($path), true); + } + + return []; + } + + + public function flushPopularity() + { + file_put_contents($this->daily_file, []); + file_put_contents($this->monthly_file, []); + file_put_contents($this->totals_file, []); + file_put_contents($this->visitors_file, []); + } +} diff --git a/user/plugins/admin/classes/themes.php b/user/plugins/admin/classes/themes.php new file mode 100644 index 0000000..43883bb --- /dev/null +++ b/user/plugins/admin/classes/themes.php @@ -0,0 +1,22 @@ +grav['themes']; + $themes->configure(); + $themes->initTheme(); + + $this->grav->fireEvent('onAdminThemeInitialized'); + } +} diff --git a/user/plugins/admin/classes/utils.php b/user/plugins/admin/classes/utils.php new file mode 100644 index 0000000..067764b --- /dev/null +++ b/user/plugins/admin/classes/utils.php @@ -0,0 +1,54 @@ +find($email, ['email']); + } + + /** + * Generates a slug of the given string + * + * @param string $str + * @return string + */ + public static function slug(string $str) + { + if (function_exists('transliterator_transliterate')) { + $str = transliterator_transliterate('Any-Latin; NFD; [:Nonspacing Mark:] Remove; NFC; [:Punctuation:] Remove;', $str); + } else { + $str = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $str); + } + + $str = strtolower($str); + $str = preg_replace('/[-\s]+/', '-', $str); + $str = preg_replace('/[^a-z0-9-]/i', '', $str); + $str = trim($str, '-'); + + return $str; + } +} diff --git a/user/plugins/admin/codeception.yml b/user/plugins/admin/codeception.yml new file mode 100644 index 0000000..7d317a5 --- /dev/null +++ b/user/plugins/admin/codeception.yml @@ -0,0 +1,18 @@ +actor: Tester +paths: + tests: tests + log: tests/_output + data: tests/_data + support: tests/_support + envs: tests/_envs +settings: + bootstrap: _bootstrap.php + colors: true + memory_limit: 1024M +extensions: + enabled: + - Codeception\Extension\RunFailed + # - Codeception\Extension\Recorder + +modules: + config: diff --git a/user/plugins/admin/composer.json b/user/plugins/admin/composer.json new file mode 100644 index 0000000..86ebc21 --- /dev/null +++ b/user/plugins/admin/composer.json @@ -0,0 +1,51 @@ +{ + "name": "getgrav/grav-plugin-admin", + "type": "grav-plugin", + "description": "Admin plugin for Grav CMS", + "keywords": ["admin", "plugin", "manager", "panel"], + "homepage": "https://github.com/getgrav/grav-plugin-admin", + "license": "MIT", + "authors": [ + { + "name": "Team Grav", + "email": "devs@getgrav.org", + "homepage": "https://getgrav.org", + "role": "Developer" + } + ], + "support": { + "issues": "https://github.com/getgrav/grav-plugin-admin/issues", + "irc": "https://chat.getgrav.org", + "forum": "https://discourse.getgrav.org", + "docs": "https://github.com/getgrav/grav-plugin-admin/blob/master/README.md" + }, + "require": { + "php": ">=7.1.3", + "ext-json": "*", + "composer/semver": "^1.4", + "p3k/picofeed": "@stable" + }, + "require-dev": { + "codeception/codeception": "^2.4", + "fzaninotto/faker": "^1.8", + "symfony/yaml": "~4.1", + "symfony/console": "~4.1", + "symfony/finder": "~4.1", + "symfony/event-dispatcher": "~4.1" + }, + "autoload": { + "classmap": [ + "classes/", + "admin.php" + ] + }, + "config": { + "platform": { + "php": "7.1.3" + } + }, + "scripts": { + "test": "vendor/bin/codecept run unit", + "test-windows": "vendor\\bin\\codecept run unit" + } +} diff --git a/user/plugins/admin/composer.lock b/user/plugins/admin/composer.lock new file mode 100644 index 0000000..1a16fd4 --- /dev/null +++ b/user/plugins/admin/composer.lock @@ -0,0 +1,2852 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "8b3c07286e8c9baf049b2da482136b3a", + "packages": [ + { + "name": "composer/semver", + "version": "1.4.2", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573", + "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573", + "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" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "time": "2016-08-30T16:08:34+00:00" + }, + { + "name": "p3k/picofeed", + "version": "v0.1.38", + "source": { + "type": "git", + "url": "https://github.com/aaronpk/picoFeed.git", + "reference": "989c0bcf2eac016a4104abce1aadff791fc287ab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/aaronpk/picoFeed/zipball/989c0bcf2eac016a4104abce1aadff791fc287ab", + "reference": "989c0bcf2eac016a4104abce1aadff791fc287ab", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-iconv": "*", + "ext-libxml": "*", + "ext-simplexml": "*", + "ext-xml": "*", + "php": ">=5.3.0", + "zendframework/zendxml": "^1.0" + }, + "require-dev": { + "phpdocumentor/reflection-docblock": "2.0.4", + "phpunit/phpunit": "4.8.26", + "symfony/yaml": "2.8.7" + }, + "suggest": { + "ext-curl": "PicoFeed will use cURL if present" + }, + "bin": [ + "picofeed" + ], + "type": "library", + "autoload": { + "psr-0": { + "PicoFeed": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frédéric Guillot" + } + ], + "description": "Modern library to handle RSS/Atom feeds", + "homepage": "https://github.com/miniflux/picoFeed", + "time": "2017-11-30T00:16:58+00:00" + }, + { + "name": "zendframework/zendxml", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/ZendXml.git", + "reference": "eceab37a591c9e140772a1470338258857339e00" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/ZendXml/zipball/eceab37a591c9e140772a1470338258857339e00", + "reference": "eceab37a591c9e140772a1470338258857339e00", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.4", + "zendframework/zend-coding-standard": "~1.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev", + "dev-develop": "1.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "ZendXml\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Utility library for XML usage, best practices, and security in PHP", + "keywords": [ + "ZendFramework", + "security", + "xml", + "zf" + ], + "time": "2019-01-22T19:42:14+00:00" + } + ], + "packages-dev": [ + { + "name": "behat/gherkin", + "version": "v4.6.0", + "source": { + "type": "git", + "url": "https://github.com/Behat/Gherkin.git", + "reference": "ab0a02ea14893860bca00f225f5621d351a3ad07" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/Gherkin/zipball/ab0a02ea14893860bca00f225f5621d351a3ad07", + "reference": "ab0a02ea14893860bca00f225f5621d351a3ad07", + "shasum": "" + }, + "require": { + "php": ">=5.3.1" + }, + "require-dev": { + "phpunit/phpunit": "~4.5|~5", + "symfony/phpunit-bridge": "~2.7|~3|~4", + "symfony/yaml": "~2.3|~3|~4" + }, + "suggest": { + "symfony/yaml": "If you want to parse features, represented in YAML files" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.4-dev" + } + }, + "autoload": { + "psr-0": { + "Behat\\Gherkin": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + } + ], + "description": "Gherkin DSL parser for PHP 5.3", + "homepage": "http://behat.org/", + "keywords": [ + "BDD", + "Behat", + "Cucumber", + "DSL", + "gherkin", + "parser" + ], + "time": "2019-01-16T14:22:17+00:00" + }, + { + "name": "codeception/codeception", + "version": "2.5.3", + "source": { + "type": "git", + "url": "https://github.com/Codeception/Codeception.git", + "reference": "19f0fe845c0af5af2a6c094dc0df3a178a3fd5b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/Codeception/zipball/19f0fe845c0af5af2a6c094dc0df3a178a3fd5b0", + "reference": "19f0fe845c0af5af2a6c094dc0df3a178a3fd5b0", + "shasum": "" + }, + "require": { + "behat/gherkin": "^4.4.0", + "codeception/phpunit-wrapper": "^6.0.9|^7.0.6", + "codeception/stub": "^2.0", + "ext-curl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "facebook/webdriver": ">=1.1.3 <2.0", + "guzzlehttp/guzzle": ">=4.1.4 <7.0", + "guzzlehttp/psr7": "~1.0", + "php": ">=5.6.0 <8.0", + "symfony/browser-kit": ">=2.7 <5.0", + "symfony/console": ">=2.7 <5.0", + "symfony/css-selector": ">=2.7 <5.0", + "symfony/dom-crawler": ">=2.7 <5.0", + "symfony/event-dispatcher": ">=2.7 <5.0", + "symfony/finder": ">=2.7 <5.0", + "symfony/yaml": ">=2.7 <5.0" + }, + "require-dev": { + "codeception/specify": "~0.3", + "facebook/graph-sdk": "~5.3", + "flow/jsonpath": "~0.2", + "monolog/monolog": "~1.8", + "pda/pheanstalk": "~3.0", + "php-amqplib/php-amqplib": "~2.4", + "predis/predis": "^1.0", + "squizlabs/php_codesniffer": "~2.0", + "symfony/process": ">=2.7 <5.0", + "vlucas/phpdotenv": "^3.0" + }, + "suggest": { + "aws/aws-sdk-php": "For using AWS Auth in REST module and Queue module", + "codeception/phpbuiltinserver": "Start and stop PHP built-in web server for your tests", + "codeception/specify": "BDD-style code blocks", + "codeception/verify": "BDD-style assertions", + "flow/jsonpath": "For using JSONPath in REST module", + "league/factory-muffin": "For DataFactory module", + "league/factory-muffin-faker": "For Faker support in DataFactory module", + "phpseclib/phpseclib": "for SFTP option in FTP Module", + "stecman/symfony-console-completion": "For BASH autocompletion", + "symfony/phpunit-bridge": "For phpunit-bridge support" + }, + "bin": [ + "codecept" + ], + "type": "library", + "extra": { + "branch-alias": [] + }, + "autoload": { + "psr-4": { + "Codeception\\": "src/Codeception", + "Codeception\\Extension\\": "ext" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk", + "email": "davert@mail.ua", + "homepage": "http://codegyre.com" + } + ], + "description": "BDD-style testing framework", + "homepage": "http://codeception.com/", + "keywords": [ + "BDD", + "TDD", + "acceptance testing", + "functional testing", + "unit testing" + ], + "time": "2019-02-02T15:39:58+00:00" + }, + { + "name": "codeception/phpunit-wrapper", + "version": "7.6.1", + "source": { + "type": "git", + "url": "https://github.com/Codeception/phpunit-wrapper.git", + "reference": "ed4b12beb167dc2ecea293b4f6df6c20ce8d280f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/phpunit-wrapper/zipball/ed4b12beb167dc2ecea293b4f6df6c20ce8d280f", + "reference": "ed4b12beb167dc2ecea293b4f6df6c20ce8d280f", + "shasum": "" + }, + "require": { + "phpunit/php-code-coverage": "^6.0", + "phpunit/phpunit": ">=7.1 <7.6", + "sebastian/comparator": "^3.0", + "sebastian/diff": "^3.0" + }, + "require-dev": { + "codeception/specify": "*", + "vlucas/phpdotenv": "^2.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Codeception\\PHPUnit\\": "src\\" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Davert", + "email": "davert.php@resend.cc" + } + ], + "description": "PHPUnit classes used by Codeception", + "time": "2019-01-13T10:34:39+00:00" + }, + { + "name": "codeception/stub", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/Codeception/Stub.git", + "reference": "f50bc271f392a2836ff80690ce0c058efe1ae03e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/Stub/zipball/f50bc271f392a2836ff80690ce0c058efe1ae03e", + "reference": "f50bc271f392a2836ff80690ce0c058efe1ae03e", + "shasum": "" + }, + "require": { + "phpunit/phpunit": ">=4.8 <8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Codeception\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Flexible Stub wrapper for PHPUnit's Mock Builder", + "time": "2018-07-26T11:55:37+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "^6.2.3", + "squizlabs/php_codesniffer": "^3.0.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2017-07-22T11:58:36+00:00" + }, + { + "name": "facebook/webdriver", + "version": "1.6.0", + "source": { + "type": "git", + "url": "https://github.com/facebook/php-webdriver.git", + "reference": "bd8c740097eb9f2fc3735250fc1912bc811a954e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/facebook/php-webdriver/zipball/bd8c740097eb9f2fc3735250fc1912bc811a954e", + "reference": "bd8c740097eb9f2fc3735250fc1912bc811a954e", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "ext-zip": "*", + "php": "^5.6 || ~7.0", + "symfony/process": "^2.8 || ^3.1 || ^4.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.0", + "jakub-onderka/php-parallel-lint": "^0.9.2", + "php-coveralls/php-coveralls": "^2.0", + "php-mock/php-mock-phpunit": "^1.1", + "phpunit/phpunit": "^5.7", + "sebastian/environment": "^1.3.4 || ^2.0 || ^3.0", + "squizlabs/php_codesniffer": "^2.6", + "symfony/var-dumper": "^3.3 || ^4.0" + }, + "suggest": { + "ext-SimpleXML": "For Firefox profile creation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-community": "1.5-dev" + } + }, + "autoload": { + "psr-4": { + "Facebook\\WebDriver\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "description": "A PHP client for Selenium WebDriver", + "homepage": "https://github.com/facebook/php-webdriver", + "keywords": [ + "facebook", + "php", + "selenium", + "webdriver" + ], + "time": "2018-05-16T17:37:13+00:00" + }, + { + "name": "fzaninotto/faker", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/fzaninotto/Faker.git", + "reference": "f72816b43e74063c8b10357394b6bba8cb1c10de" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/f72816b43e74063c8b10357394b6bba8cb1c10de", + "reference": "f72816b43e74063c8b10357394b6bba8cb1c10de", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "ext-intl": "*", + "phpunit/phpunit": "^4.8.35 || ^5.7", + "squizlabs/php_codesniffer": "^1.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "Faker\\": "src/Faker/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "François Zaninotto" + } + ], + "description": "Faker is a PHP library that generates fake data for you.", + "keywords": [ + "data", + "faker", + "fixtures" + ], + "time": "2018-07-12T10:23:15+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "6.3.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "shasum": "" + }, + "require": { + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.4", + "php": ">=5.5" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", + "psr/log": "^1.0" + }, + "suggest": { + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.3-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2018-04-22T15:46:56+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "v1.3.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2016-12-20T10:07:11+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.5.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "9f83dded91781a01c63574e387eaa769be769115" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/9f83dded91781a01c63574e387eaa769be769115", + "reference": "9f83dded91781a01c63574e387eaa769be769115", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0", + "ralouphie/getallheaders": "^2.0.5" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "time": "2018-12-04T20:46:45+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.8.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", + "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "replace": { + "myclabs/deep-copy": "self.version" + }, + "require-dev": { + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^7.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "time": "2018-06-11T23:09:50+00:00" + }, + { + "name": "phar-io/manifest", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", + "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "phar-io/version": "^2.0", + "php": "^5.6 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "time": "2018-07-08T19:23:20+00:00" + }, + { + "name": "phar-io/version", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "time": "2018-07-08T19:19:57+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2017-09-11T18:02:19+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "4.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "94fd0001232e47129dd3504189fa1c7225010d08" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", + "reference": "94fd0001232e47129dd3504189fa1c7225010d08", + "shasum": "" + }, + "require": { + "php": "^7.0", + "phpdocumentor/reflection-common": "^1.0.0", + "phpdocumentor/type-resolver": "^0.4.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "doctrine/instantiator": "~1.0.5", + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2017-11-30T07:14:17+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "0.4.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "time": "2017-07-14T14:27:02+00:00" + }, + { + "name": "phpspec/prophecy", + "version": "1.8.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06", + "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", + "sebastian/comparator": "^1.1|^2.0|^3.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.5|^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2018-08-05T17:53:17+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "6.1.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", + "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": "^7.1", + "phpunit/php-file-iterator": "^2.0", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-token-stream": "^3.0", + "sebastian/code-unit-reverse-lookup": "^1.0.1", + "sebastian/environment": "^3.1 || ^4.0", + "sebastian/version": "^2.0.1", + "theseer/tokenizer": "^1.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0" + }, + "suggest": { + "ext-xdebug": "^2.6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2018-10-31T16:06:48+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "050bedf145a257b1ff02746c31894800e5122946" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946", + "reference": "050bedf145a257b1ff02746c31894800e5122946", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2018-09-13T20:33:42+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2015-06-21T13:50:34+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8b8454ea6958c3dee38453d3bd571e023108c91f", + "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2018-02-01T13:07:23+00:00" + }, + { + "name": "phpunit/php-token-stream", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c99e3be9d3e85f60646f152f9002d46ed7770d18", + "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2018-10-30T05:52:18+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "7.5.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "2896657da5fb237bc316bdfc18c2650efeee0dc0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2896657da5fb237bc316bdfc18c2650efeee0dc0", + "reference": "2896657da5fb237bc316bdfc18c2650efeee0dc0", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.1", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "myclabs/deep-copy": "^1.7", + "phar-io/manifest": "^1.0.2", + "phar-io/version": "^2.0", + "php": "^7.1", + "phpspec/prophecy": "^1.7", + "phpunit/php-code-coverage": "^6.0.7", + "phpunit/php-file-iterator": "^2.0.1", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-timer": "^2.0", + "sebastian/comparator": "^3.0", + "sebastian/diff": "^3.0", + "sebastian/environment": "^4.0", + "sebastian/exporter": "^3.1", + "sebastian/global-state": "^2.0", + "sebastian/object-enumerator": "^3.0.3", + "sebastian/resource-operations": "^2.0", + "sebastian/version": "^2.0.1" + }, + "conflict": { + "phpunit/phpunit-mock-objects": "*" + }, + "require-dev": { + "ext-pdo": "*" + }, + "suggest": { + "ext-soap": "*", + "ext-xdebug": "*", + "phpunit/php-invoker": "^2.0" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.5-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2019-02-07T14:15:04+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "2.0.5", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/5601c8a83fbba7ef674a7369456d12f1e0d0eafa", + "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "~3.7.0", + "satooshi/php-coveralls": ">=1.0" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "time": "2016-02-11T07:05:27+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "time": "2017-03-04T06:30:41+00:00" + }, + { + "name": "sebastian/comparator", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "shasum": "" + }, + "require": { + "php": "^7.1", + "sebastian/diff": "^3.0", + "sebastian/exporter": "^3.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2018-07-12T15:12:46+00:00" + }, + { + "name": "sebastian/diff", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29", + "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.5 || ^8.0", + "symfony/process": "^2 || ^3.3 || ^4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "time": "2019-02-04T06:01:07+00:00" + }, + { + "name": "sebastian/environment", + "version": "4.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "6fda8ce1974b62b14935adc02a9ed38252eca656" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6fda8ce1974b62b14935adc02a9ed38252eca656", + "reference": "6fda8ce1974b62b14935adc02a9ed38252eca656", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.5" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2019-02-01T05:27:49+00:00" + }, + { + "name": "sebastian/exporter", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", + "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2017-04-03T13:19:02+00:00" + }, + { + "name": "sebastian/global-state", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2017-04-27T15:39:26+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "time": "2017-08-03T12:35:26+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "773f97c67f28de00d397be301821b06708fca0be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", + "reference": "773f97c67f28de00d397be301821b06708fca0be", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "time": "2017-03-29T09:07:27+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2017-03-03T06:23:57+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9", + "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "time": "2018-10-04T04:07:39+00:00" + }, + { + "name": "sebastian/version", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2016-10-03T07:35:21+00:00" + }, + { + "name": "symfony/browser-kit", + "version": "v4.2.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/browser-kit.git", + "reference": "ee4462581eb54bf34b746e4a5d522a4f21620160" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/ee4462581eb54bf34b746e4a5d522a4f21620160", + "reference": "ee4462581eb54bf34b746e4a5d522a4f21620160", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/dom-crawler": "~3.4|~4.0" + }, + "require-dev": { + "symfony/css-selector": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0" + }, + "suggest": { + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\BrowserKit\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony BrowserKit Component", + "homepage": "https://symfony.com", + "time": "2019-01-16T21:31:25+00:00" + }, + { + "name": "symfony/console", + "version": "v4.2.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "1f0ad51dfde4da8a6070f06adc58b4e37cbb37a4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/1f0ad51dfde4da8a6070f06adc58b4e37cbb37a4", + "reference": "1f0ad51dfde4da8a6070f06adc58b4e37cbb37a4", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/contracts": "^1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/process": "<3.3" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/lock": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2019-01-25T14:35:16+00:00" + }, + { + "name": "symfony/contracts", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/contracts.git", + "reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/contracts/zipball/1aa7ab2429c3d594dd70689604b5cf7421254cdf", + "reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "require-dev": { + "psr/cache": "^1.0", + "psr/container": "^1.0" + }, + "suggest": { + "psr/cache": "When using the Cache contracts", + "psr/container": "When using the Service contracts", + "symfony/cache-contracts-implementation": "", + "symfony/service-contracts-implementation": "", + "symfony/translation-contracts-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\": "" + }, + "exclude-from-classmap": [ + "**/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A set of abstractions extracted out of the Symfony components", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2018-12-05T08:06:11+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v4.2.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "48eddf66950fa57996e1be4a55916d65c10c604a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/48eddf66950fa57996e1be4a55916d65c10c604a", + "reference": "48eddf66950fa57996e1be4a55916d65c10c604a", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony CssSelector Component", + "homepage": "https://symfony.com", + "time": "2019-01-16T20:31:39+00:00" + }, + { + "name": "symfony/dom-crawler", + "version": "v4.2.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "d8476760b04cdf7b499c8718aa437c20a9155103" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/d8476760b04cdf7b499c8718aa437c20a9155103", + "reference": "d8476760b04cdf7b499c8718aa437c20a9155103", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "symfony/css-selector": "~3.4|~4.0" + }, + "suggest": { + "symfony/css-selector": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DomCrawler Component", + "homepage": "https://symfony.com", + "time": "2019-01-16T20:35:37+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v4.2.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "bd09ad265cd50b2b9d09d65ce6aba2d29bc81fe1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/bd09ad265cd50b2b9d09d65ce6aba2d29bc81fe1", + "reference": "bd09ad265cd50b2b9d09d65ce6aba2d29bc81fe1", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/contracts": "^1.0" + }, + "conflict": { + "symfony/dependency-injection": "<3.4" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/stopwatch": "~3.4|~4.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2019-01-16T20:35:37+00:00" + }, + { + "name": "symfony/finder", + "version": "v4.2.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "ef71816cbb264988bb57fe6a73f610888b9aa70c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/ef71816cbb264988bb57fe6a73f610888b9aa70c", + "reference": "ef71816cbb264988bb57fe6a73f610888b9aa70c", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2019-01-16T20:35:37+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.10.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "e3d826245268269cd66f8326bd8bc066687b4a19" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19", + "reference": "e3d826245268269cd66f8326bd8bc066687b4a19", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + }, + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2018-08-06T14:22:27+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.10.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "c79c051f5b3a46be09205c73b80b346e4153e494" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494", + "reference": "c79c051f5b3a46be09205c73b80b346e4153e494", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2018-09-21T13:07:52+00:00" + }, + { + "name": "symfony/process", + "version": "v4.2.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "6c05edb11fbeff9e2b324b4270ecb17911a8b7ad" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/6c05edb11fbeff9e2b324b4270ecb17911a8b7ad", + "reference": "6c05edb11fbeff9e2b324b4270ecb17911a8b7ad", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Process Component", + "homepage": "https://symfony.com", + "time": "2019-01-24T22:05:03+00:00" + }, + { + "name": "symfony/yaml", + "version": "v4.2.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "d461670ee145092b7e2a56c1da7118f19cadadb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/d461670ee145092b7e2a56c1da7118f19cadadb0", + "reference": "d461670ee145092b7e2a56c1da7118f19cadadb0", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/console": "<3.4" + }, + "require-dev": { + "symfony/console": "~3.4|~4.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2019-01-16T20:35:37+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b", + "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "time": "2017-04-07T12:08:54+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9", + "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0", + "symfony/polyfill-ctype": "^1.8" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2018-12-25T11:19:39+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "p3k/picofeed": 0 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=7.1.3", + "ext-json": "*" + }, + "platform-dev": [], + "platform-overrides": { + "php": "7.1.3" + } +} diff --git a/user/plugins/admin/hebe.json b/user/plugins/admin/hebe.json new file mode 100644 index 0000000..b99bbbb --- /dev/null +++ b/user/plugins/admin/hebe.json @@ -0,0 +1,15 @@ +{ + "project":"grav-plugin-admin", + "platforms":{ + "grav":{ + "nodes":{ + "plugin":[ + { + "source":"/", + "destination":"/user/plugins/admin" + } + ] + } + } + } +} diff --git a/user/plugins/admin/languages/ar.yaml b/user/plugins/admin/languages/ar.yaml new file mode 100644 index 0000000..cbb42ed --- /dev/null +++ b/user/plugins/admin/languages/ar.yaml @@ -0,0 +1,308 @@ +--- +PLUGIN_ADMIN: + ADMIN_BETA_MSG: "هذا إصدار بيتا! استخدم هذا في الإنتاج على مسؤوليتك الخاصة..." + ADMIN_REPORT_ISSUE: "وجدت مشكلة؟ الرجاء الإبلاغ عن GitHub." + EMAIL_FOOTER: "Powered by Grav - The Modern Flat File CMS" + LOGIN_BTN: "تسجل الدخول" + LOGIN_BTN_FORGOT: "نسيت" + LOGIN_BTN_RESET: "إعادة تعيين كلمة المرور" + LOGIN_BTN_SEND_INSTRUCTIONS: "إرسال إرشادات إعادة تعيين" + LOGIN_BTN_CLEAR: "مسح النموذج" + LOGIN_BTN_CREATE_USER: "أنشاء مستخدم جديد" + LOGIN_LOGGED_IN: "لقد تم تسجيل بنجاح" + LOGIN_FAILED: "فشل تسجيل الخول" + LOGGED_OUT: "لقد قمت بتسجيل الخروج" + RESET_NEW_PASSWORD: "إدخال كلمة سر جديدة رجاءً …" + RESET_LINK_EXPIRED: "انتهت مدة صلاحية إعادة الارتباط، الرجاء المحاولة مرة أخرى" + RESET_PASSWORD_RESET: "لقد تم إعادة تعيين كلمة المرور" + RESET_INVALID_LINK: "اللينك خاطئ ، الرجاء المحاولة مرة أخرى" + FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL: "تم إرسال إرشادات إعادة تعيين كلمة المرور الخاصة بك عبر البريد الإلكتروني إلى %s" + FORGOT_FAILED_TO_EMAIL: "فشل في تعليمات البريد الإلكتروني، الرجاء المحاولة مرة أخرى لاحقاً" + FORGOT_CANNOT_RESET_EMAIL_NO_EMAIL: "لا يمكن إعادة تعيين كلمة المرور ل %s، لم يتم تعيين عنوان البريد الإلكتروني" + FORGOT_USERNAME_DOES_NOT_EXIST: "لا يوجد المستخدم مع اسم المستخدم %s" + FORGOT_EMAIL_NOT_CONFIGURED: "لا يمكن إعادة تعيين كلمة المرور. لم يتم تكوين هذا الموقع لإرسال رسائل البريد الإلكتروني" + FORGOT_EMAIL_SUBJECT: "طلب إعادة تعيين كلمة المرور %s" + FORGOT_EMAIL_BODY: "

\"إعادة تعيين كلمة المرور\"

عزيزي %1$s،

طلبا قدم في %4$s لإعادة تعيين كلمة المرور الخاصة بك.


انقر فوق هذا الخيار لإعادة تعيين الخاص بك كلمة مرور

بدلاً من ذلك، نسخ عنوان URL التالي في شريط العناوين في المستعرض الخاص بك:

%2$s


أطيب التحيات،

%3$s

" + MANAGE_PAGES: "إدارة الصفحات" + CONFIGURATION: "الإعدادات" + PAGES: "الصفحات" + PLUGINS: "الملحقات" + PLUGIN: "البرنامج الإضافي" + THEMES: "المواضيع" + LOGOUT: "تسجيل الخروج" + BACK: "الرجوع" + NEXT: "التالي" + PREVIOUS: "السابق" + ADD_PAGE: "إضافة صفحة" + ADD_MODULAR: "إضافة وحدة" + MOVE: "انقل" + DELETE: "حذف" + UNSET: "تراجع عن التعيين" + VIEW: "عرض" + SAVE: "حفظ" + NORMAL: "عادي" + EXPERT: "خبير" + EXPAND_ALL: "عرض الكل" + COLLAPSE_ALL: "طي الكل" + ERROR: "خطأ" + CLOSE: "أغلق" + CANCEL: "إلغاء" + CONTINUE: "المتابعة" + MODAL_DELETE_PAGE_CONFIRMATION_REQUIRED_TITLE: "التأكيد مطلوب" + MODAL_CHANGED_DETECTED_TITLE: "تم الكشف عن التغييرات" + MODAL_CHANGED_DETECTED_DESC: "وقد تغييرات غير محفوظة. هل أنت متأكد من أنك تريد ترك دون الحفظ؟" + MODAL_DELETE_FILE_CONFIRMATION_REQUIRED_TITLE: "التأكيد مطلوب" + MODAL_DELETE_FILE_CONFIRMATION_REQUIRED_DESC: "هل أنت متأكد من حذف هذا الملف؟ لا يمكن التراجع عن هذا الإجراء." + ADD_FILTERS: "إضافة عامل تصفية" + SEARCH_PAGES: "صفحات البحث" + VERSION: "النسخة" + WAS_MADE_WITH: "تم عمله مع" + BY: "بواسطة" + UPDATE_THEME: "تحديث الموضوع" + UPDATE_PLUGIN: "تحديث البرنامج الإضافي" + OF_THIS_THEME_IS_NOW_AVAILABLE: "من هذه السمة الآن متوفرة" + OF_THIS_PLUGIN_IS_NOW_AVAILABLE: "من هذه الإضافة متوفرة الآن" + AUTHOR: "المؤلّف" + HOMEPAGE: "الصفحة الرئيسية" + DEMO: "عرض تجريبي" + BUG_TRACKER: "متتبع الأخطاء" + KEYWORDS: "الكلمات الرئيسية" + LICENSE: "الرخصة" + DESCRIPTION: "الوصف" + README: "الملف التمهيدي" + REMOVE_THEME: "إزالة الموضوع" + INSTALL_THEME: "تثبيت الموضوع" + THEME: "الموضوع" + BACK_TO_THEMES: "العودة إلى المواضيع" + BACK_TO_PLUGINS: "العودة إلى البرامج الإضافية" + CHECK_FOR_UPDATES: "التحقق من وجود تحديثات" + ADD: "أَضِف" + CLEAR_CACHE: "مسح ذاكرة التخزين المؤقتة" + CLEAR_CACHE_ALL_CACHE: "كافة المحفوظات" + CLEAR_CACHE_ASSETS_ONLY: "الاصول فقط" + CLEAR_CACHE_IMAGES_ONLY: "الصور فقط" + CLEAR_CACHE_CACHE_ONLY: "المحفوظات فقط" + CLEAR_CACHE_TMP_ONLY: "المؤقتة فقط" + DASHBOARD: "لوحة المعلومات" + UPDATES_AVAILABLE: "تحديثات متوفّرة" + DAYS: "أيام" + UPDATE: "تحديث" + BACKUP: "نسخة احتياطية" + BACKUPS: "النسخ الاحتياطية" + BACKUP_NOW: "قم بحفض نسخة احتياطية" + BACKUPS_STATS: "قم بحفض نسخة احتياطية لاحصائيات" + BACKUPS_HISTORY: "قم بحفض نسخة احتياطية للسجل" + BACKUPS_PROFILES: "قم بحفض نسخة احتياطي للحسابات" + BACKUPS_COUNT: "عدد النسخ الاحتياطية" + BACKUPS_PROFILES_COUNT: "عدد الحسابات" + BACKUPS_TOTAL_SIZE: "المساحة المستعملة" + BACKUPS_NEWEST: "النسخ الاحتياطية الحديثة" + BACKUPS_OLDEST: "النسخ الاحتياطية القديمة" + BACKUPS_PURGE: "تطهير" + BACKUPS_NOT_GENERATED: "لم يتم إنشاء نسخ احتياطية بعد..." + BACKUPS_PURGE_NUMBER: "استخدام %s من %s من فتحات النسخ الاحتياطي" + BACKUPS_PURGE_TIME: "%s ايام من النسخ الاحتياطية بقية" + BACKUPS_PURGE_SPACE: "استعمال %s من %s" + BACKUP_DELETED: "تم حذف النسخة الاحتياطية بنجاح" + BACKUP_NOT_FOUND: "لم يتم العثور على نسخة احتياطية" + BACKUP_DATE: "تاريخ النسخ الاحتياطي" + STATISTICS: "إحصائيات" + TODAY: "اليوم" + WEEK: "اسبوع" + MONTH: "شهر" + LATEST_PAGE_UPDATES: "آخر التحديثات" + MAINTENANCE: "الصيانه" + UPDATED: "تم تحديثه" + MON: "الإثنين" + TUE: "الثلاثاء" + WED: "الإربعاء" + THU: "الخميس" + FRI: "الجمعة" + SAT: "السبت" + SUN: "الأحد" + COPY: "نسخ" + EDIT: "تحرير" + CREATE: "انشاء" + GRAV_ADMIN: "مدير جريف" + GRAV_OFFICIAL_PLUGIN: "اضاف رسمية ل جريف" + GRAV_OFFICIAL_THEME: "سمة جريف رسمية" + PLUGIN_SYMBOLICALLY_LINKED: "هذه الاضافه مرتبطة بمرجع. لن يام اكتشاف التحديثات." + THEME_SYMBOLICALLY_LINKED: "هذه السمة مرتبطة بمرجع. لم يتم اكتشاف التحديثات" + REMOVE_PLUGIN: "حذف الإضافة" + INSTALL_PLUGIN: "تثبيت الإضافة" + AVAILABLE: "متوفر" + INSTALLED: "مثبت" + INSTALL: "تثبيت" + ACTIVE_THEME: "سمة نشطة" + SWITCHING_TO: "التبديل إلى" + SWITCHING_TO_DESCRIPTION: "بالتبديل إلى سمة مختلفة, لايوجد أي ضمانات بأن صفحات الواجهة مدعومة, من المحتمل أن تحدث أخطاء عند محاولة تحميل الصفحات المذكورة." + SWITCHING_TO_CONFIRMATION: "هل تريد التبديل الى السمة والمتابعة" + CREATE_NEW_USER: "إنشاء مستخدم جديد" + REMOVE_USER: "حذف المستخدم" + ACCESS_DENIED: "الدخول ممنوع" + ACCOUNT_NOT_ADMIN: "لا يملك حسابك أي صلاحيات للإدارة" + PHP_INFO: "معلومات بي إش بي" + INSTALLER: "المثبت" + AVAILABLE_THEMES: "سمات متوفرة" + AVAILABLE_PLUGINS: "إضافات متوفرة" + INSTALLED_THEMES: "السمات المثبتة" + INSTALLED_PLUGINS: "الإضافات المثبتة" + BROWSE_ERROR_LOGS: "سجل أخطاء التصفح" + SITE: "موقع" + INFO: "معلومات" + SYSTEM: "النظام" + USER: "المستخدم" + ADD_ACCOUNT: "إضافة حساب" + SWITCH_LANGUAGE: "تبديل اللغة" + SUCCESSFULLY_ENABLED_PLUGIN: "تم تفعيل الإضافة بنجاح" + SUCCESSFULLY_DISABLED_PLUGIN: "تم إيقاف الإضافة بنجاح" + SUCCESSFULLY_CHANGED_THEME: "تم تبديل السمة الإفتراضية بنجاح" + INSTALLATION_FAILED: "فشل التثبيت" + INSTALLATION_SUCCESSFUL: "تم التثبيت بنجاح" + UNINSTALL_FAILED: "فشل الغاء التثبيت" + UNINSTALL_SUCCESSFUL: "تم إلغاء التثبيت بنجاح" + SUCCESSFULLY_SAVED: "حفظ بنجاح" + SUCCESSFULLY_COPIED: "نسخ بنجاح" + REORDERING_WAS_SUCCESSFUL: "إعادة ترتيب تم بنجاح" + SUCCESSFULLY_DELETED: "تم الحذف بنجاح" + SUCCESSFULLY_SWITCHED_LANGUAGE: "تم تغيير اللغة بنجاح" + INSUFFICIENT_PERMISSIONS_FOR_TASK: "لديك أذونات غير كافية للقيام بالمهمة" + CACHE_CLEARED: "تم مسح الذاكرة المؤقتة" + METHOD: "الأسلوب" + ERROR_CLEARING_CACHE: "خطأ مسح ذاكرة التخزين المؤقت" + AN_ERROR_OCCURRED: "حدث خطأ ما" + YOUR_BACKUP_IS_READY_FOR_DOWNLOAD: "النسخة الاحتياطية جاهزة للتحميل" + DOWNLOAD_BACKUP: "تنزيل النسخة الاحتياطية" + PAGES_FILTERED: "الصفحات التي تمت تصفيتها" + NO_PAGE_FOUND: "لم يتم العثور على أي صفحة" + INVALID_PARAMETERS: "متغيرات غير صالحة" + NO_FILES_SENT: "لا توجد ملفات أرسلت حتى الآن" + EXCEEDED_FILESIZE_LIMIT: "تجاوز الحد الأقصى لحجم ملف التكوين بي إتش بي" + UNKNOWN_ERRORS: "خطأ غير معروف" + EXCEEDED_GRAV_FILESIZE_LIMIT: "تجاوز الحد الأقصى لحجم ملف التكوين بي إتش بي" + UNSUPPORTED_FILE_TYPE: "نوع ملف غير معتمد" + FAILED_TO_MOVE_UPLOADED_FILE: "فشل في تحميل الملف" + FILE_UPLOADED_SUCCESSFULLY: "تم رفع الملف بنجاح" + FILE_DELETED: "تم حذف الملف" + FILE_COULD_NOT_BE_DELETED: "لا يمكن حذف الملف" + FILE_NOT_FOUND: "لم يتم العثور على الملف" + NO_FILE_FOUND: "لا يوجد ملف" + GRAV_WAS_SUCCESSFULLY_UPDATED_TO: "تم تحديث النظام بنجاح الى" + GRAV_UPDATE_FAILED: "فشل تحديث نظام جراف" + EVERYTHING_UPDATED: "تم تحديث كل شيء" + UPDATES_FAILED: "فشل التحديث" + AVATAR_BY: "الصورة الرمزية التي" + AVATAR_UPLOAD_OWN: "أو قم بتحميل الخاصة بك..." + LAST_BACKUP: "آخر نسخ احتياطي" + FULL_NAME: "الإسم الكامل" + USERNAME: "إسم المستخدم" + EMAIL: "البريد الإلكتروني" + USERNAME_EMAIL: "إسم المستخدم أو البريد الإلكتروني" + PASSWORD: "كلمة السر" + PASSWORD_CONFIRM: "تأكيد كلمة السر" + TITLE: "العنوان" + LANGUAGE: "اللّغة" + ACCOUNT: "الحساب" + EMAIL_VALIDATION_MESSAGE: "يجب أن يكون البريد الإلكتروني صحيحاً" + PASSWORD_VALIDATION_MESSAGE: "يجب أن تحتوي كلمة المرور على الأقل على رقم وعلى حرف كبير وعلى حرف صغير، و أن تكون مكونة على الأقل من 8 أحرف أو أكثر" + LANGUAGE_HELP: "تعيين اللغة المفضلة" + MEDIA: "وسائط" + DEFAULTS: "الإعدادات الافتراضية" + SITE_TITLE: "عنوان الموقع" + SITE_TITLE_PLACEHOLDER: "عنوان الموقع العريض" + SITE_TITLE_HELP: "العنوان الإفتراضي لموقعك, غالبا يستخدم في السمات" + SITE_DEFAULT_LANG: "اللغة الإفتراضية" + SITE_DEFAULT_LANG_PLACEHOLDER: "اللغة الإفتراضية المستخدمة في السمات وسم " + SITE_DEFAULT_LANG_HELP: "اللغة الإفتراضية المستخدمة في السمات وسم " + DEFAULT_AUTHOR: "المؤلف الافتراضي" + DEFAULT_AUTHOR_HELP: "إسم المؤلف الإفتراضي, يستخدم عادة في السمات او محتوى الصفحة" + DEFAULT_EMAIL: "البريد الإلكتروني الإفتراضي" + DEFAULT_EMAIL_HELP: "البريد الإلكتروني للإشارة في المواضيع أو صفحات" + TAXONOMY_TYPES: "أنواع التصنيف" + TAXONOMY_TYPES_HELP: "يجب أن يتم تعريف أنواع التصنيف هنا إذا كنت ترغب في استخدامها في صفحات" + PAGE_SUMMARY: "ملخص الصفحة" + ENABLED: "فعال" + ENABLED_HELP: "تمكين صفحة الموجز (الملخص ترجع نفس محتوى الصفحة)" + 'YES': "نعم" + 'NO': "لا" + SUMMARY_SIZE: "حجم الملخص" + SUMMARY_SIZE_HELP: "مقدار أحرف صفحة لاستخدامها كمحتوى موجز" + FORMAT: "الشكل" + FORMAT_HELP: "اختصار = الاستخدام الأولى لوقوع محدد أو الحجم؛ = فترة طويلة سيتم تجاهل موجز محدد" + SHORT: "قصير" + LONG: "طويل" + DELIMITER: "الفاصل" + DELIMITER_HELP: "موجز محدد (الافتراضي '= = =')" + METADATA: "البيانات الوصفية" + METADATA_HELP: "قيم بيانات التعريف الافتراضية التي سيتم عرضها في كل صفحة ما لم يتم تجاوز الصفحة" + NAME: "الإسم" + CONTENT: "المحتوى" + SIZE: "حجم" + ACTION: "اجراء" + REDIRECTS_AND_ROUTES: "اعادة التوجيه و المسارات" + CUSTOM_REDIRECTS: "تخصيص اعادة التوجيه" + CUSTOM_REDIRECTS_HELP: "مسارات لإعادة التوجيه إلى صفحات أخرى. الاستبدال الاساسي ل Regex صحيح" + CUSTOM_REDIRECTS_PLACEHOLDER_KEY: "/ الخاص / الاسم المستعار" + CUSTOM_REDIRECTS_PLACEHOLDER_VALUE: "/ الخاص /إعادة التوجيه" + CUSTOM_ROUTES: "تخصيص المسارات" + CUSTOM_ROUTES_HELP: "مسارات لاسماء المستعارة إلى صفحات أخرى. الاستبدال الاساسي ل Regex صحيح" + CUSTOM_ROUTES_PLACEHOLDER_KEY: "/ الخاص / الاسم المستعار" + CUSTOM_ROUTES_PLACEHOLDER_VALUE: "/ الخاص / المسار" + FILE_STREAMS: "تيارات الملف" + DEFAULT: "الإعدادات العامة" + PAGE_MEDIA: "صور و فيديوهات الصفحة" + OPTIONS: "الخيارات" + PUBLISHED: "نُشِرَ" + PUBLISHED_HELP: "بشكل افتراضي، يتم نشر صفحة إلا إذا قمت بتعيين المنشور: false أو عن طريق publish_date يجري في المستقبل، أو unpublish_date في الماضي" + DATE: "التاريخ" + ROBOTS: "الروبوتات" + ADVANCED: "خيارات متقدمة" + SETTINGS: "الإعدادات" + FOLDER_NAME: "إسم المجلد" + MENU: "القائمة" + USE_GLOBAL: "الاستخدام العام" + ROUTABLE: "قابل للتوجيه" + ROUTABLE_HELP: "إذا أمكن ولوج هذه الصفحة عبر عنوان URL" + VISIBLE: "مرئي" + ASCENDING: "تصاعدي" + DESCENDING: "تنازلي" + PAGE_TITLE: "موضوع عنوان الصفحة" + PAGE_TITLE_HELP: "عنوان الصفحة" + PAGE: "صفحة" + MODULAR_TEMPLATE: "قالب متعدد الفقرات" + FILENAME: "اسم الملف" + PARENT_PAGE: "الصفحة الأصل" + HOME_PAGE: "الصفحة الرئيسية" + TIMEZONE: "المنطقة الزمنية" + LANGUAGES: "اللغات" + EXPIRES: "انتهاء الصلاحية" + LAST_MODIFIED: "آخر تعديل" + SESSION: "الجلسة" + CURRENT: "الحالي" + SAVE_AS: "حفظ كـ" + AND: "و" + FULLY_UPDATED: "تم تحديث النظام بالكامل" + GROUPS: "الفِرَق" + SESSION_SECURE: "آمن" + ADD_FOLDER: "إضافة مجلد" + ADD_ITEM: "إضافة عنصر" + LOADING: "جار التحميل …" + PACKAGES_SUCCESSFULLY_UPDATED: "تم تحديث حزمة أو حزمات بنجاح." + INSERT: "إدراج" + UNDO: "تراجع" + REDO: "إعادة" + HEADERS: "العناوين الرأسية" + ITALIC: "مائل" + LINK: "رابط" + IMAGE: "صورة" + PREVIEW: "معاينة" + PUBLISHING: "النشر" + IMAGE_OPTIONS: "خيارات الصورة" + ALL: "الكل" + FROM: "من" + TO: "إلى" + RELEASE_DATE: "تاريخ الإصدار" + DROPZONE_REMOVE_FILE: "إزالة الملف" + TOOLS: "الأدوات" + 2FA_CODE_INPUT: "000000" + 2FA_REGENERATE: "إعادة التوليد" diff --git a/user/plugins/admin/languages/bg.yaml b/user/plugins/admin/languages/bg.yaml new file mode 100644 index 0000000..35da781 --- /dev/null +++ b/user/plugins/admin/languages/bg.yaml @@ -0,0 +1,361 @@ +--- +PLUGIN_ADMIN: + ADMIN_BETA_MSG: "Това е Бета версия! Използвате на ваша отговорност..." + ADMIN_REPORT_ISSUE: "Открили сте проблем? Моля, съобщете за него в GitHub." + EMAIL_FOOTER: "Задвижван от Grav - Модерният Флат Файл CMS" + LOGIN_BTN: "Вход" + LOGIN_BTN_FORGOT: "Забравена парола" + LOGIN_BTN_RESET: "Промяна на паролата" + LOGIN_BTN_SEND_INSTRUCTIONS: "Изпращане на инструкциите за възстановяването" + LOGIN_BTN_CLEAR: "Изтриване на формуляра" + LOGIN_BTN_CREATE_USER: "Създаване на потребител" + LOGIN_LOGGED_IN: "Влязохте успешно" + LOGIN_FAILED: "Влизането не е успешно" + LOGGED_OUT: "Излязохте от системата" + RESET_NEW_PASSWORD: "Въведете нова парола …" + RESET_LINK_EXPIRED: "Връзката за нулиране е изтекла, опитайте отново" + RESET_PASSWORD_RESET: "Паролата е променена" + RESET_INVALID_LINK: "Използвана невалидна връзка за нулиране, моля опитайте отново" + FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL: "На Вашия имейл, бяха изпратени инструкции за възстановяване на паролата" + FORGOT_FAILED_TO_EMAIL: "Неуспешно изпращане на имейл с инструкции, опитайте по-късно" + FORGOT_CANNOT_RESET_EMAIL_NO_EMAIL: "Паролата на %s не може да бъде обновена, няма въведен имейл адрес" + FORGOT_USERNAME_DOES_NOT_EXIST: "Потребител с име %s не съществува" + FORGOT_EMAIL_NOT_CONFIGURED: "Не може да обнови паролата. Този сайт не е конфигуриран да изпраща имейли" + FORGOT_EMAIL_SUBJECT: "%s - искане за смяна на парола" + FORGOT_EMAIL_BODY: "

Смяна на парола

Уважаеми %1$s

На %4$s бе направено искане за смяна на парола.


Натиснете тук за да обновите паролата си

Като алтернатива, можете да копирате линка в адресната лента на браузъра си:

%2$s


С уважение,

%3$s

" + MANAGE_PAGES: "Управление на страниците" + CONFIGURATION: "Настройки" + PAGES: "Страници" + PLUGINS: "Разширения" + PLUGIN: "Разширение" + THEMES: "Теми" + LOGOUT: "Изход" + BACK: "Назад" + NEXT: "Напред" + PREVIOUS: "Назад" + ADD_PAGE: "Добавяне на страница" + ADD_MODULAR: "Добавяне на модулна страница" + MOVE: "Преместване" + DELETE: "Изтриване" + UNSET: "Незададен" + VIEW: "Виж" + SAVE: "Запазване" + NORMAL: "Обикновен" + EXPERT: "Експертен" + EXPAND_ALL: "Разгъване на всички" + COLLAPSE_ALL: "Свиване на всички" + ERROR: "Грешка" + CLOSE: "Затваряне" + CANCEL: "Отказ" + CONTINUE: "Продължаване" + MODAL_DELETE_PAGE_CONFIRMATION_REQUIRED_TITLE: "Изисква се потвърждение" + MODAL_CHANGED_DETECTED_TITLE: "Засечени са промени" + MODAL_CHANGED_DETECTED_DESC: "Имате незапазени промени. Наистина ли искате да излезете без да сте ги запазили?" + MODAL_DELETE_FILE_CONFIRMATION_REQUIRED_TITLE: "Изисква се потвърждение" + MODAL_DELETE_FILE_CONFIRMATION_REQUIRED_DESC: "Наистина ли искате да изтриете този файл? Това действие не може да бъде отменено." + ADD_FILTERS: "Добавяне на филтри" + SEARCH_PAGES: "Търсене" + VERSION: "Версия" + WAS_MADE_WITH: "е създаден с" + BY: "от" + UPDATE_THEME: "Актуализация на тема" + UPDATE_PLUGIN: "Актуализация на разширение" + OF_THIS_THEME_IS_NOW_AVAILABLE: "на тази тема е наличен" + OF_THIS_PLUGIN_IS_NOW_AVAILABLE: "на този плъгин е вече наличен" + AUTHOR: "Автор" + HOMEPAGE: "Страница" + DEMO: "Демо" + BUG_TRACKER: "Докладване за грешки" + KEYWORDS: "Ключови думи" + LICENSE: "Лиценз" + DESCRIPTION: "Описание" + README: "Документация" + REMOVE_THEME: "Премахване на тема" + INSTALL_THEME: "Инсталиране на тема" + THEME: "Тема" + BACK_TO_THEMES: "Обратно към темите" + BACK_TO_PLUGINS: "Обратно към разширенията" + CHECK_FOR_UPDATES: "Проверка за актуализации" + ADD: "Добавяне" + CLEAR_CACHE: "Изтриване на временните файлове" + CLEAR_CACHE_ALL_CACHE: "Всички" + CLEAR_CACHE_ASSETS_ONLY: "Само Assets" + CLEAR_CACHE_IMAGES_ONLY: "Само изображенията" + CLEAR_CACHE_CACHE_ONLY: "Само временните файлове" + CLEAR_CACHE_TMP_ONLY: "само временен" + DASHBOARD: "Контролен панел" + UPDATES_AVAILABLE: "Налични актуализации" + DAYS: "Дни" + UPDATE: "Актуализация" + BACKUP: "Резервно копие" + BACKUPS: "Резервно копие" + BACKUP_NOW: "Създай резервно копие" + BACKUPS_STATS: "Статистика резервни копия" + BACKUPS_HISTORY: "История резервни копия" + BACKUPS_PURGE_CONFIG: "Настройка изтриване на резервно копие" + BACKUPS_PROFILES: "Профили на резервни копия" + BACKUPS_COUNT: "Брой резервни копия" + BACKUPS_PROFILES_COUNT: "Брой профили" + BACKUPS_TOTAL_SIZE: "Използвано пространство" + BACKUPS_NEWEST: "Най-ново резервно копие" + BACKUPS_OLDEST: "Най-старо резервно копие" + BACKUPS_PURGE: "Изтриване" + BACKUPS_NOT_GENERATED: "Все още не са генериране резервни копия..." + BACKUPS_PURGE_NUMBER: "Използва %s от %s слота за резервни копия" + BACKUPS_PURGE_TIME: "Остават %s дни за резервно копие" + BACKUPS_PURGE_SPACE: "Използва %s от %s" + BACKUP_DELETED: "Успешно изтрито резервно копие" + BACKUP_NOT_FOUND: "Не е намерено резервно копие" + BACKUP_DATE: "Данни за резервно копие" + STATISTICS: "Статистика" + TODAY: "Днес" + WEEK: "Седмица" + MONTH: "Месец" + LATEST_PAGE_UPDATES: "Скоро актуализирани страници" + MAINTENANCE: "Техническа поддръжка" + UPDATED: "Актуализиран" + MON: "пон" + TUE: "вт" + WED: "ср" + THU: "чт" + FRI: "пт" + SAT: "сб" + SUN: "нд" + COPY: "Копиране" + EDIT: "Редактиране" + CREATE: "Създаване" + GRAV_ADMIN: "Grav Admin" + GRAV_OFFICIAL_PLUGIN: "Официално разширение на Grav" + GRAV_OFFICIAL_THEME: "Официална тема на Grav" + PLUGIN_SYMBOLICALLY_LINKED: "Този плъгин е символично свързан. Актуализации няма да бъдат отразени." + THEME_SYMBOLICALLY_LINKED: "Тази тема е символично свързана. Актуализации няма да бъдат отразени." + REMOVE_PLUGIN: "Премахване на разширение" + INSTALL_PLUGIN: "Инсталиране на разширение" + AVAILABLE: "Налични" + INSTALLED: "Инсталирани" + INSTALL: "Инсталиране" + ACTIVE_THEME: "Активна тема" + SWITCHING_TO: "Превключване към" + SWITCHING_TO_DESCRIPTION: "При превключването към различна тема няма гаранция, че всички страници са поддържани, което може да доведе до потенциални грешки при опит за зареждане на тези страници." + SWITCHING_TO_CONFIRMATION: "Искате ли да продължите и да превключите към темата" + CREATE_NEW_USER: "Създаване на нов потребител" + REMOVE_USER: "Премахване на потребител" + ACCESS_DENIED: "Нямате достъп" + ACCOUNT_NOT_ADMIN: "вашият профил няма администраторски права" + PHP_INFO: "Информация за PHP" + INSTALLER: "Инсталатор" + AVAILABLE_THEMES: "Налични теми" + AVAILABLE_PLUGINS: "Налични разширения" + INSTALLED_THEMES: "Инсталирани теми" + INSTALLED_PLUGINS: "Инсталирани разширения" + BROWSE_ERROR_LOGS: "Преглед на дневниците за грешки" + SITE: "Сайт" + INFO: "Информация" + SYSTEM: "Система" + USER: "Потребител" + ADD_ACCOUNT: "Добавяне на профил" + SWITCH_LANGUAGE: "Превключване на езика" + SUCCESSFULLY_ENABLED_PLUGIN: "Разширението е активирано успешно" + SUCCESSFULLY_DISABLED_PLUGIN: "Разширението е спряно" + SUCCESSFULLY_CHANGED_THEME: "Промяната на подразбиращата се тема е успешно" + INSTALLATION_FAILED: "Неуспешна инсталация" + INSTALLATION_SUCCESSFUL: "Инсталацията е успешна" + UNINSTALL_FAILED: "Неуспешно деинсталиране" + UNINSTALL_SUCCESSFUL: "Деинсталирането е успешно" + SUCCESSFULLY_SAVED: "Успешно запазено" + SUCCESSFULLY_COPIED: "Успешно копирано" + REORDERING_WAS_SUCCESSFUL: "Записът бе успешен" + SUCCESSFULLY_DELETED: "Успешно изтрити" + SUCCESSFULLY_SWITCHED_LANGUAGE: "Езикът е променен успешно" + INSUFFICIENT_PERMISSIONS_FOR_TASK: "Нямате достатъчно права за тази задача" + CACHE_CLEARED: "Временните файлове са изчистени" + METHOD: "Метод" + ERROR_CLEARING_CACHE: "Грешка при изтриването на временните файлове" + AN_ERROR_OCCURRED: "Възникна грешка" + YOUR_BACKUP_IS_READY_FOR_DOWNLOAD: "Резервното копие е готово за изтегляне" + DOWNLOAD_BACKUP: "Изтегляне на резервното копие" + PAGES_FILTERED: "Филтрирани страници" + NO_PAGE_FOUND: "Няма намерени страници" + INVALID_PARAMETERS: "Невалидни параметри" + NO_FILES_SENT: "Няма изпратени файлове" + EXCEEDED_FILESIZE_LIMIT: "Надхвърлен лимит за размер на PHP конфигурационен файл" + UNKNOWN_ERRORS: "Неизвестни грешки" + EXCEEDED_GRAV_FILESIZE_LIMIT: "Превишен лимит за размера на конфигурационен GRAV файл" + UNSUPPORTED_FILE_TYPE: "Този файлов формат не се поддържа" + FAILED_TO_MOVE_UPLOADED_FILE: "Преместването на качения файл не е успешно." + FILE_UPLOADED_SUCCESSFULLY: "Файлът е качен успешно" + FILE_DELETED: "Файлът е изтрит" + FILE_COULD_NOT_BE_DELETED: "Файлът не може да бъде изтрит" + FILE_NOT_FOUND: "Файлът не е намерен" + NO_FILE_FOUND: "Няма намерени файлове" + GRAV_WAS_SUCCESSFULLY_UPDATED_TO: "Grav беше успешно актуализиран до" + GRAV_UPDATE_FAILED: "Актуализацията на Grav е неуспешна" + EVERYTHING_UPDATED: "Всичко е актуализирано" + UPDATES_FAILED: "Актуализациите не бяха успшено" + AVATAR_BY: "Аватар от" + AVATAR_UPLOAD_OWN: "Или качи собствени..." + LAST_BACKUP: "Последно резервно копие" + FULL_NAME: "Пълно име" + USERNAME: "Потребителско име" + EMAIL: "Ел. поща" + USERNAME_EMAIL: "Потребителско име или инейл" + PASSWORD: "Парола" + PASSWORD_CONFIRM: "Потвърждение на паролата" + TITLE: "Титла" + LANGUAGE: "Език" + ACCOUNT: "Профил" + EMAIL_VALIDATION_MESSAGE: "Ел. поща трябва да бъде валидна" + PASSWORD_VALIDATION_MESSAGE: "Паролата трябва да съдържа поне един номер, една главна буква, една малка буква и да съдържа поне 8 или повече знака" + LANGUAGE_HELP: "Задаване на любим език" + MEDIA: "Медиа" + DEFAULTS: "По подразбиране" + SITE_TITLE: "Заглавие на сайта" + SITE_TITLE_PLACEHOLDER: "Заглавие за всички страници" + SITE_TITLE_HELP: "Подразбиращо се заглавие за вашият сайт, често се използва от темите" + SITE_DEFAULT_LANG: "Език по подразбиране" + SITE_DEFAULT_LANG_PLACEHOLDER: "Език по подразбиране, използван от тага на темите" + SITE_DEFAULT_LANG_HELP: "Език по подразбиране, използван от тага на темите" + DEFAULT_AUTHOR: "Подразбиращ се автор" + DEFAULT_AUTHOR_HELP: "Име на автор по подразбиране, често използвано в теми или страници" + DEFAULT_EMAIL: "Имейл по подразбиране" + DEFAULT_EMAIL_HELP: "Имейл по подразбиране, използван в теми или страници" + TAXONOMY_TYPES: "Видове таксономии" + TAXONOMY_TYPES_HELP: "Типовете таксономия трябва да бъдат дефинирани тук, ако искате да ги използвате в страници" + PAGE_SUMMARY: "Резюме на страницата" + ENABLED: "Включен" + ENABLED_HELP: "Разреши извлечение (извлечението връща същото съдържание, като в страницата)" + 'YES': "Да" + 'NO': "Не" + SUMMARY_SIZE: "Размер на резюмето" + SUMMARY_SIZE_HELP: "Брой знаци, които да бъдат използвани при създаването на резюме за страницата" + FORMAT: "Формат" + SHORT: "Къс" + LONG: "Дълъг" + DELIMITER: "Делител" + DELIMITER_HELP: "Разделител на извлечението (по подразбиране '===')" + METADATA: "Мета-данни" + METADATA_HELP: "Ще бъдат показани метадата стойностите по подразбиране на всяка страница, освен ако не са отхвърлени от страницата" + NAME: "Име" + CONTENT: "Съдържание" + SIZE: "Размер" + ACTION: "Действие" + REDIRECTS_AND_ROUTES: "Пренасочвания и пътища" + CUSTOM_REDIRECTS: "Потребителски пренасочвания" + CUSTOM_REDIRECTS_HELP: "маршрути за пренасочване към сдруга страница. Подмяна със стандартен Regex е валидна" + CUSTOM_REDIRECTS_PLACEHOLDER_KEY: "/your/alias" + CUSTOM_REDIRECTS_PLACEHOLDER_VALUE: "/your/redirect" + CUSTOM_ROUTES: "Потребителски пренасочвания" + CUSTOM_ROUTES_PLACEHOLDER_KEY: "/your/alias" + CUSTOM_ROUTES_PLACEHOLDER_VALUE: "/your/route" + FILE_STREAMS: "Потоци файлове" + DEFAULT: "По подразбиране" + PAGE_MEDIA: "Страница с медия" + OPTIONS: "Опции" + PUBLISHED: "Публикувано" + PUBLISHED_HELP: "По подразбиране страницата се публикува, освен ако не е зададео published: false или publish_date е в бъдеще или unpublish_date е в миналото" + DATE: "Дата" + DATE_HELP: "Променливата за дата позволява да се зададе дата асоциирана със страницата." + PUBLISHED_DATE: "Дата на публикуване" + PUBLISHED_DATE_HELP: "Дата, на която автоматично ще се публикува." + UNPUBLISHED_DATE: "Дата на непубликуване" + UNPUBLISHED_DATE_HELP: "Може да зададе дата за автоматично непубликуване." + ROBOTS: "Роботи" + TAXONOMIES: "Таксономии" + TAXONOMY: "Таксономия" + ADVANCED: "Разширено" + SETTINGS: "Настройки" + FOLDER_NUMERIC_PREFIX: "Цифров префикс на папка" + FOLDER_NUMERIC_PREFIX_HELP: "Цифров префикс осигуряващ ръчно подреждане и по-добра видимост" + FOLDER_NAME: "Име на папка" + FOLDER_NAME_HELP: "Името на папката, която ще се съхрани във файлова система за тази страница" + PARENT: "Родител" + DEFAULT_OPTION_ROOT: "- Коренова папка -" + DEFAULT_OPTION_SELECT: "- Избор -" + DISPLAY_TEMPLATE: "Показване на шаблон" + BODY_CLASSES: "Класове на тялото" + ORDERING: "Подреждане" + PAGE_ORDER: "Подредба на страниците" + OVERRIDES: "Замени" + MENU: "Меню" + MENU_HELP: "Стрингът, който ще се използва в меню. Ако не се зададе, ще се използва Title." + SLUG: "Слъг" + SLUG_HELP: "Слъг променливата Ви позволява да зададете конкретна порция от URL на страницата" + SLUG_VALIDATE_MESSAGE: "Слъговете могат да съдържат само малки букви, цифри и тирета" + PROCESS: "Обработване" + PROCESS_HELP: "Контролирайте обработката на страниците. Може да бъде за отделна страница или глобално" + DEFAULT_CHILD_TYPE: "Тип по подразбиране" + USE_GLOBAL: "Използвай глобални" + ROUTABLE: "Маршрутизируем" + ROUTABLE_HELP: "Ако страницата е достъпна през URL" + CACHING: "Създаване на временни файлове" + VISIBLE: "Видим" + VISIBLE_HELP: "Определя дали една страница е видима в навигацията." + DISABLED: "Изключено" + ITEMS: "Елементи" + ORDER_BY: "Подреждане по" + ORDER: "Подреждане" + FOLDER: "Папка" + ASCENDING: "Възходящо" + DESCENDING: "Низходящо" + ADD_MODULAR_CONTENT: "Добави модулно съдържание" + PAGE_TITLE: "Заглавие на страницата" + PAGE_TITLE_HELP: "Заглавието на страницата" + PAGE: "Страница" + MODULAR_TEMPLATE: "Модулен шаблон" + FRONTMATTER: "Встъпление" + FILENAME: "Име на файла" + PARENT_PAGE: "Родителска страница" + HOME_PAGE: "Начална страница" + HOME_PAGE_HELP: "Страницата, която Grav ще използва по подразбиране за начална страница" + DEFAULT_THEME: "Тема по подразбиране" + DEFAULT_THEME_HELP: "Задаване на темата по подразбиране, която Grav ще използва (по подразбиране това е Antimatter)" + TIMEZONE: "Часова зона" + TIMEZONE_HELP: "Презаписване на времевата зона на сървъра" + SHORT_DATE_FORMAT: "Кратък формат дата" + SHORT_DATE_FORMAT_HELP: "Задай кратък формат дата, който може да се използва от темите" + LONG_DATE_FORMAT: "Пълен формат дата" + LONG_DATE_FORMAT_HELP: "Задай пълен формат дата, който може да се използва от темите" + DEFAULT_ORDERING: "По подразбиране" + DEFAULT_ORDERING_DEFAULT: "По подразбиране - според име на папка" + DEFAULT_ORDERING_FOLDER: "Папка - според името на папката без префикс" + DEFAULT_ORDERING_TITLE: "Заглавие - според заглавно поле в главата" + DEFAULT_ORDERING_DATE: "Дата - според поле за дата в главата" + DEFAULT_ORDER_DIRECTION: "Подреждане по подразбиране" + DEFAULT_ORDER_DIRECTION_HELP: "Посоката на страниците в списък" + DEFAULT_PAGE_COUNT: "Брой страници по подразбиране" + DEFAULT_PAGE_COUNT_HELP: "Максимален брой страници в списък по подразбиране" + DATE_BASED_PUBLISHING: "Публикуване според датата" + DATE_BASED_PUBLISHING_HELP: "Автоматично (не)публикувай постове според датата" + EVENTS: "Събития" + EVENTS_HELP: "Пускане или спиране на специфични събития. Спирането на някои събития може да счупи определени приставки" + REDIRECT_DEFAULT_ROUTE: "Пренасочване на пътя по подразбиране" + REDIRECT_DEFAULT_ROUTE_HELP: "Автоматично пренасочване към пътя по подразбиране на страницата" + LANGUAGES: "Езици" + SUPPORTED: "Поддържани" + SUPPORTED_HELP: "Списък от двубуквени езикови кодове, отделени със запетая (пример 'bg,en,de')" + TRANSLATIONS_ENABLED: "Преводите са включен" + HTTP_HEADERS: "HTTP заглавки" + EXPIRES: "Изтича на" + CACHE_CONTROL: "HTTP кеш-контрол" + LAST_MODIFIED: "Последна промяна" + CACHE_CHECK_METHOD: "Мотод проверка на кеша" + CACHE_DRIVER: "Кеш драйвър" + CACHE_PREFIX: "Кеш представка" + CACHE_PURGE: "Изтриване на стр кеш" + LIFETIME: "Продължителност на живот" + GZIP_COMPRESSION: "Gzip компресия" + GZIP_COMPRESSION_HELP: "Разреши GZip компресия на Grav страницата, за оптимизация." + CSS_PIPELINE: "CSS pipeline" + JAVASCRIPT_PIPELINE: "JavaScript pipeline" + LOG_HANDLER: "Обработка на лога" + DEBUGGER: "Дибъгър" + SESSION: "Сесия" + TIMEOUT: "Таймаут" + CURRENT: "Текущ" + SAVE_AS: "Запази като" + AND: "и" + UPDATE_AVAILABLE: "Налична актуализация" + FULLY_UPDATED: "Напълно обновен" + SAVE_LOCATION: "Местоположение за запис" + IGNORE_HIDDEN_HELP: "Игнорирай всички файлове и папки, които започват с точка" + WRAPPED_SITE: "Опаковани сайт" diff --git a/user/plugins/admin/languages/br.yaml b/user/plugins/admin/languages/br.yaml new file mode 100644 index 0000000..cdd75df --- /dev/null +++ b/user/plugins/admin/languages/br.yaml @@ -0,0 +1,600 @@ +--- +PLUGIN_ADMIN: + ADMIN_BETA_MSG: "Un ermaeziadenn beta an hini eo! Arverit en endro produadur gant evezh..." + ADMIN_REPORT_ISSUE: "Kavet hoc'h eus ur gudenn? Danevellit anezhi war Github." + EMAIL_FOOTER: "Lusket gant Grav - Ar CMS Restr plad modern" + LOGIN_BTN: "Anv arveriad" + LOGIN_BTN_FORGOT: "Ankouaet" + LOGIN_BTN_RESET: "Adderaouekaat ar ger-tremen" + LOGIN_BTN_SEND_INSTRUCTIONS: "Kas an ditouroù adderaouekaat" + LOGIN_BTN_CLEAR: "Skarzhañ ar furmskrid" + LOGIN_BTN_CREATE_USER: "Krouiñ an arveriad" + LOGIN_LOGGED_IN: "Kennasket oc'h gant berzh" + LOGIN_FAILED: "C'hwitadenn war ar c'hennask" + LOGGED_OUT: "Digennasket oc'h" + RESET_NEW_PASSWORD: "Enankit ur ger-tremen nevez …" + RESET_LINK_EXPIRED: "Diamzeret eo an ere adderaouekaat, klaskit en-dro" + RESET_PASSWORD_RESET: "Adderaouekaet eo bet ar ger-tremen" + RESET_INVALID_LINK: "Ere adderaouekaat didalvoudek, klaskit en-dro" + FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL: "Kaset eo bet an ditouroù da adderaouekaat ho ker-tremen d'ho chmolec'h postel" + FORGOT_FAILED_TO_EMAIL: "C'hwitadenn en ur gas an ditouroù, klaskit en-dro diwezhatoc'h" + FORGOT_CANNOT_RESET_EMAIL_NO_EMAIL: "N'haller ket adderaouekaat ar ger-tremen evit %s, chomlec'h postel ebet arventennet" + FORGOT_USERNAME_DOES_NOT_EXIST: "N'eus ket eus an arveriad gant an anv %s" + FORGOT_EMAIL_NOT_CONFIGURED: "N'haller ket adderaouekaat ar ger-tremen. N'eo ket kefluniet al lec'hienn evit kas posteloù" + FORGOT_EMAIL_SUBJECT: "%s Goulenn adderaouekaat ar ger-tremen" + FORGOT_EMAIL_BODY: "

Adderaouekaat ar ger-tremen/h1>

%1$s,

Graet eo bet un azgoulenn war %4$s evit adderaouekaat ho ker-tremen.


Klikit amañ da adderaouekaat ho ker-tremen

Gallout a rit ivez eilañ an URL da heul er varrenn chomlec'h en ho merdeer:

%2$s


A galon,

%3$s

" + MANAGE_PAGES: "Ardeiñ ar pajennoù" + CONFIGURATION: "Kefluniadur" + PAGES: "Pajennoù" + PLUGINS: "Enlugelladoù" + PLUGIN: "Enlugellad" + THEMES: "Neuzioù" + LOGOUT: "Digennaskañ" + BACK: "Distreiñ" + NEXT: "War-lerc'h" + PREVIOUS: "Diaraog" + ADD_PAGE: "Ouzhpennañ ur bajenn" + ADD_MODULAR: "Ouzhpennañ ur mollad" + MOVE: "Dilec'hiañ" + DELETE: "Dilemel" + VIEW: "Gwel" + SAVE: "Enrollañ" + NORMAL: "Reoliek" + EXPERT: "Kemplezhoc'h" + EXPAND_ALL: "Astenn an holl" + COLLAPSE_ALL: "Bihanaat an holl" + ERROR: "Fazi" + CLOSE: "Serriñ" + CANCEL: "Nullañ" + CONTINUE: "Kenderc'hel" + MODAL_DELETE_PAGE_CONFIRMATION_REQUIRED_TITLE: "Kadarnadur azgoulennet" + MODAL_CHANGED_DETECTED_TITLE: "Kemmoù dinoet" + MODAL_CHANGED_DETECTED_DESC: "Kemmoù dienrollet a zo. Sur oc'h e fell deoc'h kuitaat hep enrollañ?" + MODAL_DELETE_FILE_CONFIRMATION_REQUIRED_TITLE: "Kadarnadur azgoulennet" + MODAL_DELETE_FILE_CONFIRMATION_REQUIRED_DESC: "Sur oc'h e fell deoc'h dilemel ar restr-mañ? N'haller ket dizober ar gwered-mañ." + ADD_FILTERS: "Ouzhpennañ siloù" + SEARCH_PAGES: "Klask pajennoù" + VERSION: "Handelv" + WAS_MADE_WITH: "Savet eo bet gant" + BY: "Gant" + UPDATE_THEME: "Hizivaat an neuz" + UPDATE_PLUGIN: "Hizivaat an enlugellad" + OF_THIS_THEME_IS_NOW_AVAILABLE: "an neuz-mañ a zo hegerz" + OF_THIS_PLUGIN_IS_NOW_AVAILABLE: "an enlugellad-mañ a zo hegerz" + AUTHOR: "Aozer" + HOMEPAGE: "Pennbajenn" + DEMO: "Tañva" + BUG_TRACKER: "Heulier beugoù" + KEYWORDS: "Gerioù-alc'hwez" + LICENSE: "Lañvaz" + DESCRIPTION: "Deskrivadur" + README: "Skoazell" + REMOVE_THEME: "Dilemel an neuz" + INSTALL_THEME: "Staliañ an neuz" + THEME: "Neuz" + BACK_TO_THEMES: "Distreiñ d'an neuzioù" + BACK_TO_PLUGINS: "Distreiñ d'an enlugelladoù" + CHECK_FOR_UPDATES: "Klask hizivadennoù" + ADD: "Ouzhpenañ" + CLEAR_CACHE: "Skarzhañ ar c'hrubuilh" + CLEAR_CACHE_ALL_CACHE: "Ar c'hrubuilh a-bezh" + CLEAR_CACHE_ASSETS_ONLY: "Loazioù nemetken" + CLEAR_CACHE_IMAGES_ONLY: "Skeudennoù nemetken" + CLEAR_CACHE_CACHE_ONLY: "Krubuilh nemetken" + CLEAR_CACHE_TMP_ONLY: "Padennek hepken" + DASHBOARD: "Taolenn labour" + UPDATES_AVAILABLE: "Hizivadennoù hegerz" + DAYS: "Devezhioù" + UPDATE: "Hizivadenn" + BACKUP: "Gwared" + STATISTICS: "Stadegoù" + TODAY: "Hiziv" + WEEK: "Sizhun" + MONTH: "Miz" + LATEST_PAGE_UPDATES: "Hizivadennoù diwezhañ ar bajenn" + MAINTENANCE: "Trezalc'h" + UPDATED: "Hizivaet" + MON: "Lun" + TUE: "Meu" + WED: "Mer" + THU: "Yao" + FRI: "Gwe" + SAT: "Sad" + SUN: "Sul" + COPY: "Eilañ" + EDIT: "Kemmañ" + CREATE: "Krouiñ" + GRAV_ADMIN: "Merour Grav" + GRAV_OFFICIAL_PLUGIN: "Enlugellad Kefridiel Grav" + GRAV_OFFICIAL_THEME: "Neuz Kefridiel Grav" + PLUGIN_SYMBOLICALLY_LINKED: "Gant un ere arouezus eo lakaet an enlugellad. Ne vo ket dinoet an hizivadennoù." + THEME_SYMBOLICALLY_LINKED: "Gant un ere arouezus eo lakaet an neuz. Ne vo ket dinoet an hizivadennoù" + REMOVE_PLUGIN: "Dilemel an enlugellad" + INSTALL_PLUGIN: "Staliañ an enlugellad" + AVAILABLE: "Hegerz" + INSTALLED: "Staliet" + INSTALL: "Staliañ" + ACTIVE_THEME: "Neuz oberiant" + SWITCHING_TO: "Kemmañ da" + SWITCHING_TO_DESCRIPTION: "En ur gemmañ d'un neuz disheñvel n'eus gwarant ebet e vo skoret an holl frammoù pajenn, ar pezh a zegasfe fazioù en ur gargañ ar pajennoù-mañ." + SWITCHING_TO_CONFIRMATION: "Fellout a ra deoc'h kenderc'hel ha kemmañ an neuz" + CREATE_NEW_USER: "Krouiñ un arveriad nevez" + REMOVE_USER: "Dilemel an arveriad" + ACCESS_DENIED: "Haeziñ nac'het" + ACCOUNT_NOT_ADMIN: "n'hoc'h eus ket an aotreoù a-zere" + PHP_INFO: "Titouroù PHP" + INSTALLER: "Stalier" + AVAILABLE_THEMES: "Neuzioù hegerz" + AVAILABLE_PLUGINS: "Enlugelladoù hegerz" + INSTALLED_THEMES: "Neuzioù staliet" + INSTALLED_PLUGINS: "Enlugelladoù staliet" + BROWSE_ERROR_LOGS: "Furchal er c'herzhlevr fazioù" + SITE: "Lec'hienn" + INFO: "Titouroù" + SYSTEM: "Reizhiad" + USER: "Arveriad" + ADD_ACCOUNT: "Ouzhpennañ ur gont" + SWITCH_LANGUAGE: "Kemmañ ar yezh" + SUCCESSFULLY_ENABLED_PLUGIN: "Gweredekaet an enlugellad gant berzh" + SUCCESSFULLY_DISABLED_PLUGIN: "Diweredekaet an enlugellad gant berzh" + SUCCESSFULLY_CHANGED_THEME: "Kemmet an neuz dre ziouer gant berzh" + INSTALLATION_FAILED: "C'hwitadenn war ar staliadur" + INSTALLATION_SUCCESSFUL: "Berzh war ar staliadur" + UNINSTALL_FAILED: "C'hwitadenn war an distaliadur" + UNINSTALL_SUCCESSFUL: "Berzh war an distaliadur" + SUCCESSFULLY_SAVED: "Enrollet gant berzh" + SUCCESSFULLY_COPIED: "Eilet gant berzh" + REORDERING_WAS_SUCCESSFUL: "Adurzhiet gant berzh" + SUCCESSFULLY_DELETED: "Dilamet gant berzh" + SUCCESSFULLY_SWITCHED_LANGUAGE: "Kemmet ar yezh gant berzh" + INSUFFICIENT_PERMISSIONS_FOR_TASK: "N'ho peus ket trawalc'h a aotreoù evit ar gwered" + CACHE_CLEARED: "Skarzhet ar c'hrubuilh" + METHOD: "Hentenn" + ERROR_CLEARING_CACHE: "Fazi en ur skarzhañ ar c'hrubuilh" + AN_ERROR_OCCURRED: "Degouezhet ez eus bet ur fazi" + YOUR_BACKUP_IS_READY_FOR_DOWNLOAD: "Prest eo ho kwared da vezañ pellgarget" + DOWNLOAD_BACKUP: "Pellgargañ ar gwared" + PAGES_FILTERED: "Pajennoù silet" + NO_PAGE_FOUND: "Pajenn ebet kavet" + INVALID_PARAMETERS: "Arventennoù didalvoudek" + NO_FILES_SENT: "Restr ebet kaset" + UNKNOWN_ERRORS: "Fazioù dianav" + UNSUPPORTED_FILE_TYPE: "Doare restr amskor" + FAILED_TO_MOVE_UPLOADED_FILE: "C'hwitadenn en ur zilec'hiañ ar restr pellgaset." + FILE_UPLOADED_SUCCESSFULLY: "Restr pellgaset gant berzh" + FILE_DELETED: "Restr dilamet" + FILE_COULD_NOT_BE_DELETED: "N'haller ket dilemel ar restr" + FILE_NOT_FOUND: "N'eus ket bet kavet ar restr" + NO_FILE_FOUND: "Restr ebet kavet" + GRAV_WAS_SUCCESSFULLY_UPDATED_TO: "Hizivaet eo bet Grav da" + GRAV_UPDATE_FAILED: "C'hwitadenn war hizivadenn Grav" + EVERYTHING_UPDATED: "Hizivaet pep tra" + UPDATES_FAILED: "C'hwitadenn war a hizivadennoù" + AVATAR_BY: "Avatar gant" + LAST_BACKUP: "Gwared diwezhañ" + FULL_NAME: "Anv klok" + USERNAME: "Anv arveriad" + EMAIL: "Chomlec'h postel" + PASSWORD: "Ger-tremen" + PASSWORD_CONFIRM: "Kadarnat ar ger-tremen" + TITLE: "Titl" + LANGUAGE: "Yezh" + ACCOUNT: "Kont" + EMAIL_VALIDATION_MESSAGE: "Ret eo reiñ ur chomlec'h postel talvoudek" + PASSWORD_VALIDATION_MESSAGE: "Ret eo d'ar ger-tremen enderc'hel ur niverenn, ul lizherenn vras hag ul lizherenn vihan hag 8 arouezenn d'an nebeutañ" + LANGUAGE_HELP: "Dibabit ar yezh" + MEDIA: "Media" + DEFAULTS: "Dre ziouer" + SITE_TITLE: "Titl al lec'hienn" + SITE_TITLE_PLACEHOLDER: "Titl ledan al lec'hienn" + SITE_TITLE_HELP: "Titl dre ziouer ho lec'hienn, arveret en neuzioù" + SITE_DEFAULT_LANG: "Yezh defot" + DEFAULT_AUTHOR: "Aozer dre ziouer" + DEFAULT_AUTHOR_HELP: "Un anv aozer dre ziouer, arveret en neuzioù pe er pajennoù" + DEFAULT_EMAIL: "Chomlec'h postel dre ziouer" + DEFAULT_EMAIL_HELP: "Ur chomlec'h postel dre ziouer, arveret en neuze pe er pajennoù" + TAXONOMY_TYPES: "Doareoù rummadoù" + TAXONOMY_TYPES_HELP: "An doareoù rummadoù a rank bezañ erspizet amañ ma fell deoc'h arverañ anezho er pajennoù" + PAGE_SUMMARY: "Berradenn ar bajenn" + ENABLED: "Gweredekaet" + ENABLED_HELP: "Gweredekaat berradenn ar bajenn (ar verradenn a zistro an hevelep tra hag endalc'had ar bajenn)" + 'YES': "Ya" + 'NO': "Ket" + SUMMARY_SIZE: "Ment ar verradenn" + SUMMARY_SIZE_HELP: "An niverenn a arouezenn da arverañ evel berradenn ur bajenn" + FORMAT: "Mentrezh" + FORMAT_HELP: "berr = arverañ degouezh kentañ an disranner pe ment; hir = laosket e vo an disranner berradenn a-gostez" + SHORT: "Berr" + LONG: "Hir" + DELIMITER: "Disranner" + DELIMITER_HELP: "Disranner ar verradenn (diouer '===')" + METADATA: "Metaroadennoù" + METADATA_HELP: "Skrammet e vo ar gwerzhioù metaroadennoù dre ziouer war an holl bajennoù war-bouez m'eo flastret gant ar bajenn" + NAME: "Anv" + CONTENT: "Endalc'had" + REDIRECTS_AND_ROUTES: "Adheñchañ ha treugoù" + CUSTOM_REDIRECTS: "Adheñchañ personelaet" + CUSTOM_REDIRECTS_HELP: "treugoù da adheñchañ davet pajennoù all. Talvoudek eo an amsaviñ regex" + CUSTOM_REDIRECTS_PLACEHOLDER_KEY: "/un/anv" + CUSTOM_REDIRECTS_PLACEHOLDER_VALUE: "/un/adeñchañ" + CUSTOM_ROUTES: "Treugoù personelaet" + CUSTOM_ROUTES_HELP: "treugoù da adheñchañ davet pajennoù all. Talvoudek eo an amsaviñ Regex" + CUSTOM_ROUTES_PLACEHOLDER_KEY: "/ho/anv" + CUSTOM_ROUTES_PLACEHOLDER_VALUE: "/ho/treug" + FILE_STREAMS: "Lanvioù restroù" + DEFAULT: "Dre ziouer" + PAGE_MEDIA: "Media ar bajenn" + OPTIONS: "Dibarzhioù" + PUBLISHED: "Embannet" + PUBLISHED_HELP: "Dre ziouer eo embannet ur bajenn war-bouez m'eo lakaet da \"Embannet: ket\" pe dre un deiziad embann en dazont, pe un deiziad diembannañ tremenet" + DATE: "Deiziad" + DATE_HELP: "Ar vaezienn deiziad a laosk ac'hanoc'h da arventennañ un deiziad liammet gant ar bajenn." + PUBLISHED_DATE: "Deiziad embann" + PUBLISHED_DATE_HELP: "Gallout a rit reiñ un deiziad da embann ent emgefreek." + UNPUBLISHED_DATE: "Deiziad diembannañ" + UNPUBLISHED_DATE_HELP: "Gallout a rit reiñ un deiziad evit diembannañ ent emgefreek." + ROBOTS: "Robotoù" + TAXONOMIES: "Rummadoù" + TAXONOMY: "Rummad" + ADVANCED: "Kempleshoc'h" + SETTINGS: "Arventennoù" + FOLDER_NUMERIC_PREFIX: "Rakger niverel an teuliad" + FOLDER_NUMERIC_PREFIX_HELP: "Rakgerioù niverel evit urzhiañ gant an dorn ha emplegañ ar gwelusted" + FOLDER_NAME: "Anv an teuliad" + FOLDER_NAME_HELP: "Anv an teuliad a vo kadavet er reizhiad restroù evit ar bajenn" + PARENT: "Kar" + DEFAULT_OPTION_ROOT: "- Gwrizienn -" + DEFAULT_OPTION_SELECT: "- Diuzañ -" + DISPLAY_TEMPLATE: "Skrammañ ar patrom" + DISPLAY_TEMPLATE_HELP: "An doare pajenn a ziviz peseurt patrom twig a zeznaouo ar bajenn" + BODY_CLASSES: "Klasoù korf" + ORDERING: "Urzh" + PAGE_ORDER: "Urzh ar pajennoù" + OVERRIDES: "Flastrañ" + MENU: "Lañser" + MENU_HELP: "Ar chadennoù da arverañ el lañser. Ma n'eo ket arventennet, Titl a vo arveret." + SLUG: "Slug" + SLUG_HELP: "An argemenn slug a aotren ac'hanoc'h da arventennañ URL lodenn ar bajenn" + SLUG_VALIDATE_MESSAGE: "Lizherennoù bihan, sifroù ha tiredoù a c'hall bezañ er slug hepken" + PROCESS: "Keweriañ" + PROCESS_HELP: "Reoliañ penaos eo keweriet ar pajennoù. Gallout a ra bezañ lakaet dre bajenn kentoc'h eget en un doare hollek" + DEFAULT_CHILD_TYPE: "Doare bugel dre ziouer" + USE_GLOBAL: "Arverañ Hollek" + ROUTABLE: "Treugus" + ROUTABLE_HELP: "M'eo haezadus ar bajenn dre un URL" + CACHING: "Krubuilhiñ" + VISIBLE: "Gwelus" + VISIBLE_HELP: "Despizañ a ra gwelusted ur bajenn er merdeiñ." + DISABLED: "Diweredekaet" + ITEMS: "Ergorennoù" + ORDER_BY: "Urzhiañ dre" + ORDER: "Urzh" + FOLDER: "Teuliad" + ASCENDING: "War-gresk" + DESCENDING: "War-zigresk" + ADD_MODULAR_CONTENT: "Ouzhpennañ un endalc'had molladel" + PAGE_TITLE: "Titl ar bajenn" + PAGE_TITLE_HELP: "Titl ar bajenn" + PAGE: "Pajenn" + MODULAR_TEMPLATE: "Patrom molladel" + FRONTMATTER: "Frontmatter" + FILENAME: "Anv ar restr" + PARENT_PAGE: "Pajenn gar" + HOME_PAGE: "Pennbajenn" + HOME_PAGE_HELP: "Pajenn arveret gant Grav evel pajenn degemer dre ziouer" + DEFAULT_THEME: "Neuz dre ziouer" + DEFAULT_THEME_HELP: "Arventennañ an neuz arveret gant Grav dre ziouer (Antimatter dre ziouer)" + TIMEZONE: "Gwerzhid-eur" + TIMEZONE_HELP: "Flastrañ gwerzhid-eur dre ziouer an dafariad" + SHORT_DATE_FORMAT: "Mentrezh skrammañ an deiziad berr" + SHORT_DATE_FORMAT_HELP: "Arventennan ar mentrezh deiziad berr da arverañ gant an neuzioù" + LONG_DATE_FORMAT: "Mentrezh deiziad hir" + LONG_DATE_FORMAT_HELP: "Arventennañ ar mentrezh deiziad hir a vo arveret en neuzioù" + DEFAULT_ORDERING: "Urzh dre ziouer" + DEFAULT_ORDERING_HELP: "Pajennoù er roll a vo skrammet en urzh-mañ war-bouez m'eo flastret" + DEFAULT_ORDERING_DEFAULT: "Dre ziouer - diazezet war anv an teuliad" + DEFAULT_ORDERING_FOLDER: "Teuliad - diazezet war anv an teuliad hep rakger" + DEFAULT_ORDERING_TITLE: "Titl - diazezet war vaezienn ditl an talbenn" + DEFAULT_ORDERING_DATE: "Deiziad - diazezet war vaezienn deiziad an talbenn" + DEFAULT_ORDER_DIRECTION: "Tu an urzh dre ziouer" + DEFAULT_ORDER_DIRECTION_HELP: "Tu ar pajennoù er roll" + DEFAULT_PAGE_COUNT: "Niver a bajennoù dre ziouer" + DEFAULT_PAGE_COUNT_HELP: "Niver a bajennoù en ur roll d'ar muiañ" + DATE_BASED_PUBLISHING: "Embannadenn diazezet war un deiziad" + DATE_BASED_PUBLISHING_HELP: "(Di)embann pennadoù ent emgefreek hervez o deiziad" + EVENTS: "Darvoudoù" + EVENTS_HELP: "(Di)weredekaat darvoudoù resis. Diweredekaat anezho a c'hall terriñ enlugelladoù" + REDIRECT_DEFAULT_ROUTE: "Adheñchañ an treug dre ziouer" + REDIRECT_DEFAULT_ROUTE_HELP: "Adheñchañ ent emgefreek d'un treug pajenn dre ziouer" + LANGUAGES: "Yezhoù" + SUPPORTED: "Skoret" + SUPPORTED_HELP: "Roll bonegoù yezh 2 lizherenn ennañ disrannet gant skejoù (skouer: 'br, cy, en')" + TRANSLATIONS_ENABLED: "Troidigezhioù gweredekaet" + TRANSLATIONS_ENABLED_HELP: "Skor an troidigezhioù e Grav, an enlugelladoù hag an askouezhioù" + TRANSLATIONS_FALLBACK: "Troidigezh dre ziouer" + TRANSLATIONS_FALLBACK_HELP: "Arverañ un droidigezh all ma n'eus ket eus ar tezh oberiant" + ACTIVE_LANGUAGE_IN_SESSION: "Yezhoù oberiant en estez" + ACTIVE_LANGUAGE_IN_SESSION_HELP: "Kadaviñ ar yezh oberiant en estez" + HTTP_HEADERS: "Talbennoù HTTP" + EXPIRES: "Diamzer" + EXPIRES_HELP: "Arventennañ an talbenn diamzeriñ e eilennoù." + LAST_MODIFIED: "Kemmet da ziwezhañ" + LAST_MODIFIED_HELP: "Arventennañ an talbenn kemmet da ziwezhañ a c'hall skoazell da wellaat ar proksi ha krubuilh ar merdeer" + ETAG: "ETag" + ETAG_HELP: "Arventennañ an talbenn etag evit skoazell da c'houzout peur eo bet kemmet ur bajenn" + VARY_ACCEPT_ENCODING: "Vary accept encoding" + VARY_ACCEPT_ENCODING_HELP: "Arventennañ a ra an talbenn `Vary: Accept Encoding` evit skoazell gant ar proksi hag ar c'hrubuilh CDN" + MARKDOWN_EXTRA_HELP: "Gweredekaat ar skor dre ziouer evit Markdown Ectra - https://michelf.ca/projects/php-markdown/extra/" + AUTO_LINE_BREAKS: "Tremen d'al linenn ent emgefreek" + AUTO_LINE_BREAKS_HELP: "Gweredekaat skor tremen al linenn ent emgefreek e Markdown" + AUTO_URL_LINKS: "Ereoù URL emgefreek" + AUTO_URL_LINKS_HELP: "Gweredekaat amdroadur emgefreek an URLoù da ereoù HTML" + ESCAPE_MARKUP: "Gwareziñ an HTML" + ESCAPE_MARKUP_HELP: "Gwareziñ ar c'hlavioù e elfennoù HTML" + CACHING_HELP: "Trec'haoler hollek evit (di)weredekaat krubuilh Grav" + CACHE_CHECK_METHOD: "Hentenn gwiriekaat ar c'hrubuilh" + CACHE_CHECK_METHOD_HELP: "Dibab an hentenn arveret gant Grav evit gwiriekaat m'eo bet kemmer ar restoù pajenn." + CACHE_DRIVER: "Sturier Krubuilh" + CACHE_DRIVER_HELP: "Dibab pe sturier krubuilh a zo arveret Grav. 'Dinoiñ emgefreek' a glask kavout pe zoare a zo an hini gwellañ" + CACHE_PREFIX: "Rakger ar c'hrubuilh" + CACHE_PREFIX_HELP: "Lodenn naoudi an alc'hwez Grav. Na gemmit anezhi ma n'ouzit ket petra rit." + CACHE_PREFIX_PLACEHOLDER: "Deveret eus an URL diazez (flastret en un enkañ ur chadenn dargouezhek)" + LIFETIME: "Padelezh buhez" + LIFETIME_HELP: "Arventennañ padelezh ar c'hrubuilh e eilennoù. 0 = anvevenn" + GZIP_COMPRESSION: "Koazhadur Gzip" + GZIP_COMPRESSION_HELP: "Gweredekaat koazhadur Gzip ar bajenn Grav evit kreskiñ an digonusted." + TWIG_TEMPLATING: "Patromiñ Twig" + TWIG_CACHING: "Krubuilh Twig" + TWIG_CACHING_HELP: "Reoliañ wikefre krubuilh Twig. Laoskit gweredekaet evit an digonusted gwellañ." + TWIG_DEBUG: "Diveugañ Twig" + TWIG_DEBUG_HELP: "Aotren an dibarzh evit chom hep kargañ an askouezh diveugañ Twig" + DETECT_CHANGES: "Dinoiñ ar c'hemmoù" + DETECT_CHANGES_HELP: "Adkempunet e vo krubuilh Twig ent emgefreek ma vez dinoet kemmoù er patromoù Twig" + AUTOESCAPE_VARIABLES: "Gwareziñ an argemennoù ent emgefreek" + AUTOESCAPE_VARIABLES_HELP: "Gwareziñ an holl argemennoù ent emgefreek. Moarvat e torro ho lec'hienn" + ASSETS: "Madoù" + CSS_PIPELINE: "Arrevellañ CSS" + CSS_PIPELINE_HELP: "Arrevellañ ar CSS a zo unvanadur meur a loaz CSS en ur restr hepken" + CSS_PIPELINE_INCLUDE_EXTERNALS: "Ebarzhiñ restroù estren en arrevellañ CSS" + CSS_PIPELINE_INCLUDE_EXTERNALS_HELP: "URLoù diavaez a zo gant daveoù restroù daveel a-wechoù ha ne rankont ket bezañ arrevellet" + CSS_PIPELINE_BEFORE_EXCLUDES: "Deoueziñ an arrevellañ CSS da gentañ" + CSS_PIPELINE_BEFORE_EXCLUDES_HELP: "Deoueziñ an arrevellañ CSS a-raok kement dave CSS all ha n'int ket enkorfet" + CSS_MINIFY: "Bihanadur CSS" + CSS_MINIFY_HELP: "Bihanaat ar CSS e-pad an arrevellañ" + CSS_MINIFY_WINDOWS_OVERRIDE: "Amsaviñ bihanadur ar CSS Windows" + CSS_MINIFY_WINDOWS_OVERRIDE_HELP: "Amsaviñ ar bihanadur evit savennoù Windows. Faos dre ziouer abalamour da ThreadStackSize" + CSS_REWRITE: "Adskrivañ CSS" + CSS_REWRITE_HELP: "Adskrivañ kement URL daveel CSS e-pad an arrevellañ" + JAVASCRIPT_PIPELINE: "Arrevellañ Javascript" + JAVASCRIPT_PIPELINE_HELP: "An arrevellañ JS a zo unvanadur meur a restr JS en ur restr hepken" + JAVASCRIPT_PIPELINE_INCLUDE_EXTERNALS: "Enkorfañ ar JS diavaez evit an arrevellañ" + JAVASCRIPT_PIPELINE_INCLUDE_EXTERNALS_HELP: "Urloù diavaez o deus daveoù restroù daveel a-wechoù ha ne rankont ket bezañ arrevellet" + JAVASCRIPT_PIPELINE_BEFORE_EXCLUDES: "Arrevellañ JS da gentañ" + JAVASCRIPT_PIPELINE_BEFORE_EXCLUDES_HELP: "Deoueziñ an arrevellañ JS a-raok kement dave JS all ha n'int ket enkorfet" + JAVASCRIPT_MINIFY: "Bihanat ar javascript" + JAVASCRIPT_MINIFY_HELP: "Bihanaat ar JS e-pad an arrevellañ" + ENABLED_TIMESTAMPS_ON_ASSETS: "Gweredekaat ar boneg-amzer war al loazioù" + ENABLED_TIMESTAMPS_ON_ASSETS_HELP: "Gweredekaat bonegoù-amzer al loazioù" + COLLECTIONS: "Dastumadegoù" + ERROR_HANDLER: "Dornataour fazioù" + DISPLAY_ERRORS: "Skrammañ ar fazioù" + DISPLAY_ERRORS_HELP: "Skrammañ ur bajenn fazi gant munudoù" + LOG_ERRORS: "Kerzhlevr ar fazioù" + LOG_ERRORS_HELP: "Lakaat kerzhlevr ar fazioù en teuliad /logs" + DEBUGGER: "Diveuger" + DEBUGGER_HELP: "Gweredekaat diveuger Grav hag an arventennoù da heul" + DEBUG_TWIG: "Diveugañ Twig" + DEBUG_TWIG_HELP: "Gweredekaat diveugañ ar patromoù Twig" + SHUTDOWN_CLOSE_CONNECTION: "Shutdown a serr ar c'hennask" + SHUTDOWN_CLOSE_CONNECTION_HELP: "Serriñ ar c'hennask a-raok gervel onShutdown(). 'false' evit diveugañ" + DEFAULT_IMAGE_QUALITY: "Perzhded skeudenn dre ziouer" + DEFAULT_IMAGE_QUALITY_HELP: "Perzhded skeudenn dre ziouer da arverañ e-pad adstandilhonañ ar skeudennoù (85%)" + CACHE_ALL: "Lakaat an holl skeudennoù er c'hrubuilh" + CACHE_ALL_HELP: "Lakaat an holl skeudennoù da dremen dre reizhiad krubuilh Grav zoken ma n'o deus dornatadur media ebet" + IMAGES_DEBUG: "Rouedigell diveugañ ar skeudenn" + IMAGES_DEBUG_HELP: "Diskouez un diflugell a-us d'ar skeudennoù a ziskouez an donder piksel pa labourer war Retina da skouer" + UPLOAD_LIMIT: "Bevenn ment ar restroù da bellgas" + UPLOAD_LIMIT_HELP: "Lakaat ar ment restroù uhelañ e eizhbitoù (0 a zo anvevenn)" + ENABLE_MEDIA_TIMESTAMP: "Gweredekaat ar boneg-amzer war ar media" + ENABLE_MEDIA_TIMESTAMP_HELP: "Ouzhpennañ ur boneg-amzer diazezet war an deiziad kemmadur evit pep elfenn media" + SESSION: "Estez" + SESSION_ENABLED_HELP: "Gweredekaat skor an estez evit Grav" + TIMEOUT: "Diamzeriñ" + TIMEOUT_HELP: "Lakaat an amzer diamzeriñ e eilennoù" + SESSION_NAME_HELP: "Un naoudi arveret da stummañ anv toupin an estez" + ABSOLUTE_URLS: "URL dizave" + ABSOLUTE_URLS_HELP: "URLoù dizave pe daveel evit 'base_url'" + PARAMETER_SEPARATOR: "Disranner arventenn" + PARAMETER_SEPARATOR_HELP: "An disranner evit an arventennoù tremenet a c'hall bezañ kemmet evit Apache war Windows" + TASK_COMPLETED: "Trevell echuet" + EVERYTHING_UP_TO_DATE: "Pep tra a zo hizivaet" + UPDATES_ARE_AVAILABLE: "hizivadennoù hegerz" + IS_AVAILABLE_FOR_UPDATE: "a zo gant un hizivadenn hegerz" + IS_NOW_AVAILABLE: "a zo hegerz" + CURRENT: "Bremanel" + UPDATE_GRAV_NOW: "Hizivaat Grav bremañ" + GRAV_SYMBOLICALLY_LINKED: "Gant un ere arouezel eo staliet Grav. Dihegerz eo an hizivadenn" + UPDATING_PLEASE_WAIT: "Oc'h hizivaat... gortozit, emañ o pellgargañ" + OF_THIS: "eus an" + OF_YOUR: "eus ho" + HAVE_AN_UPDATE_AVAILABLE: "en deus un hizivadenn hegerz" + SAVE_AS: "Enrollañ evel" + MODAL_DELETE_PAGE_CONFIRMATION_REQUIRED_DESC: "Sur oc'h e fell deoc'h dilemel ar bajenn-mañ hag holl he bugale? M'eo troet ar bajenn en ur yezh all e vo miret an troidigezhioù a rankout a reot o dilemel en un doare distag. E mod all e vo dilamet teuliad ar bajenn gant an is-pajennoù. N'haller ket dizober ar gwered-mañ." + AND: "ha" + UPDATE_AVAILABLE: "Hizivadenn hegerz" + METADATA_KEY: "Alc'hwez (sk. 'Gerioù-alc'hwez')" + METADATA_VALUE: "Gwerzh (sk. 'Blog, Grav')" + USERNAME_HELP: "Etre 3 ha 16 arouezenn e rank an anv arveriad bezañ o kontañ al lizherennoù bihan, an niverennoù, an islinennoù hag ar barrennigoù. N'eo ket aotreet al lizherennoù bras, an esaouennoù hag an arouezennoù arbennik" + FULLY_UPDATED: "Hizivaet" + SAVE_LOCATION: "Lec'hiadur enrollañ" + PAGE_FILE: "Patrom pajenn" + PAGE_FILE_HELP: "Anv restr patrom ar bajenn, ha patrom skrammañ ar bajenn dre ziouer" + NO_USER_ACCOUNTS: "Kont arveriad ebet kavet, krouit unan da gentañ..." + REDIRECT_TRAILING_SLASH: "Adheñchañ ar veskell dibenn" + REDIRECT_TRAILING_SLASH_HELP: "Ober un adheñchañ 301 e-lerc'h merañ an beskell dibenn an URI en un doare treuzwelus." + DEFAULT_DATE_FORMAT: "Mentrezh deiziad ar bajenn" + DEFAULT_DATE_FORMAT_HELP: "Mentrezh deiziad ar bajenn arveret gant Grav. Dre ziouer, Grav a glask divinout mentrezh an deiziad met gallout a rit erspizañ unan gant kevreadur deiziad PHP (sk.: Y-m-d H:i)" + DEFAULT_DATE_FORMAT_PLACEHOLDER: "Divinout en emgefreek" + IGNORE_FILES: "Leuskel restroù a-gostez" + IGNORE_FILES_HELP: "Restroù da leuskel a-gostez e-pad keweriañ ar pajennoù" + IGNORE_FOLDERS: "Leuskel teuliadoù a-gostez" + IGNORE_FOLDERS_HELP: "Teuliadoù resis da leuskel a-gostez e-pad keweriañ ar pajennoù" + HTTP_ACCEPT_LANGUAGE: "Lakaat yezh ar merdeer" + HTTP_ACCEPT_LANGUAGE_HELP: "Gallout a rit klask arventennañ ar yezh gant hini ar talbenn `http_accept_language` ar merdeer" + OVERRIDE_LOCALE: "Flastrañ ar yezh" + OVERRIDE_LOCALE_HELP: "Flastrañ arventenn yezh PHP diazezet war ar yezh vremanel" + REDIRECT: "Adheñchañ ar bajenn" + REDIRECT_HELP: "Enankit hent ur bajenn pe un URL diavaez da adheñchañ ar bajenn. Sk. '/un/hent' pe 'http://ulload.bzh'" + PLUGIN_STATUS: "Stad an elugellad" + INCLUDE_DEFAULT_LANG: "Enkorfañ ar yezh dre ziouer" + INCLUDE_DEFAULT_LANG_HELP: "Ouzhpennañ a raio ar yezh dre ziouer en holl URLoù er yezh dre ziouer. Sk. '/br/blog/post'" + ALLOW_URL_TAXONOMY_FILTERS: "URL siloù rummad" + ALLOW_URL_TAXONOMY_FILTERS_HELP: "Dastumadegoù pajennoù a aotren ac'hanoc'h da silañ dre '/rummad:gwerzh'." + REDIRECT_DEFAULT_CODE: "Boneg adheñchan dre ziouer" + REDIRECT_DEFAULT_CODE_HELP: "Boneg stad HTTP da arverañ evit adheñchañ" + IGNORE_HIDDEN: "Leuskel ar re kuzhet a-gostez" + IGNORE_HIDDEN_HELP: "Leuskel an holl restroù ha teuliadoù a grog gant ur POENT" + WRAPPED_SITE: "Lec'hienn enkorfet" + WRAPPED_SITE_HELP: "Evit ma ouife an neuzioù/enlugelladoù m'eo enkorfet Grav en ur savenn all" + FALLBACK_TYPES: "Aotren doareoù fallback" + FALLBACK_TYPES_HELP: "Doareoù restr aotreet a c'hall bezañ kavet m'int haezet dre hent ar bajenn. An holl zoareoù media skoret dre ziouer." + INLINE_TYPES: "Doareoù fallback enkorfet" + INLINE_TYPES_HELP: "Ur roll doareoù restroù a rank bezañ skrammet en un doare enkorfet kentoc'h eget pellgarget" + APPEND_URL_EXT: "Ouzhpennañ an astenn d'an URL" + APPEND_URL_EXT_HELP: "Ouzhpennañ a raio un astenn personelaet da URL ar bajenn. Talvezout a ra e glasko Grav ur patrom anvet `..twig`" + PAGE_MODES: "Modoù pajenn" + PAGE_TYPES: "Doareoù pajenn" + ACCESS_LEVELS: "Liveoù haeziñ" + GROUPS: "Strolladoù" + GROUPS_HELP: "Roll ar strolladoù gant an arveriad enno" + ADMIN_ACCESS: "Haeziñ ardoer" + SITE_ACCESS: "Haeziñ d'al lec'hienn" + INVALID_SECURITY_TOKEN: "Reveziadenn diogelroez didalvoudek" + ACTIVATE: "Gweredekaat" + TWIG_UMASK_FIX: "Ratreadur Umask" + TWIG_UMASK_FIX_HELP: "Twig a grou ar restroù krubuilh gant 0755 dre ziouer, ar ratreañ a lak anezho da 0755" + CACHE_PERMS: "Aotreoù ar c'hrubuilh" + CACHE_PERMS_HELP: "Aotreoù dre ziouer teuliad ar c'hrubuilh. 0755 pe 0775 peurvuiañ, hervez ar c'hefluniadur" + REMOVE_SUCCESSFUL: "Dilamet gant berzh" + REMOVE_FAILED: "C'hwitadenn war an dilemel" + HIDE_HOME_IN_URLS: "Kuzhat hent ar pennbajenn en URL" + HIDE_HOME_IN_URLS_HELP: "Gwiriekaat a raio n'eo ket daveet hent skoueriek an degemer gant hentoù dre ziouer ar pajennoù dindan an degemer" + TWIG_FIRST: "Keweriañ an Twig da gentañ" + TWIG_FIRST_HELP: "M'ho peus gweredekaat keweriañ ar bajenn Twig e c'hallit kefluniañ Twig evit e geweriañ a-raok pe goude ar Markdown" + SESSION_SECURE: "Diogel" + SESSION_SECURE_HELP: "M'eo gwir, diskouez a ra eo ret d'ar c'hehentiñ evit an toupin-mañ bezañ graet war un treuzkas diogel. DIWALLIT: Gweredekait an dra-se war lec'hiennoù e HTTPS nemetken" + SESSION_HTTPONLY: "HTTP nemetken" + SESSION_HTTPONLY_HELP: "M'eo gwir, diskouez a ra eo ret d'ar c'hehentiñ evit an toupin-mañ bezañ graet war un treuzkas HTTP ha n'eo ket aotreet kemmañ ar Javascript" + REVERSE_PROXY: "Proksi en tu-gin" + REVERSE_PROXY_HELP: "Gweredekait an dra-se m'hoc'h a-dreñv ur proksi en tu-gin hag ho peus diaesterioù gant an URLoù oc'h enderc'hel ur porzh didalvoudek" + INVALID_FRONTMATTER_COULD_NOT_SAVE: "Frontmatter didalvoudek, n'haller ket enrollan" + ADD_FOLDER: "Ouzhpennañ un teuliad" + PROXY_URL: "URL ar proksi" + PROXY_URL_HELP: "Enankit HERBERC'HIER pe IP ar proksi hag ar PORZH" + NOTHING_TO_SAVE: "Netra da enrollañ" + FILE_ERROR_ADD: "Degouezhet ez eus bet ur fazi en ur glask enrollañ ar restr" + FILE_ERROR_UPLOAD: "Degouezhet ez eus bet ur fazi en ur glask pellgas ar restr" + FILE_UNSUPPORTED: "Doare restr anskor" + ADD_ITEM: "Ouzhpennañ un elfenn" + FILE_TOO_LARGE: "Re leden eo ar restr evit bezañ pellgaset. %s eo an uhelañ aotreet hervez
hoc'h arventennoù PHP. Kreskit an arventenn PHP`post_max_size`" + INSTALLING: "O staliañ" + LOADING: "O kargañ.." + DEPENDENCIES_NOT_MET_MESSAGE: "Ret eo deoc'h staliañ an amzalc'hoù da-heul a-raok:" + ERROR_INSTALLING_PACKAGES: "Fazi en ur staliañ ar pakad(où)" + INSTALLING_DEPENDENCIES: "O staliañ an amzalc'hoù..." + INSTALLING_PACKAGES: "O staliañ ar pakad(où).." + PACKAGES_SUCCESSFULLY_INSTALLED: "Pakad(où) staliet gant berzh." + READY_TO_INSTALL_PACKAGES: "Prest da staliañ ar pakad(où)" + PACKAGES_NOT_INSTALLED: "N'eo ket stalied ar pakadoù" + PACKAGES_NEED_UPDATE: "Staliet eo ar pakadoù endeo, met re gozh eo" + PACKAGES_SUGGESTED_UPDATE: "Staliet eo ar pakadoù endeo, dereat eo an handelv, met hizivaet e vint evit ma vefec'h en handelv diwezhañ" + REMOVE_THE: "Dilemel an %s" + CONFIRM_REMOVAL: "Sur oc'h e fell deoc'h dilemel %s?" + REMOVED_SUCCESSFULLY: "%s dilamet gant berzh" + ERROR_REMOVING_THE: "Fazi en ur zilemel %s" + ADDITIONAL_DEPENDENCIES_CAN_BE_REMOVED: "An amzalc'hoù da heul a zo azgoulennet gant %s, met n'eo ket azgoulennet gant ur pakad all. Ma ne arverit ket anezho e c'hallit o dilemel adalek amañ." + READY_TO_UPDATE_PACKAGES: "Prest da hizivaat ar pakad(où)" + ERROR_UPDATING_PACKAGES: "Fazi en ur hizivaat ar pakad(où)" + UPDATING_PACKAGES: "Oc'h hizivaat ar pakad(où).." + PACKAGES_SUCCESSFULLY_UPDATED: "Pakad(où) hizivaet gant berzh." + UPDATING: "Hizivaet" + GPM_RELEASES: "Ermaeziadennoù GPM" + GPM_RELEASES_HELP: "Dibabit 'Amprouiñ' evit staliañ an handelv beta pe amprouiñ" + AUTO: "Oto" + FOPEN: "fopen" + CURL: "cURL" + STABLE: "Stabil" + TESTING: "Amprouiñ" + FRONTMATTER_PROCESS_TWIG: "Keweriañ frontmatter Twig" + FRONTMATTER_PROCESS_TWIG_HELP: "P'eo oberiant e c'hallit arverañ argemennoù kefluniañ Twig e frontmatter ar bajenn" + FRONTMATTER_IGNORE_FIELDS: "Leuskel maeziennoù Frontmatter a-gostez" + FRONTMATTER_IGNORE_FIELDS_HELP: "Maeziennoù Frontmatter a c'hall enderc'hel Twig met ne rankont ket bezañ keweriet, evel 'forms'" + PACKAGE_X_INSTALLED_SUCCESSFULLY: "Pakad %s staliet gant berzh" + ORDERING_DISABLED_BECAUSE_PARENT_SETTING_ORDER: "Urzh ar c'har, diweredekaet eo an urzhiañ" + ORDERING_DISABLED_BECAUSE_PAGE_NOT_VISIBLE: "Diwelus eo ar bajenn, diweredekaet eo an urzhiañ" + ORDERING_DISABLED_BECAUSE_TOO_MANY_SIBLINGS: "N'eo ket skoret an urzhiañ dre an ardeiñ dre ma zo ouzhpenn 200 c'hoar" + CANNOT_ADD_MEDIA_FILES_PAGE_NOT_SAVED: "EVEZHIADENN: n'hallit ket ouzhpennañ restroù media evit enrollañ ar bajenn. Klikit war 'Enrollañ' a-us" + CANNOT_ADD_FILES_PAGE_NOT_SAVED: "EVEZHIADENN: ret eo enrollañ ar bajenn a-raok pellgas restroù dezhi." + DROP_FILES_HERE_TO_UPLOAD: "Lakait ho restroù amañ pe klikit amañ" + INSERT: "Enlakaat" + UNDO: "Dizober" + REDO: "Adober" + HEADERS: "Talbennoù" + BOLD: "Tev" + ITALIC: "Stouet" + STRIKETHROUGH: "Barrennet" + SUMMARY_DELIMITER: "Bonner diverrad" + LINK: "Liamm" + IMAGE: "Skeudenn" + BLOCKQUOTE: "Meneg" + UNORDERED_LIST: "Roll dizurzh" + ORDERED_LIST: "Roll urzhiet" + EDITOR: "Embanner" + PREVIEW: "Alberz" + FULLSCREEN: "Skramm a-bezh" + MODULAR: "Modulel" + NON_ROUTABLE: "Dihentus" + NON_MODULAR: "Divodulel" + NON_VISIBLE: "Diwelus" + NON_PUBLISHED: "Diembannet" + CHARACTERS: "arouezioù" + PUBLISHING: "Embann" + NOTIFICATIONS: "Notifiadenn" + MEDIA_TYPES: "Doareoù media" + IMAGE_OPTIONS: "Opsionoù skeudenn" + MIME_TYPE: "Doare Mime" + THUMB: "Miniaturenn" + TYPE: "Doare" + FILE_EXTENSION: "Astenn ar fichenn" + LEGEND: "Alc'hwez ar bajenn" + MEMCACHE_SERVER: "Servijer Memcached" + MEMCACHE_SERVER_HELP: "Chomlec'h ar servijer Memcached" + MEMCACHE_PORT: "Porzh Memcached" + MEMCACHE_PORT_HELP: "Porzh ar servijer Memcached" + MEMCACHED_SERVER: "Servijer Memcached" + MEMCACHED_SERVER_HELP: "Chomlec'h ar servijer Memcached" + MEMCACHED_PORT: "Porzh Memcached" + MEMCACHED_PORT_HELP: "Porzh ar servijer Memcached" + REDIS_SERVER: "Servijer Redis" + REDIS_SERVER_HELP: "Chomlec'h ar servijer Redis" + REDIS_PORT: "Porzh Redis" + REDIS_PORT_HELP: "Porzh ar servijer Redis" + ALL: "Tout" + FROM: "eus" + TO: "da" + RESOURCE_FILTER: "Sil..." + FORCE_SSL: "Forsañ SSL" + DROPZONE_CANCEL_UPLOAD: 'Nullañ ar gargamant' + DROPZONE_REMOVE_FILE: "Dilemel ar fichenn" + PREMIUM_PRODUCT: "Premium" + ERROR_SIMPLE: "Fazi simpl" + ERROR_SYSTEM: "Fazi Sistem" + NOT_SET: "Pas termenet" + PERMISSIONS: "Permisionoù" + REINSTALL_PLUGIN: "Adstaliañ ar Plugin" + REINSTALL_THEME: "Adstaliañ an Tem" + REINSTALL_THE: "Adstaliañ ar %s" + REINSTALLATION_FAILED: "Adstaliañ c'hwitet" + TOOLS: "Ostilhoù" + DIRECT_INSTALL: "Staliañ war-eeun" + 2FA_CODE_INPUT: "000000" diff --git a/user/plugins/admin/languages/ca.yaml b/user/plugins/admin/languages/ca.yaml new file mode 100644 index 0000000..8a848cd --- /dev/null +++ b/user/plugins/admin/languages/ca.yaml @@ -0,0 +1,641 @@ +--- +PLUGIN_ADMIN: + ADMIN_BETA_MSG: "Aquesta és una versió beta! Utilitza-la en producció sota el teu propi risc..." + ADMIN_REPORT_ISSUE: "Has trobat algun problema? Sisplau, reporta'l a GitHub." + EMAIL_FOOTER: "Funcionant amb Grav - El CMS de fitxers plans modern" + LOGIN_BTN: "Inicia sessió" + LOGIN_BTN_FORGOT: "Ho he oblidat" + LOGIN_BTN_RESET: "Restablir contrasenya" + LOGIN_BTN_SEND_INSTRUCTIONS: "Envia instruccions pel reset" + LOGIN_BTN_CLEAR: "Netejar formulari" + LOGIN_BTN_CREATE_USER: "Crear usuari" + LOGIN_LOGGED_IN: "S'ha iniciat sessió correctament" + LOGIN_FAILED: "No s'ha pogut iniciar sessió" + LOGGED_OUT: "S'ha tancat la sessió" + RESET_NEW_PASSWORD: "Sisplau introdueix una nova contasenya …" + RESET_LINK_EXPIRED: "L'enllaç per a restablir contrasenya ha expirat, torna a provar" + RESET_PASSWORD_RESET: "S'ha restablert la contrasenya" + RESET_INVALID_LINK: "L'enllaç per a restablir contrasenya invàl·lid, torna a provar" + FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL: "Les instruccions per a restablir la contrasenya s'han enviat per correu electrònic a %s" + FORGOT_FAILED_TO_EMAIL: "S'ha fallat al enviar les instruccions, sisplau torna-ho a provar" + FORGOT_CANNOT_RESET_EMAIL_NO_EMAIL: "No es pot restablir la contrasenya per a %s, no té cap email assignat" + FORGOT_USERNAME_DOES_NOT_EXIST: "L'usuari %s no existeix" + FORGOT_EMAIL_NOT_CONFIGURED: "No es pot restablir la contrasenya. Aquest lloc no està configurat per enviar missatges de correu electrònic" + FORGOT_EMAIL_SUBJECT: "%s Petició de restabliment de contrasenya" + FORGOT_EMAIL_BODY: "

Restabliment de contrasenya

Benvolgut/da %1$s,

S'ha fet una petició a %4$s per a restablir la contrasenya.


Fes clic aquí per a restablir la contrasenya

Altrament, copia el següent URL al teu navegador:

%2$s


Atentament,

%3$s

" + MANAGE_PAGES: "Gestiona pàgines" + CONFIGURATION: "Configuració" + PAGES: "Pàgines" + PLUGINS: "Plugins" + PLUGIN: "Plugin" + THEMES: "Temes" + LOGOUT: "Tanca sessió" + BACK: "Enrere" + ADD_PAGE: "Afegeix pàgina" + ADD_MODULAR: "Afegeix modular" + MOVE: "Mou" + DELETE: "Esborra" + SAVE: "Desa" + NORMAL: "Normal" + EXPERT: "Expert" + EXPAND_ALL: "Expandeix tot" + COLLAPSE_ALL: "Col·lapsa tot" + ERROR: "Error" + CLOSE: "Tanca" + CANCEL: "Cancel·la" + CONTINUE: "Continua" + MODAL_DELETE_PAGE_CONFIRMATION_REQUIRED_TITLE: "Confirmació requerida" + MODAL_CHANGED_DETECTED_TITLE: "Canvis detectats" + MODAL_CHANGED_DETECTED_DESC: "Tens canvis no desats. Estàs segur que vols sortir sense desar?" + MODAL_DELETE_FILE_CONFIRMATION_REQUIRED_TITLE: "Confirmació requerida" + MODAL_DELETE_FILE_CONFIRMATION_REQUIRED_DESC: "Estàs segur que vols eliminar aquest fitxer? Aquesta acció no es pot desfer." + ADD_FILTERS: "Afegeix filtres" + SEARCH_PAGES: "Cerca pàgines" + VERSION: "Versió" + WAS_MADE_WITH: "Es va fer amb" + BY: "Per" + UPDATE_THEME: "Actualitza tema" + UPDATE_PLUGIN: "Actualitza plugin" + OF_THIS_THEME_IS_NOW_AVAILABLE: "d'aquest tema està disponible" + OF_THIS_PLUGIN_IS_NOW_AVAILABLE: "d'aquest plugin està disponible" + AUTHOR: "Autor/a" + HOMEPAGE: "Pàgina d'inici" + DEMO: "Demo" + BUG_TRACKER: "Rastrejador d'errors" + KEYWORDS: "Paraules clau" + LICENSE: "Llicència" + DESCRIPTION: "Descripció" + README: "Llegiu-me" + REMOVE_THEME: "Elimina tema" + INSTALL_THEME: "Instal·la tema" + THEME: "Tema" + BACK_TO_THEMES: "Torna a Temes" + BACK_TO_PLUGINS: "Torna a Plugins" + CHECK_FOR_UPDATES: "Cerca actualitzacions" + ADD: "Afegeix" + CLEAR_CACHE: "Neteja la memòria cache" + CLEAR_CACHE_ALL_CACHE: "Tota la cache" + CLEAR_CACHE_ASSETS_ONLY: "Només assets" + CLEAR_CACHE_IMAGES_ONLY: "Només imatges" + CLEAR_CACHE_CACHE_ONLY: "Només cache" + CLEAR_CACHE_TMP_ONLY: "Només tmp" + DASHBOARD: "Panell de control" + UPDATES_AVAILABLE: "Hi ha actualizacions disponibles" + DAYS: "Dies" + UPDATE: "Actualitza" + BACKUP: "Còpia de seguretat" + STATISTICS: "Estadístiques" + TODAY: "Avui" + WEEK: "Setmana" + MONTH: "Mes" + LATEST_PAGE_UPDATES: "Últimes pàgines actualitzades" + MAINTENANCE: "Manteniment" + UPDATED: "Actualitzat" + MON: "Dl." + TUE: "Dt." + WED: "Dc." + THU: "Dj." + FRI: "Dv." + SAT: "Ds." + SUN: "Dg." + COPY: "Copia" + EDIT: "Edita" + CREATE: "Crea" + GRAV_ADMIN: "Administració Grav" + GRAV_OFFICIAL_PLUGIN: "Plugin oficial de Grav" + GRAV_OFFICIAL_THEME: "Tema oficial de Grav" + PLUGIN_SYMBOLICALLY_LINKED: "Aquest plugin està lligat simbòlicament. Les actualitzacions no seran detectades." + THEME_SYMBOLICALLY_LINKED: "Aquest tema està lligat simbòlicament. Les actualitzacions no seran detectades" + REMOVE_PLUGIN: "Elimina plugin" + INSTALL_PLUGIN: "Instal·la plugin" + AVAILABLE: "Disponible" + INSTALLED: "Instal·lat" + INSTALL: "Instal·la" + ACTIVE_THEME: "Tema actiu" + SWITCHING_TO: "Canviant a" + SWITCHING_TO_DESCRIPTION: "Al canviar a un tema diferent, no es garanteix que tots els estils de pàgina siguin compatibles, potencialment, pot haver-hi errors al intentar carregar aquestes pàgines." + SWITCHING_TO_CONFIRMATION: "Vols continuar i canviar de tema" + CREATE_NEW_USER: "Crea nou usuari" + REMOVE_USER: "Elimina usuari" + ACCESS_DENIED: "Accés denegat" + ACCOUNT_NOT_ADMIN: "el teu compte no té permisos d'administrador" + PHP_INFO: "Informació PHP" + INSTALLER: "Instal·lador" + AVAILABLE_THEMES: "Temes disponibles" + AVAILABLE_PLUGINS: "Plugins disponibles" + INSTALLED_THEMES: "Temes instal·lats" + INSTALLED_PLUGINS: "Plugins instal·lats" + BROWSE_ERROR_LOGS: "Examina registres d'errors" + SITE: "Lloc web" + INFO: "Info" + SYSTEM: "Sistema" + USER: "Usuari" + ADD_ACCOUNT: "Afegeix compte" + SWITCH_LANGUAGE: "Canvia l'idioma" + SUCCESSFULLY_ENABLED_PLUGIN: "El plugin s'ha activat correctament" + SUCCESSFULLY_DISABLED_PLUGIN: "El plugin s'ha desactivat correctament" + SUCCESSFULLY_CHANGED_THEME: "S'ha canviat el tema per defecte correctament" + INSTALLATION_FAILED: "La instal·lació ha fallat" + INSTALLATION_SUCCESSFUL: "Instal·lació satisfactòria" + UNINSTALL_FAILED: "Desinstal·lació fallida" + UNINSTALL_SUCCESSFUL: "Desinstal·lació satisfactòria" + SUCCESSFULLY_SAVED: "Desat satisfactòriament" + SUCCESSFULLY_COPIED: "Copiat satisfactòriament" + REORDERING_WAS_SUCCESSFUL: "Reordenació satisfactòria" + SUCCESSFULLY_DELETED: "Eliminat satisfactòriament" + SUCCESSFULLY_SWITCHED_LANGUAGE: "Idioma canviat satisfactòriament" + INSUFFICIENT_PERMISSIONS_FOR_TASK: "No tens permisos suficients per a la tasca" + CACHE_CLEARED: "Memòria cache esborrada" + METHOD: "Mètode" + ERROR_CLEARING_CACHE: "Error al esborrar cache" + AN_ERROR_OCCURRED: "S'ha produït un error" + YOUR_BACKUP_IS_READY_FOR_DOWNLOAD: "La teva còpia de seguretat està llesta per a descarregar" + DOWNLOAD_BACKUP: "Descarrega còpia de seguretat" + PAGES_FILTERED: "Pàgines filtrades" + NO_PAGE_FOUND: "No s'han trobat pàgines" + INVALID_PARAMETERS: "Els paràmetres són invàlids" + NO_FILES_SENT: "No s'han enviat fitxers" + EXCEEDED_FILESIZE_LIMIT: "S'ha excedit el límit de tamany de fitxer de la configuració de PHP" + UNKNOWN_ERRORS: "Hi ha hagut errors desconeguts" + EXCEEDED_GRAV_FILESIZE_LIMIT: "S'ha excedit el límit de tamany de fitxer de la configuració de Grav" + UNSUPPORTED_FILE_TYPE: "Tipus de fitxer no suportat" + FAILED_TO_MOVE_UPLOADED_FILE: "S'ha fallat al moure el fitxer carregat." + FILE_UPLOADED_SUCCESSFULLY: "S'ha carregat el fitxer amb èxit" + FILE_DELETED: "S'ha esborrat el fitxer" + FILE_COULD_NOT_BE_DELETED: "No s'ha pogut esborrar el fitxer" + FILE_NOT_FOUND: "No s'ha trobat el fitxer" + NO_FILE_FOUND: "No s'han trobat fitxers" + GRAV_WAS_SUCCESSFULLY_UPDATED_TO: "Grav ha estat actualitzat amb èxit a" + GRAV_UPDATE_FAILED: "Ha fallat l'actualització de Grav" + EVERYTHING_UPDATED: "Tot està actualitzat" + UPDATES_FAILED: "Han fallat les actualitzacions" + AVATAR_BY: "Avatar per" + LAST_BACKUP: "Última còpia de seguretat" + FULL_NAME: "Nom complet" + USERNAME: "Nom d'usuari" + EMAIL: "Email" + USERNAME_EMAIL: "Nom d'usuari o correu electrònic" + PASSWORD: "Contrasenya" + PASSWORD_CONFIRM: "Confirma contrasenya" + TITLE: "Títol" + LANGUAGE: "Llengua" + ACCOUNT: "Compte d'usuari" + EMAIL_VALIDATION_MESSAGE: "Ha de ser una adreça de correu electrònic vàl·lida" + PASSWORD_VALIDATION_MESSAGE: "La contrasenya ha de contenir almenys un número i una lletra majúscula i minúscula, i almenys 8 o més caràcters" + LANGUAGE_HELP: "Estableix la llengua preferida" + MEDIA: "Mèdia" + DEFAULTS: "Per defecte" + SITE_TITLE: "Títol del lloc" + SITE_TITLE_PLACEHOLDER: "Títol a tot el lloc" + SITE_TITLE_HELP: "Títol per defecte pel teu lloc, sovint utilitzat en els temes" + SITE_DEFAULT_LANG: "Llenguatge per defecte" + SITE_DEFAULT_LANG_PLACEHOLDER: "Llenguatge per defecte per a ser utilitzat per l'etiqueta del tema " + SITE_DEFAULT_LANG_HELP: "Llenguatge per defecte per a ser utilitzat per l'etiqueta del tema " + DEFAULT_AUTHOR: "Autor/a per defecte" + DEFAULT_AUTHOR_HELP: "Un nom d'autor/a per defecte, algunes vegades utilitzat en temes o contingut de les pàgines" + DEFAULT_EMAIL: "Email per defecte" + DEFAULT_EMAIL_HELP: "Un correu electrònic per referenciar en temes o pàgines" + TAXONOMY_TYPES: "Tipus de taxonomia" + TAXONOMY_TYPES_HELP: "Els tipus de taxonomia han de definir-se aquí si es desitja utilitzar-les en pàgines" + PAGE_SUMMARY: "Resum de pàgina" + ENABLED: "Habilitat" + ENABLED_HELP: "Habilita resum de pàgina (el resum retorna el mateix que el contingut de la pàgina)" + 'YES': "Sí" + 'NO': "No" + SUMMARY_SIZE: "Mida del resum" + SUMMARY_SIZE_HELP: "La quantitat de caràcters d'una pàgina a utilitzar com a resum del contingut" + FORMAT: "Format" + FORMAT_HELP: "curt = utilitza la primera ocurrència del delimitador o mida; llarg = s'ignorarà el delimitador del resum" + SHORT: "Curt" + LONG: "Llarg" + DELIMITER: "Delimitador" + DELIMITER_HELP: "El delimitador de resum (per defecte '===')" + METADATA: "Metadades" + METADATA_HELP: "Valors de metadades per defecte que es mostraran a cada pàgina excepte si es sobreescriuen a la pàgina" + NAME: "Nom" + CONTENT: "Contingut" + REDIRECTS_AND_ROUTES: "Redireccions i rutes" + CUSTOM_REDIRECTS: "Redireccions personalitzades" + CUSTOM_REDIRECTS_HELP: "rutes per redirigir a altres pàgines. Substitució de Regex estàndard és vàl·lida" + CUSTOM_REDIRECTS_PLACEHOLDER_KEY: "/el/teu/àlies" + CUSTOM_REDIRECTS_PLACEHOLDER_VALUE: "/la/teva/redirecció" + CUSTOM_ROUTES: "Rutes personalitzades" + CUSTOM_ROUTES_HELP: "rutes a àlies a altres pàgines. Substitució de Regex estàndard és vàl·lida" + CUSTOM_ROUTES_PLACEHOLDER_KEY: "/el/teu/àlies" + CUSTOM_ROUTES_PLACEHOLDER_VALUE: "/la/teva/ruta" + FILE_STREAMS: "Streams de fitxers" + DEFAULT: "Per defecte" + PAGE_MEDIA: "Contingut multimèdia de la pàgina" + OPTIONS: "Opcions" + PUBLISHED: "Publicat" + PUBLISHED_HELP: "Per defect, una pàgina es publica excepte que estableixis explícitament 'published': false o posant una publish_date al futur o una unpublish_date al passat" + DATE: "Data" + DATE_HELP: "La variable data permet definir específicament una data associada a aquesta pàgina." + PUBLISHED_DATE: "Data de publicació" + PUBLISHED_DATE_HELP: "Pots proporcionar una data per provocar automàticament la publicació." + UNPUBLISHED_DATE: "Data de despublicació" + UNPUBLISHED_DATE_HELP: "Pots proporcionar una data per provocar automàticament la despublicació." + ROBOTS: "Robots" + TAXONOMIES: "Taxonomies" + TAXONOMY: "Taxonomia" + ADVANCED: "Avançat" + SETTINGS: "Configuració" + FOLDER_NUMERIC_PREFIX: "Prefix numèric carpeta" + FOLDER_NUMERIC_PREFIX_HELP: "Prefix numèric que proporciona ordenació manual i implica la visibilitat" + FOLDER_NAME: "Nom de la carpeta" + FOLDER_NAME_HELP: "El nom de carpeta que s'emmagatzemarà al sistema de fitxers per a aquesta pàgina" + PARENT: "Pare" + DEFAULT_OPTION_ROOT: "-Root-" + DEFAULT_OPTION_SELECT: "- selecciona -" + DISPLAY_TEMPLATE: "Plantilla a mostrar" + DISPLAY_TEMPLATE_HELP: "El tipus de pàgina que es tradueix a la plantilla de Twig en què es renderitza la pàgina" + BODY_CLASSES: "Classes del Body" + ORDERING: "Ordenació" + PAGE_ORDER: "Ordre de pàgines" + OVERRIDES: "Sobreescriu" + MENU: "Menú" + MENU_HELP: "El text a utilitzar en un menú. Si no s'estableix, s'utilitzarà el Títol." + SLUG: "Slug" + SLUG_HELP: "La variable slug permet definir específicament la part de l'URL que correspon a la pàgina" + SLUG_VALIDATE_MESSAGE: "L'slug ha de contenir només caràcters alfanumèrics en minúscules i guions" + PROCESS: "Processa" + PROCESS_HELP: "Control de com es processen les pàgines. Configurable per a pàgina enlloc de globalment" + DEFAULT_CHILD_TYPE: "Tipus de fill per defecte" + USE_GLOBAL: "Ús global" + ROUTABLE: "Accessible" + ROUTABLE_HELP: "Si aquesta pàgina és accessible des d'una URL" + CACHING: "Caching" + VISIBLE: "Visible" + VISIBLE_HELP: "Determina si una pàgina és visible en la navegació." + DISABLED: "Deshabilitat" + ITEMS: "Ítems" + ORDER_BY: "Ordena per" + ORDER: "Ordena" + FOLDER: "Carpeta" + ASCENDING: "Ascendent" + DESCENDING: "Descendent" + ADD_MODULAR_CONTENT: "Afegeix contingut modular" + PAGE_TITLE: "Títol de pàgina" + PAGE_TITLE_HELP: "El títol de la pàgina" + PAGE: "Pàgina" + MODULAR_TEMPLATE: "Plantilla modular" + FRONTMATTER: "Frontmatter" + FILENAME: "Nom de fitxer" + PARENT_PAGE: "Pàgina pare" + HOME_PAGE: "Pàgina d'inici" + HOME_PAGE_HELP: "La pàgina que utilitzarà Grav com a destinació per defecte" + DEFAULT_THEME: "Tema per defecte" + DEFAULT_THEME_HELP: "Estableix el tema per defecte que utilitzarà Grav (per defecte és Antimatter)" + TIMEZONE: "Zona horària" + TIMEZONE_HELP: "Sobreescriu la zona horària del servidor" + SHORT_DATE_FORMAT: "Format de data curt" + SHORT_DATE_FORMAT_HELP: "Estableix el format de data curt que poden utilitzar els temes" + LONG_DATE_FORMAT: "Format de data llarg" + LONG_DATE_FORMAT_HELP: "Estableix el format de data llarg que poden utilitzar els temes" + DEFAULT_ORDERING: "Ordre per defecte" + DEFAULT_ORDERING_HELP: "Les pàgines de la llista seran generades utilitzant aquest ordre excepte que se sobreescrigui" + DEFAULT_ORDERING_DEFAULT: "Per defecte - basat en el nom de la carpeta" + DEFAULT_ORDERING_FOLDER: "Carpeta - basat en el nom de carpeta sense prefix" + DEFAULT_ORDERING_TITLE: "Títol - basat en el camp de títol de la capçalera" + DEFAULT_ORDERING_DATE: "Data - basat en el camp data de la capçalera" + DEFAULT_ORDER_DIRECTION: "Direcció d'ordre per defecte" + DEFAULT_ORDER_DIRECTION_HELP: "La direcció de les pàgines en una llista" + DEFAULT_PAGE_COUNT: "Compte de pàgina per defecte" + DEFAULT_PAGE_COUNT_HELP: "Nombre màxim de compte de pàgines en una llista" + DATE_BASED_PUBLISHING: "Publicació basada en la data" + DATE_BASED_PUBLISHING_HELP: "(Des)publicar automàticament posts basant-se en la seva data" + EVENTS: "Esdeveniments" + EVENTS_HELP: "Habilita o inhabilita esdeveniments concrets. Deshabilitant-los pot trencar plugins" + REDIRECT_DEFAULT_ROUTE: "Ruta de redirecció per defecte" + REDIRECT_DEFAULT_ROUTE_HELP: "Redirigir automàticament a la ruta per defecte d'una pàgina" + LANGUAGES: "Idiomes" + SUPPORTED: "Suportat" + SUPPORTED_HELP: "Llista separada per comes de codis d'idioma de 2 lletres (per exemple 'en,fr,de')" + TRANSLATIONS_ENABLED: "Traduccions habilitades" + TRANSLATIONS_ENABLED_HELP: "Suport a traduccions a Grav, plugins i extensions" + TRANSLATIONS_FALLBACK: "Fallback de traduccions" + TRANSLATIONS_FALLBACK_HELP: "Fallback en traduccions suportades si l'idioma actiu no existeix" + ACTIVE_LANGUAGE_IN_SESSION: "Idioma actiu a la sessió" + ACTIVE_LANGUAGE_IN_SESSION_HELP: "Emmagatzema l'idioma actiu a la sessió" + HTTP_HEADERS: "Capçaleres HTTP" + EXPIRES: "Caduca" + EXPIRES_HELP: "Estableix la capçalera d'expiració. El valor és en segons." + LAST_MODIFIED: "Darrera modificació" + LAST_MODIFIED_HELP: "Estableix la capçalera de darrera modificació que pot optimitzar el proxy i la cache del navegador" + ETAG: "ETag" + ETAG_HELP: "Estableix la capçalera d'etag per ajudar a identificar quan una pàgina ha estat modificada" + VARY_ACCEPT_ENCODING: "Variar accept encoding" + VARY_ACCEPT_ENCODING_HELP: "Estableix la capçalera 'Vary: Accept Encoding' per ajudar amb el proxy i la cache CDN" + MARKDOWN_EXTRA_HELP: "Habilita suport per defecte per a Markdown Extra - https://michelf.ca/projects/php-markdown/extra/" + AUTO_LINE_BREAKS: "Salts de línia automàtics" + AUTO_LINE_BREAKS_HELP: "Habilita el suport per a salts de línia automàtics a Markdown" + AUTO_URL_LINKS: "Enllaços URL automàtics" + AUTO_URL_LINKS_HELP: "Habilita l'autoconversió d'URLs a hyperlinks HTML" + ESCAPE_MARKUP: "Escape markup" + ESCAPE_MARKUP_HELP: "Escape markup tags en entitats HTML" + CACHING_HELP: "Interruptor ON/OFF global per habilitar/deshabilitar cache de Grav" + CACHE_CHECK_METHOD: "Mètode de verificació de cache" + CACHE_CHECK_METHOD_HELP: "Seleccionar el mètode que utilitza Grav per comprovar si s'han modificat arxius de pàgina." + CACHE_DRIVER: "Contolador de cache" + CACHE_DRIVER_HELP: "Selecciona quin controlador de cache de Grav cal usar. 'Auto Detect' intenta trobar el millor per a tu" + CACHE_PREFIX: "Prefix de cache" + CACHE_PREFIX_HELP: "Un identificador per part de la clau de Grav. No la canviïs excepte que sàpigues el que estàs fent." + CACHE_PREFIX_PLACEHOLDER: "Derivat de l'URL base (sobreescriu introduint strings aleatòris)" + LIFETIME: "Cicle de vida" + LIFETIME_HELP: "Defineix el cicle de vida de la cache en segons. 0 = infinit" + GZIP_COMPRESSION: "Compressió gzip" + GZIP_COMPRESSION_HELP: "Habilita la compressió GZip de la pàgina de Grav per augmentar el rendiment." + TWIG_TEMPLATING: "Plantilles de Twig" + TWIG_CACHING: "Cache de Twig" + TWIG_CACHING_HELP: "Controla el mecanisme de cache de Twig. Deixa'l habilitat per a millor rendiment." + TWIG_DEBUG: "Depuració de Twig" + TWIG_DEBUG_HELP: "Permet l'opció de no carregar l'extensió de depuració de Twig" + DETECT_CHANGES: "Detectar canvis" + DETECT_CHANGES_HELP: "Twig recompilarà automàticament la cache de Twig si detecta canvis a les plantilles de Twig" + AUTOESCAPE_VARIABLES: "Variables d'autoescape" + AUTOESCAPE_VARIABLES_HELP: "Autoescapa totes les variables. Això probablement trencarà el teu lloc" + ASSETS: "Assets" + CSS_PIPELINE: "CSS pipeline" + CSS_PIPELINE_HELP: "El CSS pipeline és l'unificació de diversos recursos CSS en un sol fitxer" + CSS_PIPELINE_INCLUDE_EXTERNALS: "Inclou fitxers externs en el CSS pipeline" + CSS_PIPELINE_INCLUDE_EXTERNALS_HELP: "A vegades, algunes URLs externes tenen referències relatives de fitxer i no s'hi hauria de fer pipelining" + CSS_PIPELINE_BEFORE_EXCLUDES: "Processar pimer el CSS pipeline" + CSS_PIPELINE_BEFORE_EXCLUDES_HELP: "Intrepreta el CSS pipeline abans de qualsevol altra referència CSS que no estigui inclosa" + CSS_MINIFY: "Minifica CSS" + CSS_MINIFY_HELP: "Minifica el CSS durant el pipelining" + CSS_MINIFY_WINDOWS_OVERRIDE: "Sobreesciu la minificació de CSS a Windows" + CSS_MINIFY_WINDOWS_OVERRIDE_HELP: "Sobreescriu la minificació en plataformes Windows. Fals per defecte degut a ThreadStackSize" + CSS_REWRITE: "Reescriptura CSS" + CSS_REWRITE_HELP: "Reescriu qualsevol URL relativa de CSS durant el pipelining" + JAVASCRIPT_PIPELINE: "JavaScript pipeline" + JAVASCRIPT_PIPELINE_HELP: "El JS pipeline és l'unificació de diversos recursos JS en un sol fitxer" + JAVASCRIPT_PIPELINE_INCLUDE_EXTERNALS: "Inclou fitxers externs en el JS pipeline" + JAVASCRIPT_PIPELINE_INCLUDE_EXTERNALS_HELP: "A vegades, les URLs externes tenen referències d'arxiu i no s'hi hauria de fer pipelining" + JAVASCRIPT_PIPELINE_BEFORE_EXCLUDES: "Interpreta primer el JS pipeline" + JAVASCRIPT_PIPELINE_BEFORE_EXCLUDES_HELP: "Interpreta el JS pipeline abans de qualsevol altra referència JS que no estigui inclosa" + JAVASCRIPT_MINIFY: "Minificació JavaScript" + JAVASCRIPT_MINIFY_HELP: "Minifica el JS durant el pipelining" + ENABLED_TIMESTAMPS_ON_ASSETS: "Habilita les marques de temps als assets" + ENABLED_TIMESTAMPS_ON_ASSETS_HELP: "Habilita les marques de temps a assets" + COLLECTIONS: "Col·leccions" + ERROR_HANDLER: "Controlador d'errors" + DISPLAY_ERRORS: "Mostra errors" + DISPLAY_ERRORS_HELP: "Mostra pàgina d'error full backstrace-style" + LOG_ERRORS: "Registre d'errors" + LOG_ERRORS_HELP: "Registre d'errors a la carpeta /logs" + DEBUGGER: "Depurador" + DEBUGGER_HELP: "Habilita depurador de Grav i les configuracions següents" + DEBUG_TWIG: "Depuració de Twig" + DEBUG_TWIG_HELP: "Habilita la depuració de plantilles de Twig" + SHUTDOWN_CLOSE_CONNECTION: "Al apagar tanca la connexió" + SHUTDOWN_CLOSE_CONNECTION_HELP: "Tanca la connexió abans de cridar onShutdown(). False per a la depuració" + DEFAULT_IMAGE_QUALITY: "Qualitat d'imatge per defecte" + DEFAULT_IMAGE_QUALITY_HELP: "Qualitat d'imatge per defecte per a ser utilitzada quan es remostri o es guardi a cache les imatges (85%)" + CACHE_ALL: "Guardar totes les imatges a cache" + CACHE_ALL_HELP: "Guarda totes les imatges al sistema cache de Grav fins i tot si no tenen cap manipulació de mèdia" + IMAGES_DEBUG: "Marca d'aigua de depuració" + IMAGES_DEBUG_HELP: "Mostra un overlay sobre les imatges indicant la profunditat de píxels quan es treballa amb retina, per exemple" + UPLOAD_LIMIT: "Límit de tamany de fitxer" + UPLOAD_LIMIT_HELP: "Defineix el tamany màxim de càrrega en bytes (0 = il·limitat)" + ENABLE_MEDIA_TIMESTAMP: "Permet timestamps en fitxers multimèdia" + ENABLE_MEDIA_TIMESTAMP_HELP: "Afegeix un timestamp basat en la data d'última modificació a cada element multimèdia" + SESSION: "Sessió" + SESSION_ENABLED_HELP: "Habilita suport de sessions a Grav" + TIMEOUT: "Temps d'espera" + TIMEOUT_HELP: "Estableix el temps d'espera de la sessió en segons" + SESSION_NAME_HELP: "Un identificador usat per formar el nom de la galeta de sessió" + ABSOLUTE_URLS: "URLs absolutes" + ABSOLUTE_URLS_HELP: "URLs absolutes o relatives per a 'base_url'" + PARAMETER_SEPARATOR: "Separador de paràmetres" + PARAMETER_SEPARATOR_HELP: "Separador per a paràmetres passats que es poden canviar d'Apache a Windows" + TASK_COMPLETED: "Tasca completada" + EVERYTHING_UP_TO_DATE: "Tot està actualitzat" + UPDATES_ARE_AVAILABLE: "hi ha actualitzacions disponibles" + IS_AVAILABLE_FOR_UPDATE: "està disponible per a l'actualització" + IS_NOW_AVAILABLE: "ja està disponible" + CURRENT: "Actual" + UPDATE_GRAV_NOW: "Actualitza Grav ara" + GRAV_SYMBOLICALLY_LINKED: "Grav està lligat simbòlicament. Les actualitzacions no estaran disponibles" + UPDATING_PLEASE_WAIT: "Actualitzant... descarregant, espera sisplau" + OF_THIS: "d'aquest/a" + OF_YOUR: "del teu" + HAVE_AN_UPDATE_AVAILABLE: "té disponible una actualització" + SAVE_AS: "Desa com a" + MODAL_DELETE_PAGE_CONFIRMATION_REQUIRED_DESC: "Esteu segur que voleu suprimir aquesta pàgina i tots els seus fills? Si la pàgina es tradueix en altres llengües, les traduccions es mantindran i han de ser esborrades per separat. En cas contrari la carpeta de la pàgina serà eliminada juntament amb les seves subpàgines. Aquesta acció no es pot desfer." + AND: "i" + UPDATE_AVAILABLE: "Actualització disponible" + METADATA_KEY: "Clau (p. ex. 'paraules clau')" + METADATA_VALUE: "Valor (per exemple, \"Blog, Grav\")" + USERNAME_HELP: "El nom d'usuari ha de tenir entre 3 i 16 caràcters, incloent minúscules, números, guions i guions baixos. Lletres majúscules, espais i caràcters especials no estan permesos" + FULLY_UPDATED: "Completament actualitzat" + SAVE_LOCATION: "Desa a la ubicació" + PAGE_FILE: "Plantilla de pàgina" + PAGE_FILE_HELP: "Nom d'arxiu de la plantilla de pàgina i plantilla de visualització per defecte" + NO_USER_ACCOUNTS: "No s'han trobat comptes d'usuari, sisplau crea'n una..." + REDIRECT_TRAILING_SLASH: "Redirigeix barra final" + REDIRECT_TRAILING_SLASH_HELP: "Realitza una redirecció 301 en lloc de manteniment transparent de barra final." + DEFAULT_DATE_FORMAT: "Format de data de pàgina" + DEFAULT_DATE_FORMAT_HELP: "Format de data de pàgina utilitzat per Grav. Per defecte, Grav intenta endivinar el format de data, tot i això pots especificar un format utilitzant la sintaxi de data de PHP (p.e., Y-m-d H:i)" + DEFAULT_DATE_FORMAT_PLACEHOLDER: "Endevina automàticament" + IGNORE_FILES: "Ignora fitxers" + IGNORE_FILES_HELP: "Arxius específics a ignorar al processar pàgines" + IGNORE_FOLDERS: "Ignora carpetes" + IGNORE_FOLDERS_HELP: "Carpetes específiques a ignorar al processar pàgines" + HTTP_ACCEPT_LANGUAGE: "Estableix la llengua a partir del navegador" + HTTP_ACCEPT_LANGUAGE_HELP: "Pots optar per intentar establir la llengua basant-se en l'etiqueta de la capçalera 'http_accept_language' en el navegador" + OVERRIDE_LOCALE: "Sobreescriu la configuració local" + OVERRIDE_LOCALE_HELP: "Sobreescriu la configuració local en PHP basant-se en la llengua actual" + REDIRECT: "Redirecció de pàgina" + REDIRECT_HELP: "Escriu una ruta de pàgina o URL externa per aqueta pàgina a redirigir a per exemple, '/alguna/ruta' o 'https://algunlloc.com'" + PLUGIN_STATUS: "Estat del plugin" + INCLUDE_DEFAULT_LANG: "Inclou llengua predeterminada" + INCLUDE_DEFAULT_LANG_HELP: "Això sobreposarà totes les URLs amb la llengua per defecte. Per exemple, 'ca/blog/el-meu-post'" + ALLOW_URL_TAXONOMY_FILTERS: "Filtres de taxonomia d'URL" + ALLOW_URL_TAXONOMY_FILTERS_HELP: "Col·lecions basades en pàgines que et permeten filtrar per '/taxonomia:valor'." + REDIRECT_DEFAULT_CODE: "Codi de redirecció per defecte" + REDIRECT_DEFAULT_CODE_HELP: "El codi d'estat HTTP per utilitzar en redireccions" + IGNORE_HIDDEN: "Ignora ocults" + IGNORE_HIDDEN_HELP: "Ignora tots els fitxers i carpetes que comencin amb un punt" + WRAPPED_SITE: "Lloc encapsulat" + WRAPPED_SITE_HELP: "Per a que els temes/plugins sàpiguen si Grav està encapsulat en una altra plataforma" + FALLBACK_TYPES: "Tipus de fallback permesos" + FALLBACK_TYPES_HELP: "Tipus de fitxers permesos que es poden trobar si s'accedeix per la ruta de la pàgina. Per defecte, qualsevol tipus de mèdia compatible." + INLINE_TYPES: "Tipus de fallback en línia" + INLINE_TYPES_HELP: "Una llista de tipus d'arxius que han de ser mostrats en línia enlloc de descarregats" + APPEND_URL_EXT: "Afegeix extensió de direcció URL" + APPEND_URL_EXT_HELP: "Afegirà una extensió personalitzarà a l'URL de la pàgina. Tingues en compte que això farà que Grav busqui la plantilla '